kmmainwidget.cpp 197 KB
Newer Older
Laurent Montel's avatar
Laurent Montel committed
1
/*
2
  This file is part of KMail, the KDE mail client.
3
  SPDX-FileCopyrightText: 2002 Don Sanders <sanders@kde.org>
Laurent Montel's avatar
Laurent Montel committed
4
  SPDX-FileCopyrightText: 2009-2021 Laurent Montel <montel@kde.org>
5
6
7

  Based on the work of Stefan Taferner <taferner@kde.org>

8
  SPDX-License-Identifier: GPL-2.0-only
9
*/
Stephan Kulow's avatar
Stephan Kulow committed
10

Thomas McGuire's avatar
Thomas McGuire committed
11
// KMail includes
Yuri Chornoivan's avatar
Yuri Chornoivan committed
12
#include "kmmainwidget.h"
Laurent Montel's avatar
Laurent Montel committed
13
#include "editor/composer.h"
Laurent Montel's avatar
Laurent Montel committed
14
15
16
17
#include "job/composenewmessagejob.h"
#include "kmcommands.h"
#include "kmmainwin.h"
#include "kmreadermainwin.h"
Laurent Montel's avatar
Laurent Montel committed
18
#include "searchdialog/searchwindow.h"
Laurent Montel's avatar
Laurent Montel committed
19
20
#include "undostack.h"
#include "util.h"
21
#include "widgets/vacationscriptindicatorwidget.h"
Laurent Montel's avatar
Laurent Montel committed
22
#include "widgets/zoomlabelwidget.h"
Laurent Montel's avatar
Laurent Montel committed
23
24
#include <MailCommon/FolderSelectionDialog>
#include <PimCommonAkonadi/MailUtil>
Laurent Montel's avatar
Laurent Montel committed
25
#include <TemplateParser/CustomTemplatesMenu>
26

Laurent Montel's avatar
Laurent Montel committed
27
#include "dialog/archivefolderdialog.h"
Laurent Montel's avatar
Laurent Montel committed
28
29
30
31
32
#include "foldershortcutactionmanager.h"
#include "job/markallmessagesasreadinfolderandsubfolderjob.h"
#include "job/removeduplicatemessageinfolderandsubfolderjob.h"
#include "manageshowcollectionproperties.h"
#include "plugininterface/kmailplugininterface.h"
Laurent Montel's avatar
Laurent Montel committed
33
#include "settings/kmailsettings.h"
Laurent Montel's avatar
Laurent Montel committed
34
#include "sieveimapinterface/kmsieveimappasswordprovider.h"
Laurent Montel's avatar
Laurent Montel committed
35
#include "tag/tagactionmanager.h"
Laurent Montel's avatar
Laurent Montel committed
36
#include "widgets/collectionpane.h"
37
#include "widgets/kactionmenuaccount.h"
Laurent Montel's avatar
Laurent Montel committed
38
#include "widgets/kactionmenutransport.h"
Laurent Montel's avatar
Laurent Montel committed
39
#include <KPIMTextEdit/TextToSpeech>
Laurent Montel's avatar
Laurent Montel committed
40
#include <KSieveUi/SieveDebugDialog>
Laurent Montel's avatar
Laurent Montel committed
41
42
43
44
#include <MailCommon/FolderTreeView>
#include <MailCommon/MailKernel>
#include <MailCommon/MailUtil>
#include <MailCommon/SearchRuleStatus>
45

Laurent Montel's avatar
Laurent Montel committed
46
#include "collectionpage/collectionmailinglistpage.h"
Laurent Montel's avatar
Laurent Montel committed
47
48
#include "collectionpage/collectionquotapage.h"
#include "collectionpage/collectionshortcutpage.h"
Laurent Montel's avatar
Laurent Montel committed
49
#include "collectionpage/collectiontemplatespage.h"
Laurent Montel's avatar
Laurent Montel committed
50
#include "collectionpage/collectionviewpage.h"
51
#include "folderarchive/folderarchivemanager.h"
Laurent Montel's avatar
Laurent Montel committed
52
53
54
55
#include "folderarchive/folderarchiveutil.h"
#include "job/createnewcontactjob.h"
#include "tag/tagselectdialog.h"
#include <AkonadiWidgets/CollectionMaintenancePage>
56

Laurent Montel's avatar
Laurent Montel committed
57
#include "mailcommonsettings_base.h"
Laurent Montel's avatar
Laurent Montel committed
58
#include <MailCommon/CollectionExpiryPage>
Laurent Montel's avatar
Laurent Montel committed
59
#include <MailCommon/CollectionGeneralPage>
Laurent Montel's avatar
Laurent Montel committed
60
#include <MailCommon/ExpireCollectionAttribute>
Laurent Montel's avatar
Laurent Montel committed
61
62
#include <MailCommon/FavoriteCollectionOrderProxyModel>
#include <MailCommon/FavoriteCollectionWidget>
Laurent Montel's avatar
Laurent Montel committed
63
64
#include <MailCommon/FilterManager>
#include <MailCommon/MailFilter>
Laurent Montel's avatar
Laurent Montel committed
65
66
#include <PimCommon/PimUtil>
#include <PimCommonAkonadi/CollectionAclPage>
67

Thomas McGuire's avatar
Thomas McGuire committed
68
// Other PIM includes
69
#include "kmail-version.h"
70

Laurent Montel's avatar
Laurent Montel committed
71
72
73
#include "messageviewer/config-messageviewer.h"
#include <MessageViewer/HeaderStyle>
#include <MessageViewer/HeaderStylePlugin>
Laurent Montel's avatar
Laurent Montel committed
74
75
#include <MessageViewer/MessageViewerSettings>
#include <MessageViewer/Viewer>
76

77
#include <MessageViewer/AttachmentStrategy>
Laurent Montel's avatar
Laurent Montel committed
78
#include <MessageViewer/MessageViewerCheckBeforeDeletingPluginManager>
79

80
#include <KCursorSaver>
81

Laurent Montel's avatar
Laurent Montel committed
82
#include <MessageComposer/MessageHelper>
Laurent Montel's avatar
Laurent Montel committed
83
#include <MessageComposer/MessageSender>
84

Laurent Montel's avatar
Laurent Montel committed
85
#include <MessageCore/MailingList>
Laurent Montel's avatar
Laurent Montel committed
86
#include <MessageCore/MessageCoreSettings>
87

Laurent Montel's avatar
Laurent Montel committed
88
#include "dialog/kmknotify.h"
89
#include "widgets/displaymessageformatactionmenu.h"
90

91
#include "kmlaunchexternalcomponent.h"
Laurent Montel's avatar
Laurent Montel committed
92
#include <KSieveUi/VacationManager>
Laurent Montel's avatar
Laurent Montel committed
93

Thomas McGuire's avatar
Thomas McGuire committed
94
// LIBKDEPIM includes
Laurent Montel's avatar
Laurent Montel committed
95
#include <Libkdepim/ProgressManager>
96
#include <PimCommon/BroadcastStatus>
97

