kmcomposerwin.cpp 159 KB
Newer Older
Volker Krause's avatar
Volker Krause committed
1
2
/*
 * This file is part of KMail.
Laurent Montel's avatar
Laurent Montel committed
3
 * SPDX-FileCopyrightText: 2011-2021 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
#include "editor/plugininterface/kmailplugineditorcheckbeforesendmanagerinterface.h"
Laurent Montel's avatar
Laurent Montel committed
20
#include "editor/plugininterface/kmailplugineditorconverttextmanagerinterface.h"
Sandro Knauß's avatar
Sandro Knauß committed
21
22
#include "editor/plugininterface/kmailplugineditorinitmanagerinterface.h"
#include "editor/plugininterface/kmailplugineditormanagerinterface.h"
23
#include "editor/plugininterface/kmailplugingrammareditormanagerinterface.h"
Sandro Knauß's avatar
Sandro Knauß committed
24
25
#include "editor/potentialphishingemail/potentialphishingemailjob.h"
#include "editor/potentialphishingemail/potentialphishingemailwarning.h"
26
#include "editor/warningwidgets/attachmentaddedfromexternalwarning.h"
Laurent Montel's avatar
Laurent Montel committed
27
#include "editor/warningwidgets/incorrectidentityfolderwarning.h"
Sandro Knauß's avatar
Sandro Knauß committed
28
29
#include "job/addressvalidationjob.h"
#include "job/createnewcontactjob.h"
Laurent Montel's avatar
Laurent Montel committed
30
#include "job/dndfromarkjob.h"
Sandro Knauß's avatar
Sandro Knauß committed
31
32
33
34
35
36
#include "job/saveasfilejob.h"
#include "job/savedraftjob.h"
#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"
Laurent Montel's avatar
Laurent Montel committed
44
#include "undosend/undosendmanager.h"
Sandro Knauß's avatar
Sandro Knauß committed
45
46
#include "util.h"
#include "validatesendmailshortcut.h"
Laurent Montel's avatar
Laurent Montel committed
47
48
#include "warningwidgets/attachmentmissingwarning.h"
#include "warningwidgets/externaleditorwarning.h"
Laurent Montel's avatar
Laurent Montel committed
49
#include "widgets/cryptostateindicatorwidget.h"
50
#include "widgets/kactionmenutransport.h"
51

Sandro Knauß's avatar
Sandro Knauß committed
52
53
54
55
56
57
#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
58

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

Sandro Knauß's avatar
Sandro Knauß committed
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#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>
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
#include <MessageComposer/ComposerLineEdit>
Laurent Montel's avatar
Laurent Montel committed
97
98
#include <MessageComposer/ComposerViewInterface>
#include <MessageComposer/ConvertSnippetVariablesJob>
Sandro Knauß's avatar
Sandro Knauß committed
99
#include <MessageComposer/FollowUpReminderSelectDateDialog>
100
#include <MessageComposer/FollowupReminder>
Laurent Montel's avatar
Laurent Montel committed
101
#include <MessageComposer/FollowupReminderCreateJob>
Laurent Montel's avatar
Laurent Montel committed
102
103
#include <MessageComposer/GlobalPart>
#include <MessageComposer/InfoPart>
Sandro Knauß's avatar
Sandro Knauß committed
104
105
106
#include <MessageComposer/InsertTextFileJob>
#include <MessageComposer/Kleo_Util>
#include <MessageComposer/MessageComposerSettings>
Laurent Montel's avatar
Laurent Montel committed
107
#include <MessageComposer/MessageHelper>
Laurent Montel's avatar
Laurent Montel committed
108
#include <MessageComposer/PluginActionType>
Sandro Knauß's avatar
Sandro Knauß committed
109
#include <MessageComposer/PluginEditorCheckBeforeSendParams>
Laurent Montel's avatar
Laurent Montel committed
110
111
#include <MessageComposer/PluginEditorConverterBeforeConvertingData>
#include <MessageComposer/PluginEditorConverterInitialData>
Sandro Knauß's avatar
Sandro Knauß committed
112
#include <MessageComposer/PluginEditorInterface>
Laurent Montel's avatar
Laurent Montel committed
113
#include <MessageComposer/RecipientsEditor>
Sandro Knauß's avatar
Sandro Knauß committed
114
#include <MessageComposer/RichTextComposerSignatures>
115
116
117
#include <MessageComposer/SendLaterDialog>
#include <MessageComposer/SendLaterInfo>
#include <MessageComposer/SendLaterUtil>
Laurent Montel's avatar
Laurent Montel committed
118
119
120
121
#include <MessageComposer/SignatureController>
#include <MessageComposer/StatusBarLabelToggledState>
#include <MessageComposer/TextPart>
#include <MessageComposer/Util>
122

Laurent Montel's avatar
Laurent Montel committed
123
#include <Sonnet/DictionaryComboBox>
Laurent Montel's avatar
Laurent Montel committed
124

Laurent Montel's avatar
Laurent Montel committed
125
#include <MessageCore/AttachmentPart>
126
#include <MessageCore/AutocryptStorage>
Laurent Montel's avatar
Laurent Montel committed
127
#include <MessageCore/MessageCoreSettings>
Laurent Montel's avatar
Laurent Montel committed
128
#include <MessageCore/NodeHelper>
Sandro Knauß's avatar
Sandro Knauß committed
129
#include <MessageCore/StringUtil>
Thomas McGuire's avatar
Thomas McGuire committed
130

Sandro Knauß's avatar
Sandro Knauß committed
131
132
#include <MessageViewer/MessageViewerSettings>
#include <MessageViewer/Stl_Util>
133

Sandro Knauß's avatar
Sandro Knauß committed
134
135
136
#include <MimeTreeParser/NodeHelper>
#include <MimeTreeParser/ObjectTreeParser>
#include <MimeTreeParser/SimpleObjectTreeSource>
137

Laurent Montel's avatar
Laurent Montel committed
138
#include <PimCommon/CustomToolsPluginManager>
Sandro Knauß's avatar
Sandro Knauß committed
139
140
141
#include <PimCommon/CustomToolsWidgetng>
#include <PimCommon/KActionMenuChangeCase>
#include <PimCommon/LineEditWithAutoCorrection>
Laurent Montel's avatar
Laurent Montel committed
142

Sandro Knauß's avatar
Sandro Knauß committed
143
144
145
146
147
#include <TemplateParser/TemplateParserJob>
#include <TemplateParser/TemplatesConfiguration>

#include <QGpgME/ExportJob>
#include <QGpgME/KeyForMailboxJob>
Laurent Montel's avatar
Laurent Montel committed
148
#include <QGpgME/Protocol>
Sandro Knauß's avatar
Sandro Knauß committed
149
150
151
152
153
154
155

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

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

189
190
191
#include <KDialogJobUiDelegate>
#include <KIO/CommandLauncherJob>

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

196
197
Q_DECLARE_METATYPE(MessageComposer::Recipient::Ptr)

Laurent Montel's avatar
Laurent Montel committed
198
199
200
201
202
203
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
204
205
                                     const QString &customTemplate)
{
Laurent Montel's avatar
Laurent Montel committed
206
    return KMComposerWin::create(msg, lastSignState, lastEncryptState, context, identity, textSelection, customTemplate);
Volker Krause's avatar
Volker Krause committed
207
208
}

Laurent Montel's avatar
Laurent Montel committed
209
210
211
212
213
214
215
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
216
{
Laurent Montel's avatar
Laurent Montel committed
217
    return new KMComposerWin(msg, lastSignState, lastEncryptState, context, identity, textSelection, customTemplate);
Volker Krause's avatar
Volker Krause committed
218
219
}

Laurent Montel's avatar
Laurent Montel committed
220
int KMComposerWin::s_composerNumber = 0;
Volker Krause's avatar
Volker Krause committed
221

Laurent Montel's avatar
Laurent Montel committed
222
223
224
225
226
227
228
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
229
230
231
232
233
234
    : KMail::Composer(QStringLiteral("kmail-composer#"))
    , mTextSelection(textSelection)
    , mCustomTemplate(customTemplate)
    , mFolder(Akonadi::Collection(-1))
    , mId(id)
    , mContext(context)
Laurent Montel's avatar
Laurent Montel committed
235
236
237
    , mPluginEditorManagerInterface(new KMailPluginEditorManagerInterface(this))
    , mPluginEditorGrammarManagerInterface(new KMailPluginGrammarEditorManagerInterface(this))

Laurent Montel's avatar
Laurent Montel committed
238
{
Laurent Montel's avatar
Laurent Montel committed
239
    mGlobalAction = new KMComposerGlobalAction(this, this);
Laurent Montel's avatar
Laurent Montel committed
240
241
    mComposerBase = new MessageComposer::ComposerViewBase(this, this);
    mComposerBase->setIdentityManager(kmkernel->identityManager());
Laurent Montel's avatar
Laurent Montel committed
242

Laurent Montel's avatar
Laurent Montel committed
243
    connect(mPluginEditorManagerInterface, &KMailPluginEditorManagerInterface::message, this, &KMComposerWin::slotMessage);
244
    connect(mPluginEditorManagerInterface, &KMailPluginEditorManagerInterface::insertText, this, &KMComposerWin::slotEditorPluginInsertText);
Laurent Montel's avatar
Laurent Montel committed
245
    mPluginEditorCheckBeforeSendManagerInterface = new KMailPluginEditorCheckBeforeSendManagerInterface(this);
Laurent Montel's avatar
Laurent Montel committed
246
    mPluginEditorInitManagerInterface = new KMailPluginEditorInitManagerInterface(this);
Laurent Montel's avatar
Laurent Montel committed
247
    mPluginEditorConvertTextManagerInterface = new KMailPluginEditorConvertTextManagerInterface(this);
Laurent Montel's avatar
Laurent Montel committed
248

249

Laurent Montel's avatar
Laurent Montel committed
250
251
252
253
254
    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
255

Laurent Montel's avatar
Laurent Montel committed
256
    (void)new MailcomposerAdaptor(this);
Laurent Montel's avatar
Laurent Montel committed
257
258
    mdbusObjectPath = QLatin1String("/Composer_") + QString::number(++s_composerNumber);
    QDBusConnection::sessionBus().registerObject(mdbusObjectPath, this);
Laurent Montel's avatar
Laurent Montel committed
259

260
    auto sigController = new MessageComposer::SignatureController(this);
Laurent Montel's avatar
Laurent Montel committed
261
    connect(sigController, &MessageComposer::SignatureController::enableHtml, this, &KMComposerWin::enableHtml);
Laurent Montel's avatar
Laurent Montel committed
262
    mComposerBase->setSignatureController(sigController);
Laurent Montel's avatar
Laurent Montel committed
263

Laurent Montel's avatar
Laurent Montel committed
264
    if (!kmkernel->xmlGuiInstanceName().isEmpty()) {
Laurent Montel's avatar
Laurent Montel committed
265
        setComponentName(kmkernel->xmlGuiInstanceName(), i18n("KMail2"));
Laurent Montel's avatar
Laurent Montel committed
266
    }
Laurent Montel's avatar
Laurent Montel committed
267
    mMainWidget = new QWidget(this);
Laurent Montel's avatar
Laurent Montel committed
268
    // splitter between the headers area and the actual editor
Laurent Montel's avatar
Laurent Montel committed
269
    mHeadersToEditorSplitter = new QSplitter(Qt::Vertical, mMainWidget);
Laurent Montel's avatar
Laurent Montel committed
270
    mHeadersToEditorSplitter->setObjectName(QStringLiteral("mHeadersToEditorSplitter"));
Laurent Montel's avatar
Laurent Montel committed
271
272
    mHeadersToEditorSplitter->setChildrenCollapsible(false);
    mHeadersArea = new QWidget(mHeadersToEditorSplitter);
Laurent Montel's avatar
Laurent Montel committed
273
    mHeadersArea->setSizePolicy(mHeadersToEditorSplitter->sizePolicy().horizontalPolicy(), QSizePolicy::Expanding);
Laurent Montel's avatar
Laurent Montel committed
274
    mHeadersToEditorSplitter->addWidget(mHeadersArea);
Laurent Montel's avatar
Laurent Montel committed
275
    const QList<int> defaultSizes{0};
Laurent Montel's avatar
Laurent Montel committed
276
    mHeadersToEditorSplitter->setSizes(defaultSizes);
Laurent Montel's avatar
Laurent Montel committed
277

278
    auto v = new QVBoxLayout(mMainWidget);
Laurent Montel's avatar
Laurent Montel committed
279
    v->setContentsMargins({});
Laurent Montel's avatar
Laurent Montel committed
280
    v->addWidget(mHeadersToEditorSplitter);
Laurent Montel's avatar
Laurent Montel committed
281
    auto identity = new KIdentityManagement::IdentityCombo(kmkernel->identityManager(), mHeadersArea);
282
    identity->setCurrentIdentity(mId);
Sandro Knauß's avatar
Sandro Knauß committed
283
    identity->setObjectName(QStringLiteral("identitycombo"));
284
    connect(identity, &KIdentityManagement::IdentityCombo::identityDeleted, this, &KMComposerWin::slotIdentityDeleted);
285
    connect(identity, &KIdentityManagement::IdentityCombo::invalidIdentity, this, &KMComposerWin::slotInvalidIdentity);
Laurent Montel's avatar
Laurent Montel committed
286
    mComposerBase->setIdentityCombo(identity);
Laurent Montel's avatar
Laurent Montel committed
287

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

291
    auto dictionaryCombo = new DictionaryComboBox(mHeadersArea);
292
    dictionaryCombo->setToolTip(i18n("Select the dictionary to use when spell-checking this message"));
293
    mComposerBase->setDictionary(dictionaryCombo);
Laurent Montel's avatar
Laurent Montel committed
294

Laurent Montel's avatar
Laurent Montel committed
295
296
297
    mFccFolder = new MailCommon::FolderRequester(mHeadersArea);
    mFccFolder->setNotAllowToCreateNewFolder(true);
    mFccFolder->setMustBeReadWrite(true);
Laurent Montel's avatar
Laurent Montel committed
298

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

303
    auto transport = new MailTransport::TransportComboBox(mHeadersArea);
Laurent Montel's avatar
Laurent Montel committed
304
305
    transport->setToolTip(i18n("Select the outgoing account to use for sending this message"));
    mComposerBase->setTransportCombo(transport);
Laurent Montel's avatar
Laurent Montel committed
306
    connect(transport, qOverload<int>(&MailTransport::TransportComboBox::activated), this, &KMComposerWin::slotTransportChanged);
307
    connect(transport, &MailTransport::TransportComboBox::transportRemoved, this, &KMComposerWin::slotTransportRemoved);
Laurent Montel's avatar
Laurent Montel committed
308
    mEdtFrom = new MessageComposer::ComposerLineEdit(false, mHeadersArea);
309
    mEdtFrom->installEventFilter(this);
Laurent Montel's avatar
Laurent Montel committed
310
    mEdtFrom->setObjectName(QStringLiteral("fromLine"));
Laurent Montel's avatar
Laurent Montel committed
311
312
    mEdtFrom->setRecentAddressConfig(MessageComposer::MessageComposerSettings::self()->config());
    mEdtFrom->setToolTip(i18n("Set the \"From:\" email address for this message"));
Laurent Montel's avatar
Laurent Montel committed
313

314
    auto recipientsEditor = new MessageComposer::RecipientsEditor(mHeadersArea);
Laurent Montel's avatar
Laurent Montel committed
315
    recipientsEditor->setRecentAddressConfig(MessageComposer::MessageComposerSettings::self()->config());
Laurent Montel's avatar
Laurent Montel committed
316
317
    connect(recipientsEditor, &MessageComposer::RecipientsEditor::completionModeChanged, this, &KMComposerWin::slotCompletionModeChanged);
    connect(recipientsEditor, &MessageComposer::RecipientsEditor::sizeHintChanged, this, &KMComposerWin::recipientEditorSizeHintChanged);
318
    connect(recipientsEditor, &MessageComposer::RecipientsEditor::lineAdded, this, &KMComposerWin::slotRecipientEditorLineAdded);
319
    connect(recipientsEditor, &MessageComposer::RecipientsEditor::focusInRecipientLineEdit, this, &KMComposerWin::slotRecipientEditorLineFocused);
Laurent Montel's avatar
Laurent Montel committed
320
    mComposerBase->setRecipientsEditor(recipientsEditor);
Laurent Montel's avatar
Laurent Montel committed
321

Laurent Montel's avatar
Laurent Montel committed
322
    mEdtSubject = new PimCommon::LineEditWithAutoCorrection(mHeadersArea, QStringLiteral("kmail2rc"));
323
    mEdtSubject->installEventFilter(this);
Laurent Montel's avatar
Laurent Montel committed
324
    mEdtSubject->setActivateLanguageMenu(false);
Laurent Montel's avatar
Laurent Montel committed
325
    mEdtSubject->setToolTip(i18n("Set a subject for this message"));
Laurent Montel's avatar
Laurent Montel committed
326
    mEdtSubject->setAutocorrection(KMKernel::self()->composerAutoCorrection());
Laurent Montel's avatar
Laurent Montel committed
327
328
329
330
331
332
    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
333
    mShowHeaders = KMailSettings::self()->headers();
Laurent Montel's avatar
Laurent Montel committed
334
335
    mDone = false;
    // the attachment view is separated from the editor by a splitter
Laurent Montel's avatar
Laurent Montel committed
336
    mSplitter = new QSplitter(Qt::Vertical, mMainWidget);
Laurent Montel's avatar
Laurent Montel committed
337
    mSplitter->setObjectName(QStringLiteral("mSplitter"));
Laurent Montel's avatar
Laurent Montel committed
338
339
    mSplitter->setChildrenCollapsible(false);
    mSnippetSplitter = new QSplitter(Qt::Horizontal, mSplitter);
Laurent Montel's avatar
Laurent Montel committed
340
    mSnippetSplitter->setObjectName(QStringLiteral("mSnippetSplitter"));
Laurent Montel's avatar
Laurent Montel committed
341
342
    mSplitter->addWidget(mSnippetSplitter);

Laurent Montel's avatar
Laurent Montel committed
343
    auto editorAndCryptoStateIndicators = new QWidget(mSplitter);
Laurent Montel's avatar
Laurent Montel committed
344
    mCryptoStateIndicatorWidget = new CryptoStateIndicatorWidget(this);
Laurent Montel's avatar
Laurent Montel committed
345
    mCryptoStateIndicatorWidget->setShowAlwaysIndicator(KMailSettings::self()->showCryptoLabelIndicator());
Laurent Montel's avatar
Laurent Montel committed
346

347
    auto vbox = new QVBoxLayout(editorAndCryptoStateIndicators);
Laurent Montel's avatar
Laurent Montel committed
348
    vbox->setContentsMargins({});
349

350
351
352
353
354
355
356
357
358
    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);

359
    auto composerEditorNg = new KMComposerEditorNg(this, mCryptoStateIndicatorWidget);
Laurent Montel's avatar
Laurent Montel committed
360
    mRichTextEditorwidget = new KPIMTextEdit::RichTextEditorWidget(composerEditorNg, mCryptoStateIndicatorWidget);
361
    composerEditorNg->installEventFilter(this);
Laurent Montel's avatar
Laurent Montel committed
362

363
    connect(composerEditorNg, &KMComposerEditorNg::insertEmoticon, mGlobalAction, &KMComposerGlobalAction::slotInsertEmoticon);
Laurent Montel's avatar
Laurent Montel committed
364
    // Don't use new connect api here. It crashes
365
    connect(composerEditorNg, SIGNAL(textChanged()), this, SLOT(slotEditorTextChanged()));
366
    connect(composerEditorNg, &KMComposerEditorNg::selectionChanged, this, &KMComposerWin::slotSelectionChanged);
Laurent Montel's avatar
Laurent Montel committed
367
    // connect(editor, &KMComposerEditor::textChanged, this, &KMComposeWin::slotEditorTextChanged);
Laurent Montel's avatar
Laurent Montel committed
368
    mComposerBase->setEditor(composerEditorNg);
369
370
371
    mIncorrectIdentityFolderWarning = new IncorrectIdentityFolderWarning(this);
    vbox->addWidget(mIncorrectIdentityFolderWarning);

372
373
374
    mAttachmentFromExternalMissing = new AttachmentAddedFromExternalWarning(this);
    vbox->addWidget(mAttachmentFromExternalMissing);

Laurent Montel's avatar
Laurent Montel committed
375
    vbox->addWidget(mCryptoStateIndicatorWidget);
376
    vbox->addWidget(mRichTextEditorwidget);
Laurent Montel's avatar
Laurent Montel committed
377

Laurent Montel's avatar
Laurent Montel committed
378
379
    mSnippetSplitter->insertWidget(0, editorAndCryptoStateIndicators);
    mSnippetSplitter->setOpaqueResize(true);
Laurent Montel's avatar
Laurent Montel committed
380
    sigController->setEditor(composerEditorNg);
Laurent Montel's avatar
Laurent Montel committed
381

Laurent Montel's avatar
Laurent Montel committed
382
    mHeadersToEditorSplitter->addWidget(mSplitter);
Laurent Montel's avatar
Laurent Montel committed
383
    composerEditorNg->setAcceptDrops(true);
Laurent Montel's avatar
Laurent Montel committed
384
385
386
387
    connect(sigController,
            &MessageComposer::SignatureController::signatureAdded,
            mComposerBase->editor()->externalComposer(),
            &KPIMTextEdit::RichTextExternalComposer::startExternalEditor);
Laurent Montel's avatar
Laurent Montel committed
388

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

Laurent Montel's avatar
Laurent Montel committed
391
392
393
394
    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
395
    mSnippetWidget = new MailCommon::SnippetTreeView(actionCollection(), mSnippetSplitter);
Laurent Montel's avatar
Laurent Montel committed
396
    connect(mSnippetWidget, &MailCommon::SnippetTreeView::insertSnippetInfo, this, &KMComposerWin::insertSnippetInfo);
Laurent Montel's avatar
Laurent Montel committed
397
    connect(composerEditorNg, &KMComposerEditorNg::insertSnippet, mSnippetWidget->snippetsManager(), &MailCommon::SnippetsManager::insertSnippet);
Laurent Montel's avatar
Laurent Montel committed
398
    mSnippetWidget->setVisible(KMailSettings::self()->showSnippetManager());
Laurent Montel's avatar
Laurent Montel committed
399
400
    mSnippetSplitter->addWidget(mSnippetWidget);
    mSnippetSplitter->setCollapsible(0, false);
401
    mSnippetSplitterCollapser = new KSplitterCollapserButton(mSnippetWidget, mSnippetSplitter);
Laurent Montel's avatar
Laurent Montel committed
402
    mSnippetSplitterCollapser->setVisible(KMailSettings::self()->showSnippetManager());
Laurent Montel's avatar
Laurent Montel committed
403

Laurent Montel's avatar
Laurent Montel committed
404
    mSplitter->setOpaqueResize(true);
Laurent Montel's avatar
Laurent Montel committed
405

Laurent Montel's avatar
Laurent Montel committed
406
    setWindowTitle(i18nc("@title:window", "Composer"));
Laurent Montel's avatar
Laurent Montel committed
407
    setMinimumSize(200, 200);
Laurent Montel's avatar
Laurent Montel committed
408

409
410
    mCustomToolsWidget = new PimCommon::CustomToolsWidgetNg(this);
    mCustomToolsWidget->initializeView(actionCollection(), PimCommon::CustomToolsPluginManager::self()->pluginsList());
Laurent Montel's avatar
Laurent Montel committed
411
    mSplitter->addWidget(mCustomToolsWidget);
Laurent Montel's avatar
Laurent Montel committed
412
    connect(mCustomToolsWidget, &PimCommon::CustomToolsWidgetNg::insertText, this, &KMComposerWin::slotInsertShortUrl);
Laurent Montel's avatar
Laurent Montel committed
413

414
415
    auto attachmentModel = new MessageComposer::AttachmentModel(this);
    auto attachmentView = new KMail::AttachmentView(attachmentModel, mSplitter);
Laurent Montel's avatar
Laurent Montel committed
416
    attachmentView->hideIfEmpty();
Laurent Montel's avatar
Laurent Montel committed
417
    connect(attachmentView, &KMail::AttachmentView::modified, this, &KMComposerWin::setModified);
418
    auto attachmentController = new KMail::AttachmentController(attachmentModel, attachmentView, this);
Laurent Montel's avatar
Laurent Montel committed
419

Laurent Montel's avatar
Laurent Montel committed
420
421
    mComposerBase->setAttachmentModel(attachmentModel);
    mComposerBase->setAttachmentController(attachmentController);
Laurent Montel's avatar
Laurent Montel committed
422

Laurent Montel's avatar
Laurent Montel committed
423
    if (KMailSettings::self()->showForgottenAttachmentWarning()) {
Laurent Montel's avatar
Laurent Montel committed
424
425
426
427
        mVerifyMissingAttachment = new QTimer(this);
        mVerifyMissingAttachment->setSingleShot(true);
        mVerifyMissingAttachment->setInterval(1000 * 5);
        connect(mVerifyMissingAttachment, &QTimer::timeout, this, &KMComposerWin::slotVerifyMissingAttachmentTimeout);
428
    }
Laurent Montel's avatar
Laurent Montel committed
429
    connect(attachmentController, &KMail::AttachmentController::fileAttached, mAttachmentMissing, &AttachmentMissingWarning::slotFileAttached);
Laurent Montel's avatar
Laurent Montel committed
430
431
432
433

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

Laurent Montel's avatar
Laurent Montel committed
434
435
    mPluginEditorManagerInterface->setParentWidget(this);
    mPluginEditorManagerInterface->setRichTextEditor(mRichTextEditorwidget->editor());
Laurent Montel's avatar
Laurent Montel committed
436
    mPluginEditorManagerInterface->setActionCollection(actionCollection());
Laurent Montel's avatar
Laurent Montel committed
437
    mPluginEditorManagerInterface->setComposerInterface(mComposerBase);
Laurent Montel's avatar
Laurent Montel committed
438

Laurent Montel's avatar
Laurent Montel committed
439
440
    mPluginEditorCheckBeforeSendManagerInterface->setParentWidget(this);

Laurent Montel's avatar
Laurent Montel committed
441
    mPluginEditorInitManagerInterface->setParentWidget(this);
Laurent Montel's avatar
Laurent Montel committed
442
    mPluginEditorInitManagerInterface->setRichTextEditor(composerEditorNg);
Laurent Montel's avatar
Laurent Montel committed
443

Laurent Montel's avatar
Laurent Montel committed
444
445
    mPluginEditorConvertTextManagerInterface->setParentWidget(this);
    mPluginEditorConvertTextManagerInterface->setActionCollection(actionCollection());
446
    mPluginEditorConvertTextManagerInterface->setRichTextEditor(composerEditorNg);
Laurent Montel's avatar
Laurent Montel committed
447

448
449
450
451
452
    mPluginEditorGrammarManagerInterface->setParentWidget(this);
    mPluginEditorGrammarManagerInterface->setActionCollection(actionCollection());
    mPluginEditorGrammarManagerInterface->setRichTextEditor(composerEditorNg);
    mPluginEditorGrammarManagerInterface->setCustomToolsWidget(mCustomToolsWidget);

Laurent Montel's avatar
Laurent Montel committed
453
454
455
456
    setupStatusBar(attachmentView->widget());
    setupActions();
    setupEditor();
    rethinkFields();
457
458
    readConfig();

Laurent Montel's avatar
Laurent Montel committed
459
    updateSignatureAndEncryptionStateIndicators();
Laurent Montel's avatar
Laurent Montel committed
460

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

463
    mUpdateWindowTitleConnection = connect(mEdtSubject, &PimCommon::LineEditWithAutoCorrection::textChanged, this, &KMComposerWin::slotUpdateWindowTitle);
Laurent Montel's avatar
Laurent Montel committed
464
    mIdentityConnection = connect(identity, &KIdentityManagement::IdentityCombo::identityChanged, this, [this](uint val) {
Laurent Montel's avatar
Laurent Montel committed
465
        slotIdentityChanged(val);
Laurent Montel's avatar
Laurent Montel committed
466
    });
Laurent Montel's avatar
Laurent Montel committed
467
    connect(kmkernel->identityManager(), qOverload<uint>(&KIdentityManagement::IdentityManager::changed), this, [this](uint val) {
468
        if (currentIdentity() == val) {
469
470
            slotIdentityChanged(val);
        }
Laurent Montel's avatar
Laurent Montel committed
471
    });
Laurent Montel's avatar
Laurent Montel committed
472

Laurent Montel's avatar
Laurent Montel committed
473
474
475
    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
476

Laurent Montel's avatar
Laurent Montel committed
477
    mMainWidget->resize(800, 600);
Laurent Montel's avatar
Laurent Montel committed
478
    setCentralWidget(mMainWidget);
Laurent Montel's avatar
Laurent Montel committed
479

Laurent Montel's avatar
Laurent Montel committed
480
    if (KMailSettings::self()->useHtmlMarkup()) {
Laurent Montel's avatar
Laurent Montel committed
481
        enableHtml();
Laurent Montel's avatar
Laurent Montel committed
482
483
484
    } else {
        disableHtml(MessageComposer::ComposerViewBase::LetUserConfirm);
    }
Laurent Montel's avatar
Laurent Montel committed
485

Laurent Montel's avatar
Laurent Montel committed
486
    if (KMailSettings::self()->useExternalEditor()) {
Laurent Montel's avatar
Laurent Montel committed
487
488
        composerEditorNg->setUseExternalEditor(true);
        composerEditorNg->setExternalEditorPath(KMailSettings::self()->externalEditor());
Laurent Montel's avatar
Laurent Montel committed
489
490
    }

Laurent Montel's avatar
Laurent Montel committed
491
492
    const QList<KPIM::MultiplyingLine *> lstLines = recipientsEditor->lines();
    for (KPIM::MultiplyingLine *line : lstLines) {
493
494
495
        slotRecipientEditorLineAdded(line);
    }

Laurent Montel's avatar
Laurent Montel committed
496
497
    if (aMsg) {
        setMessage(aMsg, lastSignState, lastEncryptState);
Laurent Montel's avatar
Laurent Montel committed
498
499
    }

500
    mComposerBase->recipientsEditor()->setFocusBottom();
Laurent Montel's avatar
Laurent Montel committed
501
    composerEditorNg->composerActions()->updateActionStates(); // set toolbar buttons to correct values
Laurent Montel's avatar
Laurent Montel committed
502
503
504

    mDone = true;

Laurent Montel's avatar
Laurent Montel committed
505
506
    mDummyComposer = new MessageComposer::Composer(this);
    mDummyComposer->globalPart()->setParentWidgetForGui(this);
507
508
509

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

Laurent Montel's avatar
Laurent Montel committed
512
KMComposerWin::~KMComposerWin()
Volker Krause's avatar
Volker Krause committed
513
{
514
    disconnect(mUpdateWindowTitleConnection);
Laurent Montel's avatar
Laurent Montel committed
515
516
517
    // 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
518
    if (mFolder.isValid() && mMsg && isModified()) {
519
        auto saveDraftJob = new SaveDraftJob(mMsg, mFolder);
520
        saveDraftJob->start();
Laurent Montel's avatar
Laurent Montel committed
521
    }
Volker Krause's avatar
Volker Krause committed
522

Laurent Montel's avatar
Laurent Montel committed
523
    delete mComposerBase;
Volker Krause's avatar
Volker Krause committed
524
525
}

526
527
528
529
530
void KMComposerWin::slotRecipientEditorLineFocused()
{
    mPluginEditorManagerInterface->setStatusBarWidgetEnabled(MessageComposer::PluginEditorInterface::ApplyOnFieldType::EmailFields);
}

531
532
533
534
535
536
537
538
539
540
KMComposerWin::ModeType KMComposerWin::modeType() const
{
    return mModeType;
}

void KMComposerWin::setModeType(const ModeType &modeType)
{
    mModeType = modeType;
}

541
542
543
544
545
546
547
548
549
550
551
552
553
554
bool KMComposerWin::eventFilter(QObject *obj, QEvent *event)
{
    if (event->type() == QEvent::FocusIn) {
        if (obj == mEdtSubject) {
            mPluginEditorManagerInterface->setStatusBarWidgetEnabled(MessageComposer::PluginEditorInterface::ApplyOnFieldType::SubjectField);
        } else if (obj == mComposerBase->recipientsEditor()) {
            mPluginEditorManagerInterface->setStatusBarWidgetEnabled(MessageComposer::PluginEditorInterface::ApplyOnFieldType::EmailFields);
        } else if (obj == mEdtFrom) {
            mPluginEditorManagerInterface->setStatusBarWidgetEnabled(MessageComposer::PluginEditorInterface::ApplyOnFieldType::EmailFields);
        }
    }
    return KMail::Composer::eventFilter(obj, event);
}

Laurent Montel's avatar
Laurent Montel committed
555
void KMComposerWin::insertSnippetInfo(const MailCommon::SnippetInfo &info)
Laurent Montel's avatar
Laurent Montel committed
556
{
Laurent Montel's avatar
Laurent Montel committed
557
558
    {
        if (!info.to.isEmpty()) {
Laurent Montel's avatar
Laurent Montel committed
559
            const QStringList lst = KEmailAddress::splitAddressList(info.to);
Laurent Montel's avatar
Laurent Montel committed
560
            for (const QString &addr : lst) {
561
562
563
                if (!mComposerBase->recipientsEditor()->addRecipient(addr, MessageComposer::Recipient::To)) {
                    qCWarning(KMAIL_LOG) << "Impossible to add to entry";
                }
Laurent Montel's avatar
Laurent Montel committed
564
            }
Laurent Montel's avatar
Laurent Montel committed
565
566
567
568
        }
    }
    {
        if (!info.cc.isEmpty()) {
Laurent Montel's avatar
Laurent Montel committed
569
            const QStringList lst = KEmailAddress::splitAddressList(info.cc);
Laurent Montel's avatar
Laurent Montel committed
570
            for (const QString &addr : lst) {
571
572
573
                if (!mComposerBase->recipientsEditor()->addRecipient(addr, MessageComposer::Recipient::Cc)) {
                    qCWarning(KMAIL_LOG) << "Impossible to add cc entry";
                }
Laurent Montel's avatar
Laurent Montel committed
574
575
576
577
578
            }
        }
    }
    {
        if (!info.bcc.isEmpty()) {
Laurent Montel's avatar
Laurent Montel committed
579
            const QStringList lst = KEmailAddress::splitAddressList(info.bcc);
Laurent Montel's avatar
Laurent Montel committed
580
            for (const QString &addr : lst) {
581
582
583
                if (!mComposerBase->recipientsEditor()->addRecipient(addr, MessageComposer::Recipient::Bcc)) {
                    qCWarning(KMAIL_LOG) << "Impossible to add bcc entry";
                }
Laurent Montel's avatar
Laurent Montel committed
584
585
            }
        }
Laurent Montel's avatar
Laurent Montel committed
586
    }
Laurent Montel's avatar
Laurent Montel committed
587
588
589
590
    {
        if (!info.attachment.isEmpty()) {
            const QStringList lst = info.attachment.split(QLatin1Char(','));
            for (const QString &attach : lst) {
591
                auto job = new MessageComposer::ConvertSnippetVariablesJob(this);
Laurent Montel's avatar
Laurent Montel committed
592
                job->setText(attach);
593
                auto interface = new MessageComposer::ComposerViewInterface(mComposerBase);
Laurent Montel's avatar
Laurent Montel committed
594
595
596
597
                job->setComposerViewInterface(interface);
                connect(job, &MessageComposer::ConvertSnippetVariablesJob::textConverted, this, [this](const QString &str) {
                    if (!str.isEmpty()) {
                        const QUrl localUrl = QUrl::fromLocalFile(str);
598
599
                        AttachmentInfo info;
                        info.url = localUrl;
Laurent Montel's avatar
Laurent Montel committed
600
                        addAttachment(QVector<AttachmentInfo>() << info, false);
Laurent Montel's avatar
Laurent Montel committed
601
602
603
                    }
                });
                job->start();
Laurent Montel's avatar
Laurent Montel committed
604
605
606
            }
        }
    }
607
608
    {
        if (!info.subject.isEmpty()) {
Laurent Montel's avatar
Laurent Montel committed
609
            // Convert subject
610
            auto job = new MessageComposer::ConvertSnippetVariablesJob(this);
611
            job->setText(info.subject);
612
            auto interface = new MessageComposer::ComposerViewInterface(mComposerBase);
613
614
615
            job->setComposerViewInterface(interface);
            connect(job, &MessageComposer::ConvertSnippetVariablesJob::textConverted, this, [this](const QString &str) {
                if (!str.isEmpty()) {
Laurent Montel's avatar
Laurent Montel committed
616
                    if (mComposerBase->subject().isEmpty()) { // Add subject only if we don't have subject
617
618
619
620
621
622
623
624
625
                        mEdtSubject->setText(str);
                    }
                }
            });
            job->start();
        }
    }
    {
        if (!info.text.isEmpty()) {
Laurent Montel's avatar
Laurent Montel committed
626
            // Convert plain text
627
            auto job = new MessageComposer::ConvertSnippetVariablesJob(this);
628
            job->setText(info.text);
629
            auto interface = new MessageComposer::ComposerViewInterface(mComposerBase);
630
631
632
633
634
635
636
            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
637
638
}

Laurent Montel's avatar
Laurent Montel committed
639
void KMComposerWin::slotSpellCheckingLanguage(const QString &language)
Laurent Montel's avatar
Laurent Montel committed
640
{
Laurent Montel's avatar
Laurent Montel committed
641
642
    mComposerBase->editor()->setSpellCheckingLanguage(language);
    mEdtSubject->setSpellCheckingLanguage(language);
Laurent Montel's avatar
Laurent Montel committed
643
644
}

Laurent Montel's avatar
Laurent Montel committed
645
QString KMComposerWin::dbusObjectPath() const
Volker Krause's avatar
Volker Krause committed
646
{
Laurent Montel's avatar
Laurent Montel committed
647
    return mdbusObjectPath;
Volker Krause's avatar
Volker Krause committed
648
649
}

Laurent Montel's avatar
Laurent Montel committed
650
void KMComposerWin::slotEditorTextChanged()
Allen Winter's avatar
Allen Winter committed
651
{
Laurent Montel's avatar
Laurent Montel committed
652
    const bool textIsNotEmpty = !mComposerBase->editor()->document()->isEmpty();
Laurent Montel's avatar
Laurent Montel committed
653
654
655
656
    mFindText->setEnabled(textIsNotEmpty);
    mFindNextText->setEnabled(textIsNotEmpty);
    mReplaceText->setEnabled(textIsNotEmpty);
    mSelectAll->setEnabled(textIsNotEmpty);
Laurent Montel's avatar
Laurent Montel committed
657
658
    if (mVerifyMissingAttachment && !mVerifyMissingAttachment->isActive()) {
        mVerifyMissingAttachment->start();
659
    }
Allen Winter's avatar
Allen Winter committed
660
661
}

Laurent Montel's avatar
Laurent Montel committed
662
void KMComposerWin::send(int how)
Volker Krause's avatar
Volker Krause committed
663
{
Laurent Montel's avatar
Laurent Montel committed
664
    switch (how) {
Laurent Montel's avatar
Laurent Montel committed
665
666
667
668
669
    case 1:
        slotSendNow();
        break;
    default:
    case 0:
Laurent Montel's avatar
Laurent Montel committed
670
    // TODO: find out, what the default send method is and send it this way
Laurent Montel's avatar
Laurent Montel committed
671
672
673
674
    case 2:
        slotSendLater();
        break;
    }
Volker Krause's avatar
Volker Krause committed
675
676
}

Laurent Montel's avatar
Laurent Montel committed
677
void KMComposerWin::addAttachmentsAndSend(const QList<QUrl> &urls, const QString &comment, int how)
Volker Krause's avatar
Volker Krause committed
678
{
Laurent Montel's avatar
Laurent Montel committed
679
    const int nbUrl = urls.count();
Laurent Montel's avatar
Laurent Montel committed
680
    for (int i = 0; i < nbUrl; ++i) {
681
        mComposerBase->addAttachment(urls.at(i), comment, true);
Laurent Montel's avatar
Laurent Montel committed
682
    }
Laurent Montel's avatar
Laurent Montel committed
683

Laurent Montel's avatar
Laurent Montel committed
684
    send(how);
Volker Krause's avatar
Volker Krause committed
685
686
}

Laurent Montel's avatar
Laurent Montel committed
687
void KMComposerWin::addAttachment(const QVector<KMail::Composer::AttachmentInfo> &infos, bool showWarning)
Volker Krause's avatar
Volker Krause committed
688
{
689
690
691
692
693
694
695
696
697
698
699
    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
700
701
}

Laurent Montel's avatar
Laurent Montel committed
702
703
704
705
706
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
707
{
Laurent Montel's avatar
Laurent Montel committed
708
    Q_UNUSED(cte)
Laurent Montel's avatar
Laurent Montel committed
709
    mComposerBase->addAttachment(name, name, charset, data, mimeType);
Volker Krause's avatar
Volker Krause committed
710
711
}

712
void KMComposerWin::readConfig(bool reload)
Volker Krause's avatar
Volker Krause committed
713
{
Laurent Montel's avatar
Laurent Montel committed
714
715
    mEdtFrom->setCompletionMode(static_cast<KCompletion::CompletionMode>(KMailSettings::self()->completionMode()));
    mComposerBase->recipientsEditor()->setCompletionMode(static_cast<KCompletion::CompletionMode>(KMailSettings::self()->completionMode()));
Laurent Montel's avatar
Laurent Montel committed
716

Laurent Montel's avatar
Laurent Montel committed
717
    if (MessageCore::MessageCoreSettings::self()->useDefaultFonts()) {
Laurent Montel's avatar
Laurent Montel committed
718
719
        mBodyFont = QFontDatabase::systemFont(QFontDatabase::GeneralFont);
        mFixedFont = QFontDatabase::systemFont(QFontDatabase::FixedFont);
Volker Krause's avatar
Volker Krause committed
720
    } else {
Laurent Montel's avatar
Laurent Montel committed
721
        mBodyFont = KMailSettings::self()->composerFont();
Laurent Montel's avatar
Laurent Montel committed
722
        mFixedFont = MessageViewer::MessageViewerSettings::self()->fixedFont();
Volker Krause's avatar
Volker Krause committed
723
724
    }

Laurent Montel's avatar
Laurent Montel committed
725
    slotUpdateFont();
Laurent Montel's avatar
Laurent Montel committed
726
727
    mEdtFrom->setFont(mBodyFont);
    mEdtSubject->setFont(mBodyFont);
Volker Krause's avatar
Volker Krause committed
728

Laurent Montel's avatar
Laurent Montel committed
729
    if (!reload) {
Laurent Montel's avatar
Laurent Montel committed
730
731
732
        QSize composerSize = KMailSettings::self()->composerSize();
        if (composerSize.width() < 200) {
            composerSize.setWidth(200);
Laurent Montel's avatar
Laurent Montel committed
733
        }
Laurent Montel's avatar
Laurent Montel committed
734
735
        if (composerSize.height() < 200) {
            composerSize.setHeight(200);
Laurent Montel's avatar
Laurent Montel committed
736
        }
Laurent Montel's avatar
Laurent Montel committed
737
        resize(composerSize);
Laurent Montel's avatar
Laurent Montel committed
738

Laurent Montel's avatar
Laurent Montel committed
739
740
        if (!KMailSettings::self()->snippetSplitterPosition().isEmpty()) {
            mSnippetSplitter->setSizes(KMailSettings::self()->snippetSplitterPosition());
Laurent Montel's avatar
Laurent Montel committed
741
742
743
        } else {
            QList<int> defaults;
            defaults << (int)(width() * 0.8) << (int)(width() * 0.2);
Laurent Montel's avatar
Laurent Montel committed
744
            mSnippetSplitter->setSizes(defaults);
Laurent Montel's avatar
Laurent Montel committed
745
746
747
        }
    }

Laurent Montel's avatar
Laurent Montel committed
748
    mComposerBase->identityCombo()->setCurrentIdentity(mId);
Laurent Montel's avatar
Laurent Montel committed
749
    qCDebug(KMAIL_LOG) << mComposerBase->identityCombo()->currentIdentityName();
Laurent Montel's avatar
Laurent Montel committed
750
    const KIdentityManagement::Identity &ident = kmkernel->identityManager()->identityForUoid(mId);
Volker Krause's avatar
Volker Krause committed
751

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

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

Laurent Montel's avatar
Laurent Montel committed
756
    const QString fccName = ident.fcc();
Laurent Montel's avatar
Laurent Montel committed
757
    setFcc(fccName);
Volker Krause's avatar
Volker Krause committed
758
759
}

Laurent Montel's avatar
Laurent Montel committed
760
void KMComposerWin::writeConfig()
Laurent Montel's avatar
Laurent Montel committed
761
{
Laurent Montel's avatar
Laurent Montel committed
762
    KMailSettings::self()->setHeaders(mShowHeaders);
Laurent Montel's avatar
Laurent Montel committed
763
    KMailSettings::self()->setCurrentTransport(mComposerBase->transportComboBox()->currentText());
764
    KMailSettings::self()->setPreviousIdentity(currentIdentity());
Laurent Montel's avatar
Laurent Montel committed
765
766
    KMailSettings::self()->setPreviousFcc(QString::number(mFccFolder->collection().id()));
    KMailSettings::self()->setPreviousDictionary(mComposerBase->dictionary()->currentDictionaryName());
Laurent Montel's avatar
Laurent Montel committed
767
    KMailSettings::self()->setAutoSpellChecking(mAutoSpellCheckingAction->isChecked());
Laurent Montel's avatar
Laurent Montel committed
768
    MessageViewer::MessageViewerSettings::self()->setUseFixedFont(mFixedFontAction->isChecked());
Laurent Montel's avatar
Laurent Montel committed
769
    if (!mForceDisableHtml) {
Laurent Montel's avatar
Laurent Montel committed
770
        KMailSettings::self()->setUseHtmlMarkup(mComposerBase->editor()->textMode() == MessageComposer::RichTextComposerNg::Rich);
Laurent Montel's avatar
Laurent Montel committed
771
    }
Laurent Montel's avatar
Laurent Montel committed
772
773
    KMailSettings::self()->setComposerSize(size());
    KMailSettings::self()->setShowSnippetManager(mSnippetAction->isChecked());
Laurent Montel's avatar
Laurent Montel committed
774
775

    if (mSnippetAction->isChecked()) {
Laurent Montel's avatar
Laurent Montel committed
776
        KMailSettings::setSnippetSplitterPosition(mSnippetSplitter->sizes());
Laurent Montel's avatar
Laurent Montel committed
777
    }
Laurent Montel's avatar
Laurent Montel committed
778
779
780

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

Laurent Montel's avatar
Laurent Montel committed
783
MessageComposer::Composer *KMComposerWin::createSimpleComposer()
784
{
Laurent Montel's avatar
Laurent Montel committed
785
    QVector<QByteArray> charsets = mCodecAction->mimeCharsets();
Laurent Montel's avatar
Laurent Montel committed
786
787
    if (!mOriginalPreferredCharset.isEmpty()) {
        charsets.insert(0, mOriginalPreferredCharset);
Laurent Montel's avatar
Laurent Montel committed
788
    }
Laurent Montel's avatar
Laurent Montel committed
789
790
791
    mComposerBase->setFrom(from());
    mComposerBase->setSubject(subject());
    mComposerBase->setCharsets(charsets);
Laurent Montel's avatar
Laurent Montel committed
792
    return mComposerBase->createSimpleComposer();
793
794
}

Laurent Montel's avatar
Laurent Montel committed
795
bool KMComposerWin::canSignEncryptAttachments() const
Laurent Montel's avatar
Laurent Montel committed
796
797
798
799
{
    return cryptoMessageFormat() != Kleo::InlineOpenPGPFormat;
}

800
void KMComposerWin::slotUpdateView()
Volker Krause's avatar
Volker Krause committed
801
{
Laurent Montel's avatar
Laurent Montel committed
802
    if (!mDone) {
Laurent Montel's avatar
Laurent Montel committed
803
804
805
806
        return; // otherwise called from rethinkFields during the construction
        // which is not the intended behavior
    }

Laurent Montel's avatar
Laurent Montel committed
807
    // This sucks awfully, but no, I cannot get an activated(int id) from
Laurent Montel's avatar
Laurent Montel committed
808
    // actionContainer()
Laurent Montel's avatar
Laurent Montel committed
809
    auto *act = ::qobject_cast<KToggleAction *>(sender());
Laurent Montel's avatar
Laurent Montel committed
810
    if (!act) {
Laurent Montel's avatar
Laurent Montel committed
811
812
813
814
        return;
    }
    int id;

Laurent Montel's avatar
Laurent Montel committed
815
    if (act == mAllFieldsAction) {
Laurent Montel's avatar
Laurent Montel committed
816
        id = 0;
Laurent Montel's avatar
Laurent Montel committed
817
    } else if (act == mIdentityAction) {
Laurent Montel's avatar
Laurent Montel committed
818
        id = HDR_IDENTITY;
Laurent Montel's avatar
Laurent Montel committed
819
    } else if (act == mTransportAction) {
Laurent Montel's avatar
Laurent Montel committed
820
        id = HDR_TRANSPORT;
Laurent Montel's avatar
Laurent Montel committed
821
    } else if (act == mFromAction) {
Laurent Montel's avatar
Laurent Montel committed
822
        id = HDR_FROM;