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;
}
QString timetrackerstorage::load(TaskView* view, const QString &fileName)
// loads data from filename into view. If no filename is given, filename from preferences is used.
// filename might be of use if this program is run as embedded konqueror plugin.
{
    Q_UNUSED(fileName); // TODO: receive changes from akonadi
    kDebug(5970) << "Entering function";
    QString err;
    KEMailSettings settings;

    // If file doesn't exist, create a blank one to avoid ResourceLocal load
    // error.  We make it user and group read/write, others read.  This is
    // masked by the users umask.  (See man creat)
    if ( d->mCalendar )
        closeStorage();
    // Create local file resource and add to resources
    d->mICalFile = "";
    d->mCalendar = KTTCalendar::createInstance();

    QObject::connect( d->mCalendar.data(), SIGNAL(calendarChanged()),
                      view, SLOT(iCalFileModified()) );
    d->mCalendar->setTimeSpec( KSystemTimeZones::local() );
    d->mCalendar->reload();

    // Claim ownership of iCalendar file if no one else has.
    KCalCore::Person::Ptr owner = d->mCalendar->owner();
    if ( owner && owner->isEmpty() )
    {
        // TODO
        d->mCalendar->setOwner( KCalCore::Person::Ptr(
           new KCalCore::Person( settings.getSetting( KEMailSettings::RealName ),
                                 settings.getSetting( KEMailSettings::EmailAddress ) ) ) );
    }

    // TODO
    // Build task view from iCal data
    if (!err.isEmpty())
    {
        KCalCore::Todo::List todoList;
        KCalCore::Todo::List::ConstIterator todo;
        QMultiHash< QString, Task* > map;

        // Build dictionary to look up Task object from Todo uid.  Each task is a
        // QListViewItem, and is initially added with the view as the parent.
        todoList = d->mCalendar->rawTodos();
        kDebug(5970) << "timetrackerstorage::load"
            << "rawTodo count (includes completed todos) ="
            << todoList.count();
        for (todo = todoList.constBegin(); todo != todoList.constEnd(); ++todo)
        {
            Task* task = new Task(*todo, view);
            map.insert( (*todo)->uid(), task );
            view->setRootIsDecorated(true);
            task->setPixmapProgress();
        }

        // Load each task under it's parent task.
        for (todo = todoList.constBegin(); todo != todoList.constEnd(); ++todo)
        {
            Task* task = map.value( (*todo)->uid() );
            // No relatedTo incident just means this is a top-level task.
            if ( !(*todo)->relatedTo().isEmpty() )
            {
                Task *newParent = map.value( (*todo)->relatedTo() );

                // Complete the loading but return a message
                if ( !newParent )
                    err = i18n("Error loading \"%1\": could not find parent (uid=%2)",
                        task->name(), (*todo)->relatedTo()  );

                if (!err.isEmpty()) task->move( newParent );
            }
        }

        kDebug(5970) << "timetrackerstorage::load - loaded" << view->count()
            << "tasks from" << d->mICalFile;
    }

    if ( view ) buildTaskView(d->mCalendar->weakPointer(), view);

    this->save(view); // FIXME ?

    return err;
}
Example #3
0
                << attendee->d->mCustomProperties;
}

QDataStream &KCalCore::operator>>( QDataStream &stream, KCalCore::Attendee::Ptr &attendee )
{
  bool RSVP;
  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 );