kmcomposerwin.cpp 155 KB
Newer Older
Volker Krause's avatar
Volker Krause committed
1
2
/*
 * This file is part of KMail.
3
 * SPDX-FileCopyrightText: 2011-2020 Laurent Montel <montel@kde.org>
4
 *
5
 * SPDX-FileCopyrightText: 2009 Constantin Berzan <exit3219@gmail.com>
Volker Krause's avatar
Volker Krause committed
6
7
 *
 * Based on KMail code by:
8
 * SPDX-FileCopyrightText: 1997 Markus Wuebben <markus.wuebben@kde.org>
Volker Krause's avatar
Volker Krause committed
9
 *
10
 * SPDX-License-Identifier: GPL-2.0-or-later
Volker Krause's avatar
Volker Krause committed
11
 */
Laurent Montel's avatar
Laurent Montel committed
12
#include "kmcomposerwin.h"
Volker Krause's avatar
Volker Krause committed
13
// KMail includes
Laurent Montel's avatar
Laurent Montel committed
14
15
#include "attachment/attachmentcontroller.h"
#include "attachment/attachmentview.h"
16
#include "codec/codecaction.h"
Sandro Knauß's avatar
Sandro Knauß committed
17
#include "custommimeheader.h"
18
#include "editor/kmcomposereditorng.h"
Sandro Knauß's avatar
Sandro Knauß committed
19
20
21
#include "editor/plugininterface/kmailplugineditorcheckbeforesendmanagerinterface.h"
#include "editor/plugininterface/kmailplugineditorinitmanagerinterface.h"
#include "editor/plugininterface/kmailplugineditormanagerinterface.h"
Laurent Montel's avatar
Laurent Montel committed
22
#include "editor/plugininterface/kmailplugineditorconverttextmanagerinterface.h"
23
#include "editor/plugininterface/kmailplugingrammareditormanagerinterface.h"
Sandro Knauß's avatar
Sandro Knauß committed
24
25
26
#include "editor/potentialphishingemail/potentialphishingemailjob.h"
#include "editor/potentialphishingemail/potentialphishingemailwarning.h"
#include "editor/warningwidgets/incorrectidentityfolderwarning.h"
27
#include "editor/warningwidgets/attachmentaddedfromexternalwarning.h"
Sandro Knauß's avatar
Sandro Knauß committed
28
29
30
31
#include "job/addressvalidationjob.h"
#include "job/createnewcontactjob.h"
#include "job/saveasfilejob.h"
#include "job/savedraftjob.h"
Laurent Montel's avatar
Laurent Montel committed
32
#include "job/dndfromarkjob.h"
Sandro Knauß's avatar
Sandro Knauß committed
33
34
35
36
#include "kmail_debug.h"
#include "kmcommands.h"
#include "kmcomposercreatenewcomposerjob.h"
#include "kmcomposerglobalaction.h"
Laurent Montel's avatar
Laurent Montel committed
37
#include "kmcomposerupdatetemplatejob.h"
38
#include "kmkernel.h"
39
#include "kmmainwidget.h"
Sandro Knauß's avatar
Sandro Knauß committed
40
#include "kmmainwin.h"
41
#include "mailcomposeradaptor.h" // TODO port all D-Bus stuff...
Sandro Knauß's avatar
Sandro Knauß committed
42
#include "settings/kmailsettings.h"
Laurent Montel's avatar
Laurent Montel committed
43
#include "templatesconfiguration_kfg.h"
Sandro Knauß's avatar
Sandro Knauß committed
44
45
#include "util.h"
#include "validatesendmailshortcut.h"
Laurent Montel's avatar
Laurent Montel committed
46
47
#include "warningwidgets/attachmentmissingwarning.h"
#include "warningwidgets/externaleditorwarning.h"
Laurent Montel's avatar
Laurent Montel committed
48
#include "widgets/cryptostateindicatorwidget.h"
49
#include "widgets/kactionmenutransport.h"
50
#include "undosend/undosendmanager.h"
Sandro Knauß's avatar
Sandro Knauß committed
51
52
53
54
55
56
#include <Akonadi/Contact/ContactGroupExpandJob>
#include <Akonadi/KMime/MessageFlags>
#include <Akonadi/KMime/MessageStatus>
#include <AkonadiCore/ItemFetchJob>
#include <AkonadiCore/Monitor>
#include <AkonadiCore/changerecorder.h>
Laurent Montel's avatar
Laurent Montel committed
57

Sandro Knauß's avatar
Sandro Knauß committed
58
#include <KContacts/VCardConverter>
Laurent Montel's avatar
Laurent Montel committed
59

Sandro Knauß's avatar
Sandro Knauß committed
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#include <KIdentityManagement/Identity>
#include <KIdentityManagement/IdentityCombo>
#include <KIdentityManagement/IdentityManager>
#include <KIdentityManagement/Signature>

#include <KMime/Message>

#include <KPIMTextEdit/EditorUtil>
#include <KPIMTextEdit/RichTextComposerActions>
#include <KPIMTextEdit/RichTextComposerControler>
#include <KPIMTextEdit/RichTextComposerImages>
#include <KPIMTextEdit/RichTextEditorWidget>
#include <KPIMTextEdit/RichTextExternalComposer>

#include <Libkdepim/ProgressStatusBarWidget>
#include <Libkdepim/StatusbarProgressWidget>
76
#include <followupreminder.h>
Laurent Montel's avatar
Laurent Montel committed
77

78
#include <KCursorSaver>
Laurent Montel's avatar
Laurent Montel committed
79

Sandro Knauß's avatar
Sandro Knauß committed
80
81
82
83
84
85
86
#include <Libkleo/KeySelectionDialog>
#include <Libkleo/ProgressDialog>

#include <MailCommon/FolderCollectionMonitor>
#include <MailCommon/FolderRequester>
#include <MailCommon/FolderSettings>
#include <MailCommon/MailKernel>
Laurent Montel's avatar
Laurent Montel committed
87
#include <MailCommon/SnippetTreeView>
Laurent Montel's avatar
Laurent Montel committed
88
89
#include <MailCommon/SnippetsManager>

Sandro Knauß's avatar
Sandro Knauß committed
90
91
92
93
94
#include <MailTransport/Transport>
#include <MailTransport/TransportComboBox>
#include <MailTransport/TransportManager>

#include <MessageComposer/AttachmentModel>
Laurent Montel's avatar
Laurent Montel committed
95
#include <MessageComposer/Composer>
Sandro Knauß's avatar
Sandro Knauß committed
96
97
98
#include <MessageComposer/ComposerLineEdit>
#include <MessageComposer/FollowUpReminderSelectDateDialog>
#include <MessageComposer/FollowupReminderCreateJob>
99
#include <MessageComposer/FollowupReminder>
Laurent Montel's avatar
Laurent Montel committed
100
101
#include <MessageComposer/GlobalPart>
#include <MessageComposer/InfoPart>
Sandro Knauß's avatar
Sandro Knauß committed
102
103
104
#include <MessageComposer/InsertTextFileJob>
#include <MessageComposer/Kleo_Util>
#include <MessageComposer/MessageComposerSettings>
Laurent Montel's avatar
Laurent Montel committed
105
#include <MessageComposer/MessageHelper>
Sandro Knauß's avatar
Sandro Knauß committed
106
107
#include <MessageComposer/PluginEditorCheckBeforeSendParams>
#include <MessageComposer/PluginEditorInterface>
Laurent Montel's avatar
Laurent Montel committed
108
#include <MessageComposer/PluginActionType>
Sandro Knauß's avatar
Sandro Knauß committed
109
#include <MessageComposer/RichTextComposerSignatures>
Laurent Montel's avatar
Laurent Montel committed
110
#include <MessageComposer/SignatureController>
Sandro Knauß's avatar
Sandro Knauß committed
111
112
#include <MessageComposer/TextPart>
#include <MessageComposer/Util>
113
#include <MessageComposer/StatusBarLabelToggledState>
114
115
#include <MessageComposer/ConvertSnippetVariablesJob>
#include <MessageComposer/ComposerViewInterface>
116

