messageactions.cpp 29.6 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/*
    Copyright (c) 2007 Volker Krause <vkrause@kde.org>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

#include "messageactions.h"

Laurent Montel's avatar
Laurent Montel committed
21
#include "settings/kmailsettings.h"
22
#include "kmreaderwin.h"
Stephen Kelly's avatar
Stephen Kelly committed
23
#include "kmkernel.h"
Laurent Montel's avatar
Laurent Montel committed
24
#include "mailcommon/mailkernel.h"
25
#include "kmmainwidget.h"
Stephen Kelly's avatar
Stephen Kelly committed
26
#include "util.h"
27
#include "kmcommands.h"
28
#include <TemplateParser/CustomTemplatesMenu>
29

Laurent Montel's avatar
Laurent Montel committed
30
#include <PimCommonAkonadi/AnnotationDialog>
Laurent Montel's avatar
Laurent Montel committed
31
#include <MessageCore/MessageCoreSettings>
Laurent Montel's avatar
Laurent Montel committed
32
#include "MessageCore/MailingList"
Laurent Montel's avatar
Laurent Montel committed
33
#include <MessageCore/StringUtil>
34
#include "messageviewer/messageviewersettings.h"
Laurent Montel's avatar
Laurent Montel committed
35
#include "messageviewer/headerstyleplugin.h"
36

Laurent Montel's avatar
Laurent Montel committed
37
#include <AkonadiCore/itemfetchjob.h>
38
#include <Akonadi/KMime/MessageParts>
Laurent Montel's avatar
Laurent Montel committed
39
#include <AkonadiCore/ChangeRecorder>
Laurent Montel's avatar
Laurent Montel committed
40
#include <QAction>
Laurent Montel's avatar
Laurent Montel committed
41
#include <AkonadiSearch/Debug/akonadisearchdebugdialog.h>
42
#include <KIO/KUriFilterSearchProviderActions>
43

44
#include "messagecomposer/followupreminderselectdatedialog.h"
45
46
#include "job/createfollowupreminderonexistingmessagejob.h"

47
#include <AkonadiCore/ItemFetchJob>
48
49
#include <KActionMenu>
#include <KActionCollection>
Laurent Montel's avatar
Laurent Montel committed
50
#include "kmail_debug.h"
Laurent Montel's avatar
Laurent Montel committed
51
#include <KLocalizedString>
52
#include <KXMLGUIClient>
53
#include <KRun>
Laurent Montel's avatar
Laurent Montel committed
54
#include <QMenu>
55
#include <KUriFilter>
Laurent Montel's avatar
Laurent Montel committed
56
#include <KStringHandler>
Laurent Montel's avatar
Laurent Montel committed
57
#include <QIcon>
58
#include <QFileDialog>
59

60
#include <QVariant>
Laurent Montel's avatar
Laurent Montel committed
61
#include <QWidget>
Laurent Montel's avatar
Laurent Montel committed
62
#include <AkonadiCore/collection.h>
Laurent Montel's avatar
Laurent Montel committed
63
#include <AkonadiCore/entityannotationsattribute.h>
Laurent Montel's avatar
Laurent Montel committed
64
#include <mailcommon/mailutil.h>
65
66
67

using namespace KMail;

Laurent Montel's avatar
Laurent Montel committed
68
MessageActions::MessageActions(KActionCollection *ac, QWidget *parent)
Laurent Montel's avatar
Laurent Montel committed
69
70
    : QObject(parent)
    , mParent(parent)
71
{
72
    mWebShortcutMenuManager = new KIO::KUriFilterSearchProviderActions(this);
73
74
    mReplyActionMenu = new KActionMenu(QIcon::fromTheme(QStringLiteral("mail-reply-sender")), i18nc("Message->", "&Reply"), this);
    ac->addAction(QStringLiteral("message_reply_menu"), mReplyActionMenu);
Laurent Montel's avatar
Laurent Montel committed
75
    connect(mReplyActionMenu, &KActionMenu::triggered, this, &MessageActions::slotReplyToMsg);
Laurent Montel's avatar
Laurent Montel committed
76

77
78
    mReplyAction = new QAction(QIcon::fromTheme(QStringLiteral("mail-reply-sender")), i18n("&Reply..."), this);
    ac->addAction(QStringLiteral("reply"), mReplyAction);
Laurent Montel's avatar
Laurent Montel committed
79
    ac->setDefaultShortcut(mReplyAction, Qt::Key_R);
Laurent Montel's avatar
Laurent Montel committed
80
    connect(mReplyAction, &QAction::triggered, this, &MessageActions::slotReplyToMsg);
Laurent Montel's avatar
Laurent Montel committed
81
    mReplyActionMenu->addAction(mReplyAction);
Laurent Montel's avatar
Laurent Montel committed
82

83
84
    mReplyAuthorAction = new QAction(QIcon::fromTheme(QStringLiteral("mail-reply-sender")), i18n("Reply to A&uthor..."), this);
    ac->addAction(QStringLiteral("reply_author"), mReplyAuthorAction);
Laurent Montel's avatar
Laurent Montel committed
85
    ac->setDefaultShortcut(mReplyAuthorAction, Qt::SHIFT + Qt::Key_A);
Laurent Montel's avatar
Laurent Montel committed
86
    connect(mReplyAuthorAction, &QAction::triggered, this, &MessageActions::slotReplyAuthorToMsg);
Laurent Montel's avatar
Laurent Montel committed
87
    mReplyActionMenu->addAction(mReplyAuthorAction);
Laurent Montel's avatar
Laurent Montel committed
88

89
90
    mReplyAllAction = new QAction(QIcon::fromTheme(QStringLiteral("mail-reply-all")), i18n("Reply to &All..."), this);
    ac->addAction(QStringLiteral("reply_all"), mReplyAllAction);
Laurent Montel's avatar
Laurent Montel committed
91
    ac->setDefaultShortcut(mReplyAllAction, Qt::Key_A);
Laurent Montel's avatar
Laurent Montel committed
92
    connect(mReplyAllAction, &QAction::triggered, this, &MessageActions::slotReplyAllToMsg);
Laurent Montel's avatar
Laurent Montel committed
93
    mReplyActionMenu->addAction(mReplyAllAction);
Laurent Montel's avatar
Laurent Montel committed
94

95
96
    mReplyListAction = new QAction(QIcon::fromTheme(QStringLiteral("mail-reply-list")), i18n("Reply to Mailing-&List..."), this);
    ac->addAction(QStringLiteral("reply_list"), mReplyListAction);
Laurent Montel's avatar
Laurent Montel committed
97
98

    ac->setDefaultShortcut(mReplyListAction, Qt::Key_L);
Laurent Montel's avatar
Laurent Montel committed
99
    connect(mReplyListAction, &QAction::triggered, this, &MessageActions::slotReplyListToMsg);
Laurent Montel's avatar
Laurent Montel committed
100
    mReplyActionMenu->addAction(mReplyListAction);
Laurent Montel's avatar
Laurent Montel committed
101

Laurent Montel's avatar
Laurent Montel committed
102
    mNoQuoteReplyAction = new QAction(i18n("Reply Without &Quote..."), this);
103
    ac->addAction(QStringLiteral("noquotereply"), mNoQuoteReplyAction);
Laurent Montel's avatar
Laurent Montel committed
104
    ac->setDefaultShortcut(mNoQuoteReplyAction, Qt::SHIFT + Qt::Key_R);
Laurent Montel's avatar
Laurent Montel committed
105
    connect(mNoQuoteReplyAction, &QAction::triggered, this, &MessageActions::slotNoQuoteReplyToMsg);
Laurent Montel's avatar
Laurent Montel committed
106

Laurent Montel's avatar
Laurent Montel committed
107
    mListFilterAction = new QAction(i18n("Filter on Mailing-&List..."), this);
108
    ac->addAction(QStringLiteral("mlist_filter"), mListFilterAction);
Laurent Montel's avatar
Laurent Montel committed
109
    connect(mListFilterAction, &QAction::triggered, this, &MessageActions::slotMailingListFilter);
Laurent Montel's avatar
Laurent Montel committed
110

Laurent Montel's avatar
Laurent Montel committed
111
    mStatusMenu = new KActionMenu(i18n("Mar&k Message"), this);
112
    ac->addAction(QStringLiteral("set_status"), mStatusMenu);
Laurent Montel's avatar
Laurent Montel committed
113

Laurent Montel's avatar
Laurent Montel committed
114
115
116
117
    KMMainWidget *mainwin = kmkernel->getKMMainWidget();
    if (mainwin) {
        QAction *action = mainwin->akonadiStandardAction(Akonadi::StandardMailActionManager::MarkMailAsRead);
        mStatusMenu->addAction(action);
Laurent Montel's avatar
Laurent Montel committed
118

Laurent Montel's avatar
Laurent Montel committed
119
120
        action = mainwin->akonadiStandardAction(Akonadi::StandardMailActionManager::MarkMailAsUnread);
        mStatusMenu->addAction(action);
Laurent Montel's avatar
Laurent Montel committed
121
122

        mStatusMenu->addSeparator();
Laurent Montel's avatar
Laurent Montel committed
123
124
        action = mainwin->akonadiStandardAction(Akonadi::StandardMailActionManager::MarkMailAsImportant);
        mStatusMenu->addAction(action);
Laurent Montel's avatar
Laurent Montel committed
125

Laurent Montel's avatar
Laurent Montel committed
126
127
        action = mainwin->akonadiStandardAction(Akonadi::StandardMailActionManager::MarkMailAsActionItem);
        mStatusMenu->addAction(action);
Laurent Montel's avatar
Laurent Montel committed
128
129
    }

130
131
    mAnnotateAction = new QAction(QIcon::fromTheme(QStringLiteral("view-pim-notes")), i18n("Add Note..."), this);
    ac->addAction(QStringLiteral("annotate"), mAnnotateAction);
Laurent Montel's avatar
Laurent Montel committed
132
    connect(mAnnotateAction, &QAction::triggered, this, &MessageActions::annotateMessage);
Laurent Montel's avatar
Laurent Montel committed
133

134
    mEditAsNewAction = new QAction(QIcon::fromTheme(QStringLiteral("document-edit")), i18n("&Edit As New"), this);
Laurent Montel's avatar
Laurent Montel committed
135
136
137
138
    ac->addAction(QStringLiteral("editasnew"), mEditAsNewAction);
    connect(mEditAsNewAction, &QAction::triggered, this, &MessageActions::editCurrentMessage);
    ac->setDefaultShortcut(mEditAsNewAction, Qt::Key_T);

Laurent Montel's avatar
Laurent Montel committed
139
140
    mPrintAction = KStandardAction::print(this, &MessageActions::slotPrintMessage, ac);
    mPrintPreviewAction = KStandardAction::printPreview(this, &MessageActions::slotPrintPreviewMsg, ac);
Laurent Montel's avatar
Laurent Montel committed
141

Laurent Montel's avatar
Laurent Montel committed
142
    mForwardActionMenu = new KActionMenu(QIcon::fromTheme(QStringLiteral("mail-forward")), i18nc("Message->", "&Forward"), this);
143
    ac->addAction(QStringLiteral("message_forward"), mForwardActionMenu);
Laurent Montel's avatar
Laurent Montel committed
144

145
    mForwardAttachedAction = new QAction(QIcon::fromTheme(QStringLiteral("mail-forward")),
Laurent Montel's avatar
Laurent Montel committed
146
                                         i18nc("@action:inmenu Message->Forward->",
Laurent Montel's avatar
Laurent Montel committed
147
                                               "As &Attachment..."),
Laurent Montel's avatar
Laurent Montel committed
148
                                         this);
Laurent Montel's avatar
Laurent Montel committed
149
    connect(mForwardAttachedAction, SIGNAL(triggered(bool)), parent, SLOT(slotForwardAttachedMessage()));
Laurent Montel's avatar
Laurent Montel committed
150

151
    ac->addAction(QStringLiteral("message_forward_as_attachment"), mForwardAttachedAction);
Laurent Montel's avatar
Laurent Montel committed
152

153
    mForwardInlineAction = new QAction(QIcon::fromTheme(QStringLiteral("mail-forward")),
Laurent Montel's avatar
Laurent Montel committed
154
                                       i18nc("@action:inmenu Message->Forward->",
Laurent Montel's avatar
Laurent Montel committed
155
                                             "&Inline..."),
Laurent Montel's avatar
Laurent Montel committed
156
157
                                       this);
    connect(mForwardInlineAction, SIGNAL(triggered(bool)), parent, SLOT(slotForwardInlineMsg()));
Laurent Montel's avatar
Laurent Montel committed
158

159
    ac->addAction(QStringLiteral("message_forward_inline"), mForwardInlineAction);
Laurent Montel's avatar
Laurent Montel committed
160

Laurent Montel's avatar
Laurent Montel committed
161
    setupForwardActions(ac);
Laurent Montel's avatar
Laurent Montel committed
162

Laurent Montel's avatar
Laurent Montel committed
163
    mRedirectAction = new QAction(i18nc("Message->Forward->", "&Redirect..."), this);
164
    ac->addAction(QStringLiteral("message_forward_redirect"), mRedirectAction);
Laurent Montel's avatar
Laurent Montel committed
165
    connect(mRedirectAction, SIGNAL(triggered(bool)), parent, SLOT(slotRedirectMessage()));
Laurent Montel's avatar
Laurent Montel committed
166

Laurent Montel's avatar
Laurent Montel committed
167
168
    ac->setDefaultShortcut(mRedirectAction, QKeySequence(Qt::Key_E));
    mForwardActionMenu->addAction(mRedirectAction);
Laurent Montel's avatar
Laurent Montel committed
169

Laurent Montel's avatar
Laurent Montel committed
170
    mMailingListActionMenu = new KActionMenu(QIcon::fromTheme(QStringLiteral("mail-message-new-list")), i18nc("Message->", "Mailing-&List"), this);
Laurent Montel's avatar
Laurent Montel committed
171
    connect(mMailingListActionMenu->menu(), &QMenu::triggered, this, &MessageActions::slotRunUrl);
172
    ac->addAction(QStringLiteral("mailing_list"), mMailingListActionMenu);
Laurent Montel's avatar
Laurent Montel committed
173
174
    mMailingListActionMenu->setEnabled(false);

175
176
    connect(kmkernel->folderCollectionMonitor(), &Akonadi::Monitor::itemChanged, this, &MessageActions::slotItemModified);
    connect(kmkernel->folderCollectionMonitor(), &Akonadi::Monitor::itemRemoved, this, &MessageActions::slotItemRemoved);
Laurent Montel's avatar
Laurent Montel committed
177

Laurent Montel's avatar
Laurent Montel committed
178
    mCustomTemplatesMenu = new TemplateParser::CustomTemplatesMenu(parent, ac);
Laurent Montel's avatar
Laurent Montel committed
179

Laurent Montel's avatar
Laurent Montel committed
180
181
182
    connect(mCustomTemplatesMenu, SIGNAL(replyTemplateSelected(QString)), parent, SLOT(slotCustomReplyToMsg(QString)));
    connect(mCustomTemplatesMenu, SIGNAL(replyAllTemplateSelected(QString)), parent, SLOT(slotCustomReplyAllToMsg(QString)));
    connect(mCustomTemplatesMenu, SIGNAL(forwardTemplateSelected(QString)), parent, SLOT(slotCustomForwardMsg(QString)));
Laurent Montel's avatar
Laurent Montel committed
183
    connect(KMKernel::self(), &KMKernel::customTemplatesChanged, mCustomTemplatesMenu, &TemplateParser::CustomTemplatesMenu::update);
Laurent Montel's avatar
Laurent Montel committed
184

Laurent Montel's avatar
Laurent Montel committed
185
    forwardMenu()->addSeparator();
Laurent Montel's avatar
Laurent Montel committed
186
    forwardMenu()->addAction(mCustomTemplatesMenu->forwardActionMenu());
Laurent Montel's avatar
Laurent Montel committed
187
    replyMenu()->addSeparator();
Laurent Montel's avatar
Laurent Montel committed
188
189
    replyMenu()->addAction(mCustomTemplatesMenu->replyActionMenu());
    replyMenu()->addAction(mCustomTemplatesMenu->replyAllActionMenu());
Laurent Montel's avatar
Laurent Montel committed
190

Laurent Montel's avatar
Laurent Montel committed
191
192
193
    //Don't translate it. Shown only when we set env variable AKONADI_SEARCH_DEBUG
    mDebugAkonadiSearchAction = new QAction(QStringLiteral("Debug Akonadi Search..."), this);
    connect(mDebugAkonadiSearchAction, &QAction::triggered, this, &MessageActions::slotDebugAkonadiSearch);
194

Laurent Montel's avatar
Laurent Montel committed
195
    mAddFollowupReminderAction = new QAction(i18n("Add Followup Reminder..."), this);
196
    ac->addAction(QStringLiteral("message_followup_reminder"), mAddFollowupReminderAction);
197
    connect(mAddFollowupReminderAction, &QAction::triggered, this, &MessageActions::slotAddFollowupReminder);
198

199
200
201
202
    mSendAgainAction = new QAction(i18n("Send A&gain..."), this);
    ac->addAction(QStringLiteral("send_again"), mSendAgainAction);
    connect(mSendAgainAction, &QAction::triggered, this, &MessageActions::slotResendMessage);

Laurent Montel's avatar
Laurent Montel committed
203
204
205
206
207
    mNewMessageFromTemplateAction = new QAction(QIcon::fromTheme(QStringLiteral("document-new")), i18n("New Message From &Template"), this);
    ac->addAction(QStringLiteral("use_template"), mNewMessageFromTemplateAction);
    connect(mNewMessageFromTemplateAction, &QAction::triggered, this, &MessageActions::slotUseTemplate);
    ac->setDefaultShortcut(mNewMessageFromTemplateAction, QKeySequence(Qt::SHIFT + Qt::Key_N));

208
209
210
211
    mExportToPdfAction = new QAction(QIcon::fromTheme(QStringLiteral("application-pdf")), i18n("Export to PDF..."), this);
    ac->addAction(QStringLiteral("file_export_pdf"), mExportToPdfAction);
    connect(mExportToPdfAction, &QAction::triggered, this, &MessageActions::slotExportToPdf);

Laurent Montel's avatar
Laurent Montel committed
212
    updateActions();
213
214
}

Laurent Montel's avatar
Laurent Montel committed
215
216
MessageActions::~MessageActions()
{
Laurent Montel's avatar
Laurent Montel committed
217
    delete mCustomTemplatesMenu;
Laurent Montel's avatar
Laurent Montel committed
218
219
}

Laurent Montel's avatar
Laurent Montel committed
220
TemplateParser::CustomTemplatesMenu *MessageActions::customTemplatesMenu() const
221
{
Laurent Montel's avatar
Laurent Montel committed
222
    return mCustomTemplatesMenu;
223
224
}

Laurent Montel's avatar
Laurent Montel committed
225
226
227
228
229
230
231
232
233
void MessageActions::slotUseTemplate()
{
    if (!mCurrentItem.isValid()) {
        return;
    }
    KMCommand *command = new KMUseTemplateCommand(mParent, mCurrentItem);
    command->start();
}

Laurent Montel's avatar
Laurent Montel committed
234
235
236
237
238
QAction *MessageActions::editAsNewAction() const
{
    return mEditAsNewAction;
}

Laurent Montel's avatar
Laurent Montel committed
239
void MessageActions::setCurrentMessage(const Akonadi::Item &msg, const Akonadi::Item::List &items)
240
{
Laurent Montel's avatar
Laurent Montel committed
241
    mCurrentItem = msg;
Laurent Montel's avatar
Laurent Montel committed
242

Laurent Montel's avatar
Laurent Montel committed
243
    if (!items.isEmpty()) {
Laurent Montel's avatar
Laurent Montel committed
244
        if (msg.isValid()) {
Laurent Montel's avatar
Laurent Montel committed
245
            mVisibleItems = items;
Laurent Montel's avatar
Laurent Montel committed
246
247
        } else {
            mVisibleItems.clear();
Laurent Montel's avatar
Laurent Montel committed
248
        }
249
    }
Laurent Montel's avatar
Laurent Montel committed
250

Laurent Montel's avatar
Laurent Montel committed
251
    if (!msg.isValid()) {
252
        mVisibleItems.clear();
Laurent Montel's avatar
Laurent Montel committed
253
        clearMailingListActions();
254
    }
255

Laurent Montel's avatar
Laurent Montel committed
256
    updateActions();
257
258
}

259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
KActionMenu *MessageActions::replyMenu() const
{
    return mReplyActionMenu;
}

QAction *MessageActions::replyListAction() const
{
    return mReplyListAction;
}

QAction *MessageActions::forwardInlineAction() const
{
    return mForwardInlineAction;
}

QAction *MessageActions::forwardAttachedAction() const
{
    return mForwardAttachedAction;
}

QAction *MessageActions::redirectAction() const
{
    return mRedirectAction;
}

KActionMenu *MessageActions::messageStatusMenu() const
{
    return mStatusMenu;
}

KActionMenu *MessageActions::forwardMenu() const
{
    return mForwardActionMenu;
}

QAction *MessageActions::annotateAction() const
{
    return mAnnotateAction;
}

QAction *MessageActions::printAction() const
{
    return mPrintAction;
}

QAction *MessageActions::printPreviewAction() const
{
    return mPrintPreviewAction;
}

QAction *MessageActions::listFilterAction() const
{
    return mListFilterAction;
}

KActionMenu *MessageActions::mailingListActionMenu() const
{
    return mMailingListActionMenu;
}

Laurent Montel's avatar
Laurent Montel committed
319
void MessageActions::slotItemRemoved(const Akonadi::Item &item)
320
{
Laurent Montel's avatar
Laurent Montel committed
321
    if (item == mCurrentItem) {
Laurent Montel's avatar
Laurent Montel committed
322
323
324
        mCurrentItem = Akonadi::Item();
        updateActions();
    }
325
326
}

Laurent Montel's avatar
Laurent Montel committed
327
void MessageActions::slotItemModified(const Akonadi::Item &item, const QSet< QByteArray > &partIdentifiers)
328
{
Laurent Montel's avatar
Laurent Montel committed
329
330
    Q_UNUSED(partIdentifiers);
    if (item == mCurrentItem) {
Laurent Montel's avatar
Laurent Montel committed
331
332
        mCurrentItem = item;
        const int numberOfVisibleItems = mVisibleItems.count();
Laurent Montel's avatar
Laurent Montel committed
333
        for (int i = 0; i < numberOfVisibleItems; ++i) {
Laurent Montel's avatar
Laurent Montel committed
334
            Akonadi::Item it = mVisibleItems.at(i);
Laurent Montel's avatar
Laurent Montel committed
335
            if (item == it) {
Laurent Montel's avatar
Laurent Montel committed
336
337
338
339
                mVisibleItems[i] = item;
            }
        }
        updateActions();
340
    }
341
342
}

343
344
void MessageActions::updateActions()
{
Laurent Montel's avatar
Laurent Montel committed
345
346
347
    const bool hasPayload = mCurrentItem.hasPayload<KMime::Message::Ptr>();
    bool itemValid = mCurrentItem.isValid();
    Akonadi::Collection parent;
Laurent Montel's avatar
Laurent Montel committed
348
    if (itemValid) { //=> valid
Laurent Montel's avatar
Laurent Montel committed
349
        parent = mCurrentItem.parentCollection();
Laurent Montel's avatar
Laurent Montel committed
350
351
352
    }
    if (parent.isValid()) {
        if (CommonKernel->folderIsTemplates(parent)) {
Laurent Montel's avatar
Laurent Montel committed
353
            itemValid = false;
Laurent Montel's avatar
Laurent Montel committed
354
        }
Laurent Montel's avatar
Laurent Montel committed
355
356
    }

Laurent Montel's avatar
Laurent Montel committed
357
    const bool multiVisible = !mVisibleItems.isEmpty() || mCurrentItem.isValid();
Laurent Montel's avatar
Laurent Montel committed
358
359
360
361
362
363
364
365
366
367
    const bool uniqItem = (itemValid || hasPayload) && (mVisibleItems.count() <= 1);
    mReplyActionMenu->setEnabled(hasPayload);
    mReplyAction->setEnabled(hasPayload);
    mNoQuoteReplyAction->setEnabled(hasPayload);
    mReplyAuthorAction->setEnabled(hasPayload);
    mReplyAllAction->setEnabled(hasPayload);
    mReplyListAction->setEnabled(hasPayload);
    mNoQuoteReplyAction->setEnabled(hasPayload);

    mAnnotateAction->setEnabled(uniqItem);
368
    mAddFollowupReminderAction->setEnabled(uniqItem);
Laurent Montel's avatar
Laurent Montel committed
369
370
371
372
373
374
375
376
    if (!mCurrentItem.hasAttribute<Akonadi::EntityAnnotationsAttribute>()) {
        mAnnotateAction->setText(i18n("Add Note..."));
    } else {
        mAnnotateAction->setText(i18n("Edit Note..."));
    }

    mStatusMenu->setEnabled(multiVisible);

377
378
379
    mPrintAction->setEnabled(mMessageView != nullptr);
    mPrintPreviewAction->setEnabled(mMessageView != nullptr);

Laurent Montel's avatar
Laurent Montel committed
380
381
382
    if (mCurrentItem.hasPayload<KMime::Message::Ptr>()) {
        if (mCurrentItem.loadedPayloadParts().contains("RFC822")) {
            updateMailingListActions(mCurrentItem);
Laurent Montel's avatar
Laurent Montel committed
383
        } else {
Laurent Montel's avatar
Laurent Montel committed
384
            Akonadi::ItemFetchJob *job = new Akonadi::ItemFetchJob(mCurrentItem);
Laurent Montel's avatar
Laurent Montel committed
385
            job->fetchScope().fetchAllAttributes();
Laurent Montel's avatar
Laurent Montel committed
386
387
            job->fetchScope().fetchFullPayload(true);
            job->fetchScope().fetchPayloadPart(Akonadi::MessagePart::Header);
388
            job->fetchScope().fetchAttribute<Akonadi::EntityAnnotationsAttribute>();
Laurent Montel's avatar
Laurent Montel committed
389
            connect(job, &Akonadi::ItemFetchJob::result, this, &MessageActions::slotUpdateActionsFetchDone);
Laurent Montel's avatar
Laurent Montel committed
390
        }
391
    }
Laurent Montel's avatar
Laurent Montel committed
392
    mEditAsNewAction->setEnabled(uniqItem);
393
}
394

Laurent Montel's avatar
Laurent Montel committed
395
void MessageActions::slotUpdateActionsFetchDone(KJob *job)
396
{
Laurent Montel's avatar
Laurent Montel committed
397
    if (job->error()) {
Laurent Montel's avatar
Laurent Montel committed
398
        return;
Laurent Montel's avatar
Laurent Montel committed
399
    }
400

Laurent Montel's avatar
Laurent Montel committed
401
402
    Akonadi::ItemFetchJob *fetchJob = static_cast<Akonadi::ItemFetchJob *>(job);
    if (fetchJob->items().isEmpty()) {
Laurent Montel's avatar
Laurent Montel committed
403
        return;
Laurent Montel's avatar
Laurent Montel committed
404
    }
405
    const Akonadi::Item messageItem = fetchJob->items().constFirst();
Laurent Montel's avatar
Laurent Montel committed
406
    if (messageItem == mCurrentItem) {
Laurent Montel's avatar
Laurent Montel committed
407
        mCurrentItem = messageItem;
Laurent Montel's avatar
Laurent Montel committed
408
        updateMailingListActions(messageItem);
Laurent Montel's avatar
Laurent Montel committed
409
    }
410
411
}

412
413
void MessageActions::clearMailingListActions()
{
Laurent Montel's avatar
Laurent Montel committed
414
415
416
    mMailingListActionMenu->setEnabled(false);
    mListFilterAction->setEnabled(false);
    mListFilterAction->setText(i18n("Filter on Mailing-List..."));
417
418
}

Laurent Montel's avatar
Laurent Montel committed
419
void MessageActions::updateMailingListActions(const Akonadi::Item &messageItem)
420
{
Laurent Montel's avatar
Laurent Montel committed
421
422
423
    if (!messageItem.hasPayload<KMime::Message::Ptr>()) {
        return;
    }
Laurent Montel's avatar
Laurent Montel committed
424
    KMime::Message::Ptr message = messageItem.payload<KMime::Message::Ptr>();
Laurent Montel's avatar
Laurent Montel committed
425
    const MessageCore::MailingList mailList = MessageCore::MailingList::detect(message);
Laurent Montel's avatar
Laurent Montel committed
426

Laurent Montel's avatar
Laurent Montel committed
427
    if (mailList.features() == MessageCore::MailingList::None) {
Laurent Montel's avatar
Laurent Montel committed
428
429
430
431
432
        clearMailingListActions();
    } else {
        // A mailing list menu with only a title is pretty boring
        // so make sure theres at least some content
        QString listId;
Laurent Montel's avatar
Laurent Montel committed
433
        if (mailList.features() & MessageCore::MailingList::Id) {
Laurent Montel's avatar
Laurent Montel committed
434
435
436
            // From a list-id in the form, "Birds of France <bof.yahoo.com>",
            // take "Birds of France" if it exists otherwise "bof.yahoo.com".
            listId = mailList.id();
Laurent Montel's avatar
Laurent Montel committed
437
438
439
440
441
442
443
            const int start = listId.indexOf(QLatin1Char('<'));
            if (start > 0) {
                listId.truncate(start - 1);
            } else if (start == 0) {
                const int end = listId.lastIndexOf(QLatin1Char('>'));
                if (end < 1) {   // shouldn't happen but account for it anyway
                    listId.remove(0, 1);
Laurent Montel's avatar
Laurent Montel committed
444
                } else {
Laurent Montel's avatar
Laurent Montel committed
445
                    listId = listId.mid(1, end - 1);
Laurent Montel's avatar
Laurent Montel committed
446
447
448
449
450
451
                }
            }
        }
        mMailingListActionMenu->menu()->clear();
        qDeleteAll(mMailListActionList);
        mMailListActionList.clear();
452
        mMailingListActionMenu->menu()->setTitle(KStringHandler::rsqueeze(i18n("Mailing List Name: %1", (listId.isEmpty() ? i18n("<unknown>") : listId)), 40));
Laurent Montel's avatar
Laurent Montel committed
453
        if (mailList.features() & MessageCore::MailingList::ArchivedAt) {
Laurent Montel's avatar
Laurent Montel committed
454
            // IDEA: this may be something you want to copy - "Copy in submenu"?
Laurent Montel's avatar
Laurent Montel committed
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
            addMailingListActions(i18n("Open Message in List Archive"), mailList.archivedAtUrls());
        }
        if (mailList.features() & MessageCore::MailingList::Post) {
            addMailingListActions(i18n("Post New Message"), mailList.postUrls());
        }
        if (mailList.features() & MessageCore::MailingList::Archive) {
            addMailingListActions(i18n("Go to Archive"), mailList.archiveUrls());
        }
        if (mailList.features() & MessageCore::MailingList::Help) {
            addMailingListActions(i18n("Request Help"), mailList.helpUrls());
        }
        if (mailList.features() & MessageCore::MailingList::Owner) {
            addMailingListActions(i18nc("Contact the owner of the mailing list", "Contact Owner"), mailList.ownerUrls());
        }
        if (mailList.features() & MessageCore::MailingList::Subscribe) {
            addMailingListActions(i18n("Subscribe to List"), mailList.subscribeUrls());
        }
        if (mailList.features() & MessageCore::MailingList::Unsubscribe) {
            addMailingListActions(i18n("Unsubscribe from List"), mailList.unsubscribeUrls());
        }
        mMailingListActionMenu->setEnabled(true);
Laurent Montel's avatar
Laurent Montel committed
476
477
478

        QByteArray name;
        QString value;
Laurent Montel's avatar
Laurent Montel committed
479
480
481
482
        const QString lname = MailingList::name(message, name, value);
        if (!lname.isEmpty()) {
            mListFilterAction->setEnabled(true);
            mListFilterAction->setText(i18n("Filter on Mailing-List %1...", lname));
483
        }
484
    }
485
486
}

Laurent Montel's avatar
Laurent Montel committed
487
void MessageActions::replyCommand(MessageComposer::ReplyStrategy strategy)
Thomas McGuire's avatar
Thomas McGuire committed
488
{
Laurent Montel's avatar
Laurent Montel committed
489
490
491
    if (!mCurrentItem.hasPayload<KMime::Message::Ptr>()) {
        return;
    }
492

Laurent Montel's avatar
Laurent Montel committed
493
    const QString text = mMessageView ? mMessageView->copyText() : QString();
Laurent Montel's avatar
Laurent Montel committed
494
    KMCommand *command = new KMReplyCommand(mParent, mCurrentItem, strategy, text);
Laurent Montel's avatar
Laurent Montel committed
495
    connect(command, &KMCommand::completed, this, &MessageActions::replyActionFinished);
Laurent Montel's avatar
Laurent Montel committed
496
    command->start();
Thomas McGuire's avatar
Thomas McGuire committed
497
498
}

Laurent Montel's avatar
Laurent Montel committed
499
void MessageActions::setMessageView(KMReaderWin *msgView)
500
{
Laurent Montel's avatar
Laurent Montel committed
501
    mMessageView = msgView;
502
503
}

Laurent Montel's avatar
Laurent Montel committed
504
void MessageActions::setupForwardActions(KActionCollection *ac)
505
{
Laurent Montel's avatar
Laurent Montel committed
506
    disconnect(mForwardActionMenu, SIGNAL(triggered(bool)), nullptr, nullptr);
Laurent Montel's avatar
Laurent Montel committed
507
508
509
    mForwardActionMenu->removeAction(mForwardInlineAction);
    mForwardActionMenu->removeAction(mForwardAttachedAction);

Laurent Montel's avatar
Laurent Montel committed
510
    if (KMailSettings::self()->forwardingInlineByDefault()) {
Laurent Montel's avatar
Laurent Montel committed
511
512
513
514
515
516
        mForwardActionMenu->insertAction(mRedirectAction, mForwardInlineAction);
        mForwardActionMenu->insertAction(mRedirectAction, mForwardAttachedAction);
        ac->setDefaultShortcut(mForwardInlineAction, QKeySequence(Qt::Key_F));
        ac->setDefaultShortcut(mForwardAttachedAction, QKeySequence(Qt::SHIFT + Qt::Key_F));
        QObject::connect(mForwardActionMenu, SIGNAL(triggered(bool)),
                         mParent, SLOT(slotForwardInlineMsg()));
Laurent Montel's avatar
Laurent Montel committed
517
    } else {
Laurent Montel's avatar
Laurent Montel committed
518
519
520
521
522
        mForwardActionMenu->insertAction(mRedirectAction, mForwardAttachedAction);
        mForwardActionMenu->insertAction(mRedirectAction, mForwardInlineAction);
        ac->setDefaultShortcut(mForwardInlineAction, QKeySequence(Qt::Key_F));
        ac->setDefaultShortcut(mForwardAttachedAction, QKeySequence(Qt::SHIFT + Qt::Key_F));
        QObject::connect(mForwardActionMenu, SIGNAL(triggered(bool)),
Laurent Montel's avatar
Laurent Montel committed
523
                         mParent, SLOT(slotForwardAttachedMessage()));
Laurent Montel's avatar
Laurent Montel committed
524
    }
525
526
}

Laurent Montel's avatar
Laurent Montel committed
527
void MessageActions::setupForwardingActionsList(KXMLGUIClient *guiClient)
528
{
Laurent Montel's avatar
Laurent Montel committed
529
    QList<QAction *> forwardActionList;
530
    guiClient->unplugActionList(QStringLiteral("forward_action_list"));
Laurent Montel's avatar
Laurent Montel committed
531
    if (KMailSettings::self()->forwardingInlineByDefault()) {
Laurent Montel's avatar
Laurent Montel committed
532
533
        forwardActionList.append(mForwardInlineAction);
        forwardActionList.append(mForwardAttachedAction);
Laurent Montel's avatar
Laurent Montel committed
534
    } else {
Laurent Montel's avatar
Laurent Montel committed
535
536
        forwardActionList.append(mForwardAttachedAction);
        forwardActionList.append(mForwardInlineAction);
Laurent Montel's avatar
Laurent Montel committed
537
    }
Laurent Montel's avatar
Laurent Montel committed
538
    forwardActionList.append(mRedirectAction);
539
    guiClient->plugActionList(QStringLiteral("forward_action_list"), forwardActionList);
540
541
}

542
543
void MessageActions::slotReplyToMsg()
{
Laurent Montel's avatar
Laurent Montel committed
544
    replyCommand(MessageComposer::ReplySmart);
545
546
547
548
}

void MessageActions::slotReplyAuthorToMsg()
{
Laurent Montel's avatar
Laurent Montel committed
549
    replyCommand(MessageComposer::ReplyAuthor);
550
551
552
553
}

void MessageActions::slotReplyListToMsg()
{
Laurent Montel's avatar
Laurent Montel committed
554
    replyCommand(MessageComposer::ReplyList);
555
556
557
558
}

void MessageActions::slotReplyAllToMsg()
{
Laurent Montel's avatar
Laurent Montel committed
559
    replyCommand(MessageComposer::ReplyAll);
560
561
562
563
}

void MessageActions::slotNoQuoteReplyToMsg()
{
Laurent Montel's avatar
Laurent Montel committed
564
    if (!mCurrentItem.hasPayload<KMime::Message::Ptr>()) {
Laurent Montel's avatar
Laurent Montel committed
565
        return;
Laurent Montel's avatar
Laurent Montel committed
566
567
    }
    KMCommand *command = new KMReplyCommand(mParent, mCurrentItem, MessageComposer::ReplySmart, QString(), true);
Laurent Montel's avatar
Laurent Montel committed
568
    command->start();
569
570
}

Laurent Montel's avatar
Laurent Montel committed
571
void MessageActions::slotRunUrl(QAction *urlAction)
572
{
Laurent Montel's avatar
Laurent Montel committed
573
    const QVariant q = urlAction->data();
Laurent Montel's avatar
Laurent Montel committed
574
575
    if (q.type() == QVariant::Url) {
        new KRun(q.toUrl(), mParent);
Laurent Montel's avatar
Laurent Montel committed
576
    }
577
578
}

579
580
void MessageActions::slotMailingListFilter()
{
Laurent Montel's avatar
Laurent Montel committed
581
    if (!mCurrentItem.hasPayload<KMime::Message::Ptr>()) {
Laurent Montel's avatar
Laurent Montel committed
582
        return;
Laurent Montel's avatar
Laurent Montel committed
583
    }
Laurent Montel's avatar
Laurent Montel committed
584

Laurent Montel's avatar
Laurent Montel committed
585
    KMCommand *command = new KMMailingListFilterCommand(mParent, mCurrentItem);
Laurent Montel's avatar
Laurent Montel committed
586
    command->start();
587
588
}

Laurent Montel's avatar
Laurent Montel committed
589
void MessageActions::printMessage(bool preview)
590
{
Laurent Montel's avatar
Laurent Montel committed
591
    if (mMessageView) {
Laurent Montel's avatar
Laurent Montel committed
592
        bool result = false;
Laurent Montel's avatar
Laurent Montel committed
593
        if (MessageViewer::MessageViewerSettings::self()->printSelectedText()) {
Laurent Montel's avatar
Laurent Montel committed
594
595
            result = mMessageView->printSelectedText(preview);
        }
Laurent Montel's avatar
Laurent Montel committed
596
597
598
599
600
        if (!result) {
            const bool useFixedFont = MessageViewer::MessageViewerSettings::self()->useFixedFont();
            const QString overrideEncoding = MessageCore::MessageCoreSettings::self()->overrideCharacterEncoding();

            const Akonadi::Item message = mCurrentItem;
601
602
603
604
            KMPrintCommandInfo commandInfo;
            commandInfo.mMsg = message;
            commandInfo.mHeaderStylePlugin = mMessageView->viewer()->headerStylePlugin();
            commandInfo.mFormat = mMessageView->viewer()->displayFormatMessageOverwrite();
Laurent Montel's avatar
Laurent Montel committed
605
            commandInfo.mHtmlLoadExtOverride = mMessageView->viewer()->htmlLoadExternal();
606
607
608
            commandInfo.mPrintPreview = preview;
            commandInfo.mUseFixedFont = useFixedFont;
            commandInfo.mOverrideFont = overrideEncoding;
609
610
            commandInfo.mShowSignatureDetails = mMessageView->viewer()->showSignatureDetails() || MessageViewer::MessageViewerSettings::self()->alwaysShowEncryptionSignatureDetails();
            commandInfo.mShowEncryptionDetails = mMessageView->viewer()->showEncryptionDetails() || MessageViewer::MessageViewerSettings::self()->alwaysShowEncryptionSignatureDetails();
611

Laurent Montel's avatar
Laurent Montel committed
612
            KMPrintCommand *command
613
                = new KMPrintCommand(mParent, commandInfo);
Laurent Montel's avatar
Laurent Montel committed
614
615
            command->start();
        }
616
617
    } else {
        qCWarning(KMAIL_LOG) << "MessageActions::printMessage impossible to do it if we don't have a viewer";
618
    }
619
}
620

Laurent Montel's avatar
Laurent Montel committed
621
void MessageActions::slotPrintPreviewMsg()
622
{
Laurent Montel's avatar
Laurent Montel committed
623
    printMessage(true);
Laurent Montel's avatar
Laurent Montel committed
624
}
625

Laurent Montel's avatar
Laurent Montel committed
626
void MessageActions::slotPrintMessage()
Laurent Montel's avatar
Laurent Montel committed
627
{
Laurent Montel's avatar
Laurent Montel committed
628
    printMessage(false);
629
630
}

631
632
633
634
635
636
637
638
/**
 * This adds a list of actions to mMailingListActionMenu mapping the identifier item to
 * the url.
 *
 * e.g.: item = "Contact Owner"
 * "Contact Owner (email)" -> KRun( "mailto:bob@arthouseflowers.example.com" )
 * "Contact Owner (web)" -> KRun( "http://arthouseflowers.example.com/contact-owner.php" )
 */
Laurent Montel's avatar
KUrl--    
Laurent Montel committed
639
void MessageActions::addMailingListActions(const QString &item, const QList<QUrl> &list)
640
{
Laurent Montel's avatar
Laurent Montel committed
641
    for (const QUrl &url : list) {
Laurent Montel's avatar
Laurent Montel committed
642
        addMailingListAction(item, url);
Laurent Montel's avatar
Laurent Montel committed
643
    }
644
645
646
647
648
649
}

/**
 * This adds a action to mMailingListActionMenu mapping the identifier item to
 * the url. See addMailingListActions above.
 */
Laurent Montel's avatar
KUrl--    
Laurent Montel committed
650
void MessageActions::addMailingListAction(const QString &item, const QUrl &url)
651
{
Laurent Montel's avatar
KUrl--    
Laurent Montel committed
652
653
    QString protocol = url.scheme().toLower();
    QString prettyUrl = url.toDisplayString();
654
    if (protocol == QLatin1String("mailto")) {
Laurent Montel's avatar
Laurent Montel committed
655
656
        protocol = i18n("email");
        prettyUrl.remove(0, 7);   // length( "mailto:" )
Laurent Montel's avatar
Laurent Montel committed
657
    } else if (protocol.startsWith(QLatin1String("http"))) {
Laurent Montel's avatar
Laurent Montel committed
658
        protocol = i18n("web");
Laurent Montel's avatar
Laurent Montel committed
659
660
    }
    // item is a mailing list url description passed from the updateActions method above.
Laurent Montel's avatar
Laurent Montel committed
661
662
    QAction *act
        = new QAction(i18nc("%1 is a 'Contact Owner' or similar action. %2 is a protocol normally web or email though could be irc/ftp or other url variant", "%1 (%2)", item, protocol), this);
Laurent Montel's avatar
Laurent Montel committed
663
    mMailListActionList.append(act);
Laurent Montel's avatar
KUrl--    
Laurent Montel committed
664
    const QVariant v(url);
Laurent Montel's avatar
Laurent Montel committed
665
    act->setData(v);
Laurent Montel's avatar
Laurent Montel committed
666
    KMail::Util::addQActionHelpText(act, prettyUrl);
Laurent Montel's avatar
Laurent Montel committed
667
    mMailingListActionMenu->addAction(act);
668
669
}

670
671
void MessageActions::editCurrentMessage()
{
Laurent Montel's avatar
Laurent Montel committed
672
    KMCommand *command = nullptr;
Laurent Montel's avatar
Laurent Montel committed
673
    if (mCurrentItem.isValid()) {
Laurent Montel's avatar
Laurent Montel committed
674
        Akonadi::Collection col = mCurrentItem.parentCollection();
Laurent Montel's avatar
Laurent Montel committed
675
        qCDebug(KMAIL_LOG) << " mCurrentItem.parentCollection()" << mCurrentItem.parentCollection();
Laurent Montel's avatar
Laurent Montel committed
676
677
        // edit, unlike send again, removes the message from the folder
        // we only want that for templates and drafts folders
Laurent Montel's avatar
Laurent Montel committed
678
        if (col.isValid()
Laurent Montel's avatar
Laurent Montel committed
679
680
681
            && (CommonKernel->folderIsDraftOrOutbox(col)
                || CommonKernel->folderIsTemplates(col))
            ) {
Laurent Montel's avatar
Laurent Montel committed
682
683
684
685
            command = new KMEditItemCommand(mParent, mCurrentItem, true);
        } else {
            command = new KMEditItemCommand(mParent, mCurrentItem, false);
        }
Laurent Montel's avatar
Laurent Montel committed
686
        command->start();
Laurent Montel's avatar
Laurent Montel committed
687
688
    } else if (mCurrentItem.hasPayload<KMime::Message::Ptr>()) {
        command = new KMEditMessageCommand(mParent, mCurrentItem.payload<KMime::Message::Ptr>());
Laurent Montel's avatar
Laurent Montel committed
689
690
        command->start();
    }
691
692
}

