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;
}
Exemple #2
0
  Attendee::Role role;
  Attendee::PartStat status;
  QString uid;
  QString delegate;
  QString delegator;
  CustomProperties customProperties;
  uint role_int;
  uint status_int;

  KCalCore::Person::Ptr person( new Person() );
  stream >> person;
  stream >> RSVP
         >> role_int
         >> status_int
         >> uid
         >> delegate
         >> delegator
         >> customProperties;

  role = Attendee::Role( role_int );
  status = Attendee::PartStat( status_int );

  Attendee::Ptr att_temp( new KCalCore::Attendee( person->name(), person->email(),
                                                  RSVP, status, role, uid ) );
  att_temp->setDelegate( delegate );
  att_temp->setDelegator( delegator );
  att_temp->d->mCustomProperties = customProperties;
  attendee.swap( att_temp );
  return stream;
}