IncidenceEditorNG::IncidenceDialog *KODialogManager::createDialog(const Akonadi::Item &item) { const KCalCore::Incidence::Ptr incidence = CalendarSupport::incidence(item); if (!incidence) { return Q_NULLPTR; } IncidenceEditorNG::IncidenceDialog *dialog = IncidenceEditorNG::IncidenceDialogFactory::create( /*needs initial saving=*/false, incidence->type(), mMainView->incidenceChanger(), mMainView); return dialog; }
void MailClient::mailTo( const KCalCore::IncidenceBase::Ptr &incidence, const KPIMIdentities::Identity &identity, const QString &from, bool bccMe, const QString &recipients, const QString &attachment, const QString &mailTransport ) { QString subject; if ( incidence->type() != KCalCore::Incidence::TypeFreeBusy ) { KCalCore::Incidence::Ptr inc = incidence.staticCast<KCalCore::Incidence>() ; subject = inc->summary(); } else { subject = i18n( "Free Busy Message" ); } const QString body = KCalUtils::IncidenceFormatter::mailBodyStr( incidence, KSystemTimeZones::local() ); send( identity, from, recipients, QString(), subject, body, false, bccMe, attachment, mailTransport ); }
bool NemoCalendarImportModel::importToMemory(const QString &fileName) { if (!mEventList.isEmpty()) mEventList.clear(); beginResetModel(); KCalCore::MemoryCalendar::Ptr cal(new KCalCore::MemoryCalendar(KDateTime::Spec::LocalZone())); importFromFile(fileName, cal); KCalCore::Incidence::List incidenceList = cal->incidences(); for (int i = 0; i < incidenceList.size(); i++) { KCalCore::Incidence::Ptr incidence = incidenceList.at(i); if (incidence->type() == KCalCore::IncidenceBase::TypeEvent) mEventList.append(incidence.staticCast<KCalCore::Event>()); } if (!mEventList.isEmpty()) qSort(mEventList.begin(), mEventList.end(), incidenceLessThan); endResetModel(); emit countChanged(); return true; }
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(); } }
void MailClient::mailOrganizer( const KCalCore::IncidenceBase::Ptr &incidence, const KPIMIdentities::Identity &identity, const QString &from, bool bccMe, const QString &attachment, const QString &sub, const QString &mailTransport ) { const QString to = incidence->organizer()->fullName(); QString subject = sub; if ( incidence->type() != KCalCore::Incidence::TypeFreeBusy ) { KCalCore::Incidence::Ptr inc = incidence.staticCast<KCalCore::Incidence>(); if ( subject.isEmpty() ) { subject = inc->summary(); } } else { subject = i18n( "Free Busy Message" ); } const QString body = KCalUtils::IncidenceFormatter::mailBodyStr( incidence, KSystemTimeZones::local() ); send( identity, from, to, QString(), subject, body, false, bccMe, attachment, mailTransport ); }
QByteArray mailOrganizer( const KCalCore::IncidenceBase::Ptr &incidence, // const KPIMIdentities::Identity &identity, const QString &from, bool bccMe, const QString &attachment, const QString &sub/*, const QString &mailTransport*/ ) { const QString to = incidence->organizer()->fullName(); QString subject = sub; if ( incidence->type() != KCalCore::Incidence::TypeFreeBusy ) { KCalCore::Incidence::Ptr inc = incidence.staticCast<KCalCore::Incidence>(); if ( subject.isEmpty() ) { subject = inc->summary(); } } else { subject = QString( "Free Busy Message" ); } QString body = KCalUtils::IncidenceFormatter::mailBodyStr( incidence, KSystemTimeZones::local() ); return createMessage( /*identity, */from, to, QString(), subject, body, false, bccMe, attachment/*, mailTransport */)->encodedContent(); }
Akonadi::Item KolabHelpers::translateFromImap(Kolab::FolderType folderType, const Akonadi::Item &imapItem, bool &ok) { //Avoid trying to convert imap messages if (folderType == Kolab::MailType) { return imapItem; } //No payload, probably a flag change or alike, we just pass it through if (!imapItem.hasPayload()) { return imapItem; } if (!imapItem.hasPayload<KMime::Message::Ptr>()) { qCWarning(KOLABRESOURCE_LOG) << "Payload is not a MessagePtr!"; Q_ASSERT(false); ok = false; return imapItem; } const KMime::Message::Ptr payload = imapItem.payload<KMime::Message::Ptr>(); const Kolab::KolabObjectReader reader(payload); if (checkForErrors(imapItem)) { ok = true; //We return an error object so the sync keeps working, and we can clean up the mess by simply deleting the object in the application. return getErrorItem(folderType, imapItem.remoteId()); } switch (reader.getType()) { case Kolab::EventObject: case Kolab::TodoObject: case Kolab::JournalObject: { const KCalCore::Incidence::Ptr incidencePtr = reader.getIncidence(); if (!incidencePtr) { qCWarning(KOLABRESOURCE_LOG) << "Failed to read incidence."; ok = false; return Akonadi::Item(); } Akonadi::Item newItem(incidencePtr->mimeType()); newItem.setPayload(incidencePtr); newItem.setRemoteId(imapItem.remoteId()); newItem.setGid(incidencePtr->instanceIdentifier()); return newItem; } break; case Kolab::NoteObject: { const KMime::Message::Ptr note = reader.getNote(); if (!note) { qCWarning(KOLABRESOURCE_LOG) << "Failed to read note."; ok = false; return Akonadi::Item(); } Akonadi::Item newItem(QStringLiteral("text/x-vnd.akonadi.note")); newItem.setPayload(note); newItem.setRemoteId(imapItem.remoteId()); const Akonadi::NoteUtils::NoteMessageWrapper wrapper(note); newItem.setGid(wrapper.uid()); return newItem; } break; case Kolab::ContactObject: { Akonadi::Item newItem(KContacts::Addressee::mimeType()); newItem.setPayload(reader.getContact()); newItem.setRemoteId(imapItem.remoteId()); newItem.setGid(reader.getContact().uid()); return newItem; } break; case Kolab::DistlistObject: { KContacts::ContactGroup contactGroup = reader.getDistlist(); QList<KContacts::ContactGroup::ContactReference> toAdd; for (uint index = 0; index < contactGroup.contactReferenceCount(); ++index) { const KContacts::ContactGroup::ContactReference &reference = contactGroup.contactReference(index); KContacts::ContactGroup::ContactReference ref; ref.setGid(reference.uid()); //libkolab set a gid with setUid() toAdd << ref; } contactGroup.removeAllContactReferences(); foreach (const KContacts::ContactGroup::ContactReference &ref, toAdd) { contactGroup.append(ref); } Akonadi::Item newItem(KContacts::ContactGroup::mimeType()); newItem.setPayload(contactGroup); newItem.setRemoteId(imapItem.remoteId()); newItem.setGid(contactGroup.id()); return newItem; } break; default: qCWarning(KOLABRESOURCE_LOG) << "Object type not handled"; ok = false; break; }
void MailClient::mailAttendees( const KCalCore::IncidenceBase::Ptr &incidence, const KPIMIdentities::Identity &identity, bool bccMe, const QString &attachment, const QString &mailTransport ) { Q_ASSERT( incidence ); KCalCore::Attendee::List attendees = incidence->attendees(); if ( attendees.isEmpty() ) { kWarning() << "There are no attendees to e-mail"; emit finished( ResultNoAttendees, i18n( "There are no attendees to e-mail" ) ); return; } const QString from = incidence->organizer()->fullName(); const QString organizerEmail = incidence->organizer()->email(); QStringList toList; QStringList ccList; const int numberOfAttendees = attendees.count(); for ( int i=0; i<numberOfAttendees; ++i ) { KCalCore::Attendee::Ptr a = attendees.at( i ); const QString email = a->email(); if ( email.isEmpty() ) { continue; } // In case we (as one of our identities) are the organizer we are sending // this mail. We could also have added ourselves as an attendee, in which // case we don't want to send ourselves a notification mail. if ( organizerEmail == email ) { continue; } // Build a nice address for this attendee including the CN. QString tname, temail; const QString username = KPIMUtils::quoteNameIfNecessary( a->name() ); // ignore the return value from extractEmailAddressAndName() because // it will always be false since tusername does not contain "@domain". KPIMUtils::extractEmailAddressAndName( username, temail/*byref*/, tname/*byref*/ ); tname += QLatin1String( " <" ) + email + QLatin1Char( '>' ); // Optional Participants and Non-Participants are copied on the email if ( a->role() == KCalCore::Attendee::OptParticipant || a->role() == KCalCore::Attendee::NonParticipant ) { ccList << tname; } else { toList << tname; } } if( toList.isEmpty() && ccList.isEmpty() ) { // Not really to be called a groupware meeting, eh kWarning() << "There are really no attendees to e-mail"; emit finished( ResultReallyNoAttendees, i18n( "There are no attendees to e-mail" ) ); return; } QString to; if ( !toList.isEmpty() ) { to = toList.join( QLatin1String( ", " ) ); } QString cc; if ( !ccList.isEmpty() ) { cc = ccList.join( QLatin1String( ", " ) ); } QString subject; if ( incidence->type() != KCalCore::Incidence::TypeFreeBusy ) { KCalCore::Incidence::Ptr inc = incidence.staticCast<KCalCore::Incidence>(); subject = inc->summary(); } else { subject = i18n( "Free Busy Object" ); } const QString body = KCalUtils::IncidenceFormatter::mailBodyStr( incidence, KSystemTimeZones::local() ); send( identity, from, to, cc, subject, body, false, bccMe, attachment, mailTransport ); }
void IncidenceWhatWhere::save( const KCalCore::Incidence::Ptr &incidence ) { Q_ASSERT( incidence ); incidence->setSummary( mUi->mSummaryEdit->text() ); incidence->setLocation( mUi->mLocationEdit->text() ); }
void TodoPlugin::processDropEvent( QDropEvent *event ) { const QMimeData *md = event->mimeData(); if ( KABC::VCardDrag::canDecode( md ) ) { KABC::Addressee::List contacts; KABC::VCardDrag::fromMimeData( md, contacts ); KABC::Addressee::List::Iterator it; QStringList attendees; for ( it = contacts.begin(); it != contacts.end(); ++it ) { QString email = (*it).fullEmail(); if ( email.isEmpty() ) { attendees.append( (*it).realName() + "<>" ); } else { attendees.append( email ); } } interface()->openTodoEditor( i18nc( "@item", "Meeting" ), QString(), QStringList(), attendees ); return; } if ( KCalUtils::ICalDrag::canDecode( event->mimeData() ) ) { KCalCore::MemoryCalendar::Ptr cal( new KCalCore::MemoryCalendar( KSystemTimeZones::local() ) ); if ( KCalUtils::ICalDrag::fromMimeData( event->mimeData(), cal ) ) { KCalCore::Incidence::List incidences = cal->incidences(); Q_ASSERT( incidences.count() ); if ( !incidences.isEmpty() ) { event->accept(); KCalCore::Incidence::Ptr i = incidences.first(); QString summary; if ( i->type() == KCalCore::Incidence::TypeJournal ) { summary = i18nc( "@item", "Note: %1", i->summary() ); } else { summary = i->summary(); } interface()->openTodoEditor( summary, i->description(), QStringList() ); return; } // else fall through to text decoding } } if ( md->hasText() ) { QString text = md->text(); interface()->openTodoEditor( text ); return; } if ( KPIM::MailList::canDecode( md ) ) { KPIM::MailList mails = KPIM::MailList::fromMimeData( md ); event->accept(); if ( mails.count() != 1 ) { KMessageBox::sorry( core(), i18nc( "@info", "Dropping multiple mails is not supported." ) ); } else { KPIM::MailSummary mail = mails.first(); QString txt = i18nc( "@item", "From: %1\nTo: %2\nSubject: %3", mail.from(), mail.to(), mail.subject() ); QString uri = QLatin1String( "kmail:" ) + QString::number( mail.serialNumber() ) + '/' + mail.messageId(); KTemporaryFile tf; tf.setAutoRemove( true ); tf.write( event->encodedData( "message/rfc822" ) ); interface()->openTodoEditor( i18nc( "@item", "Mail: %1", mail.subject() ), txt, uri, tf.fileName(), QStringList(), "message/rfc822" ); tf.close(); } return; } kWarning() << QString( "Cannot handle drop events of type '%1'." ).arg( event->format() ); }
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; }
void IncidenceChanger::Private::onCollectionsLoaded(KJob *job) { Q_ASSERT(!mPendingCreations.isEmpty()); if (job->error() != 0 || !m_collectionFetchJob) { qCritical() << "Error loading collections:" << job->errorString(); return; } Q_ASSERT(job == m_collectionFetchJob); Akonadi::Collection::List allCollections; foreach (const Akonadi::Collection &collection, m_collectionFetchJob->collections()) { if (collection.rights() & Akonadi::Collection::CanCreateItem) { allCollections << collection; } } m_collectionFetchJob = Q_NULLPTR; bool canceled = false; // These two will never be true, maybe even assert bool noAcl = false; bool invalidCollection = false; Collection collectionToUse; foreach (const Change::Ptr &change, mPendingCreations) { mPendingCreations.removeAll(change); if (canceled) { change->resultCode = ResultCodeUserCanceled; continue; } if (noAcl) { change->resultCode = ResultCodePermissions; continue; } if (invalidCollection) { change->resultCode = ResultCodeInvalidUserCollection; continue; } if (collectionToUse.isValid()) { // We don't show the dialog multiple times step2CreateIncidence(change, collectionToUse); continue; } KCalCore::Incidence::Ptr incidence = CalendarUtils::incidence(change->newItem); Collection::List candidateCollections = collectionsForMimeType(incidence->mimeType(), allCollections); if (candidateCollections.count() == 1 && candidateCollections.first().isValid()) { // We only have 1 writable collection, don't bother the user with a dialog collectionToUse = candidateCollections.first(); qCDebug(AKONADICALENDAR_LOG) << "Only one collection exists, will not show collection dialog: " << collectionToUse.displayName(); step2CreateIncidence(change, collectionToUse); continue; } // Lets ask the user which collection to use: int dialogCode; QWidget *parent = change->parentWidget; const QStringList mimeTypes(incidence->mimeType()); collectionToUse = CalendarUtils::selectCollection(parent, /*by-ref*/dialogCode, mimeTypes, mDefaultCollection); if (dialogCode != QDialog::Accepted) { qCDebug(AKONADICALENDAR_LOG) << "User canceled collection choosing"; change->resultCode = ResultCodeUserCanceled; canceled = true; cancelTransaction(); continue; } if (collectionToUse.isValid() && !hasRights(collectionToUse, ChangeTypeCreate)) { qCWarning(AKONADICALENDAR_LOG) << "No ACLs for incidence creation"; const QString errorMessage = showErrorDialog(ResultCodePermissions, parent); change->resultCode = ResultCodePermissions; change->errorString = errorMessage; noAcl = true; cancelTransaction(); continue; } // TODO: add unit test for these two situations after reviewing API if (!collectionToUse.isValid()) { qCritical() << "Invalid collection selected. Can't create incidence."; change->resultCode = ResultCodeInvalidUserCollection; const QString errorString = showErrorDialog(ResultCodeInvalidUserCollection, parent); change->errorString = errorString; invalidCollection = true; cancelTransaction(); continue; } step2CreateIncidence(change, collectionToUse); }