Laurent Montel's avatar
Laurent Montel committed
98
99
#include <Akonadi/Contact/ContactSearchJob>
#include <Akonadi/KMime/MessageFlags>
Laurent Montel's avatar
Laurent Montel committed
100
#include <AkonadiCore/AgentManager>
Laurent Montel's avatar
Laurent Montel committed
101
#include <AkonadiCore/AttributeFactory>
Laurent Montel's avatar
Laurent Montel committed
102
103
104
105
106
#include <AkonadiCore/CachePolicy>
#include <AkonadiCore/EntityMimeTypeFilterModel>
#include <AkonadiCore/agentinstance.h>
#include <AkonadiCore/agenttype.h>
#include <AkonadiCore/changerecorder.h>
Laurent Montel's avatar
Laurent Montel committed
107
#include <AkonadiCore/collectionattributessynchronizationjob.h>
Laurent Montel's avatar
Laurent Montel committed
108
109
#include <AkonadiCore/collectionfetchjob.h>
#include <AkonadiCore/collectionfetchscope.h>
Laurent Montel's avatar
Laurent Montel committed
110
#include <AkonadiCore/collectionstatistics.h>
Laurent Montel's avatar
Laurent Montel committed
111
112
#include <AkonadiCore/entitydisplayattribute.h>
#include <AkonadiCore/entitytreemodel.h>
Laurent Montel's avatar
Laurent Montel committed
113
#include <AkonadiCore/favoritecollectionsmodel.h>
Laurent Montel's avatar
Laurent Montel committed
114
#include <AkonadiCore/itemfetchjob.h>
Laurent Montel's avatar
Laurent Montel committed
115
116
#include <AkonadiCore/itemfetchscope.h>
#include <AkonadiCore/itemmodifyjob.h>
Laurent Montel's avatar
Laurent Montel committed
117
#include <AkonadiCore/session.h>
Laurent Montel's avatar
Laurent Montel committed
118
#include <AkonadiWidgets/collectiondialog.h>
Laurent Montel's avatar
Laurent Montel committed
119
120
121
122
#include <AkonadiWidgets/collectionpropertiesdialog.h>
#include <AkonadiWidgets/controlgui.h>
#include <AkonadiWidgets/entitylistview.h>
#include <AkonadiWidgets/etmviewstatesaver.h>
Laurent Montel's avatar
Laurent Montel committed
123
#include <AkonadiWidgets/standardactionmanager.h>
124

125
#include <KEmailAddress>
Laurent Montel's avatar
Laurent Montel committed
126
127
#include <KSieveUi/ManageSieveScriptsDialog>
#include <KSieveUi/Util>
128
#include <MailTransport/Transport>
Laurent Montel's avatar
Laurent Montel committed
129
130
131
#include <MailTransport/TransportManager>
#include <kidentitymanagement/identity.h>
#include <kidentitymanagement/identitymanager.h>
Laurent Montel's avatar
Laurent Montel committed
132
#include <kmime/kmime_header_parsing.h>
Laurent Montel's avatar
Laurent Montel committed
133
#include <kmime/kmime_mdn.h>
Laurent Montel's avatar
Laurent Montel committed
134
#include <kmime/kmime_message.h>
135

136
137
#include <PimCommon/LogActivitiesManager>

Laurent Montel's avatar
Laurent Montel committed
138
#include "kmail_debug.h"
Laurent Montel's avatar
Laurent Montel committed
139
// KF5 includes
140
#include <KAcceleratorManager>
Laurent Montel's avatar
Laurent Montel committed
141
#include <KActionMenu>
142
#include <KCharsets>
Laurent Montel's avatar
Laurent Montel committed
143
144
145
#include <KMessageBox>
#include <KStandardShortcut>
#include <KWindowSystem>
Laurent Montel's avatar
Laurent Montel committed
146

Laurent Montel's avatar
Laurent Montel committed
147
#include <KConfigGroup>
148
#include <KNotification>
Laurent Montel's avatar
Laurent Montel committed
149
#include <KRecentFilesMenu>
Laurent Montel's avatar
Laurent Montel committed
150
#include <KStandardAction>
151
#include <KStringHandler>
Laurent Montel's avatar
Laurent Montel committed
152
#include <KToggleAction>
153
#include <KXMLGUIFactory>
154

Thomas McGuire's avatar
Thomas McGuire committed
155
// Qt includes
Laurent Montel's avatar
Laurent Montel committed
156
#include <QAction>
Thomas McGuire's avatar
Thomas McGuire committed
157
#include <QByteArray>
158
#include <QHeaderView>
Thomas McGuire's avatar
Thomas McGuire committed
159
#include <QList>
Laurent Montel's avatar
Laurent Montel committed
160
#include <QMenu>
Laurent Montel's avatar
Laurent Montel committed
161
162
#include <QProcess>
#include <QShortcut>
Thomas McGuire's avatar
Thomas McGuire committed
163
#include <QSplitter>
Laurent Montel's avatar
Laurent Montel committed
164
#include <QStatusBar>
Thomas McGuire's avatar
Thomas McGuire committed
165
#include <QVBoxLayout>
166
#include <WebEngineViewer/WebHitTestResult>
Thomas McGuire's avatar
Thomas McGuire committed
167
// System includes
168
#include <QDBusConnection>
Laurent Montel's avatar
Laurent Montel committed
169
#include <QDBusInterface>
170
#include <QDBusReply>
Laurent Montel's avatar
Laurent Montel committed
171
#include <QStandardPaths>
172

Laurent Montel's avatar
Laurent Montel committed
173
#include <PimCommonAkonadi/ManageServerSideSubscriptionJob>
Laurent Montel's avatar
Laurent Montel committed
174
#include <job/removecollectionjob.h>
Laurent Montel's avatar
Laurent Montel committed
175
#include <job/removeduplicatemailjob.h>
176

Laurent Montel's avatar
Laurent Montel committed
177
#include <MessageViewer/DKIMViewerMenu>
Laurent Montel's avatar
Laurent Montel committed
178
#include <MessageViewer/DKIMWidgetInfo>
Laurent Montel's avatar
Laurent Montel committed
179
#include <MessageViewer/RemoteContentMenu>
180
181
182

#include "plugininterface/kmailplugincheckbeforedeletingmanagerinterface.h"

183
184
185
#ifdef WITH_KUSERFEEDBACK
#include <KUserFeedback/NotificationPopup>
#include <KUserFeedback/Provider>
186
#endif
Laurent Montel's avatar
Laurent Montel committed
187
188

using namespace std::chrono_literals;
189
#include <chrono>
190

Thomas McGuire's avatar
Thomas McGuire committed
191
using namespace KMime;
192
using namespace Akonadi;
Andras Mantia's avatar
Andras Mantia committed
193
using namespace MailCommon;
Thomas McGuire's avatar
Thomas McGuire committed
194
195
using KMail::SearchWindow;
using KMime::Types::AddrSpecList;
Laurent Montel's avatar
Laurent Montel committed
196
using KPIM::ProgressManager;
197
using MessageViewer::AttachmentStrategy;
Laurent Montel's avatar
Laurent Montel committed
198
using PimCommon::BroadcastStatus;
Stephan Kulow's avatar
Stephan Kulow committed
199

Laurent Montel's avatar
Laurent Montel committed
200
Q_GLOBAL_STATIC(KMMainWidget::PtrList, theMainWidgetList)
201

