kmcomposerwin.cpp 141 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
 * Copyright (c) 2011-2018 Laurent Montel <montel@kde.org>
4
 *
Volker Krause's avatar
Volker Krause committed
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 * Copyright (c) 2009 Constantin Berzan <exit3219@gmail.com>
 *
 * Based on KMail code by:
 * Copyright (c) 1997 Markus Wuebben <markus.wuebben@kde.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */
Laurent Montel's avatar
Laurent Montel committed
24
#include "kmcomposerwin.h"
Volker Krause's avatar
Volker Krause committed
25
// KMail includes
Laurent Montel's avatar
Laurent Montel committed
26 27
#include "attachment/attachmentcontroller.h"
#include "attachment/attachmentview.h"
28
#include "codec/codecaction.h"
Sandro Knauß's avatar
Sandro Knauß committed
29
#include "custommimeheader.h"
30
#include "editor/kmcomposereditorng.h"
Sandro Knauß's avatar
Sandro Knauß committed
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
#include "editor/plugininterface/kmailplugineditorcheckbeforesendmanagerinterface.h"
#include "editor/plugininterface/kmailplugineditorinitmanagerinterface.h"
#include "editor/plugininterface/kmailplugineditormanagerinterface.h"
#include "editor/potentialphishingemail/potentialphishingemailjob.h"
#include "editor/potentialphishingemail/potentialphishingemailwarning.h"
#include "editor/warningwidgets/incorrectidentityfolderwarning.h"
#include "editor/widgets/snippetwidget.h"
#include "job/addressvalidationjob.h"
#include "job/createnewcontactjob.h"
#include "job/saveasfilejob.h"
#include "job/savedraftjob.h"
#include "kconfigwidgets_version.h"
#include "kmail_debug.h"
#include "kmcommands.h"
#include "kmcomposercreatenewcomposerjob.h"
#include "kmcomposerglobalaction.h"
Laurent Montel's avatar
Laurent Montel committed
47
#include "kmcomposerupdatetemplatejob.h"
48
#include "kmkernel.h"
49
#include "kmmainwidget.h"
Sandro Knauß's avatar
Sandro Knauß committed
50
#include "kmmainwin.h"
51
#include "mailcomposeradaptor.h" // TODO port all D-Bus stuff...
Sandro Knauß's avatar
Sandro Knauß committed
52
#include "settings/kmailsettings.h"
Laurent Montel's avatar
Laurent Montel committed
53
#include "templatesconfiguration_kfg.h"
Sandro Knauß's avatar
Sandro Knauß committed
54 55
#include "util.h"
#include "validatesendmailshortcut.h"
Laurent Montel's avatar
Laurent Montel committed
56 57
#include "warningwidgets/attachmentmissingwarning.h"
#include "warningwidgets/externaleditorwarning.h"
Laurent Montel's avatar
Laurent Montel committed
58
#include "widgets/cryptostateindicatorwidget.h"
59
#include "widgets/kactionmenutransport.h"
Sandro Knauß's avatar
Sandro Knauß committed
60
#include "widgets/statusbarlabeltoggledstate.h"
61

Sandro Knauß's avatar
Sandro Knauß committed
62 63 64 65 66 67
#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
68

Sandro Knauß's avatar
Sandro Knauß committed
69
#include <FollowupReminder/FollowUpReminderUtil>
Laurent Montel's avatar
Laurent Montel committed
70

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

Sandro Knauß's avatar
Sandro Knauß committed
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
#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 <KPIMTextEdit/SelectSpecialCharDialog>

#include <Libkdepim/ProgressStatusBarWidget>
#include <Libkdepim/StatusbarProgressWidget>
Laurent Montel's avatar
Laurent Montel committed
90 91

#ifndef QT_NO_CURSOR
92
#include <Libkdepim/KCursorSaver>
Laurent Montel's avatar
Laurent Montel committed
93 94
#endif

Sandro Knauß's avatar
Sandro Knauß committed
95 96 97 98 99 100 101 102 103 104 105 106 107
#include <Libkleo/KeySelectionDialog>
#include <Libkleo/ProgressDialog>

#include <MailCommon/FolderCollectionMonitor>
#include <MailCommon/FolderRequester>
#include <MailCommon/FolderSettings>
#include <MailCommon/MailKernel>

#include <MailTransport/Transport>
#include <MailTransport/TransportComboBox>
#include <MailTransport/TransportManager>

#include <MessageComposer/AttachmentModel>
Laurent Montel's avatar
Laurent Montel committed
108
#include <MessageComposer/Composer>
Sandro Knauß's avatar
Sandro Knauß committed
109 110 111
#include <MessageComposer/ComposerLineEdit>
#include <MessageComposer/FollowUpReminderSelectDateDialog>
#include <MessageComposer/FollowupReminderCreateJob>
Laurent Montel's avatar
Laurent Montel committed
112 113
#include <MessageComposer/GlobalPart>
#include <MessageComposer/InfoPart>
Sandro Knauß's avatar
Sandro Knauß committed
114 115 116
#include <MessageComposer/InsertTextFileJob>
#include <MessageComposer/Kleo_Util>
#include <MessageComposer/MessageComposerSettings>
Laurent Montel's avatar
Laurent Montel committed
117
#include <MessageComposer/MessageHelper>
Sandro Knauß's avatar
Sandro Knauß committed
118 119 120
#include <MessageComposer/PluginEditorCheckBeforeSendParams>
#include <MessageComposer/PluginEditorInterface>
#include <MessageComposer/RichTextComposerSignatures>
Laurent Montel's avatar
Laurent Montel committed
121
#include <MessageComposer/SignatureController>
Sandro Knauß's avatar
Sandro Knauß committed
122 123
#include <MessageComposer/TextPart>
#include <MessageComposer/Util>
Laurent Montel's avatar
Laurent Montel committed
124
#include <MessageComposer/DictionaryComboBox>
Laurent Montel's avatar
Laurent Montel committed
125

Laurent Montel's avatar
Laurent Montel committed
126
#include <MessageCore/AttachmentPart>
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

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

Sandro Knauß's avatar
Sandro Knauß committed
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
#include <SendLater/SendLaterDialog>
#include <SendLater/SendLaterInfo>
#include <SendLater/SendLaterUtil>

