8#include "runnerresultsmodel_p.h"
12#include <KRunner/RunnerManager>
14#include "resultsmodel.h"
21 , m_manager(configGroup.
isValid() && stateConfigGroup.
isValid() ? new RunnerManager(configGroup, stateConfigGroup, this) : new RunnerManager(this))
23 connect(m_manager, &RunnerManager::matchesChanged,
this, &RunnerResultsModel::onMatchesChanged);
24 connect(m_manager, &RunnerManager::requestUpdateQueryString,
this, &RunnerResultsModel::queryStringChangeRequested);
30 return m_matches.value(category).value(idx.
row());
42 for (
const auto &match : matches) {
44 newCategories.
insert(category);
49 auto it = m_categories.
begin();
50 while (it != m_categories.end()) {
51 const int categoryNumber = int(std::distance(m_categories.begin(), it));
54 beginRemoveRows(
QModelIndex(), categoryNumber, categoryNumber);
55 m_matches.remove(*it);
56 it = m_categories.erase(it);
65 for (
auto it = m_categories.constBegin(); it != m_categories.constEnd(); ++it) {
66 Q_ASSERT(newCategories.
contains(*it));
68 const int categoryNumber = int(std::distance(m_categories.constBegin(), it));
69 const QModelIndex categoryIdx = index(categoryNumber, 0);
73 auto oldCategoryIt = m_matches.find(*it);
74 Q_ASSERT(oldCategoryIt != m_matches.end());
76 auto &oldMatchesInCategory = *oldCategoryIt;
77 const auto newMatchesInCategory = newMatches.value(*it);
79 Q_ASSERT(!oldMatchesInCategory.isEmpty());
80 Q_ASSERT(!newMatches.isEmpty());
84 bool emitDataChanged =
false;
86 const int oldCount = oldMatchesInCategory.count();
87 const int newCount = newMatchesInCategory.count();
89 const int countCeiling = qMin(oldCount, newCount);
91 for (
int i = 0; i < countCeiling; ++i) {
92 auto &oldMatch = oldMatchesInCategory[i];
93 if (oldMatch != newMatchesInCategory.at(i)) {
94 oldMatch = newMatchesInCategory.at(i);
95 emitDataChanged =
true;
100 if (emitDataChanged) {
101 Q_EMIT dataChanged(index(0, 0, categoryIdx), index(countCeiling - 1, 0, categoryIdx));
105 if (newCount > oldCount) {
106 beginInsertRows(categoryIdx, oldCount, newCount - 1);
107 oldMatchesInCategory = newMatchesInCategory;
109 }
else if (newCount < oldCount) {
110 beginRemoveRows(categoryIdx, newCount, oldCount - 1);
111 oldMatchesInCategory = newMatchesInCategory;
116 newCategories.
remove(*it);
120 if (!newCategories.
isEmpty()) {
121 beginInsertRows(
QModelIndex(), m_categories.count(), m_categories.count() + newCategories.
count() - 1);
123 for (
const QString &newCategory : newCategories) {
124 const auto matchesInNewCategory = newMatches.value(newCategory);
126 m_matches[newCategory] = matchesInNewCategory;
127 m_categories.append(newCategory);
133 Q_ASSERT(m_categories.count() == m_matches.count());
135 m_hasMatches = !m_matches.isEmpty();
137 Q_EMIT matchesChanged();
140QString RunnerResultsModel::queryString()
const
142 return m_queryString;
145void RunnerResultsModel::setQueryString(
const QString &queryString,
const QString &runner)
148 if (m_queryString.trimmed() == queryString.
trimmed() && m_prevRunner == runner) {
152 m_prevRunner = runner;
153 m_queryString = queryString;
154 m_hasMatches =
false;
158 m_manager->launchQuery(queryString, runner);
160 Q_EMIT queryStringChanged(queryString);
163void RunnerResultsModel::clear()
166 m_manager->matchSessionComplete();
170 if (!m_queryString.isEmpty()) {
171 m_queryString.clear();
172 Q_EMIT queryStringChanged(m_queryString);
176 m_categories.clear();
180 m_hasMatches =
false;
183bool RunnerResultsModel::run(
const QModelIndex &idx)
187 return m_manager->run(match);
192bool RunnerResultsModel::runAction(
const QModelIndex &idx,
int actionNumber)
199 if (actionNumber < 0 || actionNumber >=
match.actions().count()) {
203 return m_manager->run(match,
match.actions().at(actionNumber));
206int RunnerResultsModel::columnCount(
const QModelIndex &parent)
const
212int RunnerResultsModel::rowCount(
const QModelIndex &parent)
const
214 if (parent.
column() > 0) {
219 return m_categories.count();
227 return m_matches.value(category).count();
237 if (
int(index.
internalId() - 1) >= m_categories.count()) {
242 if (!
match.isValid()) {
250 if (!
match.iconName().isEmpty()) {
251 return match.iconName();
254 case ResultsModel::CategoryRelevanceRole:
255 return match.categoryRelevance();
256 case ResultsModel::RelevanceRole:
257 return match.relevance();
258 case ResultsModel::IdRole:
260 case ResultsModel::EnabledRole:
261 return match.isEnabled();
262 case ResultsModel::CategoryRole:
263 return match.matchCategory();
264 case ResultsModel::SubtextRole:
265 return match.subtext();
266 case ResultsModel::UrlsRole:
268 case ResultsModel::MultiLineRole:
269 return match.isMultiLine();
270 case ResultsModel::ActionsRole: {
271 const auto actions =
match.actions();
272 QVariantList actionsList;
273 actionsList.reserve(actions.size());
281 case ResultsModel::QueryMatchRole:
289 if (index.
row() >= m_categories.count()) {
295 return m_categories.at(index.
row());
297 case ResultsModel::FavoriteIndexRole: {
298 for (
int i = 0; i < rowCount(index); ++i) {
300 if (
match.isValid()) {
302 int idx = m_favoriteIds.indexOf(
id);
307 return m_favoriteIds.size();
309 case ResultsModel::FavoriteCountRole:
310 return m_favoriteIds.size();
312 case ResultsModel::CategoryRelevanceRole: {
314 for (
int i = 0; i < rowCount(index); ++i) {
315 const int type = this->index(i, 0, index).
data(ResultsModel::CategoryRelevanceRole).
toInt();
316 if (type > highestType) {
322 case ResultsModel::RelevanceRole: {
323 qreal highestRelevance = 0.0;
324 for (
int i = 0; i < rowCount(index); ++i) {
325 const qreal relevance = this->index(i, 0, index).
data(ResultsModel::RelevanceRole).
toReal();
326 if (relevance > highestRelevance) {
327 highestRelevance = relevance;
330 return highestRelevance;
339 if (row < 0 || column != 0) {
345 const auto matches = m_matches.value(category);
346 if (row < matches.count()) {
347 return createIndex(row, column,
int(parent.
row() + 1));
353 if (row < m_categories.count()) {
354 return createIndex(row, column,
nullptr);
363 return createIndex(
int(child.
internalId() - 1), 0,
nullptr);
376#include "moc_runnerresultsmodel_p.cpp"
This class represents an action that will be shown next to a match.
A match returned by an AbstractRunner in response to a given RunnerContext.
The RunnerManager class decides what installed runners are runnable, and their ratings.
Type type(const QSqlDatabase &db)
KCOREADDONS_EXPORT Result match(QStringView pattern, QStringView str)
bool isValid(QStringView ifopt)
Category category(StandardShortcut id)
QVariant data(int role) const const
quintptr internalId() const const
bool isValid() const const
bool contains(const QSet< T > &other) const const
qsizetype count() const const
iterator insert(const T &value)
bool isEmpty() const const
bool remove(const T &value)
bool isEmpty() const const
QString trimmed() const const
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
QVariant fromValue(T &&value)
int toInt(bool *ok) const const
qreal toReal(bool *ok) const const