Stephan Kulow's avatar
Stephan Kulow committed
202
//-----------------------------------------------------------------------------
Laurent Montel's avatar
Laurent Montel committed
203
KMMainWidget::KMMainWidget(QWidget *parent, KXMLGUIClient *aGUIClient, KActionCollection *actionCollection, const KSharedConfig::Ptr &config)
Laurent Montel's avatar
Laurent Montel committed
204
    : QWidget(parent)
Laurent Montel's avatar
Laurent Montel committed
205
    , mLaunchExternalComponent(new KMLaunchExternalComponent(this, this))
Laurent Montel's avatar
Laurent Montel committed
206
    , mManageShowCollectionProperties(new ManageShowCollectionProperties(this, this))
Stephan Kulow's avatar
Stephan Kulow committed
207
{
Laurent Montel's avatar
Laurent Montel committed
208
209
210
211
212
    // must be the first line of the constructor:
    mStartupDone = false;
    mWasEverShown = false;
    mReaderWindowActive = true;
    mReaderWindowBelow = true;
213
    mFolderHtmlLoadExtPreference = false;
Laurent Montel's avatar
Laurent Montel committed
214
215
    mDestructed = false;
    mActionCollection = actionCollection;
Laurent Montel's avatar
Laurent Montel committed
216
    mTopLayout = new QVBoxLayout(this);
Laurent Montel's avatar
Laurent Montel committed
217
    mTopLayout->setContentsMargins({});
Laurent Montel's avatar
Laurent Montel committed
218
219
    mConfig = config;
    mGUIClient = aGUIClient;
Laurent Montel's avatar
Laurent Montel committed
220
    mFolderTreeWidget = nullptr;
Laurent Montel's avatar
Laurent Montel committed
221
    Akonadi::ControlGui::widgetNeedsAkonadi(this);
Laurent Montel's avatar
Laurent Montel committed
222
    mFavoritesModel = nullptr;
Laurent Montel's avatar
Laurent Montel committed
223
    mSievePasswordProvider = new KMSieveImapPasswordProvider(this);
224
    mVacationManager = new KSieveUi::VacationManager(mSievePasswordProvider, this);
Laurent Montel's avatar
Laurent Montel committed
225
226
227
228
    connect(mVacationManager,
            &KSieveUi::VacationManager::updateVacationScriptStatus,
            this,
            qOverload<bool, const QString &>(&KMMainWidget::updateVacationScriptStatus));
Laurent Montel's avatar
Laurent Montel committed
229

230
#ifdef WITH_KUSERFEEDBACK
231
    auto userFeedBackNotificationPopup = new KUserFeedback::NotificationPopup(this);
Laurent Montel's avatar
Laurent Montel committed
232
    userFeedBackNotificationPopup->setFeedbackProvider(kmkernel->userFeedbackProvider());
233
234
#endif

Laurent Montel's avatar
Laurent Montel committed
235
236
    mToolbarActionSeparator = new QAction(this);
    mToolbarActionSeparator->setSeparator(true);
Laurent Montel's avatar
Laurent Montel committed
237

Laurent Montel's avatar
Laurent Montel committed
238
239
240
    KMailPluginInterface::self()->setActionCollection(mActionCollection);
    KMailPluginInterface::self()->initializePlugins();
    KMailPluginInterface::self()->setMainWidget(this);
241
242
    mPluginCheckBeforeDeletingManagerInterface = new KMailPluginCheckBeforeDeletingManagerInterface(this);
    mPluginCheckBeforeDeletingManagerInterface->initializePlugins();
Laurent Montel's avatar
Laurent Montel committed
243
    mPluginCheckBeforeDeletingManagerInterface->setParentWidget(this);
Laurent Montel's avatar
Laurent Montel committed
244

Laurent Montel's avatar
Laurent Montel committed
245
    theMainWidgetList->append(this);
Laurent Montel's avatar
Laurent Montel committed
246
247
248
249
250
251
252

    readPreConfig();
    createWidgets();
    setupActions();

    readConfig();

Laurent Montel's avatar
Laurent Montel committed
253
    if (!kmkernel->isOffline()) { // kmail is set to online mode, make sure the agents are also online
Laurent Montel's avatar
Laurent Montel committed
254
255
256
        kmkernel->setAccountStatus(true);
    }

257
    QTimer::singleShot(0, this, &KMMainWidget::slotShowStartupFolder);
Laurent Montel's avatar
Laurent Montel committed
258

Laurent Montel's avatar
Laurent Montel committed
259
    connect(kmkernel, &KMKernel::startCheckMail, this, &KMMainWidget::slotStartCheckMail);
Laurent Montel's avatar
Laurent Montel committed
260

Laurent Montel's avatar
Laurent Montel committed
261
    connect(kmkernel, &KMKernel::endCheckMail, this, &KMMainWidget::slotEndCheckMail);
Laurent Montel's avatar
Laurent Montel committed
262

Laurent Montel's avatar
Laurent Montel committed
263
    connect(kmkernel, &KMKernel::configChanged, this, &KMMainWidget::slotConfigChanged);
Laurent Montel's avatar
Laurent Montel committed
264

Laurent Montel's avatar
Laurent Montel committed
265
    connect(kmkernel, &KMKernel::onlineStatusChanged, this, &KMMainWidget::slotUpdateOnlineStatus);
Laurent Montel's avatar
Laurent Montel committed
266

Laurent Montel's avatar
Laurent Montel committed
267
    connect(mTagActionManager, &KMail::TagActionManager::tagActionTriggered, this, &KMMainWidget::slotUpdateMessageTagList);
Laurent Montel's avatar
Laurent Montel committed
268

Laurent Montel's avatar
Laurent Montel committed
269
    connect(mTagActionManager, &KMail::TagActionManager::tagMoreActionClicked, this, &KMMainWidget::slotSelectMoreMessageTagList);
Laurent Montel's avatar
Laurent Montel committed
270
271
272

    kmkernel->toggleSystemTray();

Laurent Montel's avatar
Laurent Montel committed
273
274
    {
        // make sure the pages are registered only once, since there can be multiple instances of KMMainWidget
Laurent Montel's avatar
Laurent Montel committed
275
276
        static bool pagesRegistered = false;

Laurent Montel's avatar
Laurent Montel committed
277
278
279
280
281
282
283
284
285
286
        if (!pagesRegistered) {
            Akonadi::CollectionPropertiesDialog::registerPage(new PimCommon::CollectionAclPageFactory);
            Akonadi::CollectionPropertiesDialog::registerPage(new MailCommon::CollectionGeneralPageFactory);
            Akonadi::CollectionPropertiesDialog::registerPage(new CollectionMaintenancePageFactory);
            Akonadi::CollectionPropertiesDialog::registerPage(new CollectionQuotaPageFactory);
            Akonadi::CollectionPropertiesDialog::registerPage(new CollectionTemplatesPageFactory);
            Akonadi::CollectionPropertiesDialog::registerPage(new MailCommon::CollectionExpiryPageFactory);
            Akonadi::CollectionPropertiesDialog::registerPage(new CollectionViewPageFactory);
            Akonadi::CollectionPropertiesDialog::registerPage(new CollectionMailingListPageFactory);
            Akonadi::CollectionPropertiesDialog::registerPage(new CollectionShortcutPageFactory);
Laurent Montel's avatar
Laurent Montel committed
287
288
289
290
291

            pagesRegistered = true;
        }
    }

292
    auto mainWin = qobject_cast<KMainWindow *>(window());
Laurent Montel's avatar
Laurent Montel committed
293
294
    mCurrentStatusBar = mainWin ? mainWin->statusBar() : nullptr;
    mVacationScriptIndicator = new KMail::VacationScriptIndicatorWidget(mCurrentStatusBar);
Laurent Montel's avatar
Laurent Montel committed
295
    mVacationScriptIndicator->hide();
Laurent Montel's avatar
Laurent Montel committed
296

Laurent Montel's avatar
Laurent Montel committed
297
298
299
300
    mZoomLabelIndicator = new ZoomLabelWidget(mCurrentStatusBar);
    if (mMsgView) {
        setZoomChanged(mMsgView->viewer()->webViewZoomFactor());
    }
Laurent Montel's avatar
Laurent Montel committed
301
    connect(mVacationScriptIndicator, &KMail::VacationScriptIndicatorWidget::clicked, this, &KMMainWidget::slotEditVacation);
Laurent Montel's avatar
Laurent Montel committed
302
    if (KSieveUi::Util::checkOutOfOfficeOnStartup()) {
303
        QTimer::singleShot(0, this, &KMMainWidget::slotCheckVacation);
Laurent Montel's avatar
Laurent Montel committed
304
    }
Laurent Montel's avatar
Laurent Montel committed
305

Laurent Montel's avatar
Laurent Montel committed
306
    connect(mFolderTreeWidget->folderTreeView()->model(), &QAbstractItemModel::modelReset, this, &KMMainWidget::restoreCollectionFolderViewConfig);
Laurent Montel's avatar
Laurent Montel committed
307
308
    restoreCollectionFolderViewConfig();

Laurent Montel's avatar
Laurent Montel committed
309
    if (kmkernel->firstStart()) {
Laurent Montel's avatar
Laurent Montel committed
310
        const QStringList listOfMailerFound = MailCommon::Util::foundMailer();
311
        if (!listOfMailerFound.isEmpty()) {
Laurent Montel's avatar
Laurent Montel committed
312
313
            if (KMessageBox::questionYesNoList(this, i18n("Another mailer was found on system. Do you want to import data from it?"), listOfMailerFound)
                == KMessageBox::Yes) {
314
                const QString path = QStandardPaths::findExecutable(QStringLiteral("akonadiimportwizard"));
315
                if (!QProcess::startDetached(path, QStringList())) {
Laurent Montel's avatar
Laurent Montel committed
316
317
318
                    KMessageBox::error(this,
                                       i18n("Could not start the import wizard. "
                                            "Please check your installation."),
Laurent Montel's avatar
Laurent Montel committed
319
                                       i18n("Unable to start import wizard"));
Laurent Montel's avatar
Laurent Montel committed
320
321
                }
            } else {
322
                mLaunchExternalComponent->slotAccountWizard();
Laurent Montel's avatar
Laurent Montel committed
323
324
            }
        } else {
325
            mLaunchExternalComponent->slotAccountWizard();
326
327
        }
    }
Laurent Montel's avatar
Laurent Montel committed
328
329
    // must be the last line of the constructor:
    mStartupDone = true;
330

Laurent Montel's avatar
Laurent Montel committed
331
    mCheckMailTimer.setInterval(3s);
Laurent Montel's avatar
Laurent Montel committed
332
    mCheckMailTimer.setSingleShot(true);
Laurent Montel's avatar
Laurent Montel committed
333
    connect(&mCheckMailTimer, &QTimer::timeout, this, &KMMainWidget::slotUpdateActionsAfterMailChecking);
334
335

    setupUnifiedMailboxChecker();
336
337
}

Laurent Montel's avatar
Laurent Montel committed
338
339
QWidget *KMMainWidget::dkimWidgetInfo() const
{
340
341
342
343
    if (mMsgView) {
        return mMsgView->viewer()->dkimWidgetInfo();
    }
    return nullptr;
Laurent Montel's avatar
Laurent Montel committed
344
}
Laurent Montel's avatar
Laurent Montel committed
345

346
void KMMainWidget::restoreCollectionFolderViewConfig()
347
{
348
    auto saver = new ETMViewStateSaver;
Laurent Montel's avatar
Laurent Montel committed
349
350
351
352
    saver->setView(mFolderTreeWidget->folderTreeView());
    const KConfigGroup cfg(KMKernel::self()->config(), "CollectionFolderView");
    mFolderTreeWidget->restoreHeaderState(cfg.readEntry("HeaderState", QByteArray()));
    saver->restoreState(cfg);
Laurent Montel's avatar
Laurent Montel committed
353
    // Restore startup folder
354

Laurent Montel's avatar
Laurent Montel committed
355
    Akonadi::Collection::Id id = -1;
356
357
    if (mCurrentCollection.isValid()) {
        id = mCurrentCollection.id();
Laurent Montel's avatar
Laurent Montel committed
358
    }
359

Laurent Montel's avatar
Laurent Montel committed
360
    if (id == -1) {
Laurent Montel's avatar
Laurent Montel committed
361
362
        if (KMailSettings::self()->startSpecificFolderAtStartup()) {
            Akonadi::Collection::Id startupFolder = KMailSettings::self()->startupFolder();
Laurent Montel's avatar
Laurent Montel committed
363
            if (startupFolder > 0) {
Laurent Montel's avatar
Laurent Montel committed
364
                saver->restoreCurrentItem(QStringLiteral("c%1").arg(startupFolder));
Laurent Montel's avatar
Laurent Montel committed
365
            }
Laurent Montel's avatar
Laurent Montel committed
366
367
        }
    } else {
Laurent Montel's avatar
Laurent Montel committed
368
        saver->restoreCurrentItem(QStringLiteral("c%1").arg(id));
369
    }
Stephan Kulow's avatar
Stephan Kulow committed
370
371
372
}

//-----------------------------------------------------------------------------
Laurent Montel's avatar
Laurent Montel committed
373
374
// The kernel may have already been deleted when this method is called,
// perform all cleanup that requires the kernel in destruct()
375
KMMainWidget::~KMMainWidget()
Stephan Kulow's avatar
Stephan Kulow committed
376
{
Laurent Montel's avatar
Laurent Montel committed
377
378
    theMainWidgetList->removeAll(this);
    qDeleteAll(mFilterCommands);
Laurent Montel's avatar
Laurent Montel committed
379
    destruct();
Stephan Kulow's avatar
Stephan Kulow committed
380
381
382
}

