26 #include "itiphandler.h"
27 #include "itiphandler_p.h"
28 #include "itiphandlerhelper_p.h"
29 #include "calendarsettings.h"
30 #include "publishdialog.h"
32 #include "mailclient_p.h"
34 #include <kcalcore/icalformat.h>
35 #include <kcalcore/incidence.h>
36 #include <kcalcore/schedulemessage.h>
37 #include <kcalcore/attendee.h>
38 #include <kcalutils/stringify.h>
41 #include <kpimidentities/identitymanager.h>
42 #include <mailtransport/transportmanager.h>
44 #include <KMessageBox>
45 #include <KLocalizedString>
47 using namespace Akonadi;
50 static void emitiTipMessageProcessed(
ITIPHandler *handler,
52 const QString &errorString)
54 QMetaObject::invokeMethod(handler,
"iTipMessageProcessed", Qt::QueuedConnection,
56 Q_ARG(QString, errorString));
59 GroupwareUiDelegate::~GroupwareUiDelegate()
65 , d(new Private(this))
67 qRegisterMetaType<Akonadi::ITIPHandler::Result>(
"Akonadi::ITIPHandler::Result");
77 const QString &action)
79 if (d->m_currentOperation != OperationNone) {
80 d->m_currentOperation = OperationNone;
81 kFatal() <<
"There can't be an operation in progress!" << d->m_currentOperation;
85 d->m_currentOperation = OperationProcessiTIPMessage;
88 d->m_queuedInvitation.receiver = receiver;
89 d->m_queuedInvitation.iCal = iCal;
90 d->m_queuedInvitation.action = action;
94 if (d->m_calendarLoadError) {
95 d->m_currentOperation = OperationNone;
96 emitiTipMessageProcessed(
this,
ResultError, i18n(
"Error loading calendar."));
100 KCalCore::ICalFormat format;
101 KCalCore::ScheduleMessage::Ptr message = format.parseScheduleMessage(d->calendar(), iCal);
104 const QString errorMessage = format.exception() ? i18n(
"Error message: %1", KCalUtils::Stringify::errorMessage(*format.exception()))
105 : i18n(
"Unknown error while parsing iCal invitation");
107 kError() <<
"Error parsing" << errorMessage;
109 KMessageBox::detailedError(0,
110 i18n(
"Error while processing an invitation or update."),
112 d->m_currentOperation = OperationNone;
118 d->m_method =
static_cast<KCalCore::iTIPMethod
>(message->method());
120 KCalCore::ScheduleMessage::Status status = message->status();
121 d->m_incidence = message->event().dynamicCast<KCalCore::Incidence>();
122 if (!d->m_incidence) {
123 kError() <<
"Invalid incidence";
124 d->m_currentOperation = OperationNone;
125 emitiTipMessageProcessed(
this,
ResultError, i18n(
"Invalid incidence"));
129 if (action.startsWith(QLatin1String(
"accepted")) ||
130 action.startsWith(QLatin1String(
"tentative")) ||
131 action.startsWith(QLatin1String(
"delegated")) ||
132 action.startsWith(QLatin1String(
"counter"))) {
135 const KCalCore::Attendee::List attendees = d->m_incidence->attendees();
136 foreach(KCalCore::Attendee::Ptr attendee, attendees) {
137 if (attendee->email() == receiver) {
138 if (action.startsWith(QLatin1String(
"accepted"))) {
139 attendee->setStatus(KCalCore::Attendee::Accepted);
140 }
else if (action.startsWith(QLatin1String(
"tentative"))) {
141 attendee->setStatus(KCalCore::Attendee::Tentative);
142 }
else if (CalendarSettings::self()->outlookCompatCounterProposals() &&
143 action.startsWith(QLatin1String(
"counter"))) {
144 attendee->setStatus(KCalCore::Attendee::Tentative);
145 }
else if (action.startsWith(QLatin1String(
"delegated"))) {
146 attendee->setStatus(KCalCore::Attendee::Delegated);
151 if (CalendarSettings::self()->outlookCompatCounterProposals() ||
152 !action.startsWith(QLatin1String(
"counter"))) {
153 d->m_scheduler->acceptTransaction(d->m_incidence, d->calendar(), d->m_method, status, receiver);
157 }
else if (action.startsWith(QLatin1String(
"cancel"))) {
159 KCalCore::Incidence::Ptr existingIncidence = d->calendar()->incidenceFromSchedulingID(d->m_incidence->uid());
160 if (existingIncidence) {
161 d->m_scheduler->acceptTransaction(d->m_incidence, d->calendar(), KCalCore::iTIPCancel, status, receiver);
165 kWarning() <<
"Couldn't find the incidence to delete.\n"
166 <<
"You deleted it previously or didn't even accept the invitation it in the first place.\n"
167 <<
"; uid=" << d->m_incidence->uid()
168 <<
"; identifier=" << d->m_incidence->instanceIdentifier()
169 <<
"; summary=" << d->m_incidence->summary();
171 kDebug() <<
"\n Here's what we do have with such a summary:";
172 KCalCore::Incidence::List knownIncidences =
calendar()->incidences();
173 foreach(
const KCalCore::Incidence::Ptr &knownIncidence, knownIncidences) {
174 if (knownIncidence->summary() == d->m_incidence->summary()) {
175 kDebug() <<
"\nFound: uid=" << knownIncidence->uid()
176 <<
"; identifier=" << knownIncidence->instanceIdentifier()
177 <<
"; schedulingId" << knownIncidence->schedulingID();
183 }
else if (action.startsWith(QLatin1String(
"reply"))) {
184 if (d->m_method != KCalCore::iTIPCounter) {
185 d->m_scheduler->acceptTransaction(d->m_incidence, d->calendar(), d->m_method, status, QString());
187 d->m_scheduler->acceptCounterProposal(d->m_incidence, d->calendar());
191 kError() <<
"Unknown incoming action" << action;
193 d->m_currentOperation = OperationNone;
194 emitiTipMessageProcessed(
this,
ResultError, i18n(
"Invalid action: %1", action));
197 if (action.startsWith(QLatin1String(
"counter"))) {
198 if (d->m_uiDelegate) {
201 item.
setPayload(KCalCore::Incidence::Ptr(d->m_incidence->clone()));
205 d->m_uiDelegate->requestIncidenceEditor(item);
206 KCalCore::Incidence::Ptr newIncidence;
207 if (item.
hasPayload<KCalCore::Incidence::Ptr>()) {
208 newIncidence = item.
payload<KCalCore::Incidence::Ptr>();
211 if (*newIncidence == *d->m_incidence) {
216 emitiTipMessageProcessed(
this,
ResultError, QString());
221 emitiTipMessageProcessed(
this,
ResultError, QLatin1String(
"Error sending counter proposal"));
227 kWarning() <<
"No UI delegate is set";
228 emitiTipMessageProcessed(
this,
ResultError, QLatin1String(
"Could not start editor to edit counter proposal"));
234 const KCalCore::Incidence::Ptr &incidence,
235 QWidget *parentWidget)
239 kError() <<
"Invalid incidence";
243 d->m_queuedInvitation.method = method;
244 d->m_queuedInvitation.incidence = incidence;
245 d->m_parentWidget = parentWidget;
247 if (!d->isLoaded()) {
252 Q_ASSERT(d->m_currentOperation == OperationNone);
253 if (d->m_currentOperation != OperationNone) {
254 kError() <<
"There can't be an operation in progress!" << d->m_currentOperation;
258 if (incidence->attendeeCount() == 0 && method != KCalCore::iTIPPublish) {
259 KMessageBox::information(parentWidget,
260 i18n(
"The item '%1' has no attendees. "
261 "Therefore no groupware message will be sent.",
262 incidence->summary()),
263 i18n(
"Message Not Sent"),
264 QLatin1String(
"ScheduleNoAttendees"));
268 d->m_currentOperation = OperationSendiTIPMessage;
270 KCalCore::Incidence *incidenceCopy = incidence->clone();
271 incidenceCopy->registerObserver(0);
272 incidenceCopy->clearAttendees();
274 d->m_scheduler->performTransaction(incidence, method);
278 QWidget *parentWidget)
282 kError() <<
"Invalid incidence. Aborting.";
286 Q_ASSERT(d->m_currentOperation == OperationNone);
287 if (d->m_currentOperation != OperationNone) {
288 kError() <<
"There can't be an operation in progress!" << d->m_currentOperation;
292 d->m_queuedInvitation.incidence = incidence;
293 d->m_parentWidget = parentWidget;
295 d->m_currentOperation = OperationPublishInformation;
297 QPointer<Akonadi::PublishDialog> publishdlg =
new Akonadi::PublishDialog();
298 if (incidence->attendeeCount() > 0) {
299 KCalCore::Attendee::List attendees = incidence->attendees();
300 KCalCore::Attendee::List::ConstIterator it;
301 KCalCore::Attendee::List::ConstIterator end(attendees.constEnd());
302 for (it = attendees.constBegin(); it != end; ++it) {
303 publishdlg->addAttendee(*it);
306 if (publishdlg->exec() == QDialog::Accepted && publishdlg)
307 d->m_scheduler->publish(incidence, publishdlg->addresses());
314 QWidget *parentWidget)
316 Q_UNUSED(parentWidget);
317 Q_ASSERT(originalIncidence);
318 if (!originalIncidence) {
319 kError() <<
"Invalid incidence";
324 KCalCore::Incidence::Ptr incidence = KCalCore::Incidence::Ptr(originalIncidence->clone());
326 KPIMIdentities::IdentityManager identityManager;
328 QPointer<Akonadi::PublishDialog> publishdlg =
new Akonadi::PublishDialog;
329 if (publishdlg->exec() == QDialog::Accepted && publishdlg) {
330 const QString recipients = publishdlg->addresses();
331 if (incidence->organizer()->isEmpty()) {
332 incidence->setOrganizer(KCalCore::Person::Ptr(
333 new KCalCore::Person(Akonadi::CalendarUtils::fullName(),
334 Akonadi::CalendarUtils::email())));
337 if (incidence->hasRecurrenceId()) {
339 incidence->setRecurrenceId(KDateTime());
342 KCalCore::ICalFormat format;
343 const QString from = Akonadi::CalendarUtils::email();
344 const bool bccMe = Akonadi::CalendarSettings::self()->bcc();
345 const QString messageText = format.createScheduleMessage(incidence, KCalCore::iTIPRequest);
346 MailClient *mailer =
new MailClient();
347 d->m_queuedInvitation.incidence = incidence;
348 connect(mailer, SIGNAL(finished(Akonadi::MailClient::Result,QString)),
349 d, SLOT(finishSendAsICalendar(Akonadi::MailScheduler::Result,QString)));
351 mailer->mailTo(incidence, identityManager.identityForAddress(from), from, bccMe,
352 recipients, messageText,
353 MailTransport::TransportManager::self()->defaultTransportName());
359 d->m_uiDelegate = delegate;
364 if (d->m_calendar != calendar) {
371 return d->m_calendar;
374 #include "itiphandler.moc"