File indexing completed on 2024-05-12 05:10:48

0001 /*
0002   SPDX-FileCopyrightText: 2002-2004 Klarälvdalens Datakonsult AB,
0003         <info@klaralvdalens-datakonsult.se>
0004 
0005   SPDX-FileCopyrightText: 2010 Bertjan Broeksema <broeksema@kde.org>
0006   SPDX-FileCopyrightText: 2010 Klaralvdalens Datakonsult AB, a KDAB Group company <info@kdab.net>
0007 
0008   SPDX-License-Identifier: LGPL-2.0-or-later
0009 */
0010 
0011 #include "itiphandlerhelper_p.h"
0012 #include "calendarsettings.h"
0013 #include "utils_p.h"
0014 
0015 #include "akonadicalendar_debug.h"
0016 #include <KCalUtils/IncidenceFormatter>
0017 #include <KCalendarCore/Calendar>
0018 #include <KLocalizedString>
0019 #include <KMessageBox>
0020 
0021 #include <QWidget>
0022 
0023 using namespace Akonadi;
0024 
0025 QString proposalComment(const KCalendarCore::Incidence::Ptr &incidence)
0026 {
0027     QString comment;
0028 
0029     // TODO: doesn't KCalUtils/IncidenceFormater already provide this?
0030     // if not, it should go there.
0031 
0032     switch (incidence->type()) {
0033     case KCalendarCore::IncidenceBase::TypeEvent: {
0034         const QDateTime dtEnd = incidence->dateTime(KCalendarCore::Incidence::RoleDisplayEnd);
0035         comment = i18n("Proposed new meeting time: %1 - %2",
0036                        KCalUtils::IncidenceFormatter::dateToString(incidence->dtStart().toLocalTime().date()),
0037                        KCalUtils::IncidenceFormatter::dateToString(dtEnd.toLocalTime().date()));
0038         break;
0039     }
0040     case KCalendarCore::IncidenceBase::TypeTodo:
0041         qCWarning(AKONADICALENDAR_LOG) << "NOT IMPLEMENTED: proposalComment called for to-do.";
0042         break;
0043     default:
0044         qCWarning(AKONADICALENDAR_LOG) << "NOT IMPLEMENTED: proposalComment called for " << incidence->typeStr();
0045     }
0046 
0047     return comment;
0048 }
0049 
0050 ITIPHandlerDialogDelegate::ITIPHandlerDialogDelegate(const KCalendarCore::Incidence::Ptr &incidence, KCalendarCore::iTIPMethod method, QWidget *parent)
0051     : mParent(parent)
0052     , mIncidence(incidence)
0053     , mMethod(method)
0054 {
0055 }
0056 
0057 int ITIPHandlerDialogDelegate::askUserIfNeeded(const QString &question, Action action, const KGuiItem &buttonYes, const KGuiItem &buttonNo) const
0058 {
0059     Q_ASSERT_X(!question.isEmpty(), "ITIPHandlerHelper::askUser", "ask what?");
0060 
0061     switch (action) {
0062     case ActionSendMessage:
0063         return KMessageBox::ButtonCode::PrimaryAction;
0064     case ActionDontSendMessage:
0065         return KMessageBox::ButtonCode::SecondaryAction;
0066     default:
0067         return KMessageBox::questionTwoActionsCancel(mParent, question, i18nc("@title:window", "Group Scheduling Email"), buttonYes, buttonNo);
0068     }
0069 }
0070 
0071 void ITIPHandlerDialogDelegate::openDialogIncidenceCreated(Recipient recipient,
0072                                                            const QString &question,
0073                                                            Action action,
0074                                                            const KGuiItem &buttonYes,
0075                                                            const KGuiItem &buttonNo)
0076 {
0077     Q_UNUSED(recipient)
0078     const int messageBoxReturnCode = askUserIfNeeded(question, action, buttonYes, buttonNo);
0079     Q_EMIT dialogClosed(messageBoxReturnCode, mMethod, mIncidence);
0080 }
0081 
0082 void ITIPHandlerDialogDelegate::openDialogIncidenceModified(bool attendeeStatusChanged,
0083                                                             Recipient recipient,
0084                                                             const QString &question,
0085                                                             Action action,
0086                                                             const KGuiItem &buttonYes,
0087                                                             const KGuiItem &buttonNo)
0088 {
0089     Q_UNUSED(attendeeStatusChanged)
0090     Q_UNUSED(recipient)
0091     const int messageBoxReturnCode = askUserIfNeeded(question, action, buttonYes, buttonNo);
0092     Q_EMIT dialogClosed(messageBoxReturnCode, mMethod, mIncidence);
0093 }
0094 
0095 void ITIPHandlerDialogDelegate::openDialogIncidenceDeleted(Recipient recipient,
0096                                                            const QString &question,
0097                                                            Action action,
0098                                                            const KGuiItem &buttonYes,
0099                                                            const KGuiItem &buttonNo)
0100 {
0101     Q_UNUSED(recipient)
0102     const int messageBoxReturnCode = askUserIfNeeded(question, action, buttonYes, buttonNo);
0103     Q_EMIT dialogClosed(messageBoxReturnCode, mMethod, mIncidence);
0104 }
0105 
0106 void ITIPHandlerDialogDelegate::openDialogSchedulerFinished(const QString &question, Action action, const KGuiItem &buttonYes, const KGuiItem &buttonNo)
0107 {
0108     const int messageBoxReturnCode = askUserIfNeeded(question, action, buttonYes, buttonNo);
0109     Q_EMIT dialogClosed(messageBoxReturnCode, mMethod, mIncidence);
0110 }
0111 
0112 int ITIPHandlerDialogDelegate::warningContinueCancel(const QString &text, const QString &title, const KGuiItem &buttonContinue, const KGuiItem &buttonCancel)
0113 {
0114     return KMessageBox::warningContinueCancel(mParent, text, title, buttonContinue, buttonCancel);
0115 }
0116 
0117 int ITIPHandlerDialogDelegate::warningTwoActionsCancel(const QString &text,
0118                                                        const QString &title,
0119                                                        const KGuiItem &primaryAction,
0120                                                        const KGuiItem &secondaryAction,
0121                                                        const KGuiItem &cancelAction)
0122 {
0123     return KMessageBox::warningTwoActionsCancel(mParent, text, title, primaryAction, secondaryAction, cancelAction);
0124 }
0125 
0126 ITIPHandlerHelper::SendResult ITIPHandlerHelper::sentInvitation(int messageBoxReturnCode,
0127                                                                 const KCalendarCore::Incidence::Ptr &incidence,
0128                                                                 KCalendarCore::iTIPMethod method,
0129                                                                 const QString &sender)
0130 {
0131     // The value represented by messageBoxReturnCode is the answer on a question
0132     // which is a variant of: Do you want to send an email to the attendees?
0133     //
0134     // Where the email contains an invitation, modification notification or
0135     // deletion notification.
0136 
0137     if (messageBoxReturnCode == KMessageBox::ButtonCode::PrimaryAction) {
0138         // We will be sending out a message here. Now make sure there is some summary
0139         // Yes, we do modify the incidence here, but we still keep the Ptr
0140         // semantics, because this change is only for sending and not stored int the
0141         // local calendar.
0142         KCalendarCore::Incidence::Ptr _incidence(incidence->clone());
0143         if (_incidence->summary().isEmpty()) {
0144             _incidence->setSummary(xi18n("<placeholder>No summary given</placeholder>"));
0145         }
0146 
0147         // Send the mail
0148         m_status = StatusSendingInvitation;
0149         m_scheduler->performTransaction(_incidence, method, sender);
0150         return ITIPHandlerHelper::ResultSuccess;
0151     } else if (messageBoxReturnCode == KMessageBox::ButtonCode::SecondaryAction) {
0152         Q_EMIT finished(ITIPHandlerHelper::ResultCanceled, QString());
0153         return ITIPHandlerHelper::ResultCanceled;
0154     } else {
0155         Q_ASSERT(false); // TODO: Figure out if/how this can happen (by closing the dialog with x??)
0156         Q_EMIT finished(ITIPHandlerHelper::ResultCanceled, QString());
0157         return ITIPHandlerHelper::ResultCanceled;
0158     }
0159 }
0160 
0161 bool ITIPHandlerHelper::weAreOrganizerOf(const KCalendarCore::Incidence::Ptr &incidence)
0162 {
0163     const QString email = incidence->organizer().email();
0164     return Akonadi::CalendarUtils::thatIsMe(email) || email.isEmpty() || email == QLatin1StringView("invalid@email.address");
0165 }
0166 
0167 bool ITIPHandlerHelper::weNeedToSendMailFor(const KCalendarCore::Incidence::Ptr &incidence)
0168 {
0169     if (!weAreOrganizerOf(incidence)) {
0170         qCritical() << "We should be the organizer of this incidence."
0171                     << "; email= " << incidence->organizer().email() << "; thatIsMe() = " << Akonadi::CalendarUtils::thatIsMe(incidence->organizer().email());
0172         Q_ASSERT(false);
0173         return false;
0174     }
0175 
0176     if (incidence->attendees().isEmpty()) {
0177         return false;
0178     }
0179 
0180     // At least one attendee
0181     return incidence->attendees().count() > 1 || incidence->attendees().at(0).email() != incidence->organizer().email();
0182 }
0183 
0184 ITIPHandlerHelper::ITIPHandlerHelper(ITIPHandlerComponentFactory *factory, QWidget *parent)
0185     : QObject(parent)
0186     , mDefaultAction(ITIPHandlerDialogDelegate::ActionAsk)
0187     , mParent(parent)
0188     , m_factory(factory ? factory : new ITIPHandlerComponentFactory(this))
0189     , m_scheduler(new MailScheduler(m_factory, this))
0190     , m_status(StatusNone)
0191 {
0192     connect(m_scheduler, &MailScheduler::transactionFinished, this, &ITIPHandlerHelper::onSchedulerFinished);
0193 }
0194 
0195 ITIPHandlerHelper::~ITIPHandlerHelper() = default;
0196 
0197 void ITIPHandlerHelper::setDialogParent(QWidget *parent)
0198 {
0199     mParent = parent;
0200 }
0201 
0202 void ITIPHandlerHelper::setDefaultAction(ITIPHandlerDialogDelegate::Action action)
0203 {
0204     mDefaultAction = action;
0205 }
0206 
0207 void ITIPHandlerHelper::setMessagePrivacy(MessagePrivacyFlags messagePrivacy)
0208 {
0209     m_scheduler->setSign((messagePrivacy & ITIPHandlerHelper::MessagePrivacySign) == ITIPHandlerHelper::MessagePrivacySign);
0210     m_scheduler->setEncrypt((messagePrivacy & ITIPHandlerHelper::MessagePrivacyEncrypt) == ITIPHandlerHelper::MessagePrivacyEncrypt);
0211 }
0212 
0213 void ITIPHandlerHelper::sendIncidenceCreatedMessage(KCalendarCore::iTIPMethod method, const KCalendarCore::Incidence::Ptr &incidence)
0214 {
0215     /// When we created the incidence, we *must* be the organizer.
0216 
0217     if (!weAreOrganizerOf(incidence)) {
0218         qCWarning(AKONADICALENDAR_LOG) << "Creating incidence which has another organizer! Will skip sending invitations."
0219                                        << "; email= " << incidence->organizer().email()
0220                                        << "; thatIsMe() = " << Akonadi::CalendarUtils::thatIsMe(incidence->organizer().email());
0221         Q_EMIT sendIncidenceCreatedMessageFinished(ITIPHandlerHelper::ResultFailAbortUpdate, method, incidence);
0222         Q_EMIT finished(ITIPHandlerHelper::ResultFailAbortUpdate, QString());
0223         return;
0224     }
0225 
0226     if (!weNeedToSendMailFor(incidence)) {
0227         Q_EMIT sendIncidenceCreatedMessageFinished(ITIPHandlerHelper::ResultNoSendingNeeded, method, incidence);
0228         Q_EMIT finished(ITIPHandlerHelper::ResultNoSendingNeeded, QString());
0229         return;
0230     }
0231 
0232     QString question;
0233     if (incidence->type() == KCalendarCore::Incidence::TypeEvent) {
0234         question = i18n(
0235             "The event \"%1\" includes other people.\n"
0236             "Do you want to email the invitation to the attendees?",
0237             incidence->summary());
0238     } else if (incidence->type() == KCalendarCore::Incidence::TypeTodo) {
0239         question = i18n(
0240             "The todo \"%1\" includes other people.\n"
0241             "Do you want to email the invitation to the attendees?",
0242             incidence->summary());
0243     } else {
0244         question = i18n(
0245             "This incidence includes other people. "
0246             "Should an email be sent to the attendees?");
0247     }
0248 
0249     ITIPHandlerDialogDelegate *askDelegator = m_factory->createITIPHanderDialogDelegate(incidence, method, mParent);
0250     connect(askDelegator, &ITIPHandlerDialogDelegate::dialogClosed, this, &ITIPHandlerHelper::slotIncidenceCreatedDialogClosed);
0251     askDelegator->openDialogIncidenceCreated(ITIPHandlerDialogDelegate::Attendees, question, mDefaultAction);
0252 }
0253 
0254 void ITIPHandlerHelper::slotIncidenceCreatedDialogClosed(int messageBoxReturnCode,
0255                                                          KCalendarCore::iTIPMethod method,
0256                                                          const KCalendarCore::Incidence::Ptr &incidence)
0257 {
0258     ITIPHandlerHelper::SendResult status = sentInvitation(messageBoxReturnCode, incidence, method);
0259     Q_EMIT sendIncidenceCreatedMessageFinished(status, method, incidence);
0260 }
0261 
0262 bool ITIPHandlerHelper::handleIncidenceAboutToBeModified(const KCalendarCore::Incidence::Ptr &incidence)
0263 {
0264     Q_ASSERT(incidence);
0265     if (!weAreOrganizerOf(incidence)) {
0266         switch (incidence->type()) {
0267         case KCalendarCore::Incidence::TypeEvent: {
0268             const QString question = i18n(
0269                 "You are not the organizer of this event. Editing it will "
0270                 "bring your calendar out of sync with the organizer's calendar. "
0271                 "Do you really want to edit it?");
0272             const int messageBoxReturnCode = KMessageBox::warningTwoActions(mParent, question, {}, KStandardGuiItem::ok(), KStandardGuiItem::cancel());
0273             return messageBoxReturnCode != KMessageBox::ButtonCode::SecondaryAction;
0274             break;
0275         }
0276         case KCalendarCore::Incidence::TypeJournal:
0277         case KCalendarCore::Incidence::TypeTodo:
0278             // Not sure why we handle to-dos differently regarding this
0279             return true;
0280             break;
0281         default:
0282             qCritical() << "Unknown incidence type: " << incidence->type() << incidence->typeStr();
0283             Q_ASSERT_X(false, "ITIPHandlerHelper::handleIncidenceAboutToBeModified()", "Unknown incidence type");
0284             return false;
0285         }
0286     } else {
0287         return true;
0288     }
0289 }
0290 
0291 void ITIPHandlerHelper::sendIncidenceModifiedMessage(KCalendarCore::iTIPMethod method,
0292                                                      const KCalendarCore::Incidence::Ptr &incidence,
0293                                                      bool attendeeStatusChanged)
0294 {
0295     ITIPHandlerDialogDelegate *askDelegator = m_factory->createITIPHanderDialogDelegate(incidence, method, mParent);
0296 
0297     connect(askDelegator, &ITIPHandlerDialogDelegate::dialogClosed, this, &ITIPHandlerHelper::slotIncidenceModifiedDialogClosed);
0298     // For a modified incidence, either we are the organizer or someone else.
0299     if (weAreOrganizerOf(incidence)) {
0300         if (weNeedToSendMailFor(incidence)) {
0301             const QString question = i18n(
0302                 "You changed the invitation \"%1\".\n"
0303                 "Do you want to email the attendees an update message?",
0304                 incidence->summary());
0305 
0306             askDelegator->openDialogIncidenceModified(attendeeStatusChanged,
0307                                                       ITIPHandlerDialogDelegate::Attendees,
0308                                                       question,
0309                                                       mDefaultAction,
0310                                                       KGuiItem(i18n("Send Update")));
0311             return;
0312         } else {
0313             Q_EMIT sendIncidenceModifiedMessageFinished(ITIPHandlerHelper::ResultNoSendingNeeded, method, incidence);
0314             Q_EMIT finished(ITIPHandlerHelper::ResultNoSendingNeeded, QString());
0315             delete askDelegator;
0316             return;
0317         }
0318     } else if (incidence->type() == KCalendarCore::Incidence::TypeTodo) {
0319         if (method == KCalendarCore::iTIPRequest) {
0320             // This is an update to be sent to the organizer
0321             method = KCalendarCore::iTIPReply;
0322         }
0323 
0324         const QString question = i18n(
0325             "Do you want to send a status update to the "
0326             "organizer of this task?");
0327         askDelegator->openDialogIncidenceModified(attendeeStatusChanged,
0328                                                   ITIPHandlerDialogDelegate::Organizer,
0329                                                   question,
0330                                                   mDefaultAction,
0331                                                   KGuiItem(i18n("Send Update")));
0332         return;
0333     } else if (incidence->type() == KCalendarCore::Incidence::TypeEvent) {
0334         if (attendeeStatusChanged && method == KCalendarCore::iTIPRequest) {
0335             method = KCalendarCore::iTIPReply;
0336             const QString question = i18n(
0337                 "Your status as an attendee of this event changed. "
0338                 "Do you want to send a status update to the event organizer?");
0339 
0340             askDelegator->openDialogIncidenceModified(attendeeStatusChanged,
0341                                                       ITIPHandlerDialogDelegate::Organizer,
0342                                                       question,
0343                                                       mDefaultAction,
0344                                                       KGuiItem(i18n("Send Update")));
0345             return;
0346         } else {
0347             slotIncidenceModifiedDialogClosed(KMessageBox::ButtonCode::PrimaryAction, method, incidence);
0348             delete askDelegator;
0349             return;
0350         }
0351     }
0352     Q_ASSERT(false); // Shouldn't happen.
0353     Q_EMIT sendIncidenceModifiedMessageFinished(ITIPHandlerHelper::ResultNoSendingNeeded, method, incidence);
0354     Q_EMIT finished(ITIPHandlerHelper::ResultNoSendingNeeded, QString());
0355     delete askDelegator;
0356 }
0357 
0358 void ITIPHandlerHelper::slotIncidenceModifiedDialogClosed(int messageBoxReturnCode,
0359                                                           KCalendarCore::iTIPMethod method,
0360                                                           const KCalendarCore::Incidence::Ptr &incidence)
0361 {
0362     ITIPHandlerHelper::SendResult status = sentInvitation(messageBoxReturnCode, incidence, method);
0363     Q_EMIT sendIncidenceModifiedMessageFinished(status, method, incidence);
0364 }
0365 
0366 void ITIPHandlerHelper::sendIncidenceDeletedMessage(KCalendarCore::iTIPMethod method, const KCalendarCore::Incidence::Ptr &incidence)
0367 {
0368     Q_ASSERT(incidence);
0369 
0370     ITIPHandlerDialogDelegate *askDelegator = m_factory->createITIPHanderDialogDelegate(incidence, method, mParent);
0371 
0372     connect(askDelegator, &ITIPHandlerDialogDelegate::dialogClosed, this, &ITIPHandlerHelper::slotIncidenceDeletedDialogClosed);
0373 
0374     // For a modified incidence, either we are the organizer or someone else.
0375     if (weAreOrganizerOf(incidence)) {
0376         if (weNeedToSendMailFor(incidence)) {
0377             QString question;
0378             if (incidence->type() == KCalendarCore::Incidence::TypeEvent) {
0379                 question = i18n(
0380                     "You removed the invitation \"%1\".\n"
0381                     "Do you want to email the attendees that the event is canceled?",
0382                     incidence->summary());
0383             } else if (incidence->type() == KCalendarCore::Incidence::TypeTodo) {
0384                 question = i18n(
0385                     "You removed the invitation \"%1\".\n"
0386                     "Do you want to email the attendees that the todo is canceled?",
0387                     incidence->summary());
0388             } else if (incidence->type() == KCalendarCore::Incidence::TypeJournal) {
0389                 question = i18n(
0390                     "You removed the invitation \"%1\".\n"
0391                     "Do you want to email the attendees that the journal is canceled?",
0392                     incidence->summary());
0393             }
0394             askDelegator->openDialogIncidenceDeleted(ITIPHandlerDialogDelegate::Attendees, question, mDefaultAction);
0395             return;
0396         } else {
0397             Q_EMIT sendIncidenceDeletedMessageFinished(ITIPHandlerHelper::ResultNoSendingNeeded, method, incidence);
0398             Q_EMIT finished(ITIPHandlerHelper::ResultNoSendingNeeded, QString());
0399             delete askDelegator;
0400             return;
0401         }
0402     } else if (incidence->type() != KCalendarCore::Incidence::TypeEvent) {
0403         if (method == KCalendarCore::iTIPRequest) {
0404             // This is an update to be sent to the organizer
0405             method = KCalendarCore::iTIPReply;
0406         }
0407 
0408         const QString question = (incidence->type() == KCalendarCore::Incidence::TypeTodo) ? i18n(
0409                                      "Do you want to send a status update to the "
0410                                      "organizer of this task?")
0411                                                                                            : i18n(
0412                                                                                                "Do you want to send a status update to the "
0413                                                                                                "organizer of this journal?");
0414         askDelegator->openDialogIncidenceDeleted(ITIPHandlerDialogDelegate::Organizer,
0415                                                  question,
0416                                                  mDefaultAction,
0417                                                  KGuiItem(i18nc("@action:button dialog positive answer", "Send Update")));
0418         return;
0419     } else {
0420         const QStringList myEmails = Akonadi::CalendarUtils::allEmails();
0421         bool incidenceAcceptedBefore = false;
0422         for (const QString &email : myEmails) {
0423             const KCalendarCore::Attendee me = incidence->attendeeByMail(email);
0424             if (!me.isNull() && (me.status() == KCalendarCore::Attendee::Accepted || me.status() == KCalendarCore::Attendee::Delegated)) {
0425                 incidenceAcceptedBefore = true;
0426                 break;
0427             }
0428         }
0429 
0430         if (incidenceAcceptedBefore) {
0431             QString question = i18n(
0432                 "You had previously accepted an invitation to this event. "
0433                 "Do you want to send an updated response to the organizer "
0434                 "declining the invitation?");
0435             askDelegator->openDialogIncidenceDeleted(ITIPHandlerDialogDelegate::Organizer,
0436                                                      question,
0437                                                      mDefaultAction,
0438                                                      KGuiItem(i18nc("@action:button dialog positive answer", "Send Update")));
0439             return;
0440         } else {
0441             // We did not accept the event before and delete it from our calendar again,
0442             // so there is no need to notify people.
0443             Q_EMIT sendIncidenceDeletedMessageFinished(ITIPHandlerHelper::ResultNoSendingNeeded, method, incidence);
0444             Q_EMIT finished(ITIPHandlerHelper::ResultNoSendingNeeded, QString());
0445             delete askDelegator;
0446             return;
0447         }
0448     }
0449 
0450     Q_ASSERT(false); // Shouldn't happen.
0451     Q_EMIT sendIncidenceDeletedMessageFinished(ITIPHandlerHelper::ResultNoSendingNeeded, method, incidence);
0452     Q_EMIT finished(ITIPHandlerHelper::ResultNoSendingNeeded, QString());
0453     delete askDelegator;
0454 }
0455 
0456 void ITIPHandlerHelper::slotIncidenceDeletedDialogClosed(const int messageBoxReturnCode,
0457                                                          KCalendarCore::iTIPMethod method,
0458                                                          const KCalendarCore::Incidence::Ptr &incidence)
0459 {
0460     ITIPHandlerHelper::SendResult status = sentInvitation(messageBoxReturnCode, incidence, method);
0461     Q_EMIT sendIncidenceDeletedMessageFinished(status, method, incidence);
0462 }
0463 
0464 ITIPHandlerHelper::SendResult
0465 ITIPHandlerHelper::sendCounterProposal(const QString &receiver, const KCalendarCore::Incidence::Ptr &oldEvent, const KCalendarCore::Incidence::Ptr &newEvent)
0466 {
0467     Q_ASSERT(oldEvent);
0468     Q_ASSERT(newEvent);
0469 
0470     if (!oldEvent || !newEvent || *oldEvent == *newEvent) {
0471         return ITIPHandlerHelper::ResultNoSendingNeeded;
0472     }
0473 
0474     if (CalendarSettings::self()->outlookCompatCounterProposals()) {
0475         KCalendarCore::Incidence::Ptr tmp(oldEvent->clone());
0476         tmp->setSummary(i18n("Counter proposal: %1", newEvent->summary()));
0477         tmp->setDescription(newEvent->description());
0478         tmp->addComment(proposalComment(newEvent));
0479 
0480         return sentInvitation(KMessageBox::ButtonCode::PrimaryAction, tmp, KCalendarCore::iTIPReply, receiver);
0481     } else {
0482         return sentInvitation(KMessageBox::ButtonCode::PrimaryAction, newEvent, KCalendarCore::iTIPCounter, receiver);
0483     }
0484 }
0485 
0486 void ITIPHandlerHelper::onSchedulerFinished(Akonadi::Scheduler::Result result, const QString &errorMsg)
0487 {
0488     const bool success = result == MailScheduler::ResultSuccess;
0489 
0490     if (m_status == StatusSendingInvitation) {
0491         m_status = StatusNone;
0492         if (!success) {
0493             const QString question(i18n("Sending group scheduling email failed."));
0494 
0495             ITIPHandlerDialogDelegate *askDelegator =
0496                 m_factory->createITIPHanderDialogDelegate(KCalendarCore::Incidence::Ptr(), KCalendarCore::iTIPNoMethod, mParent);
0497 
0498             connect(askDelegator, &ITIPHandlerDialogDelegate::dialogClosed, this, &ITIPHandlerHelper::slotSchedulerFinishDialog);
0499             askDelegator->openDialogSchedulerFinished(question,
0500                                                       ITIPHandlerDialogDelegate::ActionAsk,
0501                                                       KGuiItem(i18nc("@action:button dialog positive answer to abort question", "Abort Update")));
0502             return;
0503         } else {
0504             // fall through
0505         }
0506     }
0507 
0508     Q_EMIT finished(success ? ResultSuccess : ResultError, success ? QString() : i18n("Error: %1", errorMsg));
0509 }
0510 
0511 void ITIPHandlerHelper::slotSchedulerFinishDialog(const int result, KCalendarCore::iTIPMethod method, const KCalendarCore::Incidence::Ptr &incidence)
0512 {
0513     Q_UNUSED(method)
0514     Q_UNUSED(incidence)
0515     if (result == KMessageBox::ButtonCode::PrimaryAction) {
0516         Q_EMIT finished(ResultFailAbortUpdate, QString());
0517     } else {
0518         Q_EMIT finished(ResultFailKeepUpdate, QString());
0519     }
0520 }
0521 
0522 #include "moc_itiphandlerhelper_p.cpp"