File 2000-better-krunner.patch of Package kf6-krunner
diff --git a/autotests/runnermanagerhistorytest.cpp b/autotests/runnermanagerhistorytest.cpp
index 05e2c46a8ed6d581d39a9e5361cb8d33613aaa57..67a394e106cea30f6d5156246f2bebf5d3f5fbc0 100644
--- a/autotests/runnermanagerhistorytest.cpp
+++ b/autotests/runnermanagerhistorytest.cpp
@@ -27,7 +27,7 @@ public:
{
__changeCountBeforeSaving = 1;
QStandardPaths::setTestModeEnabled(true);
- stateConfigFile = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QDir::separator() + "krunnerstaterc";
+ stateConfigFile = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QDir::separator() + "krunner/krunnerstaterc";
}
private:
@@ -119,28 +119,31 @@ void RunnerManagerHistoryTest::testRelevanceForOftenLaunched()
launchQuery(QStringLiteral("foo"), manager.get());
- const auto matches = manager->matches();
+ auto matches = manager->matches();
QCOMPARE(matches.size(), 2);
QCOMPARE(matches.at(0).id(), QStringLiteral("foo"));
QCOMPARE(matches.at(1).id(), QStringLiteral("bar"));
- QCOMPARE(matches.at(1).relevance(), 0.2);
+ QCOMPARE(manager->searchContext()->getLaunchCount(matches.at(0)), 5);
+ QCOMPARE(manager->searchContext()->getLaunchCount(matches.at(1)), 0);
- QVERIFY(matches.at(0).relevance() > matches.at(1).relevance());
- QVERIFY(matches.at(0).relevance() < 0.6); // 0.5 is the max we add as a bonus, 0.1 comes from the runner
{
KConfig cfg(stateConfigFile);
cfg.group("PlasmaRunnerManager").writeEntry("LaunchCounts", QStringList{"5 foo", "5 bar"});
cfg.sync();
- KSharedConfig::openConfig(QStringLiteral("krunnerstaterc"), KConfig::NoGlobals, QStandardPaths::GenericDataLocation)->reparseConfiguration();
+ KSharedConfig::openConfig(QStringLiteral("krunner/krunnerstaterc"), KConfig::NoGlobals, QStandardPaths::GenericDataLocation)->reparseConfiguration();
}
manager = std::make_unique<RunnerManager>();
manager->setAllowedRunners({QStringLiteral("fakerunnerplugin")});
manager->loadRunner(KPluginMetaData::findPluginById(QStringLiteral("krunnertest"), QStringLiteral("fakerunnerplugin")));
launchQuery(QStringLiteral("foo"), manager.get());
- const auto newMatches = manager->matches();
- QCOMPARE(newMatches.size(), 2);
- QVERIFY(newMatches.at(0).relevance() < newMatches.at(1).relevance());
+
+ matches = manager->matches();
+ QCOMPARE(matches.size(), 2);
+ QCOMPARE(matches.at(0).id(), QStringLiteral("foo"));
+ QCOMPARE(matches.at(1).id(), QStringLiteral("bar"));
+ QCOMPARE(manager->searchContext()->getLaunchCount(matches.at(0)), 5);
+ QCOMPARE(manager->searchContext()->getLaunchCount(matches.at(1)), 5);
}
QTEST_MAIN(RunnerManagerHistoryTest)
diff --git a/src/model/resultsmodel.cpp b/src/model/resultsmodel.cpp
index 73c074a5883349e075690fae089012144a7bbcdc..78fc41cf9765a657b9526b02c7eff39c5cbe6f63 100644
--- a/src/model/resultsmodel.cpp
+++ b/src/model/resultsmodel.cpp
@@ -57,31 +57,32 @@ protected:
Q_ASSERT((bool)sourceA.internalId() == (bool)sourceB.internalId());
// Only check the favorite index if we compare categories. For individual matches, they will always be the same
if (isCategoryComparison) {
- const int favoriteA = sourceA.data(ResultsModel::FavoriteIndexRole).toInt();
- const int favoriteB = sourceB.data(ResultsModel::FavoriteIndexRole).toInt();
- bool isFavoriteA = favoriteA != -1;
- bool isFavoriteB = favoriteB != -1;
- if (isFavoriteA && !isFavoriteB) {
- return false;
- } else if (!isFavoriteA && isFavoriteB) {
+ const int indexA = sourceA.data(ResultsModel::FavoriteIndexRole).toInt();
+ const int indexB = sourceB.data(ResultsModel::FavoriteIndexRole).toInt();
+ if (indexA == indexB) {
+ return sourceA.data(ResultsModel::CategoryRelevanceRole).toReal() < sourceB.data(ResultsModel::CategoryRelevanceRole).toReal();
+ }
+ if (indexA < 0) {
return true;
}
-
- const int favoritesCount = sourceA.data(ResultsModel::FavoriteCountRole).toInt();
- const double favoriteAMultiplicationFactor = (favoriteA ? 1 + ((favoritesCount - favoriteA) * 0.2) : 1);
- const double typeA = sourceA.data(ResultsModel::CategoryRelevanceRole).toReal() * favoriteAMultiplicationFactor;
- const double favoriteBMultiplicationFactor = (favoriteB ? 1 + ((favoritesCount - favoriteB) * 0.2) : 1);
- const double typeB = sourceB.data(ResultsModel::CategoryRelevanceRole).toReal() * favoriteBMultiplicationFactor;
- return typeA < typeB;
+ if (indexB < 0) {
+ return false;
+ }
+ return indexA > indexB;
}
const qreal relevanceA = sourceA.data(ResultsModel::RelevanceRole).toReal();
const qreal relevanceB = sourceB.data(ResultsModel::RelevanceRole).toReal();
-
if (!qFuzzyCompare(relevanceA, relevanceB)) {
return relevanceA < relevanceB;
}
+ const uint launchCountA = sourceA.data(ResultsModel::LaunchCountRole).toUInt();
+ const uint launchCountB = sourceB.data(ResultsModel::LaunchCountRole).toUInt();
+ if (launchCountA != launchCountB) {
+ return launchCountA < launchCountB;
+ }
+
return QSortFilterProxyModel::lessThan(sourceA, sourceB);
}
diff --git a/src/model/resultsmodel.h b/src/model/resultsmodel.h
index 0687acf1c9bebb95d7943275c7629d98d91f6a9d..f7dffd60f34722da4a9a476d627eec7d8c8e40d6 100644
--- a/src/model/resultsmodel.h
+++ b/src/model/resultsmodel.h
@@ -80,6 +80,7 @@ public:
QueryMatchRole, /// @internal
FavoriteIndexRole, /// @internal
FavoriteCountRole, /// @internal
+ LaunchCountRole, /// @internal
};
Q_ENUM(Roles)
diff --git a/src/model/runnerresultsmodel.cpp b/src/model/runnerresultsmodel.cpp
index 19d8a2c8f05c1ea5255effc1920357eac62709f0..1390174e2e5f91c7b6e20e73453ea4a067cc13b1 100644
--- a/src/model/runnerresultsmodel.cpp
+++ b/src/model/runnerresultsmodel.cpp
@@ -43,6 +43,10 @@ void RunnerResultsModel::onMatchesChanged(const QList<KRunner::QueryMatch> &matc
// of existing categories to avoid pointless model changes.
QHash<QString /*category*/, QList<KRunner::QueryMatch>> newMatches;
for (const auto &match : matches) {
+ if (match.text().trimmed().isEmpty()) {
+ continue;
+ }
+
const QString category = match.matchCategory();
newCategories.insert(category);
newMatches[category].append(match);
@@ -285,6 +289,8 @@ QVariant RunnerResultsModel::data(const QModelIndex &index, int role) const
return QVariant::fromValue(match.urls());
case ResultsModel::MultiLineRole:
return match.isMultiLine();
+ case ResultsModel::LaunchCountRole:
+ return m_manager->searchContext()->getLaunchCount(match);
case ResultsModel::ActionsRole: {
const auto actions = match.actions();
QVariantList actionsList;
@@ -318,7 +324,9 @@ QVariant RunnerResultsModel::data(const QModelIndex &index, int role) const
if (match.isValid()) {
const QString id = match.runner()->id();
int idx = m_favoriteIds.indexOf(id);
- return idx;
+ if (idx >= 0) {
+ return idx;
+ }
}
}
// Any match that is not a favorite will have a greater index than an actual favorite
diff --git a/src/runnercontext.cpp b/src/runnercontext.cpp
index 7c8946877dcb6d2c6147efda65028e1d1f8a494f..dbd568c2cd296a8774a796569bd47d4d8ba6b8b1 100644
--- a/src/runnercontext.cpp
+++ b/src/runnercontext.cpp
@@ -55,22 +55,18 @@ public:
void addMatch(const QueryMatch &match)
{
if (match.runner() && match.runner()->d->hasUniqueResults) {
- if (uniqueIds.contains(match.id())) {
- const QueryMatch &existentMatch = uniqueIds.value(match.id());
- if (existentMatch.runner() && existentMatch.runner()->d->hasWeakResults) {
- // There is an existing match with the same ID and we are allowed to replace it
- matches.removeOne(existentMatch);
- matches.append(match);
+ auto iMatch = std::find_if(matches.cbegin(), matches.cend(), [&match](const QueryMatch &m) {
+ return m.id() == match.id();
+ });
+ if (iMatch != matches.cend()) {
+ if (*iMatch == match || !iMatch->runner() || !iMatch->runner()->d->hasWeakResults) {
+ return;
}
- } else {
- // There is no existing match with the same id
- uniqueIds.insert(match.id(), match);
- matches.append(match);
+ matches.erase(iMatch);
}
- } else {
- // Runner has the unique results property not set
- matches.append(match);
}
+
+ matches.append(match);
}
void matchesChanged()
@@ -84,12 +80,11 @@ public:
QPointer<RunnerManager> m_manager;
bool m_isValid = true;
QList<QueryMatch> matches;
- QHash<QString, int> launchCounts;
+ QHash<QString, uint> launchCounts;
int changedLaunchCounts = 0; // We want to sync them while the app is running, but for each query it is overkill
QString term;
bool singleRunnerQueryMode = false;
bool shouldIgnoreCurrentMatchForHistory = false;
- QMap<QString, QueryMatch> uniqueIds;
QString requestedText;
int requestedCursorPosition = 0;
qint64 queryStartTs = 0;
@@ -155,7 +150,6 @@ void RunnerContext::reset()
d->term.clear();
d->matchesChanged();
- d->uniqueIds.clear();
d->singleRunnerQueryMode = false;
d->shouldIgnoreCurrentMatchForHistory = false;
}
@@ -197,12 +191,7 @@ bool RunnerContext::addMatches(const QList<QueryMatch> &matches)
{
QWriteLocker locker(&d->lock);
- for (QueryMatch match : matches) {
- // Give previously launched matches a slight boost in relevance
- // The boost smoothly saturates to 0.5;
- if (int count = d->launchCounts.value(match.id())) {
- match.setRelevance(match.relevance() + 0.5 * (1 - exp(-count * 0.3)));
- }
+ for (const QueryMatch &match : matches) {
d->addMatch(match);
}
}
@@ -244,6 +233,11 @@ void RunnerContext::ignoreCurrentMatchForHistory() const
d->shouldIgnoreCurrentMatchForHistory = true;
}
+uint RunnerContext::getLaunchCount(const QueryMatch &match) const
+{
+ return d->launchCounts.value(match.id());
+}
+
bool RunnerContext::shouldIgnoreCurrentMatchForHistory() const
{
return d->shouldIgnoreCurrentMatchForHistory;
@@ -261,13 +255,14 @@ bool RunnerContext::shouldIgnoreCurrentMatchForHistory() const
*/
void RunnerContext::restore(const KConfigGroup &config)
{
- const QStringList cfgList = config.readEntry("LaunchCounts", QStringList());
-
- for (const QString &entry : cfgList) {
- if (int idx = entry.indexOf(QLatin1Char(' ')); idx != -1) {
- const int count = entry.mid(0, idx).toInt();
- const QString id = entry.mid(idx + 1);
- d->launchCounts[id] = count;
+ const QStringList launchCountsList = config.readEntry("LaunchCounts", QStringList());
+ for (const QString &entry : launchCountsList) {
+ if (int i = entry.indexOf(u' '); i != -1) {
+ const uint count = entry.first(i).toUInt();
+ const QString id = entry.mid(i).trimmed();
+ if (count > 0 && !id.isEmpty()) {
+ d->launchCounts[id] = count;
+ }
}
}
}
@@ -277,14 +272,16 @@ void RunnerContext::save(KConfigGroup &config)
if (d->changedLaunchCounts < __changeCountBeforeSaving) {
return;
}
+
d->changedLaunchCounts = 0;
- QStringList countList;
- countList.reserve(d->launchCounts.size());
- for (auto it = d->launchCounts.cbegin(), end = d->launchCounts.cend(); it != end; ++it) {
- countList << QString::number(it.value()) + QLatin1Char(' ') + it.key();
+
+ QStringList launchCountsList;
+ launchCountsList.reserve(d->launchCounts.size());
+ for (auto i = d->launchCounts.cbegin(), end = d->launchCounts.cend(); i != end; ++i) {
+ launchCountsList << QStringLiteral("%1 %2").arg(i.value()).arg(i.key());
}
- config.writeEntry("LaunchCounts", countList);
+ config.writeEntry("LaunchCounts", launchCountsList);
config.sync();
}
diff --git a/src/runnercontext.h b/src/runnercontext.h
index 3cf5f5f7d31826b452897661f57b8a0f34b3cba1..2075fc67804a95e3ab04e6b84c33dbb7757b5b33 100644
--- a/src/runnercontext.h
+++ b/src/runnercontext.h
@@ -115,6 +115,8 @@ public:
*/
void ignoreCurrentMatchForHistory() const;
+ uint getLaunchCount(const QueryMatch &match) const;
+
private:
KRUNNER_NO_EXPORT void increaseLaunchCount(const QueryMatch &match);
KRUNNER_NO_EXPORT QString requestedQueryString() const;
diff --git a/src/runnermanager.cpp b/src/runnermanager.cpp
index e7c8c79d1911efb73a938e0d842a9abbbae5d0e4..c462a7b29e9bf77ef9e3572d76a74e8d9586f182 100644
--- a/src/runnermanager.cpp
+++ b/src/runnermanager.cpp
@@ -386,7 +386,7 @@ RunnerManager::RunnerManager(const KConfigGroup &pluginConfigGroup, const KConfi
RunnerManager::RunnerManager(QObject *parent)
: QObject(parent)
{
- auto defaultStatePtr = KSharedConfig::openConfig(QStringLiteral("krunnerstaterc"), KConfig::NoGlobals, QStandardPaths::GenericDataLocation);
+ auto defaultStatePtr = KSharedConfig::openConfig(QStringLiteral("krunner/krunnerstaterc"), KConfig::NoGlobals, QStandardPaths::GenericDataLocation);
auto configPtr = KSharedConfig::openConfig(QStringLiteral("krunnerrc"), KConfig::NoGlobals);
d = std::make_unique<RunnerManagerPrivate>(configPtr->group(QStringLiteral("Plugins")),
defaultStatePtr->group(QStringLiteral("PlasmaRunnerManager")),