diff --git a/containmentactions/contextmenu/menu.cpp b/containmentactions/contextmenu/menu.cpp --- a/containmentactions/contextmenu/menu.cpp +++ b/containmentactions/contextmenu/menu.cpp @@ -96,7 +96,7 @@ if (!m_runCommandAction) { m_runCommandAction = new QAction(i18nc("plasma_containmentactions_contextmenu", "Show KRunner"), this); m_runCommandAction->setIcon(QIcon::fromTheme(QStringLiteral("plasma-search"))); - m_runCommandAction->setShortcut(KGlobalAccel::self()->globalShortcut(QStringLiteral("krunner"), QStringLiteral("run command")).value(0)); + m_runCommandAction->setShortcut(KGlobalAccel::self()->globalShortcut(QStringLiteral("krunner.desktop"), QStringLiteral("_launch")).value(0)); connect(m_runCommandAction, &QAction::triggered, this, &ContextMenu::runCommand); m_lockScreenAction = new QAction(i18nc("plasma_containmentactions_contextmenu", "Lock Screen"), this); diff --git a/krunner/CMakeLists.txt b/krunner/CMakeLists.txt --- a/krunner/CMakeLists.txt +++ b/krunner/CMakeLists.txt @@ -18,7 +18,6 @@ KF5::Declarative KF5::I18n KF5::PlasmaQuick - KF5::GlobalAccel KF5::DBusAddons KF5::Crash KF5::WaylandClient @@ -29,7 +28,7 @@ install(TARGETS krunner ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) install(FILES ${krunner_dbusAppXML} DESTINATION ${KDE_INSTALL_DBUSINTERFACEDIR} ) -install(FILES krunner.desktop DESTINATION ${KDE_INSTALL_AUTOSTARTDIR}) +install(FILES krunner.desktop DESTINATION ${DATA_INSTALL_DIR}/kglobalaccel) set(CMAKECONFIG_INSTALL_DIR "${KDE_INSTALL_CMAKEPACKAGEDIR}/KRunnerAppDBusInterface") configure_package_config_file(KRunnerAppDBusInterfaceConfig.cmake.in diff --git a/krunner/krunner.desktop b/krunner/krunner.desktop --- a/krunner/krunner.desktop +++ b/krunner/krunner.desktop @@ -49,4 +49,10 @@ X-DBUS-StartupType=Unique X-DBUS-ServiceName=org.kde.krunner X-KDE-StartupNotify=false -X-KDE-autostart-phase=2 +X-KDE-Shortcuts=Alt+Space,Alt+F2,Search +Actions=RunClipboard + +[Desktop Action RunClipboard] +Exec=krunner -c +Name=Run command on clipboard contents +X-KDE-Shortcuts=Alt+Shift+F2 diff --git a/krunner/main.cpp b/krunner/main.cpp --- a/krunner/main.cpp +++ b/krunner/main.cpp @@ -42,6 +42,7 @@ int main(int argc, char **argv) { qunsetenv("QT_DEVICE_PIXEL_RATIO"); + QCommandLineParser parser; QCoreApplication::setAttribute(Qt::AA_DisableHighDpiScaling); const bool qpaVariable = qEnvironmentVariableIsSet("QT_QPA_PLATFORM"); @@ -68,21 +69,28 @@ KAboutData::setApplicationData(aboutData); app.setQuitOnLastWindowClosed(false); - { - QCommandLineParser parser; - QCommandLineOption replaceOption({QStringLiteral("replace")}, i18n("Replace an existing instance")); - parser.addOption(replaceOption); - aboutData.setupCommandLine(&parser); - - parser.process(app); - aboutData.processCommandLine(&parser); - if (parser.isSet(replaceOption)) { - auto message = QDBusMessage::createMethodCall(QStringLiteral("org.kde.krunner"), - QStringLiteral("/MainApplication"), - QStringLiteral("org.qtproject.Qt.QCoreApplication"), - QStringLiteral("quit")); - QDBusConnection::sessionBus().call(message); //deliberately block until it's done, so we register the name after the app quits - } + QCommandLineOption clipboardOption({QStringLiteral("c"), QStringLiteral("clipboard")}, + i18n("Use the clipboard contents as query for KRunner")); + QCommandLineOption daemonOption({QStringLiteral("d"), QStringLiteral("daemon")}, + i18n("Start KRunner in the background, don't show it.")); + QCommandLineOption replaceOption({QStringLiteral("replace")}, i18n("Replace an existing instance")); + + parser.addOption(clipboardOption); + parser.addOption(daemonOption); + parser.addOption(replaceOption); + parser.addPositionalArgument(QStringLiteral("query"), i18n("The query to run, only used if -c is not provided")); + + aboutData.setupCommandLine(&parser); + + parser.process(app); + aboutData.processCommandLine(&parser); + + if (parser.isSet(replaceOption)) { + auto message = QDBusMessage::createMethodCall(QStringLiteral("org.kde.krunner"), + QStringLiteral("/MainApplication"), + QStringLiteral("org.qtproject.Qt.QCoreApplication"), + QStringLiteral("quit")); + QDBusConnection::sessionBus().call(message); //deliberately block until it's done, so we register the name after the app quits } if (!KAuthorized::authorize(QStringLiteral("run_command"))) { @@ -100,9 +108,28 @@ QObject::connect(&app, &QGuiApplication::saveStateRequest, disableSessionManagement); View view; - view.setVisible(false); - QObject::connect(&service, &KDBusService::activateRequested, &view, &View::display); + auto updateVisibility = [&]() { + const QString query = parser.positionalArguments().value(0); + + if (parser.isSet(daemonOption)) { + view.setVisible(false); + } else if (parser.isSet(clipboardOption)) { + view.displayWithClipboardContents(); + } else if (!query.isEmpty()) { + view.query(query); + } else { + view.display(); + } + }; + + updateVisibility(); + + QObject::connect(&service, &KDBusService::activateRequested, &view, [&](const QStringList &arguments, const QString &workingDirectory) { + Q_UNUSED(workingDirectory) + parser.parse(arguments); + updateVisibility(); + }); return app.exec(); } diff --git a/krunner/update/CMakeLists.txt b/krunner/update/CMakeLists.txt --- a/krunner/update/CMakeLists.txt +++ b/krunner/update/CMakeLists.txt @@ -1,5 +1,5 @@ set(krunnerplugins_SRCS - main.cpp + krunnerplugins.cpp ) add_executable(krunnerplugins ${krunnerplugins_SRCS}) @@ -10,3 +10,13 @@ install(FILES krunnerplugins.upd DESTINATION ${KDE_INSTALL_KCONFUPDATEDIR}) +set(krunnerglobalshortcuts_SRCS + krunnerglobalshortcuts.cpp + ) + +add_executable(krunnerglobalshortcuts ${krunnerglobalshortcuts_SRCS}) + +target_link_libraries(krunnerglobalshortcuts KF5::CoreAddons KF5::Service KF5::Runner KF5::ConfigCore KF5::GlobalAccel KF5::XmlGui) + +install(TARGETS krunnerglobalshortcuts DESTINATION ${KDE_INSTALL_LIBDIR}/kconf_update_bin/) +install(FILES krunnerglobalshortcuts.upd DESTINATION ${KDE_INSTALL_KCONFUPDATEDIR}) diff --git a/krunner/update/krunnerglobalshortcuts.cpp b/krunner/update/krunnerglobalshortcuts.cpp new file mode 100644 --- /dev/null +++ b/krunner/update/krunnerglobalshortcuts.cpp @@ -0,0 +1,85 @@ +/*************************************************************************** + * Copyright (C) 2019 by Kai Uwe Broulik * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * + ***************************************************************************/ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + QCoreApplication app(argc, argv); + + const auto oldRunCommand = KGlobalAccel::self()->globalShortcut(QStringLiteral("krunner"), QStringLiteral("run command")); + const auto oldRunClipboard = KGlobalAccel::self()->globalShortcut(QStringLiteral("krunner"), QStringLiteral("run command on clipboard contents")); + + // Fake krunner and remove the old shortcuts + { + KActionCollection oldCollection(static_cast(nullptr)); + oldCollection.setComponentName(QStringLiteral("krunner")); + + QAction *oldAction = new QAction(); + oldCollection.addAction(QStringLiteral("run command"), oldAction); + KGlobalAccel::self()->setDefaultShortcut(oldAction, {}); + KGlobalAccel::self()->removeAllShortcuts(oldAction); + + QAction *oldClipboard = new QAction(); + oldCollection.addAction(QStringLiteral("run command on clipboard contents"), oldClipboard); + KGlobalAccel::self()->setDefaultShortcut(oldClipboard, {}); + KGlobalAccel::self()->removeAllShortcuts(oldClipboard); + } + + // Fake krunner.desktop launcher and transfer the shortcuts over + { + // Since we need to fake those actions, read the translated names from the desktop file + KDesktopFile df(QStandardPaths::GenericDataLocation, QStringLiteral("kglobalaccel/krunner.desktop")); + + QString displayName = QStringLiteral("KRunner"); + if (!df.readName().isEmpty()) { + displayName = df.readName(); + } + + const QString clipboardActionName = df.actionGroup(QStringLiteral("RunClipboard")).readEntry(QStringLiteral("Name"), QStringLiteral("Run command on clipboard contents")); + + KActionCollection shortCutActions(static_cast(nullptr)); + shortCutActions.setComponentName(QStringLiteral("krunner.desktop")); + shortCutActions.setComponentDisplayName(displayName); + + if (!oldRunCommand.isEmpty()) { + QAction *runCommandAction = new QAction(displayName); + shortCutActions.addAction(QStringLiteral("_launch"), runCommandAction); + KGlobalAccel::self()->setShortcut(runCommandAction, oldRunCommand, KGlobalAccel::NoAutoloading); + } + + if (!oldRunClipboard.isEmpty()) { + QAction *runClipboardAction = new QAction(clipboardActionName); + shortCutActions.addAction(QStringLiteral("RunClipboard"), runClipboardAction); + KGlobalAccel::self()->setShortcut(runClipboardAction, oldRunClipboard, KGlobalAccel::NoAutoloading); + } + } + + return 0; +} + diff --git a/krunner/update/krunnerglobalshortcuts.upd b/krunner/update/krunnerglobalshortcuts.upd new file mode 100644 --- /dev/null +++ b/krunner/update/krunnerglobalshortcuts.upd @@ -0,0 +1,3 @@ +Version=5 +Id=5.17KRunnerGlobalShortcuts +Script=krunnerglobalshortcuts diff --git a/krunner/update/main.cpp b/krunner/update/krunnerplugins.cpp rename from krunner/update/main.cpp rename to krunner/update/krunnerplugins.cpp diff --git a/krunner/view.cpp b/krunner/view.cpp --- a/krunner/view.cpp +++ b/krunner/view.cpp @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include @@ -69,22 +68,6 @@ new AppAdaptor(this); QDBusConnection::sessionBus().registerObject(QStringLiteral("/App"), this); - QAction *a = new QAction(nullptr); - QObject::connect(a, &QAction::triggered, this, &View::displayOrHide); - a->setText(i18n("Show KRunner")); - a->setObjectName(QStringLiteral("run command")); - a->setProperty("componentDisplayName", i18nc("Name for krunner shortcuts category", "KRunner")); - KGlobalAccel::self()->setDefaultShortcut(a, QList() << QKeySequence(Qt::ALT + Qt::Key_Space), KGlobalAccel::NoAutoloading); - KGlobalAccel::self()->setShortcut(a, QList() << QKeySequence(Qt::ALT + Qt::Key_Space) << QKeySequence(Qt::ALT + Qt::Key_F2) << Qt::Key_Search); - - a = new QAction(nullptr); - QObject::connect(a, &QAction::triggered, this, &View::displayWithClipboardContents); - a->setText(i18n("Run Command on clipboard contents")); - a->setObjectName(QStringLiteral("run command on clipboard contents")); - a->setProperty("componentDisplayName", i18nc("Name for krunner shortcuts category", "KRunner")); - KGlobalAccel::self()->setDefaultShortcut(a, QList() << QKeySequence(Qt::ALT+Qt::SHIFT+Qt::Key_F2)); - KGlobalAccel::self()->setShortcut(a, QList() << QKeySequence(Qt::ALT+Qt::SHIFT+Qt::Key_F2)); - m_qmlObj = new KDeclarative::QmlObject(this); m_qmlObj->setInitializationDelayed(true); connect(m_qmlObj, &KDeclarative::QmlObject::finished, this, &View::objectIncubated);