diff --git a/CMakeLists.txt b/CMakeLists.txt index f5bf0376..23ceed62 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,182 +1,182 @@ project(plasma-workspace) set(PROJECT_VERSION "5.7.90") set(PROJECT_VERSION_MAJOR 5) cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR) set(QT_MIN_VERSION "5.6.1") -set(KF5_MIN_VERSION "5.18.0") +set(KF5_MIN_VERSION "5.24.0") set(INSTALL_SDDM_THEME TRUE) find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS Widgets Quick QuickWidgets Concurrent Test Script Network) find_package(ECM 1.8.0 REQUIRED NO_MODULE) set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR}) find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS Plasma DocTools Runner JsEmbed NotifyConfig Su NewStuff Wallet KCMUtils IdleTime Declarative TextWidgets KDELibs4Support Crash GlobalAccel DBusAddons) find_package(KF5NetworkManagerQt ${KF5_MIN_VERSION}) set_package_properties(KF5NetworkManagerQt PROPERTIES DESCRIPTION "Qt wrapper for NetworkManager API" TYPE OPTIONAL PURPOSE "Needed by geolocation data engine." ) find_package(KF5XmlRpcClient REQUIRED) # WARNING PlasmaQuick provides unversioned CMake config find_package(KF5 REQUIRED COMPONENTS PlasmaQuick) find_package(KF5 REQUIRED COMPONENTS SysGuard) find_package(KF5 REQUIRED COMPONENTS Package) # Baloo has a different version scheme than KF5 for now find_package(KF5 5.1 REQUIRED COMPONENTS Baloo) find_package(KF5TextEditor) find_package(KWinDBusInterface CONFIG REQUIRED) find_package(KScreenLocker REQUIRED) find_package(ScreenSaverDBusInterface CONFIG REQUIRED) find_package(KF5Holidays) set_package_properties(KF5Holidays PROPERTIES DESCRIPTION "Holidays provider for Plasma calendar" TYPE OPTIONAL PURPOSE "Needed to for holidays plugin for Plasma Calendar." ) find_package(Phonon4Qt5 4.6.60 REQUIRED NO_MODULE) set_package_properties(Phonon4Qt5 PROPERTIES DESCRIPTION "Qt-based audio library" TYPE REQUIRED) include(KDEInstallDirs) include(KDECMakeSettings) include(KDECompilerSettings NO_POLICY_SCOPE) include(ECMPackageConfigHelpers) include(ECMMarkNonGuiExecutable) include(CMakePackageConfigHelpers) include(WriteBasicConfigVersionFile) include(CheckIncludeFiles) include(FeatureSummary) include(ECMOptionalAddSubdirectory) include(ECMQtDeclareLoggingCategory) include(KDEPackageAppTemplates) find_package(KF5Activities ${KF5_MIN_VERSION}) set_package_properties(KF5Activities PROPERTIES DESCRIPTION "management of Plasma activities" TYPE OPTIONAL PURPOSE "Needed by activity related plasmoids." ) find_package(ZLIB) set_package_properties(ZLIB PROPERTIES DESCRIPTION "Support for gzip compressed files and data streams" URL "http://www.zlib.net" TYPE REQUIRED ) find_package(dbusmenu-qt5 CONFIG) set_package_properties(dbusmenu-qt5 PROPERTIES DESCRIPTION "Support for notification area menus via the DBusMenu protocol" URL "https://launchpad.net/libdbusmenu-qt" TYPE OPTIONAL ) find_package(X11) set_package_properties(X11 PROPERTIES DESCRIPTION "X11 libraries" URL "http://www.x.org" TYPE OPTIONAL PURPOSE "Required for building the X11 based workspace") if(X11_FOUND) find_package(XCB MODULE REQUIRED COMPONENTS XCB) set_package_properties(XCB PROPERTIES TYPE REQUIRED) if(NOT X11_SM_FOUND) message(FATAL_ERROR "\nThe X11 Session Management (SM) development package could not be found.\nPlease install libSM.\n") endif(NOT X11_SM_FOUND) find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS X11Extras) endif() if(X11_FOUND AND XCB_XCB_FOUND) set(HAVE_X11 1) endif() find_package(KF5Wayland CONFIG) set_package_properties(KF5Wayland PROPERTIES TYPE REQUIRED PURPOSE "Required for Wayland integration of plasmashell") include(ConfigureChecks.cmake) include_directories("${CMAKE_CURRENT_BINARY_DIR}") configure_file(config-workspace.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-workspace.h) configure_file(config-unix.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-unix.h ) configure_file(config-X11.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-X11.h) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/config-X11.h DESTINATION ${KDE_INSTALL_INCLUDEDIR}/legacytaskmanager COMPONENT Devel ) configure_file(plasma.desktop.cmake ${CMAKE_CURRENT_BINARY_DIR}/plasma.desktop) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/plasma.desktop DESTINATION ${KDE_INSTALL_DATADIR}/xsessions ) configure_file(plasmawayland.desktop.cmake ${CMAKE_CURRENT_BINARY_DIR}/plasmawayland.desktop) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/plasmawayland.desktop DESTINATION ${KDE_INSTALL_DATADIR}/wayland-sessions ) plasma_install_package(lookandfeel org.kde.breeze.desktop look-and-feel lookandfeel) if (INSTALL_SDDM_THEME) # Install the login theme into the SDDM directory # Longer term we need to look at making SDDM load from look and feel somehow.. and allow copying at runtime #NOTE this trailing slash is important to rename the directory install(DIRECTORY lookandfeel/contents/loginmanager/ DESTINATION ${KDE_INSTALL_FULL_DATADIR}/sddm/themes/breeze PATTERN "README.txt" EXCLUDE) install(DIRECTORY lookandfeel/contents/components DESTINATION ${KDE_INSTALL_FULL_DATADIR}/sddm/themes/breeze PATTERN "README.txt" EXCLUDE) endif() add_subdirectory(doc) add_subdirectory(libkworkspace) add_subdirectory(libtaskmanager) add_subdirectory(liblegacytaskmanager) add_subdirectory(components) if(dbusmenu-qt5_FOUND) add_subdirectory(appmenu) endif() add_subdirectory(plasma-windowed) add_subdirectory(shell) add_subdirectory(freespacenotifier) add_subdirectory(klipper) add_subdirectory(krunner) add_subdirectory(ksmserver) add_subdirectory(ksplash) add_subdirectory(systemmonitor) add_subdirectory(statusnotifierwatcher) add_subdirectory(startkde) add_subdirectory(themes) add_subdirectory(containmentactions) add_subdirectory(runners) add_subdirectory(applets) add_subdirectory(dataengines) add_subdirectory(wallpapers) add_subdirectory(kioslave) add_subdirectory(ktimezoned) add_subdirectory(kuiserver) add_subdirectory(menu) add_subdirectory(phonon) add_subdirectory(solidautoeject) add_subdirectory(drkonqi) ecm_optional_add_subdirectory(xembed-sni-proxy) add_subdirectory(soliduiserver) if(KF5Holidays_FOUND) add_subdirectory(plasmacalendarintegration) endif() add_subdirectory(templates) feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/runners/activities/activityrunner.cpp b/runners/activities/activityrunner.cpp index 00659850..23245c77 100644 --- a/runners/activities/activityrunner.cpp +++ b/runners/activities/activityrunner.cpp @@ -1,179 +1,179 @@ /* * Copyright (C) 2011 Aaron Seigo * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License version 2 as * published by the Free Software Foundation * * 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 Library 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 "activityrunner.h" #include #include #include K_EXPORT_PLASMA_RUNNER(activities, ActivityRunner) ActivityRunner::ActivityRunner(QObject *parent, const QVariantList &args) : Plasma::AbstractRunner(parent, args), m_activities(0), m_consumer(0), m_keywordi18n(i18nc("KRunner keyword", "activity")), m_keyword(QStringLiteral("activity")), m_enabled(false) { setObjectName(QStringLiteral("Activities")); setIgnoredTypes(Plasma::RunnerContext::Directory | Plasma::RunnerContext::File | Plasma::RunnerContext::NetworkLocation | Plasma::RunnerContext::Help); connect(this, &Plasma::AbstractRunner::prepare, this, &ActivityRunner::prep); connect(this, &Plasma::AbstractRunner::teardown, this, &ActivityRunner::down); qRegisterMetaType(); serviceStatusChanged(KActivities::Consumer::Running); } void ActivityRunner::prep() { if (!m_activities) { m_activities = new KActivities::Controller(this); m_consumer = new KActivities::Consumer(this); connect(m_consumer, &KActivities::Consumer::serviceStatusChanged, this, &ActivityRunner::serviceStatusChanged); serviceStatusChanged(m_activities->serviceStatus()); } } void ActivityRunner::down() { delete m_activities; m_activities = 0; } void ActivityRunner::serviceStatusChanged(KActivities::Consumer::ServiceStatus status) { const bool active = status != KActivities::Consumer::NotRunning; if (m_enabled == active) { return; } m_enabled = active; QList syntaxes; if (m_enabled) { setDefaultSyntax(Plasma::RunnerSyntax(m_keywordi18n, i18n("Lists all activities currently available to be run."))); addSyntax(Plasma::RunnerSyntax(i18nc("KRunner keyword", "activity :q:"), i18n("Switches to activity :q:."))); } } ActivityRunner::~ActivityRunner() { } void ActivityRunner::match(Plasma::RunnerContext &context) { if (!m_enabled) { return; } const QString term = context.query().trimmed(); bool list = false; QString name; if (term.startsWith(m_keywordi18n, Qt::CaseInsensitive)) { if (term.size() == m_keywordi18n.size()) { list = true; } else { name = term.right(term.size() - m_keywordi18n.size()).trimmed(); list = name.isEmpty(); } } else if (term.startsWith(m_keyword, Qt::CaseInsensitive)) { if (term.size() == m_keyword.size()) { list = true; } else { name = term.right(term.size() - m_keyword.size()).trimmed(); list = name.isEmpty(); } } else if (context.singleRunnerQueryMode()) { name = term; } else { return; } QList matches; QStringList activities = m_consumer->activities(); qSort(activities); const QString current = m_activities->currentActivity(); if (!context.isValid()) { return; } if (list) { foreach (const QString &activity, activities) { if (current == activity) { continue; } KActivities::Info info(activity); addMatch(info, matches); if (!context.isValid()) { return; } } } else { foreach (const QString &activity, activities) { if (current == activity) { continue; } KActivities::Info info(activity); if (info.name().startsWith(name, Qt::CaseInsensitive)) { addMatch(info, matches); } if (!context.isValid()) { return; } } } context.addMatches(matches); } void ActivityRunner::addMatch(const KActivities::Info &activity, QList &matches) { Plasma::QueryMatch match(this); match.setData(activity.id()); match.setType(Plasma::QueryMatch::ExactMatch); - match.setIcon(activity.icon().isEmpty() ? QIcon::fromTheme(QStringLiteral("preferences-activities")) : QIcon::fromTheme(activity.icon())); + match.setIconName(activity.icon().isEmpty() ? QStringLiteral("preferences-activities") : activity.icon()); match.setText(i18n("Switch to \"%1\"", activity.name())); match.setRelevance(0.7 + ((activity.state() == KActivities::Info::Running || activity.state() == KActivities::Info::Starting) ? 0.1 : 0)); matches << match; } void ActivityRunner::run(const Plasma::RunnerContext &context, const Plasma::QueryMatch &match) { Q_UNUSED(context) if (!m_enabled || !m_activities) { return; } m_activities->setCurrentActivity(match.data().toString()); } #include "activityrunner.moc" diff --git a/runners/baloo/baloosearchrunner.cpp b/runners/baloo/baloosearchrunner.cpp index 3b7d7e75..0ee7a85f 100644 --- a/runners/baloo/baloosearchrunner.cpp +++ b/runners/baloo/baloosearchrunner.cpp @@ -1,209 +1,209 @@ /* * This file is part of the KDE Baloo Project * Copyright (C) 2014 Vishesh Handa * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * */ #include "baloosearchrunner.h" #include #include #include #include #include #include #include #include #include #include SearchRunner::SearchRunner(QObject* parent, const QVariantList& args) : Plasma::AbstractRunner(parent, args) { } SearchRunner::SearchRunner(QObject* parent, const QString& serviceId) : Plasma::AbstractRunner(parent, serviceId) { } void SearchRunner::init() { Plasma::RunnerSyntax syntax(QStringLiteral(":q"), i18n("Search through files, emails and contacts")); } SearchRunner::~SearchRunner() { } QStringList SearchRunner::categories() const { QStringList list; list << i18n("Audio") << i18n("Image") << i18n("Document") << i18n("Video") << i18n("Folder"); return list; } QIcon SearchRunner::categoryIcon(const QString& category) const { if (category == i18n("Audio")) { return QIcon::fromTheme(QStringLiteral("audio")); } else if (category == i18n("Image")) { return QIcon::fromTheme(QStringLiteral("image")); } else if (category == i18n("Document")) { return QIcon::fromTheme(QStringLiteral("application-pdf")); } else if (category == i18n("Video")) { return QIcon::fromTheme(QStringLiteral("video")); } else if (category == i18n("Folder")) { return QIcon::fromTheme(QStringLiteral("folder")); } return Plasma::AbstractRunner::categoryIcon(category); } QList SearchRunner::match(Plasma::RunnerContext& context, const QString& type, const QString& category) { if (!context.isValid()) return QList(); const QStringList categories = context.enabledCategories(); if (!categories.isEmpty() && !categories.contains(category)) return QList(); Baloo::Query query; query.setSearchString(context.query()); query.setType(type); query.setLimit(10); Baloo::ResultIterator it = query.exec(); QList matches; QMimeDatabase mimeDb; // KRunner is absolutely retarded and allows plugins to set the global // relevance levels. so Baloo should not set the relevance of results too // high because then Applications will often appear after if the application // runner has not a higher relevance. So stupid. // Each runner plugin should not have to know about the others. // Anyway, that's why we're starting with .75 float relevance = .75; while (context.isValid() && it.next()) { Plasma::QueryMatch match(this); QString localUrl = it.filePath(); const QUrl url = QUrl::fromLocalFile(localUrl); QString iconName = mimeDb.mimeTypeForFile(localUrl).iconName(); - match.setIcon(QIcon::fromTheme(iconName)); + match.setIconName(iconName); match.setId(it.filePath()); match.setText(url.fileName()); match.setData(url); match.setType(Plasma::QueryMatch::PossibleMatch); match.setMatchCategory(category); match.setRelevance(relevance); relevance -= 0.05; QString folderPath = url.adjusted(QUrl::RemoveFilename | QUrl::StripTrailingSlash).toLocalFile(); if (folderPath.startsWith(QDir::homePath())) { folderPath.replace(0, QDir::homePath().length(), QStringLiteral("~")); } match.setSubtext(folderPath); matches << match; } return matches; } void SearchRunner::match(Plasma::RunnerContext& context) { const QString text = context.query(); // // Baloo (as of 2014-11-20) is single threaded. It has an internal mutex which results in // queries being queued one after another. Also, Baloo is really really slow for small queries // For example - on my SSD, it takes about 1.4 seconds for 'f' with an SSD. // When searching for "fire", it results in "f", "fi", "fir" and then "fire" being searched // We're therefore hacking around this by having a small delay for very short queries so that // they do not get queued internally in Baloo // if (text.length() <= 3) { QEventLoop loop; QTimer timer; connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit); timer.setSingleShot(true); timer.start(100); loop.exec(); if (!context.isValid()) { return; } } QList matches; matches << match(context, QStringLiteral("Audio"), i18n("Audio")); matches << match(context, QStringLiteral("Image"), i18n("Image")); matches << match(context, QStringLiteral("Document"), i18n("Document")); matches << match(context, QStringLiteral("Video"), i18n("Video")); matches << match(context, QStringLiteral("Folder"), i18n("Folder")); context.addMatches(matches); } void SearchRunner::run(const Plasma::RunnerContext&, const Plasma::QueryMatch& match) { const QUrl url = match.data().toUrl(); if (match.selectedAction()) { if (match.selectedAction()->data().toString() == QLatin1String("openParentDir")) { new KRun(url.adjusted(QUrl::RemoveFilename), nullptr); return; } } new KRun(url, 0); } QList SearchRunner::actionsForMatch(const Plasma::QueryMatch &match) { Q_UNUSED(match) const QString openParentDirId = QStringLiteral("openParentDir"); if (!action(openParentDirId)) { (addAction(openParentDirId, QIcon::fromTheme(QStringLiteral("document-open-folder")), i18n("Open Containing Folder")))->setData(openParentDirId); } return {action(openParentDirId)}; } QMimeData *SearchRunner::mimeDataForMatch(const Plasma::QueryMatch &match) { QMimeData *result = new QMimeData(); result->setUrls({match.data().toUrl()}); return result; } K_EXPORT_PLASMA_RUNNER(baloosearchrunner, SearchRunner) #include "baloosearchrunner.moc" diff --git a/runners/calculator/calculatorrunner.cpp b/runners/calculator/calculatorrunner.cpp index 840b7e3d..b750679e 100644 --- a/runners/calculator/calculatorrunner.cpp +++ b/runners/calculator/calculatorrunner.cpp @@ -1,325 +1,325 @@ /* * Copyright (C) 2007 Barış Metin * Copyright (C) 2006 David Faure * Copyright (C) 2007 Richard Moore * Copyright (C) 2010 Matteo Agostinelli * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License version 2 as * published by the Free Software Foundation * * 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 Library 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 "calculatorrunner.h" #ifdef ENABLE_QALCULATE #include "qalculate_engine.h" #else #include #endif #include #include #include #include K_EXPORT_PLASMA_RUNNER(calculatorrunner, CalculatorRunner) CalculatorRunner::CalculatorRunner( QObject* parent, const QVariantList &args ) : Plasma::AbstractRunner(parent, args) { Q_UNUSED(args) #ifdef ENABLE_QALCULATE m_engine = new QalculateEngine; setSpeed(SlowSpeed); #endif setObjectName( QStringLiteral("Calculator" )); setIgnoredTypes(Plasma::RunnerContext::Directory | Plasma::RunnerContext::File | Plasma::RunnerContext::NetworkLocation | Plasma::RunnerContext::Executable | Plasma::RunnerContext::ShellCommand); QString description = i18n("Calculates the value of :q: when :q: is made up of numbers and " "mathematical symbols such as +, -, /, * and ^."); addSyntax(Plasma::RunnerSyntax(QStringLiteral(":q:"), description)); addSyntax(Plasma::RunnerSyntax(QStringLiteral("=:q:"), description)); addSyntax(Plasma::RunnerSyntax(QStringLiteral(":q:="), description)); } CalculatorRunner::~CalculatorRunner() { #ifdef ENABLE_QALCULATE delete m_engine; #endif } void CalculatorRunner::powSubstitutions(QString& cmd) { if (cmd.contains(QStringLiteral("e+"), Qt::CaseInsensitive)) { cmd = cmd.replace(QLatin1String("e+"), QLatin1String("*10^"), Qt::CaseInsensitive); } if (cmd.contains(QStringLiteral("e-"), Qt::CaseInsensitive)) { cmd = cmd.replace(QLatin1String("e-"), QLatin1String("*10^-"), Qt::CaseInsensitive); } // the below code is scary mainly because we have to honor priority // honor decimal numbers and parenthesis. while (cmd.contains('^')) { int where = cmd.indexOf('^'); cmd = cmd.replace(where, 1, ','); int preIndex = where - 1; int postIndex = where + 1; int count = 0; QChar decimalSymbol = QLocale().decimalPoint(); //avoid out of range on weird commands preIndex = qMax(0, preIndex); postIndex = qMin(postIndex, cmd.length()-1); //go backwards looking for the beginning of the number or expression while (preIndex != 0) { QChar current = cmd.at(preIndex); QChar next = cmd.at(preIndex-1); //qDebug() << "index " << preIndex << " char " << current; if (current == ')') { count++; } else if (current == '(') { count--; } else { if (((next <= '9' ) && (next >= '0')) || next == decimalSymbol) { preIndex--; continue; } } if (count == 0) { //check for functions if (!((next <= 'z' ) && (next >= 'a'))) { break; } } preIndex--; } //go forwards looking for the end of the number or expression count = 0; while (postIndex != cmd.size() - 1) { QChar current=cmd.at(postIndex); QChar next=cmd.at(postIndex + 1); //check for functions if ((count == 0) && (current <= 'z') && (current >= 'a')) { postIndex++; continue; } if (current == '(') { count++; } else if (current == ')') { count--; } else { if (((next <= '9' ) && (next >= '0')) || next == decimalSymbol) { postIndex++; continue; } } if (count == 0) { break; } postIndex++; } preIndex = qMax(0, preIndex); postIndex = qMin(postIndex, cmd.length()); cmd.insert(preIndex,QLatin1String("pow(")); // +1 +4 == next position to the last number after we add 4 new characters pow( cmd.insert(postIndex + 1 + 4, ')'); //qDebug() << "from" << preIndex << " to " << postIndex << " got: " << cmd; } } void CalculatorRunner::hexSubstitutions(QString& cmd) { if (cmd.contains(QStringLiteral("0x"))) { //Append +0 so that the calculator can serve also as a hex converter cmd.append("+0"); bool ok; int pos = 0; QString hex; while (cmd.contains(QStringLiteral("0x"))) { hex.clear(); pos = cmd.indexOf(QStringLiteral("0x"), pos); for (int q = 0; q < cmd.size(); q++) {//find end of hex number QChar current = cmd[pos+q+2]; if (((current <= '9' ) && (current >= '0')) || ((current <= 'F' ) && (current >= 'A')) || ((current <= 'f' ) && (current >= 'a'))) { //Check if valid hex sign hex[q] = current; } else { break; } } cmd = cmd.replace(pos, 2+hex.length(), QString::number(hex.toInt(&ok,16))); //replace hex with decimal } } } void CalculatorRunner::userFriendlySubstitutions(QString& cmd) { if (cmd.contains(QLocale().decimalPoint(), Qt::CaseInsensitive)) { cmd=cmd.replace(QLocale().decimalPoint(), QChar('.'), Qt::CaseInsensitive); } // the following substitutions are not needed with libqalculate #ifndef ENABLE_QALCULATE hexSubstitutions(cmd); powSubstitutions(cmd); if (cmd.contains(QRegExp(QStringLiteral("\\d+and\\d+")))) { cmd = cmd.replace(QRegExp(QStringLiteral("(\\d+)and(\\d+)")), QStringLiteral("\\1&\\2")); } if (cmd.contains(QRegExp(QStringLiteral("\\d+or\\d+")))) { cmd = cmd.replace(QRegExp(QStringLiteral("(\\d+)or(\\d+)")), QStringLiteral("\\1|\\2")); } if (cmd.contains(QRegExp(QStringLiteral("\\d+xor\\d+")))) { cmd = cmd.replace(QRegExp(QStringLiteral("(\\d+)xor(\\d+)")), QStringLiteral("\\1^\\2")); } #endif } void CalculatorRunner::match(Plasma::RunnerContext &context) { const QString term = context.query(); QString cmd = term; //no meanless space between friendly guys: helps simplify code cmd = cmd.trimmed().remove(' '); if (cmd.length() < 3) { return; } if (cmd.toLower() == QLatin1String("universe") || cmd.toLower() == QLatin1String("life")) { Plasma::QueryMatch match(this); match.setType(Plasma::QueryMatch::InformationalMatch); - match.setIcon(QIcon::fromTheme(QStringLiteral("accessories-calculator"))); + match.setIconName(QStringLiteral("accessories-calculator")); match.setText(QStringLiteral("42")); match.setData("42"); match.setId(term); context.addMatch(match); return; } bool toHex = cmd.startsWith(QLatin1String("hex=")); bool startsWithEquals = !toHex && cmd[0] == '='; if (toHex || startsWithEquals) { cmd.remove(0, cmd.indexOf('=') + 1); } else if (cmd.endsWith('=')) { cmd.chop(1); } else { bool foundDigit = false; for (int i = 0; i < cmd.length(); ++i) { QChar c = cmd.at(i); if (c.isLetter()) { // not just numbers and symbols, so we return return; } if (c.isDigit()) { foundDigit = true; } } if (!foundDigit) { return; } } if (cmd.isEmpty()) { return; } userFriendlySubstitutions(cmd); #ifndef ENABLE_QALCULATE cmd.replace(QRegExp(QStringLiteral("([a-zA-Z]+)")), QStringLiteral("Math.\\1")); //needed for accessing math funktions like sin(),.... #endif QString result = calculate(cmd); if (!result.isEmpty() && result != cmd) { if (toHex) { result = "0x" + QString::number(result.toInt(), 16).toUpper(); } Plasma::QueryMatch match(this); match.setType(Plasma::QueryMatch::InformationalMatch); - match.setIcon(QIcon::fromTheme(QStringLiteral("accessories-calculator"))); + match.setIconName(QStringLiteral("accessories-calculator")); match.setText(result); match.setData(result); match.setId(term); context.addMatch(match); } } QString CalculatorRunner::calculate(const QString& term) { #ifdef ENABLE_QALCULATE QString result; try { result = m_engine->evaluate(term); } catch(std::exception& e) { qDebug() << "qalculate error: " << e.what(); } return result.replace('.', QLocale().decimalPoint(), Qt::CaseInsensitive); #else //qDebug() << "calculating" << term; QScriptEngine eng; QScriptValue result = eng.evaluate(" var result ="+term+"; result"); if (result.isError()) { return QString(); } const QString resultString = result.toString(); if (resultString.isEmpty()) { return QString(); } if (!resultString.contains('.')) { return resultString; } //ECMAScript has issues with the last digit in simple rational computations //This script rounds off the last digit; see bug 167986 QString roundedResultString = eng.evaluate(QStringLiteral("var exponent = 14-(1+Math.floor(Math.log(Math.abs(result))/Math.log(10)));\ var order=Math.pow(10,exponent);\ (order > 0? Math.round(result*order)/order : 0)")).toString(); roundedResultString.replace('.', QLocale().decimalPoint(), Qt::CaseInsensitive); return roundedResultString; #endif } QMimeData * CalculatorRunner::mimeDataForMatch(const Plasma::QueryMatch &match) { //qDebug(); QMimeData *result = new QMimeData(); result->setText(match.text()); return result; } #include "calculatorrunner.moc" diff --git a/runners/kill/killrunner.cpp b/runners/kill/killrunner.cpp index 9e137659..a7a7a01c 100644 --- a/runners/kill/killrunner.cpp +++ b/runners/kill/killrunner.cpp @@ -1,225 +1,225 @@ /* Copyright 2009 Jan Gerrit Marker * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) version 3, or any * later version accepted by the membership of KDE e.V. (or its * successor approved by the membership of KDE e.V.), which shall * act as a proxy defined in Section 6 of version 3 of the license. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ #include "killrunner.h" #include #include #include #include #include #include #include "processcore/processes.h" #include "processcore/process.h" #include "killrunner_config.h" K_EXPORT_PLASMA_RUNNER(kill, KillRunner) KillRunner::KillRunner(QObject *parent, const QVariantList& args) : Plasma::AbstractRunner(parent, args), m_processes(0) { Q_UNUSED(args); setObjectName( QLatin1String("Kill Runner") ); reloadConfiguration(); connect(this, &Plasma::AbstractRunner::prepare, this, &KillRunner::prep); connect(this, &Plasma::AbstractRunner::teardown, this, &KillRunner::cleanup); m_delayedCleanupTimer.setInterval(50); m_delayedCleanupTimer.setSingleShot(true); connect(&m_delayedCleanupTimer, &QTimer::timeout, this, &KillRunner::cleanup); } KillRunner::~KillRunner() { } void KillRunner::reloadConfiguration() { KConfigGroup grp = config(); m_triggerWord.clear(); if (grp.readEntry(CONFIG_USE_TRIGGERWORD, true)) { m_triggerWord = grp.readEntry(CONFIG_TRIGGERWORD, i18n("kill")) + ' '; } m_sorting = (KillRunnerConfig::Sort) grp.readEntry(CONFIG_SORTING, 0); QList syntaxes; syntaxes << Plasma::RunnerSyntax(m_triggerWord + ":q:", i18n("Terminate running applications whose names match the query.")); setSyntaxes(syntaxes); } void KillRunner::prep() { m_delayedCleanupTimer.stop(); } void KillRunner::cleanup() { if (!m_processes) { return; } if (m_prepLock.tryLockForWrite()) { delete m_processes; m_processes = 0; m_prepLock.unlock(); } else { m_delayedCleanupTimer.stop(); } } void KillRunner::match(Plasma::RunnerContext &context) { QString term = context.query(); const bool hasTrigger = !m_triggerWord.isEmpty(); if (hasTrigger && !term.startsWith(m_triggerWord, Qt::CaseInsensitive)) { return; } m_prepLock.lockForRead(); if (!m_processes) { m_prepLock.unlock(); m_prepLock.lockForWrite(); if (!m_processes) { suspendMatching(true); m_processes = new KSysGuard::Processes(); m_processes->updateAllProcesses(); suspendMatching(false); } } m_prepLock.unlock(); term = term.right(term.length() - m_triggerWord.length()); if (term.length() < 2) { return; } QList matches; const QList processlist = m_processes->getAllProcesses(); foreach (const KSysGuard::Process *process, processlist) { if (!context.isValid()) { return; } const QString name = process->name(); if (!name.contains(term, Qt::CaseInsensitive)) { //Process doesn't match the search term continue; } const quint64 pid = process->pid(); const qlonglong uid = process->uid(); const QString user = getUserName(uid); QVariantList data; data << pid << user; Plasma::QueryMatch match(this); match.setText(i18n("Terminate %1", name)); match.setSubtext(i18n("Process ID: %1\nRunning as user: %2", QString::number(pid), user)); - match.setIcon(QIcon::fromTheme(QStringLiteral("application-exit"))); + match.setIconName(QStringLiteral("application-exit")); match.setData(data); match.setId(name); // Set the relevance switch (m_sorting) { case KillRunnerConfig::CPU: match.setRelevance((process->userUsage() + process->sysUsage()) / 100); break; case KillRunnerConfig::CPUI: match.setRelevance(1 - (process->userUsage() + process->sysUsage()) / 100); break; case KillRunnerConfig::NONE: match.setRelevance(name.compare(term, Qt::CaseInsensitive) == 0 ? 1 : 9); break; } matches << match; } qDebug() << "match count is" << matches.count(); context.addMatches(matches); } void KillRunner::run(const Plasma::RunnerContext &context, const Plasma::QueryMatch &match) { Q_UNUSED(context) QVariantList data = match.data().value(); quint64 pid = data[0].toUInt(); QString user = data[1].toString(); int signal; if (match.selectedAction() != NULL) { signal = match.selectedAction()->data().toInt(); } else { signal = 9; //default: SIGKILL } QStringList args; args << QStringLiteral("-%1").arg(signal) << QStringLiteral("%1").arg(pid); KProcess *process = new KProcess(this); int returnCode = process->execute(QStringLiteral("kill"), args); if (returnCode == 0) { return; } KAuth::Action killAction = QStringLiteral("org.kde.ksysguard.processlisthelper.sendsignal"); killAction.setHelperId(QStringLiteral("org.kde.ksysguard.processlisthelper")); killAction.addArgument(QStringLiteral("pid0"), pid); killAction.addArgument(QStringLiteral("pidcount"), 1); killAction.addArgument(QStringLiteral("signal"), signal); killAction.execute(); } QList KillRunner::actionsForMatch(const Plasma::QueryMatch &match) { Q_UNUSED(match) QList ret; if (!action(QStringLiteral("SIGTERM"))) { (addAction(QStringLiteral("SIGTERM"), QIcon::fromTheme(QStringLiteral("application-exit")), i18n("Send SIGTERM")))->setData(15); (addAction(QStringLiteral("SIGKILL"), QIcon::fromTheme(QStringLiteral("process-stop")), i18n("Send SIGKILL")))->setData(9); } ret << action(QStringLiteral("SIGTERM")) << action(QStringLiteral("SIGKILL")); return ret; } QString KillRunner::getUserName(qlonglong uid) { KUser user(uid); if (user.isValid()) { return user.loginName(); } qDebug() << QStringLiteral("No user with UID %1 was found").arg(uid); return QStringLiteral("root");//No user with UID uid was found, so root is used } #include "killrunner.moc" diff --git a/runners/locations/locationrunner.cpp b/runners/locations/locationrunner.cpp index 126097e4..c0204ee5 100644 --- a/runners/locations/locationrunner.cpp +++ b/runners/locations/locationrunner.cpp @@ -1,208 +1,208 @@ /* * Copyright (C) 2007 Teemu Rytilahti * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License version 2 as * published by the Free Software Foundation * * 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 Library 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 "locationrunner.h" #include #include #include #include #include #include #include #include #include #include #include K_EXPORT_PLASMA_RUNNER(locations, LocationsRunner) LocationsRunner::LocationsRunner(QObject *parent, const QVariantList& args) : Plasma::AbstractRunner(parent, args) { Q_UNUSED(args); // set the name shown after the result in krunner window setObjectName(QStringLiteral("Locations")); setIgnoredTypes(Plasma::RunnerContext::Executable | Plasma::RunnerContext::ShellCommand); addSyntax(Plasma::RunnerSyntax(QStringLiteral(":q:"), i18n("Finds local directories and files, network locations and Internet sites with paths matching :q:."))); } LocationsRunner::~LocationsRunner() { } void LocationsRunner::match(Plasma::RunnerContext &context) { QString term = context.query(); Plasma::RunnerContext::Type type = context.type(); if (type == Plasma::RunnerContext::Directory || type == Plasma::RunnerContext::File) { Plasma::QueryMatch match(this); match.setType(Plasma::QueryMatch::ExactMatch); match.setText(i18n("Open %1", term)); if (type == Plasma::RunnerContext::File) { - match.setIcon(QIcon::fromTheme(KIO::iconNameForUrl(QUrl(term)))); + match.setIconName(KIO::iconNameForUrl(QUrl(term))); } else { - match.setIcon(QIcon::fromTheme(QStringLiteral("system-file-manager"))); + match.setIconName(QStringLiteral("system-file-manager")); } match.setRelevance(1); match.setData(term); match.setType(Plasma::QueryMatch::ExactMatch); if (type == Plasma::RunnerContext::Directory) { match.setId(QStringLiteral("opendir")); } else { match.setId(QStringLiteral("openfile")); } context.addMatch(match); } else if (type == Plasma::RunnerContext::Help) { //qDebug() << "Locations matching because of" << type; Plasma::QueryMatch match(this); match.setType(Plasma::QueryMatch::ExactMatch); match.setText(i18n("Open %1", term)); - match.setIcon(QIcon::fromTheme(QStringLiteral("system-help"))); + match.setIconName(QStringLiteral("system-help")); match.setRelevance(1); match.setType(Plasma::QueryMatch::ExactMatch); match.setId(QStringLiteral("help")); context.addMatch(match); } else if (type == Plasma::RunnerContext::NetworkLocation || type == Plasma::RunnerContext::UnknownType) { const bool filtered = KUriFilter::self()->filterUri(term, QStringList() << QStringLiteral("kshorturifilter")); if (!filtered) { return; } QUrl url(term); if (!KProtocolInfo::isKnownProtocol(url.scheme())) { return; } Plasma::QueryMatch match(this); match.setText(i18n("Go to %1", url.toDisplayString())); - match.setIcon(QIcon::fromTheme(KProtocolInfo::icon(url.scheme()))); + match.setIconName(KProtocolInfo::icon(url.scheme())); match.setData(url.url()); if (KProtocolInfo::isHelperProtocol(url.scheme())) { //qDebug() << "helper protocol" << url.protocol() <<"call external application" ; if (url.scheme() == QLatin1String("mailto")) { match.setText(i18n("Send email to %1",url.path())); } else { match.setText(i18n("Launch with %1", KProtocolInfo::exec(url.scheme()))); } } else { //qDebug() << "protocol managed by browser" << url.protocol(); match.setText(i18n("Go to %1", url.toDisplayString())); } if (type == Plasma::RunnerContext::UnknownType) { match.setId(QStringLiteral("openunknown")); match.setRelevance(0.5); match.setType(Plasma::QueryMatch::PossibleMatch); } else { match.setId(QStringLiteral("opennetwork")); match.setRelevance(0.7); match.setType(Plasma::QueryMatch::ExactMatch); } context.addMatch(match); } } static QString convertCaseInsensitivePath(const QString &path) { // Split the string on / const auto dirNames = path.splitRef(QDir::separator(), QString::SkipEmptyParts); // if split result is empty, path string can only contain separator. if (dirNames.empty()) { return QStringLiteral("/"); } // Match folders QDir dir(QStringLiteral("/")); for (int i = 0; i < dirNames.size() - 1; ++i) { const QStringRef dirName = dirNames.at(i); bool foundMatch = false; const QStringList entries = dir.entryList(QDir::Dirs); for (const QString &entry : entries) { if (entry.compare(dirName, Qt::CaseInsensitive) == 0) { foundMatch = dir.cd(entry); if (foundMatch) { break; } } } if (!foundMatch) { return path; } } const QStringRef finalName = dirNames.last(); const QStringList entries = dir.entryList(); for (const QString &entry : entries) { if (entry.compare(finalName, Qt::CaseInsensitive) == 0) { return dir.absoluteFilePath(entry); } } return path; } void LocationsRunner::run(const Plasma::RunnerContext &context, const Plasma::QueryMatch &match) { Q_UNUSED(match) QString location = context.query(); if (location.isEmpty()) { return; } location = convertCaseInsensitivePath(location); //qDebug() << "command: " << context.query(); //qDebug() << "url: " << location << data; QUrl urlToRun(KUriFilter::self()->filteredUri(location, {QStringLiteral("kshorturifilter")})); new KRun(urlToRun, 0); } QMimeData * LocationsRunner::mimeDataForMatch(const Plasma::QueryMatch &match) { const QString data = match.data().toString(); if (!data.isEmpty()) { QMimeData *result = new QMimeData(); result->setUrls({QUrl(data)}); return result; } return 0; } #include "locationrunner.moc" diff --git a/runners/powerdevil/PowerDevilRunner.cpp b/runners/powerdevil/PowerDevilRunner.cpp index 527a2c29..db093435 100644 --- a/runners/powerdevil/PowerDevilRunner.cpp +++ b/runners/powerdevil/PowerDevilRunner.cpp @@ -1,323 +1,323 @@ /*************************************************************************** * Copyright 2008 by Dario Freddi * * Copyright 2008 by Sebastian Kügler * * * * 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 "PowerDevilRunner.h" #include #include #include #include #include #include #include #include #include #include K_EXPORT_PLASMA_RUNNER(powerdevil, PowerDevilRunner) PowerDevilRunner::PowerDevilRunner(QObject *parent, const QVariantList &args) : Plasma::AbstractRunner(parent, args), m_shortestCommand(1000) { qDBusRegisterMetaType< StringStringMap >(); setObjectName( QLatin1String("PowerDevil" )); setIgnoredTypes(Plasma::RunnerContext::Directory | Plasma::RunnerContext::File | Plasma::RunnerContext::NetworkLocation | Plasma::RunnerContext::Help); updateStatus(); initUpdateTriggers(); /* Let's define all the words here. m_words contains all the words that * will eventually trigger a match in the runner. */ QStringList commands; commands << i18nc("Note this is a KRunner keyword", "power profile") << i18nc("Note this is a KRunner keyword", "suspend") << i18nc("Note this is a KRunner keyword", "sleep") << i18nc("Note this is a KRunner keyword", "hibernate") << i18nc("Note this is a KRunner keyword", "to disk") << i18nc("Note this is a KRunner keyword", "to ram") << i18nc("Note this is a KRunner keyword", "screen brightness") << i18nc("Note this is a KRunner keyword", "dim screen"); foreach (const QString &command, commands) { if (command.length() < m_shortestCommand) { m_shortestCommand = command.length(); } } } void PowerDevilRunner::updateSyntaxes() { QList syntaxes; syntaxes.append(Plasma::RunnerSyntax(i18nc("Note this is a KRunner keyword", "power profile"), i18n("Lists all power profiles and allows them to be activated"))); syntaxes.append(Plasma::RunnerSyntax(i18nc("Note this is a KRunner keyword", "suspend"), i18n("Lists system suspend (e.g. sleep, hibernate) options " "and allows them to be activated"))); QSet< Solid::PowerManagement::SleepState > states = Solid::PowerManagement::supportedSleepStates(); if (states.contains(Solid::PowerManagement::SuspendState)) { Plasma::RunnerSyntax sleepSyntax(i18nc("Note this is a KRunner keyword", "sleep"), i18n("Suspends the system to RAM")); sleepSyntax.addExampleQuery(i18nc("Note this is a KRunner keyword", "to ram")); syntaxes.append(sleepSyntax); } if (states.contains(Solid::PowerManagement::HibernateState)) { Plasma::RunnerSyntax hibernateSyntax(i18nc("Note this is a KRunner keyword", "hibernate"), i18n("Suspends the system to disk")); hibernateSyntax.addExampleQuery(i18nc("Note this is a KRunner keyword", "to disk")); syntaxes.append(hibernateSyntax); } Plasma::RunnerSyntax brightnessSyntax(i18nc("Note this is a KRunner keyword", "screen brightness"), // xgettext:no-c-format i18n("Lists screen brightness options or sets it to the brightness defined by :q:; " "e.g. screen brightness 50 would dim the screen to 50% maximum brightness")); brightnessSyntax.addExampleQuery(i18nc("Note this is a KRunner keyword", "dim screen")); syntaxes.append(brightnessSyntax); setSyntaxes(syntaxes); } PowerDevilRunner::~PowerDevilRunner() { } void PowerDevilRunner::initUpdateTriggers() { // Also receive updates triggered through the DBus QDBusConnection dbus = QDBusConnection::sessionBus(); if (dbus.interface()->isServiceRegistered(QStringLiteral("org.kde.Solid.PowerManagement"))) { if (!dbus.connect(QStringLiteral("org.kde.Solid.PowerManagement"), QStringLiteral("/org/kde/Solid/PowerManagement"), QStringLiteral("org.kde.Solid.PowerManagement"), QStringLiteral("profileChanged"), this, SLOT(updateStatus()))) { qDebug() << "error!"; } if (!dbus.connect(QStringLiteral("org.kde.Solid.PowerManagement"), QStringLiteral("/org/kde/Solid/PowerManagement"), QStringLiteral("org.kde.Solid.PowerManagement"), QStringLiteral("configurationReloaded"), this, SLOT(updateStatus()))) { qDebug() << "error!"; } } } void PowerDevilRunner::updateStatus() { // Profiles and their icons { KSharedConfigPtr profilesConfig = KSharedConfig::openConfig(QStringLiteral("powerdevil2profilesrc"), KConfig::SimpleConfig); // Request profiles to the daemon QDBusMessage call = QDBusMessage::createMethodCall(QStringLiteral("org.kde.Solid.PowerManagement"), QStringLiteral("/org/kde/Solid/PowerManagement"), QStringLiteral("org.kde.Solid.PowerManagement"), QStringLiteral("availableProfiles")); QDBusPendingReply< StringStringMap > reply = QDBusConnection::sessionBus().asyncCall(call); reply.waitForFinished(); if (!reply.isValid()) { qDebug() << "Error contacting the daemon!"; return; } m_availableProfiles = reply.value(); if (m_availableProfiles.isEmpty()) { qDebug() << "No available profiles!"; return; } for (StringStringMap::const_iterator i = m_availableProfiles.constBegin(); i != m_availableProfiles.constEnd(); ++i) { KConfigGroup settings(profilesConfig, i.key()); if (settings.readEntry< QString >("icon", QString()).isEmpty()) { m_profileIcon[i.key()] = QLatin1String("preferences-system-power-management"); } else { m_profileIcon[i.key()] = settings.readEntry< QString >("icon", QString()); } } } updateSyntaxes(); } bool PowerDevilRunner::parseQuery(const QString& query, const QList& rxList, QString& parameter) const { foreach (const QRegExp& rx, rxList) { if (rx.exactMatch(query)) { parameter = rx.cap(1).trimmed(); return true; } } return false; } void PowerDevilRunner::match(Plasma::RunnerContext &context) { const QString term = context.query(); if (term.length() < m_shortestCommand) { return; } QList matches; QString parameter; if (parseQuery(term, QList() << QRegExp(i18nc("Note this is a KRunner keyword; %1 is a parameter", "power profile %1", "(.*)"), Qt::CaseInsensitive) << QRegExp(i18nc("Note this is a KRunner keyword", "power profile"), Qt::CaseInsensitive), parameter)) { for (StringStringMap::const_iterator i = m_availableProfiles.constBegin(); i != m_availableProfiles.constEnd(); ++i) { if (!parameter.isEmpty()) { if (!i.value().startsWith(parameter, Qt::CaseInsensitive)) { continue; } } Plasma::QueryMatch match(this); match.setType(Plasma::QueryMatch::ExactMatch); - match.setIcon(QIcon::fromTheme(m_profileIcon[i.key()])); + match.setIconName(m_profileIcon[i.key()]); match.setText(i18n("Set Profile to '%1'", i.value())); match.setData(i.key()); match.setRelevance(1); match.setId("ProfileChange "+ i.key()); matches.append(match); } } else if (parseQuery(term, QList() << QRegExp(i18nc("Note this is a KRunner keyword; %1 is a parameter", "screen brightness %1", "(.*)"), Qt::CaseInsensitive) << QRegExp(i18nc("Note this is a KRunner keyword", "screen brightness"), Qt::CaseInsensitive) << QRegExp(i18nc("Note this is a KRunner keyword; %1 is a parameter", "dim screen %1", "(.*)"), Qt::CaseInsensitive) << QRegExp(i18nc("Note this is a KRunner keyword", "dim screen"), Qt::CaseInsensitive), parameter)) { if (!parameter.isEmpty()) { bool test; int b = parameter.toInt(&test); if (test) { int brightness = qBound(0, b, 100); Plasma::QueryMatch match(this); match.setType(Plasma::QueryMatch::ExactMatch); - match.setIcon(QIcon::fromTheme(QStringLiteral("preferences-system-power-management"))); + match.setIconName(QStringLiteral("preferences-system-power-management")); match.setText(i18n("Set Brightness to %1", brightness)); match.setData(brightness); match.setRelevance(1); match.setId(QStringLiteral("BrightnessChange")); matches.append(match); } } else { Plasma::QueryMatch match1(this); match1.setType(Plasma::QueryMatch::ExactMatch); - match1.setIcon(QIcon::fromTheme(QStringLiteral("preferences-system-power-management"))); + match1.setIconName(QStringLiteral("preferences-system-power-management")); match1.setText(i18n("Dim screen totally")); match1.setRelevance(1); match1.setId(QStringLiteral("DimTotal")); matches.append(match1); Plasma::QueryMatch match2(this); match2.setType(Plasma::QueryMatch::ExactMatch); - match2.setIcon(QIcon::fromTheme(QStringLiteral("preferences-system-power-management"))); + match2.setIconName(QStringLiteral("preferences-system-power-management")); match2.setText(i18n("Dim screen by half")); match2.setRelevance(1); match2.setId(QStringLiteral("DimHalf")); matches.append(match2); } } else if (term.compare(i18nc("Note this is a KRunner keyword", "suspend"), Qt::CaseInsensitive) == 0) { QSet< Solid::PowerManagement::SleepState > states = Solid::PowerManagement::supportedSleepStates(); if (states.contains(Solid::PowerManagement::SuspendState)) { addSuspendMatch(Solid::PowerManagement::SuspendState, matches); } if (states.contains(Solid::PowerManagement::HibernateState)) { addSuspendMatch(Solid::PowerManagement::HibernateState, matches); } } else if (term.compare(i18nc("Note this is a KRunner keyword", "sleep"), Qt::CaseInsensitive) == 0 || term.compare(i18nc("Note this is a KRunner keyword", "to ram"), Qt::CaseInsensitive) == 0) { addSuspendMatch(Solid::PowerManagement::SuspendState, matches); } else if (term.compare(i18nc("Note this is a KRunner keyword", "hibernate"), Qt::CaseInsensitive) == 0 || term.compare(i18nc("Note this is a KRunner keyword", "to disk"), Qt::CaseInsensitive) == 0) { addSuspendMatch(Solid::PowerManagement::HibernateState, matches); } if (!matches.isEmpty()) { context.addMatches(matches); } } void PowerDevilRunner::addSuspendMatch(int value, QList &matches) { Plasma::QueryMatch match(this); match.setType(Plasma::QueryMatch::ExactMatch); switch ((Solid::PowerManagement::SleepState)value) { case Solid::PowerManagement::SuspendState: case Solid::PowerManagement::StandbyState: - match.setIcon(QIcon::fromTheme(QStringLiteral("system-suspend"))); + match.setIconName(QStringLiteral("system-suspend")); match.setText(i18n("Suspend to RAM")); match.setRelevance(1); break; case Solid::PowerManagement::HibernateState: - match.setIcon(QIcon::fromTheme(QStringLiteral("system-suspend-hibernate"))); + match.setIconName(QStringLiteral("system-suspend-hibernate")); match.setText(i18n("Suspend to Disk")); match.setRelevance(0.99); break; } match.setData(value); match.setId(QStringLiteral("Suspend")); matches.append(match); } void PowerDevilRunner::run(const Plasma::RunnerContext &context, const Plasma::QueryMatch &match) { Q_UNUSED(context) QDBusInterface iface(QStringLiteral("org.kde.Solid.PowerManagement"), QStringLiteral("/org/kde/Solid/PowerManagement"), QStringLiteral("org.kde.Solid.PowerManagement")); QDBusInterface brightnessIface(QStringLiteral("org.kde.Solid.PowerManagement"), QStringLiteral("/org/kde/Solid/PowerManagement/Actions/BrightnessControl"), QStringLiteral("org.kde.Solid.PowerManagement.Actions.BrightnessControl")); if (match.id().startsWith(QLatin1String("PowerDevil_ProfileChange"))) { iface.asyncCall(QStringLiteral("loadProfile"), match.data().toString()); } else if (match.id() == QLatin1String("PowerDevil_BrightnessChange")) { brightnessIface.asyncCall(QStringLiteral("setBrightness"), match.data().toInt()); } else if (match.id() == QLatin1String("PowerDevil_DimTotal")) { brightnessIface.asyncCall(QStringLiteral("setBrightness"), 0); } else if (match.id() == QLatin1String("PowerDevil_DimHalf")) { QDBusReply brightness = brightnessIface.asyncCall(QStringLiteral("brightness")); brightnessIface.asyncCall(QStringLiteral("setBrightness"), static_cast(brightness / 2)); } else if (match.id().startsWith(QLatin1String("PowerDevil_Suspend"))) { switch ((Solid::PowerManagement::SleepState)match.data().toInt()) { case Solid::PowerManagement::SuspendState: case Solid::PowerManagement::StandbyState: Solid::PowerManagement::requestSleep(Solid::PowerManagement::SuspendState, 0, 0); break; case Solid::PowerManagement::HibernateState: Solid::PowerManagement::requestSleep(Solid::PowerManagement::HibernateState, 0, 0); break; } } } #include "PowerDevilRunner.moc" diff --git a/runners/recentdocuments/recentdocuments.cpp b/runners/recentdocuments/recentdocuments.cpp index 7dac3b97..f053c487 100644 --- a/runners/recentdocuments/recentdocuments.cpp +++ b/runners/recentdocuments/recentdocuments.cpp @@ -1,110 +1,109 @@ /* * Copyright 2008 Sebastian Kügler * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, 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 Library 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 "recentdocuments.h" #include #include #include #include #include #include #include #include K_EXPORT_PLASMA_RUNNER(recentdocuments, RecentDocuments) RecentDocuments::RecentDocuments(QObject *parent, const QVariantList& args) : Plasma::AbstractRunner(parent, args) { Q_UNUSED(args); setObjectName( QStringLiteral("Recent Documents" )); - m_icon = QIcon::fromTheme(QStringLiteral("document-open-recent")); loadRecentDocuments(); // listen for changes to the list of recent documents KDirWatch *recentDocWatch = new KDirWatch(this); recentDocWatch->addDir(KRecentDocument::recentDocumentDirectory(), KDirWatch::WatchFiles); connect(recentDocWatch, &KDirWatch::created, this, &RecentDocuments::loadRecentDocuments); connect(recentDocWatch, &KDirWatch::deleted, this, &RecentDocuments::loadRecentDocuments); connect(recentDocWatch, &KDirWatch::dirty, this, &RecentDocuments::loadRecentDocuments); addSyntax(Plasma::RunnerSyntax(QStringLiteral(":q:"), i18n("Looks for documents recently used with names matching :q:."))); } RecentDocuments::~RecentDocuments() { } void RecentDocuments::loadRecentDocuments() { - //qDebug() << "Refreshing recent documents."; m_recentdocuments = KRecentDocument::recentDocuments(); } void RecentDocuments::match(Plasma::RunnerContext &context) { if (m_recentdocuments.isEmpty()) { return; } const QString term = context.query(); if (term.length() < 3) { return; } foreach (const QString &document, m_recentdocuments) { if (!context.isValid()) { return; } if (document.contains(term, Qt::CaseInsensitive)) { KDesktopFile config(document); Plasma::QueryMatch match(this); match.setType(Plasma::QueryMatch::PossibleMatch); match.setRelevance(1.0); - match.setIcon(QIcon::fromTheme(config.readIcon())); + match.setIconName(config.readIcon()); match.setData(config.readUrl()); match.setText(config.readName()); match.setSubtext(i18n("Recent Document")); + context.addMatch(match); } } } void RecentDocuments::run(const Plasma::RunnerContext &context, const Plasma::QueryMatch &match) { Q_UNUSED(context) QString url = match.data().toString(); qDebug() << "Opening Recent Document" << url; new KRun(url, 0); } QMimeData * RecentDocuments::mimeDataForMatch(const Plasma::QueryMatch& match) { QMimeData * result = new QMimeData(); QList urls; urls << QUrl(match.data().toString()); result->setUrls(urls); result->setText(match.data().toString()); return result; } #include "recentdocuments.moc" diff --git a/runners/recentdocuments/recentdocuments.h b/runners/recentdocuments/recentdocuments.h index 8bf62dfd..45a74627 100644 --- a/runners/recentdocuments/recentdocuments.h +++ b/runners/recentdocuments/recentdocuments.h @@ -1,49 +1,48 @@ /* * Copyright 2008 Sebastian Kügler * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, 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 Library 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. */ #ifndef RECENTDOCUMENTS_H #define RECENTDOCUMENTS_H #include #include class RecentDocuments : public Plasma::AbstractRunner { Q_OBJECT public: RecentDocuments( QObject *parent, const QVariantList& args ); ~RecentDocuments() override; void match(Plasma::RunnerContext &context) override; void run(const Plasma::RunnerContext &context, const Plasma::QueryMatch &match) override; private Q_SLOTS: QMimeData * mimeDataForMatch(const Plasma::QueryMatch &match) override; private Q_SLOTS: void loadRecentDocuments(); private: - QIcon m_icon; QStringList m_recentdocuments; }; #endif diff --git a/runners/services/servicerunner.cpp b/runners/services/servicerunner.cpp index aa9d2bda..07a0c8f1 100644 --- a/runners/services/servicerunner.cpp +++ b/runners/services/servicerunner.cpp @@ -1,335 +1,335 @@ /* * Copyright (C) 2006 Aaron Seigo * Copyright (C) 2014 Vishesh Handa * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License version 2 as * published by the Free Software Foundation * * 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 Library 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 "servicerunner.h" #include #include #include #include #include #include #include #include #include ServiceRunner::ServiceRunner(QObject *parent, const QVariantList &args) : Plasma::AbstractRunner(parent, args) { Q_UNUSED(args) setObjectName( QStringLiteral("Application" )); setPriority(AbstractRunner::HighestPriority); addSyntax(Plasma::RunnerSyntax(QStringLiteral(":q:"), i18n("Finds applications whose name or description match :q:"))); } ServiceRunner::~ServiceRunner() { } QStringList ServiceRunner::categories() const { QStringList cat; cat << i18n("Applications") << i18n("System Settings"); return cat; } QIcon ServiceRunner::categoryIcon(const QString& category) const { if (category == i18n("Applications")) { return QIcon::fromTheme(QStringLiteral("applications-other")); } else if (category == i18n("System Settings")) { return QIcon::fromTheme(QStringLiteral("preferences-system")); } return Plasma::AbstractRunner::categoryIcon(category); } void ServiceRunner::match(Plasma::RunnerContext &context) { const QString term = context.query(); QList matches; QSet seen; QString query; if (term.length() > 1) { // Search for applications which are executable and case-insensitively match the search term // See http://techbase.kde.org/Development/Tutorials/Services/Traders#The_KTrader_Query_Language // if the following is unclear to you. query = QStringLiteral("exist Exec and ('%1' =~ Name)").arg(term); KService::List services = KServiceTypeTrader::self()->query(QStringLiteral("Application"), query); if (!services.isEmpty()) { //qDebug() << service->name() << "is an exact match!" << service->storageId() << service->exec(); foreach (const KService::Ptr &service, services) { if (!service->noDisplay() && service->property(QStringLiteral("NotShowIn"), QVariant::String) != "KDE") { Plasma::QueryMatch match(this); match.setType(Plasma::QueryMatch::ExactMatch); setupMatch(service, match); match.setRelevance(1); matches << match; seen.insert(service->storageId()); seen.insert(service->exec()); } } } } if (!context.isValid()) { return; } // If the term length is < 3, no real point searching the Keywords and GenericName if (term.length() < 3) { query = QStringLiteral("exist Exec and ( (exist Name and '%1' ~~ Name) or ('%1' ~~ Exec) )").arg(term); } else { // Search for applications which are executable and the term case-insensitive matches any of // * a substring of one of the keywords // * a substring of the GenericName field // * a substring of the Name field // Note that before asking for the content of e.g. Keywords and GenericName we need to ask if // they exist to prevent a tree evaluation error if they are not defined. query = QStringLiteral("exist Exec and ( (exist Keywords and '%1' ~subin Keywords) or (exist GenericName and '%1' ~~ GenericName) or (exist Name and '%1' ~~ Name) or ('%1' ~~ Exec) )").arg(term); } KService::List services = KServiceTypeTrader::self()->query(QStringLiteral("Application"), query); services += KServiceTypeTrader::self()->query(QStringLiteral("KCModule"), query); //qDebug() << "got " << services.count() << " services from " << query; foreach (const KService::Ptr &service, services) { if (service->noDisplay()) { continue; } const QString id = service->storageId(); const QString name = service->desktopEntryName(); const QString exec = service->exec(); if (seen.contains(id) || seen.contains(exec)) { //qDebug() << "already seen" << id << exec; continue; } //qDebug() << "haven't seen" << id << "so processing now"; seen.insert(id); seen.insert(exec); Plasma::QueryMatch match(this); match.setType(Plasma::QueryMatch::PossibleMatch); setupMatch(service, match); qreal relevance(0.6); // If the term was < 3 chars and NOT at the beginning of the App's name or Exec, then // chances are the user doesn't want that app. if (term.length() < 3) { if (name.startsWith(term) || exec.startsWith(term)) { relevance = 0.9; } else { continue; } } else if (service->name().contains(term, Qt::CaseInsensitive)) { relevance = 0.8; if (service->name().startsWith(term, Qt::CaseInsensitive)) { relevance += 0.1; } } else if (service->genericName().contains(term, Qt::CaseInsensitive)) { relevance = 0.65; if (service->genericName().startsWith(term, Qt::CaseInsensitive)) { relevance += 0.05; } } else if (service->exec().contains(term, Qt::CaseInsensitive)) { relevance = 0.7; if (service->exec().startsWith(term, Qt::CaseInsensitive)) { relevance += 0.05; } } if (service->categories().contains(QStringLiteral("KDE")) || service->serviceTypes().contains(QStringLiteral("KCModule"))) { //qDebug() << "found a kde thing" << id << match.subtext() << relevance; if (id.startsWith(QLatin1String("kde-"))) { //qDebug() << "old" << service->type(); if (!service->isApplication()) { // avoid showing old kcms and what not continue; } // This is an older version, let's disambiguate it QString subtext(QStringLiteral("KDE3")); if (!match.subtext().isEmpty()) { subtext.append(", " + match.subtext()); } match.setSubtext(subtext); } else { relevance += .09; } } //qDebug() << service->name() << "is this relevant:" << relevance; match.setRelevance(relevance); if (service->serviceTypes().contains(QStringLiteral("KCModule"))) { match.setMatchCategory(i18n("System Settings")); } matches << match; } //search for applications whose categories contains the query query = QStringLiteral("exist Exec and (exist Categories and '%1' ~subin Categories)").arg(term); services = KServiceTypeTrader::self()->query(QStringLiteral("Application"), query); //qDebug() << service->name() << "is an exact match!" << service->storageId() << service->exec(); foreach (const KService::Ptr &service, services) { if (!service->noDisplay()) { QString id = service->storageId(); QString exec = service->exec(); if (seen.contains(id) || seen.contains(exec)) { //qDebug() << "already seen" << id << exec; continue; } Plasma::QueryMatch match(this); match.setType(Plasma::QueryMatch::PossibleMatch); setupMatch(service, match); qreal relevance = 0.6; if (service->categories().contains(QStringLiteral("X-KDE-More")) || !service->showInCurrentDesktop()) { relevance = 0.5; } if (service->isApplication()) { relevance += .04; } match.setRelevance(relevance); matches << match; } } // search for jump list actions if (term.length() >= 3) { query = QStringLiteral("exist Actions"); // doesn't work services = KServiceTypeTrader::self()->query(QStringLiteral("Application"));//, query); foreach (const KService::Ptr &service, services) { if (service->noDisplay()) { continue; } foreach (const KServiceAction &action, service->actions()) { if (action.text().isEmpty() || action.exec().isEmpty() || seen.contains(action.exec())) { continue; } if (!action.text().contains(term, Qt::CaseInsensitive)) { continue; } Plasma::QueryMatch match(this); match.setType(Plasma::QueryMatch::HelperMatch); if (!action.icon().isEmpty()) { - match.setIcon(QIcon::fromTheme(action.icon())); + match.setIconName(action.icon()); } else { - match.setIcon(QIcon::fromTheme(service->icon())); + match.setIconName(service->icon()); } match.setText(i18nc("Jump list search result, %1 is action (eg. open new tab), %2 is application (eg. browser)", "%1 - %2", action.text(), service->name())); match.setData(action.exec()); qreal relevance = 0.5; if (action.text().startsWith(term, Qt::CaseInsensitive)) { relevance += 0.05; } match.setRelevance(relevance); matches << match; } } } //context.addMatches(term, matches); context.addMatches(matches); } void ServiceRunner::run(const Plasma::RunnerContext &context, const Plasma::QueryMatch &match) { Q_UNUSED(context); if (match.type() == Plasma::QueryMatch::HelperMatch) { // Jump List Action KRun::run(match.data().toString(), {}, nullptr); return; } KService::Ptr service = KService::serviceByStorageId(match.data().toString()); if (service) { KActivities::ResourceInstance::notifyAccessed( QUrl(QStringLiteral("applications:") + service->storageId()), QStringLiteral("org.kde.krunner") ); KRun::runService(*service, {}, nullptr, true); } } void ServiceRunner::setupMatch(const KService::Ptr &service, Plasma::QueryMatch &match) { const QString name = service->name(); match.setText(name); match.setData(service->storageId()); if (!service->genericName().isEmpty() && service->genericName() != name) { match.setSubtext(service->genericName()); } else if (!service->comment().isEmpty()) { match.setSubtext(service->comment()); } if (!service->icon().isEmpty()) { - match.setIcon(QIcon::fromTheme(service->icon())); + match.setIconName(service->icon()); } } QMimeData * ServiceRunner::mimeDataForMatch(const Plasma::QueryMatch &match) { KService::Ptr service = KService::serviceByStorageId(match.data().toString()); if (service) { QMimeData * result = new QMimeData(); QList urls; urls << QUrl::fromLocalFile(service->entryPath()); qDebug() << urls; result->setUrls(urls); return result; } return 0; } K_EXPORT_PLASMA_RUNNER(services, ServiceRunner) #include "servicerunner.moc" diff --git a/runners/sessions/sessionrunner.cpp b/runners/sessions/sessionrunner.cpp index 14218e32..4d614d7f 100644 --- a/runners/sessions/sessionrunner.cpp +++ b/runners/sessions/sessionrunner.cpp @@ -1,280 +1,280 @@ /* * Copyright (C) 2006 Aaron Seigo * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License version 2 as * published by the Free Software Foundation * * 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 Library 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 "sessionrunner.h" #include #include #include #include #include "kworkspace.h" #include "screensaver_interface.h" K_EXPORT_PLASMA_RUNNER(calculatorrunner, SessionRunner) SessionRunner::SessionRunner(QObject *parent, const QVariantList &args) : Plasma::AbstractRunner(parent, args) { setObjectName( QLatin1String("Sessions" )); setPriority(LowPriority); setIgnoredTypes(Plasma::RunnerContext::Directory | Plasma::RunnerContext::File | Plasma::RunnerContext::NetworkLocation); m_canLogout = KAuthorized::authorizeKAction(QStringLiteral("logout")) && KAuthorized::authorize(QStringLiteral("logout")); if (m_canLogout) { addSyntax(Plasma::RunnerSyntax(i18nc("log out command", "logout"), i18n("Logs out, exiting the current desktop session"))); addSyntax(Plasma::RunnerSyntax(i18nc("shutdown computer command", "shutdown"), i18n("Turns off the computer"))); } if (KAuthorized::authorizeKAction(QStringLiteral("lock_screen")) && m_canLogout) { addSyntax(Plasma::RunnerSyntax(i18nc("lock screen command", "lock"), i18n("Locks the current sessions and starts the screen saver"))); } Plasma::RunnerSyntax rebootSyntax(i18nc("restart computer command", "restart"), i18n("Reboots the computer")); rebootSyntax.addExampleQuery(i18nc("restart computer command", "reboot")); addSyntax(rebootSyntax); m_triggerWord = i18nc("switch user command", "switch"); addSyntax(Plasma::RunnerSyntax(i18nc("switch user command", "switch :q:"), i18n("Switches to the active session for the user :q:, " "or lists all active sessions if :q: is not provided"))); Plasma::RunnerSyntax fastUserSwitchSyntax(i18n("switch user"), i18n("Starts a new session as a different user")); fastUserSwitchSyntax.addExampleQuery(i18n("new session")); addSyntax(fastUserSwitchSyntax); //"SESSIONS" should not be translated; it's used programmaticaly setDefaultSyntax(Plasma::RunnerSyntax(QStringLiteral("SESSIONS"), i18n("Lists all sessions"))); } SessionRunner::~SessionRunner() { } void SessionRunner::matchCommands(QList &matches, const QString& term) { if (!m_canLogout) { return; } if (term.compare(i18nc("log out command","logout"), Qt::CaseInsensitive) == 0 || term.compare(i18n("log out"), Qt::CaseInsensitive) == 0) { Plasma::QueryMatch match(this); match.setText(i18nc("log out command","Logout")); - match.setIcon(QIcon::fromTheme(QStringLiteral("system-log-out"))); + match.setIconName(QStringLiteral("system-log-out")); match.setData(LogoutAction); match.setType(Plasma::QueryMatch::ExactMatch); match.setRelevance(0.9); matches << match; } else if (term.compare(i18nc("restart computer command", "restart"), Qt::CaseInsensitive) == 0 || term.compare(i18nc("restart computer command", "reboot"), Qt::CaseInsensitive) == 0) { Plasma::QueryMatch match(this); match.setText(i18n("Restart the computer")); - match.setIcon(QIcon::fromTheme(QStringLiteral("system-reboot"))); + match.setIconName(QStringLiteral("system-reboot")); match.setData(RestartAction); match.setType(Plasma::QueryMatch::ExactMatch); match.setRelevance(0.9); matches << match; } else if (term.compare(i18nc("shutdown computer command","shutdown"), Qt::CaseInsensitive) == 0) { Plasma::QueryMatch match(this); match.setText(i18n("Shutdown the computer")); - match.setIcon(QIcon::fromTheme(QStringLiteral("system-shutdown"))); + match.setIconName(QStringLiteral("system-shutdown")); match.setData(ShutdownAction); match.setType(Plasma::QueryMatch::ExactMatch); match.setRelevance(0.9); matches << match; } else if (term.compare(i18nc("lock screen command","lock"), Qt::CaseInsensitive) == 0) { if (KAuthorized::authorizeKAction(QStringLiteral("lock_screen"))) { Plasma::QueryMatch match(this); match.setText(i18n("Lock the screen")); - match.setIcon(QIcon::fromTheme(QStringLiteral("system-lock-screen"))); + match.setIconName(QStringLiteral("system-lock-screen")); match.setData(LockAction); match.setType(Plasma::QueryMatch::ExactMatch); match.setRelevance(0.9); matches << match; } } } void SessionRunner::match(Plasma::RunnerContext &context) { const QString term = context.query(); QString user; bool matchUser = false; QList matches; if (term.size() < 3) { return; } // first compare with SESSIONS. this must *NOT* be translated (i18n) // as it is used as an internal command trigger (e.g. via d-bus), // not as a user supplied query. and yes, "Ugh, magic strings" bool listAll = term.compare(QLatin1String("SESSIONS"), Qt::CaseInsensitive) == 0 || term.compare(i18nc("User sessions", "sessions"), Qt::CaseInsensitive) == 0; if (!listAll) { //no luck, try the "switch" user command if (term.startsWith(m_triggerWord, Qt::CaseInsensitive)) { user = term.right(term.size() - m_triggerWord.length()).trimmed(); listAll = user.isEmpty(); matchUser = !listAll; } else { // we know it's not SESSION or "switch ", so let's // try some other possibilities matchCommands(matches, term); } } qDebug() << "session switching to" << (listAll ? QStringLiteral("all sessions") : term); bool switchUser = listAll || term.compare(i18n("switch user"), Qt::CaseInsensitive) == 0 || term.compare(i18n("new session"), Qt::CaseInsensitive) == 0; if (switchUser && KAuthorized::authorizeKAction(QStringLiteral("start_new_session")) && dm.isSwitchable() && dm.numReserve() >= 0) { Plasma::QueryMatch match(this); match.setType(Plasma::QueryMatch::ExactMatch); - match.setIcon(QIcon::fromTheme(QStringLiteral("system-switch-user"))); + match.setIconName(QStringLiteral("system-switch-user")); match.setText(i18n("New Session")); matches << match; } // now add the active sessions if (listAll || matchUser) { SessList sessions; dm.localSessions(sessions); foreach (const SessEnt& session, sessions) { if (!session.vt || session.self) { continue; } QString name = KDisplayManager::sess2Str(session); Plasma::QueryMatch::Type type = Plasma::QueryMatch::NoMatch; qreal relevance = 0.7; if (listAll) { type = Plasma::QueryMatch::ExactMatch; relevance = 1; } else if (matchUser) { if (name.compare(user, Qt::CaseInsensitive) == 0) { // we need an elif branch here because we don't // want the last conditional to be checked if !listAll type = Plasma::QueryMatch::ExactMatch; relevance = 1; } else if (name.contains(user, Qt::CaseInsensitive)) { type = Plasma::QueryMatch::PossibleMatch; } } if (type != Plasma::QueryMatch::NoMatch) { Plasma::QueryMatch match(this); match.setType(type); match.setRelevance(relevance); - match.setIcon(QIcon::fromTheme(QStringLiteral("user-identity"))); + match.setIconName(QStringLiteral("user-identity")); match.setText(name); match.setData(QString::number(session.vt)); matches << match; } } } context.addMatches(matches); } void SessionRunner::run(const Plasma::RunnerContext &context, const Plasma::QueryMatch &match) { Q_UNUSED(context); if (match.data().type() == QVariant::Int) { KWorkSpace::ShutdownType type = KWorkSpace::ShutdownTypeDefault; switch (match.data().toInt()) { case LogoutAction: type = KWorkSpace::ShutdownTypeNone; break; case RestartAction: type = KWorkSpace::ShutdownTypeReboot; break; case ShutdownAction: type = KWorkSpace::ShutdownTypeHalt; break; case LockAction: lock(); return; break; } if (type != KWorkSpace::ShutdownTypeDefault) { KWorkSpace::ShutdownConfirm confirm = KWorkSpace::ShutdownConfirmDefault; KWorkSpace::requestShutDown(confirm, type); return; } } if (!match.data().toString().isEmpty()) { dm.lockSwitchVT(match.data().toString().toInt()); return; } //TODO: this message is too verbose and too technical. int result = QMessageBox::warning( 0, i18n("Warning - New Session"), i18n("

