[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    [kdepimlibs/calendaring] akonadi/calendar: Introduce the invitation handling code into IncidenceChan
From:       Sergio Martins <iamsergio () gmail ! com>
Date:       2012-07-31 21:34:39
Message-ID: 20120731213439.F24A8A6094 () git ! kde ! org
[Download RAW message or body]

Git commit 800765f0f7553aa733d36980b18c6f4b63c3ad4f by Sergio Martins.
Committed on 31/07/2012 at 23:32.
Pushed by smartins into branch 'calendaring'.

Introduce the invitation handling code into IncidenceChanger.

M  +173  -0    akonadi/calendar/incidencechanger.cpp
M  +3    -0    akonadi/calendar/incidencechanger.h
M  +9    -0    akonadi/calendar/incidencechanger_p.h
M  +10   -0    akonadi/calendar/invitationhandler_p.cpp
M  +3    -0    akonadi/calendar/invitationhandler_p.h

http://commits.kde.org/kdepimlibs/800765f0f7553aa733d36980b18c6f4b63c3ad4f

diff --git a/akonadi/calendar/incidencechanger.cpp \
b/akonadi/calendar/incidencechanger.cpp index 87a6444..1da6ab0 100644
--- a/akonadi/calendar/incidencechanger.cpp
+++ b/akonadi/calendar/incidencechanger.cpp
@@ -19,6 +19,7 @@
 */
 #include "incidencechanger.h"
 #include "incidencechanger_p.h"
+#include "mailscheduler_p.h"
 
 #include <Akonadi/ItemCreateJob>
 #include <Akonadi/ItemModifyJob>
@@ -35,6 +36,26 @@
 using namespace Akonadi;
 using namespace KCalCore;
 
+InvitationHandler::Action actionFromStatus( InvitationHandler::SendResult result )
+{
+  //enum SendResult {
+  //      Canceled,        /**< Sending was canceled by the user, meaning there are
+  //                          local changes of which other attendees are not aware. \
*/ +  //      FailKeepUpdate,  /**< Sending failed, the changes to the incidence must \
be kept. */ +  //      FailAbortUpdate, /**< Sending failed, the changes to the \
incidence must be undone. */ +  //      NoSendingNeeded, /**< In some cases it is not \
needed to send an invitation +  //                          (e.g. when we are the \
only attendee) */ +  //      Success
+  switch ( result ) {
+  case InvitationHandler::ResultCanceled:
+    return InvitationHandler::ActionDontSendMessage;
+  case InvitationHandler::ResultSuccess:
+    return InvitationHandler::ActionSendMessage;
+  default:
+    return InvitationHandler::ActionAsk;
+  }
+}
+
 namespace Akonadi {
   static Akonadi::Collection selectCollection( QWidget *parent,
                                                int &dialogCode,
@@ -142,6 +163,7 @@ IncidenceChanger::Private::Private( bool enableHistory, \
IncidenceChanger *qq ) :  mUseHistory = enableHistory;
   mDestinationPolicy = DestinationPolicyDefault;
   mRespectsCollectionRights = false;
+  mGroupwareCommunication = false;
   mLatestAtomicOperationId = 0;
   mBatchOperationInProgress = false;
 
@@ -415,6 +437,147 @@ bool IncidenceChanger::Private::deleteAlreadyCalled( \
Akonadi::Item::Id id ) cons  return mDeletedItemIds.contains( id );
 }
 
+bool IncidenceChanger::Private::handleInvitationsBeforeChange( const Change::Ptr \
&change ) +{
+  bool result = true;
+  if ( mGroupwareCommunication ) {
+    InvitationHandler handler( FetchJobCalendar::Ptr(), change->parentWidget );  // \
TODO make async +    if ( mInvitationStatusByAtomicOperation.contains( \
change->atomicOperationId ) ) { +      handler.setDefaultAction( actionFromStatus( \
mInvitationStatusByAtomicOperation.value( change->atomicOperationId ) ) ); +    }
+
+    switch( change->type ) {
+      case IncidenceChanger::ChangeTypeCreate:
+        // nothing needs to be done
+      break;
+      case IncidenceChanger::ChangeTypeDelete:
+      {
+        InvitationHandler::SendResult status;
+
+        Incidence::Ptr incidence = \
change->originalItem.payload<KCalCore::Incidence::Ptr>(); +        status = \
handler.sendIncidenceDeletedMessage( KCalCore::iTIPCancel, incidence ); +        if ( \
change->atomicOperationId ) { +          mInvitationStatusByAtomicOperation.insert( \
change->atomicOperationId, status ); +        }
+        result = status != InvitationHandler::ResultFailAbortUpdate;
+      }
+      break;
+      case IncidenceChanger::ChangeTypeModify:
+      {
+        Incidence::Ptr oldIncidence = \
change->originalItem.payload<KCalCore::Incidence::Ptr>(); +        Incidence::Ptr \
newIncidence = change->originalItem.payload<KCalCore::Incidence::Ptr>(); +
+        const bool modify = handler.handleIncidenceAboutToBeModified( newIncidence \
); +        if ( !modify ) {
+          if ( newIncidence->type() == oldIncidence->type() ) {
+            IncidenceBase *i1 = newIncidence.data();
+            IncidenceBase *i2 = oldIncidence.data();
+            *i1 = *i2;
+          }
+          result = false;
+        }
+      }
+      break;
+      default:
+        Q_ASSERT( false );
+        result = false;
+    }
+  }
+  return result;
+}
+
+bool IncidenceChanger::Private::handleInvitationsAfterChange( const Change::Ptr \
&change ) +{
+  if ( mGroupwareCommunication ) {
+    InvitationHandler handler( FetchJobCalendar::Ptr(), change->parentWidget ); // \
TODO make async +    switch( change->type ) {
+      case IncidenceChanger::ChangeTypeCreate:
+      {
+        Incidence::Ptr incidence = \
change->newItem.payload<KCalCore::Incidence::Ptr>(); +        const \
InvitationHandler::SendResult status = +          \
handler.sendIncidenceCreatedMessage( KCalCore::iTIPRequest, incidence ); +
+        if ( status == InvitationHandler::ResultFailAbortUpdate ) {
+          kError() << "Sending invitations failed, but did not delete the \
incidence"; +        }
+
+        const uint atomicOperationId = change->atomicOperationId;
+        if ( atomicOperationId != 0 ) {
+          mInvitationStatusByAtomicOperation.insert( atomicOperationId, status );
+        }
+      }
+      break;
+      case IncidenceChanger::ChangeTypeDelete:
+      {
+        Incidence::Ptr incidence = \
change->originalItem.payload<KCalCore::Incidence::Ptr>(); +        Q_ASSERT( \
incidence ); +        if ( !handler.thatIsMe( incidence->organizer()->email() ) ) {
+          const QStringList myEmails = handler.allEmails();
+          bool notifyOrganizer = false;
+          for ( QStringList::ConstIterator it = myEmails.begin(); it != \
myEmails.end(); ++it ) { +            const QString email = *it;
+            KCalCore::Attendee::Ptr me( incidence->attendeeByMail( email ) );
+            if ( me ) {
+              if ( me->status() == KCalCore::Attendee::Accepted ||
+                   me->status() == KCalCore::Attendee::Delegated ) {
+                notifyOrganizer = true;
+              }
+              KCalCore::Attendee::Ptr newMe( new KCalCore::Attendee( *me ) );
+              newMe->setStatus( KCalCore::Attendee::Declined );
+              incidence->clearAttendees();
+              incidence->addAttendee( newMe );
+              break;
+            }
+          }
+
+          if ( notifyOrganizer ) {
+            FetchJobCalendar::Ptr invalidPtr;
+            MailScheduler scheduler( invalidPtr ); // TODO make async
+            scheduler.performTransaction( incidence, KCalCore::iTIPReply );
+          }
+        }
+      }
+      break;
+      case IncidenceChanger::ChangeTypeModify:
+      {
+        Incidence::Ptr oldIncidence = \
change->originalItem.payload<KCalCore::Incidence::Ptr>(); +        Incidence::Ptr \
newIncidence = change->newItem.payload<KCalCore::Incidence::Ptr>(); +        if ( \
mInvitationStatusByAtomicOperation.contains( change->atomicOperationId ) ) { +        \
handler.setDefaultAction( actionFromStatus( mInvitationStatusByAtomicOperation.value( \
change->atomicOperationId ) ) ); +        }
+        const bool attendeeStatusChanged = myAttendeeStatusChanged( newIncidence,
+                                                                    oldIncidence,
+                                                                    \
handler.allEmails() ); +        InvitationHandler::SendResult status = \
handler.sendIncidenceModifiedMessage( KCalCore::iTIPRequest, +                        \
newIncidence, +                                                                       \
attendeeStatusChanged ); +
+        if ( change->atomicOperationId != 0 ) {
+          mInvitationStatusByAtomicOperation.insert( change->atomicOperationId, \
status ); +        }
+      }
+      break;
+      default:
+        Q_ASSERT( false );
+        return false;
+    }
+  }
+  return true;
+}
+
+/** static */
+bool IncidenceChanger::Private::myAttendeeStatusChanged( const Incidence::Ptr \
&newInc, +                                                         const \
Incidence::Ptr &oldInc, +                                                         \
const QStringList &myEmails ) +{
+  Q_ASSERT( newInc );
+  Q_ASSERT( oldInc );
+  const Attendee::Ptr oldMe = oldInc->attendeeByMails( myEmails );
+  const Attendee::Ptr newMe = newInc->attendeeByMails( myEmails );
+
+  return oldMe && newMe && oldMe->status() != newMe->status();
+}
+
 IncidenceChanger::IncidenceChanger( QObject *parent ) : QObject( parent )
                                                       , d( new Private( \
/**history=*/true, this ) )  {
@@ -905,6 +1068,16 @@ History* IncidenceChanger::history() const
   return d->mHistory;
 }
 
+void IncidenceChanger::setGroupwareCommuniation( bool enabled )
+{
+  d->mGroupwareCommunication = enabled;
+}
+
+bool IncidenceChanger::groupwareCommunication() const
+{
+  return d->mGroupwareCommunication;
+}
+
 QString IncidenceChanger::Private::showErrorDialog( IncidenceChanger::ResultCode \
resultCode,  QWidget *parent )
 {
diff --git a/akonadi/calendar/incidencechanger.h \
b/akonadi/calendar/incidencechanger.h index 05f8722..0f3568f 100644
--- a/akonadi/calendar/incidencechanger.h
+++ b/akonadi/calendar/incidencechanger.h
@@ -311,6 +311,9 @@ class AKONADI_CALENDAR_EXPORT IncidenceChanger : public QObject
      */
     History* history() const;
 
+    void setGroupwareCommuniation( bool enabled );
+    bool groupwareCommunication() const;
+
 Q_SIGNALS:
     /**
      * Emitted when IncidenceChanger creates an Incidence in akonadi.
diff --git a/akonadi/calendar/incidencechanger_p.h \
b/akonadi/calendar/incidencechanger_p.h index 9e59468..04dbdcc 100644
--- a/akonadi/calendar/incidencechanger_p.h
+++ b/akonadi/calendar/incidencechanger_p.h
@@ -25,6 +25,7 @@
 #define AKONADI_INCIDENCECHANGER_P_H
 
 #include "incidencechanger.h"
+#include "invitationhandler_p.h"
 #include "history.h"
 
 #include <Akonadi/Item>
@@ -273,6 +274,12 @@ class IncidenceChanger::Private : public QObject
     void cleanupTransaction();
     bool allowAtomicOperation( int atomicOperationId, const Change::Ptr &change ) \
const;  
+    bool handleInvitationsBeforeChange( const Change::Ptr &change );
+    bool handleInvitationsAfterChange( const Change::Ptr &change );
+    static bool myAttendeeStatusChanged( const KCalCore::Incidence::Ptr \
&newIncidence, +                                         const \
KCalCore::Incidence::Ptr &oldIncidence, +                                         \
const QStringList &myEmails ); +
   public Q_SLOTS:
     void handleCreateJobResult( KJob* );
     void handleModifyJobResult( KJob* );
@@ -314,8 +321,10 @@ class IncidenceChanger::Private : public QObject
     QHash<uint,AtomicOperation*> mAtomicOperations;
 
     bool mRespectsCollectionRights;
+    bool mGroupwareCommunication;
 
     QHash<Akonadi::TransactionSequence*, uint> mAtomicOperationByTransaction;
+    QHash<uint,InvitationHandler::SendResult> mInvitationStatusByAtomicOperation;
 
     uint mLatestAtomicOperationId;
     bool mBatchOperationInProgress;
diff --git a/akonadi/calendar/invitationhandler_p.cpp \
b/akonadi/calendar/invitationhandler_p.cpp index b76cd6c..fd7853f 100644
--- a/akonadi/calendar/invitationhandler_p.cpp
+++ b/akonadi/calendar/invitationhandler_p.cpp
@@ -634,4 +634,14 @@ void InvitationHandler::onSchedulerFinished( \
MailScheduler::Result result, const  success ? QString() : i18n( "Error: %1", \
errorMsg ) );  }
 
+QStringList InvitationHandler::allEmails() const
+{
+  return d->allEmails();
+}
+
+bool InvitationHandler::thatIsMe( const QString &email ) const
+{
+  return d->thatIsMe( email );
+}
+
 #include "invitationhandler_p.moc"
diff --git a/akonadi/calendar/invitationhandler_p.h \
b/akonadi/calendar/invitationhandler_p.h index b18edf4..a6ce657 100644
--- a/akonadi/calendar/invitationhandler_p.h
+++ b/akonadi/calendar/invitationhandler_p.h
@@ -166,6 +166,9 @@ class InvitationHandler : public QObject
     // Frees calendar if it doesn't have jobs running
     void calendarJobFinished( bool success, const QString &errorString );
 
+    QStringList allEmails() const;
+    bool thatIsMe( const QString &email ) const;
+
   Q_SIGNALS:
     /**
       This signal is emitted when an invitation for a counter proposal is sent.


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic