File indexing completed on 2024-04-28 05:26:02

0001 // SPDX-FileCopyrightText: 2020 Carl Schwan <carlschwan@kde.org>
0002 // SPDX-License-Identifier: LGPL-2.0-or-later
0003 
0004 #include "mailmanager.h"
0005 #include "mailmodel.h"
0006 
0007 #include <QTimer>
0008 
0009 // Akonadi
0010 #include <Akonadi/ChangeRecorder>
0011 #include <Akonadi/CollectionFilterProxyModel>
0012 #include <Akonadi/EntityMimeTypeFilterModel>
0013 #include <Akonadi/EntityTreeModel>
0014 #include <Akonadi/ItemFetchScope>
0015 #include <Akonadi/MessageModel>
0016 #include <Akonadi/Monitor>
0017 #include <Akonadi/SelectionProxyModel>
0018 #include <Akonadi/ServerManager>
0019 #include <Akonadi/Session>
0020 #include <KDescendantsProxyModel>
0021 #include <KMime/Message>
0022 #include <MailCommon/FolderCollectionMonitor>
0023 #include <QApplication>
0024 #include <QtCore/QItemSelectionModel>
0025 
0026 #include <KItemModels/KDescendantsProxyModel>
0027 
0028 MailManager::MailManager(QObject *parent)
0029     : QObject(parent)
0030     , m_loading(true)
0031 {
0032     using namespace Akonadi;
0033     //                              mailModel
0034     //                                  ^
0035     //                                  |
0036     //                              itemModel
0037     //                                  |
0038     //                              flatModel
0039     //                                  |
0040     //  descendantsProxyModel ------> selectionModel
0041     //           ^                      ^
0042     //           |                      |
0043     //  collectionFilter                |
0044     //            \__________________treemodel
0045 
0046     m_session = new Session(QByteArrayLiteral("KMailManager Kernel ETM"), this);
0047     auto folderCollectionMonitor = new MailCommon::FolderCollectionMonitor(m_session, this);
0048 
0049     // setup collection model
0050     auto treeModel = new Akonadi::EntityTreeModel(folderCollectionMonitor->monitor(), this);
0051     treeModel->setItemPopulationStrategy(Akonadi::EntityTreeModel::LazyPopulation);
0052 
0053     m_foldersModel = new Akonadi::CollectionFilterProxyModel(this);
0054     m_foldersModel->setSourceModel(treeModel);
0055     m_foldersModel->addMimeTypeFilter(KMime::Message::mimeType());
0056 
0057     // Setup selection model
0058     m_collectionSelectionModel = new QItemSelectionModel(m_foldersModel);
0059     connect(m_collectionSelectionModel, &QItemSelectionModel::selectionChanged, this, [this](const QItemSelection &selected, const QItemSelection &deselected) {
0060         Q_UNUSED(deselected)
0061         const auto indexes = selected.indexes();
0062         if (indexes.count()) {
0063             QString name;
0064             QModelIndex index = indexes[0];
0065             while (index.isValid()) {
0066                 if (name.isEmpty()) {
0067                     name = index.data(Qt::DisplayRole).toString();
0068                 } else {
0069                     name = index.data(Qt::DisplayRole).toString() + QLatin1String(" / ") + name;
0070                 }
0071                 index = index.parent();
0072             }
0073             m_selectedFolderName = name;
0074             Q_EMIT selectedFolderNameChanged();
0075         }
0076     });
0077     auto selectionModel = new SelectionProxyModel(m_collectionSelectionModel, this);
0078     selectionModel->setSourceModel(treeModel);
0079     selectionModel->setFilterBehavior(KSelectionProxyModel::ChildrenOfExactSelection);
0080 
0081     // Setup mail model
0082     auto folderFilterModel = new EntityMimeTypeFilterModel(this);
0083     folderFilterModel->setSourceModel(selectionModel);
0084     folderFilterModel->setHeaderGroup(EntityTreeModel::ItemListHeaders);
0085     folderFilterModel->addMimeTypeInclusionFilter(KMime::Message::mimeType());
0086     folderFilterModel->addMimeTypeExclusionFilter(Collection::mimeType());
0087 
0088     // Proxy for QML roles
0089     m_folderModel = new MailModel(this);
0090     m_folderModel->setSourceModel(folderFilterModel);
0091 
0092     if (Akonadi::ServerManager::isRunning()) {
0093         m_loading = false;
0094     } else {
0095         connect(Akonadi::ServerManager::self(), &Akonadi::ServerManager::stateChanged, this, [this](Akonadi::ServerManager::State state) {
0096             if (state == Akonadi::ServerManager::State::Broken) {
0097                 qApp->exit(-1);
0098                 return;
0099             }
0100             bool loading = state != Akonadi::ServerManager::State::Running;
0101             if (loading == m_loading) {
0102                 return;
0103             }
0104             m_loading = loading;
0105             Q_EMIT loadingChanged();
0106             disconnect(Akonadi::ServerManager::self(), &Akonadi::ServerManager::stateChanged, this, nullptr);
0107         });
0108     }
0109     Q_EMIT folderModelChanged();
0110     Q_EMIT loadingChanged();
0111 }
0112 
0113 MailModel *MailManager::folderModel() const
0114 {
0115     return m_folderModel;
0116 }
0117 
0118 void MailManager::loadMailCollection(const QModelIndex &modelIndex)
0119 {
0120     if (!modelIndex.isValid()) {
0121         return;
0122     }
0123 
0124     m_collectionSelectionModel->select(modelIndex, QItemSelectionModel::ClearAndSelect);
0125 }
0126 
0127 bool MailManager::loading() const
0128 {
0129     return m_loading;
0130 }
0131 
0132 Akonadi::CollectionFilterProxyModel *MailManager::foldersModel() const
0133 {
0134     return m_foldersModel;
0135 }
0136 
0137 Akonadi::Session *MailManager::session() const
0138 {
0139     return m_session;
0140 }
0141 
0142 QString MailManager::selectedFolderName() const
0143 {
0144     return m_selectedFolderName;
0145 }