#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 <KDescendantsProxyModel>
#include <KEditToolBar>
160
#include <KEmailAddress>
161 162
#include <KEncodingFileDialog>
#include <KHelpClient>
Sandro Knauß's avatar
Sandro Knauß committed
163
#include <KIO/JobUiDelegate>
164
#include <KIconUtils>
Sandro Knauß's avatar
Sandro Knauß committed
165 166 167 168 169 170 171 172 173 174 175 176
#include <KMessageBox>
#include <KRecentFilesAction>
#include <KRun>
#include <KShortcutsDialog>
#include <KSplitterCollapserButton>
#include <KStandardShortcut>
#include <KToggleAction>
#include <KToolBar>
#include <KToolInvocation>
#include <KXMLGUIFactory>

#include <sonnet_version.h>
Volker Krause's avatar
Volker Krause committed
177 178

// Qt includes
179
#include <QAction>
180
#include <QApplication>
181
#include <QCheckBox>
Sandro Knauß's avatar
Sandro Knauß committed
182 183
#include <QClipboard>
#include <QFileDialog>
184
#include <QFontDatabase>
Sandro Knauß's avatar
Sandro Knauß committed
185 186 187
#include <QInputDialog>
#include <QMenu>
#include <QMimeData>
188 189
#include <QMimeDatabase>
#include <QMimeType>
190
#include <QPointer>
Sandro Knauß's avatar
Sandro Knauß committed
191 192 193 194 195 196
#include <QShortcut>
#include <QSplitter>
#include <QStandardPaths>
#include <QStatusBar>
#include <QTemporaryDir>
#include <QTextDocumentWriter>
197
#include <QMenuBar>
198 199 200 201

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

Laurent Montel's avatar
Laurent Montel committed
203
using MessageComposer::DictionaryComboBox;
Thomas McGuire's avatar
Thomas McGuire committed
204 205
using MailTransport::TransportManager;
using MailTransport::Transport;
Volker Krause's avatar
Volker Krause committed
206

207 208
Q_DECLARE_METATYPE(MessageComposer::Recipient::Ptr)

Laurent Montel's avatar
Laurent Montel committed
209
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
210 211
                                     const QString &customTemplate)
{
Laurent Montel's avatar
Laurent Montel committed
212
    return KMComposerWin::create(msg, lastSignState, lastEncryptState, context, identity, textSelection, customTemplate);
Volker Krause's avatar
Volker Krause committed
213 214
}

Laurent Montel's avatar
Laurent Montel committed
215
KMail::Composer *KMComposerWin::create(const KMime::Message::Ptr &msg, bool lastSignState, bool lastEncryptState, Composer::TemplateContext context, uint identity, const QString &textSelection,
Laurent Montel's avatar
Laurent Montel committed
216
                                       const QString &customTemplate)
Laurent Montel's avatar
Laurent Montel committed
217
{
Laurent Montel's avatar
Laurent Montel committed
218
    return new KMComposerWin(msg, lastSignState, lastEncryptState, context, identity, textSelection, customTemplate);
Volker Krause's avatar
Volker Krause committed
219 220
}

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

Laurent Montel's avatar
Laurent Montel committed
223 224 225 226 227 228 229 230
KMComposerWin::KMComposerWin(const KMime::Message::Ptr &aMsg, bool lastSignState, bool lastEncryptState, Composer::TemplateContext context, uint id, const QString &textSelection,
                             const QString &customTemplate)
    : KMail::Composer(QStringLiteral("kmail-composer#"))
    , mTextSelection(textSelection)
    , mCustomTemplate(customTemplate)
    , mFolder(Akonadi::Collection(-1))
    , mId(id)
    , mContext(context)
Laurent Montel's avatar
Laurent Montel committed
231
{
Laurent Montel's avatar
Laurent Montel committed
232
    mGlobalAction = new KMComposerGlobalAction(this, this);
Laurent Montel's avatar
Laurent Montel committed
233 234
    mComposerBase = new MessageComposer::ComposerViewBase(this, this);
    mComposerBase->setIdentityManager(kmkernel->identityManager());
Laurent Montel's avatar
Laurent Montel committed
235

Laurent Montel's avatar
Laurent Montel committed
236
    mPluginEditorManagerInterface = new KMailPluginEditorManagerInterface(this);
Laurent Montel's avatar
Laurent Montel committed
237
    connect(mPluginEditorManagerInterface, &KMailPluginEditorManagerInterface::message, this, &KMComposerWin::slotMessage);
Laurent Montel's avatar
Laurent Montel committed
238
    mPluginEditorCheckBeforeSendManagerInterface = new KMailPluginEditorCheckBeforeSendManagerInterface(this);
Laurent Montel's avatar
Laurent Montel committed
239
    mPluginEditorInitManagerInterface = new KMailPluginEditorInitManagerInterface(this);
Laurent Montel's avatar
Laurent Montel committed
240

Laurent Montel's avatar
Laurent Montel committed
241 242 243 244 245
    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
246

Laurent Montel's avatar
Laurent Montel committed
247
    (void)new MailcomposerAdaptor(this);
Laurent Montel's avatar
Laurent Montel committed
248 249
    mdbusObjectPath = QLatin1String("/Composer_") + QString::number(++s_composerNumber);
    QDBusConnection::sessionBus().registerObject(mdbusObjectPath, this);
Laurent Montel's avatar
Laurent Montel committed
250

Laurent Montel's avatar
Laurent Montel committed
251
    MessageComposer::SignatureController *sigController = new MessageComposer::SignatureController(this);
Laurent Montel's avatar
Laurent Montel committed
252
    connect(sigController, &MessageComposer::SignatureController::enableHtml, this, &KMComposerWin::enableHtml);
Laurent Montel's avatar
Laurent Montel committed
253
    mComposerBase->setSignatureController(sigController);
Laurent Montel's avatar
Laurent Montel committed
254

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

Laurent Montel's avatar
Laurent Montel committed
272
    QVBoxLayout *v = new QVBoxLayout(mMainWidget);
Laurent Montel's avatar
Laurent Montel committed
273
    v->setMargin(0);
Laurent Montel's avatar
Laurent Montel committed
274 275
    v->addWidget(mHeadersToEditorSplitter);
    KIdentityManagement::IdentityCombo *identity = new KIdentityManagement::IdentityCombo(kmkernel->identityManager(),
Laurent Montel's avatar
Laurent Montel committed
276
                                                                                          mHeadersArea);
277
    identity->setCurrentIdentity(mId);
278
    connect(identity, &KIdentityManagement::IdentityCombo::identityDeleted, this, &KMComposerWin::slotIdentityDeleted);
Laurent Montel's avatar
Laurent Montel committed
279
    mComposerBase->setIdentityCombo(identity);
Laurent Montel's avatar
Laurent Montel committed
280

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

Laurent Montel's avatar
Laurent Montel committed
284
    MessageComposer::DictionaryComboBox *dictionaryCombo = new DictionaryComboBox(mHeadersArea);
285
    dictionaryCombo->setToolTip(i18n("Select the dictionary to use when spell-checking this message"));
286
    mComposerBase->setDictionary(dictionaryCombo);
Laurent Montel's avatar
Laurent Montel committed
287

Laurent Montel's avatar
Laurent Montel committed
288 289 290
    mFccFolder = new MailCommon::FolderRequester(mHeadersArea);
    mFccFolder->setNotAllowToCreateNewFolder(true);
    mFccFolder->setMustBeReadWrite(true);
Laurent Montel's avatar
Laurent Montel committed
291

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

Laurent Montel's avatar
Laurent Montel committed
296 297 298
    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
299
    connect(transport, QOverload<int>::of(&MailTransport::TransportComboBox::activated), this, &KMComposerWin::slotTransportChanged);
300
    connect(transport, &MailTransport::TransportComboBox::transportRemoved, this, &KMComposerWin::slotTransportRemoved);
Laurent Montel's avatar
Laurent Montel committed
301
    mEdtFrom = new MessageComposer::ComposerLineEdit(false, mHeadersArea);
Laurent Montel's avatar
Laurent Montel committed
302
    mEdtFrom->setObjectName(QStringLiteral("fromLine"));
Laurent Montel's avatar
Laurent Montel committed
303 304 305
    mEdtFrom->setRecentAddressConfig(MessageComposer::MessageComposerSettings::self()->config());
    mEdtFrom->setToolTip(i18n("Set the \"From:\" email address for this message"));
    mEdtReplyTo = new MessageComposer::ComposerLineEdit(true, mHeadersArea);
Laurent Montel's avatar
Laurent Montel committed
306
    mEdtReplyTo->setObjectName(QStringLiteral("replyToLine"));
Laurent Montel's avatar
Laurent Montel committed
307 308
    mEdtReplyTo->setRecentAddressConfig(MessageComposer::MessageComposerSettings::self()->config());
    mEdtReplyTo->setToolTip(i18n("Set the \"Reply-To:\" email address for this message"));
Laurent Montel's avatar
Laurent Montel committed
309
    connect(mEdtReplyTo, &MessageComposer::ComposerLineEdit::completionModeChanged, this, &KMComposerWin::slotCompletionModeChanged);
Laurent Montel's avatar
Laurent Montel committed
310

Laurent Montel's avatar
Laurent Montel committed
311 312
    MessageComposer::RecipientsEditor *recipientsEditor = new MessageComposer::RecipientsEditor(mHeadersArea);
    recipientsEditor->setRecentAddressConfig(MessageComposer::MessageComposerSettings::self()->config());
Laurent Montel's avatar
Laurent Montel committed
313 314
    connect(recipientsEditor, &MessageComposer::RecipientsEditor::completionModeChanged, this, &KMComposerWin::slotCompletionModeChanged);
    connect(recipientsEditor, &MessageComposer::RecipientsEditor::sizeHintChanged, this, &KMComposerWin::recipientEditorSizeHintChanged);
315
    connect(recipientsEditor, &MessageComposer::RecipientsEditor::lineAdded, this, &KMComposerWin::slotRecipientEditorLineAdded);
Laurent Montel's avatar
Laurent Montel committed
316
    mComposerBase->setRecipientsEditor(recipientsEditor);
Laurent Montel's avatar
Laurent Montel committed
317

Laurent Montel's avatar
Laurent Montel committed
318
    mEdtSubject = new PimCommon::LineEditWithAutoCorrection(mHeadersArea, QStringLiteral("kmail2rc"));
Laurent Montel's avatar
Laurent Montel committed
319
    mEdtSubject->setActivateLanguageMenu(false);
Laurent Montel's avatar
Laurent Montel committed
320
    mEdtSubject->setToolTip(i18n("Set a subject for this message"));
Laurent Montel's avatar
Laurent Montel committed
321
    mEdtSubject->setAutocorrection(KMKernel::self()->composerAutoCorrection());
Laurent Montel's avatar
Laurent Montel committed
322 323 324 325 326 327 328
    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);
    mLblReplyTo = new QLabel(i18n("&Reply to:"), mHeadersArea);
    mLblSubject = new QLabel(i18nc("@label:textbox Subject of email.", "S&ubject:"), mHeadersArea);
Laurent Montel's avatar
Laurent Montel committed
329
    mShowHeaders = KMailSettings::self()->headers();
Laurent Montel's avatar
Laurent Montel committed
330
    mDone = false;
Laurent Montel's avatar
Laurent Montel committed
331 332
    mGrid = nullptr;
    mFixedFontAction = nullptr;
Laurent Montel's avatar
Laurent Montel committed
333
    // the attachment view is separated from the editor by a splitter
Laurent Montel's avatar
Laurent Montel committed
334
    mSplitter = new QSplitter(Qt::Vertical, mMainWidget);
Laurent Montel's avatar
Laurent Montel committed
335
    mSplitter->setObjectName(QStringLiteral("mSplitter"));
Laurent Montel's avatar
Laurent Montel committed
336 337
    mSplitter->setChildrenCollapsible(false);
    mSnippetSplitter = new QSplitter(Qt::Horizontal, mSplitter);
Laurent Montel's avatar
Laurent Montel committed
338
    mSnippetSplitter->setObjectName(QStringLiteral("mSnippetSplitter"));
Laurent Montel's avatar
Laurent Montel committed
339 340 341
    mSplitter->addWidget(mSnippetSplitter);

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

