예제 #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";
    }
}
예제 #2
0
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 );
}
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;
}
예제 #5
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;
}