as per communication in irc with aseigo, here is a patch (**against 4.2 branch**) for better handling of stragglers in krunner. Please note that the patch in libs is actually quite noisy because there's also the backport of part of aseigo improvements for the oldMatchesJob stuff. the only relevant part is the "isRunning" method.
Index: runnermanager.h =================================================================== --- runnermanager.h (revision 936456) +++ runnermanager.h (working copy) @@ -99,6 +99,14 @@ */ void reloadConfiguration(); + /** + * @return true if the runner is still running + * (i.e. querying is not finished for that runner) + * @arg runner is the runner to check + */ + + bool isRunning(AbstractRunner* runner) const; + public Q_SLOTS: /** * Launch a query, this will create threads and return inmediately. Index: runnermanager.cpp =================================================================== --- runnermanager.cpp (revision 936456) +++ runnermanager.cpp (working copy) @@ -138,23 +138,19 @@ int priority() const; Plasma::AbstractRunner *runner() const; - void setStale(); - bool isStale() const; protected: void run(); private: Plasma::RunnerContext m_context; Plasma::AbstractRunner *m_runner; - bool m_stale; }; FindMatchesJob::FindMatchesJob(Plasma::AbstractRunner *runner, Plasma::RunnerContext *context, QObject *parent) : ThreadWeaver::Job(parent), m_context(*context, 0), - m_runner(runner), - m_stale(false) + m_runner(runner) { if (runner->speed() == Plasma::AbstractRunner::SlowSpeed) { assignQueuePolicy(&RunnerRestrictionPolicy::instance()); @@ -178,16 +174,6 @@ return m_runner; } -void FindMatchesJob::setStale() -{ - m_stale = true; -} - -bool FindMatchesJob::isStale() const -{ - return m_stale; -} - /***************************************************** * RunnerManager::Private class * @@ -207,7 +193,7 @@ void scheduleMatchesChanged() { - matchChangeTimer.start(0); + matchChangeTimer.start(50); } void matchesChanged() @@ -305,8 +291,17 @@ deferredRun = QueryMatch(0); tmpRun.run(context); } - searchJobs.removeAll(runJob); + + searchJobs.remove(runJob); + oldSearchJobs.remove(runJob); delete runJob; + + if (searchJobs.isEmpty() /*&& context.matches().isEmpty()*/) { + // we finished our run, and there are no valid matches, and so no + // signal will have been sent out. so we need to emit the signal + // ourselves here + emit q->matchesChanged(context.matches()); + } } RunnerManager *q; @@ -314,7 +309,8 @@ RunnerContext context; QTimer matchChangeTimer; QHash<QString, AbstractRunner*> runners; - QList<FindMatchesJob*> searchJobs; + QSet<FindMatchesJob*> searchJobs; + QSet<FindMatchesJob*> oldSearchJobs; // QStringList prioritylist; bool loadAll; KConfigGroup config; @@ -380,8 +376,17 @@ run(d->context.match(id)); } -void RunnerManager::run(const QueryMatch &match) +bool RunnerManager::isRunning(AbstractRunner * runner) const { + foreach (FindMatchesJob *job, d->searchJobs) { + if (job->runner() == runner) return true; + } + return false; +} + + +void RunnerManager::run(const QueryMatch &match) +{ if (!match.isEnabled()) { return; } @@ -390,8 +395,8 @@ AbstractRunner *runner = match.runner(); foreach (FindMatchesJob *job, d->searchJobs) { - if (job->runner() == runner && !job->isFinished() && !job->isStale()) { - kDebug() << "!!!!!!!!!!!!!!!!!!! uh oh!"; + if (job->runner() == runner && !job->isFinished()) { + kDebug() << "deferred run"; d->deferredRun = match; return; } @@ -400,11 +405,8 @@ if (d->deferredRun.isValid()) { d->deferredRun = QueryMatch(0); } - + match.run(d->context); - - - } QList<QAction*> RunnerManager::actionsForMatch(const QueryMatch &match) @@ -460,7 +462,7 @@ FindMatchesJob *job = new FindMatchesJob(r, &d->context, this); connect(job, SIGNAL(done(ThreadWeaver::Job*)), this, SLOT(jobDone(ThreadWeaver::Job*))); Weaver::instance()->enqueue(job); - d->searchJobs.append(job); + d->searchJobs.insert(job); } } } @@ -518,16 +520,15 @@ // If ThreadWeaver is idle, it is safe to clear previous jobs if (Weaver::instance()->isIdle()) { qDeleteAll(d->searchJobs); - d->searchJobs.clear(); + qDeleteAll(d->oldSearchJobs); + d->oldSearchJobs.clear(); } else { Weaver::instance()->dequeue(); - // Since we cannot safely delete the jobs, mark them as stale - // TODO: delete them eventually? - foreach (FindMatchesJob *job, d->searchJobs) { - job->setStale(); - } + d->oldSearchJobs += d->searchJobs; } + d->searchJobs.clear(); + if (d->deferredRun.isEnabled()) { //kDebug() << "job actually done, running now **************"; QueryMatch tmpRun = d->deferredRun;
Index: interface.cpp =================================================================== --- interface.cpp (revision 936097) +++ interface.cpp (working copy) @@ -53,7 +53,7 @@ #include "interfaces/default/resultscene.h" #include "interfaces/default/resultitem.h" -static const int MIN_WIDTH = 400; +static const int MIN_WIDTH = 420; Interface::Interface(Plasma::RunnerManager *runnerManager, QWidget *parent) : KRunnerDialog(runnerManager, parent), @@ -188,9 +188,13 @@ connect(m_previousPage, SIGNAL(linkActivated(const QString&)), m_resultsScene, SLOT(previousPage())); connect(m_nextPage, SIGNAL(linkActivated(const QString&)), m_resultsScene, SLOT(nextPage())); - m_layout->addWidget(m_resultsView); + m_layout->addWidget(m_resultsView); - connect(m_searchTerm, SIGNAL(editTextChanged(QString)), this, SLOT(queryTextEdited(QString))); + // connect(lineEdit, SIGNAL(completion(QString)), this, SLOT(completionStarted())); + //connect(lineEdit, SIGNAL(completionDone(QString)), this, SLOT(completionFinished())); + + connect(lineEdit, SIGNAL(userTextChanged(QString)), this, SLOT(queryTextEdited(QString))); + connect(m_searchTerm, SIGNAL(returnPressed()), this, SLOT(runDefaultResultItem())); themeUpdated(); @@ -429,10 +433,24 @@ } } +void Interface::completionStarted() +{ + kDebug()<<"completion started"; +} + +void Interface::completionFinished() +{ + kDebug()<<"completion done"; +} + void Interface::queryTextEdited(const QString &query) { + // Disregard the parameter, which might contain an autocompleted suggestion, + // we want to launch a query only on the text the user actually entered + // or in the event the user accepts the autocompletion + m_delayedRun = false; - + kDebug() <<"would launch:" << query; //REMOVEME if (query.isEmpty()) { resetInterface(); m_queryRunning = false; Index: resultitem.h =================================================================== --- resultitem.h (revision 936097) +++ resultitem.h (working copy) @@ -26,6 +26,7 @@ #include <QtGui/QIcon> #include <Plasma/QueryMatch> +#include <Plasma/AbstractRunner> class QGraphicsLinearLayout; @@ -74,6 +75,7 @@ Plasma::QueryMatch::Type group() const; qreal priority() const; bool isFavorite() const; + Plasma::AbstractRunner * runner() const; void setIndex(int index); int index() const; void setRowStride(int stride); Index: interface.h =================================================================== --- interface.h (revision 936097) +++ interface.h (working copy) @@ -65,7 +65,9 @@ void setWidgetPalettes(); void run(ResultItem *item); void runDefaultResultItem(); + void completionStarted(); void queryTextEdited(const QString &query); + void completionFinished(); void updateDescriptionLabel(ResultItem *item); void matchCountChanged(int count); void hideResultsArea(); Index: resultscene.cpp =================================================================== --- resultscene.cpp (revision 936097) +++ resultscene.cpp (working copy) @@ -126,7 +126,9 @@ { // kDebug() << "============================" << endl << "matches retrieved: " << m.count(); if (m.isEmpty()) { - //kDebug() << "clearing"; + kDebug() << "clearing"; + //It should be fine to clear all items if we got here without matches, since this means we have + //been called by the last runner emit itemHoverEnter(0); m_clearTimer.start(200); return; @@ -138,7 +140,13 @@ QList<Plasma::QueryMatch> matches = m; QMutableListIterator<Plasma::QueryMatch> newMatchIt(matches); - // first pass: we try and match up items with existing ids (match persisitence) + // first pass: we try and match up items with existing ids (match persisitence) + kDebug()<<"Matches in context:"; + while (newMatchIt.hasNext()) + kDebug() << newMatchIt.next().id(); + + newMatchIt.toFront(); + while (!m_itemsById.isEmpty() && newMatchIt.hasNext()) { ResultItem *item = addQueryMatch(newMatchIt.next(), false); @@ -148,22 +156,36 @@ } } + // first and a half pass: we allow old items to stay if the corresponding + // runner has not finished yet + + QMapIterator<QString, ResultItem *> it(m_itemsById); + while (it.hasNext()) { + // reuse if the runner is still running + ResultItem * tmpItem=it.next().value(); + kDebug() << "Reuse?" << tmpItem->id() << tmpItem->runner()->id() << m_runnerManager->isRunning(tmpItem->runner()); + if (m_runnerManager->isRunning(tmpItem->runner())) { + m_itemsById.remove(it.key()); + m_items.append(tmpItem); + } + } + // second pass: now we just use any item that exists (item re-use) newMatchIt.toFront(); while (newMatchIt.hasNext()) { m_items.append(addQueryMatch(newMatchIt.next(), true)); } + + it = QMapIterator<QString, ResultItem *>(m_itemsById); - // delete the stragglers - QMapIterator<QString, ResultItem *> it(m_itemsById); while (it.hasNext()) { - it.next().value()->remove(); + it.next().value()->remove(); } // organize the remainders int i = 0; m_itemsById.clear(); - + // this will leave them in *reverse* order qSort(m_items.begin(), m_items.end(), ResultItem::compare); @@ -177,11 +199,12 @@ QListIterator<ResultItem*> matchIt(m_items); QGraphicsWidget *tab = 0; while (matchIt.hasNext()) { + ResultItem *item = matchIt.next(); - //kDebug() << item->name() << item->id() << item->priority() << i; + kDebug() << item->name() << item->id() << item->priority() << item->type() << i; QGraphicsWidget::setTabOrder(tab, item); - m_itemsById.insert(item->id(), item); - item->setIndex(i); + m_itemsById.insert(item->id(), item); + item->setIndex(i); // it is vital that focus is set *after* the index if (i == 0) { Index: resultitem.cpp =================================================================== --- resultitem.cpp (revision 936097) +++ resultitem.cpp (working copy) @@ -310,6 +310,11 @@ return d->isFavorite; } +Plasma::AbstractRunner * ResultItem::runner() const +{ + return d->match.runner(); +} + void ResultItem::setIndex(int index) { if (d->index == index) {
_______________________________________________ Plasma-devel mailing list Plasma-devel@kde.org https://mail.kde.org/mailman/listinfo/plasma-devel