345 346
    QVBoxLayout *vbox = new QVBoxLayout(editorAndCryptoStateIndicators);
    vbox->setMargin(0);
347

348 349 350 351 352 353 354 355 356
    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
357 358
    KMComposerEditorNg *composerEditorNg = new KMComposerEditorNg(this, mCryptoStateIndicatorWidget);
    mRichTextEditorwidget = new KPIMTextEdit::RichTextEditorWidget(composerEditorNg, mCryptoStateIndicatorWidget);
Laurent Montel's avatar
Laurent Montel committed
359

360
    //Don't use new connect api here. It crashs
Laurent Montel's avatar
Laurent Montel committed
361
    connect(composerEditorNg, SIGNAL(textChanged()), this, SLOT(slotEditorTextChanged()));
362
    connect(composerEditorNg, &KMComposerEditorNg::selectionChanged, this, &KMComposerWin::slotSelectionChanged);
363
    //connect(editor, &KMComposerEditor::textChanged, this, &KMComposeWin::slotEditorTextChanged);
Laurent Montel's avatar
Laurent Montel committed
364
    mComposerBase->setEditor(composerEditorNg);
365 366 367
    mIncorrectIdentityFolderWarning = new IncorrectIdentityFolderWarning(this);
    vbox->addWidget(mIncorrectIdentityFolderWarning);

Laurent Montel's avatar
Laurent Montel committed
368
    vbox->addWidget(mCryptoStateIndicatorWidget);
369
    vbox->addWidget(mRichTextEditorwidget);
Laurent Montel's avatar
Laurent Montel committed
370

Laurent Montel's avatar
Laurent Montel committed
371 372
    mSnippetSplitter->insertWidget(0, editorAndCryptoStateIndicators);
    mSnippetSplitter->setOpaqueResize(true);
Laurent Montel's avatar
Laurent Montel committed
373
    sigController->setEditor(composerEditorNg);
Laurent Montel's avatar
Laurent Montel committed
374

Laurent Montel's avatar
Laurent Montel committed
375
    mHeadersToEditorSplitter->addWidget(mSplitter);
Laurent Montel's avatar
Laurent Montel committed
376
    composerEditorNg->setAcceptDrops(true);
Laurent Montel's avatar
Laurent Montel committed
377 378
    connect(sigController, &MessageComposer::SignatureController::signatureAdded,
            mComposerBase->editor()->externalComposer(), &KPIMTextEdit::RichTextExternalComposer::startExternalEditor);
Laurent Montel's avatar
Laurent Montel committed
379

Laurent Montel's avatar
Laurent Montel committed
380
    connect(dictionaryCombo, &MessageComposer::DictionaryComboBox::dictionaryChanged, this, &KMComposerWin::slotSpellCheckingLanguage);
Laurent Montel's avatar
Laurent Montel committed
381

Laurent Montel's avatar
Laurent Montel committed
382 383 384 385 386
    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);
    mSnippetWidget = new SnippetWidget(composerEditorNg, actionCollection(), mSnippetSplitter);
Laurent Montel's avatar
Laurent Montel committed
387
    mSnippetWidget->setVisible(KMailSettings::self()->showSnippetManager());
Laurent Montel's avatar
Laurent Montel committed
388 389
    mSnippetSplitter->addWidget(mSnippetWidget);
    mSnippetSplitter->setCollapsible(0, false);
390
    mSnippetSplitterCollapser = new KSplitterCollapserButton(mSnippetWidget, mSnippetSplitter);
Laurent Montel's avatar
Laurent Montel committed
391
    mSnippetSplitterCollapser->setVisible(KMailSettings::self()->showSnippetManager());
Laurent Montel's avatar
Laurent Montel committed
392

Laurent Montel's avatar
Laurent Montel committed
393
    mSplitter->setOpaqueResize(true);
Laurent Montel's avatar
Laurent Montel committed
394

Laurent Montel's avatar
Laurent Montel committed
395 396
    setWindowTitle(i18n("Composer"));
    setMinimumSize(200, 200);
Laurent Montel's avatar
Laurent Montel committed
397

Laurent Montel's avatar
Laurent Montel committed
398
    mCustomToolsWidget = new PimCommon::CustomToolsWidgetNg(actionCollection(), this);
Laurent Montel's avatar
Laurent Montel committed
399
    mSplitter->addWidget(mCustomToolsWidget);
Laurent Montel's avatar
Laurent Montel committed
400
    connect(mCustomToolsWidget, &PimCommon::CustomToolsWidgetNg::insertText, this, &KMComposerWin::slotInsertShortUrl);
Laurent Montel's avatar
Laurent Montel committed
401

Laurent Montel's avatar
Laurent Montel committed
402 403
    MessageComposer::AttachmentModel *attachmentModel = new MessageComposer::AttachmentModel(this);
    KMail::AttachmentView *attachmentView = new KMail::AttachmentView(attachmentModel, mSplitter);
Laurent Montel's avatar
Laurent Montel committed
404
    attachmentView->hideIfEmpty();
Laurent Montel's avatar
Laurent Montel committed
405
    connect(attachmentView, &KMail::AttachmentView::modified, this, &KMComposerWin::setModified);
Laurent Montel's avatar
Laurent Montel committed
406
    KMail::AttachmentController *attachmentController = new KMail::AttachmentController(attachmentModel, attachmentView, this);
Laurent Montel's avatar
Laurent Montel committed
407

Laurent Montel's avatar
Laurent Montel committed
408 409
    mComposerBase->setAttachmentModel(attachmentModel);
    mComposerBase->setAttachmentController(attachmentController);
Laurent Montel's avatar
Laurent Montel committed
410

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

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

Laurent Montel's avatar
Laurent Montel committed
422 423
    mPluginEditorManagerInterface->setParentWidget(this);
    mPluginEditorManagerInterface->setRichTextEditor(mRichTextEditorwidget->editor());
Laurent Montel's avatar
Laurent Montel committed
424
    mPluginEditorManagerInterface->setActionCollection(actionCollection());
Laurent Montel's avatar
Laurent Montel committed
425

Laurent Montel's avatar
Laurent Montel committed
426 427
    mPluginEditorCheckBeforeSendManagerInterface->setParentWidget(this);

