kmmainwidget.cpp 199 KB
Newer Older
Laurent Montel's avatar
Laurent Montel committed
1
/*
2
3
  This file is part of KMail, the KDE mail client.
  Copyright (c) 2002 Don Sanders <sanders@kde.org>
Laurent Montel's avatar
Laurent Montel committed
4
  Copyright (c) 2009-2020 Laurent Montel <montel@kde.org>
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

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

  KMail is free software; you can redistribute it and/or modify it
  under the terms of the GNU General Public License, version 2, as
  published by the Free Software Foundation.

  KMail 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
*/
Stephan Kulow's avatar
Stephan Kulow committed
21

Thomas McGuire's avatar
Thomas McGuire committed
22
// KMail includes
Yuri Chornoivan's avatar
Yuri Chornoivan committed
23
#include "kmmainwidget.h"
Leo Franchi's avatar
Leo Franchi committed
24
#include "kmreadermainwin.h"
25
#include "job/composenewmessagejob.h"
Laurent Montel's avatar
Laurent Montel committed
26
#include "editor/composer.h"
Laurent Montel's avatar
Laurent Montel committed
27
#include "searchdialog/searchwindow.h"
28
#include "widgets/vacationscriptindicatorwidget.h"
Laurent Montel's avatar
Laurent Montel committed
29
#include "widgets/zoomlabelwidget.h"
Thomas McGuire's avatar
Thomas McGuire committed
30
31
32
#include "undostack.h"
#include "kmcommands.h"
#include "kmmainwin.h"
33
#include <TemplateParser/CustomTemplatesMenu>
Laurent Montel's avatar
Laurent Montel committed
34
35
#include "MailCommon/FolderSelectionDialog"
#include "MailCommon/FolderTreeWidget"
Laurent Montel's avatar
Laurent Montel committed
36
#include "PimCommonAkonadi/MailUtil"
Laurent Montel's avatar
Port++    
Laurent Montel committed
37
#include "util.h"
38

Laurent Montel's avatar
Laurent Montel committed
39
40
#include "mailcommon/mailutil.h"
#include "mailcommon/mailkernel.h"
Laurent Montel's avatar
Laurent Montel committed
41
#include "dialog/archivefolderdialog.h"
Laurent Montel's avatar
Laurent Montel committed
42
#include "settings/kmailsettings.h"
Laurent Montel's avatar
Laurent Montel committed
43
#include "MailCommon/FolderTreeView"
Laurent Montel's avatar
Laurent Montel committed
44
#include "tag/tagactionmanager.h"
45
#include "foldershortcutactionmanager.h"
Laurent Montel's avatar
Laurent Montel committed
46
#include "widgets/collectionpane.h"
47
#include "manageshowcollectionproperties.h"
48
#include "widgets/kactionmenutransport.h"
49
#include "widgets/kactionmenuaccount.h"
50
#include "mailcommon/searchrulestatus.h"
Laurent Montel's avatar
Laurent Montel committed
51
#include "plugininterface/kmailplugininterface.h"
Laurent Montel's avatar
Laurent Montel committed
52
#include "kpimtextedit/texttospeech.h"
53
#include "job/markallmessagesasreadinfolderandsubfolderjob.h"
54
#include "job/removeduplicatemessageinfolderandsubfolderjob.h"
55
#include "sieveimapinterface/kmsieveimappasswordprovider.h"
Laurent Montel's avatar
Laurent Montel committed
56
#include <KSieveUi/SieveDebugDialog>
57

58
#include <AkonadiWidgets/CollectionMaintenancePage>
Laurent Montel's avatar
Laurent Montel committed
59
60
61
62
63
#include "collectionpage/collectionquotapage.h"
#include "collectionpage/collectiontemplatespage.h"
#include "collectionpage/collectionshortcutpage.h"
#include "collectionpage/collectionviewpage.h"
#include "collectionpage/collectionmailinglistpage.h"
Laurent Montel's avatar
Laurent Montel committed
64
#include "tag/tagselectdialog.h"
Laurent Montel's avatar
Laurent Montel committed
65
#include "job/createnewcontactjob.h"
66
67
#include "folderarchive/folderarchiveutil.h"
#include "folderarchive/folderarchivemanager.h"
68

Laurent Montel's avatar
Laurent Montel committed
69
#include <PimCommonAkonadi/CollectionAclPage>
Laurent Montel's avatar
Laurent Montel committed
70
#include "PimCommon/PimUtil"
Laurent Montel's avatar
Laurent Montel committed
71
72
73
74
75
76
#include "MailCommon/CollectionGeneralPage"
#include "MailCommon/CollectionExpiryPage"
#include "MailCommon/ExpireCollectionAttribute"
#include "MailCommon/FilterManager"
#include "MailCommon/MailFilter"
#include "MailCommon/FavoriteCollectionWidget"
77
#include "MailCommon/FavoriteCollectionOrderProxyModel"
Laurent Montel's avatar
Laurent Montel committed
78
#include "mailcommonsettings_base.h"
79

Thomas McGuire's avatar
Thomas McGuire committed
80
// Other PIM includes
81
#include "kmail-version.h"
82

83
#include "messageviewer/messageviewersettings.h"
84
#include "messageviewer/viewer.h"
Laurent Montel's avatar
Laurent Montel committed
85
86
#include "messageviewer/headerstyleplugin.h"
#include "messageviewer/headerstyle.h"
Laurent Montel's avatar
Laurent Montel committed
87
#include "messageviewer/config-messageviewer.h"
88

89
#include <MessageViewer/AttachmentStrategy>
90

