/* SPDX-FileCopyrightText: 2012 Aurélien Gâteau SPDX-FileCopyrightText: 2014 Eike Hein SPDX-License-Identifier: GPL-2.0-or-later */ #include "runnermodel.h" #include "runnermatchesmodel.h" #include #include #include #include #include #include #include using namespace std::chrono_literals; RunnerModel::RunnerModel(QObject *parent) : QAbstractListModel(parent) , m_favoritesModel(nullptr) , m_appletInterface(nullptr) , m_mergeResults(false) , m_krunnerConfig(KSharedConfig::openConfig(QStringLiteral("krunnerrc"))) { m_queryTimer.setSingleShot(true); m_queryTimer.setInterval(10ms); connect(&m_queryTimer, &QTimer::timeout, this, &RunnerModel::startQuery); const auto readFavorites = [this]() { m_favoritePluginIds = m_krunnerConfig ->group(QStringLiteral("Plugins")) // .group(QStringLiteral("Favorites")) .readEntry("plugins", QStringList(QStringLiteral("krunner_services"))); if (m_mergeResults && !m_models.isEmpty()) { m_models.constFirst()->setFavoriteIds(m_favoritePluginIds); } }; m_configWatcher = KConfigWatcher::create(m_krunnerConfig); connect(m_configWatcher.data(), &KConfigWatcher::configChanged, this, readFavorites); readFavorites(); } RunnerModel::~RunnerModel() { } QHash RunnerModel::roleNames() const { return {{Qt::DisplayRole, "display"}}; } AbstractModel *RunnerModel::favoritesModel() const { return m_favoritesModel; } void RunnerModel::setFavoritesModel(AbstractModel *model) { if (m_favoritesModel != model) { m_favoritesModel = model; clear(); for (auto *model : std::as_const(m_models)) { model->setFavoritesModel(m_favoritesModel); } if (!m_query.isEmpty()) { m_queryTimer.start(); } Q_EMIT favoritesModelChanged(); } } QObject *RunnerModel::appletInterface() const { return m_appletInterface; } void RunnerModel::setAppletInterface(QObject *appletInterface) { if (m_appletInterface != appletInterface) { m_appletInterface = appletInterface; clear(); if (!m_query.isEmpty()) { m_queryTimer.start(); } Q_EMIT appletInterfaceChanged(); } } bool RunnerModel::mergeResults() const { return m_mergeResults; } void RunnerModel::setMergeResults(bool merge) { if (m_mergeResults != merge) { m_mergeResults = merge; Q_EMIT mergeResultsChanged(); // If we haven't lazy-initialzed our models, we do not need to re-create them if (!m_models.isEmpty()) { qDeleteAll(m_models); m_models.clear(); // Just re-create all models, initializeModels(); } } } QVariant RunnerModel::data(const QModelIndex &index, int role) const { if (!index.isValid() || index.row() >= m_models.count()) { return QVariant(); } if (role == Qt::DisplayRole) { return m_models.at(index.row())->name(); } return QVariant(); } int RunnerModel::rowCount(const QModelIndex &parent) const { return parent.isValid() ? 0 : m_models.count(); } int RunnerModel::count() const { return rowCount(); } RunnerMatchesModel *RunnerModel::modelForRow(int row) { if (row < 0 || row >= m_models.count()) { return nullptr; } return m_models.at(row); } QStringList RunnerModel::runners() const { return m_runners; } void RunnerModel::setRunners(const QStringList &runners) { if (runners == m_runners) { return; } m_runners = runners; Q_EMIT runnersChanged(); // Update the existing models only, if we have intialized the models if (!m_models.isEmpty()) { if (m_mergeResults) { Q_ASSERT(m_models.length() == 1); m_models.constFirst()->runnerManager()->setAllowedRunners(runners); } else { // Just re-create all the models, it is an edge-case anyway qDeleteAll(m_models); m_models.clear(); initializeModels(); } } } QString RunnerModel::query() const { return m_query; } void RunnerModel::setQuery(const QString &query) { if (m_query == query) { return; // do not init models if the query doesn't change. particularly important during startup! } if (m_models.isEmpty()) { initializeModels(); } m_query = query; m_queryTimer.start(); Q_EMIT queryChanged(); } void RunnerModel::startQuery() { if (m_query.isEmpty()) { clear(); QTimer::singleShot(0, this, &RunnerModel::queryFinished); } else { m_queryingModels = m_models.size(); for (KRunner::ResultsModel *model : std::as_const(m_models)) { model->setQueryString(m_query); } } } void RunnerModel::clear() { for (KRunner::ResultsModel *model : std::as_const(m_models)) { model->clear(); } } void RunnerModel::initializeModels() { beginResetModel(); if (m_mergeResults) { auto model = new RunnerMatchesModel(QString(), i18n("Search results"), this); model->runnerManager()->setAllowedRunners(m_runners); model->setFavoritesModel(m_favoritesModel); model->setFavoriteIds(m_favoritePluginIds); m_models.append(model); } else { for (const QString &runnerId : std::as_const(m_runners)) { auto *model = new RunnerMatchesModel(runnerId, std::nullopt, this); model->setFavoritesModel(m_favoritesModel); m_models.append(model); } } for (auto model : std::as_const(m_models)) { connect(model->runnerManager(), &KRunner::RunnerManager::queryFinished, this, [this]() { if (--m_queryingModels == 0) { Q_EMIT queryFinished(); } }); } endResetModel(); Q_EMIT countChanged(); }