Laurent Montel's avatar
Laurent Montel committed
428
    mPluginEditorInitManagerInterface->setParent(this);
Laurent Montel's avatar
Laurent Montel committed
429
    mPluginEditorInitManagerInterface->setRichTextEditor(composerEditorNg);
Laurent Montel's avatar
Laurent Montel committed
430

Laurent Montel's avatar
Laurent Montel committed
431 432 433 434
    setupStatusBar(attachmentView->widget());
    setupActions();
    setupEditor();
    rethinkFields();
435 436
    readConfig();

Laurent Montel's avatar
Laurent Montel committed
437
    updateSignatureAndEncryptionStateIndicators();
Laurent Montel's avatar
Laurent Montel committed
438

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

Laurent Montel's avatar
Laurent Montel committed
441
    connect(mEdtSubject, &PimCommon::LineEditWithAutoCorrection::textChanged, this, &KMComposerWin::slotUpdateWindowTitle);
Laurent Montel's avatar
Laurent Montel committed
442 443 444
    connect(identity, &KIdentityManagement::IdentityCombo::identityChanged, [this](uint val) {
        slotIdentityChanged(val);
    });
Laurent Montel's avatar
Laurent Montel committed
445 446 447
    connect(kmkernel->identityManager(), QOverload<uint>::of(&KIdentityManagement::IdentityManager::changed), this, [this](uint val) {
        slotIdentityChanged(val);
    });
Laurent Montel's avatar
Laurent Montel committed
448

Laurent Montel's avatar
Laurent Montel committed
449 450 451
    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
452

Laurent Montel's avatar
Laurent Montel committed
453
    mMainWidget->resize(800, 600);
Laurent Montel's avatar
Laurent Montel committed
454
    setCentralWidget(mMainWidget);
Laurent Montel's avatar
Laurent Montel committed
455

Laurent Montel's avatar
Laurent Montel committed
456
    if (KMailSettings::self()->useHtmlMarkup()) {
Laurent Montel's avatar
Laurent Montel committed
457
        enableHtml();
Laurent Montel's avatar
Laurent Montel committed
458 459 460
    } else {
        disableHtml(MessageComposer::ComposerViewBase::LetUserConfirm);
    }
Laurent Montel's avatar
Laurent Montel committed
461

Laurent Montel's avatar
Laurent Montel committed
462
    if (KMailSettings::self()->useExternalEditor()) {
Laurent Montel's avatar
Laurent Montel committed
463 464
        composerEditorNg->setUseExternalEditor(true);
        composerEditorNg->setExternalEditorPath(KMailSettings::self()->externalEditor());
Laurent Montel's avatar
Laurent Montel committed
465 466
    }

Laurent Montel's avatar
Laurent Montel committed
467 468
    const QList<KPIM::MultiplyingLine *> lstLines = recipientsEditor->lines();
    for (KPIM::MultiplyingLine *line : lstLines) {
469 470 471
        slotRecipientEditorLineAdded(line);
    }

Laurent Montel's avatar
Laurent Montel committed
472 473
    if (aMsg) {
        setMessage(aMsg, lastSignState, lastEncryptState);
Laurent Montel's avatar
Laurent Montel committed
474 475 476
    }

    mComposerBase->recipientsEditor()->setFocus();
Laurent Montel's avatar
Laurent Montel committed
477
    composerEditorNg->composerActions()->updateActionStates(); // set toolbar buttons to correct values
Laurent Montel's avatar
Laurent Montel committed
478 479 480

    mDone = true;

Laurent Montel's avatar
Laurent Montel committed
481 482
    mDummyComposer = new MessageComposer::Composer(this);
    mDummyComposer->globalPart()->setParentWidgetForGui(this);
483 484 485

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

Laurent Montel's avatar
Laurent Montel committed
488
KMComposerWin::~KMComposerWin()
Volker Krause's avatar
Volker Krause committed
489
{
Laurent Montel's avatar
Laurent Montel committed
490 491 492
    // 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
493
    if (mFolder.isValid() && mMsg && isModified()) {
494 495
        SaveDraftJob *saveDraftJob = new SaveDraftJob(mMsg, mFolder);
        saveDraftJob->start();
Laurent Montel's avatar
Laurent Montel committed
496
    }
Volker Krause's avatar
Volker Krause committed
497

Laurent Montel's avatar
Laurent Montel committed
498
    delete mComposerBase;
Volker Krause's avatar
Volker Krause committed
499 500
}

Laurent Montel's avatar
Laurent Montel committed
501
void KMComposerWin::slotSpellCheckingLanguage(const QString &language)
Laurent Montel's avatar
Laurent Montel committed
502
{
Laurent Montel's avatar
Laurent Montel committed
503 504
    mComposerBase->editor()->setSpellCheckingLanguage(language);
    mEdtSubject->setSpellCheckingLanguage(language);
Laurent Montel's avatar
Laurent Montel committed
505 506
}

Laurent Montel's avatar
Laurent Montel committed
507
QString KMComposerWin::dbusObjectPath() const
Volker Krause's avatar
Volker Krause committed
508
{
Laurent Montel's avatar
Laurent Montel committed
509
    return mdbusObjectPath;
Volker Krause's avatar
Volker Krause committed
510 511
}

Laurent Montel's avatar
Laurent Montel committed
512
void KMComposerWin::slotEditorTextChanged()
Allen Winter's avatar
Allen Winter committed
513
{
Laurent Montel's avatar
Laurent Montel committed
514
    const bool textIsNotEmpty = !mComposerBase->editor()->document()->isEmpty();
Laurent Montel's avatar
Laurent Montel committed
515 516 517 518
    mFindText->setEnabled(textIsNotEmpty);
    mFindNextText->setEnabled(textIsNotEmpty);
    mReplaceText->setEnabled(textIsNotEmpty);
    mSelectAll->setEnabled(textIsNotEmpty);
Laurent Montel's avatar
Laurent Montel committed
519 520
    if (mVerifyMissingAttachment && !mVerifyMissingAttachment->isActive()) {
        mVerifyMissingAttachment->start();
521
    }
Allen Winter's avatar
Allen Winter committed
522 523
}