91
#ifndef QT_NO_CURSOR
92
#include "Libkdepim/KCursorSaver"
93
#endif
94

Laurent Montel's avatar
Laurent Montel committed
95
#include <MessageComposer/MessageSender>
Laurent Montel's avatar
Laurent Montel committed
96
#include "MessageComposer/MessageHelper"
97

Laurent Montel's avatar
Laurent Montel committed
98
#include <MessageCore/MessageCoreSettings>
Laurent Montel's avatar
Laurent Montel committed
99
#include "MessageCore/MailingList"
100

Laurent Montel's avatar
Laurent Montel committed
101
#include "dialog/kmknotify.h"
102
#include "widgets/displaymessageformatactionmenu.h"
103

104
#include "ksieveui/vacationmanager.h"
105
#include "kmlaunchexternalcomponent.h"
Laurent Montel's avatar
Laurent Montel committed
106

Thomas McGuire's avatar
Thomas McGuire committed
107
// LIBKDEPIM includes
Laurent Montel's avatar
Laurent Montel committed
108
#include "libkdepim/progressmanager.h"
Laurent Montel's avatar
Laurent Montel committed
109
#include "libkdepim/broadcaststatus.h"
110

Thomas McGuire's avatar
Thomas McGuire committed
111
// KDEPIMLIBS includes
Laurent Montel's avatar
Laurent Montel committed
112
#include <AkonadiCore/AgentManager>
Laurent Montel's avatar
Laurent Montel committed
113
114
#include <AkonadiCore/AttributeFactory>
#include <AkonadiCore/itemfetchjob.h>
Laurent Montel's avatar
Laurent Montel committed
115
#include <AkonadiCore/collectionattributessynchronizationjob.h>
Laurent Montel's avatar
Laurent Montel committed
116
117
#include <AkonadiCore/collectionfetchjob.h>
#include <AkonadiCore/collectionfetchscope.h>
118
#include <Akonadi/Contact/ContactSearchJob>
Laurent Montel's avatar
Laurent Montel committed
119
#include <AkonadiWidgets/collectionpropertiesdialog.h>
Laurent Montel's avatar
Laurent Montel committed
120
#include <AkonadiCore/entitydisplayattribute.h>
Laurent Montel's avatar
Laurent Montel committed
121
122
#include <AkonadiWidgets/entitylistview.h>
#include <AkonadiWidgets/etmviewstatesaver.h>
Laurent Montel's avatar
Laurent Montel committed
123
124
125
126
127
#include <AkonadiCore/agentinstance.h>
#include <AkonadiCore/agenttype.h>
#include <AkonadiCore/changerecorder.h>
#include <AkonadiCore/session.h>
#include <AkonadiCore/entitytreemodel.h>
Laurent Montel's avatar
Laurent Montel committed
128
#include <AkonadiCore/favoritecollectionsmodel.h>
Laurent Montel's avatar
Laurent Montel committed
129
130
#include <AkonadiCore/itemfetchscope.h>
#include <AkonadiCore/itemmodifyjob.h>
Laurent Montel's avatar
Laurent Montel committed
131
#include <AkonadiWidgets/controlgui.h>
Laurent Montel's avatar
Laurent Montel committed
132
#include <AkonadiWidgets/collectiondialog.h>
Laurent Montel's avatar
Laurent Montel committed
133
#include <AkonadiCore/collectionstatistics.h>
Laurent Montel's avatar
Laurent Montel committed
134
#include <AkonadiCore/EntityMimeTypeFilterModel>
135
#include <Akonadi/KMime/MessageFlags>
Laurent Montel's avatar
Laurent Montel committed
136
#include <AkonadiCore/CachePolicy>
137

Laurent Montel's avatar
Laurent Montel committed
138
139
#include <kidentitymanagement/identity.h>
#include <kidentitymanagement/identitymanager.h>
140
#include <KEmailAddress>
Laurent Montel's avatar
Laurent Montel committed
141
142
143
#include <mailtransport/transportmanager.h>
#include <mailtransport/transport.h>
#include <kmime/kmime_mdn.h>
Laurent Montel's avatar
Laurent Montel committed
144
145
#include <kmime/kmime_header_parsing.h>
#include <kmime/kmime_message.h>
146
147
#include <ksieveui/managesievescriptsdialog.h>
#include <ksieveui/util.h>
148

149
150
#include <PimCommon/LogActivitiesManager>

Thomas McGuire's avatar
Thomas McGuire committed
151
// KDELIBS includes
152
#include <KWindowSystem>
153
154
#include <KMessageBox>
#include <KActionMenu>
Laurent Montel's avatar
Laurent Montel committed
155
#include <QMenu>
156
157
158
#include <KAcceleratorManager>
#include <KStandardShortcut>
#include <KCharsets>
Laurent Montel's avatar
Laurent Montel committed
159
#include "kmail_debug.h"
Laurent Montel's avatar
Laurent Montel committed
160

161
162
163
164
165
166
167
168
169
#include <KStandardAction>
#include <KToggleAction>
#include <KNotification>
#include <KNotifyConfigWidget>
#include <KStringHandler>
#include <KConfigGroup>
#include <KToolInvocation>
#include <KXMLGUIFactory>
#include <KXMLGUIClient>
Laurent Montel's avatar
Laurent Montel committed
170
171
#include <QStatusBar>
#include <QAction>
Laurent Montel's avatar
Laurent Montel committed
172
#include <KRecentFilesAction>
173