Laurent Montel's avatar
Laurent Montel committed
117
#include <Sonnet/DictionaryComboBox>
Laurent Montel's avatar
Laurent Montel committed
118

Laurent Montel's avatar
Laurent Montel committed
119
#include <MessageCore/AttachmentPart>
Laurent Montel's avatar
Laurent Montel committed
120
#include <MessageCore/MessageCoreSettings>
Laurent Montel's avatar
Laurent Montel committed
121
#include <MessageCore/NodeHelper>
Sandro Knauß's avatar
Sandro Knauß committed
122
#include <MessageCore/StringUtil>
Thomas McGuire's avatar
Thomas McGuire committed
123

Sandro Knauß's avatar
Sandro Knauß committed
124
125
#include <MessageViewer/MessageViewerSettings>
#include <MessageViewer/Stl_Util>
126

Sandro Knauß's avatar
Sandro Knauß committed
127
128
129
#include <MimeTreeParser/NodeHelper>
#include <MimeTreeParser/ObjectTreeParser>
#include <MimeTreeParser/SimpleObjectTreeSource>
130

Sandro Knauß's avatar
Sandro Knauß committed
131
132
133
#include <PimCommon/CustomToolsWidgetng>
#include <PimCommon/KActionMenuChangeCase>
#include <PimCommon/LineEditWithAutoCorrection>
134
#include <PimCommon/CustomToolsPluginManager>
Laurent Montel's avatar
Laurent Montel committed
135

136
137
138
#include <MessageComposer/SendLaterDialog>
#include <MessageComposer/SendLaterInfo>
#include <MessageComposer/SendLaterUtil>
Sandro Knauß's avatar
Sandro Knauß committed
139
140
141
142
143
144
145
146
147
148
149
150
151
152

#include <TemplateParser/TemplateParserJob>
#include <TemplateParser/TemplatesConfiguration>

#include <QGpgME/Protocol>
#include <QGpgME/ExportJob>
#include <QGpgME/KeyForMailboxJob>

// KDE Frameworks includes
#include <KActionCollection>
#include <KActionMenu>
#include <KCharsets>
#include <KConfigGroup>
#include <KEditToolBar>
153
#include <KEmailAddress>
154
#include <KEncodingFileDialog>
Sandro Knauß's avatar
Sandro Knauß committed
155
#include <KIO/JobUiDelegate>
156
#include <KIconUtils>
Sandro Knauß's avatar
Sandro Knauß committed
157
158
159
160
161
162
163
#include <KMessageBox>
#include <KRecentFilesAction>
#include <KShortcutsDialog>
#include <KSplitterCollapserButton>
#include <KStandardShortcut>
#include <KToggleAction>
#include <KToolBar>
164
#include <QDBusConnection>
Sandro Knauß's avatar
Sandro Knauß committed
165
#include <sonnet_version.h>
Laurent Montel's avatar
Laurent Montel committed
166
#include <KXMLGUIFactory>
Volker Krause's avatar
Volker Krause committed
167
// Qt includes
168
#include <QAction>
169
#include <QApplication>
170
#include <QCheckBox>
Sandro Knauß's avatar
Sandro Knauß committed
171
#include <QClipboard>
172
#include <QFontDatabase>
Sandro Knauß's avatar
Sandro Knauß committed
173
174
175
#include <QInputDialog>
#include <QMenu>
#include <QMimeData>
176
#include <QPointer>
Sandro Knauß's avatar
Sandro Knauß committed
177
178
179
180
#include <QShortcut>
#include <QSplitter>
#include <QStandardPaths>
#include <QStatusBar>
181
#include <QMenuBar>
Laurent Montel's avatar
Laurent Montel committed
182
#include <MessageComposer/PluginEditorConverterInitialData>
Laurent Montel's avatar
Laurent Montel committed
183
#include <MessageComposer/PluginEditorConverterBeforeConvertingData>
184
185
186
187

// GPGME
#include <gpgme++/keylistresult.h>
#include <gpgme++/key.h>
Volker Krause's avatar
Volker Krause committed
188

189
190
191
192
193
#include <kio_version.h>

#include <KDialogJobUiDelegate>
#include <KIO/CommandLauncherJob>

Laurent Montel's avatar
Laurent Montel committed
194
using Sonnet::DictionaryComboBox;
Thomas McGuire's avatar
Thomas McGuire committed
195
196
using MailTransport::TransportManager;
using MailTransport::Transport;
Volker Krause's avatar
Volker Krause committed
197

198
199
Q_DECLARE_METATYPE(MessageComposer::Recipient::Ptr)

Laurent Montel's avatar
Laurent Montel committed
200
KMail::Composer *KMail::makeComposer(const KMime::Message::Ptr &msg, bool lastSignState, bool lastEncryptState, Composer::TemplateContext context, uint identity, const QString &textSelection,
Laurent Montel's avatar
Laurent Montel committed
201
202
                                     const QString &customTemplate)
{
Laurent Montel's avatar
Laurent Montel committed
203
    return KMComposerWin::create(msg, lastSignState, lastEncryptState, context, identity, textSelection, customTemplate);
Volker Krause's avatar
Volker Krause committed
204
205
}

Laurent Montel's avatar
Laurent Montel committed
206
KMail::Composer *KMComposerWin::create(const KMime::Message::Ptr &msg, bool lastSignState, bool lastEncryptState, Composer::TemplateContext context, uint identity, const QString &textSelection, const QString &customTemplate)
Laurent Montel's avatar
Laurent Montel committed
207
{
Laurent Montel's avatar
Laurent Montel committed
208
    return new KMComposerWin(msg, lastSignState, lastEncryptState, context, identity, textSelection, customTemplate);
Volker Krause's avatar
Volker Krause committed
209
210
}

Laurent Montel's avatar
Laurent Montel committed
211
int KMComposerWin::s_composerNumber = 0;
Volker Krause's avatar
Volker Krause committed
212

Laurent Montel's avatar
Laurent Montel committed
213
KMComposerWin::KMComposerWin(const KMime::Message::Ptr &aMsg, bool lastSignState, bool lastEncryptState, Composer::TemplateContext context, uint id, const QString &textSelection, const QString &customTemplate)
Laurent Montel's avatar
Laurent Montel committed
214
215
216
217
218
219
    : KMail::Composer(QStringLiteral("kmail-composer#"))
    , mTextSelection(textSelection)
    , mCustomTemplate(customTemplate)
    , mFolder(Akonadi::Collection(-1))
    , mId(id)
    , mContext(context)
