diff --git a/extension/_locales/en/messages.json b/extension/_locales/en/messages.json
--- a/extension/_locales/en/messages.json
+++ b/extension/_locales/en/messages.json
@@ -50,6 +50,15 @@
"message": "Show downloads in notification area"
},
+ "options_plugin_bookmarksrunner_title": {
+ "description": "Title for Bookmarks KRunner plugin",
+ "message": "Find bookmarks in “Run Command” window"
+ },
+ "options_plugin_bookmarksrunner_description": {
+ "description": "Description for Bookmarks KRunner plugin",
+ "message": "Make sure the “Bookmarks” module is enabled in Plasma Search settings."
+ },
+
"options_plugin_tabsrunner_title": {
"description": "Title for Browser Tabs KRunner plugin",
"message": "Find browser tabs in “Run Command” window"
diff --git a/extension/constants.js b/extension/constants.js
--- a/extension/constants.js
+++ b/extension/constants.js
@@ -25,6 +25,9 @@
downloads: {
enabled: true
},
+ bookmarksrunner: {
+ enabled: true
+ },
tabsrunner: {
enabled: true
},
diff --git a/extension/extension.js b/extension/extension.js
--- a/extension/extension.js
+++ b/extension/extension.js
@@ -462,6 +462,27 @@
}
});
+// Bookmarks Runner
+// ------------------------------------------------------------------------
+//
+
+// only forward certain tab properties back to our host
+var whitelistedBookmarkProperties = [
+ "id", "url", "title"
+];
+
+addCallback("bookmarksrunner", "search", function (message) {
+ chrome.bookmarks.search(message.query, function (bookmarks) {
+ var filteredBookmarks = filterArrayObjects(bookmarks, whitelistedBookmarkProperties);
+
+ port.postMessage({
+ subsystem: "bookmarksrunner",
+ event: "gotBookmarks",
+ bookmarks: filteredBookmarks
+ });
+ });
+});
+
// Tabs Runner
// ------------------------------------------------------------------------
//
diff --git a/extension/manifest.json b/extension/manifest.json
--- a/extension/manifest.json
+++ b/extension/manifest.json
@@ -47,6 +47,7 @@
"downloads.shelf",
"tabs",
"history",
+ "bookmarks",
"",
"contextMenus"
diff --git a/extension/options.html b/extension/options.html
--- a/extension/options.html
+++ b/extension/options.html
@@ -39,6 +39,12 @@
+ I18N
+
+
+
I18N
diff --git a/host/CMakeLists.txt b/host/CMakeLists.txt
--- a/host/CMakeLists.txt
+++ b/host/CMakeLists.txt
@@ -10,11 +10,15 @@
kdeconnectplugin.cpp
downloadplugin.cpp
downloadjob.cpp
+ bookmarksrunnerplugin.cpp
tabsrunnerplugin.cpp
slcplugin.cpp
)
qt5_add_dbus_adaptor(HOST_SOURCES ../dbus/org.kde.plasma.browser_integration.TabsRunner.xml tabsrunnerplugin.h TabsRunnerPlugin)
+
+qt5_add_dbus_adaptor(HOST_SOURCES "org.kde.krunner1.xml" bookmarksrunnerplugin.h BookmarksRunnerPlugin)
+
qt5_add_dbus_adaptor(HOST_SOURCES ../dbus/org.kde.plasma.browser_integration.Settings.xml settings.h Settings)
qt5_add_dbus_adaptor(HOST_SOURCES ../dbus/org.mpris.MediaPlayer2.xml mprisplugin.h MPrisPlugin mprisroot MPrisRoot)
@@ -31,8 +35,11 @@
KF5::Notifications
KF5::WindowSystem
KF5::Activities
+ KF5::Runner
)
feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES)
install(TARGETS plasma-browser-integration-host ${KDE_INSTALL_TARGETS_DEFAULT_ARGS})
+
+install(FILES plasma-runner-bookmarks.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR} RENAME plasma-runner-bookmarkspbi.desktop) #FIXME
diff --git a/host/bookmarksrunnerplugin.h b/host/bookmarksrunnerplugin.h
new file mode 100644
--- /dev/null
+++ b/host/bookmarksrunnerplugin.h
@@ -0,0 +1,55 @@
+/*
+ Copyright (C) 2018 by Kai Uwe Broulik
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+*/
+
+#pragma once
+
+#include "abstractbrowserplugin.h"
+
+#include
+#include
+
+#include "dbusutils_p.h"
+
+class BookmarksRunnerPlugin : public AbstractBrowserPlugin, protected QDBusContext
+{
+ Q_OBJECT
+
+public:
+ BookmarksRunnerPlugin(QObject *parent);
+
+ bool onLoad() override;
+ bool onUnload() override;
+ void handleData(const QString &event, const QJsonObject &data) override;
+
+ RemoteActions Actions();
+ RemoteMatches Match(const QString &searchTerm);
+ void Run(const QString &id, const QString &actionId);
+
+private:
+ void performMatch();
+ RemoteMatches matchInternal(const QString &searchTerm, const QString &type,
+ const QString &category);
+
+ QDBusMessage m_lastRequest;
+ QString m_searchTerm;
+
+};
diff --git a/host/bookmarksrunnerplugin.cpp b/host/bookmarksrunnerplugin.cpp
new file mode 100644
--- /dev/null
+++ b/host/bookmarksrunnerplugin.cpp
@@ -0,0 +1,133 @@
+/*
+ Copyright (C) 2018 by Kai Uwe Broulik
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+*/
+
+#include "bookmarksrunnerplugin.h"
+
+#include "connection.h"
+
+#include
+
+#include
+
+#include "dbusutils_p.h"
+#include "krunner1adaptor.h"
+
+BookmarksRunnerPlugin::BookmarksRunnerPlugin(QObject *parent)
+ : AbstractBrowserPlugin(QStringLiteral("bookmarksrunner"), 1, parent)
+{
+ new Krunner1Adaptor(this);
+ qDBusRegisterMetaType();
+ qDBusRegisterMetaType();
+ qDBusRegisterMetaType();
+ qDBusRegisterMetaType();
+}
+
+bool BookmarksRunnerPlugin::onLoad()
+{
+ return QDBusConnection::sessionBus().registerObject("/BookmarksRunner", this);
+}
+
+bool BookmarksRunnerPlugin::onUnload()
+{
+ QDBusConnection::sessionBus().unregisterObject(QStringLiteral("/BookmarksRunner"));
+ return true;
+}
+
+RemoteActions BookmarksRunnerPlugin::Actions()
+{
+ return {};
+}
+
+RemoteMatches BookmarksRunnerPlugin::Match(const QString &searchTerm)
+{
+ setDelayedReply(true);
+
+ if (m_lastRequest.type() != QDBusMessage::InvalidMessage) {
+ QDBusConnection::sessionBus().send(m_lastRequest.createReply(QVariantList()));
+ }
+
+ m_lastRequest = message();
+ m_searchTerm = searchTerm;
+
+ // TODO enforce minimum length?
+ sendData(QStringLiteral("search"), {
+ {QStringLiteral("query"), searchTerm}
+ });
+
+ return RemoteMatches();
+}
+
+void BookmarksRunnerPlugin::handleData(const QString &event, const QJsonObject &json)
+{
+ if (event != QLatin1String("gotBookmarks")) {
+ return;
+ }
+
+ if (m_lastRequest.type() == QDBusMessage::InvalidMessage) {
+ return;
+ }
+
+ RemoteMatches matches;
+
+ const QJsonArray &bookmarks = json.value(QStringLiteral("bookmarks")).toArray();
+
+ qreal relevance = 0.75; // FIXME
+
+ for (auto it = bookmarks.constBegin(), end = bookmarks.constEnd(); it != end; ++it) {
+ const QJsonObject &bookmark = it->toObject();
+
+ const QString urlString = bookmark.value(QStringLiteral("url")).toString();
+ const QString title = bookmark.value(QStringLiteral("title")).toString();
+ // folders don't have a URL
+ if (urlString.isEmpty()) {
+ continue;
+ }
+
+ RemoteMatch match;
+ match.id = urlString;
+ match.text = title;
+ // TODO bookmarks API doesn't expose bookmarks, at least show browser icon instead?
+ match.iconName = QStringLiteral("text-html");
+ match.relevance = relevance;
+ match.type = Plasma::QueryMatch::PossibleMatch; // TODO when's an exact match?
+ match.properties = QVariantMap{
+ {QStringLiteral("urls"), QStringList(urlString)},
+ {QStringLiteral("subtext"), QUrl(urlString).toDisplayString()}
+ };
+
+ relevance -= 0.05;
+
+ // TODO should we limit the number of results? I often get like 70 of them
+ matches << match;
+ }
+
+ QDBusConnection::sessionBus().send(m_lastRequest.createReply(QVariant::fromValue(matches)));
+ m_lastRequest = QDBusMessage();
+}
+
+void BookmarksRunnerPlugin::Run(const QString &id, const QString &actionId)
+{
+ if (actionId.isEmpty()) {
+ // didn't want to pull in KIOWidgets just for KRun
+ QDesktopServices::openUrl(QUrl(id));
+ }
+}
diff --git a/host/dbusutils_p.h b/host/dbusutils_p.h
new file mode 100644
--- /dev/null
+++ b/host/dbusutils_p.h
@@ -0,0 +1,81 @@
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+
+struct RemoteMatch
+{
+ //sssuda{sv}
+ QString id;
+ QString text;
+ QString iconName;
+ Plasma::QueryMatch::Type type = Plasma::QueryMatch::NoMatch;
+ qreal relevance = 0;
+ QVariantMap properties;
+};
+
+typedef QList RemoteMatches;
+
+struct RemoteAction
+{
+ QString id;
+ QString text;
+ QString iconName;
+};
+
+typedef QList RemoteActions;
+
+inline QDBusArgument &operator<< (QDBusArgument &argument, const RemoteMatch &match) {
+ argument.beginStructure();
+ argument << match.id;
+ argument << match.text;
+ argument << match.iconName;
+ argument << match.type;
+ argument << match.relevance;
+ argument << match.properties;
+ argument.endStructure();
+ return argument;
+}
+
+inline const QDBusArgument &operator>>(const QDBusArgument &argument, RemoteMatch &match) {
+ argument.beginStructure();
+ argument >> match.id;
+ argument >> match.text;
+ argument >> match.iconName;
+ uint type;
+ argument >> type;
+ match.type = (Plasma::QueryMatch::Type)type;
+ argument >> match.relevance;
+ argument >> match.properties;
+ argument.endStructure();
+
+ return argument;
+}
+
+inline QDBusArgument &operator<< (QDBusArgument &argument, const RemoteAction &action)
+{
+ argument.beginStructure();
+ argument << action.id;
+ argument << action.text;
+ argument << action.iconName;
+ argument.endStructure();
+ return argument;
+}
+
+inline const QDBusArgument &operator>>(const QDBusArgument &argument, RemoteAction &action) {
+ argument.beginStructure();
+ argument >> action.id;
+ argument >> action.text;
+ argument >> action.iconName;
+ argument.endStructure();
+ return argument;
+}
+
+Q_DECLARE_METATYPE(RemoteMatch);
+Q_DECLARE_METATYPE(RemoteMatches);
+Q_DECLARE_METATYPE(RemoteAction);
+Q_DECLARE_METATYPE(RemoteActions);
+
diff --git a/host/main.cpp b/host/main.cpp
--- a/host/main.cpp
+++ b/host/main.cpp
@@ -33,6 +33,7 @@
#include "incognitoplugin.h"
#include "kdeconnectplugin.h"
#include "downloadplugin.h"
+#include "bookmarksrunnerplugin.h"
#include "tabsrunnerplugin.h"
#include "mprisplugin.h"
#include "slcplugin.h"
@@ -81,6 +82,7 @@
m_plugins << new IncognitoPlugin(&a);
m_plugins << new KDEConnectPlugin(&a);
m_plugins << new DownloadPlugin(&a);
+ m_plugins << new BookmarksRunnerPlugin(&a);
m_plugins << new TabsRunnerPlugin(&a);
m_plugins << new MPrisPlugin(&a);
m_plugins << new SlcPlugin(&a);
diff --git a/host/org.kde.krunner1.xml b/host/org.kde.krunner1.xml
new file mode 100644
--- /dev/null
+++ b/host/org.kde.krunner1.xml
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/host/plasma-runner-bookmarks.desktop b/host/plasma-runner-bookmarks.desktop
new file mode 100644
--- /dev/null
+++ b/host/plasma-runner-bookmarks.desktop
@@ -0,0 +1,17 @@
+[Desktop Entry]
+Name=Bookmarks (p-b-i)
+Comment=Find and open bookmarks
+X-KDE-ServiceTypes=Plasma/Runner
+Type=Service
+Icon=bookmarks
+X-KDE-PluginInfo-Author=Kai Uwe Broulik
+X-KDE-PluginInfo-Email=kde@privat.broulik.de
+X-KDE-PluginInfo-Name=bookmarkspbi
+X-KDE-PluginInfo-Version=1.0
+X-KDE-PluginInfo-License=LGPL
+X-Plasma-AdvertiseSingleRunnerQueryMode=true
+X-KDE-PluginInfo-EnabledByDefault=true
+X-Plasma-API=DBus
+# FIXME there can be multiple
+X-Plasma-DBusRunner-Service=org.kde.plasma.browser_integration
+X-Plasma-DBusRunner-Path=/BookmarksRunner