Thomas McGuire's avatar
Thomas McGuire committed
174
175
// Qt includes
#include <QByteArray>
176
#include <QHeaderView>
Thomas McGuire's avatar
Thomas McGuire committed
177
178
179
180
181
#include <QList>
#include <QSplitter>
#include <QVBoxLayout>
#include <QShortcut>
#include <QProcess>
182
#include <WebEngineViewer/WebHitTestResult>
Thomas McGuire's avatar
Thomas McGuire committed
183
// System includes
Laurent Montel's avatar
Laurent Montel committed
184
#include <AkonadiWidgets/standardactionmanager.h>
Laurent Montel's avatar
Laurent Montel committed
185
#include <QStandardPaths>
186
187
188
#include <QDBusInterface>
#include <QDBusConnection>
#include <QDBusReply>
189

Laurent Montel's avatar
Laurent Montel committed
190
#include "PimCommonAkonadi/ManageServerSideSubscriptionJob"
191
#include <job/removeduplicatemailjob.h>
Laurent Montel's avatar
Laurent Montel committed
192
#include <job/removecollectionjob.h>
193

Laurent Montel's avatar
Laurent Montel committed
194
#include <MessageViewer/DKIMWidgetInfo>
Laurent Montel's avatar
Laurent Montel committed
195
#include <MessageViewer/DKIMViewerMenu>
196
197
198
199
200
#ifdef WITH_KUSERFEEDBACK
#include <KUserFeedback/NotificationPopup>
#include <KUserFeedback/Provider>
#endif

Laurent Montel's avatar
Laurent Montel committed
201

Thomas McGuire's avatar
Thomas McGuire committed
202
using namespace KMime;
203
using namespace Akonadi;
Andras Mantia's avatar
Andras Mantia committed
204
using namespace MailCommon;
Thomas McGuire's avatar
Thomas McGuire committed
205
206
207
208
using KPIM::ProgressManager;
using KPIM::BroadcastStatus;
using KMail::SearchWindow;
using KMime::Types::AddrSpecList;
209
using MessageViewer::AttachmentStrategy;
Stephan Kulow's avatar
Stephan Kulow committed
210

Laurent Montel's avatar
Laurent Montel committed
211
Q_GLOBAL_STATIC(KMMainWidget::PtrList, theMainWidgetList)
212

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

238
#ifdef WITH_KUSERFEEDBACK
Laurent Montel's avatar
Laurent Montel committed
239
240
    KUserFeedback::NotificationPopup *userFeedBackNotificationPopup = new KUserFeedback::NotificationPopup(this);
    userFeedBackNotificationPopup->setFeedbackProvider(kmkernel->userFeedbackProvider());
241
242
#endif

Laurent Montel's avatar
Laurent Montel committed
243
244
    mToolbarActionSeparator = new QAction(this);
    mToolbarActionSeparator->setSeparator(true);
Laurent Montel's avatar
Laurent Montel committed
245

Laurent Montel's avatar
Laurent Montel committed
246
247
248
    KMailPluginInterface::self()->setActionCollection(mActionCollection);
    KMailPluginInterface::self()->initializePlugins();
    KMailPluginInterface::self()->setMainWidget(this);
Laurent Montel's avatar
Laurent Montel committed
249

Laurent Montel's avatar
Laurent Montel committed
250
    theMainWidgetList->append(this);
Laurent Montel's avatar
Laurent Montel committed
251
252
253
254
255
256
257

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

    readConfig();

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

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

264
265
    connect(kmkernel, &KMKernel::startCheckMail,
            this, &KMMainWidget::slotStartCheckMail);
Laurent Montel's avatar
Laurent Montel committed
266

267
268
    connect(kmkernel, &KMKernel::endCheckMail,
            this, &KMMainWidget::slotEndCheckMail);
Laurent Montel's avatar
Laurent Montel committed
269

270
271
    connect(kmkernel, &KMKernel::configChanged,
            this, &KMMainWidget::slotConfigChanged);
Laurent Montel's avatar
Laurent Montel committed
272

273
274
    connect(kmkernel, &KMKernel::onlineStatusChanged,
            this, &KMMainWidget::slotUpdateOnlineStatus);
Laurent Montel's avatar
Laurent Montel committed
275

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

Laurent Montel's avatar
Laurent Montel committed
279
280
    connect(mTagActionManager, &KMail::TagActionManager::tagMoreActionClicked,
            this, &KMMainWidget::slotSelectMoreMessageTagList);
Laurent Montel's avatar
Laurent Montel committed
281
282
283

    kmkernel->toggleSystemTray();

Laurent Montel's avatar
Laurent Montel committed
284
285
    {
        // make sure the pages are registered only once, since there can be multiple instances of KMMainWidget
Laurent Montel's avatar
Laurent Montel committed
286
287
        static bool pagesRegistered = false;

Laurent Montel's avatar
Laurent Montel committed
288
289
290
291
292
293
294
295
296
297
        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
298
299
300
301
302

            pagesRegistered = true;
        }
    }

Laurent Montel's avatar
Laurent Montel committed
303
    KMainWindow *mainWin = qobject_cast<KMainWindow *>(window());
Laurent Montel's avatar
Laurent Montel committed
304
305
    mCurrentStatusBar = mainWin ? mainWin->statusBar() : nullptr;
    mVacationScriptIndicator = new KMail::VacationScriptIndicatorWidget(mCurrentStatusBar);
Laurent Montel's avatar
Laurent Montel committed
306
    mVacationScriptIndicator->hide();
Laurent Montel's avatar
Laurent Montel committed
307

Laurent Montel's avatar
Laurent Montel committed
308
309
310
311
    mZoomLabelIndicator = new ZoomLabelWidget(mCurrentStatusBar);
    if (mMsgView) {
        setZoomChanged(mMsgView->viewer()->webViewZoomFactor());
    }