Laurent Montel's avatar
Laurent Montel committed
220
{
Laurent Montel's avatar
Laurent Montel committed
221
    mGlobalAction = new KMComposerGlobalAction(this, this);
Laurent Montel's avatar
Laurent Montel committed
222
223
    mComposerBase = new MessageComposer::ComposerViewBase(this, this);
    mComposerBase->setIdentityManager(kmkernel->identityManager());
Laurent Montel's avatar
Laurent Montel committed
224

Laurent Montel's avatar
Laurent Montel committed
225
    mPluginEditorManagerInterface = new KMailPluginEditorManagerInterface(this);
Laurent Montel's avatar
Laurent Montel committed
226
    connect(mPluginEditorManagerInterface, &KMailPluginEditorManagerInterface::message, this, &KMComposerWin::slotMessage);
227
    connect(mPluginEditorManagerInterface, &KMailPluginEditorManagerInterface::insertText, this, &KMComposerWin::slotEditorPluginInsertText);
Laurent Montel's avatar
Laurent Montel committed
228
    mPluginEditorCheckBeforeSendManagerInterface = new KMailPluginEditorCheckBeforeSendManagerInterface(this);
Laurent Montel's avatar
Laurent Montel committed
229
    mPluginEditorInitManagerInterface = new KMailPluginEditorInitManagerInterface(this);
Laurent Montel's avatar
Laurent Montel committed
230
    mPluginEditorConvertTextManagerInterface = new KMailPluginEditorConvertTextManagerInterface(this);
Laurent Montel's avatar
Laurent Montel committed
231

232
233
    mPluginEditorGrammarManagerInterface = new KMailPluginGrammarEditorManagerInterface(this);

Laurent Montel's avatar
Laurent Montel committed
234
235
236
237
238
    connect(mComposerBase, &MessageComposer::ComposerViewBase::disableHtml, this, &KMComposerWin::disableHtml);
    connect(mComposerBase, &MessageComposer::ComposerViewBase::enableHtml, this, &KMComposerWin::enableHtml);
    connect(mComposerBase, &MessageComposer::ComposerViewBase::failed, this, &KMComposerWin::slotSendFailed);
    connect(mComposerBase, &MessageComposer::ComposerViewBase::sentSuccessfully, this, &KMComposerWin::slotSendSuccessful);
    connect(mComposerBase, &MessageComposer::ComposerViewBase::modified, this, &KMComposerWin::setModified);
Laurent Montel's avatar
Laurent Montel committed
239

Laurent Montel's avatar
Laurent Montel committed
240
    (void)new MailcomposerAdaptor(this);
Laurent Montel's avatar
Laurent Montel committed
241
242
    mdbusObjectPath = QLatin1String("/Composer_") + QString::number(++s_composerNumber);
    QDBusConnection::sessionBus().registerObject(mdbusObjectPath, this);
Laurent Montel's avatar
Laurent Montel committed
243

Laurent Montel's avatar
Laurent Montel committed
244
    MessageComposer::SignatureController *sigController = new MessageComposer::SignatureController(this);
Laurent Montel's avatar
Laurent Montel committed
245
    connect(sigController, &MessageComposer::SignatureController::enableHtml, this, &KMComposerWin::enableHtml);
Laurent Montel's avatar
Laurent Montel committed
246
    mComposerBase->setSignatureController(sigController);
Laurent Montel's avatar
Laurent Montel committed
247

Laurent Montel's avatar
Laurent Montel committed
248
    if (!kmkernel->xmlGuiInstanceName().isEmpty()) {
Laurent Montel's avatar
Laurent Montel committed
249
        setComponentName(kmkernel->xmlGuiInstanceName(), i18n("KMail2"));
Laurent Montel's avatar
Laurent Montel committed
250
    }
Laurent Montel's avatar
Laurent Montel committed
251
    mMainWidget = new QWidget(this);
Laurent Montel's avatar
Laurent Montel committed
252
    // splitter between the headers area and the actual editor
Laurent Montel's avatar
Laurent Montel committed
253
    mHeadersToEditorSplitter = new QSplitter(Qt::Vertical, mMainWidget);
Laurent Montel's avatar
Laurent Montel committed
254
    mHeadersToEditorSplitter->setObjectName(QStringLiteral("mHeadersToEditorSplitter"));
Laurent Montel's avatar
Laurent Montel committed
255
256
257
258
259
    mHeadersToEditorSplitter->setChildrenCollapsible(false);
    mHeadersArea = new QWidget(mHeadersToEditorSplitter);
    mHeadersArea->setSizePolicy(mHeadersToEditorSplitter->sizePolicy().horizontalPolicy(),
                                QSizePolicy::Expanding);
    mHeadersToEditorSplitter->addWidget(mHeadersArea);
Laurent Montel's avatar
Laurent Montel committed
260
261
262
    const QList<int> defaultSizes{
        0
    };
Laurent Montel's avatar
Laurent Montel committed
263
    mHeadersToEditorSplitter->setSizes(defaultSizes);
Laurent Montel's avatar
Laurent Montel committed
264

Laurent Montel's avatar
Laurent Montel committed
265
    QVBoxLayout *v = new QVBoxLayout(mMainWidget);
266
    v->setContentsMargins(0, 0, 0, 0);
Laurent Montel's avatar
Laurent Montel committed
267
268
    v->addWidget(mHeadersToEditorSplitter);
    KIdentityManagement::IdentityCombo *identity = new KIdentityManagement::IdentityCombo(kmkernel->identityManager(),
Laurent Montel's avatar
Laurent Montel committed
269
                                                                                          mHeadersArea);
270
    identity->setCurrentIdentity(mId);
271
    connect(identity, &KIdentityManagement::IdentityCombo::identityDeleted, this, &KMComposerWin::slotIdentityDeleted);
272
    connect(identity, &KIdentityManagement::IdentityCombo::invalidIdentity, this, &KMComposerWin::slotInvalidIdentity);
Laurent Montel's avatar
Laurent Montel committed
273
    mComposerBase->setIdentityCombo(identity);
Laurent Montel's avatar
Laurent Montel committed
274

Laurent Montel's avatar
Laurent Montel committed
275
    sigController->setIdentityCombo(identity);
Laurent Montel's avatar
Laurent Montel committed
276
277
    sigController->suspend(); // we have to do identity change tracking ourselves due to the template code

Laurent Montel's avatar
Laurent Montel committed
278
    Sonnet::DictionaryComboBox *dictionaryCombo = new DictionaryComboBox(mHeadersArea);
279
    dictionaryCombo->setToolTip(i18n("Select the dictionary to use when spell-checking this message"));
280
    mComposerBase->setDictionary(dictionaryCombo);
Laurent Montel's avatar
Laurent Montel committed
281

Laurent Montel's avatar
Laurent Montel committed
282
283
284
    mFccFolder = new MailCommon::FolderRequester(mHeadersArea);
    mFccFolder->setNotAllowToCreateNewFolder(true);
    mFccFolder->setMustBeReadWrite(true);
Laurent Montel's avatar
Laurent Montel committed
285

Laurent Montel's avatar
Laurent Montel committed
286
    mFccFolder->setToolTip(i18n("Select the sent-mail folder where a copy of this message will be saved"));
Laurent Montel's avatar
Laurent Montel committed
287
    connect(mFccFolder, &MailCommon::FolderRequester::folderChanged, this, &KMComposerWin::slotFccFolderChanged);
Laurent Montel's avatar
Laurent Montel committed
288
    connect(mFccFolder, &MailCommon::FolderRequester::invalidFolder, this, &KMComposerWin::slotFccIsInvalid);
Laurent Montel's avatar
Laurent Montel committed
289

Laurent Montel's avatar
Laurent Montel committed
290
291
292
    MailTransport::TransportComboBox *transport = new MailTransport::TransportComboBox(mHeadersArea);
    transport->setToolTip(i18n("Select the outgoing account to use for sending this message"));
    mComposerBase->setTransportCombo(transport);
Laurent Montel's avatar
Laurent Montel committed
293
    connect(transport, qOverload<int>(&MailTransport::TransportComboBox::activated), this, &KMComposerWin::slotTransportChanged);
294
    connect(transport, &MailTransport::TransportComboBox::transportRemoved, this, &KMComposerWin::slotTransportRemoved);
Laurent Montel's avatar
Laurent Montel committed
295
    mEdtFrom = new MessageComposer::ComposerLineEdit(false, mHeadersArea);
Laurent Montel's avatar
Laurent Montel committed
296
    mEdtFrom->setObjectName(QStringLiteral("fromLine"));
Laurent Montel's avatar
Laurent Montel committed
297
298
    mEdtFrom->setRecentAddressConfig(MessageComposer::MessageComposerSettings::self()->config());
    mEdtFrom->setToolTip(i18n("Set the \"From:\" email address for this message"));
Laurent Montel's avatar
Laurent Montel committed
299

Laurent Montel's avatar
Laurent Montel committed
300
301
    MessageComposer::RecipientsEditor *recipientsEditor = new MessageComposer::RecipientsEditor(mHeadersArea);
    recipientsEditor->setRecentAddressConfig(MessageComposer::MessageComposerSettings::self()->config());
Laurent Montel's avatar
Laurent Montel committed
302
303
    connect(recipientsEditor, &MessageComposer::RecipientsEditor::completionModeChanged, this, &KMComposerWin::slotCompletionModeChanged);
    connect(recipientsEditor, &MessageComposer::RecipientsEditor::sizeHintChanged, this, &KMComposerWin::recipientEditorSizeHintChanged);
304
    connect(recipientsEditor, &MessageComposer::RecipientsEditor::lineAdded, this, &KMComposerWin::slotRecipientEditorLineAdded);
Laurent Montel's avatar
Laurent Montel committed
305
    mComposerBase->setRecipientsEditor(recipientsEditor);
Laurent Montel's avatar
Laurent Montel committed
306

Laurent Montel's avatar
Laurent Montel committed
307
    mEdtSubject = new PimCommon::LineEditWithAutoCorrection(mHeadersArea, QStringLiteral("kmail2rc"));
Laurent Montel's avatar
Laurent Montel committed
308
    mEdtSubject->setActivateLanguageMenu(false);
Laurent Montel's avatar
Laurent Montel committed
309
    mEdtSubject->setToolTip(i18n("Set a subject for this message"));
Laurent Montel's avatar
Laurent Montel committed
310
    mEdtSubject->setAutocorrection(KMKernel::self()->composerAutoCorrection());
Laurent Montel's avatar
Laurent Montel committed
311
312
313
314
315
316
    mLblIdentity = new QLabel(i18n("&Identity:"), mHeadersArea);
    mDictionaryLabel = new QLabel(i18n("&Dictionary:"), mHeadersArea);
    mLblFcc = new QLabel(i18n("&Sent-Mail folder:"), mHeadersArea);
    mLblTransport = new QLabel(i18n("&Mail transport:"), mHeadersArea);
    mLblFrom = new QLabel(i18nc("sender address field", "&From:"), mHeadersArea);
    mLblSubject = new QLabel(i18nc("@label:textbox Subject of email.", "S&ubject:"), mHeadersArea);
Laurent Montel's avatar
Laurent Montel committed
317
    mShowHeaders = KMailSettings::self()->headers();
Laurent Montel's avatar
Laurent Montel committed
318
    mDone = false;
Laurent Montel's avatar
Laurent Montel committed
319
320
    mGrid = nullptr;
    mFixedFontAction = nullptr;
Laurent Montel's avatar
Laurent Montel committed
321
    // the attachment view is separated from the editor by a splitter
Laurent Montel's avatar
Laurent Montel committed
322
    mSplitter = new QSplitter(Qt::Vertical, mMainWidget);
Laurent Montel's avatar
Laurent Montel committed
323
    mSplitter->setObjectName(QStringLiteral("mSplitter"));
Laurent Montel's avatar
Laurent Montel committed
324
325
    mSplitter->setChildrenCollapsible(false);
    mSnippetSplitter = new QSplitter(Qt::Horizontal, mSplitter);
Laurent Montel's avatar
Laurent Montel committed
326
    mSnippetSplitter->setObjectName(QStringLiteral("mSnippetSplitter"));
Laurent Montel's avatar
Laurent Montel committed
327
328
329
    mSplitter->addWidget(mSnippetSplitter);

    QWidget *editorAndCryptoStateIndicators = new QWidget(mSplitter);
Laurent Montel's avatar
Laurent Montel committed
330
    mCryptoStateIndicatorWidget = new CryptoStateIndicatorWidget(this);
Laurent Montel's avatar
Laurent Montel committed
331
    mCryptoStateIndicatorWidget->setShowAlwaysIndicator(KMailSettings::self()->showCryptoLabelIndicator());
Laurent Montel's avatar
Laurent Montel committed
332

333
    QVBoxLayout *vbox = new QVBoxLayout(editorAndCryptoStateIndicators);
334
    vbox->setContentsMargins(0, 0, 0, 0);
335

336
337
338
339
340
341
342
343
344
    mPotentialPhishingEmailWarning = new PotentialPhishingEmailWarning(this);
    connect(mPotentialPhishingEmailWarning, &PotentialPhishingEmailWarning::sendNow, this, &KMComposerWin::slotCheckSendNowStep2);
    vbox->addWidget(mPotentialPhishingEmailWarning);

    mAttachmentMissing = new AttachmentMissingWarning(this);
    connect(mAttachmentMissing, &AttachmentMissingWarning::attachMissingFile, this, &KMComposerWin::slotAttachMissingFile);
    connect(mAttachmentMissing, &AttachmentMissingWarning::explicitClosedMissingAttachment, this, &KMComposerWin::slotExplicitClosedMissingAttachment);
    vbox->addWidget(mAttachmentMissing);

Laurent Montel's avatar
Laurent Montel committed
345
346
    KMComposerEditorNg *composerEditorNg = new KMComposerEditorNg(this, mCryptoStateIndicatorWidget);
    mRichTextEditorwidget = new KPIMTextEdit::RichTextEditorWidget(composerEditorNg, mCryptoStateIndicatorWidget);
Laurent Montel's avatar
Laurent Montel committed
347

348
    connect(composerEditorNg, &KMComposerEditorNg::insertEmoticon, mGlobalAction, &KMComposerGlobalAction::slotInsertEmoticon);
349
    //Don't use new connect api here. It crashes
350
    connect(composerEditorNg, SIGNAL(textChanged()), this, SLOT(slotEditorTextChanged()));
351
    connect(composerEditorNg, &KMComposerEditorNg::selectionChanged, this, &KMComposerWin::slotSelectionChanged);
352
    //connect(editor, &KMComposerEditor::textChanged, this, &KMComposeWin::slotEditorTextChanged);
Laurent Montel's avatar
Laurent Montel committed
353
    mComposerBase->setEditor(composerEditorNg);
354
355
356
    mIncorrectIdentityFolderWarning = new IncorrectIdentityFolderWarning(this);
    vbox->addWidget(mIncorrectIdentityFolderWarning);

357
358
359
    mAttachmentFromExternalMissing = new AttachmentAddedFromExternalWarning(this);
    vbox->addWidget(mAttachmentFromExternalMissing);

Laurent Montel's avatar
Laurent Montel committed
360
    vbox->addWidget(mCryptoStateIndicatorWidget);
361
    vbox->addWidget(mRichTextEditorwidget);
Laurent Montel's avatar
Laurent Montel committed
362

Laurent Montel's avatar
Laurent Montel committed
363
364
    mSnippetSplitter->insertWidget(0, editorAndCryptoStateIndicators);
    mSnippetSplitter->setOpaqueResize(true);
Laurent Montel's avatar
Laurent Montel committed
365
    sigController->setEditor(composerEditorNg);
Laurent Montel's avatar
Laurent Montel committed
366

Laurent Montel's avatar
Laurent Montel committed
367
    mHeadersToEditorSplitter->addWidget(mSplitter);
Laurent Montel's avatar
Laurent Montel committed
368
    composerEditorNg->setAcceptDrops(true);
Laurent Montel's avatar
Laurent Montel committed
369
370
    connect(sigController, &MessageComposer::SignatureController::signatureAdded,
            mComposerBase->editor()->externalComposer(), &KPIMTextEdit::RichTextExternalComposer::startExternalEditor);
Laurent Montel's avatar
Laurent Montel committed
371

Laurent Montel's avatar
Laurent Montel committed
372
    connect(dictionaryCombo, &Sonnet::DictionaryComboBox::dictionaryChanged, this, &KMComposerWin::slotSpellCheckingLanguage);
Laurent Montel's avatar
Laurent Montel committed
373

Laurent Montel's avatar
Laurent Montel committed
374
375
376
377
    connect(composerEditorNg, &KMComposerEditorNg::languageChanged, this, &KMComposerWin::slotDictionaryLanguageChanged);
    connect(composerEditorNg, &KMComposerEditorNg::spellCheckStatus, this, &KMComposerWin::slotSpellCheckingStatus);
    connect(composerEditorNg, &KMComposerEditorNg::insertModeChanged, this, &KMComposerWin::slotOverwriteModeChanged);
    connect(composerEditorNg, &KMComposerEditorNg::spellCheckingFinished, this, &KMComposerWin::slotDelayedCheckSendNow);
Laurent Montel's avatar
Laurent Montel committed
378
    mSnippetWidget = new MailCommon::SnippetTreeView(actionCollection(), mSnippetSplitter);
Laurent Montel's avatar
Laurent Montel committed
379
    connect(mSnippetWidget, &MailCommon::SnippetTreeView::insertSnippetInfo, this, &KMComposerWin::insertSnippetInfo);
Laurent Montel's avatar
Laurent Montel committed
380
    connect(composerEditorNg, &KMComposerEditorNg::insertSnippet, mSnippetWidget->snippetsManager(), &MailCommon::SnippetsManager::insertSnippet);
Laurent Montel's avatar
Laurent Montel committed
381
    mSnippetWidget->setVisible(KMailSettings::self()->showSnippetManager());
Laurent Montel's avatar
Laurent Montel committed
382
383
    mSnippetSplitter->addWidget(mSnippetWidget);
    mSnippetSplitter->setCollapsible(0, false);
384
    mSnippetSplitterCollapser = new KSplitterCollapserButton(mSnippetWidget, mSnippetSplitter);
Laurent Montel's avatar
Laurent Montel committed
385
    mSnippetSplitterCollapser->setVisible(KMailSettings::self()->showSnippetManager());
Laurent Montel's avatar
Laurent Montel committed
386

Laurent Montel's avatar
Laurent Montel committed
387
    mSplitter->setOpaqueResize(true);
Laurent Montel's avatar
Laurent Montel committed
388

Laurent Montel's avatar
Laurent Montel committed
389
    setWindowTitle(i18nc("@title:window", "Composer"));
Laurent Montel's avatar
Laurent Montel committed
390
    setMinimumSize(200, 200);
Laurent Montel's avatar
Laurent Montel committed
391

392
393
    mCustomToolsWidget = new PimCommon::CustomToolsWidgetNg(this);
    mCustomToolsWidget->initializeView(actionCollection(), PimCommon::CustomToolsPluginManager::self()->pluginsList());
Laurent Montel's avatar
Laurent Montel committed
394
    mSplitter->addWidget(mCustomToolsWidget);
Laurent Montel's avatar
Laurent Montel committed
395
    connect(mCustomToolsWidget, &PimCommon::CustomToolsWidgetNg::insertText, this, &KMComposerWin::slotInsertShortUrl);
Laurent Montel's avatar
Laurent Montel committed
396

Laurent Montel's avatar
Laurent Montel committed
397
398
    MessageComposer::AttachmentModel *attachmentModel = new MessageComposer::AttachmentModel(this);
    KMail::AttachmentView *attachmentView = new KMail::AttachmentView(attachmentModel, mSplitter);
Laurent Montel's avatar
Laurent Montel committed
399
    attachmentView->hideIfEmpty();
Laurent Montel's avatar
Laurent Montel committed
400
    connect(attachmentView, &KMail::AttachmentView::modified, this, &KMComposerWin::setModified);
Laurent Montel's avatar
Laurent Montel committed
401
    KMail::AttachmentController *attachmentController = new KMail::AttachmentController(attachmentModel, attachmentView, this);
Laurent Montel's avatar
Laurent Montel committed
402

Laurent Montel's avatar
Laurent Montel committed
403
404
    mComposerBase->setAttachmentModel(attachmentModel);
    mComposerBase->setAttachmentController(attachmentController);
Laurent Montel's avatar
Laurent Montel committed
405

Laurent Montel's avatar
Laurent Montel committed
406
    if (KMailSettings::self()->showForgottenAttachmentWarning()) {
Laurent Montel's avatar
Laurent Montel committed
407
408
409
410
        mVerifyMissingAttachment = new QTimer(this);
        mVerifyMissingAttachment->setSingleShot(true);
        mVerifyMissingAttachment->setInterval(1000 * 5);
        connect(mVerifyMissingAttachment, &QTimer::timeout, this, &KMComposerWin::slotVerifyMissingAttachmentTimeout);
411
    }
Laurent Montel's avatar
Laurent Montel committed
412
    connect(attachmentController, &KMail::AttachmentController::fileAttached, mAttachmentMissing, &AttachmentMissingWarning::slotFileAttached);
Laurent Montel's avatar
Laurent Montel committed
413
414
415
416

    mExternalEditorWarning = new ExternalEditorWarning(this);
    v->addWidget(mExternalEditorWarning);

Laurent Montel's avatar
Laurent Montel committed
417
418
    mPluginEditorManagerInterface->setParentWidget(this);
    mPluginEditorManagerInterface->setRichTextEditor(mRichTextEditorwidget->editor());
Laurent Montel's avatar
Laurent Montel committed
419
    mPluginEditorManagerInterface->setActionCollection(actionCollection());
Laurent Montel's avatar
Laurent Montel committed
420
    mPluginEditorManagerInterface->setComposerInterface(mComposerBase);
Laurent Montel's avatar
Laurent Montel committed
421

Laurent Montel's avatar
Laurent Montel committed
422
423
    mPluginEditorCheckBeforeSendManagerInterface->setParentWidget(this);

Laurent Montel's avatar
Laurent Montel committed
424
    mPluginEditorInitManagerInterface->setParentWidget(this);
Laurent Montel's avatar
Laurent Montel committed
425
    mPluginEditorInitManagerInterface->setRichTextEditor(composerEditorNg);
Laurent Montel's avatar
Laurent Montel committed
426

Laurent Montel's avatar
Laurent Montel committed
427
428
    mPluginEditorConvertTextManagerInterface->setParentWidget(this);
    mPluginEditorConvertTextManagerInterface->setActionCollection(actionCollection());
429
    mPluginEditorConvertTextManagerInterface->setRichTextEditor(composerEditorNg);
Laurent Montel's avatar
Laurent Montel committed
430

431
432
433
434
435
    mPluginEditorGrammarManagerInterface->setParentWidget(this);
    mPluginEditorGrammarManagerInterface->setActionCollection(actionCollection());
    mPluginEditorGrammarManagerInterface->setRichTextEditor(composerEditorNg);
    mPluginEditorGrammarManagerInterface->setCustomToolsWidget(mCustomToolsWidget);

Laurent Montel's avatar
Laurent Montel committed
436
437
438
439
    setupStatusBar(attachmentView->widget());
    setupActions();
    setupEditor();
    rethinkFields();
440
441
    readConfig();

Laurent Montel's avatar
Laurent Montel committed
442
    updateSignatureAndEncryptionStateIndicators();
Laurent Montel's avatar
Laurent Montel committed
443

Laurent Montel's avatar
Laurent Montel committed
444
    applyMainWindowSettings(KMKernel::self()->config()->group("Composer"));
Laurent Montel's avatar
Laurent Montel committed
445

446
    mUpdateWindowTitleConnection = connect(mEdtSubject, &PimCommon::LineEditWithAutoCorrection::textChanged, this, &KMComposerWin::slotUpdateWindowTitle);
Laurent Montel's avatar
Laurent Montel committed
447
    mIdentityConnection = connect(identity, &KIdentityManagement::IdentityCombo::identityChanged, this, [this](uint val) {
Laurent Montel's avatar
Laurent Montel committed
448
        slotIdentityChanged(val);
Laurent Montel's avatar
Laurent Montel committed
449
    });
Laurent Montel's avatar
Laurent Montel committed
450
    connect(kmkernel->identityManager(), qOverload<uint>(&KIdentityManagement::IdentityManager::changed), this, [this](uint val) {
451
452
453
        if (mComposerBase->identityCombo()->currentIdentity() == val) {
            slotIdentityChanged(val);
        }
Laurent Montel's avatar
Laurent Montel committed
454
    });
Laurent Montel's avatar
Laurent Montel committed
455

Laurent Montel's avatar
Laurent Montel committed
456
457
458
    connect(mEdtFrom, &MessageComposer::ComposerLineEdit::completionModeChanged, this, &KMComposerWin::slotCompletionModeChanged);
    connect(kmkernel->folderCollectionMonitor(), &Akonadi::Monitor::collectionRemoved, this, &KMComposerWin::slotFolderRemoved);
    connect(kmkernel, &KMKernel::configChanged, this, &KMComposerWin::slotConfigChanged);
Laurent Montel's avatar
Laurent Montel committed
459

Laurent Montel's avatar
Laurent Montel committed
460
    mMainWidget->resize(800, 600);
Laurent Montel's avatar
Laurent Montel committed
461
    setCentralWidget(mMainWidget);
Laurent Montel's avatar
Laurent Montel committed
462

Laurent Montel's avatar
Laurent Montel committed
463
    if (KMailSettings::self()->useHtmlMarkup()) {
Laurent Montel's avatar
Laurent Montel committed
464
        enableHtml();
Laurent Montel's avatar
Laurent Montel committed
465
466
467
    } else {
        disableHtml(MessageComposer::ComposerViewBase::LetUserConfirm);
    }
Laurent Montel's avatar
Laurent Montel committed
468

Laurent Montel's avatar
Laurent Montel committed
469
    if (KMailSettings::self()->useExternalEditor()) {
Laurent Montel's avatar
Laurent Montel committed
470
471
        composerEditorNg->setUseExternalEditor(true);
        composerEditorNg->setExternalEditorPath(KMailSettings::self()->externalEditor());
Laurent Montel's avatar
Laurent Montel committed
472
473
    }

Laurent Montel's avatar
Laurent Montel committed
474
475
    const QList<KPIM::MultiplyingLine *> lstLines = recipientsEditor->lines();
    for (KPIM::MultiplyingLine *line : lstLines) {
476
477
478
        slotRecipientEditorLineAdded(line);
    }

Laurent Montel's avatar
Laurent Montel committed
479
480
    if (aMsg) {
        setMessage(aMsg, lastSignState, lastEncryptState);
Laurent Montel's avatar
Laurent Montel committed
481
482
    }

483
    mComposerBase->recipientsEditor()->setFocusBottom();
Laurent Montel's avatar
Laurent Montel committed
484
    composerEditorNg->composerActions()->updateActionStates(); // set toolbar buttons to correct values
Laurent Montel's avatar
Laurent Montel committed
485
486
487

    mDone = true;

Laurent Montel's avatar
Laurent Montel committed
488
489
    mDummyComposer = new MessageComposer::Composer(this);
    mDummyComposer->globalPart()->setParentWidgetForGui(this);
490
491
492

    KConfigGroup grp(KMKernel::self()->config()->group("Composer"));
    setAutoSaveSettings(grp, true);
Volker Krause's avatar
Volker Krause committed
493
494
}

Laurent Montel's avatar
Laurent Montel committed
495
KMComposerWin::~KMComposerWin()
Volker Krause's avatar
Volker Krause committed
496
{
497
    disconnect(mUpdateWindowTitleConnection);
Laurent Montel's avatar
Laurent Montel committed
498
499
500
    // When we have a collection set, store the message back to that collection.
    // Note that when we save the message or sent it, mFolder is set back to 0.
    // So this for example kicks in when opening a draft and then closing the window.
Laurent Montel's avatar
Laurent Montel committed
501
    if (mFolder.isValid() && mMsg && isModified()) {
502
503
        SaveDraftJob *saveDraftJob = new SaveDraftJob(mMsg, mFolder);
        saveDraftJob->start();
Laurent Montel's avatar
Laurent Montel committed
504
    }
Volker Krause's avatar
Volker Krause committed
505

Laurent Montel's avatar
Laurent Montel committed
506
    delete mComposerBase;
Volker Krause's avatar
Volker Krause committed
507
508
}

Laurent Montel's avatar
Laurent Montel committed
509
void KMComposerWin::insertSnippetInfo(const MailCommon::SnippetInfo &info)
Laurent Montel's avatar
Laurent Montel committed
510
{
Laurent Montel's avatar
Laurent Montel committed
511
512
513
514
515
    {
        if (!info.to.isEmpty()) {
            const QStringList lst = info.to.split(QLatin1Char(','));
            for (const QString &addr : lst) {
                mComposerBase->recipientsEditor()->addRecipient(addr, MessageComposer::Recipient::To);
Laurent Montel's avatar
Laurent Montel committed
516
            }
Laurent Montel's avatar
Laurent Montel committed
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
        }
    }
    {
        if (!info.cc.isEmpty()) {
            const QStringList lst = info.cc.split(QLatin1Char(','));
            for (const QString &addr : lst) {
                mComposerBase->recipientsEditor()->addRecipient(addr, MessageComposer::Recipient::Cc);
            }
        }
    }
    {
        if (!info.bcc.isEmpty()) {
            const QStringList lst = info.bcc.split(QLatin1Char(','));
            for (const QString &addr : lst) {
                mComposerBase->recipientsEditor()->addRecipient(addr, MessageComposer::Recipient::Bcc);
            }
        }
Laurent Montel's avatar
Laurent Montel committed
534
    }
Laurent Montel's avatar
Laurent Montel committed
535
536
537
538
    {
        if (!info.attachment.isEmpty()) {
            const QStringList lst = info.attachment.split(QLatin1Char(','));
            for (const QString &attach : lst) {
Laurent Montel's avatar
Laurent Montel committed
539
540
541
542
543
544
545
                MessageComposer::ConvertSnippetVariablesJob *job = new MessageComposer::ConvertSnippetVariablesJob(this);
                job->setText(attach);
                MessageComposer::ComposerViewInterface *interface = new MessageComposer::ComposerViewInterface(mComposerBase);
                job->setComposerViewInterface(interface);
                connect(job, &MessageComposer::ConvertSnippetVariablesJob::textConverted, this, [this](const QString &str) {
                    if (!str.isEmpty()) {
                        const QUrl localUrl = QUrl::fromLocalFile(str);
546
547
                        AttachmentInfo info;
                        info.url = localUrl;
Laurent Montel's avatar
Laurent Montel committed
548
                        addAttachment(QVector<AttachmentInfo>() << info, false);
Laurent Montel's avatar
Laurent Montel committed
549
550
551
                    }
                });
                job->start();
Laurent Montel's avatar
Laurent Montel committed
552
553
554
            }
        }
    }
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
    {
        if (!info.subject.isEmpty()) {
            //Convert subject
            MessageComposer::ConvertSnippetVariablesJob *job = new MessageComposer::ConvertSnippetVariablesJob(this);
            job->setText(info.subject);
            MessageComposer::ComposerViewInterface *interface = new MessageComposer::ComposerViewInterface(mComposerBase);
            job->setComposerViewInterface(interface);
            connect(job, &MessageComposer::ConvertSnippetVariablesJob::textConverted, this, [this](const QString &str) {
                if (!str.isEmpty()) {
                    if (mComposerBase->subject().isEmpty()) { //Add subject only if we don't have subject
                        mEdtSubject->setText(str);
                    }
                }
            });
            job->start();
        }
    }
    {
        if (!info.text.isEmpty()) {
            //Convert plain text
            MessageComposer::ConvertSnippetVariablesJob *job = new MessageComposer::ConvertSnippetVariablesJob(this);
            job->setText(info.text);
            MessageComposer::ComposerViewInterface *interface = new MessageComposer::ComposerViewInterface(mComposerBase);
            job->setComposerViewInterface(interface);
            connect(job, &MessageComposer::ConvertSnippetVariablesJob::textConverted, this, [this](const QString &str) {
                mComposerBase->editor()->insertPlainText(str);
            });
            job->start();
        }
    }
Laurent Montel's avatar
Laurent Montel committed
585
586
}

