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

0001 /*
0002   SPDX-FileCopyrightText: 2012 Sérgio Martins <iamsergio@gmail.com>
0003 
0004   SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "itiphandler_p.h"
0008 #include "fetchjobcalendar.h"
0009 #include <KCalendarCore/Incidence>
0010 #include <KLocalizedString>
0011 #include <KMessageBox>
0012 using namespace Akonadi;
0013 
0014 ITIPHandlerPrivate::ITIPHandlerPrivate(ITIPHandlerComponentFactory *factory, ITIPHandler *qq)
0015     : m_factory(factory ? factory : new ITIPHandlerComponentFactory(this))
0016     , m_scheduler(new MailScheduler(m_factory, qq))
0017     , m_method(KCalendarCore::iTIPNoMethod)
0018     , m_helper(new ITIPHandlerHelper(m_factory))
0019     , m_currentOperation(OperationNone)
0020     , m_uiDelegate(nullptr)
0021     , q(qq)
0022 {
0023     m_helper->setParent(this);
0024     connect(m_scheduler, &Scheduler::transactionFinished, this, &ITIPHandlerPrivate::onSchedulerFinished);
0025 
0026     connect(m_helper, &ITIPHandlerHelper::finished, this, &ITIPHandlerPrivate::onHelperFinished);
0027 
0028     connect(m_helper, &ITIPHandlerHelper::sendIncidenceModifiedMessageFinished, this, &ITIPHandlerPrivate::onHelperModifyDialogClosed);
0029 }
0030 
0031 void ITIPHandlerPrivate::onSchedulerFinished(Akonadi::Scheduler::Result result, const QString &errorMessage)
0032 {
0033     if (m_currentOperation == OperationNone) {
0034         qCritical() << "Operation can't be none!" << result << errorMessage;
0035         return;
0036     }
0037 
0038     if (m_currentOperation == OperationProcessiTIPMessage) {
0039         m_currentOperation = OperationNone;
0040         finishProcessiTIPMessage(result, errorMessage);
0041     } else if (m_currentOperation == OperationSendiTIPMessage) {
0042         m_currentOperation = OperationNone;
0043         finishSendiTIPMessage(result, errorMessage);
0044     } else if (m_currentOperation == OperationPublishInformation) {
0045         m_currentOperation = OperationNone;
0046         finishPublishInformation(result, errorMessage);
0047     } else {
0048         Q_ASSERT(false);
0049         qCritical() << "Unknown operation" << m_currentOperation;
0050     }
0051 }
0052 
0053 void ITIPHandlerPrivate::onHelperFinished(Akonadi::ITIPHandlerHelper::SendResult result, const QString &errorMessage)
0054 {
0055     const bool success = result == ITIPHandlerHelper::ResultSuccess;
0056 
0057     if (m_currentOperation == OperationProcessiTIPMessage) {
0058         MailScheduler::Result result2 = success ? MailScheduler::ResultSuccess : MailScheduler::ResultGenericError;
0059         finishProcessiTIPMessage(result2, i18n("Error: %1", errorMessage));
0060     } else {
0061         Q_EMIT q->iTipMessageSent(success ? ITIPHandler::ResultSuccess : ITIPHandler::ResultError, success ? QString() : i18n("Error: %1", errorMessage));
0062     }
0063 }
0064 
0065 void ITIPHandlerPrivate::onCounterProposalDelegateFinished(bool success, const QString &errorMessage)
0066 {
0067     Q_UNUSED(success)
0068     Q_UNUSED(errorMessage)
0069     // This will be used when we make editing counter proposals async.
0070 }
0071 
0072 void ITIPHandlerPrivate::onLoadFinished(bool success, const QString &errorMessage)
0073 {
0074     if (m_currentOperation == OperationProcessiTIPMessage) {
0075         if (success) {
0076             // Harmless hack, processiTIPMessage() asserts that there's not current operation running
0077             // to prevent users from calling it twice.
0078             m_currentOperation = OperationNone;
0079             q->processiTIPMessage(m_queuedInvitation.receiver, m_queuedInvitation.iCal, m_queuedInvitation.action);
0080         } else {
0081             Q_EMIT q->iTipMessageProcessed(ITIPHandler::ResultError, i18n("Error loading calendar: %1", errorMessage));
0082         }
0083     } else if (m_currentOperation == OperationSendiTIPMessage) {
0084         q->sendiTIPMessage(m_queuedInvitation.method, m_queuedInvitation.incidence, m_parentWidget);
0085     } else if (!success) { // TODO
0086         m_calendarLoadError = true;
0087     }
0088 }
0089 
0090 void ITIPHandlerPrivate::finishProcessiTIPMessage(Akonadi::MailScheduler::Result result, const QString &errorMessage)
0091 {
0092     // Handle when user cancels on the collection selection dialog
0093     if (result == MailScheduler::ResultUserCancelled) {
0094         Q_EMIT q->iTipMessageProcessed(ITIPHandler::ResultCancelled, QString());
0095         return;
0096     }
0097 
0098     const bool success = result == MailScheduler::ResultSuccess;
0099 
0100     if (m_method == KCalendarCore::iTIPCounter) {
0101         // Here we're processing a counter-proposal that someone sent us and we're the organizer.
0102         // TODO: Shouldn't there be a test to see if we're the organizer?
0103         if (success) {
0104             // send update to all attendees
0105             Q_ASSERT(m_incidence);
0106             m_helper->setDialogParent(m_parentWidget);
0107             m_helper->sendIncidenceModifiedMessage(KCalendarCore::iTIPRequest, KCalendarCore::Incidence::Ptr(m_incidence->clone()), false);
0108             m_incidence.clear();
0109             return;
0110         } else {
0111             // fall through
0112         }
0113     }
0114 
0115     Q_EMIT q->iTipMessageProcessed(success ? ITIPHandler::ResultSuccess : ITIPHandler::ResultError, success ? QString() : i18n("Error: %1", errorMessage));
0116 }
0117 
0118 void ITIPHandlerPrivate::onHelperModifyDialogClosed(ITIPHandlerHelper::SendResult sendResult,
0119                                                     KCalendarCore::iTIPMethod /*method*/,
0120                                                     const KCalendarCore::Incidence::Ptr &)
0121 {
0122     if (sendResult == ITIPHandlerHelper::ResultNoSendingNeeded || sendResult == ITIPHandlerHelper::ResultCanceled) {
0123         Q_EMIT q->iTipMessageSent(ITIPHandler::ResultSuccess, QString());
0124     }
0125 }
0126 
0127 void ITIPHandlerPrivate::finishSendiTIPMessage(Akonadi::MailScheduler::Result result, const QString &errorMessage)
0128 {
0129     if (result == Scheduler::ResultSuccess) {
0130         if (m_parentWidget) {
0131             KMessageBox::information(m_parentWidget,
0132                                      i18n("The groupware message for item '%1' "
0133                                           "was successfully sent.\nMethod: %2",
0134                                           m_queuedInvitation.incidence->summary(),
0135                                           KCalendarCore::ScheduleMessage::methodName(m_queuedInvitation.method)),
0136                                      i18nc("@title:window", "Sending Free/Busy"),
0137                                      QStringLiteral("FreeBusyPublishSuccess"));
0138         }
0139         Q_EMIT q->iTipMessageSent(ITIPHandler::ResultSuccess, QString());
0140     } else {
0141         const QString error = i18nc(
0142             "Groupware message sending failed. "
0143             "%2 is request/reply/add/cancel/counter/etc.",
0144             "Unable to send the item '%1'.\nMethod: %2",
0145             m_queuedInvitation.incidence->summary(),
0146             KCalendarCore::ScheduleMessage::methodName(m_queuedInvitation.method));
0147         if (m_parentWidget) {
0148             KMessageBox::error(m_parentWidget, error);
0149         }
0150         qCritical() << "Groupware message sending failed." << error << errorMessage;
0151         Q_EMIT q->iTipMessageSent(ITIPHandler::ResultError, error + errorMessage);
0152     }
0153 }
0154 
0155 void ITIPHandlerPrivate::finishPublishInformation(Akonadi::MailScheduler::Result result, const QString &errorMessage)
0156 {
0157     if (result == Scheduler::ResultSuccess) {
0158         if (m_parentWidget) {
0159             KMessageBox::information(m_parentWidget,
0160                                      i18n("The item information was successfully sent."),
0161                                      i18nc("@title:window", "Publishing"),
0162                                      QStringLiteral("IncidencePublishSuccess"));
0163         }
0164         Q_EMIT q->informationPublished(ITIPHandler::ResultSuccess, QString());
0165     } else {
0166         const QString error = i18n("Unable to publish the item '%1'", m_queuedInvitation.incidence->summary());
0167         if (m_parentWidget) {
0168             KMessageBox::error(m_parentWidget, error);
0169         }
0170         qCritical() << "Publish failed." << error << errorMessage;
0171         Q_EMIT q->informationPublished(ITIPHandler::ResultError, error + errorMessage);
0172     }
0173 }
0174 
0175 void ITIPHandlerPrivate::finishSendAsICalendar(Akonadi::MailClient::Result result, const QString &errorMessage)
0176 {
0177     if (result == MailClient::ResultSuccess) {
0178         if (m_parentWidget) {
0179             KMessageBox::information(m_parentWidget,
0180                                      i18n("The item information was successfully sent."),
0181                                      i18nc("@title:window", "Forwarding"),
0182                                      QStringLiteral("IncidenceForwardSuccess"));
0183         }
0184         Q_EMIT q->sentAsICalendar(ITIPHandler::ResultSuccess, QString());
0185     } else {
0186         if (m_parentWidget) {
0187             KMessageBox::error(m_parentWidget,
0188                                i18n("Unable to forward the item '%1'", m_queuedInvitation.incidence->summary()),
0189                                i18nc("@title:window", "Forwarding Error"));
0190         }
0191         qCritical() << "Sent as iCalendar failed." << errorMessage;
0192         Q_EMIT q->sentAsICalendar(ITIPHandler::ResultError, errorMessage);
0193     }
0194 
0195     sender()->deleteLater(); // Delete the mailer
0196 }
0197 
0198 CalendarBase::Ptr ITIPHandlerPrivate::calendar()
0199 {
0200     if (!m_calendar) {
0201         FetchJobCalendar::Ptr fetchJobCalendar = FetchJobCalendar::Ptr(new FetchJobCalendar());
0202         connect(fetchJobCalendar.data(), &FetchJobCalendar::loadFinished, this, &ITIPHandlerPrivate::onLoadFinished);
0203 
0204         m_calendar = fetchJobCalendar;
0205     }
0206 
0207     return m_calendar;
0208 }
0209 
0210 bool ITIPHandlerPrivate::isLoaded()
0211 {
0212     FetchJobCalendar::Ptr fetchJobCalendar = calendar().dynamicCast<Akonadi::FetchJobCalendar>();
0213     if (fetchJobCalendar) {
0214         return !fetchJobCalendar->isLoading();
0215     }
0216 
0217     // If it's an ETMCalendar, set through setCalendar(), then it's already loaded, it's a requirement of setCalendar().
0218     // ETM doesn't have any way to check if it's already populated, so we have to require loaded calendars.
0219     return true;
0220 }
0221 
0222 #include "moc_itiphandler_p.cpp"