File indexing completed on 2024-05-05 17:44:59
0001 /* 0002 SPDX-FileCopyrightText: 2014 Vishesh Handa <me@vhanda.in> 0003 SPDX-FileCopyrightText: 2017 David Edmundson <davidedmundson@kde.org> 0004 0005 SPDX-License-Identifier: LGPL-2.1-or-later 0006 */ 0007 0008 #include "baloosearchrunner.h" 0009 0010 #include <KLocalizedString> 0011 #include <QAction> 0012 #include <QApplication> 0013 #include <QDBusConnection> 0014 #include <QDir> 0015 #include <QIcon> 0016 #include <QMimeData> 0017 #include <QMimeDatabase> 0018 #include <QTimer> 0019 0020 #include <Baloo/IndexerConfig> 0021 #include <Baloo/Query> 0022 0023 #include <KIO/JobUiDelegate> 0024 #include <KIO/JobUiDelegateFactory> 0025 #include <KIO/OpenFileManagerWindowJob> 0026 #include <KIO/OpenUrlJob> 0027 #include <KNotificationJobUiDelegate> 0028 #include <KShell> 0029 0030 #include "krunner1adaptor.h" 0031 0032 static const QString s_openParentDirId = QStringLiteral("openParentDir"); 0033 0034 int main(int argc, char **argv) 0035 { 0036 QCoreApplication::setAttribute(Qt::AA_DisableSessionManager); 0037 QApplication::setQuitOnLastWindowClosed(false); 0038 QApplication app(argc, argv); // KRun needs widgets for error message boxes 0039 SearchRunner r; 0040 return app.exec(); 0041 } 0042 0043 SearchRunner::SearchRunner(QObject *parent) 0044 : QObject(parent) 0045 { 0046 new Krunner1Adaptor(this); 0047 qDBusRegisterMetaType<RemoteMatch>(); 0048 qDBusRegisterMetaType<RemoteMatches>(); 0049 qDBusRegisterMetaType<RemoteAction>(); 0050 qDBusRegisterMetaType<RemoteActions>(); 0051 QDBusConnection::sessionBus().registerObject(QStringLiteral("/runner"), this); 0052 QDBusConnection::sessionBus().registerService(QStringLiteral("org.kde.runners.baloo")); 0053 } 0054 0055 SearchRunner::~SearchRunner() 0056 { 0057 } 0058 0059 RemoteActions SearchRunner::Actions() 0060 { 0061 Baloo::IndexerConfig config; 0062 if (!config.fileIndexingEnabled()) { 0063 sendErrorReply(QDBusError::ErrorType::NotSupported); 0064 } 0065 return RemoteActions({RemoteAction{s_openParentDirId, i18n("Open Containing Folder"), QStringLiteral("document-open-folder")}}); 0066 } 0067 0068 RemoteMatches SearchRunner::Match(const QString &searchTerm) 0069 { 0070 Baloo::IndexerConfig config; 0071 if (!config.fileIndexingEnabled()) { 0072 sendErrorReply(QDBusError::ErrorType::NotSupported); 0073 return {}; 0074 } 0075 0076 // Do not try to show results for queries starting with = 0077 // this should trigger the calculator, but the AdvancedQueryParser::parse method 0078 // in baloo interpreted it as an operator, BUG 345134 0079 if (searchTerm.startsWith(QLatin1Char('='))) { 0080 return RemoteMatches(); 0081 } 0082 0083 // Filter out duplicates 0084 QSet<QUrl> foundUrls; 0085 0086 RemoteMatches matches; 0087 matches << matchInternal(searchTerm, QStringLiteral("Audio"), i18n("Audio"), foundUrls); 0088 matches << matchInternal(searchTerm, QStringLiteral("Image"), i18n("Image"), foundUrls); 0089 matches << matchInternal(searchTerm, QStringLiteral("Video"), i18n("Video"), foundUrls); 0090 matches << matchInternal(searchTerm, QStringLiteral("Spreadsheet"), i18n("Spreadsheet"), foundUrls); 0091 matches << matchInternal(searchTerm, QStringLiteral("Presentation"), i18n("Presentation"), foundUrls); 0092 matches << matchInternal(searchTerm, QStringLiteral("Folder"), i18n("Folder"), foundUrls); 0093 matches << matchInternal(searchTerm, QStringLiteral("Document"), i18n("Document"), foundUrls); 0094 matches << matchInternal(searchTerm, QStringLiteral("Archive"), i18n("Archive"), foundUrls); 0095 matches << matchInternal(searchTerm, QStringLiteral("Text"), i18n("Text"), foundUrls); 0096 0097 return matches; 0098 } 0099 0100 RemoteMatches SearchRunner::matchInternal(const QString &searchTerm, const QString &type, const QString &category, QSet<QUrl> &foundUrls) 0101 { 0102 Baloo::Query query; 0103 query.setSearchString(searchTerm); 0104 query.setType(type); 0105 query.setLimit(10); 0106 0107 Baloo::ResultIterator it = query.exec(); 0108 0109 RemoteMatches matches; 0110 0111 QMimeDatabase mimeDb; 0112 0113 // KRunner is absolutely daft and allows plugins to set the global 0114 // relevance levels. so Baloo should not set the relevance of results too 0115 // high because then Applications will often appear after if the application 0116 // runner has not a higher relevance. So stupid. 0117 // Each runner plugin should not have to know about the others. 0118 // Anyway, that's why we're starting with .75 0119 float relevance = .75; 0120 while (it.next()) { 0121 RemoteMatch match; 0122 QString localUrl = it.filePath(); 0123 const QUrl url = QUrl::fromLocalFile(localUrl); 0124 0125 if (foundUrls.contains(url)) { 0126 continue; 0127 } 0128 0129 foundUrls.insert(url); 0130 0131 match.id = url.toString(); 0132 match.text = url.fileName(); 0133 match.iconName = mimeDb.mimeTypeForFile(localUrl).iconName(); 0134 match.relevance = relevance; 0135 match.type = 0136 url.fileName().compare(searchTerm, Qt::CaseInsensitive) == 0 || QFileInfo(url.fileName()).baseName().compare(searchTerm, Qt::CaseInsensitive) == 0 0137 ? Plasma::QueryMatch::ExactMatch 0138 : url.fileName().contains(searchTerm, Qt::CaseInsensitive) ? Plasma::QueryMatch::PossibleMatch 0139 : Plasma::QueryMatch::CompletionMatch; 0140 QVariantMap properties; 0141 0142 QString folderPath = url.adjusted(QUrl::RemoveFilename | QUrl::StripTrailingSlash).toLocalFile(); 0143 folderPath = KShell::tildeCollapse(folderPath); 0144 0145 properties[QStringLiteral("urls")] = QStringList({QString::fromLocal8Bit(url.toEncoded())}); 0146 properties[QStringLiteral("subtext")] = folderPath; 0147 properties[QStringLiteral("category")] = category; 0148 0149 match.properties = properties; 0150 relevance -= 0.05; 0151 0152 matches << match; 0153 } 0154 0155 return matches; 0156 } 0157 0158 void SearchRunner::Run(const QString &id, const QString &actionId) 0159 { 0160 const QUrl url(id); 0161 if (actionId == s_openParentDirId) { 0162 KIO::highlightInFileManager({url}); 0163 return; 0164 } 0165 0166 auto *job = new KIO::OpenUrlJob(url); 0167 job->setUiDelegate(KIO::createDefaultJobUiDelegate(KJobUiDelegate::AutoHandlingEnabled, QApplication::activeWindow())); 0168 job->setShowOpenOrExecuteDialog(true); 0169 job->start(); 0170 }