Laurent Montel's avatar
Laurent Montel committed
587
void KMComposerWin::slotSpellCheckingLanguage(const QString &language)
Laurent Montel's avatar
Laurent Montel committed
588
{
Laurent Montel's avatar
Laurent Montel committed
589
590
    mComposerBase->editor()->setSpellCheckingLanguage(language);
    mEdtSubject->setSpellCheckingLanguage(language);
Laurent Montel's avatar
Laurent Montel committed
591
592
}

Laurent Montel's avatar
Laurent Montel committed
593
QString KMComposerWin::dbusObjectPath() const
Volker Krause's avatar
Volker Krause committed
594
{
Laurent Montel's avatar
Laurent Montel committed
595
    return mdbusObjectPath;
Volker Krause's avatar
Volker Krause committed
596
597
}

Laurent Montel's avatar
Laurent Montel committed
598
void KMComposerWin::slotEditorTextChanged()
Allen Winter's avatar
Allen Winter committed
599
{
Laurent Montel's avatar
Laurent Montel committed
600
    const bool textIsNotEmpty = !mComposerBase->editor()->document()->isEmpty();
Laurent Montel's avatar
Laurent Montel committed
601
602
603
604
    mFindText->setEnabled(textIsNotEmpty);
    mFindNextText->setEnabled(textIsNotEmpty);
    mReplaceText->setEnabled(textIsNotEmpty);
    mSelectAll->setEnabled(textIsNotEmpty);
Laurent Montel's avatar
Laurent Montel committed
605
606
    if (mVerifyMissingAttachment && !mVerifyMissingAttachment->isActive()) {
        mVerifyMissingAttachment->start();
607
    }
Allen Winter's avatar
Allen Winter committed
608
609
}

