From 8ce63b1df3d811bb203a9e88cb23ea9a70216c35 Mon Sep 17 00:00:00 2001
From: tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>
Date: Sun, 29 Aug 2010 18:08:07 +0000
Subject: * Fixed crash when modifying single instance of recurring meeeting in
 agenda view * Allow CalDAV tasks read/write to continue even if events
 read/write failed * Documentation cleanup

git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdepim@1169577 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
---
 korganizer/calendarview.cpp  |  8 ++--
 korganizer/koagenda.cpp      | 91 ++++++++++++++++++++++++++++++++------------
 kresources/caldav/reader.cpp | 15 +++++---
 kresources/caldav/writer.cpp | 31 ++++++++-------
 libkcal/calendar.cpp         |  2 +
 libkcal/calendarresources.h  |  4 +-
 6 files changed, 104 insertions(+), 47 deletions(-)

diff --git a/korganizer/calendarview.cpp b/korganizer/calendarview.cpp
index ae4a5b6e..eb294fe7 100644
--- a/korganizer/calendarview.cpp
+++ b/korganizer/calendarview.cpp
@@ -1258,9 +1258,11 @@ void CalendarView::dissociateOccurrence( Incidence *incidence, const TQDate &dat
   Incidence* newInc = mCalendar->dissociateOccurrence( incidence, date, true );
 
   if ( newInc ) {
-    // TODO: Use the same resource instead of asking again!
-    mChanger->changeIncidence( oldincidence, incidence );
-    mChanger->addIncidence( newInc, this );
+    // TODO [FIXME]: Use the same resource instead of asking again!
+    // See also koagenda.cpp: endItemAction()
+    bool success = mChanger->addIncidence( newInc, this );
+    if ( success )
+      mChanger->changeIncidence( oldincidence, incidence );
   } else {
     KMessageBox::sorry( this, i18n("Dissociating the occurrence failed."),
       i18n("Dissociating Failed") );
diff --git a/korganizer/koagenda.cpp b/korganizer/koagenda.cpp
index 270ca8f8..589c1328 100644
--- a/korganizer/koagenda.cpp
+++ b/korganizer/koagenda.cpp
@@ -1046,6 +1046,12 @@ void KOAgenda::endItemAction()
   bool multiModify = false;
   // FIXME: do the cloning here...
   Incidence* inc = mActionItem->incidence();
+  // Store modification information in case it is needed to recreate the changes with a new actionitem...
+  int mai_xl = mActionItem->cellXLeft();
+  int mai_xr = mActionItem->cellXRight();
+  int mai_yt = mActionItem->cellYTop();
+  int mai_yb = mActionItem->cellYBottom();
+  Incidence* newInc;
 
   if ( mItemMoved ) {
     bool modify = true;
@@ -1061,6 +1067,9 @@ void KOAgenda::endItemAction()
             // Moving the whole sequene of events is handled by the itemModified below.
             modify = true;
             break;
+        // FIXME: The following two cases do the following bad things:
+        // 1. Pop up a message box asking which resource to save the disassociated event to (!)
+        // 2. Crash at mActionItem->endMove(); below.
         case KMessageBox::Yes: { // Just this occurrence
             // Dissociate this occurrence:
             // create clone of event, set relation to old event, set cloned event
@@ -1073,16 +1082,18 @@ void KOAgenda::endItemAction()
             emit startMultiModify( i18n("Dissociate event from recurrence") );
             Incidence* oldInc = mActionItem->incidence();
             Incidence* oldIncSaved = mActionItem->incidence()->clone();
-            Incidence* newInc = mCalendar->dissociateOccurrence(
+            newInc = mCalendar->dissociateOccurrence(
                 oldInc, mActionItem->itemDate() );
             if ( newInc ) {
               // don't recreate items, they already have the correct position
               emit enableAgendaUpdate( false );
               mActionItem->dissociateFromMultiItem();
               mActionItem->setIncidence( newInc );
-              mChanger->addIncidence( newInc, this );
+              bool success = mChanger->addIncidence( newInc, this );
               emit enableAgendaUpdate( true );
-              mChanger->changeIncidence( oldIncSaved, oldInc );
+              if ( success ) {
+                mChanger->changeIncidence( oldIncSaved, oldInc );
+              }
             } else {
               KMessageBox::sorry( this, i18n("Unable to add the exception item to the "
                   "calendar. No change will be done."), i18n("Error Occurred") );
@@ -1101,15 +1112,17 @@ void KOAgenda::endItemAction()
             emit startMultiModify( i18n("Split future recurrences") );
             Incidence* oldInc = mActionItem->incidence();
             Incidence* oldIncSaved = mActionItem->incidence()->clone();
-            Incidence* newInc = mCalendar->dissociateOccurrence(
+            newInc = mCalendar->dissociateOccurrence(
                 oldInc, mActionItem->itemDate(), false );
             if ( newInc ) {
               emit enableAgendaUpdate( false );
               mActionItem->dissociateFromMultiItem();
               mActionItem->setIncidence( newInc );
-              mChanger->addIncidence( newInc, this );
+              bool success = mChanger->addIncidence( newInc, this );
               emit enableAgendaUpdate( true );
-              mChanger->changeIncidence( oldIncSaved, oldInc );
+              if ( success ) {
+                mChanger->changeIncidence( oldIncSaved, oldInc );
+              }
             } else {
               KMessageBox::sorry( this, i18n("Unable to add the future items to the "
                   "calendar. No change will be done."), i18n("Error Occurred") );
@@ -1124,28 +1137,58 @@ void KOAgenda::endItemAction()
     }
 
     if ( modify ) {
-      mActionItem->endMove();
-      KOAgendaItem *placeItem = mActionItem->firstMultiItem();
-      if  ( !placeItem ) {
-        placeItem = mActionItem;
+      if ( multiModify ) {
+        // mActionItem does not exist any more, seeing as we just got done deleting it
+        // (by deleting/replacing the original incidence it was created from through
+        // user modification of said incidence) above!
+        // Therefore we have to find the new KOAgendaItem that matches the new incidence
+        // Then we can apply the saved X/Y settings from the original move operation as shown.
+
+        KOAgendaItem *koai_insertedItem;
+        for ( koai_insertedItem = mItems.first(); koai_insertedItem; koai_insertedItem = mItems.next() ) {
+          if (koai_insertedItem->incidence() == newInc) {
+            selectItem( koai_insertedItem );
+            mSelectedItem->startMove();
+            mSelectedItem->setCellY(mai_yt, mai_yb);
+            mSelectedItem->setCellX(mai_xl, mai_xr);
+            mActionItem = mSelectedItem;
+            //mSelectedItem->endMove();
+            break;
+          }
+        }
+
+//         mActionItem->startMove();
+//         mActionItem->setCellY(mai_yt, mai_yb);
+//         mActionItem->setCellX(mai_xl, mai_xr);
+//         mActionItem->endMove();
       }
+    }
+
+    if ( modify ) {
+//       if ( !multiModify ) {
+        mActionItem->endMove();
+        KOAgendaItem *placeItem = mActionItem->firstMultiItem();
+        if  ( !placeItem ) {
+          placeItem = mActionItem;
+        }
 
-      KOAgendaItem *modif = placeItem;
+        KOAgendaItem *modif = placeItem;
 
-      TQPtrList<KOAgendaItem> oldconflictItems = placeItem->conflictItems();
-      KOAgendaItem *item;
-      for ( item = oldconflictItems.first(); item != 0;
-            item = oldconflictItems.next() ) {
-        placeSubCells( item );
-      }
-      while ( placeItem ) {
-        placeSubCells( placeItem );
-        placeItem = placeItem->nextMultiItem();
-      }
+        TQPtrList<KOAgendaItem> oldconflictItems = placeItem->conflictItems();
+        KOAgendaItem *item;
+        for ( item = oldconflictItems.first(); item != 0;
+              item = oldconflictItems.next() ) {
+          placeSubCells( item );
+        }
+        while ( placeItem ) {
+          placeSubCells( placeItem );
+          placeItem = placeItem->nextMultiItem();
+        }
 
-      // Notify about change
-      // the agenda view will apply the changes to the actual Incidence*!
-      emit itemModified( modif );
+        // Notify about change
+        // the agenda view will apply the changes to the actual Incidence*!
+        emit itemModified( modif );
+//       }
     }
     // FIXME: If the change failed, we need to update the view!
     mChanger->endChange( inc );
diff --git a/kresources/caldav/reader.cpp b/kresources/caldav/reader.cpp
index 9e167e7d..02358ba0 100644
--- a/kresources/caldav/reader.cpp
+++ b/kresources/caldav/reader.cpp
@@ -63,20 +63,22 @@ int CalDavReader::runJob(runtime_info* RT) {
 
     caldav_free_response(&result);
 
-    if ((OK == res) && (tasksUrl() != "")) {
+    CALDAV_RESPONSE tasksres = OK;
+
+    if ((OK == tasksres) && (tasksUrl() != "")) {
       kdDebug() << "reader::run, url: " << tasksUrl();
 
       result = caldav_get_response();
 
       if (mGetAll) {
           kdDebug() << "getting all objects";
-          res = caldav_tasks_getall_object(result, std::string(tasksUrl().ascii()).c_str(), RT);
+          tasksres = caldav_tasks_getall_object(result, std::string(tasksUrl().ascii()).c_str(), RT);
       } else {
           kdDebug() << "getting object from the specified time range";
-          res = caldav_tasks_get_object(result, mTimeStart.toTime_t(), mTimeEnd.toTime_t(), std::string(tasksUrl().ascii()).c_str(), RT);
+          tasksres = caldav_tasks_get_object(result, mTimeStart.toTime_t(), mTimeEnd.toTime_t(), std::string(tasksUrl().ascii()).c_str(), RT);
       }
 
-      if (OK == res) {
+      if (OK == tasksres) {
           kdDebug() << "success";
           if (result->msg) {
               mTasksData = result->msg;
@@ -90,7 +92,10 @@ int CalDavReader::runJob(runtime_info* RT) {
       caldav_free_response(&result);
     }
 
-    return res;
+    if (tasksres == OK)
+      return res;
+    else
+      return tasksres;
 }
 
 // EOF ========================================================================
diff --git a/kresources/caldav/writer.cpp b/kresources/caldav/writer.cpp
index c4101a0b..de168f36 100644
--- a/kresources/caldav/writer.cpp
+++ b/kresources/caldav/writer.cpp
@@ -75,37 +75,42 @@ int CalDavWriter::runJob(runtime_info* RT) {
       }
     }
 
-    if ((OK == res) && (tasksUrl() != "")) {
+    int tasksres = OK;
+
+    if ((OK == tasksres) && (tasksUrl() != "")) {
       kdDebug() << "pushing added tasks objects";
-      res = pushTasksObjects(mTasksAdded, caldav_add_object, OK, RT);
-      if (OK == res) {
+      tasksres = pushTasksObjects(mTasksAdded, caldav_add_object, OK, RT);
+      if (OK == tasksres) {
 #ifdef USE_CALDAV_TASKS_MODIFY
           kdDebug() << "pushing changed objects";
-          res = pushTasksObjects(mTasksChanged, caldav_tasks_modify_object, OK, RT);
-          if (OK == res) {
+          tasksres = pushTasksObjects(mTasksChanged, caldav_tasks_modify_object, OK, RT);
+          if (OK == tasksres) {
               kdDebug() << "pushing deleted objects";
-              res = pushTasksObjects(mTasksDeleted, caldav_tasks_delete_object, OK, RT);
+              tasksres = pushTasksObjects(mTasksDeleted, caldav_tasks_delete_object, OK, RT);
           }
 #else // if USE_CALDAV_TASKS_MODIFY
           kdDebug() << "pushing changed objects (delete)";
-          res = pushTasksObjects(mTasksChanged, caldav_tasks_delete_object, OK, RT);
-          if (OK == res) {
+          tasksres = pushTasksObjects(mTasksChanged, caldav_tasks_delete_object, OK, RT);
+          if (OK == tasksres) {
               kdDebug() << "pushing changed objects (add)";
-              res = pushTasksObjects(mTasksChanged, caldav_add_object, OK, RT);
-              if (OK == res) {
+              tasksres = pushTasksObjects(mTasksChanged, caldav_add_object, OK, RT);
+              if (OK == tasksres) {
                   kdDebug() << "pushing deleted objects";
-                  res = pushTasksObjects(mTasksDeleted, caldav_tasks_delete_object, OK, RT);
+                  tasksres = pushTasksObjects(mTasksDeleted, caldav_tasks_delete_object, OK, RT);
               }
           }
 #endif // if USE_CALDAV_TASKS_MODIFY
       }
     }
 
-    if (OK != res) {
+    if ((OK != res) || (OK != tasksres)) {
         clearObjects();
     }
 
-    return res;
+    if (tasksres == OK)
+      return res;
+    else
+      return tasksres;
 }
 
 // EOF ========================================================================
diff --git a/libkcal/calendar.cpp b/libkcal/calendar.cpp
index 0be3dffc..65afb77e 100644
--- a/libkcal/calendar.cpp
+++ b/libkcal/calendar.cpp
@@ -328,6 +328,8 @@ Incidence *Calendar::dissociateOccurrence( Incidence *incidence, TQDate date,
 
   Incidence *newInc = incidence->clone();
   newInc->recreate();
+  newInc->setHasRecurrenceID(false);
+  newInc->setRecurrenceID(QString());
   newInc->setRelatedTo( incidence );
   Recurrence *recur = newInc->recurrence();
   if ( single ) {
diff --git a/libkcal/calendarresources.h b/libkcal/calendarresources.h
index 1858a85b..9d343634 100644
--- a/libkcal/calendarresources.h
+++ b/libkcal/calendarresources.h
@@ -177,7 +177,7 @@ class LIBKCAL_EXPORT CalendarResources :
 
     /**
      * Reloads all incidences from all resources.
-     * @par tz The timezone to set.
+     * @param tz The timezone to set.
      * @return success or failure
      */
     bool reload( const TQString &tz );
@@ -293,7 +293,7 @@ class LIBKCAL_EXPORT CalendarResources :
     /**
        Add a Resource to the Calendar.
        This method must be public, because in-process added Resources
-       do not emit the corresponding signal, so this methodd has to be
+       do not emit the corresponding signal, so this method has to be
        called manually!
 
        @param resource is a pointer to the ResourceCalendar to add.
-- 
cgit v1.2.3

