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() ); }
void MemoryCalendarTest::testIncidences() { MemoryCalendar::Ptr cal( new MemoryCalendar( KDateTime::UTC ) ); cal->setProductId( QLatin1String( "fredware calendar" ) ); QDate dt = QDate::currentDate(); Event::Ptr event1 = Event::Ptr( new Event() ); event1->setUid( "1" ); event1->setDtStart( KDateTime( dt ) ); event1->setDtEnd( KDateTime( dt ).addDays( 1 ) ); event1->setSummary( "Event1 Summary" ); event1->setDescription( "This is a description of the first event" ); event1->setLocation( "the place" ); Event::Ptr event2 = Event::Ptr( new Event() ); event2->setUid( "2" ); event2->setDtStart( KDateTime( dt ).addDays( 1 ) ); event2->setDtEnd( KDateTime( dt ).addDays( 2 ) ); event2->setSummary( "Event2 Summary" ); event2->setDescription( "This is a description of the second event" ); event2->setLocation( "the other place" ); QVERIFY( cal->addEvent( event1 ) ); QVERIFY( cal->addEvent( event2 ) ); Todo::Ptr todo1 = Todo::Ptr( new Todo() ); todo1->setUid( "3" ); todo1->setDtStart( KDateTime( dt ).addDays( 1 ) ); todo1->setDtDue( KDateTime( dt ).addDays( 2 ) ); todo1->setSummary( "Todo1 Summary" ); todo1->setDescription( "This is a description of a todo" ); todo1->setLocation( "this place" ); Todo::Ptr todo2 = Todo::Ptr( new Todo() ); todo2->setUid( "4" ); todo2->setDtStart( KDateTime( dt ).addDays( 1 ) ); todo2->setAllDay( true ); todo2->setSummary( "<qt><h1>Todo2 Summary</h1></qt>", true ); todo2->setDescription( "This is a description of a todo" ); todo2->setLocation( "<html><a href=\"http://www.fred.com\">this place</a></html>", true ); QVERIFY( cal->addTodo( todo1 ) ); QVERIFY( cal->addTodo( todo2 ) ); FileStorage store( cal, "foo.ics" ); QVERIFY( store.save() ); cal->close(); QVERIFY( store.load() ); Todo::Ptr todo = cal->incidence( "4" ).staticCast<Todo>(); QVERIFY( todo->uid() == "4" ); QVERIFY( todo->summaryIsRich() ); QVERIFY( todo->locationIsRich() ); cal->close(); unlink( "foo.ics" ); }
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(); }
Item::Id CalendarBaseTest::createTodo(const QString &uid, const QString &parentUid) { Todo::Ptr todo = Todo::Ptr(new Todo()); todo->setUid(uid); todo->setSummary(QStringLiteral("summary")); if (!parentUid.isEmpty()) { todo->setRelatedTo(parentUid); } mCalendar->addTodo(todo); QTestEventLoop::instance().enterLoop(5); //QVERIFY( !QTestEventLoop::instance().timeout() ); return mCalendar->item(uid).id(); }
QString Stringify::todoCompletedDateTime( const Todo::Ptr &todo, bool shortfmt ) { return KGlobal::locale()->formatDateTime( todo->completed().dateTime(), ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) ); }
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; }
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; }
Incidence::Ptr pasteIncidence( const Incidence::Ptr &incidence, KDateTime newDateTime, const QFlags<PasteFlag> &pasteOptions ) { Incidence::Ptr inc( incidence ); if ( inc ) { inc = Incidence::Ptr( inc->clone() ); inc->recreate(); } if ( inc && newDateTime.isValid() ) { if ( inc->type() == Incidence::TypeEvent ) { Event::Ptr event = inc.staticCast<Event>(); if ( pasteOptions & FlagPasteAtOriginalTime ) { // Set date and preserve time and timezone stuff const QDate date = newDateTime.date(); newDateTime = event->dtStart(); newDateTime.setDate( date ); } // in seconds const int durationInSeconds = event->dtStart().secsTo( event->dtEnd() ); const int durationInDays = event->dtStart().daysTo( event->dtEnd() ); event->setDtStart( newDateTime ); if ( newDateTime.isDateOnly() ) { event->setDtEnd( newDateTime.addDays( durationInDays ) ); } else { event->setDtEnd( newDateTime.addSecs( durationInSeconds ) ); } } else if ( inc->type() == Incidence::TypeTodo ) { Todo::Ptr aTodo = inc.staticCast<Todo>(); const bool pasteAtDtStart = ( pasteOptions & FlagTodosPasteAtDtStart ); if ( pasteOptions & FlagPasteAtOriginalTime ) { // Set date and preserve time and timezone stuff const QDate date = newDateTime.date(); newDateTime = pasteAtDtStart ? aTodo->dtStart() : aTodo->dtDue(); newDateTime.setDate( date ); } if ( pasteAtDtStart ) { aTodo->setDtStart( newDateTime ); } else { aTodo->setDtDue( newDateTime ); } } else if ( inc->type() == Incidence::TypeJournal ) { if ( pasteOptions & FlagPasteAtOriginalTime ) { // Set date and preserve time and timezone stuff const QDate date = newDateTime.date(); newDateTime = inc->dtStart(); newDateTime.setDate( date ); } inc->setDtStart( newDateTime ); } else { kDebug() << "Trying to paste unknown incidence of type" << int( inc->type() ); } } return inc; }
void HtmlExport::createTodo(QTextStream *ts, const Todo::Ptr &todo) { qCDebug(KCALUTILS_LOG); const bool completed = todo->isCompleted(); Incidence::List relations = d->mCalendar->relations(todo->uid()); *ts << "<tr>" << endl; *ts << " <td class=\"sum"; if (completed) { *ts << "done"; } *ts << "\">" << endl; *ts << " <a name=\"" << todo->uid() << "\"></a>" << endl; *ts << " <b>" << cleanChars(todo->summary()) << "</b>" << endl; if (!todo->description().isEmpty()) { *ts << " <p>" << breakString(cleanChars(todo->description())) << "</p>" << endl; } if (relations.count()) { *ts << " <div align=\"right\"><a href=\"#sub" << todo->uid() << "\">" << i18nc("@title:column sub-to-dos of the parent to-do", "Sub-To-dos") << "</a></div>" << endl; } *ts << " </td>" << endl; *ts << " <td"; if (completed) { *ts << " class=\"done\""; } *ts << ">" << endl; *ts << " " << todo->priority() << endl; *ts << " </td>" << endl; *ts << " <td"; if (completed) { *ts << " class=\"done\""; } *ts << ">" << endl; *ts << " " << i18nc("@info to-do percent complete", "%1 %", todo->percentComplete()) << endl; *ts << " </td>" << endl; if (d->mSettings->taskDueDate()) { *ts << " <td"; if (completed) { *ts << " class=\"done\""; } *ts << ">" << endl; if (todo->hasDueDate()) { *ts << " " << Stringify::formatDate(todo->dtDue(true)) << endl; } else { *ts << " " << endl; } *ts << " </td>" << endl; } if (d->mSettings->taskLocation()) { *ts << " <td"; if (completed) { *ts << " class=\"done\""; } *ts << ">" << endl; formatLocation(ts, todo); *ts << " </td>" << endl; } if (d->mSettings->taskCategories()) { *ts << " <td"; if (completed) { *ts << " class=\"done\""; } *ts << ">" << endl; formatCategories(ts, todo); *ts << " </td>" << endl; } if (d->mSettings->taskAttendees()) { *ts << " <td"; if (completed) { *ts << " class=\"done\""; } *ts << ">" << endl; formatAttendees(ts, todo); *ts << " </td>" << endl; } *ts << "</tr>" << endl; }
void HtmlExport::createTodoList(QTextStream *ts) { Todo::List rawTodoList = d->mCalendar->todos(); int index = 0; while (index < rawTodoList.count()) { Todo::Ptr ev = rawTodoList[ index ]; Todo::Ptr subev = ev; const QString uid = ev->relatedTo(); if (!uid.isEmpty()) { Incidence::Ptr inc = d->mCalendar->incidence(uid); if (inc && inc->type() == Incidence::TypeTodo) { Todo::Ptr todo = inc.staticCast<Todo>(); if (!rawTodoList.contains(todo)) { rawTodoList.append(todo); } } } index = rawTodoList.indexOf(subev); ++index; } // FIXME: Sort list by priorities. This is brute force and should be // replaced by a real sorting algorithm. Todo::List todoList; Todo::List::ConstIterator it; for (int i = 1; i <= 9; ++i) { for (it = rawTodoList.constBegin(); it != rawTodoList.constEnd(); ++it) { if ((*it)->priority() == i && checkSecrecy(*it)) { todoList.append(*it); } } } for (it = rawTodoList.constBegin(); it != rawTodoList.constEnd(); ++it) { if ((*it)->priority() == 0 && checkSecrecy(*it)) { todoList.append(*it); } } int columns = 3; *ts << "<table border=\"0\" cellpadding=\"3\" cellspacing=\"3\">" << endl; *ts << " <tr>" << endl; *ts << " <th class=\"sum\">" << i18nc("@title:column", "To-do") << "</th>" << endl; *ts << " <th>" << i18nc("@title:column to-do priority", "Priority") << "</th>" << endl; *ts << " <th>" << i18nc("@title:column to-do percent completed", "Completed") << "</th>" << endl; if (d->mSettings->taskDueDate()) { *ts << " <th>" << i18nc("@title:column to-do due date", "Due Date") << "</th>" << endl; ++columns; } if (d->mSettings->taskLocation()) { *ts << " <th>" << i18nc("@title:column to-do location", "Location") << "</th>" << endl; ++columns; } if (d->mSettings->taskCategories()) { *ts << " <th>" << i18nc("@title:column to-do categories", "Categories") << "</th>" << endl; ++columns; } if (d->mSettings->taskAttendees()) { *ts << " <th>" << i18nc("@title:column to-do attendees", "Attendees") << "</th>" << endl; ++columns; } *ts << " </tr>" << endl; // Create top-level list. for (it = todoList.constBegin(); it != todoList.constEnd(); ++it) { if ((*it)->relatedTo().isEmpty()) { createTodo(ts, *it); } } // Create sub-level lists for (it = todoList.constBegin(); it != todoList.constEnd(); ++it) { Incidence::List relations = d->mCalendar->relations((*it)->uid()); if (relations.count()) { // Generate sub-to-do list *ts << " <tr>" << endl; *ts << " <td class=\"subhead\" colspan="; *ts << "\"" << QString::number(columns) << "\""; *ts << "><a name=\"sub" << (*it)->uid() << "\"></a>" << i18nc("@title:column sub-to-dos of the parent to-do", "Sub-To-dos of: ") << "<a href=\"#" << (*it)->uid() << "\"><b>" << cleanChars((*it)->summary()) << "</b></a></td>" << endl; *ts << " </tr>" << endl; Todo::List sortedList; // FIXME: Sort list by priorities. This is brute force and should be // replaced by a real sorting algorithm. for (int i = 1; i <= 9; ++i) { Incidence::List::ConstIterator it2; for (it2 = relations.constBegin(); it2 != relations.constEnd(); ++it2) { Todo::Ptr ev3 = (*it2).staticCast<Todo>(); if (ev3 && ev3->priority() == i) { sortedList.append(ev3); } } } Incidence::List::ConstIterator it2; for (it2 = relations.constBegin(); it2 != relations.constEnd(); ++it2) { Todo::Ptr ev3 = (*it2).staticCast<Todo>(); if (ev3 && ev3->priority() == 0) { sortedList.append(ev3); } } Todo::List::ConstIterator it3; for (it3 = sortedList.constBegin(); it3 != sortedList.constEnd(); ++it3) { createTodo(ts, *it3); } } } *ts << "</table>" << endl; }