Laurent Montel's avatar
Laurent Montel committed
610
void KMComposerWin::send(int how)
Volker Krause's avatar
Volker Krause committed
611
{
Laurent Montel's avatar
Laurent Montel committed
612
    switch (how) {
Laurent Montel's avatar
Laurent Montel committed
613
614
615
616
617
    case 1:
        slotSendNow();
        break;
    default:
    case 0:
Laurent Montel's avatar
Laurent Montel committed
618
    // TODO: find out, what the default send method is and send it this way
Laurent Montel's avatar
Laurent Montel committed
619
620
621
622
    case 2:
        slotSendLater();
        break;
    }
Volker Krause's avatar
Volker Krause committed
623
624
}

Laurent Montel's avatar
Laurent Montel committed
625
void KMComposerWin::addAttachmentsAndSend(const QList<QUrl> &urls, const QString &comment, int how)
Volker Krause's avatar
Volker Krause committed
626
{
Laurent Montel's avatar
Laurent Montel committed
627
    const int nbUrl = urls.count();
Laurent Montel's avatar
Laurent Montel committed
628
    for (int i = 0; i < nbUrl; ++i) {
629
        mComposerBase->addAttachment(urls.at(i), comment, true);
Laurent Montel's avatar
Laurent Montel committed
630
    }
Laurent Montel's avatar
Laurent Montel committed
631

Laurent Montel's avatar
Laurent Montel committed
632
    send(how);
Volker Krause's avatar
Volker Krause committed
633
634
}

