From 46b9145f0e23814e6590e1a17369231cb3d7e050 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Vr=C3=A1til?= <daniel.vratil@kdab.com> Date: Wed, 17 Feb 2016 18:15:18 +0100 Subject: [PATCH 42/74] Search: wait for collections to be reindexed before searching When users selectes to reindex collections that are not fully indexed when creating a search, we wait for the Indexer to finish reindexing the collections before we create the search. This is needed for two reasons: the results would not be updated as more items would be indexer by the indexer, and users would still get incomplete results. --- kmail/searchdialog/incompleteindexdialog.cpp | 85 +++++++++++++++++++++- kmail/searchdialog/incompleteindexdialog.h | 14 +++- kmail/searchdialog/searchwindow.cpp | 18 ++--- .../widgets/searchcollectionindexingwarning.cpp | 4 + 4 files changed, 104 insertions(+), 17 deletions(-) diff --git a/kmail/searchdialog/incompleteindexdialog.cpp b/kmail/searchdialog/incompleteindexdialog.cpp index 4ab0424de5..9aaeeea4ba 100644 --- a/kmail/searchdialog/incompleteindexdialog.cpp +++ b/kmail/searchdialog/incompleteindexdialog.cpp @@ -20,13 +20,21 @@ #include "incompleteindexdialog.h" #include "ui_incompleteindexdialog.h" #include "kmkernel.h" +#include "pimcommon/util/indexerutils.h" +#include <KProgressDialog> #include <KDescendantsProxyModel> #include <Akonadi/EntityTreeModel> #include <Akonadi/EntityMimeTypeFilterModel> +#include <QDBusInterface> +#include <QDBusReply> +#include <QDBusMetaType> +#include <QTimer> + Q_DECLARE_METATYPE(Qt::CheckState) +Q_DECLARE_METATYPE(QVector<qint64>) class SearchCollectionProxyModel : public QSortFilterProxyModel { @@ -94,11 +102,15 @@ private: }; -IncompleteIndexDialog::IncompleteIndexDialog(const QVector<qint64> &unindexedCollections) - : mUi(new Ui::IncompleteIndexDialog) +IncompleteIndexDialog::IncompleteIndexDialog(const QVector<qint64> &unindexedCollections, QWidget *parent) + : KDialog(parent) + , mUi(new Ui::IncompleteIndexDialog) + , mProgressDialog(0) + , mIndexer(0) { - mUi->setupUi(mainWidget()); + qDBusRegisterMetaType<QVector<qint64> >(); + mUi->setupUi(mainWidget()); Akonadi::EntityTreeModel *etm = KMKernel::self()->entityTreeModel(); Akonadi::EntityMimeTypeFilterModel *mimeProxy = new @@ -128,6 +140,15 @@ IncompleteIndexDialog::~IncompleteIndexDialog() { } +void IncompleteIndexDialog::slotButtonClicked(int btn) +{ + if (btn == Ok) { + waitForIndexer(); + } else { + KDialog::slotButtonClicked(btn); + } +} + void IncompleteIndexDialog::selectAll() { updateAllSelection(true); @@ -161,3 +182,61 @@ Akonadi::Collection::List IncompleteIndexDialog::collectionsToReindex() const return res; } + +void IncompleteIndexDialog::waitForIndexer() +{ + mIndexer = new QDBusInterface(PimCommon::indexerServiceName(), QLatin1String("/"), + QLatin1String("org.freedesktop.Akonadi.BalooIndexer"), + QDBusConnection::sessionBus(), this); + if (!mIndexer->isValid()) { + accept(); + return; + } + + Q_FOREACH (const Akonadi::Collection &col, collectionsToReindex()) { + mIndexer->asyncCall(QLatin1String("reindexCollection"), col.id()); + mIndexingQueue.push_back(col.id()); + } + + if (mIndexingQueue.isEmpty()) { + accept(); + return; + } + + mProgressDialog = new KProgressDialog(this); + mProgressDialog->progressBar()->setMaximum(mIndexingQueue.size()); + mProgressDialog->progressBar()->setValue(1); + mProgressDialog->setLabelText(i18n("Indexing Collections...")); + mProgressDialog->show(); + connect(mProgressDialog, SIGNAL(rejected()), + this, SLOT(slotStopIndexing())); + + connect(mIndexer, SIGNAL(currentCollectionChanged(qlonglong)), + this, SLOT(slotCurrentlyIndexingCollectionChanged(qlonglong))); +} + +void IncompleteIndexDialog::slotStopIndexing() +{ + mProgressDialog->close(); + reject(); +} + +void IncompleteIndexDialog::slotCurrentlyIndexingCollectionChanged(qlonglong colId) +{ + if (colId == -1) { + // Give indexer time to commit + QTimer::singleShot(1000, this, SLOT(accept())); + return; + } + + const int idx = mIndexingQueue.indexOf(colId); + if (idx > -1) { + mIndexingQueue.remove(idx); + } + + mProgressDialog->progressBar()->setValue(mProgressDialog->progressBar()->maximum() - mIndexingQueue.size()); + + if (mIndexingQueue.isEmpty()) { + QTimer::singleShot(1000, this, SLOT(accept())); + } +} diff --git a/kmail/searchdialog/incompleteindexdialog.h b/kmail/searchdialog/incompleteindexdialog.h index 4b3b848f73..de024192c8 100644 --- a/kmail/searchdialog/incompleteindexdialog.h +++ b/kmail/searchdialog/incompleteindexdialog.h @@ -22,6 +22,10 @@ #include <KDialog> #include <Akonadi/Collection> +#include <QVector> + +class KProgressDialog; +class QDBusInterface; class Ui_IncompleteIndexDialog; class IncompleteIndexDialog : public KDialog @@ -29,19 +33,27 @@ class IncompleteIndexDialog : public KDialog Q_OBJECT public: - explicit IncompleteIndexDialog(const QVector<qint64> &unindexedCollections); + explicit IncompleteIndexDialog(const QVector<qint64> &unindexedCollections, QWidget *parent = 0); ~IncompleteIndexDialog(); Akonadi::Collection::List collectionsToReindex() const; + void slotButtonClicked(int button); + private Q_SLOTS: void selectAll(); void unselectAll(); + void slotCurrentlyIndexingCollectionChanged(qlonglong colId); + void slotStopIndexing(); private: + void waitForIndexer(); void updateAllSelection(bool select); QScopedPointer<Ui_IncompleteIndexDialog> mUi; + KProgressDialog *mProgressDialog; + QDBusInterface *mIndexer; + QVector<qint64> mIndexingQueue; }; diff --git a/kmail/searchdialog/searchwindow.cpp b/kmail/searchdialog/searchwindow.cpp index d84bf6aa71..ae92ceb2f5 100644 --- a/kmail/searchdialog/searchwindow.cpp +++ b/kmail/searchdialog/searchwindow.cpp @@ -40,6 +40,7 @@ #include <Akonadi/CollectionModifyJob> #include <Akonadi/CollectionFetchJob> #include <Akonadi/EntityTreeView> +#include <Akonadi/EntityHiddenAttribute> #include <akonadi/persistentsearchattribute.h> #include <Akonadi/SearchCreateJob> #include <Akonadi/ChangeRecorder> @@ -62,9 +63,6 @@ #include <QKeyEvent> #include <QMenu> #include <QVBoxLayout> -#include <QDBusInterface> -#include <QDBusConnection> -#include <QDBusReply> #include <QScopedPointer> using namespace KPIM; @@ -509,15 +507,7 @@ void SearchWindow::doSearch() QVector<qint64> unindexedCollections = checkIncompleteIndex(searchCollections, recursive); if (!unindexedCollections.isEmpty()) { QScopedPointer<IncompleteIndexDialog> dlg(new IncompleteIndexDialog(unindexedCollections)); - if (dlg->exec() == QDialog::Accepted) { - const Akonadi::Collection::List collectionsToReindex = dlg->collectionsToReindex(); - QDBusInterface indexer(PimCommon::indexerServiceName(), QLatin1String("/"), - QLatin1String("org.freedesktop.Akonadi.BalooIndexer"), - QDBusConnection::sessionBus(), this); - Q_FOREACH (const Akonadi::Collection &col, collectionsToReindex) { - indexer.asyncCall(QLatin1String("reindexCollection"), col.id()); - } - } + dlg->exec(); } if ( !mFolder.isValid() ) { @@ -930,7 +920,9 @@ Akonadi::Collection::List SearchWindow::searchCollectionsRecursive(const Akonadi result.push_back(col); } else { const Akonadi::Collection collection = etm->data(colIdx, Akonadi::EntityTreeModel::CollectionRole).value<Akonadi::Collection>(); - result.push_back(collection); + if (!collection.hasAttribute<Akonadi::EntityHiddenAttribute>()) { + result.push_back(collection); + } } const int childrenCount = etm->rowCount(colIdx); diff --git a/messagelist/core/widgets/searchcollectionindexingwarning.cpp b/messagelist/core/widgets/searchcollectionindexingwarning.cpp index 17528b671b..8eaf581295 100644 --- a/messagelist/core/widgets/searchcollectionindexingwarning.cpp +++ b/messagelist/core/widgets/searchcollectionindexingwarning.cpp @@ -23,6 +23,7 @@ #include <akonadi/collectionfetchjob.h> #include <akonadi/collectionfetchscope.h> #include <akonadi/collectionstatistics.h> +#include <akonadi/entityhiddenattribute.h> #include <pimcommon/util/indexerutils.h> @@ -135,6 +136,9 @@ void SearchCollectionIndexingWarning::indexerStatsFetchFinished(KJob* job) bool allFullyIndexed = true; QMap<qint64, qint64> stats = qobject_cast<PimCommon::CollectionIndexStatusJob*>(job)->resultStats(); Q_FOREACH (const Akonadi::Collection &col, mCollections) { + if (col.hasAttribute<Akonadi::EntityHiddenAttribute>()) { + continue; + } kDebug() << "Collection:" << col.displayName() << "(" << col.id() << "), count:" << col.statistics().count() << ", index:" << stats.value(col.id()); if (col.statistics().count() != stats.value(col.id())) { allFullyIndexed = false; -- 2.14.1