//-----------------------------------------------------------------------------
Laurent Montel's avatar
Laurent Montel committed
383
// This method performs all cleanup that requires the kernel to exist.
384
void KMMainWidget::destruct()
Stephan Kulow's avatar
Stephan Kulow committed
385
{
Laurent Montel's avatar
Laurent Montel committed
386
    if (mDestructed) {
Laurent Montel's avatar
Laurent Montel committed
387
        return;
Laurent Montel's avatar
Laurent Montel committed
388
389
    }
    if (mSearchWin) {
Laurent Montel's avatar
Laurent Montel committed
390
        mSearchWin->close();
Laurent Montel's avatar
Laurent Montel committed
391
    }
392
    disconnect(mFolderTreeWidget->folderTreeView()->selectionModel(), &QItemSelectionModel::selectionChanged, this, &KMMainWidget::updateFolderMenu);
Laurent Montel's avatar
Laurent Montel committed
393
394
395
    writeConfig(false); /* don't force kmkernel sync when close BUG: 289287 */
    writeFolderConfig();
    deleteWidgets();
396
    clearCurrentFolder();
Laurent Montel's avatar
Laurent Montel committed
397
398
    delete mMoveOrCopyToDialog;
    delete mSelectFromAllFoldersDialog;
399
    delete mSievePasswordProvider;
Laurent Montel's avatar
Laurent Montel committed
400

Laurent Montel's avatar
Laurent Montel committed
401
    disconnect(kmkernel->folderCollectionMonitor(), SIGNAL(itemAdded(Akonadi::Item, Akonadi::Collection)), this, nullptr);
Laurent Montel's avatar
Laurent Montel committed
402
    disconnect(kmkernel->folderCollectionMonitor(), SIGNAL(itemRemoved(Akonadi::Item)), this, nullptr);
Laurent Montel's avatar
Laurent Montel committed
403
404
405
    disconnect(kmkernel->folderCollectionMonitor(), SIGNAL(itemMoved(Akonadi::Item, Akonadi::Collection, Akonadi::Collection)), this, nullptr);
    disconnect(kmkernel->folderCollectionMonitor(), SIGNAL(collectionChanged(Akonadi::Collection, QSet<QByteArray>)), this, nullptr);
    disconnect(kmkernel->folderCollectionMonitor(), SIGNAL(collectionStatisticsChanged(Akonadi::Collection::Id, Akonadi::CollectionStatistics)), this, nullptr);
Laurent Montel's avatar
Laurent Montel committed
406

Laurent Montel's avatar
Laurent Montel committed
407
    mDestructed = true;
Stephan Kulow's avatar
Stephan Kulow committed
408
409
}

410
411
void KMMainWidget::clearCurrentFolder()
{
Laurent Montel's avatar
Laurent Montel committed
412
    mCurrentFolderSettings.clear();
413
414
415
    mCurrentCollection = Akonadi::Collection();
}

416
417
void KMMainWidget::slotStartCheckMail()
{
Laurent Montel's avatar
Laurent Montel committed
418
    if (mCheckMailTimer.isActive()) {
Laurent Montel's avatar
Laurent Montel committed
419
        mCheckMailTimer.stop();
Laurent Montel's avatar
Laurent Montel committed
420
    }
421
422
423
424
}

void KMMainWidget::slotEndCheckMail()
{
Laurent Montel's avatar
Laurent Montel committed
425
    if (!mCheckMailTimer.isActive()) {
Laurent Montel's avatar
Laurent Montel committed
426
        mCheckMailTimer.start();
Laurent Montel's avatar
Laurent Montel committed
427
    }
428
429
}

Laurent Montel's avatar
Laurent Montel committed
430
void KMMainWidget::slotUpdateActionsAfterMailChecking()
431
{
Laurent Montel's avatar
Laurent Montel committed
432
433
    const bool sendOnAll = KMailSettings::self()->sendOnCheck() == KMailSettings::EnumSendOnCheck::SendOnAllChecks;
    const bool sendOnManual = KMailSettings::self()->sendOnCheck() == KMailSettings::EnumSendOnCheck::SendOnManualChecks;
Laurent Montel's avatar
Laurent Montel committed
434
    if (!kmkernel->isOffline() && (sendOnAll || sendOnManual)) {
Laurent Montel's avatar
Laurent Montel committed
435
436
437
438
439
        slotSendQueued();
    }
    // update folder menus in case some mail got filtered to trash/current folder
    // and we can enable "empty trash/move all to trash" action etc.
    updateFolderMenu();
440
441
}

442
443
444
void KMMainWidget::setCurrentCollection(const Akonadi::Collection &col)
{
    mCurrentCollection = col;
Laurent Montel's avatar
Laurent Montel committed
445
446
    if (mCurrentFolderSettings) {
        mCurrentFolderSettings->setCollection(col);
447
448
449
    }
}

Laurent Montel's avatar
Laurent Montel committed
450
void KMMainWidget::slotCollectionFetched(int collectionId)
451
{
Laurent Montel's avatar
Laurent Montel committed
452
453
454
    // Called when a collection is fetched for the first time by the ETM.
    // This is the right time to update the caption (which still says "Loading...")
    // and to update the actions that depend on the number of mails in the folder.
455
    if (collectionId == mCurrentCollection.id()) {
456
        setCurrentCollection(CommonKernel->collectionFromId(mCurrentCollection.id()));
Laurent Montel's avatar
Laurent Montel committed
457
458
459
460
        updateMessageActions();
        updateFolderMenu();
    }
    // We call this for any collection, it could be one of our parents...
461
    if (mCurrentCollection.isValid()) {
462
        Q_EMIT captionChangeRequest(fullCollectionPath());
Laurent Montel's avatar
Laurent Montel committed
463
    }
464
465
}

466
467
468
469
470
471
472
QString KMMainWidget::fullCollectionPath() const
{
    if (mCurrentCollection.isValid()) {
        return MailCommon::Util::fullCollectionPath(mCurrentCollection);
    }
    return {};
}
473

474
// Connected to the currentChanged signals from the folderTreeView and favorites view.
Laurent Montel's avatar
Laurent Montel committed
475
void KMMainWidget::slotFolderChanged(const Akonadi::Collection &collection)
476
{
Laurent Montel's avatar
Laurent Montel committed
477
    if (mCurrentCollection == collection) {
478
        return;
Laurent Montel's avatar
Laurent Montel committed
479
    }
Laurent Montel's avatar
Laurent Montel committed
480
481
482
483
484
    folderSelected(collection);
    if (collection.cachePolicy().syncOnDemand()) {
        AgentManager::self()->synchronizeCollection(collection, false);
    }
    mMsgActions->setCurrentMessage(Akonadi::Item());
Laurent Montel's avatar
Laurent Montel committed
485
    Q_EMIT captionChangeRequest(MailCommon::Util::fullCollectionPath(collection));
Laurent Montel's avatar
Laurent Montel committed
486
487
}