You have chosen to open another desktop session.
" "The current session will be hidden " "and a new login screen will be displayed.
" "An F-key is assigned to each session; " "F%1 is usually assigned to the first session, " "F%2 to the second session and so on. " "You can switch between sessions by pressing " "Ctrl, Alt and the appropriate F-key at the same time. " "Additionally, the KDE Panel and Desktop menus have " "actions for switching between sessions.

", 7, 8)); if (result == QMessageBox::Cancel) { return; } lock(); dm.startReserve(); } void SessionRunner::lock() { QString interface(QStringLiteral("org.freedesktop.ScreenSaver")); org::freedesktop::ScreenSaver screensaver(interface, QStringLiteral("/ScreenSaver"), QDBusConnection::sessionBus()); if (screensaver.isValid()) { screensaver.Lock(); } } #include "sessionrunner.moc" diff --git a/runners/shell/shellrunner.cpp b/runners/shell/shellrunner.cpp index 25661af7..a893b83e 100644 --- a/runners/shell/shellrunner.cpp +++ b/runners/shell/shellrunner.cpp @@ -1,103 +1,103 @@ /* * Copyright (C) 2006 Aaron Seigo * Copyright (C) 2016 Kai Uwe Broulik * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License version 2 as * published by the Free Software Foundation * * 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 Library 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 "shellrunner.h" #include #include #ifdef Q_OS_UNIX #include #endif #include #include #include #include #include #include #include "shell_config.h" K_EXPORT_PLASMA_RUNNER(shell, ShellRunner) ShellRunner::ShellRunner(QObject *parent, const QVariantList &args) : Plasma::AbstractRunner(parent, args) { setObjectName( QLatin1String("Command" )); setPriority(AbstractRunner::HighestPriority); setHasRunOptions(true); m_enabled = KAuthorized::authorize(QStringLiteral("run_command")) && KAuthorized::authorize(QStringLiteral("shell_access")); setIgnoredTypes(Plasma::RunnerContext::Directory | Plasma::RunnerContext::File | Plasma::RunnerContext::NetworkLocation | Plasma::RunnerContext::UnknownType | Plasma::RunnerContext::Help); addSyntax(Plasma::RunnerSyntax(QStringLiteral(":q:"), i18n("Finds commands that match :q:, using common shell syntax"))); } ShellRunner::~ShellRunner() { } void ShellRunner::match(Plasma::RunnerContext &context) { if (!m_enabled) { return; } if (context.type() == Plasma::RunnerContext::Executable || context.type() == Plasma::RunnerContext::ShellCommand) { const QString term = context.query(); Plasma::QueryMatch match(this); match.setId(term); match.setType(Plasma::QueryMatch::ExactMatch); - match.setIcon(QIcon::fromTheme(QStringLiteral("system-run"))); + match.setIconName(QStringLiteral("system-run")); match.setText(i18n("Run %1", term)); match.setRelevance(0.7); context.addMatch(match); } } void ShellRunner::run(const Plasma::RunnerContext &context, const Plasma::QueryMatch &match) { Q_UNUSED(match); if (m_enabled) { if (match.selectedAction() && match.selectedAction() == actions().value(QStringLiteral("runInTerminal"))) { KToolInvocation::invokeTerminal(context.query()); } else { KRun::runCommand(context.query(), NULL); } } } QList ShellRunner::actionsForMatch(const Plasma::QueryMatch &match) { Q_UNUSED(match) const QString runInTerminalId = QStringLiteral("runInTerminal"); QAction *terminalAction = action(runInTerminalId); if (!terminalAction) { terminalAction = addAction(runInTerminalId, QIcon::fromTheme(QStringLiteral("utilities-terminal")), i18n("Run in Terminal Window")); }; return {terminalAction}; } #include "shellrunner.moc" diff --git a/runners/webshortcuts/webshortcutrunner.cpp b/runners/webshortcuts/webshortcutrunner.cpp index 2c09d218..1ad6677d 100644 --- a/runners/webshortcuts/webshortcutrunner.cpp +++ b/runners/webshortcuts/webshortcutrunner.cpp @@ -1,165 +1,163 @@ /* * Copyright (C) 2007 Teemu Rytilahti * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License version 2 as * published by the Free Software Foundation * * 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 Library 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 "webshortcutrunner.h" #include #include #include #include #include WebshortcutRunner::WebshortcutRunner(QObject *parent, const QVariantList& args) : Plasma::AbstractRunner(parent, args), m_match(this), m_filterBeforeRun(false) { Q_UNUSED(args); setObjectName( QLatin1String("Web Shortcut" )); setIgnoredTypes(Plasma::RunnerContext::Directory | Plasma::RunnerContext::File | Plasma::RunnerContext::Executable); - m_icon = QIcon::fromTheme(QStringLiteral("internet-web-browser")); - m_match.setType(Plasma::QueryMatch::ExactMatch); m_match.setRelevance(0.9); // Listen for KUriFilter plugin config changes and update state... QDBusConnection sessionDbus = QDBusConnection::sessionBus(); sessionDbus.connect(QString(), QStringLiteral("/"), QStringLiteral("org.kde.KUriFilterPlugin"), QStringLiteral("configure"), this, SLOT(readFiltersConfig())); connect(this, &WebshortcutRunner::teardown, this, &WebshortcutRunner::resetState); readFiltersConfig(); } WebshortcutRunner::~WebshortcutRunner() { } void WebshortcutRunner::readFiltersConfig() { // Make sure that the searchEngines cache, etc. is refreshed when the config file is changed. loadSyntaxes(); } void WebshortcutRunner::loadSyntaxes() { KUriFilterData filterData (QLatin1String(":q")); filterData.setSearchFilteringOptions(KUriFilterData::RetrieveAvailableSearchProvidersOnly); if (KUriFilter::self()->filterSearchUri(filterData, KUriFilter::NormalTextFilter)) { m_delimiter = filterData.searchTermSeparator(); } //qDebug() << "keyword delimiter:" << m_delimiter; //qDebug() << "search providers:" << filterData.preferredSearchProviders(); QList syns; Q_FOREACH (const QString &provider, filterData.preferredSearchProviders()) { //qDebug() << "checking out" << provider; Plasma::RunnerSyntax s(filterData.queryForPreferredSearchProvider(provider), /*":q:",*/ i18n("Opens \"%1\" in a web browser with the query :q:.", provider)); syns << s; } setSyntaxes(syns); } void WebshortcutRunner::resetState() { qDebug(); m_lastFailedKey.clear(); m_lastProvider.clear(); m_lastKey.clear(); } void WebshortcutRunner::match(Plasma::RunnerContext &context) { const QString term = context.query(); if (term.length() < 3 || !term.contains(m_delimiter)) return; // qDebug() << "checking term" << term; const int delimIndex = term.indexOf(m_delimiter); if (delimIndex == term.length() - 1) return; const QString key = term.left(delimIndex); if (key == m_lastFailedKey) { return; // we already know it's going to suck ;) } if (!context.isValid()) { qDebug() << "invalid context"; return; } // Do a fake user feedback text update if the keyword has not changed. // There is no point filtering the request on every key stroke. // filtering if (m_lastKey == key) { m_filterBeforeRun = true; m_match.setText(i18n("Search %1 for %2", m_lastProvider, term.mid(delimIndex + 1))); context.addMatch(m_match); return; } KUriFilterData filterData(term); if (!KUriFilter::self()->filterSearchUri(filterData, KUriFilter::WebShortcutFilter)) { m_lastFailedKey = key; return; } m_lastFailedKey.clear(); m_lastKey = key; m_lastProvider = filterData.searchProvider(); m_match.setData(filterData.uri().url()); m_match.setId("WebShortcut:" + key); - m_match.setIcon(QIcon::fromTheme(filterData.iconName())); + m_match.setIconName(filterData.iconName()); m_match.setText(i18n("Search %1 for %2", m_lastProvider, filterData.searchTerm())); context.addMatch(m_match); } void WebshortcutRunner::run(const Plasma::RunnerContext &context, const Plasma::QueryMatch &match) { QString location; //qDebug() << "filter before run?" << m_filterBeforeRun; if (m_filterBeforeRun) { m_filterBeforeRun = false; //qDebug() << "look up webshortcut:" << context.query(); KUriFilterData filterData (context.query()); if (KUriFilter::self()->filterSearchUri(filterData, KUriFilter::WebShortcutFilter)) location = filterData.uri().url(); } else { location = match.data().toString(); } //qDebug() << location; if (!location.isEmpty()) { KToolInvocation::invokeBrowser(location); } } K_EXPORT_PLASMA_RUNNER(webshortcuts, WebshortcutRunner) #include "webshortcutrunner.moc" diff --git a/runners/webshortcuts/webshortcutrunner.h b/runners/webshortcuts/webshortcutrunner.h index cf347bf6..36aa46c4 100644 --- a/runners/webshortcuts/webshortcutrunner.h +++ b/runners/webshortcuts/webshortcutrunner.h @@ -1,54 +1,53 @@ /* * Copyright (C) 2007 Teemu Rytilahti * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License version 2 as * published by the Free Software Foundation * * 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 Library 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. */ #ifndef WEBSHORTCUTRUNNER_H #define WEBSHORTCUTRUNNER_H #include #include class WebshortcutRunner : public Plasma::AbstractRunner { Q_OBJECT public: WebshortcutRunner( QObject *parent, const QVariantList& args ); ~WebshortcutRunner() override; void match(Plasma::RunnerContext &context) override; void run(const Plasma::RunnerContext &context, const Plasma::QueryMatch &match) override; private: void loadSyntaxes(); private Q_SLOTS: void readFiltersConfig(); void resetState(); private: - QIcon m_icon; Plasma::QueryMatch m_match; bool m_filterBeforeRun; QChar m_delimiter; QString m_lastFailedKey; QString m_lastKey; QString m_lastProvider; }; #endif diff --git a/runners/windowedwidgets/windowedwidgetsrunner.cpp b/runners/windowedwidgets/windowedwidgetsrunner.cpp index dbd30420..5ccbd27b 100644 --- a/runners/windowedwidgets/windowedwidgetsrunner.cpp +++ b/runners/windowedwidgets/windowedwidgetsrunner.cpp @@ -1,144 +1,144 @@ /* * Copyright (C) 2006 Aaron Seigo * Copyright (C) 2010 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License version 2 as * published by the Free Software Foundation * * 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 Library 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 "windowedwidgetsrunner.h" #include #include #include #include #include #include #include #include K_EXPORT_PLASMA_RUNNER(windowedwidgets, WindowedWidgetsRunner) WindowedWidgetsRunner::WindowedWidgetsRunner(QObject *parent, const QVariantList &args) : Plasma::AbstractRunner(parent, args) { Q_UNUSED(args) setObjectName( QLatin1String("WindowedWidgets" )); setPriority(AbstractRunner::HighestPriority); addSyntax(Plasma::RunnerSyntax(QStringLiteral(":q:"), i18n("Finds Plasma widgets whose name or description match :q:"))); setDefaultSyntax(Plasma::RunnerSyntax(i18nc("Note this is a KRunner keyword", "mobile applications"), i18n("list all Plasma widgets that can run as standalone applications"))); } WindowedWidgetsRunner::~WindowedWidgetsRunner() { } void WindowedWidgetsRunner::match(Plasma::RunnerContext &context) { const QString term = context.query(); if (!context.singleRunnerQueryMode() && term.length() < 3) { return; } QList matches; foreach (const KPluginInfo &info, Plasma::PluginLoader::self()->listAppletInfo(QString())) { KService::Ptr service = info.service(); if (((service->name().contains(term, Qt::CaseInsensitive) || service->genericName().contains(term, Qt::CaseInsensitive) || service->comment().contains(term, Qt::CaseInsensitive)) || service->categories().contains(term, Qt::CaseInsensitive) || term.startsWith(i18nc("Note this is a KRunner keyword", "mobile applications"))) && !info.property(QStringLiteral("NoDisplay")).toBool()) { QVariant val = info.property(QStringLiteral("X-Plasma-StandAloneApp")); if (!val.isValid() || !val.toBool()) { continue; } Plasma::QueryMatch match(this); setupMatch(service, match); if (service->name().compare(term, Qt::CaseInsensitive) == 0) { match.setType(Plasma::QueryMatch::ExactMatch); match.setRelevance(1); } else { match.setType(Plasma::QueryMatch::PossibleMatch); match.setRelevance(0.7); } matches << match; qDebug() << service; } } if (!context.isValid()) { return; } context.addMatches(matches); } void WindowedWidgetsRunner::run(const Plasma::RunnerContext &context, const Plasma::QueryMatch &match) { Q_UNUSED(context); KService::Ptr service = KService::serviceByStorageId(match.data().toString()); if (service) { QProcess::startDetached(QStringLiteral("plasmawindowed"), QStringList() << service->property(QStringLiteral("X-KDE-PluginInfo-Name"), QVariant::String).toString()); } } void WindowedWidgetsRunner::setupMatch(const KService::Ptr &service, Plasma::QueryMatch &match) { const QString name = service->name(); match.setText(name); match.setData(service->storageId()); if (!service->genericName().isEmpty() && service->genericName() != name) { match.setSubtext(service->genericName()); } else if (!service->comment().isEmpty()) { match.setSubtext(service->comment()); } if (!service->icon().isEmpty()) { - match.setIcon(QIcon::fromTheme(service->icon())); + match.setIconName(service->icon()); } } QMimeData * WindowedWidgetsRunner::mimeDataForMatch(const Plasma::QueryMatch &match) { KService::Ptr service = KService::serviceByStorageId(match.data().toString()); if (service) { QMimeData *data = new QMimeData(); data->setData(QStringLiteral("text/x-plasmoidservicename"), service->property(QStringLiteral("X-KDE-PluginInfo-Name"), QVariant::String).toString().toUtf8()); return data; } return 0; } #include "windowedwidgetsrunner.moc" diff --git a/runners/windows/windowsrunner.cpp b/runners/windows/windowsrunner.cpp index 008889f7..6571459d 100644 --- a/runners/windows/windowsrunner.cpp +++ b/runners/windows/windowsrunner.cpp @@ -1,484 +1,484 @@ /*************************************************************************** * Copyright 2009 by Martin Gräßlin * * * * 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 "windowsrunner.h" #include "config-windowsrunner.h" #include #include #include #include #include #if HAVE_X11 #include #include #endif K_EXPORT_PLASMA_RUNNER(windows, WindowsRunner) WindowsRunner::WindowsRunner(QObject* parent, const QVariantList& args) : AbstractRunner(parent, args), m_inSession(false), m_ready(false) { Q_UNUSED(args) setObjectName( QLatin1String("Windows" )); addSyntax(Plasma::RunnerSyntax(QStringLiteral(":q:"), i18n("Finds windows whose name, window class or window role match :q:. " "It is possible to interact with the windows by using one of the following keywords: " "activate, close, min(imize), max(imize), fullscreen, shade, keep above and keep below."))); addSyntax(Plasma::RunnerSyntax(QStringLiteral(":q:"), i18n("Finds windows which are on desktop named :q: " "It is possible to interact with the windows by using one of the following keywords: " "activate, close, min(imize), max(imize), fullscreen, shade, keep above and keep below."))); addSyntax(Plasma::RunnerSyntax(QStringLiteral(":q:"), i18n("Switch to desktop named :q:"))); setDefaultSyntax(Plasma::RunnerSyntax(i18nc("Note this is a KRunner keyword", "window"), i18n("Lists all windows and allows to activate them. " "With name=, class=, role= and desktop= the list can be reduced to " "windows matching these restrictions. " "It is possible to interact with the windows by using one of the following keywords: " "activate, close, min(imize), max(imize), fullscreen, shade, keep above and keep below."))); addSyntax(Plasma::RunnerSyntax(i18nc("Note this is a KRunner keyword", "desktop"), i18n("Lists all other desktops and allows to switch to them."))); connect(this, &Plasma::AbstractRunner::prepare, this, &WindowsRunner::prepareForMatchSession); connect(this, &Plasma::AbstractRunner::teardown, this, &WindowsRunner::matchSessionComplete); } WindowsRunner::~WindowsRunner() { } // Called in the main thread void WindowsRunner::gatherInfo() { QMutexLocker locker(&m_mutex); if (!m_inSession) { return; } foreach (const WId w, KWindowSystem::windows()) { KWindowInfo info = KWindowSystem::windowInfo(w, NET::WMWindowType | NET::WMDesktop | NET::WMState | NET::XAWMState | NET::WMName, NET::WM2WindowClass | NET::WM2WindowRole | NET::WM2AllowedActions); if (info.valid()) { // ignore NET::Tool and other special window types NET::WindowType wType = info.windowType(NET::NormalMask | NET::DesktopMask | NET::DockMask | NET::ToolbarMask | NET::MenuMask | NET::DialogMask | NET::OverrideMask | NET::TopMenuMask | NET::UtilityMask | NET::SplashMask); if (wType != NET::Normal && wType != NET::Override && wType != NET::Unknown && wType != NET::Dialog && wType != NET::Utility) { continue; } m_windows.insert(w, info); m_icons.insert(w, QIcon(KWindowSystem::icon(w))); } } for (int i=1; i<=KWindowSystem::numberOfDesktops(); i++) { m_desktopNames << KWindowSystem::desktopName(i); } m_ready = true; } // Called in the main thread void WindowsRunner::prepareForMatchSession() { QMutexLocker locker(&m_mutex); m_inSession = true; m_ready = false; QTimer::singleShot(0, this, &WindowsRunner::gatherInfo); } // Called in the main thread void WindowsRunner::matchSessionComplete() { QMutexLocker locker(&m_mutex); m_inSession = false; m_ready = false; m_desktopNames.clear(); m_icons.clear(); m_windows.clear(); } // Called in the secondary thread void WindowsRunner::match(Plasma::RunnerContext& context) { QMutexLocker locker(&m_mutex); if (!m_ready) { return; } QString term = context.query(); if (!context.singleRunnerQueryMode() && (term.length() < 3)) { return; } QList matches; // check if the search term ends with an action keyword WindowAction action = ActivateAction; if (term.endsWith(i18nc("Note this is a KRunner keyword", "activate") , Qt::CaseInsensitive)) { action = ActivateAction; term = term.left(term.lastIndexOf(i18nc("Note this is a KRunner keyword", "activate")) - 1); } else if (term.endsWith(i18nc("Note this is a KRunner keyword", "close") , Qt::CaseInsensitive)) { action = CloseAction; term = term.left(term.lastIndexOf(i18nc("Note this is a KRunner keyword", "close")) - 1); } else if (term.endsWith(i18nc("Note this is a KRunner keyword", "min") , Qt::CaseInsensitive)) { action = MinimizeAction; term = term.left(term.lastIndexOf(i18nc("Note this is a KRunner keyword", "min")) - 1); } else if (term.endsWith(i18nc("Note this is a KRunner keyword", "minimize") , Qt::CaseInsensitive)) { action = MinimizeAction; term = term.left(term.lastIndexOf(i18nc("Note this is a KRunner keyword", "minimize")) - 1); } else if (term.endsWith(i18nc("Note this is a KRunner keyword", "max") , Qt::CaseInsensitive)) { action = MaximizeAction; term = term.left(term.lastIndexOf(i18nc("Note this is a KRunner keyword", "max")) - 1); } else if (term.endsWith(i18nc("Note this is a KRunner keyword", "maximize") , Qt::CaseInsensitive)) { action = MaximizeAction; term = term.left(term.lastIndexOf(i18nc("Note this is a KRunner keyword", "maximize")) - 1); } else if (term.endsWith(i18nc("Note this is a KRunner keyword", "fullscreen") , Qt::CaseInsensitive)) { action = FullscreenAction; term = term.left(term.lastIndexOf(i18nc("Note this is a KRunner keyword", "fullscreen")) - 1); } else if (term.endsWith(i18nc("Note this is a KRunner keyword", "shade") , Qt::CaseInsensitive)) { action = ShadeAction; term = term.left(term.lastIndexOf(i18nc("Note this is a KRunner keyword", "shade")) - 1); } else if (term.endsWith(i18nc("Note this is a KRunner keyword", "keep above") , Qt::CaseInsensitive)) { action = KeepAboveAction; term = term.left(term.lastIndexOf(i18nc("Note this is a KRunner keyword", "keep above")) - 1); } else if (term.endsWith(i18nc("Note this is a KRunner keyword", "keep below") , Qt::CaseInsensitive)) { action = KeepBelowAction; term = term.left(term.lastIndexOf(i18nc("Note this is a KRunner keyword", "keep below")) - 1); } // keyword match: when term starts with "window" we list all windows // the list can be restricted to windows matching a given name, class, role or desktop if (term.startsWith(i18nc("Note this is a KRunner keyword", "window") , Qt::CaseInsensitive)) { const QStringList keywords = term.split(QStringLiteral(" ")); QString windowName; QString windowClass; QString windowRole; int desktop = -1; foreach (const QString& keyword, keywords) { if (keyword.endsWith('=')) { continue; } if (keyword.startsWith(i18nc("Note this is a KRunner keyword", "name") + "=" , Qt::CaseInsensitive)) { windowName = keyword.split(QStringLiteral("="))[1]; } else if (keyword.startsWith(i18nc("Note this is a KRunner keyword", "class") + "=" , Qt::CaseInsensitive)) { windowClass = keyword.split(QStringLiteral("="))[1]; } else if (keyword.startsWith(i18nc("Note this is a KRunner keyword", "role") + "=" , Qt::CaseInsensitive)) { windowRole = keyword.split(QStringLiteral("="))[1]; } else if (keyword.startsWith(i18nc("Note this is a KRunner keyword", "desktop") + "=" , Qt::CaseInsensitive)) { bool ok; desktop = keyword.split(QStringLiteral("="))[1].toInt(&ok); if (!ok || desktop > KWindowSystem::numberOfDesktops()) { desktop = -1; // sanity check } } else { // not a keyword - use as name if name is unused, but another option is set if (windowName.isEmpty() && !keyword.contains('=') && (!windowRole.isEmpty() || !windowClass.isEmpty() || desktop != -1)) { windowName = keyword; } } } QHashIterator it(m_windows); while(it.hasNext()) { it.next(); WId w = it.key(); KWindowInfo info = it.value(); QString windowClassCompare = QString::fromUtf8(info.windowClassName()) + " " + QString::fromUtf8(info.windowClassClass()); // exclude not matching windows if (!KWindowSystem::hasWId(w)) { continue; } if (!windowName.isEmpty() && !info.name().contains(windowName, Qt::CaseInsensitive)) { continue; } if (!windowClass.isEmpty() && !windowClassCompare.contains(windowClass, Qt::CaseInsensitive)) { continue; } if (!windowRole.isEmpty() && !QString::fromUtf8(info.windowRole()).contains(windowRole, Qt::CaseInsensitive)) { continue; } if (desktop != -1 && !info.isOnDesktop(desktop)) { continue; } // check for windows when no keywords were used // check the name, class and role for containing the query without the keyword if (windowName.isEmpty() && windowClass.isEmpty() && windowRole.isEmpty() && desktop == -1) { const QString& test = term.mid(keywords[0].length() + 1); if (!info.name().contains(test, Qt::CaseInsensitive) && !windowClassCompare.contains(test, Qt::CaseInsensitive) && !QString::fromUtf8(info.windowRole()).contains(test, Qt::CaseInsensitive)) { continue; } } // blacklisted everything else: we have a match if (actionSupported(info, action)){ matches << windowMatch(info, action); } } if (!matches.isEmpty()) { // the window keyword found matches - do not process other syntax possibilities context.addMatches(matches); return; } } bool desktopAdded = false; // check for desktop keyword if (term.startsWith(i18nc("Note this is a KRunner keyword", "desktop") , Qt::CaseInsensitive)) { const QStringList parts = term.split(QStringLiteral(" ")); if (parts.size() == 1) { // only keyword - list all desktops for (int i=1; i<=KWindowSystem::numberOfDesktops(); i++) { if (i == KWindowSystem::currentDesktop()) { continue; } matches << desktopMatch(i); desktopAdded = true; } } else { // keyword + desktop - restrict matches bool isInt; int desktop = term.midRef(parts[0].length() + 1).toInt(&isInt); if (isInt && desktop != KWindowSystem::currentDesktop()) { matches << desktopMatch(desktop); desktopAdded = true; } } } // check for matches without keywords QHashIterator it(m_windows); while (it.hasNext()) { it.next(); WId w = it.key(); if (!KWindowSystem::hasWId(w)) { continue; } // check if window name, class or role contains the query KWindowInfo info = it.value(); QString className = QString::fromUtf8(info.windowClassName()); if (info.name().startsWith(term, Qt::CaseInsensitive) || className.startsWith(term, Qt::CaseInsensitive)) { matches << windowMatch(info, action, 0.8, Plasma::QueryMatch::ExactMatch); } else if ((info.name().contains(term, Qt::CaseInsensitive) || className.contains(term, Qt::CaseInsensitive)) && actionSupported(info, action)) { matches << windowMatch(info, action, 0.7, Plasma::QueryMatch::PossibleMatch); } } // check for matching desktops by name foreach (const QString& desktopName, m_desktopNames) { int desktop = m_desktopNames.indexOf(desktopName) +1; if (desktopName.contains(term, Qt::CaseInsensitive)) { // desktop name matches - offer switch to // only add desktops if it hasn't been added by the keyword which is quite likely if (!desktopAdded && desktop != KWindowSystem::currentDesktop()) { matches << desktopMatch(desktop, 0.8); } // search for windows on desktop and list them with less relevance QHashIterator it(m_windows); while (it.hasNext()) { it.next(); KWindowInfo info = it.value(); if (info.isOnDesktop(desktop) && actionSupported(info, action)) { matches << windowMatch(info, action, 0.5, Plasma::QueryMatch::PossibleMatch); } } } } if (!matches.isEmpty()) { context.addMatches(matches); } } // Called in the main thread void WindowsRunner::run(const Plasma::RunnerContext& context, const Plasma::QueryMatch& match) { QMutexLocker locker(&m_mutex); Q_UNUSED(context) // check if it's a desktop if (match.id().startsWith(QLatin1String("windows_desktop"))) { KWindowSystem::setCurrentDesktop(match.data().toInt()); return; } const QStringList parts = match.data().toString().split(QStringLiteral("_")); WindowAction action = WindowAction(parts[0].toInt()); WId w(parts[1].toULong()); //this is needed since KWindowInfo() doesn't exist, m_windows[w] doesn't work QHash::iterator i = m_windows.find(w); KWindowInfo info = i.value(); switch (action) { case ActivateAction: KWindowSystem::forceActiveWindow(w); break; case CloseAction: { NETRootInfo ri(QX11Info::connection(), NET::CloseWindow); ri.closeWindowRequest(w); break; } case MinimizeAction: if (info.isMinimized()) { KWindowSystem::unminimizeWindow(w); } else { KWindowSystem::minimizeWindow(w); } break; case MaximizeAction: if (info.hasState(NET::Max)) { KWindowSystem::clearState(w, NET::Max); } else { KWindowSystem::setState(w, NET::Max); } break; case FullscreenAction: if (info.hasState(NET::FullScreen)) { KWindowSystem::clearState(w, NET::FullScreen); } else { KWindowSystem::setState(w, NET::FullScreen); } break; case ShadeAction: if (info.hasState(NET::Shaded)) { KWindowSystem::clearState(w, NET::Shaded); } else { KWindowSystem::setState(w, NET::Shaded); } break; case KeepAboveAction: if (info.hasState(NET::KeepAbove)) { KWindowSystem::clearState(w, NET::KeepAbove); } else { KWindowSystem::setState(w, NET::KeepAbove); } break; case KeepBelowAction: if (info.hasState(NET::KeepBelow)) { KWindowSystem::clearState(w, NET::KeepBelow); } else { KWindowSystem::setState(w, NET::KeepBelow); } break; } } Plasma::QueryMatch WindowsRunner::desktopMatch(int desktop, qreal relevance) { Plasma::QueryMatch match(this); match.setType(Plasma::QueryMatch::ExactMatch); match.setData(desktop); match.setId("desktop-" + QString::number(desktop)); - match.setIcon(QIcon::fromTheme(QStringLiteral("user-desktop"))); + match.setIconName(QStringLiteral("user-desktop")); QString desktopName; if (desktop <= m_desktopNames.size()) { desktopName = m_desktopNames[desktop - 1]; } else { desktopName = KWindowSystem::desktopName(desktop); } match.setText(desktopName); match.setSubtext(i18n("Switch to desktop %1", desktop)); match.setRelevance(relevance); return match; } Plasma::QueryMatch WindowsRunner::windowMatch(const KWindowInfo& info, WindowAction action, qreal relevance, Plasma::QueryMatch::Type type) { Plasma::QueryMatch match(this); match.setType(type); match.setData(QString(QString::number((int)action) + "_" + QString::number(info.win()))); match.setIcon(m_icons[info.win()]); match.setText(info.name()); QString desktopName; int desktop = info.desktop(); if (desktop == NET::OnAllDesktops) { desktop = KWindowSystem::currentDesktop(); } if (desktop <= m_desktopNames.size()) { desktopName = m_desktopNames[desktop - 1]; } else { desktopName = KWindowSystem::desktopName(desktop); } switch (action) { case CloseAction: match.setSubtext(i18n("Close running window on %1", desktopName)); break; case MinimizeAction: match.setSubtext(i18n("(Un)minimize running window on %1", desktopName)); break; case MaximizeAction: match.setSubtext(i18n("Maximize/restore running window on %1", desktopName)); break; case FullscreenAction: match.setSubtext(i18n("Toggle fullscreen for running window on %1", desktopName)); break; case ShadeAction: match.setSubtext(i18n("(Un)shade running window on %1", desktopName)); break; case KeepAboveAction: match.setSubtext(i18n("Toggle keep above for running window on %1", desktopName)); break; case KeepBelowAction: match.setSubtext(i18n("Toggle keep below running window on %1", desktopName)); break; case ActivateAction: default: match.setSubtext(i18n("Activate running window on %1", desktopName)); break; } match.setRelevance(relevance); return match; } bool WindowsRunner::actionSupported(const KWindowInfo& info, WindowAction action) { switch (action) { case CloseAction: return info.actionSupported(NET::ActionClose); case MinimizeAction: return info.actionSupported(NET::ActionMinimize); case MaximizeAction: return info.actionSupported(NET::ActionMax); case ShadeAction: return info.actionSupported(NET::ActionShade); case FullscreenAction: return info.actionSupported(NET::ActionFullScreen); case KeepAboveAction: case KeepBelowAction: case ActivateAction: default: return true; } } #include "windowsrunner.moc"