693
694
void MessageActions::annotateMessage()
{
Laurent Montel's avatar
Laurent Montel committed
695
    if (!mCurrentItem.isValid()) {
Laurent Montel's avatar
Laurent Montel committed
696
        return;
Laurent Montel's avatar
Laurent Montel committed
697
    }
698

Laurent Montel's avatar
Laurent Montel committed
699
    QPointer<PimCommon::AnnotationEditDialog> dialog = new PimCommon::AnnotationEditDialog(mCurrentItem, mParent);
Laurent Montel's avatar
Laurent Montel committed
700
    dialog->setAttribute(Qt::WA_DeleteOnClose);
701
    dialog->exec();
702
703
}

Laurent Montel's avatar
Laurent Montel committed
704
void MessageActions::addWebShortcutsMenu(QMenu *menu, const QString &text)
705
{
Laurent Montel's avatar
Laurent Montel committed
706
    mWebShortcutMenuManager->setSelectedText(text);
Laurent Montel's avatar
Laurent Montel committed
707
    mWebShortcutMenuManager->addWebShortcutsToMenu(menu);
708
}
709

Laurent Montel's avatar
Laurent Montel committed
710
QAction *MessageActions::debugAkonadiSearchAction() const
711
{
Laurent Montel's avatar
Laurent Montel committed
712
    return mDebugAkonadiSearchAction;
713
714
715
716
717
718
719
}