Laurent Montel's avatar
Laurent Montel committed
635
void KMComposerWin::addAttachment(const QVector<KMail::Composer::AttachmentInfo> &infos, bool showWarning)
Volker Krause's avatar
Volker Krause committed
636
{
637
638
639
640
641
642
643
644
645
646
647
    QStringList lst;
    for (const AttachmentInfo &info : infos) {
        if (showWarning) {
            lst.append(info.url.toDisplayString());
        }
        mComposerBase->addAttachment(info.url, info.comment, false);
    }
    if (showWarning) {
        mAttachmentFromExternalMissing->setAttachmentNames(lst);
        mAttachmentFromExternalMissing->animatedShow();
    }
Volker Krause's avatar
Volker Krause committed
648
649
}

Laurent Montel's avatar
Laurent Montel committed
650
void KMComposerWin::addAttachment(const QString &name, KMime::Headers::contentEncoding cte, const QString &charset, const QByteArray &data, const QByteArray &mimeType)
Volker Krause's avatar
Volker Krause committed
651
{
Laurent Montel's avatar
Laurent Montel committed
652
653
    Q_UNUSED(cte);
    mComposerBase->addAttachment(name, name, charset, data, mimeType);
Volker Krause's avatar
Volker Krause committed
654
655
}

Laurent Montel's avatar
Laurent Montel committed
656
void KMComposerWin::readConfig(bool reload /* = false */)
Volker Krause's avatar
Volker Krause committed
657
{
Laurent Montel's avatar
Laurent Montel committed
658
659
    mEdtFrom->setCompletionMode((KCompletion::CompletionMode)KMailSettings::self()->completionMode());
    mComposerBase->recipientsEditor()->setCompletionMode((KCompletion::CompletionMode)KMailSettings::self()->completionMode());
Laurent Montel's avatar
Laurent Montel committed
660

Laurent Montel's avatar
Laurent Montel committed
661
    if (MessageCore::MessageCoreSettings::self()->useDefaultFonts()) {
Laurent Montel's avatar
Laurent Montel committed
662
663
        mBodyFont = QFontDatabase::systemFont(QFontDatabase::GeneralFont);
        mFixedFont = QFontDatabase::systemFont(QFontDatabase::FixedFont);
Volker Krause's avatar
Volker Krause committed
664
    } else {
Laurent Montel's avatar
Laurent Montel committed
665
        mBodyFont = KMailSettings::self()->composerFont();
Laurent Montel's avatar
Laurent Montel committed
666
        mFixedFont = MessageViewer::MessageViewerSettings::self()->fixedFont();
Volker Krause's avatar
Volker Krause committed
667
668
    }

Laurent Montel's avatar
Laurent Montel committed
669
    slotUpdateFont();
Laurent Montel's avatar
Laurent Montel committed
670
671
    mEdtFrom->setFont(mBodyFont);
    mEdtSubject->setFont(mBodyFont);
Volker Krause's avatar
Volker Krause committed
672

Laurent Montel's avatar
Laurent Montel committed
673
    if (!reload) {
Laurent Montel's avatar
Laurent Montel committed
674
        QSize siz = KMailSettings::self()->composerSize();
Laurent Montel's avatar
Laurent Montel committed
675
676
        if (siz.width() < 200) {
            siz.setWidth(200);
Laurent Montel's avatar
Laurent Montel committed
677
        }
Laurent Montel's avatar
Laurent Montel committed
678
679
        if (siz.height() < 200) {
            siz.setHeight(200);
Laurent Montel's avatar
Laurent Montel committed
680
        }
Laurent Montel's avatar
Laurent Montel committed
681
        resize(siz);
Laurent Montel's avatar
Laurent Montel committed
682

Laurent Montel's avatar
Laurent Montel committed
683
684
        if (!KMailSettings::self()->snippetSplitterPosition().isEmpty()) {
            mSnippetSplitter->setSizes(KMailSettings::self()->snippetSplitterPosition());
Laurent Montel's avatar
Laurent Montel committed
685
686
687
        } else {
            QList<int> defaults;
            defaults << (int)(width() * 0.8) << (int)(width() * 0.2);
Laurent Montel's avatar
Laurent Montel committed
688
            mSnippetSplitter->setSizes(defaults);
Laurent Montel's avatar
Laurent Montel committed
689
690
691
        }
    }

Laurent Montel's avatar
Laurent Montel committed
692
    mComposerBase->identityCombo()->setCurrentIdentity(mId);
Laurent Montel's avatar
Laurent Montel committed
693
    qCDebug(KMAIL_LOG) << mComposerBase->identityCombo()->currentIdentityName();
Laurent Montel's avatar
Laurent Montel committed
694
695
    const KIdentityManagement::Identity &ident
        = kmkernel->identityManager()->identityForUoid(mId);
Volker Krause's avatar
Volker Krause committed
696

Laurent Montel's avatar
Laurent Montel committed
697
    mComposerBase->setAutoSaveInterval(KMailSettings::self()->autosaveInterval() * 1000 * 60);
698

Laurent Montel's avatar
Laurent Montel committed
699
    mComposerBase->dictionary()->setCurrentByDictionaryName(ident.dictionary());
Laurent Montel's avatar
Laurent Montel committed
700

Laurent Montel's avatar
Laurent Montel committed
701
    const QString fccName = ident.fcc();
Laurent Montel's avatar
Laurent Montel committed
702
    setFcc(fccName);
Volker Krause's avatar
Volker Krause committed
703
704
}

