int CalDavClient::removeCommonIncidences(KCalCore::Incidence::List *firstList, KCalCore::Incidence::List *secondList) { QSet<QString> firstListUids; for (int i=0; i<firstList->count(); i++) { firstListUids.insert(firstList->at(i)->uid()); } QSet<QString> commonUids; for (KCalCore::Incidence::List::iterator it = secondList->begin(); it != secondList->end();) { KCalCore::Incidence::Ptr incidence = *it; if (firstListUids.contains(incidence->uid())) { commonUids.insert(incidence->uid()); it = secondList->erase(it); } else { ++it; } } int removed = commonUids.count(); if (removed > 0) { for (KCalCore::Incidence::List::iterator it = firstList->begin(); it != firstList->end();) { KCalCore::Incidence::Ptr incidence = *it; if (commonUids.contains(incidence->uid())) { commonUids.remove(incidence->uid()); it = firstList->erase(it); } else { ++it; } } } return removed; }
static bool incidenceLessThan(const KCalCore::Incidence::Ptr e1, const KCalCore::Incidence::Ptr e2) { if (e1->dtStart() == e2->dtStart()) { int cmp = QString::compare(e1->summary(), e2->summary(), Qt::CaseInsensitive); if (cmp == 0) return QString::compare(e1->uid(), e2->uid()) < 0; else return cmp < 0; } else { return e1->dtStart() < e2->dtStart(); } }
bool NotebookSyncAgent::discardRemoteChanges(KCalCore::Incidence::List *localInserted, KCalCore::Incidence::List *localModified, KCalCore::Incidence::List *localDeleted) { NOTEBOOK_FUNCTION_CALL_TRACE; // Go through the local inserted, modified and deletions list and: // - Discard from them respectively the additions, modifications and deletions that were // created as a result of the last remote sync. // - Discard any incidences that have already been deleted on the server. (These will be // deleted locally when the current sync finishes.) // - Discard any local modifications that were modified on the server, as the server // modifications take precedence. if (!mNotebook) { LOG_CRITICAL("no notebook"); return false; } bool ok = false; QSet<QString> remoteDeletedIncidences = QSet<QString>::fromList(mIncidenceUidsToDelete); QStringList additions = mDatabase->additions(mNotebook->uid(), &ok); if (!ok) { LOG_CRITICAL("Unable to look up last sync additions for notebook:" << mNotebook->uid()); return false; } QHash<QString,QString> modifications = mDatabase->modifications(mNotebook->uid(), &ok); if (!ok) { LOG_CRITICAL("Unable to look up last sync modifications for notebook:" << mNotebook->uid()); return false; } for (KCalCore::Incidence::List::iterator it = localInserted->begin(); it != localInserted->end();) { const KCalCore::Incidence::Ptr &incidence = *it; const QString &uid = incidence->uid(); if (remoteDeletedIncidences.contains(uid)) { LOG_DEBUG("Discarding addition deleted on server:" << uid); it = localInserted->erase(it); } else if (additions.indexOf(uid) >= 0) { if (incidence->lastModified().isValid() && incidence->lastModified() > incidence->created()) { // This incidence has been modified since it was added from the server in the last sync, // so it's a modification rather than an addition. LOG_DEBUG("Moving to modified:" << uid); KCalCore::Incidence::Ptr savedIncidence = fetchIncidence(mCalendar, uid); if (savedIncidence) { localModified->append(savedIncidence); it = localInserted->erase(it); } else { ++it; } } else { LOG_DEBUG("Discarding addition from previous sync:" << uid); it = localInserted->erase(it); } } else { ++it; } } QSet<QString> serverModifiedUids; for (int i=0; i<mReceivedCalendarResources.count(); i++) { serverModifiedUids.insert(Reader::hrefToUid(mReceivedCalendarResources[i].href)); } for (KCalCore::Incidence::List::iterator it = localModified->begin(); it != localModified->end();) { KCalCore::Incidence::Ptr sourceIncidence = *it; const QString &uid = sourceIncidence->uid(); if (remoteDeletedIncidences.contains(uid) || serverModifiedUids.contains(uid)) { LOG_DEBUG("Discarding modification," << (remoteDeletedIncidences.contains(uid) ? "was already deleted on server" : "") << (serverModifiedUids.contains(uid) ? "was already modified on server": "")); it = localModified->erase(it); continue; } else if (modifications.contains(uid)) { KCalCore::ICalFormat iCalFormat; KCalCore::Incidence::Ptr receivedIncidence = iCalFormat.fromString(modifications[uid]); if (receivedIncidence.isNull()) { LOG_WARNING("Not sending modification, cannot parse the received incidence:" << modifications[uid]); it = localModified->erase(it); continue; } // If incidences are the same, then we assume the local incidence was not changed after // the remote incidence was received, and thus there are no modifications to report. IncidenceHandler::prepareImportedIncidence(receivedIncidence); // ensure fields are updated as per imported incidences if (IncidenceHandler::copiedPropertiesAreEqual(sourceIncidence, receivedIncidence)) { LOG_DEBUG("Discarding modification" << uid); it = localModified->erase(it); continue; } } // The default storage implementation applies the organizer as an attendee by default. Don't do this // as it turns the incidence into a scheduled event requiring acceptance/rejection/etc. const KCalCore::Person::Ptr organizer = sourceIncidence->organizer(); if (organizer) { Q_FOREACH (const KCalCore::Attendee::Ptr &attendee, sourceIncidence->attendees()) { if (attendee->email() == organizer->email() && attendee->fullName() == organizer->fullName()) { LOG_DEBUG("Discarding organizer as attendee" << attendee->fullName()); sourceIncidence->deleteAttendee(attendee); break; } } } ++it; } QStringList deletions = mDatabase->deletions(mNotebook->uid(), &ok); if (!ok) { LOG_CRITICAL("Unable to look up last sync deletions for notebook:" << mNotebook->uid()); return false; } for (KCalCore::Incidence::List::iterator it = localDeleted->begin(); it != localDeleted->end();) { const QString &uid = (*it)->uid(); mLocalDeletedUids.insert(uid); if (remoteDeletedIncidences.contains(uid) || deletions.indexOf(uid) >= 0) { LOG_DEBUG("Discarding deletion" << uid); it = localDeleted->erase(it); } else { ++it; } } return true; }