1 /*
2     SPDX-FileCopyrightText: 2007 Teemu Rytilahti <tpr@iki.fi>
3 
4     SPDX-License-Identifier: LGPL-2.0-only
5 */
6 
7 #include "locationrunner.h"
8 
9 #include <QDir>
10 #include <QIcon>
11 #include <QMimeData>
12 #include <QUrl>
13 
14 #include <KApplicationTrader>
15 #include <KIO/DesktopExecParser>
16 #include <KIO/Global>
17 #include <KIO/OpenUrlJob>
18 #include <KLocalizedString>
19 #include <KNotificationJobUiDelegate>
20 #include <KProtocolInfo>
21 #include <KShell>
22 #include <KUriFilter>
23 #include <QDebug>
24 
25 K_PLUGIN_CLASS_WITH_JSON(LocationsRunner, "plasma-runner-locations.json")
26 
LocationsRunner(QObject * parent,const KPluginMetaData & metaData,const QVariantList & args)27 LocationsRunner::LocationsRunner(QObject *parent, const KPluginMetaData &metaData, const QVariantList &args)
28     : Plasma::AbstractRunner(parent, metaData, args)
29 {
30     // set the name shown after the result in krunner window
31     setObjectName(QStringLiteral("Locations"));
32     addSyntax(
33         Plasma::RunnerSyntax(QStringLiteral(":q:"), i18n("Finds local directories and files, network locations and Internet sites with paths matching :q:.")));
34 }
35 
~LocationsRunner()36 LocationsRunner::~LocationsRunner()
37 {
38 }
39 
match(Plasma::RunnerContext & context)40 void LocationsRunner::match(Plasma::RunnerContext &context)
41 {
42     QString term = context.query();
43     // If we have a query with an executable and optionally arguments, BUG: 433053
44     const QStringList split = KShell::splitArgs(term);
45     if (!split.isEmpty()) {
46         QFileInfo tmpInfo(KShell::tildeExpand(split.constFirst()));
47         if (tmpInfo.isFile() && tmpInfo.isExecutable()) {
48             return;
49         }
50     }
51     // We want to expand ENV variables like $HOME to get the actual path, BUG: 358221
52     KUriFilter::self()->filterUri(term, {QStringLiteral("kshorturifilter")});
53     const QUrl url(term);
54     // The uri filter takes care of the shell expansion
55     const QFileInfo fileInfo = QFileInfo(url.toLocalFile());
56 
57     if (fileInfo.exists()) {
58         Plasma::QueryMatch match(this);
59         match.setType(Plasma::QueryMatch::ExactMatch);
60         match.setText(i18n("Open %1", context.query()));
61         match.setIconName(fileInfo.isFile() ? KIO::iconNameForUrl(url) : QStringLiteral("system-file-manager"));
62 
63         match.setRelevance(1);
64         match.setData(url);
65         match.setUrls({url});
66         match.setType(Plasma::QueryMatch::ExactMatch);
67         context.addMatch(match);
68     } else if (!url.isLocalFile() && !url.isEmpty() && !url.scheme().isEmpty()) {
69         const QString protocol = url.scheme();
70         Plasma::QueryMatch match(this);
71         match.setData(url);
72         match.setUrls({url});
73 
74         if (!KProtocolInfo::isKnownProtocol(protocol) || KProtocolInfo::isHelperProtocol(protocol)) {
75             const KService::Ptr service = KApplicationTrader::preferredService(QLatin1String("x-scheme-handler/") + protocol);
76             if (service) {
77                 match.setIconName(service->icon());
78                 match.setText(i18n("Launch with %1", service->name()));
79             } else if (KProtocolInfo::isKnownProtocol(protocol)) {
80                 Q_ASSERT(KProtocolInfo::isHelperProtocol(protocol));
81                 match.setIconName(KProtocolInfo::icon(protocol));
82                 match.setText(i18n("Launch with %1", KIO::DesktopExecParser::executableName(KProtocolInfo::exec(protocol))));
83             } else {
84                 return;
85             }
86         } else {
87             match.setIconName(KProtocolInfo::icon(protocol));
88             match.setText(i18n("Go to %1", url.toDisplayString(QUrl::PreferLocalFile)));
89             // in case of https://phabricator.kde.org we add a slash at the end to make it comparable to results of other runners
90             if (url.scheme() == QLatin1String("https") && url.toString().endsWith(url.host())) {
91                 match.setId(url.toString() + QLatin1Char('/'));
92             }
93         }
94 
95         if (url.scheme() == QLatin1String("mailto")) {
96             match.setText(i18n("Send email to %1", url.path()));
97         }
98         context.addMatch(match);
99     }
100 }
101 
run(const Plasma::RunnerContext & context,const Plasma::QueryMatch & match)102 void LocationsRunner::run(const Plasma::RunnerContext &context, const Plasma::QueryMatch &match)
103 {
104     Q_UNUSED(context)
105 
106     auto *job = new KIO::OpenUrlJob(match.data().toUrl());
107     job->setUiDelegate(new KNotificationJobUiDelegate(KJobUiDelegate::AutoErrorHandlingEnabled));
108     job->setRunExecutables(false);
109     job->start();
110 }
111 
112 #include "locationrunner.moc"
113