Laurent Montel's avatar
Laurent Montel committed
705
void KMComposerWin::writeConfig()
Laurent Montel's avatar
Laurent Montel committed
706
{
Laurent Montel's avatar
Laurent Montel committed
707
    KMailSettings::self()->setHeaders(mShowHeaders);
Laurent Montel's avatar
Laurent Montel committed
708
709
    KMailSettings::self()->setCurrentTransport(mComposerBase->transportComboBox()->currentText());
    KMailSettings::self()->setPreviousIdentity(mComposerBase->identityCombo()->currentIdentity());
Laurent Montel's avatar
Laurent Montel committed
710
711
    KMailSettings::self()->setPreviousFcc(QString::number(mFccFolder->collection().id()));
    KMailSettings::self()->setPreviousDictionary(mComposerBase->dictionary()->currentDictionaryName());
Laurent Montel's avatar
Laurent Montel committed
712
    KMailSettings::self()->setAutoSpellChecking(mAutoSpellCheckingAction->isChecked());
Laurent Montel's avatar
Laurent Montel committed
713
    MessageViewer::MessageViewerSettings::self()->setUseFixedFont(mFixedFontAction->isChecked());
Laurent Montel's avatar
Laurent Montel committed
714
    if (!mForceDisableHtml) {
Laurent Montel's avatar
Laurent Montel committed
715
        KMailSettings::self()->setUseHtmlMarkup(mComposerBase->editor()->textMode() == MessageComposer::RichTextComposerNg::Rich);
Laurent Montel's avatar
Laurent Montel committed
716
    }
Laurent Montel's avatar
Laurent Montel committed
717
718
    KMailSettings::self()->setComposerSize(size());
    KMailSettings::self()->setShowSnippetManager(mSnippetAction->isChecked());
Laurent Montel's avatar
Laurent Montel committed
719
720

    if (mSnippetAction->isChecked()) {
Laurent Montel's avatar
Laurent Montel committed
721
        KMailSettings::setSnippetSplitterPosition(mSnippetSplitter->sizes());
Laurent Montel's avatar
Laurent Montel committed
722
    }
Laurent Montel's avatar
Laurent Montel committed
723
724
725

    // make sure config changes are written to disk, cf. bug 127538
    KMKernel::self()->slotSyncConfig();
Volker Krause's avatar
Volker Krause committed
726
727
}

Laurent Montel's avatar
Laurent Montel committed
728
MessageComposer::Composer *KMComposerWin::createSimpleComposer()
729
{
Laurent Montel's avatar
Laurent Montel committed
730
    QVector< QByteArray > charsets = mCodecAction->mimeCharsets();
Laurent Montel's avatar
Laurent Montel committed
731
732
    if (!mOriginalPreferredCharset.isEmpty()) {
        charsets.insert(0, mOriginalPreferredCharset);
Laurent Montel's avatar
Laurent Montel committed
733
    }
Laurent Montel's avatar
Laurent Montel committed
734
735
736
    mComposerBase->setFrom(from());
    mComposerBase->setSubject(subject());
    mComposerBase->setCharsets(charsets);
Laurent Montel's avatar
Laurent Montel committed
737
    return mComposerBase->createSimpleComposer();
738
739
}

Laurent Montel's avatar
Laurent Montel committed
740
bool KMComposerWin::canSignEncryptAttachments() const
Laurent Montel's avatar
Laurent Montel committed
741
742
743
744
{
    return cryptoMessageFormat() != Kleo::InlineOpenPGPFormat;
}

745
void KMComposerWin::slotUpdateView()
Volker Krause's avatar
Volker Krause committed
746
{
Laurent Montel's avatar
Laurent Montel committed
747
    if (!mDone) {
Laurent Montel's avatar
Laurent Montel committed
748
749
750
751
752
753
        return; // otherwise called from rethinkFields during the construction
        // which is not the intended behavior
    }

    //This sucks awfully, but no, I cannot get an activated(int id) from
    // actionContainer()
Laurent Montel's avatar
Laurent Montel committed
754
755
    KToggleAction *act = ::qobject_cast<KToggleAction *>(sender());
    if (!act) {
Laurent Montel's avatar
Laurent Montel committed
756
757
758
759
        return;
    }
    int id;

Laurent Montel's avatar
Laurent Montel committed
760
    if (act == mAllFieldsAction) {
Laurent Montel's avatar
Laurent Montel committed
761
        id = 0;
Laurent Montel's avatar
Laurent Montel committed
762
    } else if (act == mIdentityAction) {
Laurent Montel's avatar
Laurent Montel committed
763
        id = HDR_IDENTITY;
Laurent Montel's avatar
Laurent Montel committed
764
    } else if (act == mTransportAction) {
Laurent Montel's avatar
Laurent Montel committed
765
        id = HDR_TRANSPORT;
Laurent Montel's avatar
Laurent Montel committed
766
    } else if (act == mFromAction) {
Laurent Montel's avatar
Laurent Montel committed
767
        id = HDR_FROM;
Laurent Montel's avatar
Laurent Montel committed
768
    } else if (act == mSubjectAction) {
Laurent Montel's avatar
Laurent Montel committed
769
        id = HDR_SUBJECT;
Laurent Montel's avatar
Laurent Montel committed
770
    } else if (act == mFccAction) {
Laurent Montel's avatar
Laurent Montel committed
771
        id = HDR_FCC;
Laurent Montel's avatar
Laurent Montel committed
772
    } else if (act == mDictionaryAction) {
Laurent Montel's avatar
Laurent Montel committed
773
        id = HDR_DICTIONARY;
Volker Krause's avatar
Volker Krause committed
774
    } else {
Laurent Montel's avatar
Laurent Montel committed
775
        qCDebug(KMAIL_LOG) << "Something is wrong (Oh, yeah?)";
Laurent Montel's avatar
Laurent Montel committed
776
        return;
Volker Krause's avatar
Volker Krause committed
777
    }
Laurent Montel's avatar
Laurent Montel committed
778

779
    bool forceAllHeaders = false;
Laurent Montel's avatar
Laurent Montel committed
780
781
782
    // sanders There's a bug here this logic doesn't work if no
    // fields are shown and then show all fields is selected.
    // Instead of all fields being shown none are.
Laurent Montel's avatar
Laurent Montel committed
783
    if (!act->isChecked()) {
Laurent Montel's avatar
Laurent Montel committed
784
        // hide header
Laurent Montel's avatar
Laurent Montel committed
785
        if (id > 0) {
Laurent Montel's avatar
Laurent Montel committed
786
787
            mShowHeaders = mShowHeaders & ~id;
        } else {
788
            mShowHeaders = std::abs(mShowHeaders);
Laurent Montel's avatar
Laurent Montel committed
789
        }
Volker Krause's avatar
Volker Krause committed
790
    } else {
Laurent Montel's avatar
Laurent Montel committed
791
        // show header
Laurent Montel's avatar
Laurent Montel committed
792
        if (id > 0) {
Laurent Montel's avatar
Laurent Montel committed
793
794
            mShowHeaders |= id;
        } else {
795
796
797
            mShowHeaders = -std::abs(mShowHeaders);
            if (mShowHeaders == 0) {
                forceAllHeaders = true;
798
            }
Laurent Montel's avatar
Laurent Montel committed
799
        }
Volker Krause's avatar
Volker Krause committed
800
    }
801
    rethinkFields(true, forceAllHeaders);
Volker Krause's avatar
Volker Krause committed
802
803
}

Laurent Montel's avatar
Laurent Montel committed
804
int KMComposerWin::calcColumnWidth(int which, long allShowing, int width) const
Volker Krause's avatar
Volker Krause committed
805
{
Laurent Montel's avatar
Laurent Montel committed
806
    if ((allShowing & which) == 0) {
Laurent Montel's avatar
Laurent Montel committed
807
808
809
        return width;
    }

Laurent Montel's avatar
Laurent Montel committed
810
    QLabel *w = nullptr;
Laurent Montel's avatar
Laurent Montel committed
811
    if (which ==