void AlarmDialog::slotCalendarChanged() { Akonadi::Item::List incidences = mCalendar->incidences(); for ( Akonadi::Item::List::ConstIterator it = incidences.constBegin(); it != incidences.constEnd(); ++it ) { ReminderListItem *item = searchByItem( *it ); if ( item ) { Incidence::Ptr incidence = CalendarSupport::incidence( *it ); QString displayStr; // Yes, alarms can be empty, if someone edited the incidence and removed all alarms if ( !incidence->alarms().isEmpty() ) { const KDateTime dateTime = triggerDateForIncidence( incidence, item->mRemindAt, displayStr ); const QString summary = cleanSummary( incidence->summary() ); if ( displayStr != item->text( 1 ) || summary != item->text( 0 ) ) { item->setText( 1, displayStr ); item->setText( 0, summary ); } } } } }
void DndFactoryTest::testPasteTodo() { MemoryCalendar::Ptr calendar( new MemoryCalendar( QString() ) ); DndFactory factory( calendar ); Todo::Ptr todo( new Todo() ); todo->setSummary( QLatin1String( "Summary 1" ) ); todo->setDtDue( KDateTime( QDate( 2010, 8, 9 ) ) ); Incidence::List incidencesToPaste; incidencesToPaste.append( todo ); QVERIFY( factory.copyIncidences( incidencesToPaste ) ); const KDateTime newDateTime( QDate( 2011, 1, 1 ), QTime( 10, 10 ) ); Incidence::List pastedIncidences = factory.pasteIncidences( newDateTime ); QVERIFY( pastedIncidences.size() == 1 ); Incidence::Ptr incidence = pastedIncidences.first(); QVERIFY( incidence->type() == Incidence::TypeTodo ); // check if a new uid was generated. QVERIFY( incidence->uid() != todo->uid() ); Todo::Ptr pastedTodo = incidence.staticCast<Todo>(); QVERIFY( pastedTodo->dtDue() == newDateTime ); QVERIFY( pastedTodo->summary() == todo->summary() ); }
/** static */ KDateTime AlarmDialog::triggerDateForIncidence( const Incidence::Ptr &incidence, const QDateTime &reminderAt, QString &displayStr ) { KDateTime result; if ( incidence->alarms().isEmpty() ) { return result; } Alarm::Ptr alarm = incidence->alarms().first(); if ( incidence->recurs() ) { result = incidence->recurrence()->getNextDateTime( KDateTime( reminderAt, KDateTime::Spec::LocalZone( ) ) ); displayStr = KGlobal::locale()->formatDateTime( result.toLocalZone() ); } if ( !result.isValid() ) { result = incidence->dateTime( Incidence::RoleAlarm ); displayStr = IncidenceFormatter::dateTimeToString( result, false, true, KDateTime::Spec::LocalZone() ); } return result; }
QString Stringify::incidenceStatus( const Incidence::Ptr &incidence ) { if ( incidence->status() == Incidence::StatusX ) { return incidence->customStatus(); } else { return incidenceStatus( incidence->status() ); } }
void CompatPre32::fixRecurrence( const Incidence::Ptr &incidence ) { Recurrence *recurrence = incidence->recurrence(); if ( recurrence->recurs() && recurrence->duration() > 0 ) { recurrence->setDuration( recurrence->duration() + incidence->recurrence()->exDates().count() ); } // Call base class method now that everything else is done CompatPre35::fixRecurrence( incidence ); }
void HtmlExport::formatCategories(QTextStream *ts, const Incidence::Ptr &incidence) { if (!incidence->categoriesStr().isEmpty()) { *ts << " " << cleanChars(incidence->categoriesStr()) << endl; } else { *ts << " " << endl; } }
bool AlarmDialog::openIncidenceEditorThroughKOrganizer( const Incidence::Ptr &incidence ) { if ( !QDBusConnection::sessionBus().interface()->isServiceRegistered( "org.kde.korganizer" ) ) { if ( KToolInvocation::startServiceByDesktopName( "korganizer", QString() ) ) { KMessageBox::error( this, i18nc( "@info", "Could not start KOrganizer so editing is not possible." ) ); return false; } } org::kde::korganizer::Korganizer korganizer( "org.kde.korganizer", "/Korganizer", QDBusConnection::sessionBus() ); kDebug() << "editing incidence " << incidence->summary(); if ( !korganizer.editIncidence( incidence->uid() ) ) { KMessageBox::error( this, i18nc( "@info", "An internal KOrganizer error occurred attempting to modify \"%1\"", cleanSummary( incidence->summary() ) ) ); } // get desktop # where korganizer (or kontact) runs QString object = QDBusConnection::sessionBus().interface()->isServiceRegistered( "org.kde.kontact" ) ? "kontact/MainWindow_1" : "korganizer/MainWindow_1"; QDBusInterface korganizerObj( "org.kde.korganizer", '/' + object ); #ifdef Q_WS_X11 QDBusReply<int> reply = korganizerObj.call( "winId" ); if ( reply.isValid() ) { int window = reply; int desktop = KWindowSystem::windowInfo( window, NET::WMDesktop ).desktop(); if ( KWindowSystem::currentDesktop() == desktop ) { KWindowSystem::minimizeWindow( winId(), false ); } else { KWindowSystem::setCurrentDesktop( desktop ); } KWindowSystem::activateWindow( KWindowSystem::transientFor( window ) ); } #elif defined(Q_WS_WIN) // WId is a typedef to a void* on windows QDBusReply<qlonglong> reply = korganizerObj.call( "winId" ); if ( reply.isValid() ) { qlonglong window = reply; KWindowSystem::minimizeWindow( winId(), false ); KWindowSystem::allowExternalProcessWindowActivation(); KWindowSystem::activateWindow( reinterpret_cast<WId>(window) ); } #else // TODO (mac) #endif return true; }
void CalendarBaseTest::createInitialIncidences() { mExpectedSlotResult = true; for (int i=0; i<5; ++i) { Event::Ptr event = Event::Ptr(new Event()); event->setUid(QStringLiteral("event") + QString::number(i)); event->setSummary(QStringLiteral("summary") + QString::number(i)); event->setDtStart(KDateTime::currentDateTime(KDateTime::UTC)); mUids.append(event->uid()); QVERIFY(mCalendar->addEvent(event)); QTestEventLoop::instance().enterLoop(5); QVERIFY(!QTestEventLoop::instance().timeout()); } mOneEventUid = mUids.last(); for (int i=0; i<5; ++i) { Todo::Ptr todo = Todo::Ptr(new Todo()); todo->setUid(QStringLiteral("todo") + QString::number(i)); todo->setDtStart(KDateTime::currentDateTime(KDateTime::UTC)); todo->setSummary(QStringLiteral("summary") + QString::number(i)); mUids.append(todo->uid()); QVERIFY(mCalendar->addTodo(todo)); QTestEventLoop::instance().enterLoop(5); QVERIFY(!QTestEventLoop::instance().timeout()); } mOneTodoUid = mUids.last(); for (int i=0; i<5; ++i) { Journal::Ptr journal = Journal::Ptr(new Journal()); journal->setUid(QStringLiteral("journal") + QString::number(i)); journal->setSummary(QStringLiteral("summary") + QString::number(i)); journal->setDtStart(KDateTime::currentDateTime(KDateTime::UTC)); mUids.append(journal->uid()); QVERIFY(mCalendar->addJournal(journal)); QTestEventLoop::instance().enterLoop(5); QVERIFY(!QTestEventLoop::instance().timeout()); } mOneJournalUid = mUids.last(); for (int i=0; i<5; ++i) { Incidence::Ptr incidence = Incidence::Ptr(new Event()); incidence->setUid(QStringLiteral("incidence") + QString::number(i)); incidence->setSummary(QStringLiteral("summary") + QString::number(i)); incidence->setDtStart(KDateTime::currentDateTime(KDateTime::UTC)); mUids.append(incidence->uid()); QVERIFY(mCalendar->addIncidence(incidence)); QTestEventLoop::instance().enterLoop(5); QVERIFY(!QTestEventLoop::instance().timeout()); } mOneIncidenceUid = mUids.last(); }
void AlarmDialog::addIncidence( const Akonadi::Item &incidenceitem, const QDateTime &reminderAt, const QString &displayText ) { Incidence::Ptr incidence = CalendarSupport::incidence( incidenceitem ); ReminderListItem *item = searchByItem( incidenceitem ); if ( !item ) { item = new ReminderListItem( incidenceitem, mIncidenceTree ); } item->mNotified = false; item->mHappening = KDateTime(); item->mRemindAt = reminderAt; item->mTrigger = KDateTime::currentLocalDateTime(); item->mDisplayText = displayText; item->setText( 0, cleanSummary( incidence->summary() ) ); Event::Ptr event; Todo::Ptr todo; QString displayStr; const KDateTime dateTime = triggerDateForIncidence( incidence, reminderAt, displayStr ); if ( incidence->type() == Incidence::TypeEvent ) { item->setIcon( 0, SmallIcon( "view-calendar-day" ) ); } else if ( incidence->type() == Incidence::TypeTodo ) { item->setIcon( 0, SmallIcon( "view-calendar-tasks" ) ); } item->mHappening = dateTime; item->setText( 1, displayStr ); item->setText( 2, IncidenceFormatter::dateTimeToString( item->mTrigger, false, true, KDateTime::Spec::LocalZone() ) ); QString tip = IncidenceFormatter::toolTipStr( CalendarSupport::displayName( mCalendar, incidenceitem.parentCollection() ), incidence, item->mRemindAt.date(), true, KDateTime::Spec::LocalZone() ); if ( !item->mDisplayText.isEmpty() ) { tip += "<br>" + item->mDisplayText; } item->setToolTip( 0, tip ); item->setToolTip( 1, tip ); item->setToolTip( 2, tip ); item->setData( 0, QTreeWidgetItem::UserType, false ); mIncidenceTree->setCurrentItem( item ); showDetails(); slotSave(); }
bool AlarmDialog::openIncidenceEditorNG( const Akonadi::Item &item ) { if ( !IncidenceEditorNG::GroupwareIntegration::isActive() ) { //TODO: Why do we need this to have a simple editor? IncidenceEditorNG::GroupwareIntegration::activate( mCalendar ); } Incidence::Ptr incidence = CalendarSupport::incidence( item ); IncidenceEditorNG::IncidenceDialog *dialog = IncidenceEditorNG::IncidenceDialogFactory::create( false, /*doesn't need initial saving*/ incidence->type(), this ); dialog->load( item ); return true; }
void DndFactoryTest::testPasteAllDayEvent2() { MemoryCalendar::Ptr calendar( new MemoryCalendar( QString() ) ); DndFactory factory( calendar ); Event::Ptr allDayEvent( new Event() ); allDayEvent->setSummary( QLatin1String( "Summary 2" ) ); allDayEvent->setDtStart( KDateTime( QDate( 2010, 8, 8 ) ) ); allDayEvent->setDtEnd( KDateTime( QDate( 2010, 8, 9 ) ) ); const QString originalUid = allDayEvent->uid(); Incidence::List incidencesToPaste; incidencesToPaste.append( allDayEvent ); QVERIFY( factory.copyIncidences( incidencesToPaste ) ); const KDateTime newDateTime( QDate( 2011, 1, 1 ) ); const uint originalLength = allDayEvent->dtStart().secsTo( allDayEvent->dtEnd() ); // paste at the new time Incidence::List pastedIncidences = factory.pasteIncidences( newDateTime ); // we only copied one incidence QVERIFY( pastedIncidences.size() == 1 ); Incidence::Ptr incidence = pastedIncidences.first(); QVERIFY( incidence->type() == Incidence::TypeEvent ); // check if a new uid was generated. QVERIFY( incidence->uid() != originalUid ); // the new dateTime didn't have time component QVERIFY( incidence->allDay() ); Event::Ptr pastedEvent = incidence.staticCast<Event>(); const uint newLength = pastedEvent->dtStart().secsTo( pastedEvent->dtEnd() ); kDebug() << "originalLength was " << originalLength << "; and newLength is " << newLength << "; old dtStart was " << allDayEvent->dtStart() << " and old dtEnd was " << allDayEvent->dtEnd() << endl << "; new dtStart is " << pastedEvent->dtStart() << " and new dtEnd is " << pastedEvent->dtEnd(); QVERIFY( originalLength == newLength ); QVERIFY( pastedEvent->dtStart() == newDateTime ); QVERIFY( pastedEvent->summary() == allDayEvent->summary() ); }
void CompatPre35::fixRecurrence( const Incidence::Ptr &incidence ) { Recurrence *recurrence = incidence->recurrence(); if ( recurrence ) { KDateTime start( incidence->dtStart() ); // kde < 3.5 only had one rrule, so no need to loop over all RRULEs. RecurrenceRule *r = recurrence->defaultRRule(); if ( r && !r->dateMatchesRules( start ) ) { recurrence->addExDateTime( start ); } } // Call base class method now that everything else is done Compat::fixRecurrence( incidence ); }
void Compat::fixEmptySummary( const Incidence::Ptr &incidence ) { // some stupid vCal exporters ignore the standard and use Description // instead of Summary for the default field. Correct for this: Copy the // first line of the description to the summary (if summary is just one // line, move it) if ( incidence->summary().isEmpty() && !( incidence->description().isEmpty() ) ) { QString oldDescription = incidence->description().trimmed(); QString newSummary( oldDescription ); newSummary.remove( QRegExp( "\n.*" ) ); incidence->setSummary( newSummary ); if ( oldDescription == newSummary ) { incidence->setDescription( "" ); } } }
int RecurrenceActions::availableOccurrences( const Incidence::Ptr &incidence, const KDateTime &selectedOccurrence ) { int result = NoOccurrence; if ( incidence->recurrence()->recursOn( selectedOccurrence.date(), selectedOccurrence.timeSpec() ) ) { result |= SelectedOccurrence; } if ( incidence->recurrence()->getPreviousDateTime( selectedOccurrence ).isValid() ) { result |= PastOccurrences; } if ( incidence->recurrence()->getNextDateTime( selectedOccurrence ).isValid() ) { result |= FutureOccurrences; } return result; }
void AlarmDialog::edit() { ReminderList selection = selectedItems(); if ( selection.count() != 1 ) { return; } Incidence::Ptr incidence = CalendarSupport::incidence( selection.first()->mIncidence ); if ( !mCalendar->hasChangeRights( selection.first()->mIncidence ) ) { KMessageBox::sorry( this, i18nc( "@info", "\"%1\" is a read-only item so modifications are not possible.", cleanSummary( incidence->summary() ) ) ); return; } #if !defined(KDEPIM_MOBILE_UI) openIncidenceEditorNG( selection.first()->mIncidence ); #else openIncidenceEditorThroughKOrganizer( incidence ); #endif }
void DndFactoryTest::testPasteAllDayEvent() { MemoryCalendar::Ptr calendar( new MemoryCalendar( QString() ) ); DndFactory factory( calendar ); Event::Ptr allDayEvent( new Event() ); allDayEvent->setSummary( QLatin1String( "Summary 1" ) ); allDayEvent->setDtStart( KDateTime( QDate( 2010, 8, 8 ) ) ); allDayEvent->setDtEnd( KDateTime( QDate( 2010, 8, 9 ) ) ); const QString originalUid = allDayEvent->uid(); const bool originalIsAllDay = allDayEvent->allDay(); Incidence::List incidencesToPaste; incidencesToPaste.append( allDayEvent ); QVERIFY( factory.copyIncidences( incidencesToPaste ) ); Incidence::List pastedIncidences = factory.pasteIncidences(); QVERIFY( pastedIncidences.size() == 1 ); Incidence::Ptr incidence = pastedIncidences.first(); QVERIFY( incidence->type() == Incidence::TypeEvent ); // check if a new uid was generated. QVERIFY( incidence->uid() != originalUid ); // we passed an invalid KDateTime to pasteIncidences() so dates don't change. QVERIFY( incidence->allDay() == originalIsAllDay ); Event::Ptr pastedEvent = incidence.staticCast<Event>(); QVERIFY( pastedEvent->dtStart() == allDayEvent->dtStart() ); QVERIFY( pastedEvent->dtEnd() == allDayEvent->dtEnd() ); QVERIFY( pastedEvent->summary() == allDayEvent->summary() ); }
void HtmlExport::formatAttendees(QTextStream *ts, const Incidence::Ptr &incidence) { Attendee::List attendees = incidence->attendees(); if (attendees.count()) { *ts << "<em>"; *ts << incidence->organizer()->fullName(); *ts << "</em><br />"; Attendee::List::ConstIterator it; for (it = attendees.constBegin(); it != attendees.constEnd(); ++it) { Attendee::Ptr a(*it); if (!a->email().isEmpty()) { *ts << "<a href=\"mailto:" << a->email(); *ts << "\">" << cleanChars(a->name()) << "</a>"; } else { *ts << " " << cleanChars(a->name()); } *ts << "<br />" << endl; } } else { *ts << " " << endl; } }
bool HtmlExport::checkSecrecy(const Incidence::Ptr &incidence) { int secrecy = incidence->secrecy(); if (secrecy == Incidence::SecrecyPublic) { return true; } if (secrecy == Incidence::SecrecyPrivate && !d->mSettings->excludePrivate()) { return true; } if (secrecy == Incidence::SecrecyConfidential && !d->mSettings->excludeConfidential()) { return true; } return false; }
void CompatOutlook9::fixAlarms( const Incidence::Ptr &incidence ) { if ( !incidence ) { return; } Alarm::List alarms = incidence->alarms(); Alarm::List::Iterator it; for ( it = alarms.begin(); it != alarms.end(); ++it ) { Alarm::Ptr al = *it; if ( al && al->hasStartOffset() ) { Duration offsetDuration = al->startOffset(); int offs = offsetDuration.asSeconds(); if ( offs > 0 ) { offsetDuration = Duration( -offs ); } al->setStartOffset( offsetDuration ); } } }
Incidence::List DndFactory::pasteIncidences( const KDateTime &newDateTime, const QFlags<PasteFlag> &pasteOptions ) { QClipboard *clipboard = QApplication::clipboard(); Q_ASSERT( clipboard ); MemoryCalendar::Ptr calendar( createDropCalendar( clipboard->mimeData() ) ); Incidence::List list; if ( !calendar ) { kDebug() << "Can't parse clipboard"; return list; } // All pasted incidences get new uids, must keep track of old uids, // so we can update child's parents QHash<QString, Incidence::Ptr> oldUidToNewInc; Incidence::List::ConstIterator it; const Incidence::List incidences = calendar->incidences(); for ( it = incidences.constBegin(); it != incidences.constEnd(); ++it ) { Incidence::Ptr incidence = d->pasteIncidence( *it, newDateTime, pasteOptions ); if ( incidence ) { list.append( incidence ); oldUidToNewInc[(*it)->uid()] = *it; } } // update relations for ( it = list.constBegin(); it != list.constEnd(); ++it ) { Incidence::Ptr incidence = *it; if ( oldUidToNewInc.contains( incidence->relatedTo() ) ) { Incidence::Ptr parentInc = oldUidToNewInc[incidence->relatedTo()]; incidence->setRelatedTo( parentInc->uid() ); } else { // not related to anything in the clipboard incidence->setRelatedTo( QString() ); } } return list; }
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; }
int main( int argc, char **argv ) { KAboutData aboutData( "testrecurson", 0, ki18n( "Tests all dates from 2002 to 2010 to test if the event recurs on each individual date. " "This is meant to test the Recurrence::recursOn method for errors." ), "0.1" ); KCmdLineArgs::init( argc, argv, &aboutData ); KCmdLineOptions options; options.add( "verbose", ki18n( "Verbose output" ) ); options.add( "+input", ki18n( "Name of input file" ) ); options.add( "[+output]", ki18n( "optional name of output file for the recurrence dates" ) ); KCmdLineArgs::addCmdLineOptions( options ); KComponentData componentData( &aboutData ); //QCoreApplication app( KCmdLineArgs::qtArgc(), KCmdLineArgs::qtArgv() ); KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); if ( args->count() < 1 ) { args->usage( "Wrong number of arguments." ); } QString input = args->arg( 0 ); // kDebug() << "Input file:" << input; QTextStream *outstream; outstream = 0; QString fn( "" ); if ( args->count() > 1 ) { fn = args->arg( 1 ); // kDebug() << "We have a file name given:" << fn; } QFile outfile( fn ); if ( !fn.isEmpty() && outfile.open( QIODevice::WriteOnly ) ) { // kDebug() << "Opened output file!!!"; outstream = new QTextStream( &outfile ); } MemoryCalendar::Ptr cal( new MemoryCalendar( KDateTime::UTC ) ); FileStorage store( cal, input ); if ( !store.load() ) return 1; QString tz = cal->nonKDECustomProperty( "X-LibKCal-Testsuite-OutTZ" ); if ( !tz.isEmpty() ) { cal->setViewTimeZoneId( tz ); } Incidence::List inc = cal->incidences(); for ( Incidence::List::Iterator it = inc.begin(); it != inc.end(); ++it ) { Incidence::Ptr incidence = *it; // kDebug() << " ->" << incidence->summary() << "<-"; // incidence->recurrence()->dump(); QDate dt( 1996, 7, 1 ); if ( outstream ) { // Output to file for testing purposes int nr = 0; while ( dt.year() <= 2020 && nr<=500 ) { if ( incidence->recursOn( dt, cal->viewTimeSpec() ) ) { (*outstream) << dt.toString( Qt::ISODate ) << endl; nr++; } dt = dt.addDays( 1 ); } } else { dt = QDate( 2005, 1, 1 ); while ( dt.year() < 2007 ) { if ( incidence->recursOn( dt, cal->viewTimeSpec() ) ) { kDebug() << dt.toString( Qt::ISODate ); } dt = dt.addDays( 1 ); } } } delete outstream; outfile.close(); return 0; }
void CompatPre410::setCreatedToDtStamp( const Incidence::Ptr &incidence, const KDateTime &dtstamp ) { if ( dtstamp.isValid() ) { incidence->setCreated( dtstamp ); } }
void CompatPre31::fixRecurrence( const Incidence::Ptr &incidence ) { CompatPre32::fixRecurrence( incidence ); Recurrence *recur = incidence->recurrence(); RecurrenceRule *r = 0; if ( recur ) { r = recur->defaultRRule(); } if ( recur && r ) { int duration = r->duration(); if ( duration > 0 ) { // Backwards compatibility for KDE < 3.1. // rDuration was set to the number of time periods to recur, // with week start always on a Monday. // Convert this to the number of occurrences. r->setDuration( -1 ); QDate end( r->startDt().date() ); bool doNothing = false; // # of periods: int tmp = ( duration - 1 ) * r->frequency(); switch ( r->recurrenceType() ) { case RecurrenceRule::rWeekly: { end = end.addDays( tmp * 7 + 7 - end.dayOfWeek() ); break; } case RecurrenceRule::rMonthly: { int month = end.month() - 1 + tmp; end.setDate( end.year() + month / 12, month % 12 + 1, 31 ); break; } case RecurrenceRule::rYearly: { end.setDate( end.year() + tmp, 12, 31 ); break; } default: doNothing = true; break; } if ( !doNothing ) { duration = r->durationTo( KDateTime( end, QTime( 0, 0, 0 ), incidence->dtStart().timeSpec() ) ); r->setDuration( duration ); } } /* addYearlyNum */ // Dates were stored as day numbers, with a fiddle to take account of // leap years. Convert the day number to a month. QList<int> days = r->byYearDays(); if ( !days.isEmpty() ) { QList<int> months = r->byMonths(); for ( int i = 0; i < months.size(); ++i ) { int newmonth = QDate( r->startDt().date().year(), 1, 1 ).addDays( months.at( i ) - 1 ).month(); if ( !months.contains( newmonth ) ) { months.append( newmonth ); } } r->setByMonths( months ); days.clear(); r->setByYearDays( days ); } } }
void AlarmDialog::eventNotification() { bool beeped = false; bool found = false; ReminderList list; QTreeWidgetItemIterator it( mIncidenceTree ); while ( *it ) { ReminderListItem *item = static_cast<ReminderListItem *>( *it ); ++it; if ( item->isDisabled() || item->mNotified ) { //skip suspended reminders or reminders that have been notified continue; } found = true; item->mNotified = true; Incidence::Ptr incidence = CalendarSupport::incidence( item->mIncidence ); Alarm::List alarms = incidence->alarms(); Alarm::List::ConstIterator ait; for ( ait = alarms.constBegin(); ait != alarms.constEnd(); ++ait ) { Alarm::Ptr alarm = *ait; // FIXME: Check whether this should be done for all multiple alarms if ( alarm->type() == Alarm::Procedure ) { // FIXME: Add a message box asking whether the procedure should really be executed kDebug() << "Starting program: '" << alarm->programFile() << "'"; QString program = alarm->programFile(); // if the program name contains spaces escape it if ( program.contains( ' ' ) && !( program.startsWith( '\"' ) && program.endsWith( '\"' ) ) ) { program = '\"' + program + '\"'; } QProcess::startDetached( program + ' ' + alarm->programArguments() ); } else if ( alarm->type() == Alarm::Audio ) { beeped = true; Phonon::MediaObject *player = Phonon::createPlayer( Phonon::NotificationCategory, alarm->audioFile() ); player->setParent( this ); connect( player, SIGNAL(finished()), player, SLOT(deleteLater()) ); player->play(); } else if ( alarm->type() == Alarm::Email ) { QString from = CalendarSupport::KCalPrefs::instance()->email(); Identity id = KOCore::self()->identityManager()->identityForAddress( from ); QString to; if ( alarm->mailAddresses().isEmpty() ) { to = from; } else { const Person::List addresses = alarm->mailAddresses(); QStringList add; for ( Person::List::ConstIterator it = addresses.constBegin(); it != addresses.constEnd(); ++it ) { add << (*it)->fullName(); } to = add.join( ", " ); } QString subject; Akonadi::Item parentItem = mCalendar->itemForIncidenceUid( alarm->parentUid() ); Incidence::Ptr parent = CalendarSupport::incidence( parentItem ); if ( alarm->mailSubject().isEmpty() ) { if ( parent->summary().isEmpty() ) { subject = i18nc( "@title", "Reminder" ); } else { subject = i18nc( "@title", "Reminder: %1", cleanSummary( parent->summary() ) ); } } else { subject = i18nc( "@title", "Reminder: %1", alarm->mailSubject() ); } QString body = IncidenceFormatter::mailBodyStr( parent.staticCast<IncidenceBase>(), KSystemTimeZones::local() ); if ( !alarm->mailText().isEmpty() ) { body += '\n' + alarm->mailText(); } //TODO: support attachments CalendarSupport::MailClient mailer; mailer.send( id, from, to, QString(), subject, body, true, false, QString(), MailTransport::TransportManager::self()->defaultTransportName() ); } } } if ( !beeped && found ) { KNotification::beep(); } }
int main( int argc, char **argv ) { KAboutData aboutData( "testrecurrencenew", 0, ki18n( "Load recurrence rules with the new class and print out debug messages" ), "0.1" ); KCmdLineArgs::init( argc, argv, &aboutData ); KCmdLineOptions options; options.add( "verbose", ki18n( "Verbose output" ) ); options.add( "+input", ki18n( "Name of input file" ) ); options.add( "[+output]", ki18n( "optional name of output file for the recurrence dates" ) ); KCmdLineArgs::addCmdLineOptions( options ); KComponentData componentData( &aboutData ); //QCoreApplication app( KCmdLineArgs::qtArgc(), KCmdLineArgs::qtArgv() ); KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); if ( args->count() < 1 ) { args->usage( "Wrong number of arguments." ); } QString input = args->arg( 0 ); kDebug() << "Input file:" << input; QTextStream *outstream; outstream = 0; QString fn( "" ); if ( args->count() > 1 ) { fn = args->arg( 1 ); kDebug() << "We have a file name given:" << fn; } QFile outfile( fn ); if ( !fn.isEmpty() && outfile.open( QIODevice::WriteOnly ) ) { kDebug() << "Opened output file!!!"; outstream = new QTextStream( &outfile ); } MemoryCalendar::Ptr cal( new MemoryCalendar( KDateTime::UTC ) ); KDateTime::Spec viewSpec; FileStorage store( cal, input ); if ( !store.load() ) return 1; QString tz = cal->nonKDECustomProperty( "X-LibKCal-Testsuite-OutTZ" ); if ( !tz.isEmpty() ) { viewSpec = KDateTime::Spec( KSystemTimeZones::zone( tz ) ); } Incidence::List inc = cal->incidences(); for ( Incidence::List::Iterator it = inc.begin(); it != inc.end(); ++it ) { Incidence::Ptr incidence = *it; kDebug() << "*+*+*+*+*+*+*+*+*+*"; kDebug() << " ->" << incidence->summary() << "<-"; incidence->recurrence()->dump(); KDateTime dt( incidence->recurrence()->endDateTime() ); int i = 0; if ( outstream ) { if ( !dt.isValid() ) { if ( viewSpec.isValid() ) { dt = KDateTime( QDate( 2011, 1, 1 ), QTime( 0, 0, 1 ), viewSpec ); } else { dt = KDateTime( QDate( 2011, 1, 1 ), QTime( 0, 0, 1 ) ); } } else { dt = dt.addYears( 2 ); } kDebug() << "-------------------------------------------"; kDebug() << " *~*~*~*~ Starting with date:" << dumpTime( dt, viewSpec ); // Output to file for testing purposes while ( dt.isValid() && i < 500 ) { ++i; dt = incidence->recurrence()->getPreviousDateTime( dt ); if ( dt.isValid() ) { (*outstream) << dumpTime( dt, viewSpec ) << endl; } } } else { if ( !dt.isValid() ) { dt = KDateTime( QDate( 2005, 7, 31 ), QTime( 23, 59, 59 ), KDateTime::Spec::UTC() ); } else { dt = dt.addYears( 2 ); } incidence->recurrence()->dump(); kDebug() << "-------------------------------------------"; kDebug() << " *~*~*~*~ Starting with date:" << dumpTime( dt, viewSpec ); // Output to konsole while ( dt.isValid() && i < 50 ) { ++i; kDebug() << "-------------------------------------------"; dt = incidence->recurrence()->getPreviousDateTime( dt ); if ( dt.isValid() ) { kDebug() << " *~*~*~*~ Previous date is:" << dumpTime( dt, viewSpec ); } } } } delete outstream; outfile.close(); return 0; }
bool CalFilter::filterIncidence( Incidence::Ptr incidence ) const { if ( !d->mEnabled ) { return true; } Todo::Ptr todo = incidence.dynamicCast<Todo>(); if ( todo ) { if ( ( d->mCriteria & HideCompletedTodos ) && todo->isCompleted() ) { // Check if completion date is suffently long ago: if ( todo->completed().addDays( d->mCompletedTimeSpan ) < KDateTime::currentUtcDateTime() ) { return false; } } if ( ( d->mCriteria & HideInactiveTodos ) && ( ( todo->hasStartDate() && KDateTime::currentUtcDateTime() < todo->dtStart() ) || todo->isCompleted() ) ) { return false; } if ( d->mCriteria & HideNoMatchingAttendeeTodos ) { bool iAmOneOfTheAttendees = false; const Attendee::List &attendees = todo->attendees(); if ( !todo->attendees().isEmpty() ) { Attendee::List::ConstIterator it; for ( it = attendees.begin(); it != attendees.end(); ++it ) { if ( d->mEmailList.contains( ( *it )->email() ) ) { iAmOneOfTheAttendees = true; break; } } } else { // no attendees, must be me only iAmOneOfTheAttendees = true; } if ( !iAmOneOfTheAttendees ) { return false; } } } if ( d->mCriteria & HideRecurring ) { if ( incidence->recurs() ) { return false; } } if ( d->mCriteria & ShowCategories ) { for ( QStringList::ConstIterator it = d->mCategoryList.constBegin(); it != d->mCategoryList.constEnd(); ++it ) { QStringList incidenceCategories = incidence->categories(); for ( QStringList::ConstIterator it2 = incidenceCategories.constBegin(); it2 != incidenceCategories.constEnd(); ++it2 ) { if ( ( *it ) == ( *it2 ) ) { return true; } } } return false; } else { for ( QStringList::ConstIterator it = d->mCategoryList.constBegin(); it != d->mCategoryList.constEnd(); ++it ) { QStringList incidenceCategories = incidence->categories(); for ( QStringList::ConstIterator it2 = incidenceCategories.constBegin(); it2 != incidenceCategories.constEnd(); ++it2 ) { if ( ( *it ) == ( *it2 ) ) { return false; } } } return true; } return true; }
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::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::acceptReply( const IncidenceBase::Ptr &incidence, ScheduleMessage::Status status, iTIPMethod method ) { Q_UNUSED( status ); if ( incidence->type() == IncidenceBase::TypeFreeBusy ) { return acceptFreeBusy( incidence, method ); } const CallId callId = ++d->mLatestCallId; ResultCode resultCode = ResultCodeIncidenceOrAttendeeNotFound; QString errorMessage; Event::Ptr ev = d->mCalendar->event( incidence->uid() ); Todo::Ptr to = d->mCalendar->todo( incidence->uid() ); // try harder to find the correct incidence if ( !ev && !to ) { const Incidence::List list = d->mCalendar->incidences(); for ( Incidence::List::ConstIterator it=list.constBegin(), end=list.constEnd(); it != end; ++it ) { if ( (*it)->schedulingID() == incidence->uid() ) { ev = ( *it ).dynamicCast<Event>(); to = ( *it ).dynamicCast<Todo>(); break; } } } if ( ev || to ) { //get matching attendee in calendar kDebug() << "match found!"; Attendee::List attendeesIn = incidence->attendees(); Attendee::List attendeesEv; Attendee::List attendeesNew; if ( ev ) { attendeesEv = ev->attendees(); } if ( to ) { attendeesEv = to->attendees(); } Attendee::List::ConstIterator inIt; Attendee::List::ConstIterator evIt; for ( inIt = attendeesIn.constBegin(); inIt != attendeesIn.constEnd(); ++inIt ) { Attendee::Ptr attIn = *inIt; bool found = false; for ( evIt = attendeesEv.constBegin(); evIt != attendeesEv.constEnd(); ++evIt ) { Attendee::Ptr attEv = *evIt; if ( attIn->email().toLower() == attEv->email().toLower() ) { //update attendee-info kDebug() << "update attendee"; attEv->setStatus( attIn->status() ); attEv->setDelegate( attIn->delegate() ); attEv->setDelegator( attIn->delegator() ); resultCode = ResultCodeSuccess; found = true; } } if ( !found && attIn->status() != Attendee::Declined ) { attendeesNew.append( attIn ); } } bool attendeeAdded = false; for ( Attendee::List::ConstIterator it = attendeesNew.constBegin(); it != attendeesNew.constEnd(); ++it ) { Attendee::Ptr attNew = *it; QString msg = i18nc( "@info", "%1 wants to attend %2 but was not invited.", attNew->fullName(), ( ev ? ev->summary() : to->summary() ) ); if ( !attNew->delegator().isEmpty() ) { msg = i18nc( "@info", "%1 wants to attend %2 on behalf of %3.", attNew->fullName(), ( ev ? ev->summary() : to->summary() ), attNew->delegator() ); } if ( KMessageBox::questionYesNo( 0, msg, i18nc( "@title", "Uninvited attendee" ), KGuiItem( i18nc( "@option", "Accept Attendance" ) ), KGuiItem( i18nc( "@option", "Reject Attendance" ) ) ) != KMessageBox::Yes ) { Incidence::Ptr cancel = incidence.dynamicCast<Incidence>(); if ( cancel ) { cancel->addComment( i18nc( "@info", "The organizer rejected your attendance at this meeting." ) ); } performTransaction( incidence, iTIPCancel, attNew->fullName() ); // ### can't delete cancel here because it is aliased to incidence which // is accessed in the next loop iteration (CID 4232) // delete cancel; continue; } Attendee::Ptr a( new Attendee( attNew->name(), attNew->email(), attNew->RSVP(), attNew->status(), attNew->role(), attNew->uid() ) ); a->setDelegate( attNew->delegate() ); a->setDelegator( attNew->delegator() ); if ( ev ) { ev->addAttendee( a ); } else if ( to ) { to->addAttendee( a ); } resultCode = ResultCodeSuccess; attendeeAdded = true; } // send update about new participants if ( attendeeAdded ) { bool sendMail = false; if ( ev || to ) { if ( KMessageBox::questionYesNo( 0, i18nc( "@info", "An attendee was added to the incidence. " "Do you want to email the attendees an update message?" ), i18nc( "@title", "Attendee Added" ), KGuiItem( i18nc( "@option", "Send Messages" ) ), KGuiItem( i18nc( "@option", "Do Not Send" ) ) ) == KMessageBox::Yes ) { sendMail = true; } } if ( ev ) { ev->setRevision( ev->revision() + 1 ); if ( sendMail ) { performTransaction( ev, iTIPRequest ); } } if ( to ) { to->setRevision( to->revision() + 1 ); if ( sendMail ) { performTransaction( to, iTIPRequest ); } } } if ( resultCode == ResultCodeSuccess ) { // We set at least one of the attendees, so the incidence changed // Note: This should not result in a sequence number bump if ( ev ) { ev->updated(); } else if ( to ) { to->updated(); } } if ( to ) { // for VTODO a REPLY can be used to update the completion status of // a to-do. see RFC2446 3.4.3 Todo::Ptr update = incidence.dynamicCast<Todo>(); Q_ASSERT( update ); if ( update && ( to->percentComplete() != update->percentComplete() ) ) { to->setPercentComplete( update->percentComplete() ); to->updated(); } } } else { kError() << "No incidence for scheduling."; } if ( resultCode == ResultCodeSuccess ) { deleteTransaction( incidence->uid() ); } emitOperationFinished( callId, resultCode, errorMessage ); return callId; }