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
36
#include <MailCommon/FolderSelectionDialog>
#include <MailCommon/FolderTreeWidget>
#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>
#include <MailCommon/MailKernel>
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"
Laurent Montel's avatar
Laurent Montel committed
50
#include <MailCommon/SearchRuleStatus>
Laurent Montel's avatar
Laurent Montel committed
51
#include "plugininterface/kmailplugininterface.h"
Laurent Montel's avatar
Laurent Montel committed
52
#include <KPIMTextEdit/TextToSpeech>
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
71
72
73
74
75
76
77
#include <PimCommon/PimUtil>
#include <MailCommon/CollectionGeneralPage>
#include <MailCommon/CollectionExpiryPage>
#include <MailCommon/ExpireCollectionAttribute>
#include <MailCommon/FilterManager>
#include <MailCommon/MailFilter>
#include <MailCommon/FavoriteCollectionWidget>
#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

Laurent Montel's avatar
Laurent Montel committed
83
84
85
86
#include <MessageViewer/MessageViewerSettings>
#include <MessageViewer/Viewer>
#include <MessageViewer/HeaderStylePlugin>
#include <MessageViewer/HeaderStyle>
Laurent Montel's avatar
Laurent Montel committed
87
#include "messageviewer/config-messageviewer.h"
88

89
#include <MessageViewer/AttachmentStrategy>
90

91
#ifndef QT_NO_CURSOR
Laurent Montel's avatar
Laurent Montel committed
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

Laurent Montel's avatar
Laurent Montel committed
104
#include <KSieveUi/VacationManager>
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
109
#include <Libkdepim/ProgressManager>
#include <Libkdepim/BroadcastStatus>
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>
141
142
#include <MailTransport/TransportManager>
#include <MailTransport/Transport>
Laurent Montel's avatar
Laurent Montel committed
143
#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>
#include <KSieveUi/Util>
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>
Laurent Montel's avatar
Laurent Montel committed
173
#include <QFileDialog>
174

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

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

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

Laurent Montel's avatar
Laurent Montel committed
202

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

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

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

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

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

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

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

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

    readConfig();

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

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

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

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

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

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

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

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

    kmkernel->toggleSystemTray();

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

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

            pagesRegistered = true;
        }
    }

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

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

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

Laurent Montel's avatar
Laurent Montel committed
322
    if (kmkernel->firstStart()) {
Laurent Montel's avatar
Laurent Montel committed
323
        const QStringList listOfMailerFound = MailCommon::Util::foundMailer();
324
325
326
        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"));
327
                if (!QProcess::startDetached(path, QStringList())) {
Laurent Montel's avatar
Laurent Montel committed
328
329
330
                    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
331
332
                }
            } else {
333
                mLaunchExternalComponent->slotAccountWizard();
Laurent Montel's avatar
Laurent Montel committed
334
335
            }
        } else {
336
            mLaunchExternalComponent->slotAccountWizard();
337
338
        }
    }
Laurent Montel's avatar
Laurent Montel committed
339
340
    // must be the last line of the constructor:
    mStartupDone = true;
341

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

    setupUnifiedMailboxChecker();
347
348
}

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

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

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

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

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

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

Laurent Montel's avatar
Laurent Montel committed
412
413
414
415
416
    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
417

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Laurent Montel's avatar
Laurent Montel committed
568
void KMMainWidget::slotShowSelectedFolderInPane()
569
{
570
    if (mCurrentCollection.isValid()) {
571
572
573
574
        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
575
    }
Laurent Montel's avatar
Laurent Montel committed
576
577
    updateMessageActions();
    updateFolderMenu();
578
579
}

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

Laurent Montel's avatar
Laurent Montel committed
587
588
    mHtmlGlobalSetting = MessageViewer::MessageViewerSettings::self()->htmlMail();
    mHtmlLoadExtGlobalSetting = MessageViewer::MessageViewerSettings::self()->htmlLoadExternal();
Laurent Montel's avatar
Laurent Montel committed
589

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

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

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

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

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

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

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

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

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

        // and the rest to the right
Laurent Montel's avatar
Laurent Montel committed
686
        mSplitter1->addWidget(mSplitter2);
Laurent Montel's avatar
Laurent Montel committed
687
688

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

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

Laurent Montel's avatar
Laurent Montel committed
709
        mSplitter1->addWidget(mSplitter2);
Laurent Montel's avatar
Laurent Montel committed
710
711

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

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

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

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

Laurent Montel's avatar
Laurent Montel committed
738
739
740
    if (mFavoriteCollectionsView) {
        mFolderViewSplitter->setStretchFactor(0, 0);
        mFolderViewSplitter->setStretchFactor(1, 1);
Laurent Montel's avatar
Laurent Montel committed
741
    }
742

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

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

Laurent Montel's avatar
Laurent Montel committed
764
    int ffvHeight = mFolderViewSplitter ? KMKernel::self()->mailCommonSettings()->favoriteCollectionViewHeight() : 0;
Laurent Montel's avatar
Laurent Montel committed
765
766

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

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

Laurent Montel's avatar
Laurent Montel committed
790
791
    mSplitter1->setSizes(splitter1Sizes);
    mSplitter2->setSizes(splitter2Sizes);
792

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

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

Laurent Montel's avatar
Laurent Montel committed
804
805
806
807
808
    // 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
809

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

Laurent Montel's avatar
Laurent Montel committed
817
    // Make the copy action work, see disconnect comment above
Laurent Montel's avatar
Laurent Montel committed
818
    if (mMsgView) {
Laurent Montel's avatar
Laurent Montel committed
819
820
        connect(mMsgView->copyAction(), &QAction::triggered,
                mMsgView, &KMReaderWin::slotCopySelectedText);
Laurent Montel's avatar
Laurent Montel committed
821
    }
822
}
Stephan Kulow's avatar
Stephan Kulow committed
823

824
825
826
//-----------------------------------------------------------------------------
void KMMainWidget::refreshFavoriteFoldersViewProperties()
{
Laurent Montel's avatar
Laurent Montel committed
827
    if (mFavoriteCollectionsView) {
Laurent Montel's avatar
Laurent Montel committed
828
        if (KMKernel::self()->mailCommonSettings()->favoriteCollectionViewMode() == MailCommon::MailCommonSettings::EnumFavoriteCollectionViewMode::IconMode) {