File indexing completed on 2024-04-28 05:11:36

0001 /*
0002  * SPDX-FileCopyrightText: 2014 Sandro Knauß <knauss@kolabsys.com>
0003  *
0004  * SPDX-License-Identifier: GPL-2.0-or-later WITH Qt-Commercial-exception-1.0
0005  */
0006 
0007 #include "individualmailcomponentfactory.h"
0008 #include "individualmaildialog.h"
0009 #include "opencomposerjob.h"
0010 
0011 #include <CalendarSupport/KCalPrefs>
0012 
0013 #include <KMessageBox>
0014 
0015 #include <QDBusConnection>
0016 #include <QDBusConnectionInterface>
0017 
0018 using namespace IncidenceEditorNG;
0019 
0020 // IndividualMessageQueueJob
0021 
0022 IndividualMessageQueueJob::IndividualMessageQueueJob(const KIdentityManagementCore::Identity &identity,
0023                                                      const KCalendarCore::Attendee::List &update,
0024                                                      const KCalendarCore::Attendee::List &edit,
0025                                                      QObject *parent)
0026     : Akonadi::MessageQueueJob(parent)
0027     , mUpdate(update)
0028     , mEdit(edit)
0029     , mIdentity(identity)
0030 {
0031 }
0032 
0033 void IndividualMessageQueueJob::start()
0034 {
0035     const auto to = addressAttribute().to();
0036     QSet<QString> attendeesTo(to.begin(), to.end());
0037     const auto cc = addressAttribute().cc();
0038     QSet<QString> attendeesCc(cc.begin(), cc.end());
0039 
0040     QStringList attendeesAutoTo;
0041     QStringList attendeesAutoCc;
0042     for (const KCalendarCore::Attendee &attendee : std::as_const(mUpdate)) {
0043         if (attendeesTo.contains(attendee.email())) {
0044             attendeesAutoTo.append(attendee.fullName());
0045         }
0046         if (attendeesCc.contains(attendee.email())) {
0047             attendeesAutoCc.append(attendee.fullName());
0048         }
0049     }
0050     if (!attendeesAutoTo.isEmpty() || !attendeesAutoCc.isEmpty() || !addressAttribute().bcc().isEmpty()) {
0051         startQueueJob(attendeesAutoTo, addressAttribute().to(), attendeesAutoCc, addressAttribute().cc());
0052     }
0053 
0054     QStringList attendeesComposerTo;
0055     QStringList attendeesComposerCc;
0056     for (const KCalendarCore::Attendee &attendee : std::as_const(mEdit)) {
0057         if (attendeesTo.contains(attendee.email())) {
0058             attendeesComposerTo.append(attendee.fullName());
0059         }
0060         if (attendeesCc.contains(attendee.email())) {
0061             attendeesComposerCc.append(attendee.fullName());
0062         }
0063     }
0064     if (!attendeesComposerTo.isEmpty() || !attendeesComposerCc.isEmpty()) {
0065         startComposerJob(attendeesComposerTo, attendeesComposerCc);
0066     }
0067 
0068     // No subjob has been started
0069     if (!mQueueJob && !mComposerJob) {
0070         emitResult();
0071     }
0072 }
0073 
0074 void IndividualMessageQueueJob::startQueueJob(const QStringList &messageTo, const QStringList &to, const QStringList &messageCc, const QStringList &cc)
0075 {
0076     KMime::Message::Ptr msg(message());
0077     msg->to()->fromUnicodeString(messageTo.join(QLatin1StringView(", ")), "utf-8");
0078     msg->cc()->fromUnicodeString(messageCc.join(QLatin1StringView(", ")), "utf-8");
0079     msg->assemble();
0080 
0081     mQueueJob = new Akonadi::MessageQueueJob(this);
0082     mQueueJob->setMessage(msg);
0083     mQueueJob->transportAttribute().setTransportId(mIdentity.isNull() ? transportAttribute().transportId() : mIdentity.transport().toInt());
0084     mQueueJob->addressAttribute().setFrom(addressAttribute().from());
0085     mQueueJob->addressAttribute().setTo(to);
0086     mQueueJob->addressAttribute().setCc(cc);
0087     mQueueJob->addressAttribute().setBcc(addressAttribute().bcc());
0088 
0089     if (mIdentity.disabledFcc()) {
0090         mQueueJob->sentBehaviourAttribute().setSentBehaviour(Akonadi::SentBehaviourAttribute::Delete);
0091     } else {
0092         const Akonadi::Collection sentCollection(mIdentity.fcc().toLongLong());
0093         if (sentCollection.isValid()) {
0094             mQueueJob->sentBehaviourAttribute().setSentBehaviour(Akonadi::SentBehaviourAttribute::MoveToCollection);
0095             mQueueJob->sentBehaviourAttribute().setMoveToCollection(sentCollection);
0096         } else {
0097             mQueueJob->sentBehaviourAttribute().setSentBehaviour(Akonadi::SentBehaviourAttribute::MoveToDefaultSentCollection);
0098         }
0099     }
0100 
0101     connect(mQueueJob, &Akonadi::MessageQueueJob::finished, this, &IndividualMessageQueueJob::handleJobFinished);
0102     mQueueJob->start();
0103 }
0104 
0105 void IndividualMessageQueueJob::startComposerJob(const QStringList &to, const QStringList &cc)
0106 {
0107     mComposerJob = new OpenComposerJob(this, to.join(QLatin1StringView(", ")), cc.join(QLatin1StringView(", ")), QString(), message(), mIdentity);
0108     connect(mComposerJob, &OpenComposerJob::finished, this, &IndividualMessageQueueJob::handleJobFinished);
0109     mComposerJob->start();
0110 }
0111 
0112 void IndividualMessageQueueJob::handleJobFinished(KJob *job)
0113 {
0114     if (job->error()) {
0115         if (job == mQueueJob && mComposerJob) {
0116             mComposerJob->kill();
0117             mComposerJob = nullptr;
0118         } else if (job == mComposerJob && mQueueJob) {
0119             mQueueJob->kill();
0120             mQueueJob = nullptr;
0121         }
0122         setError(job->error());
0123         setErrorText(job->errorString());
0124         emitResult();
0125         return;
0126     }
0127     if (job == mQueueJob) {
0128         if (!mComposerJob) {
0129             emitResult();
0130         }
0131         mQueueJob = nullptr;
0132     } else {
0133         if (!mQueueJob) {
0134             emitResult();
0135         }
0136         mComposerJob = nullptr;
0137     }
0138 }
0139 
0140 // IndividualMailAskDelegator
0141 
0142 IndividualMailITIPHandlerDialogDelegate::IndividualMailITIPHandlerDialogDelegate(const KCalendarCore::Incidence::Ptr &incidence,
0143                                                                                  KCalendarCore::iTIPMethod method,
0144                                                                                  QWidget *parent)
0145     : Akonadi::ITIPHandlerDialogDelegate(incidence, method, parent)
0146     , mDialog(nullptr)
0147 {
0148 }
0149 
0150 void IndividualMailITIPHandlerDialogDelegate::openDialog(const QString &question,
0151                                                          const KCalendarCore::Attendee::List &attendees,
0152                                                          Action action,
0153                                                          const KGuiItem &buttonYes,
0154                                                          const KGuiItem &buttonNo)
0155 {
0156     switch (action) {
0157     case ActionSendMessage:
0158         Q_EMIT setUpdate(mIncidence, attendees);
0159         Q_EMIT dialogClosed(KMessageBox::ButtonCode::PrimaryAction, mMethod, mIncidence);
0160         break;
0161     case ActionDontSendMessage:
0162         Q_EMIT dialogClosed(KMessageBox::ButtonCode::SecondaryAction, mMethod, mIncidence);
0163         break;
0164     default:
0165         switch (CalendarSupport::KCalPrefs::instance()->sendPolicy()) {
0166         case (CalendarSupport::KCalPrefs::InvitationPolicySend):
0167             Q_EMIT setUpdate(mIncidence, attendees);
0168             Q_EMIT dialogClosed(KMessageBox::ButtonCode::PrimaryAction, mMethod, mIncidence);
0169             break;
0170         case (CalendarSupport::KCalPrefs::InvitationPolicyDontSend):
0171             Q_EMIT dialogClosed(KMessageBox::ButtonCode::SecondaryAction, mMethod, mIncidence);
0172             break;
0173         case (CalendarSupport::KCalPrefs::InvitationPolicyAsk):
0174         default:
0175             mDialog = new IndividualMailDialog(question, attendees, buttonYes, buttonNo, mParent);
0176             connect(mDialog, &QDialog::finished, this, &IndividualMailITIPHandlerDialogDelegate::onDialogClosed);
0177             mDialog->show();
0178             break;
0179         }
0180         break;
0181     }
0182 }
0183 
0184 void IndividualMailITIPHandlerDialogDelegate::openDialogIncidenceCreated(Recipient recipient,
0185                                                                          const QString &question,
0186                                                                          Action action,
0187                                                                          const KGuiItem &buttonYes,
0188                                                                          const KGuiItem &buttonNo)
0189 {
0190     if (recipient == Attendees) {
0191         openDialog(question, mIncidence->attendees(), action, buttonYes, buttonNo);
0192     } else {
0193         KCalendarCore::Attendee organizer(mIncidence->organizer().name(), mIncidence->organizer().email());
0194         openDialog(question, KCalendarCore::Attendee::List() << organizer, action, buttonYes, buttonNo);
0195     }
0196 }
0197 
0198 void IndividualMailITIPHandlerDialogDelegate::openDialogIncidenceModified(bool attendeeStatusChanged,
0199                                                                           Recipient recipient,
0200                                                                           const QString &question,
0201                                                                           Action action,
0202                                                                           const KGuiItem &buttonYes,
0203                                                                           const KGuiItem &buttonNo)
0204 {
0205     Q_UNUSED(attendeeStatusChanged)
0206     if (recipient == Attendees) {
0207         openDialog(question, mIncidence->attendees(), action, buttonYes, buttonNo);
0208     } else {
0209         KCalendarCore::Attendee organizer(mIncidence->organizer().name(), mIncidence->organizer().email());
0210         openDialog(question, KCalendarCore::Attendee::List() << organizer, action, buttonYes, buttonNo);
0211     }
0212 }
0213 
0214 void IndividualMailITIPHandlerDialogDelegate::openDialogIncidenceDeleted(Recipient recipient,
0215                                                                          const QString &question,
0216                                                                          Action action,
0217                                                                          const KGuiItem &buttonYes,
0218                                                                          const KGuiItem &buttonNo)
0219 {
0220     if (recipient == Attendees) {
0221         openDialog(question, mIncidence->attendees(), action, buttonYes, buttonNo);
0222     } else {
0223         KCalendarCore::Attendee organizer(mIncidence->organizer().name(), mIncidence->organizer().email());
0224         openDialog(question, KCalendarCore::Attendee::List() << organizer, action, buttonYes, buttonNo);
0225     }
0226 }
0227 
0228 void IndividualMailITIPHandlerDialogDelegate::onDialogClosed(int result)
0229 {
0230     if (result == QDialogButtonBox::Yes) {
0231         Q_EMIT setEdit(mIncidence, mDialog->editAttendees());
0232         Q_EMIT setUpdate(mIncidence, mDialog->updateAttendees());
0233         Q_EMIT dialogClosed(KMessageBox::ButtonCode::PrimaryAction, mMethod, mIncidence);
0234     } else {
0235         Q_EMIT dialogClosed(KMessageBox::ButtonCode::SecondaryAction, mMethod, mIncidence);
0236     }
0237 }
0238 
0239 // IndividualMailJobFactory
0240 IndividualMailComponentFactory::IndividualMailComponentFactory(QObject *parent)
0241     : Akonadi::ITIPHandlerComponentFactory(parent)
0242 {
0243 }
0244 
0245 Akonadi::MessageQueueJob *IndividualMailComponentFactory::createMessageQueueJob(const KCalendarCore::IncidenceBase::Ptr &incidence,
0246                                                                                 const KIdentityManagementCore::Identity &identity,
0247                                                                                 QObject *parent)
0248 {
0249     return new IndividualMessageQueueJob(identity, mUpdate.take(incidence->uid()), mEdit.take(incidence->uid()), parent);
0250 }
0251 
0252 Akonadi::ITIPHandlerDialogDelegate *IndividualMailComponentFactory::createITIPHanderDialogDelegate(const KCalendarCore::Incidence::Ptr &incidence,
0253                                                                                                    KCalendarCore::iTIPMethod method,
0254                                                                                                    QWidget *parent)
0255 {
0256     auto askDelegator = new IndividualMailITIPHandlerDialogDelegate(incidence, method, parent);
0257     connect(askDelegator, &IndividualMailITIPHandlerDialogDelegate::setEdit, this, &IndividualMailComponentFactory::onSetEdit);
0258     connect(askDelegator, &IndividualMailITIPHandlerDialogDelegate::setUpdate, this, &IndividualMailComponentFactory::onSetUpdate);
0259 
0260     return askDelegator;
0261 }
0262 
0263 void IndividualMailComponentFactory::onSetEdit(const KCalendarCore::Incidence::Ptr &incidence, const KCalendarCore::Attendee::List &edit)
0264 {
0265     mEdit[incidence->uid()] = edit;
0266 }
0267 
0268 void IndividualMailComponentFactory::onSetUpdate(const KCalendarCore::Incidence::Ptr &incidence, const KCalendarCore::Attendee::List &update)
0269 {
0270     mUpdate[incidence->uid()] = update;
0271 }
0272 
0273 #include "moc_individualmailcomponentfactory.cpp"