Laurent Montel's avatar
Laurent Montel committed
524
void KMComposerWin::send(int how)
Volker Krause's avatar
Volker Krause committed
525
{
Laurent Montel's avatar
Laurent Montel committed
526
    switch (how) {
Laurent Montel's avatar
Laurent Montel committed
527 528 529 530 531
    case 1:
        slotSendNow();
        break;
    default:
    case 0:
Laurent Montel's avatar
Laurent Montel committed
532
    // TODO: find out, what the default send method is and send it this way
Laurent Montel's avatar
Laurent Montel committed
533 534 535 536
    case 2:
        slotSendLater();
        break;
    }
Volker Krause's avatar
Volker Krause committed
537 538
}

Laurent Montel's avatar
Laurent Montel committed
539
void KMComposerWin::addAttachmentsAndSend(const QList<QUrl> &urls, const QString &comment, int how)
Volker Krause's avatar
Volker Krause committed
540
{
Laurent Montel's avatar
Laurent Montel committed
541
    const int nbUrl = urls.count();
Laurent Montel's avatar
Laurent Montel committed
542
    for (int i = 0; i < nbUrl; ++i) {
543
        mComposerBase->addAttachment(urls.at(i), comment, true);
Laurent Montel's avatar
Laurent Montel committed
544
    }
Laurent Montel's avatar
Laurent Montel committed
545

Laurent Montel's avatar
Laurent Montel committed
546
    send(how);
Volker Krause's avatar
Volker Krause committed
547 548
}

Laurent Montel's avatar
Laurent Montel committed
549
void KMComposerWin::addAttachment(const QUrl &url, const QString &comment)
Volker Krause's avatar
Volker Krause committed
550
{
551
    mComposerBase->addAttachment(url, comment, false);
Volker Krause's avatar
Volker Krause committed
552 553
}

Laurent Montel's avatar
Laurent Montel committed
554
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
555
{
Laurent Montel's avatar
Laurent Montel committed
556 557
    Q_UNUSED(cte);
    mComposerBase->addAttachment(name, name, charset, data, mimeType);
Volker Krause's avatar
Volker Krause committed
558 559
}

Laurent Montel's avatar
Laurent Montel committed
560
void KMComposerWin::readConfig(bool reload /* = false */)
Volker Krause's avatar
Volker Krause committed
561
{
Laurent Montel's avatar
Laurent Montel committed
562 563 564
    mEdtFrom->setCompletionMode((KCompletion::CompletionMode)KMailSettings::self()->completionMode());
    mComposerBase->recipientsEditor()->setCompletionMode((KCompletion::CompletionMode)KMailSettings::self()->completionMode());
    mEdtReplyTo->setCompletionMode((KCompletion::CompletionMode)KMailSettings::self()->completionMode());
Laurent Montel's avatar
Laurent Montel committed
565

Laurent Montel's avatar
Laurent Montel committed
566
    if (MessageCore::MessageCoreSettings::self()->useDefaultFonts()) {
Laurent Montel's avatar
Laurent Montel committed
567 568
        mBodyFont = QFontDatabase::systemFont(QFontDatabase::GeneralFont);
        mFixedFont = QFontDatabase::systemFont(QFontDatabase::FixedFont);
Volker Krause's avatar
Volker Krause committed
569
    } else {
Laurent Montel's avatar
Laurent Montel committed
570
        mBodyFont = KMailSettings::self()->composerFont();
Laurent Montel's avatar
Laurent Montel committed
571
        mFixedFont = MessageViewer::MessageViewerSettings::self()->fixedFont();
Volker Krause's avatar
Volker Krause committed
572 573
    }

Laurent Montel's avatar
Laurent Montel committed
574
    slotUpdateFont();
Laurent Montel's avatar
Laurent Montel committed
575 576 577
    mEdtFrom->setFont(mBodyFont);
    mEdtReplyTo->setFont(mBodyFont);
    mEdtSubject->setFont(mBodyFont);
Volker Krause's avatar
Volker Krause committed
578

Laurent Montel's avatar
Laurent Montel committed
579
    if (!reload) {
Laurent Montel's avatar
Laurent Montel committed
580
        QSize siz = KMailSettings::self()->composerSize();
Laurent Montel's avatar
Laurent Montel committed
581 582
        if (siz.width() < 200) {
            siz.setWidth(200);
Laurent Montel's avatar
Laurent Montel committed
583
        }
Laurent Montel's avatar
Laurent Montel committed
584 585
        if (siz.height() < 200) {
            siz.setHeight(200);
Laurent Montel's avatar
Laurent Montel committed
586
        }
Laurent Montel's avatar
Laurent Montel committed
587
        resize(siz);
Laurent Montel's avatar
Laurent Montel committed
588

Laurent Montel's avatar
Laurent Montel committed
589 590
        if (!KMailSettings::self()->snippetSplitterPosition().isEmpty()) {
            mSnippetSplitter->setSizes(KMailSettings::self()->snippetSplitterPosition());
Laurent Montel's avatar
Laurent Montel committed
591 592 593
        } else {
            QList<int> defaults;
            defaults << (int)(width() * 0.8) << (int)(width() * 0.2);
Laurent Montel's avatar
Laurent Montel committed
594
            mSnippetSplitter->setSizes(defaults);
Laurent Montel's avatar
Laurent Montel committed
595 596 597
        }
    }

Laurent Montel's avatar
Laurent Montel committed
598
    mComposerBase->identityCombo()->setCurrentIdentity(mId);
Laurent Montel's avatar
Laurent Montel committed
599
    qCDebug(KMAIL_LOG) << mComposerBase->identityCombo()->currentIdentityName();
Laurent Montel's avatar
Laurent Montel committed
600 601
    const KIdentityManagement::Identity &ident
        = kmkernel->identityManager()->identityForUoid(mId);
Volker Krause's avatar
Volker Krause committed
602

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

Laurent Montel's avatar
Laurent Montel committed
605
    mComposerBase->dictionary()->setCurrentByDictionaryName(ident.dictionary());
Laurent Montel's avatar
Laurent Montel committed
606 607

    QString fccName;
Laurent Montel's avatar
Laurent Montel committed
608
    if (!ident.fcc().isEmpty()) {
609
        fccName = ident.fcc();
Laurent Montel's avatar
Laurent Montel committed
610
    }
Laurent Montel's avatar
Laurent Montel committed
611
    setFcc(fccName);
Volker Krause's avatar
Volker Krause committed
612 613
}

