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::queryFinished,
this, [
this] {
27 connect(m_manager, &RunnerManager::requestUpdateQueryString,
this, &RunnerResultsModel::queryStringChangeRequested);
33 return m_matches.value(category).value(idx.
row());
45 for (
const auto &match : matches) {
47 newCategories.
insert(category);
52 auto it = m_categories.begin();
53 while (it != m_categories.end()) {
54 const int categoryNumber = int(std::distance(m_categories.begin(), it));
57 beginRemoveRows(
QModelIndex(), categoryNumber, categoryNumber);
58 m_matches.remove(*it);
59 it = m_categories.erase(it);
68 for (
auto it = m_categories.constBegin(); it != m_categories.constEnd(); ++it) {
69 Q_ASSERT(newCategories.
contains(*it));
71 const int categoryNumber = int(std::distance(m_categories.constBegin(), it));
72 const QModelIndex categoryIdx = index(categoryNumber, 0);
76 auto oldCategoryIt = m_matches.find(*it);
77 Q_ASSERT(oldCategoryIt != m_matches.end());
79 auto &oldMatchesInCategory = *oldCategoryIt;
80 const auto newMatchesInCategory = newMatches.value(*it);
82 Q_ASSERT(!oldMatchesInCategory.isEmpty());
83 Q_ASSERT(!newMatches.isEmpty());
87 bool emitDataChanged =
false;
89 const int oldCount = oldMatchesInCategory.count();
90 const int newCount = newMatchesInCategory.count();
92 const int countCeiling = qMin(oldCount, newCount);
94 for (
int i = 0; i < countCeiling; ++i) {
95 auto &oldMatch = oldMatchesInCategory[i];
96 if (oldMatch != newMatchesInCategory.at(i)) {
97 oldMatch = newMatchesInCategory.at(i);
98 emitDataChanged =
true;
103 if (emitDataChanged) {
104 Q_EMIT dataChanged(index(0, 0, categoryIdx), index(countCeiling - 1, 0, categoryIdx));
108 if (newCount > oldCount) {
109 beginInsertRows(categoryIdx, oldCount, newCount - 1);
110 oldMatchesInCategory = newMatchesInCategory;
112 }
else if (newCount < oldCount) {
113 beginRemoveRows(categoryIdx, newCount, oldCount - 1);
114 oldMatchesInCategory = newMatchesInCategory;
119 newCategories.
remove(*it);
123 if (!newCategories.
isEmpty()) {
124 beginInsertRows(
QModelIndex(), m_categories.count(), m_categories.count() + newCategories.
count() - 1);
126 for (
const QString &newCategory : newCategories) {
127 const auto matchesInNewCategory = newMatches.value(newCategory);
129 m_matches[newCategory] = matchesInNewCategory;
130 m_categories.append(newCategory);
136 Q_ASSERT(m_categories.count() == m_matches.count());
138 m_hasMatches = !m_matches.isEmpty();
140 Q_EMIT matchesChanged();
143QString RunnerResultsModel::queryString()
const
145 return m_queryString;
148void RunnerResultsModel::setQueryString(
const QString &queryString,
const QString &runner)
151 if (m_queryString.trimmed() == queryString.
trimmed() && m_prevRunner == runner) {
155 m_prevRunner = runner;
156 m_queryString = queryString;
157 m_hasMatches =
false;
161 m_manager->launchQuery(queryString, runner);
164 Q_EMIT queryStringChanged(queryString);
167bool RunnerResultsModel::querying()
const
172void RunnerResultsModel::setQuerying(
bool querying)
174 if (m_querying != querying) {
175 m_querying = querying;
176 Q_EMIT queryingChanged();
180void RunnerResultsModel::clear()
183 m_manager->matchSessionComplete();
188 m_categories.clear();
192 m_hasMatches =
false;
195bool RunnerResultsModel::run(
const QModelIndex &idx)
199 return m_manager->run(match);
204bool RunnerResultsModel::runAction(
const QModelIndex &idx,
int actionNumber)
211 if (actionNumber < 0 || actionNumber >=
match.actions().count()) {
215 return m_manager->run(match,
match.actions().at(actionNumber));
218int RunnerResultsModel::columnCount(
const QModelIndex &parent)
const
224int RunnerResultsModel::rowCount(
const QModelIndex &parent)
const
226 if (parent.
column() > 0) {
231 return m_categories.count();
239 return m_matches.value(category).count();
249 if (
int(index.
internalId() - 1) >= m_categories.count()) {
254 if (!
match.isValid()) {
262 if (!
match.iconName().isEmpty()) {
263 return match.iconName();
266 case ResultsModel::CategoryRelevanceRole:
267 return match.categoryRelevance();
268 case ResultsModel::RelevanceRole:
269 return match.relevance();
270 case ResultsModel::IdRole:
272 case ResultsModel::EnabledRole:
273 return match.isEnabled();
274 case ResultsModel::CategoryRole:
275 return match.matchCategory();
276 case ResultsModel::SubtextRole:
277 return match.subtext();
278 case ResultsModel::UrlsRole:
280 case ResultsModel::MultiLineRole:
281 return match.isMultiLine();
282 case ResultsModel::ActionsRole: {
283 const auto actions =
match.actions();
284 QVariantList actionsList;
285 actionsList.reserve(actions.size());
293 case ResultsModel::QueryMatchRole:
301 if (index.
row() >= m_categories.count()) {
307 return m_categories.at(index.
row());
309 case ResultsModel::FavoriteIndexRole: {
310 for (
int i = 0; i < rowCount(index); ++i) {
312 if (
match.isValid()) {
314 int idx = m_favoriteIds.indexOf(
id);
319 return m_favoriteIds.size();
321 case ResultsModel::FavoriteCountRole:
322 return m_favoriteIds.size();
324 case ResultsModel::CategoryRelevanceRole: {
326 for (
int i = 0; i < rowCount(index); ++i) {
327 const int type = this->index(i, 0, index).
data(ResultsModel::CategoryRelevanceRole).
toInt();
328 if (type > highestType) {
334 case ResultsModel::RelevanceRole: {
335 qreal highestRelevance = 0.0;
336 for (
int i = 0; i < rowCount(index); ++i) {
337 const qreal relevance = this->index(i, 0, index).
data(ResultsModel::RelevanceRole).
toReal();
338 if (relevance > highestRelevance) {
339 highestRelevance = relevance;
342 return highestRelevance;
351 if (row < 0 || column != 0) {
357 const auto matches = m_matches.
value(category);
358 if (row < matches.
count()) {
359 return createIndex(row, column,
int(parent.
row() + 1));
365 if (row < m_categories.count()) {
366 return createIndex(row, column,
nullptr);
375 return createIndex(
int(child.
internalId() - 1), 0,
nullptr);
388#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)
qsizetype count() const const
T value(qsizetype i) const const
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