File indexing completed on 2024-05-05 09:46:22

0001 /*
0002  *   SPDX-FileCopyrightText: 2008 Sebastian Kügler <sebas@kde.org>
0003  *   SPDX-FileCopyrightText: 2017 Kai Uwe Broulik <kde@privat.broulik.de>
0004  *   SPDX-FileCopyrightText: 2020 Alexander Lohnau <alexander.lohnau@gmx.de>
0005  *
0006  *   SPDX-License-Identifier: LGPL-2.0-or-later
0007  */
0008 
0009 #include "katesessions.h"
0010 
0011 #include <QCollator>
0012 #include <QDir>
0013 #include <QFileInfo>
0014 #include <QStandardPaths>
0015 
0016 #include <KDirWatch>
0017 #include <KFuzzyMatcher>
0018 #include <KLocalizedString>
0019 #include <KNotificationJobUiDelegate>
0020 
0021 #include <KIO/CommandLauncherJob>
0022 
0023 K_PLUGIN_CLASS_WITH_JSON(KateSessions, "plasma-runner-katesessions.json")
0024 
0025 KateSessions::KateSessions(QObject *parent, const KPluginMetaData &metaData)
0026     : AbstractRunner(parent, metaData)
0027 {
0028     addSyntax(QStringLiteral("kate :q:"), i18n("Finds Kate sessions matching :q:."));
0029     addSyntax(QStringLiteral("kate"), i18n("Lists all the Kate editor sessions in your account."));
0030 
0031     // Initialize watchers and sessions
0032     setTriggerWords({m_triggerWord});
0033 }
0034 
0035 void KateSessions::match(RunnerContext &context)
0036 {
0037     QString term = context.query();
0038     bool listAll = false;
0039     if (term.trimmed().compare(m_triggerWord, Qt::CaseInsensitive) == 0) {
0040         listAll = true;
0041         term.clear();
0042     } else if (term.startsWith(m_triggerWord + ' ')) {
0043         term.remove(m_triggerWord, Qt::CaseInsensitive);
0044         term = std::move(term).trimmed();
0045     } else if (!context.singleRunnerQueryMode()) {
0046         // Prevent results for queries like "katee"
0047         return;
0048     }
0049 
0050     QList<QueryMatch> matches;
0051     int maxScore = 0;
0052 
0053     for (int i = 0, count = m_model->rowCount(); i < count; ++i) {
0054         // Does the query match exactly?
0055         // no query = perfect match => list everything
0056         QString session = m_model->index(i).data(ProfilesModel::NameRole).toString();
0057         if (listAll || session.compare(term, Qt::CaseInsensitive) == 0) {
0058             QueryMatch match(this);
0059             match.setCategoryRelevance(QueryMatch::CategoryRelevance::Highest);
0060             match.setRelevance(session.compare(term, Qt::CaseInsensitive) == 0 ? 1 : 0.8);
0061             match.setIconName(m_triggerWord);
0062             match.setData(session);
0063             match.setText(session);
0064             match.setSubtext(i18n("Open Kate Session"));
0065             context.addMatch(match);
0066         } else {
0067             // Do fuzzy matching
0068             const auto res = KFuzzyMatcher::match(term, session);
0069             if (res.matched) {
0070                 QueryMatch match(this);
0071                 match.setRelevance(res.score); // store the score here for now
0072                 match.setIconName(m_triggerWord);
0073                 match.setData(session);
0074                 match.setText(session);
0075                 match.setSubtext(i18n("Open Kate Session"));
0076                 matches.push_back(match);
0077                 maxScore = std::max(res.score, maxScore);
0078             }
0079         }
0080     }
0081 
0082     auto calculate_relevance = [maxScore](double score) {
0083         return score / maxScore;
0084     };
0085     for (auto &match : matches) {
0086         match.setRelevance(calculate_relevance(match.relevance()));
0087     }
0088     context.addMatches(matches);
0089 }
0090 
0091 void KateSessions::run(const RunnerContext & /*context*/, const QueryMatch &match)
0092 {
0093     m_model->openProfile(match.data().toString());
0094 }
0095 
0096 void KateSessions::init()
0097 {
0098     // Only create this in the correct thread. Inside we use KDirWatch which is thread sensitive.
0099     m_model = new ProfilesModel(this);
0100     m_model->setAppName(m_triggerWord);
0101 }
0102 
0103 #include "katesessions.moc"