Laurent Montel's avatar
Laurent Montel committed
312
    connect(mVacationScriptIndicator, &KMail::VacationScriptIndicatorWidget::clicked, this, &KMMainWidget::slotEditVacation);
Laurent Montel's avatar
Laurent Montel committed
313
    if (KSieveUi::Util::checkOutOfOfficeOnStartup()) {
314
        QTimer::singleShot(0, this, &KMMainWidget::slotCheckVacation);
Laurent Montel's avatar
Laurent Montel committed
315
    }
Laurent Montel's avatar
Laurent Montel committed
316

317
318
    connect(mFolderTreeWidget->folderTreeView()->model(), &QAbstractItemModel::modelReset,
            this, &KMMainWidget::restoreCollectionFolderViewConfig);
Laurent Montel's avatar
Laurent Montel committed
319
320
    restoreCollectionFolderViewConfig();

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

Laurent Montel's avatar
Laurent Montel committed
341
342
    mCheckMailTimer.setInterval(3 * 1000);
    mCheckMailTimer.setSingleShot(true);
Laurent Montel's avatar
Laurent Montel committed
343
    connect(&mCheckMailTimer, &QTimer::timeout, this, &KMMainWidget::slotUpdateActionsAfterMailChecking);
344
345

    setupUnifiedMailboxChecker();
346
347
}

Laurent Montel's avatar
Laurent Montel committed
348
349
QWidget *KMMainWidget::dkimWidgetInfo() const
{
350
351
352
353
    if (mMsgView) {
        return mMsgView->viewer()->dkimWidgetInfo();
    }
    return nullptr;
Laurent Montel's avatar
Laurent Montel committed
354
}
Laurent Montel's avatar
Laurent Montel committed
355

356
void KMMainWidget::restoreCollectionFolderViewConfig()
357
{
Laurent Montel's avatar
Laurent Montel committed
358
    ETMViewStateSaver *saver = new ETMViewStateSaver;
Laurent Montel's avatar
Laurent Montel committed
359
360
361
362
    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
363
    //Restore startup folder
364

Laurent Montel's avatar
Laurent Montel committed
365
    Akonadi::Collection::Id id = -1;
366
367
    if (mCurrentCollection.isValid()) {
        id = mCurrentCollection.id();
Laurent Montel's avatar
Laurent Montel committed
368
    }
369

Laurent Montel's avatar
Laurent Montel committed
370
    if (id == -1) {
Laurent Montel's avatar
Laurent Montel committed
371
372
        if (KMailSettings::self()->startSpecificFolderAtStartup()) {
            Akonadi::Collection::Id startupFolder = KMailSettings::self()->startupFolder();
Laurent Montel's avatar
Laurent Montel committed
373
            if (startupFolder > 0) {
Laurent Montel's avatar
Laurent Montel committed
374
                saver->restoreCurrentItem(QStringLiteral("c%1").arg(startupFolder));
Laurent Montel's avatar
Laurent Montel committed
375
            }
Laurent Montel's avatar
Laurent Montel committed
376
377
        }
    } else {
Laurent Montel's avatar
Laurent Montel committed
378
        saver->restoreCurrentItem(QStringLiteral("c%1").arg(id));
379
    }
Stephan Kulow's avatar
Stephan Kulow committed
380
381
382
383
384
}

//-----------------------------------------------------------------------------
//The kernel may have already been deleted when this method is called,
//perform all cleanup that requires the kernel in destruct()
385
KMMainWidget::~KMMainWidget()
Stephan Kulow's avatar
Stephan Kulow committed
386
{
Laurent Montel's avatar
Laurent Montel committed
387
388
    theMainWidgetList->removeAll(this);
    qDeleteAll(mFilterCommands);
Laurent Montel's avatar
Laurent Montel committed
389
    destruct();
Stephan Kulow's avatar
Stephan Kulow committed
390
391
392
393
}

//-----------------------------------------------------------------------------
//This method performs all cleanup that requires the kernel to exist.
394
void KMMainWidget::destruct()
Stephan Kulow's avatar
Stephan Kulow committed
395
{
Laurent Montel's avatar
Laurent Montel committed
396
    if (mDestructed) {
Laurent Montel's avatar
Laurent Montel committed
397
        return;
Laurent Montel's avatar
Laurent Montel committed
398
399
    }
    if (mSearchWin) {
Laurent Montel's avatar
Laurent Montel committed
400
        mSearchWin->close();
Laurent Montel's avatar
Laurent Montel committed
401
    }
402
    disconnect(mFolderTreeWidget->folderTreeView()->selectionModel(), &QItemSelectionModel::selectionChanged, this, &KMMainWidget::updateFolderMenu);
Laurent Montel's avatar
Laurent Montel committed
403
404
405
    writeConfig(false); /* don't force kmkernel sync when close BUG: 289287 */
    writeFolderConfig();
    deleteWidgets();
406
    clearCurrentFolder();
Laurent Montel's avatar
Laurent Montel committed
407
408
    delete mMoveOrCopyToDialog;
    delete mSelectFromAllFoldersDialog;
409
    delete mSievePasswordProvider;
Laurent Montel's avatar
Laurent Montel committed
410

Laurent Montel's avatar
Laurent Montel committed
411
412
413
414
415
    disconnect(kmkernel->folderCollectionMonitor(), SIGNAL(itemAdded(Akonadi::Item,Akonadi::Collection)), this, nullptr);
    disconnect(kmkernel->folderCollectionMonitor(), SIGNAL(itemRemoved(Akonadi::Item)), this, nullptr);
    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
416

Laurent Montel's avatar
Laurent Montel committed
417
    mDestructed = true;
Stephan Kulow's avatar
Stephan Kulow committed
418
419
}