488
// Called by slotFolderChanged (no particular reason for this method to be split out)
Laurent Montel's avatar
Laurent Montel committed
489
void KMMainWidget::folderSelected(const Akonadi::Collection &col)
Laurent Montel's avatar
Laurent Montel committed
490
{
Laurent Montel's avatar
Laurent Montel committed
491
    if (mGoToFirstUnreadMessageInSelectedFolder) {
Laurent Montel's avatar
Laurent Montel committed
492
        // the default action has been overridden from outside
493
        mPreSelectionMode = MessageList::Core::PreSelectFirstUnreadCentered;
Laurent Montel's avatar
Laurent Montel committed
494
495
    } else {
        // use the default action
Laurent Montel's avatar
Laurent Montel committed
496
497
        switch (KMailSettings::self()->actionEnterFolder()) {
        case KMailSettings::EnumActionEnterFolder::SelectFirstUnread:
Laurent Montel's avatar
Laurent Montel committed
498
499
            mPreSelectionMode = MessageList::Core::PreSelectFirstUnreadCentered;
            break;
Laurent Montel's avatar
Laurent Montel committed
500
        case KMailSettings::EnumActionEnterFolder::SelectLastSelected:
Laurent Montel's avatar
Laurent Montel committed
501
502
            mPreSelectionMode = MessageList::Core::PreSelectLastSelected;
            break;
Laurent Montel's avatar
Laurent Montel committed
503
        case KMailSettings::EnumActionEnterFolder::SelectNewest:
Laurent Montel's avatar
Laurent Montel committed
504
505
            mPreSelectionMode = MessageList::Core::PreSelectNewestCentered;
            break;
Laurent Montel's avatar
Laurent Montel committed
506
        case KMailSettings::EnumActionEnterFolder::SelectOldest:
Laurent Montel's avatar
Laurent Montel committed
507
508
509
510
511
512
513
514
515
            mPreSelectionMode = MessageList::Core::PreSelectOldestCentered;
            break;
        default:
            mPreSelectionMode = MessageList::Core::PreSelectNone;
            break;
        }
    }

    mGoToFirstUnreadMessageInSelectedFolder = false;
516
    KCursorSaver saver(Qt::WaitCursor);
Laurent Montel's avatar
Laurent Montel committed
517

Laurent Montel's avatar
Laurent Montel committed
518
    if (mMsgView) {
Laurent Montel's avatar
Laurent Montel committed
519
        mMsgView->clear(true);
Laurent Montel's avatar
Laurent Montel committed
520
    }
521
    const bool newFolder = mCurrentCollection != col;
David Faure's avatar
David Faure committed
522

Laurent Montel's avatar
Laurent Montel committed
523
524
    // Delete any pending timer, if needed it will be recreated below
    delete mShowBusySplashTimer;
Laurent Montel's avatar
Laurent Montel committed
525
    mShowBusySplashTimer = nullptr;
Laurent Montel's avatar
Laurent Montel committed
526
    if (newFolder) {
Laurent Montel's avatar
Laurent Montel committed
527
528
529
        // We're changing folder: write configuration for the old one
        writeFolderConfig();
    }
Laurent Montel's avatar
Laurent Montel committed
530

Laurent Montel's avatar
Laurent Montel committed
531
    mCurrentFolderSettings = FolderSettings::forCollection(col);
532
    mCurrentCollection = col;
Laurent Montel's avatar
Laurent Montel committed
533

Laurent Montel's avatar
Laurent Montel committed
534
    readFolderConfig();
Laurent Montel's avatar
Laurent Montel committed
535
    if (mMsgView) {
536
        assignLoadExternalReference();
Laurent Montel's avatar
Laurent Montel committed
537
    }
Laurent Montel's avatar
Laurent Montel committed
538

Laurent Montel's avatar
Laurent Montel committed
539
    if (!mCurrentFolderSettings->isValid() && (mMessagePane->count() < 2)) {
Laurent Montel's avatar
Laurent Montel committed
540
        slotIntro();
541
542
543
544
    } else {
        if (mMessagePane->isHidden()) {
            mMessagePane->show();
        }
Laurent Montel's avatar
Laurent Montel committed
545
    }
Laurent Montel's avatar
Laurent Montel committed
546

Laurent Montel's avatar
Laurent Montel committed
547
548
549
    // The message pane uses the selection model of the folder view to load the correct aggregation model and theme
    //  settings. At this point the selection model hasn't been updated yet to the user's new choice, so it would load
    //  the old folder settings instead.
550
    QTimer::singleShot(0, this, &KMMainWidget::slotShowSelectedFolderInPane);
551
552
}

Laurent Montel's avatar
Laurent Montel committed
553
void KMMainWidget::slotShowSelectedFolderInPane()
554
{
555
    if (mCurrentCollection.isValid()) {
556
557
558
559
        const QModelIndex idx = Akonadi::EntityTreeModel::modelIndexForCollection(KMKernel::self()->entityTreeModel(), mCurrentCollection);
        if (idx.isValid()) {
            mMessagePane->setCurrentFolder(mCurrentCollection, idx, false, mPreSelectionMode);
        }
Laurent Montel's avatar
Laurent Montel committed
560
    }
Laurent Montel's avatar
Laurent Montel committed
561
562
    updateMessageActions();
    updateFolderMenu();
563
564
}

Stephan Kulow's avatar
Stephan Kulow committed
565
//-----------------------------------------------------------------------------
566
void KMMainWidget::readPreConfig()
Stephan Kulow's avatar
Stephan Kulow committed
567
{
Laurent Montel's avatar
Laurent Montel committed
568
569
570
    mLongFolderList = KMailSettings::self()->folderList() == KMailSettings::EnumFolderList::longlist;
    mReaderWindowActive = KMailSettings::self()->readerWindowMode() != KMailSettings::EnumReaderWindowMode::hide;
    mReaderWindowBelow = KMailSettings::self()->readerWindowMode() == KMailSettings::EnumReaderWindowMode::below;
Dirk Mueller's avatar
Dirk Mueller committed
571

Laurent Montel's avatar
Laurent Montel committed
572
573
    mHtmlGlobalSetting = MessageViewer::MessageViewerSettings::self()->htmlMail();
    mHtmlLoadExtGlobalSetting = MessageViewer::MessageViewerSettings::self()->htmlLoadExternal();
Laurent Montel's avatar
Laurent Montel committed
574

Laurent Montel's avatar
Laurent Montel committed
575
576
    mEnableFavoriteFolderView =
        (KMKernel::self()->mailCommonSettings()->favoriteCollectionViewMode() != MailCommon::MailCommonSettings::EnumFavoriteCollectionViewMode::HiddenMode);
577
    mEnableFolderQuickSearch = KMailSettings::self()->enableFolderQuickSearch();
578
}
579

580
581
void KMMainWidget::updateDisplayFormatMessage()
{
582
    readFolderConfig();
Laurent Montel's avatar
Laurent Montel committed
583
    updateHtmlMenuEntry();
584
585
    if (mMsgView) {
        mMsgView->setDisplayFormatMessageOverwrite(mFolderDisplayFormatPreference);
Laurent Montel's avatar
Laurent Montel committed
586
        mMsgView->update(true);
587
    }
Stephan Kulow's avatar
Stephan Kulow committed
588
589
590
}

//-----------------------------------------------------------------------------
591
void KMMainWidget::readFolderConfig()
Stephan Kulow's avatar
Stephan Kulow committed
592
{
Laurent Montel's avatar
Laurent Montel committed
593
    if (!mCurrentCollection.isValid()) {
Laurent Montel's avatar
Laurent Montel committed
594
        return;
Laurent Montel's avatar
Laurent Montel committed
595
    }
Laurent Montel's avatar
Laurent Montel committed
596
    KSharedConfig::Ptr config = KMKernel::self()->config();
Laurent Montel's avatar
Laurent Montel committed
597
    KConfigGroup group(config, MailCommon::FolderSettings::configGroupName(mCurrentCollection));
Laurent Montel's avatar
Laurent Montel committed
598
599
    if (group.hasKey("htmlMailOverride")) {
        const bool useHtml = group.readEntry("htmlMailOverride", false);
600
601
602
603
        mFolderDisplayFormatPreference = useHtml ? MessageViewer::Viewer::Html : MessageViewer::Viewer::Text;
        group.deleteEntry("htmlMailOverride");
        group.sync();
    } else {
Laurent Montel's avatar
Laurent Montel committed
604
605
        mFolderDisplayFormatPreference = static_cast<MessageViewer::Viewer::DisplayFormatMessage>(
            group.readEntry("displayFormatOverride", static_cast<int>(MessageViewer::Viewer::UseGlobalSetting)));
606
    }
Laurent Montel's avatar
Laurent Montel committed
607
    mFolderHtmlLoadExtPreference = group.readEntry("htmlLoadExternalOverride", false);
Stephan Kulow's avatar
Stephan Kulow committed
608
609
610
}

