void HtmlExport::formatAttendees( QTextStream *ts, Incidence *event ) { Attendee::List attendees = event->attendees(); if (attendees.count()) { *ts << "<em>"; #ifndef KORG_NOKABC KABC::AddressBook *add_book = KABC::StdAddressBook::self( true ); KABC::Addressee::List addressList; addressList = add_book->findByEmail(event->organizer().email()); KABC::Addressee o = addressList.first(); if (!o.isEmpty() && addressList.size()<2) { *ts << "<a href=\"mailto:" << event->organizer().email() << "\">"; *ts << cleanChars(o.formattedName()) << "</a>\n"; } else *ts << event->organizer().fullName(); #else *ts << event->organizer().fullName(); #endif *ts << "</em><br />"; Attendee::List::ConstIterator it; for( it = attendees.begin(); it != attendees.end(); ++it ) { Attendee *a = *it; if (!a->email().isEmpty()) { *ts << "<a href=\"mailto:" << a->email(); *ts << "\">" << cleanChars(a->name()) << "</a>"; } else { *ts << " " << cleanChars(a->name()); } *ts << "<br />" << "\n"; } } else { *ts << " \n"; } }
void KCalResourceSlox::createIncidenceAttributes( QDomDocument &doc, QDomElement &parent, Incidence *incidence ) { WebdavHandler::addSloxElement( this, doc, parent, fieldName( IncidenceTitle ), incidence->summary() ); WebdavHandler::addSloxElement( this, doc, parent, fieldName( Description ), incidence->description() ); if ( incidence->attendeeCount() > 0 ) { QDomElement members = WebdavHandler::addSloxElement( this, doc, parent, fieldName( Participants ) ); Attendee::List attendees = incidence->attendees(); Attendee::List::ConstIterator it; for( it = attendees.constBegin(); it != attendees.constEnd(); ++it ) { if ( mAccounts ) { QString userId = mAccounts->lookupId( (*it)->email() ); QString status; switch ( (*it)->status() ) { case Attendee::Accepted: status = "accept"; break; case Attendee::Declined: status = "decline"; break; default: status = "none"; break; } QDomElement el = WebdavHandler::addSloxElement( this, doc, members, fieldName( Participant ), userId ); el.setAttribute( "confirm", status ); } else { kError() << "KCalResourceSlox: No accounts set."; } } } // set read attributes - if SecrecyPublic, set it to users // TODO OX support if ( incidence->secrecy() == Incidence::SecrecyPublic && type() != "ox" ) { QDomElement rights = WebdavHandler::addSloxElement( this, doc, parent, "readrights" ); WebdavHandler::addSloxElement( this, doc, rights, "group", "users" ); } // set reminder as the number of minutes to the start of the event KCal::Alarm::List alarms = incidence->alarms(); if ( !alarms.isEmpty() && alarms.first()->hasStartOffset() && alarms.first()->enabled() ) WebdavHandler::addSloxElement( this, doc, parent, fieldName( Reminder ), QString::number( (-1) * alarms.first()->startOffset().asSeconds() / 60 ) ); else WebdavHandler::addSloxElement( this, doc, parent, fieldName( Reminder ), "0" ); // categories WebdavHandler::addSloxElement( this, doc, parent, fieldName( Categories ), incidence->categories().join( ", " ) ); }
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; } }
void KOAttendeeEditor::readEvent(KCal::Incidence * incidence) { mdelAttendees.clear(); if ( KOPrefs::instance()->thatIsMe( incidence->organizer().email() ) ) { if ( !mOrganizerCombo ) { mOrganizerCombo = new QComboBox( mOrganizerHBox ); fillOrganizerCombo(); } mOrganizerLabel->setText( i18n( "Identity as organizer:" ) ); int found = -1; QString fullOrganizer = incidence->organizer().fullName(); for ( int i = 0 ; i < mOrganizerCombo->count(); ++i ) { if ( mOrganizerCombo->text( i ) == fullOrganizer ) { found = i; mOrganizerCombo->setCurrentItem( i ); break; } } if ( found < 0 ) { mOrganizerCombo->insertItem( fullOrganizer, 0 ); mOrganizerCombo->setCurrentItem( 0 ); } } else { // someone else is the organizer if ( mOrganizerCombo ) { delete mOrganizerCombo; mOrganizerCombo = 0; } mOrganizerLabel->setText( i18n( "Organizer: %1" ).arg( incidence->organizer().fullName() ) ); } Attendee::List al = incidence->attendees(); Attendee::List::ConstIterator it; for( it = al.begin(); it != al.end(); ++it ) insertAttendee( new Attendee( **it ), true ); }
void KOAttendeeEditor::readIncidence( KCal::Incidence *incidence ) { qDeleteAll( mDelAttendees ); mDelAttendees.clear(); if ( KOPrefs::instance()->thatIsMe( incidence->organizer().email() ) || incidence->organizer().isEmpty() ) { //TODO: make a new private method for creating the mOrganizerCombo //and use it here and initOrganizerWidgets() above. if ( !mOrganizerCombo ) { mOrganizerCombo = new KComboBox( mOrganizerHBox ); mOrganizerCombo->setToolTip( i18nc( "@info:tooltip", "Select the organizer" ) ); mOrganizerCombo->setWhatsThis( i18nc( "@info:whatsthis", "Select the identity to use as the organizer for this incidence." ) ); fillOrganizerCombo(); } mOrganizerLabel->setText( i18nc( "@label", "Identity as organizer:" ) ); int found = -1; QString fullOrganizer = incidence->organizer().fullName(); for ( int i = 0; i < mOrganizerCombo->count(); ++i ) { if ( mOrganizerCombo->itemText( i ) == fullOrganizer ) { found = i; mOrganizerCombo->setCurrentIndex( i ); break; } } if ( found < 0 ) { mOrganizerCombo->addItem( fullOrganizer, 0 ); mOrganizerCombo->setCurrentIndex( 0 ); } } else { // someone else is the organizer if ( mOrganizerCombo ) { delete mOrganizerCombo; mOrganizerCombo = 0; } mOrganizerLabel->setText( i18nc( "@label", "Organizer: %1", incidence->organizer().fullName() ) ); } Attendee::List al = incidence->attendees(); Attendee::List::ConstIterator it; Attendee *first = 0; for ( it = al.constBegin(); it != al.constEnd(); ++it ) { Attendee *a = new Attendee( **it ); if ( !first ) { first = a; } insertAttendee( a, true ); } // Set the initial editing values to the first attendee in the list. if ( first ) { // Don't update the item here, the user didn't edit it, so it's not needed. // Also, AttendeeEditor's subclasses didn't set the current Item at this point // so if updateAttendee is called now what will happen is that a random item // will get the text of "first". mDisableItemUpdate = true; mNameEdit->setText( first->fullName() ); mUid = first->uid(); mRoleCombo->setCurrentIndex( first->role() ); if ( first->status() != KCal::Attendee::None ) { mStatusCombo->setCurrentIndex( first->status() ); } else { mStatusCombo->setCurrentIndex( KCal::Attendee::NeedsAction ); } mRsvpButton->setChecked( first->RSVP() ); mRsvpButton->setEnabled( true ); mDisableItemUpdate = false; } }
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; }
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; }
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; }
bool KOMailClient::mailAttendees( IncidenceBase *incidence, const Identity &identity, bool bccMe, const QString &attachment, bool useSendmail ) { Attendee::List attendees = incidence->attendees(); if ( attendees.count() == 0 ) { return false; } const QString from = incidence->organizer().fullName(); const QString organizerEmail = incidence->organizer().email(); QStringList toList; QStringList ccList; for ( int i=0; i<attendees.count(); ++i ) { Attendee *a = attendees.at(i); const QString email = a->email(); if ( email.isEmpty() ) { continue; } // In case we (as one of our identities) are the organizer we are sending // this mail. We could also have added ourselves as an attendee, in which // case we don't want to send ourselves a notification mail. if ( organizerEmail == email ) { continue; } // Build a nice address for this attendee including the CN. QString tname, temail; const QString username = KPIMUtils::quoteNameIfNecessary( a->name() ); // ignore the return value from extractEmailAddressAndName() because // it will always be false since tusername does not contain "@domain". KPIMUtils::extractEmailAddressAndName( username, temail, tname ); tname += " <" + email + '>'; // Optional Participants and Non-Participants are copied on the email if ( a->role() == Attendee::OptParticipant || a->role() == Attendee::NonParticipant ) { ccList << tname; } else { toList << tname; } } if( toList.count() == 0 && ccList.count() == 0 ) { // Not really to be called a groupware meeting, eh return false; } QString to; if ( toList.count() > 0 ) { to = toList.join( ", " ); } QString cc; if ( ccList.count() > 0 ) { cc = ccList.join( ", " ); } QString subject; if ( incidence->type() != "FreeBusy" ) { Incidence *inc = static_cast<Incidence *>( incidence ); subject = inc->summary(); } else { subject = "Free Busy Object"; } QString body = IncidenceFormatter::mailBodyStr( incidence, KSystemTimeZones::local() ); return send( identity, from, to, cc, subject, body, false, bccMe, attachment, useSendmail ); }