void EventArchiver::deleteIncidences(Calendar *calendar, const QDate &limitDate, QWidget *widget, const Incidence::List &incidences, bool withGUI) { QStringList incidenceStrs; Incidence::List::ConstIterator it; for(it = incidences.begin(); it != incidences.end(); ++it) { incidenceStrs.append((*it)->summary()); } if(withGUI) { int result = KMessageBox::warningContinueCancelList( widget, i18n("Delete all items before %1 without saving?\n" "The following items will be deleted:") .arg(KGlobal::locale()->formatDate(limitDate)), incidenceStrs, i18n("Delete Old Items"), KStdGuiItem::del()); if(result != KMessageBox::Continue) return; } for(it = incidences.begin(); it != incidences.end(); ++it) { calendar->deleteIncidence(*it); } emit eventsDeleted(); }
bool ResourceGroupware::doSave( bool ) { kDebug() <<"KCal::ResourceGroupware::doSave()"; saveToCache(); if ( !hasChanges() ) { kDebug() <<"No changes"; return true; } if ( !confirmSave() ) return false; #if 0 Incidence::List::ConstIterator it; Incidence::List added = addedIncidences(); for( it = added.begin(); it != added.end(); ++it ) { if ( mServer->addIncidence( *it, this ) ) { clearChange( *it ); saveToCache(); } } Incidence::List changed = changedIncidences(); for( it = changed.begin(); it != changed.end(); ++it ) { if ( mServer->changeIncidence( *it ) ) clearChange( *it ); } Incidence::List deleted = deletedIncidences(); for( it = deleted.begin(); it != deleted.end(); ++it ) { if ( mServer->deleteIncidence( *it ) ) clearChange( *it ); } #endif return true; }
bool ResourceGroupwareBase::doSave( bool syncCache ) { kDebug(5800); Q_UNUSED( syncCache ); saveToCache(); if ( !hasChanges() ) { kDebug(5800) << "No changes"; return true; } // TODO: Implement confirming of single changes i.e. it should be possible // to upload only certain changes and discard the rest. This is // particularly important for resources like the blogging resource, // where uploading would mean a republication of the blog, not only // a modifications. if ( !confirmSave() ) return false; mUploadJob = createUploadJob( adaptor() ); connect( mUploadJob, SIGNAL( result( KPIM::GroupwareJob * ) ), SLOT( slotUploadJobResult( KPIM::GroupwareJob * ) ) ); Incidence::List inc; Incidence::List::Iterator it; KPIM::GroupwareUploadItem::List addedItems, changedItems, deletedItems; inc = addedIncidences(); for( it = inc.begin(); it != inc.end(); ++it ) { addedItems.append( adaptor()->newUploadItem( *it, KPIM::GroupwareUploadItem::Added ) ); } // TODO: Check if the item has changed on the server... // In particular, check if the version we based our change on is still current // on the server inc = changedIncidences(); for( it = inc.begin(); it != inc.end(); ++it ) { changedItems.append( adaptor()->newUploadItem( *it, KPIM::GroupwareUploadItem::Changed ) ); } inc = deletedIncidences(); for( it = inc.begin(); it != inc.end(); ++it ) { deletedItems.append( adaptor()->newUploadItem( *it, KPIM::GroupwareUploadItem::Deleted ) ); } mUploadJob->setAddedItems( addedItems ); mUploadJob->setChangedItems( changedItems ); mUploadJob->setDeletedItems( deletedItems ); // FIXME: Calling clearChanges() here is not the ideal way since the // upload might fail, but there is no other place to call it... clearChanges(); return true; }
void KOListView::addIncidences(const Incidence::List &incidenceList) { Incidence::List::ConstIterator it; for(it = incidenceList.begin(); it != incidenceList.end(); ++it) { addIncidence(*it); } }
Incidence::List Calendar::incidencesFromSchedulingID(const QString &UID) { Incidence::List result; Incidence::List incidences = rawIncidences(); Incidence::List::iterator it = incidences.begin(); for(; it != incidences.end(); ++it) if((*it)->schedulingID() == UID) result.append(*it); return result; }
Incidence *Calendar::incidenceFromSchedulingID(const QString &UID) { Incidence::List incidences = rawIncidences(); Incidence::List::iterator it = incidences.begin(); for(; it != incidences.end(); ++it) if((*it)->schedulingID() == UID) // Touchdown, and the crowd goes wild return *it; // Not found return 0; }
void ConfirmSaveDialog::addIncidences( const Incidence::List &incidences, const QString &operation ) { Incidence::List::ConstIterator it; for( it = incidences.begin(); it != incidences.end(); ++it ) { Incidence *i = *it; KListViewItem *item = new KListViewItem( mListView ); item->setText( 0, operation ); item->setText( 1, i->type() ); item->setText( 2, i->summary() ); item->setText( 3, i->uid() ); } }
bool ResourceLocalDir::doSave() { Incidence::List list; bool success = true; list = addedIncidences(); list += changedIncidences(); for(Incidence::List::iterator it = list.begin(); it != list.end(); ++it) if(!doSave(*it)) success = false; return success; }
void ResourceCached::loadChangesCache(QMap<Incidence *, bool> &map, const QString &type) { CalendarLocal calendar(QString::fromLatin1("UTC")); if(KStandardDirs::exists(changesCacheFile(type))) calendar.load(changesCacheFile(type)); else return; const Incidence::List list = calendar.incidences(); Incidence::List::ConstIterator it; for(it = list.begin(); it != list.end(); ++it) map.insert((*it)->clone(), true); calendar.close(); }
void ResourceGroupware::slotJobResult( KJob *job ) { kDebug() <<"ResourceGroupware::slotJobResult():"; if ( job->error() ) { mIsShowingError = true; loadError( job->errorString() ); mIsShowingError = false; } else { disableChangeNotification(); clearCache(); // FIXME: This does not take into account the time zone! CalendarLocal calendar; ICalFormat ical; if ( !ical.fromString( &calendar, mJobData ) ) { loadError( i18n("Error parsing calendar data.") ); } else { Incidence::List incidences = calendar.incidences(); Incidence::List::ConstIterator it; for( it = incidences.begin(); it != incidences.end(); ++it ) { // kDebug() <<"INCIDENCE:" << (*it)->summary(); Incidence *i = (*it)->clone(); QString remote = (*it)->customProperty( "GWRESOURCE", "UID" ); QString local = idMapper().localId( remote ); if ( local.isEmpty() ) { idMapper().setRemoteId( i->uid(), remote ); } else { i->setUid( local ); } addIncidence( i ); } } saveToCache(); enableChangeNotification(); clearChanges(); emit resourceChanged( this ); emit resourceLoaded( this ); } mDownloadJob = 0; if ( mProgress ) mProgress->setComplete(); mProgress = 0; }
void EventArchiver::archiveIncidences( Calendar* calendar, const QDate& /*limitDate*/, QWidget* widget, const Incidence::List& incidences, bool /*withGUI*/) { FileStorage storage( calendar ); // Save current calendar to disk KTempFile tmpFile; tmpFile.setAutoDelete(true); storage.setFileName( tmpFile.name() ); if ( !storage.save() ) { kdDebug(5850) << "EventArchiver::archiveEvents(): Can't save calendar to temp file" << endl; return; } // Duplicate current calendar by loading in new calendar object CalendarLocal archiveCalendar( KOPrefs::instance()->mTimeZoneId ); FileStorage archiveStore( &archiveCalendar ); archiveStore.setFileName( tmpFile.name() ); if (!archiveStore.load()) { kdDebug(5850) << "EventArchiver::archiveEvents(): Can't load calendar from temp file" << endl; return; } // Strip active events from calendar so that only events to be archived // remain. This is not really efficient, but there is no other easy way. QStringList uids; Incidence::List allIncidences = archiveCalendar.rawIncidences(); Incidence::List::ConstIterator it; for( it = incidences.begin(); it != incidences.end(); ++it ) { uids << (*it)->uid(); } for( it = allIncidences.begin(); it != allIncidences.end(); ++it ) { if ( !uids.contains( (*it)->uid() ) ) { archiveCalendar.deleteIncidence( *it ); } } // Get or create the archive file KURL archiveURL( KOPrefs::instance()->mArchiveFile ); QString archiveFile; if ( KIO::NetAccess::exists( archiveURL, true, widget ) ) { if( !KIO::NetAccess::download( archiveURL, archiveFile, widget ) ) { kdDebug(5850) << "EventArchiver::archiveEvents(): Can't download archive file" << endl; return; } // Merge with events to be archived. archiveStore.setFileName( archiveFile ); if ( !archiveStore.load() ) { kdDebug(5850) << "EventArchiver::archiveEvents(): Can't merge with archive file" << endl; return; } } else { archiveFile = tmpFile.name(); } // Save archive calendar if ( !archiveStore.save() ) { KMessageBox::error(widget,i18n("Cannot write archive file %1.").arg( archiveStore.fileName() )); return; } // Upload if necessary KURL srcUrl; srcUrl.setPath(archiveFile); if (srcUrl != archiveURL) { if ( !KIO::NetAccess::upload( archiveFile, archiveURL, widget ) ) { KMessageBox::error(widget,i18n("Cannot write archive to final destination.")); return; } } KIO::NetAccess::removeTempFile(archiveFile); // Delete archived events from calendar for( it = incidences.begin(); it != incidences.end(); ++it ) { calendar->deleteIncidence( *it ); } emit eventsDeleted(); }
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; }
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; }
void SearchDialog::search(const QRegExp &re) { QDate startDt = mStartDate->date(); QDate endDt = mEndDate->date(); Event::List events; if(mEventsCheck->isChecked()) { events = mCalendar->events(startDt, endDt, mInclusiveCheck->isChecked()); } Todo::List todos; if(mTodosCheck->isChecked()) { if(mIncludeUndatedTodos->isChecked()) { Todo::List alltodos = mCalendar->todos(); Todo::List::iterator it; Todo *todo; for(it = alltodos.begin(); it != alltodos.end(); ++it) { todo = *it; if((!todo->hasStartDate() && !todo->hasDueDate()) || // undated (todo->hasStartDate() && (todo->dtStart() >= startDt) && (todo->dtStart() <= endDt)) || // start dt in range (todo->hasDueDate() && (todo->dtDue().date() >= startDt) && (todo->dtDue() <= endDt)) || // due dt in range (todo->hasCompletedDate() && (todo->completed().date() >= startDt) && (todo->completed() <= endDt))) // completed dt in range { todos.append(todo); } } } else { QDate dt = startDt; while(dt <= endDt) { todos += mCalendar->todos(dt); dt = dt.addDays(1); } } } Journal::List journals; if(mJournalsCheck->isChecked()) { QDate dt = startDt; while(dt <= endDt) { journals += mCalendar->journals(dt); dt = dt.addDays(1); } } Incidence::List allIncidences = Calendar::mergeIncidenceList(events, todos, journals); mMatchedEvents.clear(); Incidence::List::ConstIterator it; for(it = allIncidences.begin(); it != allIncidences.end(); ++it) { Incidence *ev = *it; if(mSummaryCheck->isChecked()) { #if QT_VERSION >= 300 if(re.search(ev->summary()) != -1) { #else if(re.match(ev->summary()) != -1) { #endif mMatchedEvents.append(ev); continue; } } if(mDescriptionCheck->isChecked()) { #if QT_VERSION >= 300 if(re.search(ev->description()) != -1) { #else if(re.match(ev->description()) != -1) { #endif mMatchedEvents.append(ev); continue; } } if(mCategoryCheck->isChecked()) { #if QT_VERSION >= 300 if(re.search(ev->categoriesStr()) != -1) { #else if(re.match(ev->categoriesStr()) != -1) { #endif mMatchedEvents.append(ev); continue; } } } }
// If a task with subtasks is deleted, move it's subtasks to the orphans list void Calendar::removeRelations(Incidence *incidence) { if(!incidence) { kdDebug(5800) << "Warning: Calendar::removeRelations( 0 )!\n"; return; } // kdDebug(5850) << "Calendar::removeRelations for incidence " << forincidence << " with UID " << forincidence->uid() << ", summary: " << forincidence->summary() << endl; QString uid = incidence->uid(); Incidence::List relations = incidence->relations(); Incidence::List::ConstIterator it; for(it = relations.begin(); it != relations.end(); ++it) { Incidence *i = *it; if(!mOrphanUids.find(i->uid())) { mOrphans.insert(uid, i); mOrphanUids.insert(i->uid(), i); i->setRelatedTo(0); i->setRelatedToUid(uid); } } // If this incidence is related to something else, tell that about it if(incidence->relatedTo()) incidence->relatedTo()->removeRelation(incidence); // Remove this one from the orphans list if(mOrphanUids.remove(uid)) { // This incidence is located in the orphans list - it should be removed // Since the mOrphans dict might contain the same key (with different // child incidence pointers!) multiple times, take care that we remove // the correct one. So we need to remove all items with the given // parent UID, and readd those that are not for this item. Also, there // might be other entries with differnet UID that point to this // incidence (this might happen when the relatedTo of the item is // changed before its parent is inserted. This might happen with // groupware servers....). Remove them, too QStringList relatedToUids; // First get the list of all keys in the mOrphans list that point to the removed item relatedToUids << incidence->relatedToUid(); for(QDictIterator<Incidence> it(mOrphans); it.current(); ++it) { if(it.current()->uid() == uid) { relatedToUids << it.currentKey(); } } // now go through all uids that have one entry that point to the incidence for(QStringList::Iterator uidit = relatedToUids.begin(); uidit != relatedToUids.end(); ++uidit) { Incidence::List tempList; // Remove all to get access to the remaining entries while(Incidence *i = mOrphans[ *uidit ]) { mOrphans.remove(*uidit); if(i != incidence) tempList.append(i); } // Readd those that point to a different orphan incidence for(Incidence::List::Iterator incit = tempList.begin(); incit != tempList.end(); ++incit) { mOrphans.insert(*uidit, *incit); } } } }
int main(int argc, char **argv) { KAboutData aboutData("testrecurrencenew", "Load recurrence rules with the new class and print out debug messages", "0.1"); KCmdLineArgs::init(argc, argv, &aboutData); KCmdLineArgs::addCmdLineOptions(options); KApplication app(false, false); KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); if(args->count() < 1) { args->usage("Wrong number of arguments."); } // use zoneinfo data from source dir set_zone_directory(KDETOPSRCDIR "/libkcal/libical/zoneinfo"); QString input = QFile::decodeName(args->arg(0)); kdDebug(5800) << "Input file: " << input << endl; QTextStream *outstream; outstream = 0; QString fn(""); if(args->count() > 1) { fn = args->arg(1); kdDebug() << "We have a file name given: " << fn << endl; } QFile outfile(fn); if(!fn.isEmpty() && outfile.open(IO_WriteOnly)) { kdDebug() << "Opened output file!!!" << endl; outstream = new QTextStream(&outfile); } CalendarLocal cal(QString::fromLatin1("UTC")); if(!cal.load(input)) return 1; QString tz = cal.nonKDECustomProperty("X-LibKCal-Testsuite-OutTZ"); if(!tz.isEmpty()) { cal.setTimeZoneIdViewOnly(tz); } Incidence::List inc = cal.incidences(); for(Incidence::List::Iterator it = inc.begin(); it != inc.end(); ++it) { Incidence *incidence = *it; kdDebug(5800) << "*+*+*+*+*+*+*+*+*+*" << endl; kdDebug(5800) << " -> " << incidence->summary() << " <- " << endl; incidence->recurrence()->dump(); QDateTime dt(incidence->recurrence()->endDateTime()); int i = 0; if(outstream) { if(!dt.isValid()) dt = QDateTime(QDate(2011, 1, 1), QTime(0, 0, 1)); else dt = dt.addYears(2); kdDebug(5800) << "-------------------------------------------" << endl; kdDebug(5800) << " *~*~*~*~ Starting with date: " << dt << endl; // Output to file for testing purposes while(dt.isValid() && i < 500) { dt = dt.addSecs(-1); ++i; dt = incidence->recurrence()->getPreviousDateTime(dt); (*outstream) << dt.toString(Qt::ISODate) << endl; } } else { if(!dt.isValid()) dt = QDateTime(QDate(2005, 7, 31), QTime(23, 59, 59)); else dt = dt.addYears(2); incidence->recurrence()->dump(); kdDebug(5800) << "-------------------------------------------" << endl; kdDebug(5800) << " *~*~*~*~ Starting with date: " << dt << endl; // Output to konsole while(dt.isValid() && i < 50) { dt = dt.addSecs(-1); ++i; kdDebug(5800) << "-------------------------------------------" << endl; dt = incidence->recurrence()->getPreviousDateTime(dt); kdDebug(5800) << " *~*~*~*~ Previous date is: " << dt << endl; } } } delete outstream; outfile.close(); return 0; }
bool Scheduler::acceptReply(IncidenceBase *incidence,ScheduleMessage::Status /* status */, Method method) { if(incidence->type()=="FreeBusy") { return acceptFreeBusy(incidence, method); } bool ret = false; Event *ev = mCalendar->event(incidence->uid()); Todo *to = mCalendar->todo(incidence->uid()); // try harder to find the correct incidence if ( !ev && !to ) { const Incidence::List list = mCalendar->incidences(); for ( Incidence::List::ConstIterator it = list.begin(), end = list.end(); it != end; ++it ) { if ( (*it)->schedulingID() == incidence->uid() ) { ev = dynamic_cast<Event*>( *it ); to = dynamic_cast<Todo*>( *it ); break; } } } if (ev || to) { //get matching attendee in calendar kdDebug(5800) << "Scheduler::acceptTransaction match found!" << endl; 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.begin(); inIt != attendeesIn.end(); ++inIt ) { Attendee *attIn = *inIt; bool found = false; for ( evIt = attendeesEv.begin(); evIt != attendeesEv.end(); ++evIt ) { Attendee *attEv = *evIt; if (attIn->email().lower()==attEv->email().lower()) { //update attendee-info kdDebug(5800) << "Scheduler::acceptTransaction update attendee" << endl; attEv->setStatus(attIn->status()); attEv->setDelegate(attIn->delegate()); attEv->setDelegator(attIn->delegator()); ret = true; 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* attNew = *it; QString msg = i18n("%1 wants to attend %2 but was not invited.").arg( attNew->fullName() ) .arg( ev ? ev->summary() : to->summary() ); if ( !attNew->delegator().isEmpty() ) msg = i18n("%1 wants to attend %2 on behalf of %3.").arg( attNew->fullName() ) .arg( ev ? ev->summary() : to->summary() ) .arg( attNew->delegator() ); if ( KMessageBox::questionYesNo( 0, msg, i18n("Uninvited attendee"), KGuiItem(i18n("Accept Attendance")), KGuiItem(i18n("Reject Attendance")) ) != KMessageBox::Yes ) { KCal::Incidence *cancel = dynamic_cast<Incidence*>( incidence ); if ( cancel ) cancel->addComment( i18n( "The organizer rejected your attendance at this meeting." ) ); performTransaction( cancel ? cancel : incidence, Scheduler::Cancel, attNew->fullName() ); delete cancel; continue; } Attendee *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 ); ret = true; attendeeAdded = true; } // send update about new participants if ( attendeeAdded ) { if ( ev ) { ev->setRevision( ev->revision() + 1 ); performTransaction( ev, Scheduler::Request ); } if ( to ) { to->setRevision( ev->revision() + 1 ); performTransaction( to, Scheduler::Request ); } } if ( ret ) { // 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 task. see RFC2446 3.4.3 Todo *update = dynamic_cast<Todo*> ( incidence ); Q_ASSERT( update ); if ( update && ( to->percentComplete() != update->percentComplete() ) ) { to->setPercentComplete( update->percentComplete() ); to->updated(); } } } else kdError(5800) << "No incidence for scheduling\n"; if (ret) deleteTransaction(incidence); return ret; }
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; }
void HtmlExport::createTodoList ( QTextStream *ts ) { Todo::List rawTodoList = mCalendar->todos(); Todo::List::Iterator it = rawTodoList.begin(); while ( it != rawTodoList.end() ) { Todo *ev = *it; Todo *subev = ev; if ( ev->relatedTo() ) { if ( ev->relatedTo()->type()=="Todo" ) { if ( rawTodoList.find( static_cast<Todo *>( ev->relatedTo() ) ) == rawTodoList.end() ) { rawTodoList.append( static_cast<Todo *>( ev->relatedTo() ) ); } } } it = rawTodoList.find( subev ); ++it; } // FIXME: Sort list by priorities. This is brute force and should be // replaced by a real sorting algorithm. Todo::List todoList; for ( int i = 1; i <= 9; ++i ) { for( it = rawTodoList.begin(); it != rawTodoList.end(); ++it ) { if ( (*it)->priority() == i && checkSecrecy( *it ) ) { todoList.append( *it ); } } } for( it = rawTodoList.begin(); it != rawTodoList.end(); ++it ) { if ( (*it)->priority() == 0 && checkSecrecy( *it ) ) { todoList.append( *it ); } } int columns = 3; *ts << "<table border=\"0\" cellpadding=\"3\" cellspacing=\"3\">\n"; *ts << " <tr>\n"; *ts << " <th class=\"sum\">" << i18n("Task") << "</th>\n"; *ts << " <th>" << i18n("Priority") << "</th>\n"; *ts << " <th>" << i18n("Completed") << "</th>\n"; if ( mSettings->taskDueDate() ) { *ts << " <th>" << i18n("Due Date") << "</th>\n"; ++columns; } if ( mSettings->taskLocation() ) { *ts << " <th>" << i18n("Location") << "</th>\n"; ++columns; } if ( mSettings->taskCategories() ) { *ts << " <th>" << i18n("Categories") << "</th>\n"; ++columns; } if ( mSettings->taskAttendees() ) { *ts << " <th>" << i18n("Attendees") << "</th>\n"; ++columns; } *ts << " </tr>\n"; // Create top-level list. for( it = todoList.begin(); it != todoList.end(); ++it ) { if ( !(*it)->relatedTo() ) createTodo( ts, *it ); } // Create sub-level lists for( it = todoList.begin(); it != todoList.end(); ++it ) { Incidence::List relations = (*it)->relations(); if (relations.count()) { // Generate sub-task list of event ev *ts << " <tr>\n"; *ts << " <td class=\"subhead\" colspan="; *ts << "\"" << QString::number(columns) << "\""; *ts << "><a name=\"sub" << (*it)->uid() << "\"></a>" << i18n("Sub-Tasks of: ") << "<a href=\"#" << (*it)->uid() << "\"><b>" << cleanChars( (*it)->summary()) << "</b></a></td>\n"; *ts << " </tr>\n"; 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.begin(); it2 != relations.end(); ++it2 ) { Todo *ev3 = dynamic_cast<Todo *>( *it2 ); if ( ev3 && ev3->priority() == i ) sortedList.append( ev3 ); } } Incidence::List::ConstIterator it2; for( it2 = relations.begin(); it2 != relations.end(); ++it2 ) { Todo *ev3 = dynamic_cast<Todo *>( *it2 ); if ( ev3 && ev3->priority() == 0 ) sortedList.append( ev3 ); } Todo::List::ConstIterator it3; for( it3 = sortedList.begin(); it3 != sortedList.end(); ++it3 ) { createTodo( ts, *it3 ); } } } *ts << "</table>\n"; }