Laurent Montel's avatar
Laurent Montel committed
614
void KMComposerWin::writeConfig(void)
Laurent Montel's avatar
Laurent Montel committed
615
{
Laurent Montel's avatar
Laurent Montel committed
616
    KMailSettings::self()->setHeaders(mShowHeaders);
Laurent Montel's avatar
Laurent Montel committed
617 618
    KMailSettings::self()->setCurrentTransport(mComposerBase->transportComboBox()->currentText());
    KMailSettings::self()->setPreviousIdentity(mComposerBase->identityCombo()->currentIdentity());
Laurent Montel's avatar
Laurent Montel committed
619 620
    KMailSettings::self()->setPreviousFcc(QString::number(mFccFolder->collection().id()));
    KMailSettings::self()->setPreviousDictionary(mComposerBase->dictionary()->currentDictionaryName());
Laurent Montel's avatar
Laurent Montel committed
621
    KMailSettings::self()->setAutoSpellChecking(mAutoSpellCheckingAction->isChecked());
Laurent Montel's avatar
Laurent Montel committed
622
    MessageViewer::MessageViewerSettings::self()->setUseFixedFont(mFixedFontAction->isChecked());
Laurent Montel's avatar
Laurent Montel committed
623
    if (!mForceDisableHtml) {
Laurent Montel's avatar
Laurent Montel committed
624
        KMailSettings::self()->setUseHtmlMarkup(mComposerBase->editor()->textMode() == MessageComposer::RichTextComposerNg::Rich);
Laurent Montel's avatar
Laurent Montel committed
625
    }
Laurent Montel's avatar
Laurent Montel committed
626 627
    KMailSettings::self()->setComposerSize(size());
    KMailSettings::self()->setShowSnippetManager(mSnippetAction->isChecked());
Laurent Montel's avatar
Laurent Montel committed
628 629

    if (mSnippetAction->isChecked()) {
Laurent Montel's avatar
Laurent Montel committed
630
        KMailSettings::setSnippetSplitterPosition(mSnippetSplitter->sizes());
Laurent Montel's avatar
Laurent Montel committed
631
    }
Laurent Montel's avatar
Laurent Montel committed
632 633 634

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

Laurent Montel's avatar
Laurent Montel committed
637
MessageComposer::Composer *KMComposerWin::createSimpleComposer()
638
{
Laurent Montel's avatar
Laurent Montel committed
639
    QList< QByteArray > charsets = mCodecAction->mimeCharsets();
Laurent Montel's avatar
Laurent Montel committed
640 641
    if (!mOriginalPreferredCharset.isEmpty()) {
        charsets.insert(0, mOriginalPreferredCharset);
Laurent Montel's avatar
Laurent Montel committed
642
    }
Laurent Montel's avatar
Laurent Montel committed
643 644 645 646
    mComposerBase->setFrom(from());
    mComposerBase->setReplyTo(replyTo());
    mComposerBase->setSubject(subject());
    mComposerBase->setCharsets(charsets);
Laurent Montel's avatar
Laurent Montel committed
647
    return mComposerBase->createSimpleComposer();
648 649
}

Laurent Montel's avatar
Laurent Montel committed
650
bool KMComposerWin::canSignEncryptAttachments() const
Laurent Montel's avatar
Laurent Montel committed
651 652 653 654
{
    return cryptoMessageFormat() != Kleo::InlineOpenPGPFormat;
}

655
void KMComposerWin::slotUpdateView()
Volker Krause's avatar
Volker Krause committed
656
{
Laurent Montel's avatar
Laurent Montel committed
657
    if (!mDone) {
Laurent Montel's avatar
Laurent Montel committed
658 659 660 661 662 663
        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
664 665
    KToggleAction *act = ::qobject_cast<KToggleAction *>(sender());
    if (!act) {
Laurent Montel's avatar
Laurent Montel committed
666 667 668 669
        return;
    }
    int id;

Laurent Montel's avatar
Laurent Montel committed
670
    if (act == mAllFieldsAction) {
Laurent Montel's avatar
Laurent Montel committed
671
        id = 0;
Laurent Montel's avatar
Laurent Montel committed
672
    } else if (act == mIdentityAction) {
Laurent Montel's avatar
Laurent Montel committed
673
        id = HDR_IDENTITY;
Laurent Montel's avatar
Laurent Montel committed
674
    } else if (act == mTransportAction) {
Laurent Montel's avatar
Laurent Montel committed
675
        id = HDR_TRANSPORT;
Laurent Montel's avatar
Laurent Montel committed
676
    } else if (act == mFromAction) {
Laurent Montel's avatar
Laurent Montel committed
677
        id = HDR_FROM;
Laurent Montel's avatar
Laurent Montel committed
678
    } else if (act == mReplyToAction) {
Laurent Montel's avatar
Laurent Montel committed
679
        id = HDR_REPLY_TO;
Laurent Montel's avatar
Laurent Montel committed
680
    } else if (act == mSubjectAction) {
Laurent Montel's avatar
Laurent Montel committed
681
        id = HDR_SUBJECT;
Laurent Montel's avatar
Laurent Montel committed
682
    } else if (act == mFccAction) {
Laurent Montel's avatar
Laurent Montel committed
683
        id = HDR_FCC;
Laurent Montel's avatar
Laurent Montel committed
684
    } else if (act == mDictionaryAction) {
Laurent Montel's avatar
Laurent Montel committed
685
        id = HDR_DICTIONARY;
Volker Krause's avatar
Volker Krause committed
686
    } else {
Laurent Montel's avatar
Laurent Montel committed
687
        qCDebug(KMAIL_LOG) << "Something is wrong (Oh, yeah?)";
Laurent Montel's avatar
Laurent Montel committed
688
        return;
Volker Krause's avatar
Volker Krause committed
689
    }
Laurent Montel's avatar
Laurent Montel committed
690

691
    bool forceAllHeaders = false;
Laurent Montel's avatar
Laurent Montel committed
692 693 694
    // 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
695
    if (!act->isChecked()) {
Laurent Montel's avatar
Laurent Montel committed
696
        // hide header
Laurent Montel's avatar
Laurent Montel committed
697
        if (id > 0) {
Laurent Montel's avatar
Laurent Montel committed
698 699
            mShowHeaders = mShowHeaders & ~id;
        } else {
700
            mShowHeaders = std::abs(mShowHeaders);
Laurent Montel's avatar
Laurent Montel committed
701
        }
Volker Krause's avatar
Volker Krause committed
702
    } else {
Laurent Montel's avatar
Laurent Montel committed
703
        // show header
Laurent Montel's avatar
Laurent Montel committed
704
        if (id > 0) {
Laurent Montel's avatar
Laurent Montel committed
705 706
            mShowHeaders |= id;
        } else {
707 708 709
            mShowHeaders = -std::abs(mShowHeaders);
            if (mShowHeaders == 0) {
                forceAllHeaders = true;
710
            }
Laurent Montel's avatar
Laurent Montel committed
711
        }
Volker Krause's avatar
Volker Krause committed
712
    }
713
    rethinkFields(true, forceAllHeaders);
Volker Krause's avatar
Volker Krause committed
714 715
}

Laurent Montel's avatar
Laurent Montel committed
716
int KMComposerWin::calcColumnWidth(int which, long allShowing, int width) const
Volker Krause's avatar
Volker Krause committed
717
{
Laurent Montel's avatar
Laurent Montel committed
718
    if ((allShowing & which) == 0) {
Laurent Montel's avatar
Laurent Montel committed
719 720 721
        return width;
    }

Laurent Montel's avatar
Laurent Montel committed
722
    QLabel *w = nullptr;
Laurent Montel's avatar
Laurent Montel committed
723
    if (which == HDR_IDENTITY) {
Laurent Montel's avatar
Laurent Montel committed
724
        w = mLblIdentity;
Laurent Montel's avatar
Laurent Montel committed
725
    } else if (which == HDR_DICTIONARY) {
Laurent Montel's avatar
Laurent Montel committed
726
        w = mDictionaryLabel;
Laurent Montel's avatar
Laurent Montel committed
727
    } else if (which == HDR_FCC) {
Laurent Montel's avatar
Laurent Montel committed
728
        w = mLblFcc;
Laurent Montel's avatar
Laurent Montel committed
729
    } else if (which == HDR_TRANSPORT) {
Laurent Montel's avatar
Laurent Montel committed
730
        w = mLblTransport;
Laurent Montel's avatar
Laurent Montel committed
731
    } else if (which == HDR_FROM) {
Laurent Montel's avatar
Laurent Montel committed
732
        w = mLblFrom;
Laurent Montel's avatar
Laurent Montel committed
733
    } else if (which == HDR_REPLY_TO) {
Laurent Montel's avatar
Laurent Montel committed
734
        w = mLblReplyTo;
Laurent Montel's avatar
Laurent Montel committed
735
    } else if (which == HDR_SUBJECT) {
Laurent Montel's avatar
Laurent Montel committed
736 737 738 739 740
        w = mLblSubject;
    } else {
        return width;
    }

Laurent Montel's avatar
Laurent Montel committed
741
    w->setBuddy(mComposerBase->editor());   // set dummy so we don't calculate width of '&' for this label.
Laurent Montel's avatar
Laurent Montel committed
742 743
    w->adjustSize();
    w->show();
Laurent Montel's avatar
Laurent Montel committed
744
    return qMax(width, w->sizeHint().width());
Volker Krause's avatar
Volker Krause committed
745 746
}

747
void KMComposerWin::rethinkFields(bool fromSlot, bool forceAllHeaders)
Volker Krause's avatar
Volker Krause committed
748
{
Laurent Montel's avatar
Laurent Montel committed
749 750 751 752
    //This sucks even more but again no ids. sorry (sven)
    int mask, row;
    long showHeaders;

753
    if ((mShowHeaders < 0) || forceAllHeaders) {
Laurent Montel's avatar
Laurent Montel committed
754 755 756 757 758
        showHeaders = HDR_ALL;
    } else {
        showHeaders = mShowHeaders;
    }

Laurent Montel's avatar
Laurent Montel committed
759 760
    for (mask = 1, mNumHeaders = 0; mask <= showHeaders; mask <<= 1) {
        if ((showHeaders & mask) != 0) {
Laurent Montel's avatar
Laurent Montel committed
761
            ++mNumHeaders;
Laurent Montel's avatar
Laurent Montel committed
762 763 764
        }
    }
    delete mGrid;
Laurent Montel's avatar
Laurent Montel committed
765 766 767 768
    mGrid = new QGridLayout(mHeadersArea);
    mGrid->setColumnStretch(0, 1);
    mGrid->setColumnStretch(1, 100);
    mGrid->setRowStretch(mNumHeaders + 1, 100);
Laurent Montel's avatar
Laurent Montel committed
769 770 771

    row = 0;

Laurent Montel's avatar
Laurent Montel committed
772
    mLabelWidth = mComposerBase->recipientsEditor()->setFirstColumnWidth(0) + 2;
773
    if (std::abs(showHeaders)&HDR_IDENTITY) {
Laurent Montel's avatar
Laurent Montel committed
774
        mLabelWidth = calcColumnWidth(HDR_IDENTITY, showHeaders, mLabelWidth);
Laurent Montel's avatar
Laurent Montel committed
775
    }
776
    if (std::abs(showHeaders)&HDR_DICTIONARY) {
Laurent Montel's avatar
Laurent Montel committed
777
        mLabelWidth = calcColumnWidth(HDR_DICTIONARY, showHeaders, mLabelWidth);
Laurent Montel's avatar
Laurent Montel committed
778
    }
779
    if (std::abs(showHeaders)&HDR_FCC) {
Laurent Montel's avatar
Laurent Montel committed
780
        mLabelWidth = calcColumnWidth(HDR_FCC, showHeaders, mLabelWidth);
Laurent Montel's avatar
Laurent Montel committed
781
    }
782
    if (std::abs(showHeaders)&HDR_TRANSPORT) {
Laurent Montel's avatar
Laurent Montel committed
783
        mLabelWidth = calcColumnWidth(HDR_TRANSPORT, showHeaders, mLabelWidth);
Laurent Montel's avatar
Laurent Montel committed
784
    }
785
    if (std::abs(showHeaders)&HDR_FROM) {