QAction *MessageActions::addFollowupReminderAction() const
{
    return mAddFollowupReminderAction;
}

Laurent Montel's avatar
Laurent Montel committed
720
void MessageActions::slotDebugAkonadiSearch()
721
{
Laurent Montel's avatar
Laurent Montel committed
722
    if (!mCurrentItem.isValid()) {
723
        return;
Laurent Montel's avatar
Laurent Montel committed
724
    }
Laurent Montel's avatar
Laurent Montel committed
725
    QPointer<Akonadi::Search::AkonadiSearchDebugDialog> dlg = new Akonadi::Search::AkonadiSearchDebugDialog;
726
    dlg->setAkonadiId(mCurrentItem.id());
Laurent Montel's avatar
Laurent Montel committed
727
    dlg->setAttribute(Qt::WA_DeleteOnClose);
Laurent Montel's avatar
Laurent Montel committed
728
    dlg->setSearchType(Akonadi::Search::AkonadiSearchDebugSearchPathComboBox::Emails);
729
    dlg->doSearch();
730
731
    dlg->show();
}
732

733
734
735
736
737
738
739
740
741
void MessageActions::slotResendMessage()
{
    if (!mCurrentItem.isValid()) {
        return;
    }
    KMCommand *command = new KMResendMessageCommand(mParent, mCurrentItem);
    command->start();
}