420
421
void KMMainWidget::clearCurrentFolder()
{
Laurent Montel's avatar
Laurent Montel committed
422
    mCurrentFolderSettings.clear();
423
424
425
    mCurrentCollection = Akonadi::Collection();
}

426
427
void KMMainWidget::slotStartCheckMail()
{
Laurent Montel's avatar
Laurent Montel committed
428
    if (mCheckMailTimer.isActive()) {
Laurent Montel's avatar
Laurent Montel committed
429
        mCheckMailTimer.stop();
Laurent Montel's avatar
Laurent Montel committed
430
    }
431
432
433
434
}

void KMMainWidget::slotEndCheckMail()
{
Laurent Montel's avatar
Laurent Montel committed
435
    if (!mCheckMailTimer.isActive()) {
Laurent Montel's avatar
Laurent Montel committed
436
        mCheckMailTimer.start();
Laurent Montel's avatar
Laurent Montel committed
437
    }
438
439
}

Laurent Montel's avatar
Laurent Montel committed
440
void KMMainWidget::slotUpdateActionsAfterMailChecking()
441
{
Laurent Montel's avatar
Laurent Montel committed
442
443
444
445
    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
446
    if (!kmkernel->isOffline() && (sendOnAll || sendOnManual)) {
Laurent Montel's avatar
Laurent Montel committed
447
448
449
450
451
        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();
452
453
}

454
455
456
void KMMainWidget::setCurrentCollection(const Akonadi::Collection &col)
{
    mCurrentCollection = col;
Laurent Montel's avatar
Laurent Montel committed
457
458
    if (mCurrentFolderSettings) {
        mCurrentFolderSettings->setCollection(col);
459
460
461
    }
}

Laurent Montel's avatar
Laurent Montel committed
462
void KMMainWidget::slotCollectionFetched(int collectionId)
463
{
Laurent Montel's avatar
Laurent Montel committed
464
465
466
    // 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.
467
    if (collectionId == mCurrentCollection.id()) {
468
        setCurrentCollection(CommonKernel->collectionFromId(mCurrentCollection.id()));
Laurent Montel's avatar
Laurent Montel committed
469
470
471
472
        updateMessageActions();
        updateFolderMenu();
    }
    // We call this for any collection, it could be one of our parents...
473
    if (mCurrentCollection.isValid()) {
474
        Q_EMIT captionChangeRequest(fullCollectionPath());
Laurent Montel's avatar
Laurent Montel committed
475
    }
476
477
}

478
479
480
481
482
483
484
QString KMMainWidget::fullCollectionPath() const
{
    if (mCurrentCollection.isValid()) {
        return MailCommon::Util::fullCollectionPath(mCurrentCollection);
    }
    return {};
}
485

486
// Connected to the currentChanged signals from the folderTreeView and favorites view.
Laurent Montel's avatar
Laurent Montel committed
487
void KMMainWidget::slotFolderChanged(const Akonadi::Collection &collection)
488
{
Laurent Montel's avatar
Laurent Montel committed
489
    if (mCurrentCollection == collection) {
490
        return;
Laurent Montel's avatar
Laurent Montel committed
491
    }
Laurent Montel's avatar
Laurent Montel committed
492
493
494
495
496
    folderSelected(collection);
    if (collection.cachePolicy().syncOnDemand()) {
        AgentManager::self()->synchronizeCollection(collection, false);
    }
    mMsgActions->setCurrentMessage(Akonadi::Item());
Laurent Montel's avatar
Laurent Montel committed
497
    Q_EMIT captionChangeRequest(MailCommon::Util::fullCollectionPath(collection));
Laurent Montel's avatar
Laurent Montel committed
498
499
}

500
// Called by slotFolderChanged (no particular reason for this method to be split out)
Laurent Montel's avatar
Laurent Montel committed
501
void KMMainWidget::folderSelected(const Akonadi::Collection &col)
Laurent Montel's avatar
Laurent Montel committed
502
{
Laurent Montel's avatar
Laurent Montel committed
503
    if (mGoToFirstUnreadMessageInSelectedFolder) {
Laurent Montel's avatar
Laurent Montel committed
504
        // the default action has been overridden from outside
505
        mPreSelectionMode = MessageList::Core::PreSelectFirstUnreadCentered;
Laurent Montel's avatar
Laurent Montel committed
506
507
    } else {
        // use the default action
Laurent Montel's avatar
Laurent Montel committed
508
509
        switch (KMailSettings::self()->actionEnterFolder()) {
        case KMailSettings::EnumActionEnterFolder::SelectFirstUnread:
Laurent Montel's avatar
Laurent Montel committed
510
511
            mPreSelectionMode = MessageList::Core::PreSelectFirstUnreadCentered;
            break;
Laurent Montel's avatar
Laurent Montel committed
512
        case KMailSettings::EnumActionEnterFolder::SelectLastSelected:
Laurent Montel's avatar
Laurent Montel committed
513
514
            mPreSelectionMode = MessageList::Core::PreSelectLastSelected;
            break;
Laurent Montel's avatar
Laurent Montel committed
515
        case KMailSettings::EnumActionEnterFolder::SelectNewest:
Laurent Montel's avatar
Laurent Montel committed
516
517
            mPreSelectionMode = MessageList::Core::PreSelectNewestCentered;
            break;
Laurent Montel's avatar
Laurent Montel committed
518
        case KMailSettings::EnumActionEnterFolder::SelectOldest:
Laurent Montel's avatar
Laurent Montel committed
519
520
521
522
523
524
525
526
527
            mPreSelectionMode = MessageList::Core::PreSelectOldestCentered;
            break;
        default:
            mPreSelectionMode = MessageList::Core::PreSelectNone;
            break;
        }
    }

    mGoToFirstUnreadMessageInSelectedFolder = false;
528
#ifndef QT_NO_CURSOR
529
    KPIM::KCursorSaver busy(KPIM::KBusyPtr::busy());
530
#endif
Laurent Montel's avatar
Laurent Montel committed
531

Laurent Montel's avatar
Laurent Montel committed
532
    if (mMsgView) {
Laurent Montel's avatar
Laurent Montel committed
533
        mMsgView->clear(true);
Laurent Montel's avatar
Laurent Montel committed
534
    }
535
    const bool newFolder = mCurrentCollection != col;
David Faure's avatar
David Faure committed
536

Laurent Montel's avatar
Laurent Montel committed
537
538
    // Delete any pending timer, if needed it will be recreated below
    delete mShowBusySplashTimer;
Laurent Montel's avatar
Laurent Montel committed
539
    mShowBusySplashTimer = nullptr;
Laurent Montel's avatar
Laurent Montel committed
540
    if (newFolder) {
Laurent Montel's avatar
Laurent Montel committed
541
542
543
        // We're changing folder: write configuration for the old one
        writeFolderConfig();
    }
Laurent Montel's avatar
Laurent Montel committed
544

Laurent Montel's avatar
Laurent Montel committed
545
    mCurrentFolderSettings = FolderSettings::forCollection(col);
546
    mCurrentCollection = col;
Laurent Montel's avatar
Laurent Montel committed
547

Laurent Montel's avatar
Laurent Montel committed
548
    readFolderConfig();
Laurent Montel's avatar
Laurent Montel committed
549
    if (mMsgView) {
550
        assignLoadExternalReference();
Laurent Montel's avatar
Laurent Montel committed
551
    }
Laurent Montel's avatar
Laurent Montel committed
552

Laurent Montel's avatar
Laurent Montel committed
553
    if (!mCurrentFolderSettings->isValid() && (mMessagePane->count() < 2)) {
Laurent Montel's avatar
Laurent Montel committed
554
        slotIntro();
555
556
557
558
    } else {
        if (mMessagePane->isHidden()) {
            mMessagePane->show();
        }
Laurent Montel's avatar
Laurent Montel committed
559
    }
Laurent Montel's avatar
Laurent Montel committed
560

Laurent Montel's avatar
Laurent Montel committed
561
562
563
    // 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.
564
    QTimer::singleShot(0, this, &KMMainWidget::slotShowSelectedFolderInPane);
565
566
}

Laurent Montel's avatar
Laurent Montel committed
567
void KMMainWidget::slotShowSelectedFolderInPane()
568
{
569
    if (mCurrentCollection.isValid()) {
570
571
        QModelIndex idx = Akonadi::EntityTreeModel::modelIndexForCollection(KMKernel::self()->entityTreeModel(), mCurrentCollection);
        mMessagePane->setCurrentFolder(mCurrentCollection, idx, false, mPreSelectionMode);
Laurent Montel's avatar
Laurent Montel committed
572
    }
Laurent Montel's avatar
Laurent Montel committed
573
574
    updateMessageActions();
    updateFolderMenu();
575
576
}

Stephan Kulow's avatar
Stephan Kulow committed
577
//-----------------------------------------------------------------------------
578
void KMMainWidget::readPreConfig()
Stephan Kulow's avatar
Stephan Kulow committed
579
{
Laurent Montel's avatar
Laurent Montel committed
580
581
582
    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
583

Laurent Montel's avatar
Laurent Montel committed
584
585
    mHtmlGlobalSetting = MessageViewer::MessageViewerSettings::self()->htmlMail();
    mHtmlLoadExtGlobalSetting = MessageViewer::MessageViewerSettings::self()->htmlLoadExternal();
Laurent Montel's avatar
Laurent Montel committed
586

Laurent Montel's avatar
Laurent Montel committed
587
    mEnableFavoriteFolderView = (KMKernel::self()->mailCommonSettings()->favoriteCollectionViewMode() != MailCommon::MailCommonSettings::EnumFavoriteCollectionViewMode::HiddenMode);
588
589
    mEnableFolderQuickSearch = KMailSettings::self()->enableFolderQuickSearch();

590
    readFolderConfig();
Laurent Montel's avatar
Laurent Montel committed
591
    updateHtmlMenuEntry();
592
593
    if (mMsgView) {
        mMsgView->setDisplayFormatMessageOverwrite(mFolderDisplayFormatPreference);
Laurent Montel's avatar
Laurent Montel committed
594
        mMsgView->update(true);
595
    }
Stephan Kulow's avatar
Stephan Kulow committed
596
597
598
}

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

//-----------------------------------------------------------------------------
619
void KMMainWidget::writeFolderConfig()
Stephan Kulow's avatar
Stephan Kulow committed
620
{
621
    if (mCurrentCollection.isValid()) {
Laurent Montel's avatar
Laurent Montel committed
622
        KSharedConfig::Ptr config = KMKernel::self()->config();
Laurent Montel's avatar
Laurent Montel committed
623
        KConfigGroup group(config, MailCommon::FolderSettings::configGroupName(mCurrentCollection));
624
625
626
627
628
        if (mFolderHtmlLoadExtPreference) {
            group.writeEntry("htmlLoadExternalOverride", mFolderHtmlLoadExtPreference);
        } else {
            group.deleteEntry("htmlLoadExternalOverride");
        }
Laurent Montel's avatar
Laurent Montel committed
629
        if (mFolderDisplayFormatPreference == MessageViewer::Viewer::UseGlobalSetting) {
630
            group.deleteEntry("displayFormatOverride");
Laurent Montel's avatar
Laurent Montel committed
631
632
633
        } else {
            group.writeEntry("displayFormatOverride", static_cast<int>(mFolderDisplayFormatPreference));
        }
Laurent Montel's avatar
Laurent Montel committed
634
    }
Stephan Kulow's avatar
Stephan Kulow committed
635
636
}

637
638
639
//-----------------------------------------------------------------------------
void KMMainWidget::layoutSplitters()
{
Laurent Montel's avatar
Laurent Montel committed
640
    // This function can only be called when the old splitters are already deleted
Laurent Montel's avatar
Laurent Montel committed
641
642
    Q_ASSERT(!mSplitter1);
    Q_ASSERT(!mSplitter2);
643

Laurent Montel's avatar
Laurent Montel committed
644
645
    // 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
646
    if (mMsgView) {
Laurent Montel's avatar
Laurent Montel committed
647
648
        disconnect(mMsgView->copyAction(), &QAction::triggered,
                   mMsgView, &KMReaderWin::slotCopySelectedText);
Laurent Montel's avatar
Laurent Montel committed
649
    }
Laurent Montel's avatar
Laurent Montel committed
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664

    // 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
665
666
    mSplitter1 = new QSplitter(this);
    mSplitter2 = new QSplitter(mSplitter1);
Laurent Montel's avatar
Laurent Montel committed
667

668
    QWidget *folderTreeWidget = mFolderTreeWidget;
Laurent Montel's avatar
Laurent Montel committed
669
670
    if (mFavoriteCollectionsView) {
        mFolderViewSplitter = new QSplitter(Qt::Vertical);
Laurent Montel's avatar
Laurent Montel committed
671
        mFolderViewSplitter->setChildrenCollapsible(false);
Laurent Montel's avatar
Laurent Montel committed
672
        mFolderViewSplitter->addWidget(mFavoriteCollectionsView);
673
        mFolderViewSplitter->addWidget(mFolderTreeWidget);
Laurent Montel's avatar
Laurent Montel committed
674
        folderTreeWidget = mFolderViewSplitter;
Till Adam's avatar
Till Adam committed
675
    }
676

Laurent Montel's avatar
Laurent Montel committed
677
    if (mLongFolderList) {
Laurent Montel's avatar
Laurent Montel committed
678
        // add folder tree
Laurent Montel's avatar
Laurent Montel committed
679
680
        mSplitter1->setOrientation(Qt::Horizontal);
        mSplitter1->addWidget(folderTreeWidget);
Laurent Montel's avatar
Laurent Montel committed
681
682

        // and the rest to the right
Laurent Montel's avatar
Laurent Montel committed
683
        mSplitter1->addWidget(mSplitter2);
Laurent Montel's avatar
Laurent Montel committed
684
685

        // add the message list to the right or below
Laurent Montel's avatar
Laurent Montel committed
686
687
        if (readerWindowAtSide) {
            mSplitter2->setOrientation(Qt::Horizontal);
Laurent Montel's avatar
Laurent Montel committed
688
        } else {
Laurent Montel's avatar
Laurent Montel committed
689
            mSplitter2->setOrientation(Qt::Vertical);
Laurent Montel's avatar
Laurent Montel committed
690
        }
Laurent Montel's avatar
Laurent Montel committed
691
        mSplitter2->addWidget(mMessagePane);
Laurent Montel's avatar
Laurent Montel committed
692
693

        // add the preview window, if there is one
Laurent Montel's avatar
Laurent Montel committed
694
695
        if (mMsgView) {
            mSplitter2->addWidget(mMsgView);
Laurent Montel's avatar
Laurent Montel committed
696
697
        }
    } else { // short folder list
Laurent Montel's avatar
Laurent Montel committed
698
699
700
        if (mReaderWindowBelow) {
            mSplitter1->setOrientation(Qt::Vertical);
            mSplitter2->setOrientation(Qt::Horizontal);
Laurent Montel's avatar
Laurent Montel committed
701
        } else { // at side or none
Laurent Montel's avatar
Laurent Montel committed
702
703
            mSplitter1->setOrientation(Qt::Horizontal);
            mSplitter2->setOrientation(Qt::Vertical);
Laurent Montel's avatar
Laurent Montel committed
704
705
        }

Laurent Montel's avatar
Laurent Montel committed
706
        mSplitter1->addWidget(mSplitter2);
Laurent Montel's avatar
Laurent Montel committed
707
708

        // add folder tree
Laurent Montel's avatar
Laurent Montel committed
709
        mSplitter2->addWidget(folderTreeWidget);
Laurent Montel's avatar
Laurent Montel committed
710
        // add message list to splitter 2
Laurent Montel's avatar
Laurent Montel committed
711
        mSplitter2->addWidget(mMessagePane);
Laurent Montel's avatar
Laurent Montel committed
712
713

        // add the preview window, if there is one
Laurent Montel's avatar
Laurent Montel committed
714
715
716
        if (mMsgView) {
            mSplitter1->addWidget(mMsgView);
        }
Till Adam's avatar
Till Adam committed
717
    }
718

Laurent Montel's avatar
Laurent Montel committed
719
720
721
    //
    // Set splitter properties
    //
Laurent Montel's avatar
Laurent Montel committed
722
    mSplitter1->setObjectName(QStringLiteral("splitter1"));
Laurent Montel's avatar
Laurent Montel committed
723
    mSplitter1->setChildrenCollapsible(false);
Laurent Montel's avatar
Laurent Montel committed
724
    mSplitter2->setObjectName(QStringLiteral("splitter2"));
Laurent Montel's avatar
Laurent Montel committed
725
    mSplitter2->setChildrenCollapsible(false);
Laurent Montel's avatar
Laurent Montel committed
726
727
728
729

    //
    // Set the stretch factors
    //
Laurent Montel's avatar
Laurent Montel committed
730
731
732
733
    mSplitter1->setStretchFactor(0, 0);
    mSplitter2->setStretchFactor(0, 0);
    mSplitter1->setStretchFactor(1, 1);
    mSplitter2->setStretchFactor(1, 1);
Laurent Montel's avatar
Laurent Montel committed
734

Laurent Montel's avatar
Laurent Montel committed
735
736
737
    if (mFavoriteCollectionsView) {
        mFolderViewSplitter->setStretchFactor(0, 0);
        mFolderViewSplitter->setStretchFactor(1, 1);
Laurent Montel's avatar
Laurent Montel committed
738
    }
739

Laurent Montel's avatar
Laurent Montel committed
740
741
742
    // 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
743
744
745
    if (readerWindowAtSide && !mLongFolderList) {
        mSplitter1->setStretchFactor(0, 1);
        mSplitter1->setStretchFactor(1, 0);
Laurent Montel's avatar
Laurent Montel committed
746
    }
747

Laurent Montel's avatar
Laurent Montel committed
748
749
750
751
752
753
    //
    // 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
754
755
756
757
758
759
    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
760

Laurent Montel's avatar
Laurent Montel committed
761
    int ffvHeight = mFolderViewSplitter ? KMKernel::self()->mailCommonSettings()->favoriteCollectionViewHeight() : 0;
Laurent Montel's avatar
Laurent Montel committed
762
763

    // If the message viewer was hidden before, make sure it is not zero height
Laurent Montel's avatar
Laurent Montel committed
764
    if (messageViewerHeight < 10 && readerWindowBelow) {
Laurent Montel's avatar
Laurent Montel committed
765
766
        headerHeight /= 2;
        messageViewerHeight = headerHeight;
767
    }
Laurent Montel's avatar
Laurent Montel committed
768

Laurent Montel's avatar
Laurent Montel committed
769
770
    if (mLongFolderList) {
        if (!readerWindowAtSide) {
Laurent Montel's avatar
Laurent Montel committed
771
772
773
            splitter1Sizes << folderViewWidth << headerWidth;
            splitter2Sizes << headerHeight << messageViewerHeight;
        } else {
Laurent Montel's avatar
Laurent Montel committed
774
            splitter1Sizes << folderViewWidth << (headerWidth + messageViewerWidth);
Laurent Montel's avatar
Laurent Montel committed
775
776
            splitter2Sizes << headerWidth << messageViewerWidth;
        }
777
    } else {
Laurent Montel's avatar
Laurent Montel committed
778
        if (!readerWindowAtSide) {
Laurent Montel's avatar
Laurent Montel committed
779
780
781
782
783
784
            splitter1Sizes << headerHeight << messageViewerHeight;
            splitter2Sizes << folderViewWidth << headerWidth;
        } else {
            splitter1Sizes << headerWidth << messageViewerWidth;
            splitter2Sizes << ftHeight + ffvHeight << messageViewerHeight;
        }
785
786
    }

Laurent Montel's avatar
Laurent Montel committed
787
788
    mSplitter1->setSizes(splitter1Sizes);
    mSplitter2->setSizes(splitter2Sizes);
789

Laurent Montel's avatar
Laurent Montel committed
790
    if (mFolderViewSplitter) {
Laurent Montel's avatar
Laurent Montel committed
791
792
        QList<int> splitterSizes;
        splitterSizes << ffvHeight << ftHeight;
Laurent Montel's avatar
Laurent Montel committed
793
        mFolderViewSplitter->setSizes(splitterSizes);
Laurent Montel's avatar
Laurent Montel committed
794
    }
795

Laurent Montel's avatar
Laurent Montel committed
796
797
798
    //
    // Now add the splitters to the main layout
    //
Laurent Montel's avatar
Laurent Montel committed
799
    mTopLayout->addWidget(mSplitter1);
800

Laurent Montel's avatar
Laurent Montel committed
801
802
803
804
805
    // 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
806

Laurent Montel's avatar
Laurent Montel committed
807
    // By default hide th unread and size columns on first run.
Laurent Montel's avatar
Laurent Montel committed
808
809
810
    if (kmkernel->firstStart()) {
        mFolderTreeWidget->folderTreeView()->hideColumn(1);
        mFolderTreeWidget->folderTreeView()->hideColumn(3);
Laurent Montel's avatar
Laurent Montel committed
811
        mFolderTreeWidget->folderTreeView()->header()->resizeSection(0, static_cast<int>(folderViewWidth * 0.8));
Laurent Montel's avatar
Laurent Montel committed
812
    }
813

Laurent Montel's avatar
Laurent Montel committed
814
    // Make the copy action work, see disconnect comment above
Laurent Montel's avatar
Laurent Montel committed
815
    if (mMsgView) {
Laurent Montel's avatar
Laurent Montel committed
816
817
        connect(mMsgView->copyAction(), &QAction::triggered,
                mMsgView, &KMReaderWin::slotCopySelectedText);
Laurent Montel's avatar
Laurent Montel committed
818