Esempio n. 1
0
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 << "    &nbsp;\n";
    }
}
Esempio n. 2
0
bool Scheduler::acceptFreeBusy(IncidenceBase *incidence, Method method)
{
    if ( !d->mFreeBusyCache ) {
        kdError() << "KCal::Scheduler: no FreeBusyCache." << endl;
        return false;
    }

    FreeBusy *freebusy = static_cast<FreeBusy *>(incidence);

    kdDebug(5800) << "acceptFreeBusy:: freeBusyDirName: " << freeBusyDir() << endl;

    Person from;
    if(method == Scheduler::Publish) {
        from = freebusy->organizer();
    }
    if((method == Scheduler::Reply) && (freebusy->attendeeCount() == 1)) {
        Attendee *attendee = freebusy->attendees().first();
        from = attendee->email();
    }

    if ( !d->mFreeBusyCache->saveFreeBusy( freebusy, from ) ) return false;

    deleteTransaction(incidence);
    return true;
}
Esempio n. 3
0
bool IncidenceChanger::myAttendeeStatusChanged( Incidence *oldInc, Incidence *newInc )
{
  Attendee *oldMe = oldInc->attendeeByMails( KOPrefs::instance()->allEmails() );
  Attendee *newMe = newInc->attendeeByMails( KOPrefs::instance()->allEmails() );
  if ( oldMe && newMe && ( oldMe->status() != newMe->status() ) )
    return true;

  return false;
}
void KOEditorDetails::fillIncidence( Incidence *incidence )
{
    incidence->clearAttendees();
    QVector<Q3ListViewItem*> toBeDeleted;
    Q3ListViewItem *item;
    AttendeeListItem *a;
    for ( item = mListView->firstChild(); item; item = item->nextSibling() ) {
        a = (AttendeeListItem *)item;
        Attendee *attendee = a->data();
        Q_ASSERT( attendee );
        /* Check if the attendee is a distribution list and expand it */
        if ( attendee->email().isEmpty() ) {
            KPIM::DistributionList list =
                KPIM::DistributionList::findByName( KABC::StdAddressBook::self(), attendee->name() );
            if ( !list.isEmpty() ) {
                toBeDeleted.push_back( item ); // remove it once we are done expanding
                KPIM::DistributionList::Entry::List entries = list.entries( KABC::StdAddressBook::self() );
                KPIM::DistributionList::Entry::List::Iterator it( entries.begin() );
                while ( it != entries.end() ) {
                    KPIM::DistributionList::Entry &e = ( *it );
                    ++it;
                    // this calls insertAttendee, which appends
                    insertAttendeeFromAddressee( e.addressee, attendee );
                    // TODO: duplicate check, in case it was already added manually
                }
            }
        } else {
            bool skip = false;
            if ( attendee->email().endsWith( QLatin1String( "example.net" ) ) ) {
                if ( KMessageBox::warningYesNo(
                            this,
                            i18nc( "@info",
                                   "%1 does not look like a valid email address. "
                                   "Are you sure you want to invite this participant?",
                                   attendee->email() ),
                            i18nc( "@title", "Invalid Email Address" ) ) != KMessageBox::Yes ) {
                    skip = true;
                }
            }
            if ( !skip ) {
                incidence->addAttendee( new Attendee( *attendee ) );
            }
        }
    }

    KOAttendeeEditor::fillIncidence( incidence );

    // cleanup
    qDeleteAll( toBeDeleted );
    toBeDeleted.clear();
}
Esempio n. 5
0
void KOEditorFreeBusy::writeEvent(KCal::Event * event)
{
  event->clearAttendees();
  QValueVector<FreeBusyItem*> toBeDeleted;
  for ( FreeBusyItem *item = static_cast<FreeBusyItem *>( mGanttView->firstChild() ); item;
        item = static_cast<FreeBusyItem*>( item->nextSibling() ) )
  {
    Attendee *attendee = item->attendee();
    Q_ASSERT( attendee );
    /* Check if the attendee is a distribution list and expand it */
    if ( attendee->email().isEmpty() ) {
      KPIM::DistributionList list =
        KPIM::DistributionList::findByName( KABC::StdAddressBook::self(), attendee->name() );
      if ( !list.isEmpty() ) {
        toBeDeleted.push_back( item ); // remove it once we are done expanding
        KPIM::DistributionList::Entry::List entries = list.entries( KABC::StdAddressBook::self() );
        KPIM::DistributionList::Entry::List::Iterator it( entries.begin() );
        while ( it != entries.end() ) {
          KPIM::DistributionList::Entry &e = ( *it );
          ++it;
          // this calls insertAttendee, which appends
          insertAttendeeFromAddressee( e.addressee, attendee );
          // TODO: duplicate check, in case it was already added manually
        }
      }
    } else {
      bool skip = false;
      if ( attendee->email().endsWith( "example.net" ) ) {
        if ( KMessageBox::warningYesNo( this, i18n("%1 does not look like a valid email address. "
                "Are you sure you want to invite this participant?").arg( attendee->email() ),
              i18n("Invalid email address") ) != KMessageBox::Yes ) {
          skip = true;
        }
      }
      if ( !skip ) {
        event->addAttendee( new Attendee( *attendee ) );
      }
    }
  }

  KOAttendeeEditor::writeEvent( event );

  // cleanup
  QValueVector<FreeBusyItem*>::iterator it;
  for( it = toBeDeleted.begin(); it != toBeDeleted.end(); ++it ) {
    delete *it;
  }
}
void KOAttendeeEditor::insertAttendeeFromAddressee( const KABC::Addressee &a, const Attendee *at )
{
  bool myself = KOPrefs::instance()->thatIsMe( a.preferredEmail() );
  bool sameAsOrganizer = mOrganizerCombo &&
                         KPIMUtils::compareEmail( a.preferredEmail(),
                                                  mOrganizerCombo->currentText(), false );
  KCal::Attendee::PartStat partStat = at ? at->status() : KCal::Attendee::NeedsAction;
  bool rsvp = at? at->RSVP() : true;

  if ( myself && sameAsOrganizer ) {
    partStat = KCal::Attendee::Accepted;
    rsvp = false;
  }
  Attendee *newAt = new Attendee( a.realName(), a.preferredEmail(), !myself,
                                  partStat, at ? at->role() : Attendee::ReqParticipant, a.uid() );
  newAt->setRSVP( rsvp );
  insertAttendee( newAt, true );
}
Esempio n. 7
0
void FreeBusyItem::updateItem()
{
  setListViewText( 0, mAttendee->fullName() );
  switch ( mAttendee->status() ) {
    case Attendee::Accepted:
      setPixmap( 0, KOGlobals::self()->smallIcon( "ok" ) );
      break;
    case Attendee::Declined:
      setPixmap( 0, KOGlobals::self()->smallIcon( "no" ) );
      break;
    case Attendee::NeedsAction:
    case Attendee::InProcess:
      setPixmap( 0, KOGlobals::self()->smallIcon( "help" ) );
      break;
    case Attendee::Tentative:
      setPixmap( 0, KOGlobals::self()->smallIcon( "apply" ) );
      break;
    case Attendee::Delegated:
      setPixmap( 0, KOGlobals::self()->smallIcon( "mail_forward" ) );
      break;
    default:
      setPixmap( 0, QPixmap() );
  }
}
void KCalResourceSlox::parseMembersAttribute( const QDomElement &e,
                                              Incidence *incidence )
{
  incidence->clearAttendees();

  QDomNode n;
  for( n = e.firstChild(); !n.isNull(); n = n.nextSibling() ) {
    QDomElement memberElement = n.toElement();
    if ( memberElement.tagName() == fieldName( Participant ) ) {
      QString member = memberElement.text();
      KABC::Addressee account;
      if ( mAccounts ) account = mAccounts->lookupUser( member );
      else kError() << "KCalResourceSlox: no accounts set";
      QString name;
      QString email;
      Attendee *a = incidence->attendeeByUid( member );
      if ( account.isEmpty() ) {
        if ( a ) continue;

        name = member;
        email = member + '@' + KUrl( mPrefs->url() ).host();
      } else {
        name = account.realName();
        email = account.preferredEmail();
      }
      if ( a ) {
        a->setName( name );
        a->setEmail( email );
      } else {
        a = new Attendee( name, email );
        a->setUid( member );
        incidence->addAttendee( a );
      }
      QString status = memberElement.attribute( "confirm" );
      if ( !status.isEmpty() ) {
        if ( status == "accept" ) {
          a->setStatus( Attendee::Accepted );
        } else if ( status == "decline" ) {
          a->setStatus( Attendee::Declined );
        } else {
          a->setStatus( Attendee::NeedsAction );
        }
      }
    } else {
      kDebug() << "Unknown tag in members attribute:"
               << memberElement.tagName();
    }
  }
}
Esempio n. 9
0
void KOAttendeeEditor::updateAttendee()
{
  Attendee *a = currentAttendee();
  if ( !a || mDisableItemUpdate )
    return;

  QString name;
  QString email;
  KPIM::getNameAndMail(mNameEdit->text(), name, email);

  bool iAmTheOrganizer = mOrganizerCombo &&
    KOPrefs::instance()->thatIsMe( mOrganizerCombo->currentText() );
  if ( iAmTheOrganizer ) {
    bool myself =
      KPIM::compareEmail( email, mOrganizerCombo->currentText(), false );
    bool wasMyself =
      KPIM::compareEmail( a->email(), mOrganizerCombo->currentText(), false );
    if ( myself ) {
      mStatusCombo->setCurrentItem( KCal::Attendee::Accepted );
      mRsvpButton->setChecked( false );
      mRsvpButton->setEnabled( false );
    } else if ( wasMyself ) {
      // this was me, but is no longer, reset
      mStatusCombo->setCurrentItem( KCal::Attendee::NeedsAction );
      mRsvpButton->setChecked( true );
      mRsvpButton->setEnabled( true );
    }
  }
  a->setName( name );
  a->setUid( mUid );
  a->setEmail( email );
  a->setRole( Attendee::Role( mRoleCombo->currentItem() ) );
  a->setStatus( Attendee::PartStat( mStatusCombo->currentItem() ) );
  a->setRSVP( mRsvpButton->isChecked() );

  updateCurrentItem();
}
Esempio n. 10
0
void KOWhatsNextView::updateView()
{
  KIconLoader kil("kdepim");
  QString *ipath = new QString();
  kil.loadIcon("kdepim",KIcon::NoGroup,32,KIcon::DefaultState,ipath);

  mText = "<table width=\"100%\">\n";
  mText += "<tr bgcolor=\"#3679AD\"><td><h1>";
  mText += "<img src=\"";
  mText += *ipath;
  mText += "\">";
  mText += "<font color=\"white\"> ";
  mText += i18n("What's Next?") + "</font></h1>";
  mText += "</td></tr>\n<tr><td>";

  mText += "<h2>";
  if ( mStartDate.daysTo( mEndDate ) < 1 ) {
    mText += KGlobal::locale()->formatDate( mStartDate );
  } else {
    mText += i18n("Date from - to", "%1 - %2")
            .arg( KGlobal::locale()->formatDate( mStartDate ) )
            .arg( KGlobal::locale()->formatDate( mEndDate ) );
  }
  mText+="</h2>\n";

  Event::List events;
  for ( QDate date = mStartDate; date <= mEndDate; date = date.addDays( 1 ) )
    events += calendar()->events(date, EventSortStartDate, SortDirectionAscending);

  if (events.count() > 0) {
    mText += "<p></p>";
    kil.loadIcon("appointment",KIcon::NoGroup,22,KIcon::DefaultState,ipath);
    mText += "<h2><img src=\"";
    mText += *ipath;
    mText += "\">";
    mText += i18n("Events:") + "</h2>\n";
    mText += "<table>\n";
    Event::List::ConstIterator it;
    for( it = events.begin(); it != events.end(); ++it ) {
      Event *ev = *it;
      if ( !ev->doesRecur() ){
        appendEvent(ev);
      } else {
        // FIXME: This should actually be cleaned up. Libkcal should
        // provide a method to return a list of all recurrences in a
        // given time span.
        Recurrence *recur = ev->recurrence();
        int duration = ev->dtStart().secsTo( ev->dtEnd() );
        QDateTime start = recur->getPreviousDateTime(
                                QDateTime( mStartDate, QTime() ) );
        QDateTime end = start.addSecs( duration );
        if ( end.date() >= mStartDate ) {
          appendEvent( ev, start, end );
        }
        start = recur->getNextDateTime( start );
        while ( start.isValid() && start.date() <= mEndDate ) {
          appendEvent( ev, start );
          start = recur->getNextDateTime( start );
        }
      }
    }
    mText += "</table>\n";
  }

  mTodos.clear();
  Todo::List todos = calendar()->todos( TodoSortDueDate, SortDirectionAscending );
  if ( todos.count() > 0 ) {
    kil.loadIcon("todo",KIcon::NoGroup,22,KIcon::DefaultState,ipath);
    mText += "<h2><img src=\"";
    mText += *ipath;
    mText += "\">";
    mText += i18n("To-do:") + "</h2>\n";
    mText += "<ul>\n";
    Todo::List::ConstIterator it;
    for( it = todos.begin(); it != todos.end(); ++it ) {
      Todo *todo = *it;
      if ( !todo->isCompleted() && todo->hasDueDate() && todo->dtDue().date() <= mEndDate )
                  appendTodo(todo);
    }
    bool gotone = false;
    int priority = 1;
    while (!gotone && priority<=9 ) {
      for( it = todos.begin(); it != todos.end(); ++it ) {
        Todo *todo = *it;
        if (!todo->isCompleted() && (todo->priority() == priority) ) {
          appendTodo(todo);
          gotone = true;
        }
      }
      priority++;
      kdDebug(5850) << "adding the todos..." << endl;
    }
    mText += "</ul>\n";
  }

  QStringList myEmails( KOPrefs::instance()->allEmails() );
  int replies = 0;
  events = calendar()->events( QDate::currentDate(), QDate(2975,12,6) );
  Event::List::ConstIterator it2;
  for( it2 = events.begin(); it2 != events.end(); ++it2 ) {
    Event *ev = *it2;
    Attendee *me = ev->attendeeByMails( myEmails );
    if (me!=0) {
      if (me->status()==Attendee::NeedsAction && me->RSVP()) {
        if (replies == 0) {
          mText += "<p></p>";
          kil.loadIcon("reply",KIcon::NoGroup,22,KIcon::DefaultState,ipath);
          mText += "<h2><img src=\"";
          mText += *ipath;
          mText += "\">";
          mText += i18n("Events and to-dos that need a reply:") + "</h2>\n";
          mText += "<table>\n";
        }
        replies++;
        appendEvent( ev );
      }
    }
  }
  todos = calendar()->todos();
  Todo::List::ConstIterator it3;
  for( it3 = todos.begin(); it3 != todos.end(); ++it3 ) {
    Todo *to = *it3;
    Attendee *me = to->attendeeByMails( myEmails );
    if (me!=0) {
      if (me->status()==Attendee::NeedsAction && me->RSVP()) {
        if (replies == 0) {
          mText += "<p></p>";
          kil.loadIcon("reply",KIcon::NoGroup,22,KIcon::DefaultState,ipath);
          mText += "<h2><img src=\"";
          mText += *ipath;
          mText += "\">";
          mText += i18n("Events and to-dos that need a reply:") + "</h2>\n";
          mText += "<table>\n";
        }
        replies++;
        appendEvent(to);
      }
    }
    kdDebug () << "check for todo-replies..." << endl;
  }
  if (replies > 0 ) mText += "</table>\n";


  mText += "</td></tr>\n</table>\n";

  kdDebug(5850) << "KOWhatsNextView::updateView: text: " << mText << endl;

  delete ipath;

  mView->setText(mText);
}
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;
  }
}
Esempio n. 12
0
bool KCal::operator==(const Attendee &a1, const Attendee &a2)
{
    return (operator==((const Person &)a1, (const Person &) a2) &&
            a1.RSVP() == a2.RSVP() &&
            a1.role() == a2.role() &&
            a1.status() == a2.status() &&
            a1.uid() == a2.uid() &&
            a1.delegate() == a2.delegate() &&
            a1.delegator() == a2.delegator());
}
Esempio n. 13
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;
}
Esempio n. 14
0
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 );
}