File indexing completed on 2024-05-26 05:14:40

0001 /*
0002    SPDX-FileCopyrightText: 2009-2024 Laurent Montel <montel@kde.org>
0003 
0004    SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "collectionmaintenancepage.h"
0008 #include "agentmanager.h"
0009 #include "akonadiwidgets_debug.h"
0010 #include "cachepolicy.h"
0011 #include "core/collectionstatistics.h"
0012 #include "indexpolicyattribute.h"
0013 #include "monitor.h"
0014 #include "servermanager.h"
0015 #include "ui_collectionmaintenancepage.h"
0016 
0017 #include <QDBusInterface>
0018 #include <QDBusPendingCallWatcher>
0019 #include <QDBusPendingReply>
0020 
0021 #include <KIO/Global>
0022 
0023 #include <KLocalizedString>
0024 #include <QCheckBox>
0025 #include <QPushButton>
0026 
0027 using namespace Akonadi;
0028 
0029 class Akonadi::CollectionMaintenancePagePrivate
0030 {
0031 public:
0032     CollectionMaintenancePagePrivate()
0033     {
0034     }
0035 
0036     void slotReindexCollection()
0037     {
0038         if (currentCollection.isValid()) {
0039             // Don't allow to reindex twice.
0040             ui.reindexButton->setEnabled(false);
0041 
0042             const auto service = ServerManager::agentServiceName(ServerManager::Agent, QStringLiteral("akonadi_indexing_agent"));
0043             QDBusInterface indexingAgentIface(service, QStringLiteral("/"), QStringLiteral("org.freedesktop.Akonadi.Indexer"));
0044             if (indexingAgentIface.isValid()) {
0045                 indexingAgentIface.call(QStringLiteral("reindexCollection"), static_cast<qlonglong>(currentCollection.id()));
0046                 ui.indexedCountLbl->setText(i18n("Remember that indexing can take some minutes."));
0047             } else {
0048                 qCWarning(AKONADIWIDGETS_LOG) << "indexer interface not valid";
0049             }
0050         }
0051     }
0052 
0053     void updateLabel(qint64 nbMail, qint64 nbUnreadMail, qint64 size)
0054     {
0055         ui.itemsCountLbl->setText(QString::number(qMax(0LL, nbMail)));
0056         ui.unreadItemsCountLbl->setText(QString::number(qMax(0LL, nbUnreadMail)));
0057         ui.folderSizeLbl->setText(KIO::convertSize(qMax(0LL, size)));
0058     }
0059 
0060     Akonadi::Collection currentCollection;
0061     Akonadi::Monitor *monitor = nullptr;
0062 
0063     Ui::CollectionMaintenancePage ui;
0064 };
0065 
0066 CollectionMaintenancePage::CollectionMaintenancePage(QWidget *parent)
0067     : CollectionPropertiesPage(parent)
0068     , d(new CollectionMaintenancePagePrivate)
0069 {
0070     setObjectName(QLatin1StringView("Akonadi::CollectionMaintenancePage"));
0071     setPageTitle(i18n("Maintenance"));
0072 }
0073 
0074 CollectionMaintenancePage::~CollectionMaintenancePage() = default;
0075 
0076 void CollectionMaintenancePage::init(const Collection &col)
0077 {
0078     d->ui.setupUi(this);
0079 
0080     d->currentCollection = col;
0081     d->monitor = new Monitor(this);
0082     d->monitor->setObjectName(QLatin1StringView("CollectionMaintenancePageMonitor"));
0083     d->monitor->setCollectionMonitored(col, true);
0084     d->monitor->fetchCollectionStatistics(true);
0085     connect(d->monitor, &Monitor::collectionStatisticsChanged, this, [this](Collection::Id /*unused*/, const CollectionStatistics &stats) {
0086         d->updateLabel(stats.count(), stats.unreadCount(), stats.size());
0087     });
0088 
0089     if (!col.isVirtual()) {
0090         const AgentInstance instance = Akonadi::AgentManager::self()->instance(col.resource());
0091         d->ui.folderTypeLbl->setText(instance.type().name());
0092     } else {
0093         d->ui.folderTypeLbl->hide();
0094         d->ui.verticalLayout->labelForField(d->ui.folderTypeLbl)->hide();
0095     }
0096 
0097     connect(d->ui.reindexButton, &QPushButton::clicked, this, [this]() {
0098         d->slotReindexCollection();
0099     });
0100 
0101     // Check if the resource caches full payloads or at least has local storage
0102     // (so that the indexer can retrieve the payloads on demand)
0103     const auto resource = Akonadi::AgentManager::self()->instance(col.resource()).type();
0104     if (!col.cachePolicy().localParts().contains(QLatin1StringView("RFC822"))
0105         && resource.customProperties().value(QStringLiteral("HasLocalStorage"), QString()) != QLatin1StringView("true")) {
0106         d->ui.indexingLabel->hide();
0107         d->ui.enableIndexingChkBox->hide();
0108         d->ui.indexedCountLbl->hide();
0109         d->ui.reindexButton->hide();
0110     }
0111 }
0112 
0113 void CollectionMaintenancePage::load(const Collection &col)
0114 {
0115     init(col);
0116     if (col.isValid()) {
0117         d->updateLabel(col.statistics().count(), col.statistics().unreadCount(), col.statistics().size());
0118         const auto attr = col.attribute<Akonadi::IndexPolicyAttribute>();
0119         const bool indexingWasEnabled(!attr || attr->indexingEnabled());
0120         d->ui.enableIndexingChkBox->setChecked(indexingWasEnabled);
0121         if (indexingWasEnabled) {
0122             const auto service = ServerManager::agentServiceName(ServerManager::Agent, QStringLiteral("akonadi_indexing_agent"));
0123             QDBusInterface indexingAgentIface(service, QStringLiteral("/"), QStringLiteral("org.freedesktop.Akonadi.Indexer"));
0124             if (indexingAgentIface.isValid()) {
0125                 auto reply = indexingAgentIface.asyncCall(QStringLiteral("indexedItems"), static_cast<qint64>(col.id()));
0126                 auto w = new QDBusPendingCallWatcher(reply, this);
0127                 connect(w, &QDBusPendingCallWatcher::finished, this, [this](QDBusPendingCallWatcher *w) {
0128                     QDBusPendingReply<qint64> reply = *w;
0129                     if (reply.isError()) {
0130                         d->ui.indexedCountLbl->setText(i18n("Error while retrieving indexed items count"));
0131                         qCWarning(AKONADIWIDGETS_LOG) << "Failed to retrieve indexed items count:" << reply.error().message();
0132                     } else {
0133                         d->ui.indexedCountLbl->setText(i18np("Indexed %1 item in this folder", "Indexed %1 items in this folder", reply.argumentAt<0>()));
0134                     }
0135                     w->deleteLater();
0136                 });
0137                 d->ui.indexedCountLbl->setText(i18n("Calculating indexed items..."));
0138             } else {
0139                 qCDebug(AKONADIWIDGETS_LOG) << "Failed to obtain Indexer interface";
0140                 d->ui.indexedCountLbl->hide();
0141             }
0142         } else {
0143             d->ui.indexedCountLbl->hide();
0144         }
0145     }
0146 }
0147 
0148 void CollectionMaintenancePage::save(Collection &collection)
0149 {
0150     if (!collection.hasAttribute<Akonadi::IndexPolicyAttribute>() && d->ui.enableIndexingChkBox->isChecked()) {
0151         return;
0152     }
0153 
0154     auto attr = collection.attribute<Akonadi::IndexPolicyAttribute>(Akonadi::Collection::AddIfMissing);
0155     attr->setIndexingEnabled(d->ui.enableIndexingChkBox->isChecked());
0156 }
0157 
0158 #include "moc_collectionmaintenancepage.cpp"