void KJotsLinkDialog::setLinkUrl(const QString &linkUrl)
{
    Akonadi::Item item = Akonadi::Item::fromUrl(KUrl(linkUrl));
    Akonadi::Collection collection = Akonadi::Collection::fromUrl(KUrl(linkUrl));

    if (!item.isValid() && !collection.isValid()) {
        linkUrlLineEdit->setText(linkUrl);
        linkUrlLineEditRadioButton->setChecked(true);
        return;
    }

    QModelIndex idx;

    if (collection.isValid()) {
        idx = Akonadi::EntityTreeModel::modelIndexForCollection( m_descendantsProxyModel, collection );
    } else if (item.isValid()) {
        const QModelIndexList list = Akonadi::EntityTreeModel::modelIndexesForItem( m_descendantsProxyModel, item );
        if (list.isEmpty())
            return;

        idx = list.first();
    }

    if (!idx.isValid())
        return;

    hrefComboRadioButton->setChecked(true);

    hrefCombo->view()->setCurrentIndex( idx );
    hrefCombo->setCurrentIndex( idx.row() );
}
Ejemplo n.º 2
0
Akonadi::Item::List Serializer::filterDescendantItems(const Akonadi::Item::List &potentialChildren, const Akonadi::Item &ancestorItem)
{
    if (potentialChildren.isEmpty())
        return Akonadi::Item::List();

    Akonadi::Item::List itemsToProcess = potentialChildren;
    Q_ASSERT(ancestorItem.isValid() && ancestorItem.hasPayload<KCalCore::Todo::Ptr>());
    KCalCore::Todo::Ptr todo = ancestorItem.payload<KCalCore::Todo::Ptr>();

    const auto bound = std::partition(itemsToProcess.begin(), itemsToProcess.end(),
                                      [ancestorItem, todo](Akonadi::Item currentItem) {
                                          return (!currentItem.hasPayload<KCalCore::Todo::Ptr>()
                                               || currentItem == ancestorItem
                                               || currentItem.payload<KCalCore::Todo::Ptr>()->relatedTo() != todo->uid());
                                      });

    Akonadi::Item::List itemsRemoved;
    std::copy(itemsToProcess.begin(), bound, std::back_inserter(itemsRemoved));
    itemsToProcess.erase(itemsToProcess.begin(), bound);

    auto result = std::accumulate(itemsToProcess.begin(), itemsToProcess.end(), Akonadi::Item::List(),
                                 [this, itemsRemoved](Akonadi::Item::List result, Akonadi::Item currentItem) {
                                     result << currentItem;
                                     return result += filterDescendantItems(itemsRemoved, currentItem);
                                 });

    return result;
}
Ejemplo n.º 3
0
QMap<QString, QString> OpportunityDetails::data(const Akonadi::Item &item) const
{
    Q_ASSERT(item.isValid());
    Q_ASSERT(item.hasPayload<SugarOpportunity>());
    SugarOpportunity opportunity = item.payload<SugarOpportunity>();
    return opportunity.data();
}
Ejemplo n.º 4
0
void KMReaderWin::slotDeleteMessage(const Akonadi::Item &item)
{
    if (!item.isValid()) {
        return;
    }
    KMTrashMsgCommand *command = new KMTrashMsgCommand(item.parentCollection(), item, -1);
    command->start();
}
Ejemplo n.º 5
0
void KMReaderWin::slotUrlClicked(const Akonadi::Item &item, const QUrl &url)
{
    if (item.isValid() && item.parentCollection().isValid()) {
        QSharedPointer<FolderCollection> fd = FolderCollection::forCollection(
                MailCommon::Util::updatedCollection(item.parentCollection()), false);
        KMail::Util::handleClickedURL(url, fd);
        return;
    }
    //No folder so we can't have identity and template.
    KMail::Util::handleClickedURL(url);
}
Ejemplo n.º 6
0
void ItemsTreeView::keyPressEvent(QKeyEvent *event)
{
    if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) {
        const QModelIndex idx = currentIndex();
        if (idx.isValid()) {
            const Akonadi::Item item = idx.data(Akonadi::EntityTreeModel::ItemRole).value<Akonadi::Item>();
            if (item.isValid()) {
                emit returnPressed(item);
            }
        }
    }
    Akonadi::EntityTreeView::keyPressEvent(event);
}
QString KJotsLinkDialog::linkUrl() const
{
    if (hrefComboRadioButton->isChecked()){
        const QModelIndex index = hrefCombo->view()->currentIndex();
        const Akonadi::Collection collection = index.data(Akonadi::EntityTreeModel::CollectionRole).value<Akonadi::Collection>();
        if (collection.isValid()) {
          return "kjots://org.kjots.book/" + QString::number(collection.id());
        }
        const Akonadi::Item item = index.data(Akonadi::EntityTreeModel::ItemRole).value<Akonadi::Item>();
        Q_ASSERT(item.isValid());
        return "kjots://org.kjots.page/" + QString::number(item.id());
    } else {
        return linkUrlLineEdit->text();
    }
}
Ejemplo n.º 8
0
void KMReaderWin::slotMailToAddToExistingContact()
{
    const QUrl url = urlClicked();
    if (url.isEmpty()) {
        return;
    }
    const QString emailString = KEmailAddress::decodeMailtoUrl(url);
    QPointer<AddEmailToExistingContactDialog> dlg = new AddEmailToExistingContactDialog(this);
    if (dlg->exec()) {
        Akonadi::Item item = dlg->selectedContact();
        if (item.isValid()) {
            AddEmailToExistingContactJob *job = new AddEmailToExistingContactJob(item, emailString, this);
            job->start();
        }
    }
    delete dlg;
}
Ejemplo n.º 9
0
bool CalFilterProxyModel::filterAcceptsRow( int source_row, const QModelIndex &source_parent ) const
{
  if ( !d->filter )
    return true;

  const QModelIndex idx = sourceModel()->index( source_row, 0, source_parent );
  if ( !idx.isValid() )
    return false;

  const Akonadi::Item item = idx.data( Akonadi::EntityTreeModel::ItemRole ).value<Akonadi::Item>();
  if ( !item.isValid() || !item.hasPayload<KCalCore::Incidence::Ptr>() )
    return false;

  const KCalCore::Incidence::Ptr incidence = item.payload<KCalCore::Incidence::Ptr>();
  if ( !incidence )
    return false;

  return d->filter->filterIncidence( incidence );
}
CallId Scheduler::acceptCancel( const IncidenceBase::Ptr &incidence,
                                ScheduleMessage::Status status,
                                const QString &attendee )
{
  Incidence::Ptr inc = incidence.staticCast<Incidence>();
  if ( !inc ) {
    return -1;
  }

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

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

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

  Incidence::List::ConstIterator incit = existingIncidences.begin();
  for ( ; incit != existingIncidences.end() ; ++incit ) {
    Incidence::Ptr i = *incit;
    kDebug() << "Considering this found event ("
             << ( i->isReadOnly() ? "readonly" : "readwrite" )
             << ") :" << d->mFormat->toString( i );

    // If it's readonly, we can't possible remove it.
    if ( i->isReadOnly() ) {
      continue;
    }

    // Code for new invitations:
    // We cannot check the value of "status" to be RequestNew because
    // "status" 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 " << i->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.
    bool isMine = true;
    const Attendee::List attendees = i->attendees();
    Attendee::List::ConstIterator ait;
    for ( ait = attendees.begin(); ait != attendees.end(); ++ait ) {
      if ( (*ait)->email() == attendee &&
           (*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 " << i->uid()
                 << " since I'm still NeedsAction there";
        isMine = false;
        break;
      }
    }

    if ( isMine ) {
      //TODO_SERGIO: use ItemDeleteJob and make this async.
      kDebug() << "removing existing incidence " << i->uid();

      Akonadi::Item item = d->mCalendar->itemForIncidenceUid( i->uid() );
      bool emitResult = true;
      if ( item.isValid() ) {
        const int changeId = d->mChanger->deleteIncidence( item );

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

      if ( emitResult ) {
        deleteTransaction( incidence->uid() );
        errorMessage = QLatin1String( "Error deleting incidence" );
        emitOperationFinished( callId, resultCode, errorMessage );
      }

      return callId;
    }
  }

  // in case we didn't find the to-be-removed incidence
  if ( existingIncidences.count() > 0 && inc->revision() > 0 ) {
    KMessageBox::error(
      0,
      i18nc( "@info",
             "The event or task could not be removed from your calendar. "
             "Maybe it has already been deleted or is not owned by you. "
             "Or it might belong to a read-only or disabled calendar." ) );
    resultCode = ResultCodeIncidenceNotFound;
    errorMessage = QLatin1String( "Incidence not found" );
  }
  deleteTransaction( incidence->uid() );
  emitOperationFinished( callId, resultCode, errorMessage );

  return callId;
}
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;
}
CallId Scheduler::acceptPublish( const IncidenceBase::Ptr &newIncBase,
                                 ScheduleMessage::Status status,
                                 iTIPMethod method )
{
  if ( newIncBase->type() == IncidenceBase::TypeFreeBusy ) {
    return acceptFreeBusy( newIncBase, method );
  }

  const CallId callId = ++d->mLatestCallId;

  ResultCode resultCode = ResultCodeSuccess;
  QString errorMessage;

  kDebug() << "status=" << Stringify::scheduleMessageStatus( status ); //krazy:exclude=kdebug

  bool emitResult = true;

  Incidence::Ptr newInc = newIncBase.staticCast<Incidence>() ;
  Incidence::Ptr calInc = d->mCalendar->incidence( newIncBase->uid() );
  switch ( status ) {
    case ScheduleMessage::Unknown:
    case ScheduleMessage::PublishNew:
    case ScheduleMessage::PublishUpdate:
      if ( calInc && newInc ) {
        if ( ( newInc->revision() > calInc->revision() ) ||
             ( newInc->revision() == calInc->revision() &&
               newInc->lastModified() > calInc->lastModified() ) ) {
          const QString oldUid = calInc->uid();

          if ( calInc->type() != newInc->type() ) {
            kError() << "assigning different incidence types";
            resultCode = ResultCodeDifferentIncidenceTypes;
            errorMessage = QLatin1String( "Cannot assign two different incidence types" );
          } else {
            IncidenceBase *ci = calInc.data();
            IncidenceBase *ni = newInc.data();
            *ci = *ni;
            calInc->setSchedulingID( newInc->uid(), oldUid );

            Akonadi::Item item = d->mCalendar->itemForIncidenceUid( calInc->uid() );
            item.setPayload<Incidence::Ptr>( calInc );

            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" );
            }
          }
        } else {
          resultCode = ResultCodeNewIncidenceTooOld;
          errorMessage = QLatin1String( "A newer existing incidence already exists" );
        }
      } else {
        resultCode = ResultCodeInvalidIncidence;
        errorMessage = QLatin1String( "Incidence is invalid" );
      }
      break;
    case ScheduleMessage::Obsolete:
      // Success
      break;
    default:
      resultCode = ResultCodeUnknownStatus;
      errorMessage = QLatin1String( "Unhandled ScheduleMessage status" );
      break;
  }

  if ( emitResult ) {
    deleteTransaction( newIncBase->uid() );
    // Delayed signal, the caller must know this CallId first.
    emitOperationFinished( callId, resultCode, errorMessage );
  }

  return callId;
}