Laurent Montel's avatar
Laurent Montel committed
742
743
744
745
746
QAction *MessageActions::newMessageFromTemplateAction() const
{
    return mNewMessageFromTemplateAction;
}

747
748
749
750
751
QAction *MessageActions::sendAgainAction() const
{
    return mSendAgainAction;
}

752
753
void MessageActions::slotAddFollowupReminder()
{
Laurent Montel's avatar
Laurent Montel committed
754
    if (!mCurrentItem.isValid()) {
755
        return;
Laurent Montel's avatar
Laurent Montel committed
756
    }
757

Laurent Montel's avatar
Laurent Montel committed
758
    QPointer<MessageComposer::FollowUpReminderSelectDateDialog> dlg = new MessageComposer::FollowUpReminderSelectDateDialog(mParent);
759
760
761
762
763
764
765
766
767
768
    if (dlg->exec()) {
        const QDate date = dlg->selectedDate();
        CreateFollowupReminderOnExistingMessageJob *job = new CreateFollowupReminderOnExistingMessageJob(this);
        job->setDate(date);
        job->setCollection(dlg->collection());
        job->setMessageItem(mCurrentItem);
        job->start();
    }
    delete dlg;
}
769
770
771
772
773
774
775
776

void MessageActions::slotExportToPdf()
{
    if (!mCurrentItem.isValid()) {
        return;
    }

    auto email = mCurrentItem.payload<KMime::Message::Ptr>();
Laurent Montel's avatar
Laurent Montel committed
777
778
779
780
781
782
783
784
785
    QString fileName;

    fileName = MessageCore::StringUtil::cleanFileName(MessageCore::StringUtil::cleanSubject(email.data()).trimmed());
    fileName.remove(QLatin1Char('\"'));
    if (!fileName.endsWith(QLatin1String(".pdf"))) {
        fileName += QLatin1String(".pdf");
    }
    fileName = QFileDialog::getSaveFileName(mParent, i18n("Export to PDF"),
                QDir::homePath() + QLatin1Char('/') + fileName,
Yuri Chornoivan's avatar
Yuri Chornoivan committed
786
                i18n("PDF document (*.pdf)"));
787
788
789
790
    if (!fileName.isEmpty()) {
        mMessageView->viewer()->exportToPdf(fileName);
    }
}
791
792
793
794
795
796

QAction *MessageActions::exportToPdfAction() const
{
    return mExportToPdfAction;
}