Example #1
0
void EventArchiver::run(Calendar *calendar, const QDate &limitDate, QWidget *widget, bool withGUI, bool errorIfNone)
{
    // We need to use rawEvents, otherwise events hidden by filters will not be archived.
    Incidence::List incidences;
    Event::List events;
    Todo::List todos;
    Journal::List journals;

    if(KOPrefs::instance()->mArchiveEvents)
    {
        events = calendar->rawEvents(
                     QDate(1769, 12, 1),
                     // #29555, also advertised by the "limitDate not included" in the class docu
                     limitDate.addDays(-1),
                     true);
    }
    if(KOPrefs::instance()->mArchiveTodos)
    {
        Todo::List t = calendar->rawTodos();
        Todo::List::ConstIterator it;
        for(it = t.begin(); it != t.end(); ++it)
        {
            if((*it) && ((*it)->isCompleted()) && ((*it)->completed().date() < limitDate))
            {
                todos.append(*it);
            }
        }
    }

    incidences = Calendar::mergeIncidenceList(events, todos, journals);


    kdDebug(5850) << "EventArchiver: archiving incidences before " << limitDate << " -> " << incidences.count() << " incidences found." << endl;
    if(incidences.isEmpty())
    {
        if(withGUI && errorIfNone)
            KMessageBox::information(widget, i18n("There are no items before %1")
                                     .arg(KGlobal::locale()->formatDate(limitDate)),
                                     "ArchiverNoIncidences");
        return;
    }


    switch(KOPrefs::instance()->mArchiveAction)
    {
        case KOPrefs::actionDelete:
            deleteIncidences(calendar, limitDate, widget, incidences, withGUI);
            break;
        case KOPrefs::actionArchive:
            archiveIncidences(calendar, limitDate, widget, incidences, withGUI);
            break;
    }
}
Example #2
0
Incidence::Ptr DndFactory::pasteIncidence( const KDateTime &newDateTime,
                                           const QFlags<PasteFlag> &pasteOptions )
{
  QClipboard *clipboard = QApplication::clipboard();
  MemoryCalendar::Ptr calendar( createDropCalendar( clipboard->mimeData() ) );

  if ( !calendar ) {
    kDebug() << "Can't parse clipboard";
    return Incidence::Ptr();
  }

  Incidence::List incidenceList = calendar->incidences();
  Incidence::Ptr incidence = incidenceList.isEmpty() ? Incidence::Ptr() : incidenceList.first();

  return d->pasteIncidence( incidence, newDateTime, pasteOptions );
}
Example #3
0
Incidence *DndFactory::pasteIncidence( const QDate &newDate, const QTime *newTime )
{
  QClipboard *cb = QApplication::clipboard();
  Calendar *cal = createDropCalendar( cb->mimeData() );

  if ( !cal ) {
    kDebug() << "Can't parse clipboard";
    return 0;
  }

  Incidence::List incList = cal->incidences();
  Incidence *inc = incList.isEmpty() ? 0 : incList.first();

  Incidence *newInc = d->pasteIncidence( inc, newDate, newTime );
  newInc->setRelatedTo( 0 );
  return newInc;
}
void KCalResourceSlox::uploadIncidences()
{
  QDomDocument doc;
  QDomElement ms = WebdavHandler::addDavElement( doc, doc, "multistatus" );
  QDomElement pu = WebdavHandler::addDavElement( doc, ms, "propertyupdate" );
  QDomElement set = WebdavHandler::addElement( doc, pu, "D:set" );
  QDomElement prop = WebdavHandler::addElement( doc, set, "D:prop" );

  mUploadIsDelete = false;
  Incidence::List added = addedIncidences();
  Incidence::List changed = changedIncidences();
  Incidence::List deleted = deletedIncidences();
  if ( !added.isEmpty() ) {
    mUploadedIncidence = added.first();
  } else if ( !changed.isEmpty() ) {
    mUploadedIncidence = changed.first();
  } else if ( !deleted.isEmpty() ) {
    mUploadedIncidence = deleted.first();
    mUploadIsDelete = true;
  } else {
    mUploadedIncidence = 0;
    kDebug() << "FINISHED";
    emit resourceSaved( this );
    return;
  }

  // Don't try to upload recurring incidences as long as the resource doesn't
  // correctly write them in order to avoid corrupting data on the server.
  // FIXME: Remove when recurrences are correctly written.
  if ( mUploadedIncidence->recurs() && type() == "slox" ) {
    clearChange( mUploadedIncidence );
    uploadIncidences();
    return;
  }

  KUrl url = mPrefs->url();

  QString sloxId = mUploadedIncidence->customProperty( "SLOX", "ID" );
  if ( !sloxId.isEmpty() ) {
    WebdavHandler::addSloxElement( this, doc, prop, fieldName( ObjectId ), sloxId );
  } else {
    if ( mUploadIsDelete ) {
      kError() << "Incidence to delete doesn't have a SLOX id";
      clearChange( mUploadedIncidence );
      uploadIncidences();
      return;
    }
  }
  WebdavHandler::addSloxElement( this, doc, prop, fieldName( ClientId ),
                                 mUploadedIncidence->uid() );

  if ( type() == "ox" ) {
    const QString lastModified = mUploadedIncidence->customProperty( "SLOX", "LastModified" );
    WebdavHandler::addSloxElement( this, doc, prop, fieldName( LastModified ), lastModified );
  }

  if ( mUploadIsDelete ) {
    if ( mUploadedIncidence->type() == "Event" ) {
      url.setPath( "/servlet/webdav.calendar/" + sloxId );
    } else if ( mUploadedIncidence->type() == "Todo" ) {
      url.setPath( "/servlet/webdav.tasks/" + sloxId );
    } else {
      kWarning() << "Unsupported incidence type:"
                 << mUploadedIncidence->type();
      return;
    }

    if ( type() == "ox" ) {
      WebdavHandler::addSloxElement( this, doc, prop, "method", "DELETE" );
      if ( mUploadedIncidence->type() == "Event" )
        WebdavHandler::addSloxElement( this, doc, prop, fieldName( FolderId ), mPrefs->calendarFolderId() );
      else if ( mUploadedIncidence->type() == "Todo" )
        WebdavHandler::addSloxElement( this, doc, prop, fieldName( FolderId ), mPrefs->taskFolderId() );
    } else {
      QDomElement remove = WebdavHandler::addElement( doc, pu, "D:remove" );
      QDomElement prop = WebdavHandler::addElement( doc, remove, "D:prop" );
      WebdavHandler::addSloxElement( this, doc, prop, "sloxid", sloxId );
    }
  } else {
    createIncidenceAttributes( doc, prop, mUploadedIncidence );
    // FIXME: Use a visitor
    if ( mUploadedIncidence->type() == "Event" ) {
      url.setPath( "/servlet/webdav.calendar/file.xml" );
      createEventAttributes( doc, prop, static_cast<Event *>( mUploadedIncidence ) );
      // TODO: OX supports recurrences also for tasks
      createRecurrenceAttributes( doc, prop, mUploadedIncidence );
    } else if ( mUploadedIncidence->type() == "Todo" ) {
      url.setPath( "/servlet/webdav.tasks/file.xml" );
      createTodoAttributes( doc, prop, static_cast<Todo *>( mUploadedIncidence ) );
    } else {
      kWarning() << "Unsupported incidence type:"
                 << mUploadedIncidence->type();
      return;
    }
  }

  url.setUser( mPrefs->user() );
  url.setPass( mPrefs->password() );

  kDebug() << url;

  kDebug() << "UPLOAD:" << doc.toString( 2 );

  mUploadJob = KIO::davPropPatch( url, doc, KIO::HideProgressInfo );
  connect( mUploadJob, SIGNAL( result( KJob * ) ),
           SLOT( slotUploadResult( KJob * ) ) );
  connect( mUploadJob, SIGNAL( percent( KJob *, unsigned long ) ),
           SLOT( slotUploadProgress( KJob *, unsigned long ) ) );

  mUploadProgress = KPIM::ProgressManager::instance()->createProgressItem(
      KPIM::ProgressManager::getUniqueID(), i18n("Uploading incidence") );
  connect( mUploadProgress,
           SIGNAL( progressItemCanceled( KPIM::ProgressItem * ) ),
           SLOT( cancelUpload() ) );
}
CallId Scheduler::acceptRequest( const IncidenceBase::Ptr &incidence,
                                 ScheduleMessage::Status status,
                                 const QString &email )
{
  Incidence::Ptr inc = incidence.staticCast<Incidence>() ;
  if ( !inc ) {
    kWarning() << "Accept what?";
    return -1;
  }

  const CallId callId = ++d->mLatestCallId;
  ResultCode resultCode = ResultCodeSuccess;
  QString errorMessage;

  if ( inc->type() == IncidenceBase::TypeFreeBusy ) {
    emitOperationFinished( callId, ResultCodeSuccess, QString() );
    // reply to this request is handled in korganizer's incomingdialog
    return callId;
  }

  const Incidence::List existingIncidences = d->mCalendar->incidencesFromSchedulingID( inc->uid() );
  kDebug() << "status=" << Stringify::scheduleMessageStatus( status ) //krazy:exclude=kdebug
           << ": found " << existingIncidences.count()
           << " incidences with schedulingID " << inc->schedulingID()
           << "; uid was = " << inc->uid();

  if ( existingIncidences.isEmpty() ) {
    // Perfectly normal if the incidence doesn't exist. This is probably
    // a new invitation.
    kDebug() << "incidence not found; calendar = " << d->mCalendar.data()
             << "; incidence count = " << d->mCalendar->incidences().count();
  }
  Incidence::List::ConstIterator incit = existingIncidences.begin();
  for ( ; incit != existingIncidences.end() ; ++incit ) {
    Incidence::Ptr existingIncidence = *incit;
    kDebug() << "Considering this found event ("
             << ( existingIncidence->isReadOnly() ? "readonly" : "readwrite" )
             << ") :" << d->mFormat->toString( existingIncidence );
    // If it's readonly, we can't possible update it.
    if ( existingIncidence->isReadOnly() ) {
      continue;
    }
    if ( existingIncidence->revision() <= inc->revision() ) {
      // The new incidence might be an update for the found one
      bool isUpdate = true;
      // Code for new invitations:
      // If you think we could check the value of "status" to be RequestNew:  we can't.
      // It comes from a similar check inside libical, where the event is compared to
      // other events in the calendar. But if we have another version of the event around
      // (e.g. shared folder for a group), the status could be RequestNew, Obsolete or Updated.
      kDebug() << "looking in " << existingIncidence->uid() << "'s attendees";
      // This is supposed to be a new request, not an update - however we want to update
      // the existing one to handle the "clicking more than once on the invitation" case.
      // So check the attendee status of the attendee.
      const Attendee::List attendees = existingIncidence->attendees();
      Attendee::List::ConstIterator ait;
      for ( ait = attendees.begin(); ait != attendees.end(); ++ait ) {
        if( (*ait)->email() == email && (*ait)->status() == Attendee::NeedsAction ) {
          // This incidence wasn't created by me - it's probably in a shared folder
          // and meant for someone else, ignore it.
          kDebug() << "ignoring "
                   << existingIncidence->uid() << " since I'm still NeedsAction there";
          isUpdate = false;
          break;
        }
      }
      if ( isUpdate ) {
        if ( existingIncidence->revision() == inc->revision() &&
             existingIncidence->lastModified() > inc->lastModified() ) {
          // This isn't an update - the found incidence was modified more recently
          deleteTransaction( existingIncidence->uid() );
          errorMessage = QLatin1String( "This isn't an update - "
                                        "the found incidence was modified more recently" );
          kDebug() << errorMessage;
          emitOperationFinished( callId, ResultCodeNotUpdate, errorMessage );

          return callId;
        }
        kDebug() << "replacing existing incidence " << existingIncidence->uid();

        bool emitResult = true;
        const QString oldUid = existingIncidence->uid();
        if ( existingIncidence->type() != inc->type() ) {
          errorMessage = QLatin1String( "Cannot assign two different incidence types" );
          resultCode = ResultCodeDifferentIncidenceTypes;
        } else {
          IncidenceBase *existingIncidenceBase = existingIncidence.data();
          IncidenceBase *incBase = inc.data();
          *existingIncidenceBase = *incBase;
          existingIncidence->setSchedulingID( inc->uid(), oldUid );

          Akonadi::Item item = d->mCalendar->itemForIncidenceUid( oldUid );
          item.setPayload<Incidence::Ptr>( existingIncidence );
          if ( item.isValid() ) {
            const int changeId = d->mChanger->modifyIncidence( item );

            if ( changeId >= 0 ) {
              d->mCallIdByChangeId.insert( changeId, callId );
              emitResult = false; // will be emitted in the job result's slot.
            } else {
              resultCode = ResultCodeErrorUpdatingIncidence;
              errorMessage = QLatin1String( "Error while trying to update the incidence" );
            }
          } else {
            resultCode = ResultCodeIncidenceNotFound;
            errorMessage = QLatin1String( "Couldn't find incidence in calendar" );
          }
        }

        if ( emitResult ) {
          deleteTransaction( incidence->uid() );
          emitOperationFinished( callId, resultCode, errorMessage );
        }
        return callId;
      }
    } else {
      // This isn't an update - the found incidence has a bigger revision number

      deleteTransaction( incidence->uid() );

      errorMessage = QLatin1String( "This isn't an update - "
                                    "the found incidence has a bigger revision number" );
      kDebug() << errorMessage;
      emitOperationFinished( callId, ResultCodeNotUpdate, errorMessage );

      return callId;
    }
  }

  // Move the uid to be the schedulingID and make a unique UID
  inc->setSchedulingID( inc->uid(), CalFormat::createUniqueId() );
  // notify the user in case this is an update and we didn't find the to-be-updated incidence
  if ( existingIncidences.count() == 0 && inc->revision() > 0 ) {
    KMessageBox::information(
      0,
      i18nc( "@info",
             "<para>You accepted an invitation update, but an earlier version of the "
             "item could not be found in your calendar.</para>"
             "<para>This may have occurred because:<list>"
             "<item>the organizer did not include you in the original invitation</item>"
             "<item>you did not accept the original invitation yet</item>"
             "<item>you deleted the original invitation from your calendar</item>"
             "<item>you no longer have access to the calendar containing the invitation</item>"
             "</list></para>"
             "<para>This is not a problem, but we thought you should know.</para>" ),
      i18nc( "@title", "Cannot find invitation to be updated" ), "AcceptCantFindIncidence" );
  }
  kDebug() << "Storing new incidence with scheduling uid=" << inc->schedulingID()
           << " and uid=" << inc->uid();
  const int changeId = d->mChanger->createIncidence( inc );

  if ( changeId > 0 ) {
    d->mCallIdByChangeId[changeId] = callId;
  } else {
    emitOperationFinished( callId, ResultCodeErrorCreatingIncidence,
                           QLatin1String( "Error creating incidence" ) );
  }

  return callId;
}