//-----------------------------------------------------------------------------
611
void KMMainWidget::writeFolderConfig()
Stephan Kulow's avatar
Stephan Kulow committed
612
{
613
614
615
616
    if (mCurrentFolderSettings) {
        mCurrentFolderSettings->setFolderHtmlLoadExtPreference(mFolderHtmlLoadExtPreference);
        mCurrentFolderSettings->setFormatMessage(mFolderDisplayFormatPreference);
        mCurrentFolderSettings->writeConfig();
Laurent Montel's avatar
Laurent Montel committed
617
    }
Stephan Kulow's avatar
Stephan Kulow committed
618
619
}

620
621
622
//-----------------------------------------------------------------------------
void KMMainWidget::layoutSplitters()
{
Laurent Montel's avatar
Laurent Montel committed
623
    // This function can only be called when the old splitters are already deleted
Laurent Montel's avatar
Laurent Montel committed
624
625
    Q_ASSERT(!mSplitter1);
    Q_ASSERT(!mSplitter2);
626

Laurent Montel's avatar
Laurent Montel committed
627
628
    // For some reason, this is necessary here so that the copy action still
    // works after changing the folder layout.
Laurent Montel's avatar
Laurent Montel committed
629
    if (mMsgView) {
Laurent Montel's avatar
Laurent Montel committed
630
        disconnect(mMsgView->copyAction(), &QAction::triggered, mMsgView, &KMReaderWin::slotCopySelectedText);
Laurent Montel's avatar
Laurent Montel committed
631
    }
Laurent Montel's avatar
Laurent Montel committed
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646

    // If long folder list is enabled, the splitters are:
    // Splitter 1: FolderView vs (HeaderAndSearch vs MessageViewer)
    // Splitter 2: HeaderAndSearch vs MessageViewer
    //
    // If long folder list is disabled, the splitters are:
    // Splitter 1: (FolderView vs HeaderAndSearch) vs MessageViewer
    // Splitter 2: FolderView vs HeaderAndSearch

    // The folder view is both the folder tree and the favorite folder view, if
    // enabled

    const bool readerWindowAtSide = !mReaderWindowBelow && mReaderWindowActive;
    const bool readerWindowBelow = mReaderWindowBelow && mReaderWindowActive;

Laurent Montel's avatar
Laurent Montel committed
647
648
    mSplitter1 = new QSplitter(this);
    mSplitter2 = new QSplitter(mSplitter1);
Laurent Montel's avatar
Laurent Montel committed
649

650
    QWidget *folderTreeWidget = mFolderTreeWidget;
Laurent Montel's avatar
Laurent Montel committed
651
652
    if (mFavoriteCollectionsView) {
        mFolderViewSplitter = new QSplitter(Qt::Vertical);
Laurent Montel's avatar
Laurent Montel committed
653
        mFolderViewSplitter->setChildrenCollapsible(false);
Laurent Montel's avatar
Laurent Montel committed
654
        mFolderViewSplitter->addWidget(mFavoriteCollectionsView);
655
        mFolderViewSplitter->addWidget(mFolderTreeWidget);
Laurent Montel's avatar
Laurent Montel committed
656
        folderTreeWidget = mFolderViewSplitter;
Till Adam's avatar
Till Adam committed
657
    }
658

Laurent Montel's avatar
Laurent Montel committed
659
    if (mLongFolderList) {
Laurent Montel's avatar
Laurent Montel committed
660
        // add folder tree
Laurent Montel's avatar
Laurent Montel committed
661
662
        mSplitter1->setOrientation(Qt::Horizontal);
        mSplitter1->addWidget(folderTreeWidget);
Laurent Montel's avatar
Laurent Montel committed
663
664

        // and the rest to the right
Laurent Montel's avatar
Laurent Montel committed
665
        mSplitter1->addWidget(mSplitter2);
Laurent Montel's avatar
Laurent Montel committed
666
667

        // add the message list to the right or below
Laurent Montel's avatar
Laurent Montel committed
668
669
        if (readerWindowAtSide) {
            mSplitter2->setOrientation(Qt::Horizontal);
Laurent Montel's avatar
Laurent Montel committed
670
        } else {
Laurent Montel's avatar
Laurent Montel committed
671
            mSplitter2->setOrientation(Qt::Vertical);
Laurent Montel's avatar
Laurent Montel committed
672
        }
Laurent Montel's avatar
Laurent Montel committed
673
        mSplitter2->addWidget(mMessagePane);
Laurent Montel's avatar
Laurent Montel committed
674
675

        // add the preview window, if there is one
Laurent Montel's avatar
Laurent Montel committed
676
677
        if (mMsgView) {
            mSplitter2->addWidget(mMsgView);
Laurent Montel's avatar
Laurent Montel committed
678
679
        }
    } else { // short folder list
Laurent Montel's avatar
Laurent Montel committed
680
681
682
        if (mReaderWindowBelow) {
            mSplitter1->setOrientation(Qt::Vertical);
            mSplitter2->setOrientation(Qt::Horizontal);
Laurent Montel's avatar
Laurent Montel committed
683
        } else { // at side or none
Laurent Montel's avatar
Laurent Montel committed
684
685
            mSplitter1->setOrientation(Qt::Horizontal);
            mSplitter2->setOrientation(Qt::Vertical);
Laurent Montel's avatar
Laurent Montel committed
686
687
        }

Laurent Montel's avatar
Laurent Montel committed
688
        mSplitter1->addWidget(mSplitter2);
Laurent Montel's avatar
Laurent Montel committed
689
690

        // add folder tree
Laurent Montel's avatar
Laurent Montel committed
691
        mSplitter2->addWidget(folderTreeWidget);
Laurent Montel's avatar
Laurent Montel committed
692
        // add message list to splitter 2
Laurent Montel's avatar
Laurent Montel committed
693
        mSplitter2->addWidget(mMessagePane);
Laurent Montel's avatar
Laurent Montel committed
694
695

        // add the preview window, if there is one
Laurent Montel's avatar
Laurent Montel committed
696
697
698
        if (mMsgView) {
            mSplitter1->addWidget(mMsgView);
        }
Till Adam's avatar
Till Adam committed
699
    }
700

Laurent Montel's avatar
Laurent Montel committed
701
702
703
    //
    // Set splitter properties
    //
Laurent Montel's avatar
Laurent Montel committed
704
    mSplitter1->setObjectName(QStringLiteral("splitter1"));
Laurent Montel's avatar
Laurent Montel committed
705
    mSplitter1->setChildrenCollapsible(false);
Laurent Montel's avatar
Laurent Montel committed
706
    mSplitter2->setObjectName(QStringLiteral("splitter2"));
Laurent Montel's avatar
Laurent Montel committed
707
    mSplitter2->setChildrenCollapsible(false);
Laurent Montel's avatar
Laurent Montel committed
708
709
710
711

    //
    // Set the stretch factors
    //
Laurent Montel's avatar
Laurent Montel committed
712
713
714
715
    mSplitter1->setStretchFactor(0, 0);
    mSplitter2->setStretchFactor(0, 0);
    mSplitter1->setStretchFactor(1, 1);
    mSplitter2->setStretchFactor(1, 1);
Laurent Montel's avatar
Laurent Montel committed
716

Laurent Montel's avatar
Laurent Montel committed
717
718
719
    if (mFavoriteCollectionsView) {
        mFolderViewSplitter->setStretchFactor(0, 0);
        mFolderViewSplitter->setStretchFactor(1, 1);
Laurent Montel's avatar
Laurent Montel committed
720
    }
721

Laurent Montel's avatar
Laurent Montel committed
722
723
724
    // Because the reader windows's width increases a tiny bit after each
    // restart in short folder list mode with message window at side, disable
    // the stretching as a workaround here
Laurent Montel's avatar
Laurent Montel committed
725
726
727
    if (readerWindowAtSide && !mLongFolderList) {
        mSplitter1->setStretchFactor(0, 1);
        mSplitter1->setStretchFactor(1, 0);
Laurent Montel's avatar
Laurent Montel committed
728
    }
729

Laurent Montel's avatar
Laurent Montel committed
730
731
732
733
734
735
    //
    // Set the sizes of the splitters to the values stored in the config
    //
    QList<int> splitter1Sizes;
    QList<int> splitter2Sizes;

Laurent Montel's avatar
Laurent Montel committed
736
737
738
739
740
741
    const int folderViewWidth = KMailSettings::self()->folderViewWidth();
    int ftHeight = KMailSettings::self()->folderTreeHeight();
    int headerHeight = KMailSettings::self()->searchAndHeaderHeight();
    const int messageViewerWidth = KMailSettings::self()->readerWindowWidth();
    int headerWidth = KMailSettings::self()->searchAndHeaderWidth();
    int messageViewerHeight = KMailSettings::self()->readerWindowHeight();
Laurent Montel's avatar
Laurent Montel committed
742

Laurent Montel's avatar
Laurent Montel committed
743
    int ffvHeight = mFolderViewSplitter ? KMKernel::self()->mailCommonSettings()->favoriteCollectionViewHeight() : 0;
Laurent Montel's avatar
Laurent Montel committed
744
745

    // If the message viewer was hidden before, make sure it is not zero height
Laurent Montel's avatar
Laurent Montel committed
746
    if (messageViewerHeight < 10 && readerWindowBelow) {
Laurent Montel's avatar
Laurent Montel committed
747
748
        headerHeight /= 2;
        messageViewerHeight = headerHeight;
749
    }
Laurent Montel's avatar
Laurent Montel committed
750

Laurent Montel's avatar
Laurent Montel committed
751
752
    if (mLongFolderList) {
        if (!readerWindowAtSide) {
Laurent Montel's avatar
Laurent Montel committed
753
754
755
            splitter1Sizes << folderViewWidth << headerWidth;
            splitter2Sizes << headerHeight << messageViewerHeight;
        } else {
Laurent Montel's avatar
Laurent Montel committed
756
            splitter1Sizes << folderViewWidth << (headerWidth + messageViewerWidth);
Laurent Montel's avatar
Laurent Montel committed
757
758
            splitter2Sizes << headerWidth << messageViewerWidth;
        }
759
    } else {
Laurent Montel's avatar
Laurent Montel committed
760
        if (!readerWindowAtSide) {
Laurent Montel's avatar
Laurent Montel committed
761
762
763
764
765
766
            splitter1Sizes << headerHeight << messageViewerHeight;
            splitter2Sizes << folderViewWidth << headerWidth;
        } else {
            splitter1Sizes << headerWidth << messageViewerWidth;
            splitter2Sizes << ftHeight + ffvHeight << messageViewerHeight;
        }
767
768
    }

Laurent Montel's avatar
Laurent Montel committed
769
770
    mSplitter1->setSizes(splitter1Sizes);
    mSplitter2->setSizes(splitter2Sizes);
771

Laurent Montel's avatar
Laurent Montel committed
772
    if (mFolderViewSplitter) {
Laurent Montel's avatar
Laurent Montel committed
773
774
        QList<int> splitterSizes;
        splitterSizes << ffvHeight << ftHeight;
Laurent Montel's avatar
Laurent Montel committed
775
        mFolderViewSplitter->setSizes(splitterSizes);
Laurent Montel's avatar
Laurent Montel committed
776
    }
777

Laurent Montel's avatar
Laurent Montel committed
778
779
780
    //
    // Now add the splitters to the main layout
    //
Laurent Montel's avatar
Laurent Montel committed
781
    mTopLayout->addWidget(mSplitter1);
782

Laurent Montel's avatar
Laurent Montel committed
783
784
785
786
787
    // Make sure the focus is on the view, and not on the quick search line edit, because otherwise
    // shortcuts like + or j go to the wrong place.
    // This would normally be done in the message list itself, but apparently something resets the focus
    // again, probably all the reparenting we do here.
    mMessagePane->focusView();
Laurent Montel's avatar
Laurent Montel committed
788

Laurent Montel's avatar
Laurent Montel committed
789
    // By default hide th unread and size columns on first run.
Laurent Montel's avatar
Laurent Montel committed
790
791
792
    if (kmkernel->firstStart()) {
        mFolderTreeWidget->folderTreeView()->hideColumn(1);
        mFolderTreeWidget->folderTreeView()->hideColumn(3);
Laurent Montel's avatar
Laurent Montel committed
793
        mFolderTreeWidget->folderTreeView()->header()->resizeSection(0, static_cast<int>(folderViewWidth * 0.8));
Laurent Montel's avatar
Laurent Montel committed
794
    }
795

Laurent Montel's avatar
Laurent Montel committed
796
    // Make the copy action work, see disconnect comment above
Laurent Montel's avatar
Laurent Montel committed
797
    if (mMsgView) {
Laurent Montel's avatar
Laurent Montel committed
798
        connect(mMsgView->copyAction(), &QAction::triggered, mMsgView, &KMReaderWin::slotCopySelectedText);
Laurent Montel's avatar
Laurent Montel committed
799
    }
800
}
Stephan Kulow's avatar
Stephan Kulow committed
801

802
803
804
//-----------------------------------------------------------------------------
void KMMainWidget::refreshFavoriteFoldersViewProperties()
{
Laurent Montel's avatar
Laurent Montel committed
805
    if (mFavoriteCollectionsView) {
Laurent Montel's avatar
Laurent Montel committed
806
        if (KMKernel::self()->mailCommonSettings()->favoriteCollectionViewMode() == MailCommon::MailCommonSettings::EnumFavoriteCollectionViewMode::IconMode) {
Laurent Montel's avatar
Laurent Montel committed
807
            mFavoriteCollectionsView->changeViewMode(QListView::IconMode);