Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package krunner for openSUSE:Factory checked in at 2021-09-16 23:14:11 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/krunner (Old) and /work/SRC/openSUSE:Factory/.krunner.new.1899 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "krunner" Thu Sep 16 23:14:11 2021 rev:93 rq:919214 version:5.86.0 Changes: -------- --- /work/SRC/openSUSE:Factory/krunner/krunner.changes 2021-08-16 10:12:18.119048099 +0200 +++ /work/SRC/openSUSE:Factory/.krunner.new.1899/krunner.changes 2021-09-16 23:16:11.107892318 +0200 @@ -1,0 +2,23 @@ +Wed Sep 15 08:24:17 UTC 2021 - Christophe Giboudeaux <[email protected]> + +- Drop the unneeded baselibs.conf. + +------------------------------------------------------------------- +Mon Sep 6 06:22:18 UTC 2021 - Christophe Giboudeaux <[email protected]> + +- Update to 5.86.0 + * New feature release + * For more details please see: + * https://kde.org/announcements/frameworks/5/5.86.0 +- Changes since 5.85.0: + * replace "MacOSX" with "macOS" + * Port away from KPluginLoader + * Output warning if unknown X-Plasma-API is requested + * Deprecate constructor overload which can not be used with KPluginFactory + * cmake: Remove intermediate copy target + * Use the pointer-to-member-function QObject::connect() signal/slot syntax + * Add snippet on how to port deprecated AbstractRunner action methods + * abstractrunner: Deprecate utility methods for actions + * dbusrunner: Add Teardown and Config methods to D-Bus interface + +------------------------------------------------------------------- Old: ---- baselibs.conf krunner-5.85.0.tar.xz krunner-5.85.0.tar.xz.sig New: ---- krunner-5.86.0.tar.xz krunner-5.86.0.tar.xz.sig ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ krunner.spec ++++++ --- /var/tmp/diff_new_pack.AzVLsI/_old 2021-09-16 23:16:11.663892894 +0200 +++ /var/tmp/diff_new_pack.AzVLsI/_new 2021-09-16 23:16:11.667892897 +0200 @@ -17,7 +17,7 @@ %define lname libKF5Runner5 -%define _tar_path 5.85 +%define _tar_path 5.86 # Full KF5 version (e.g. 5.33.0) %{!?_kf5_version: %global _kf5_version %{version}} # Last major and minor KF5 version (e.g. 5.33) @@ -25,7 +25,7 @@ # Only needed for the package signature condition %bcond_without lang Name: krunner -Version: 5.85.0 +Version: 5.86.0 Release: 0 Summary: KDE Framework for providing different actions given a string query License: LGPL-2.1-or-later @@ -36,7 +36,6 @@ Source1: https://download.kde.org/stable/frameworks/%{_tar_path}/%{name}-%{version}.tar.xz.sig Source2: frameworks.keyring %endif -Source99: baselibs.conf BuildRequires: extra-cmake-modules >= %{_kf5_bugfix_version} BuildRequires: fdupes BuildRequires: kf5-filesystem ++++++ krunner-5.85.0.tar.xz -> krunner-5.86.0.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/krunner-5.85.0/CMakeLists.txt new/krunner-5.86.0/CMakeLists.txt --- old/krunner-5.85.0/CMakeLists.txt 2021-08-04 17:53:33.000000000 +0200 +++ new/krunner-5.86.0/CMakeLists.txt 2021-09-04 17:48:31.000000000 +0200 @@ -1,12 +1,12 @@ cmake_minimum_required(VERSION 3.16) -set(KF_VERSION "5.85.0") # handled by release scripts -set(KF_DEP_VERSION "5.85.0") # handled by release scripts +set(KF_VERSION "5.86.0") # handled by release scripts +set(KF_DEP_VERSION "5.86.0") # handled by release scripts project(KRunner VERSION ${KF_VERSION}) # ECM setup include(FeatureSummary) -find_package(ECM 5.85.0 NO_MODULE) +find_package(ECM 5.86.0 NO_MODULE) set_package_properties(ECM PROPERTIES TYPE REQUIRED DESCRIPTION "Extra CMake Modules." URL "https://commits.kde.org/extra-cmake-modules") feature_summary(WHAT REQUIRED_PACKAGES_NOT_FOUND FATAL_ON_MISSING_REQUIRED_PACKAGES) @@ -38,7 +38,7 @@ ) # Dependencies -set(REQUIRED_QT_VERSION 5.15.0) +set(REQUIRED_QT_VERSION 5.15.2) find_package(Qt5 ${REQUIRED_QT_VERSION} NO_MODULE REQUIRED Gui Widgets Quick) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/krunner-5.85.0/autotests/dbusrunnertest.cpp new/krunner-5.86.0/autotests/dbusrunnertest.cpp --- old/krunner-5.85.0/autotests/dbusrunnertest.cpp 2021-08-04 17:53:33.000000000 +0200 +++ new/krunner-5.86.0/autotests/dbusrunnertest.cpp 2021-09-04 17:48:31.000000000 +0200 @@ -49,6 +49,8 @@ void testRequestActionsOnce(); void testDBusRunnerSyntaxIntegration(); void testIconData(); + void testLifecycleMethods(); + void testRequestActionsOnceWildcards(); #if WITH_KSERVICE void testMulti_data(); #endif @@ -170,8 +172,9 @@ fakeMatch.setId(QStringLiteral("dbusrunnertest_id1")); fakeMatch.setData(QVariantList({QStringLiteral("net.krunnertests.dave"), QStringList({QStringLiteral("action1"), QStringLiteral("action2")})})); - // We haven't called the prepare slot or launched a query, if the implementation works - // the actions should already be available + // The actions should not be fetched before we have set up the match session + QCOMPARE(manager->actionsForMatch(fakeMatch).count(), 0); + launchQuery(QStringLiteral("foo")); // We need to retry this, because the DBus call to fetch the actions is async QTRY_COMPARE_WITH_TIMEOUT(manager->actionsForMatch(fakeMatch).count(), 2, 2500); } @@ -235,6 +238,62 @@ QCOMPARE(result.icon().pixmap(QSize(10, 10)), QPixmap::fromImage(expectedIcon)); } +void DBusRunnerTest::testLifecycleMethods() +{ + QProcess *process = startDBusRunnerProcess({QStringLiteral("net.krunnertests.dave"), QString()}); + manager.reset(new RunnerManager()); // This case is special, because we want to load the runners manually + auto md = KPluginMetaData::fromDesktopFile(QFINDTESTDATA("dbusrunnertestruntimeconfig.desktop"), {QStringLiteral("plasma-runner.desktop")}); + manager->loadRunner(md); + QCOMPARE(manager->runners().count(), 1); + // Match session should be set up automatically + launchQuery(QStringLiteral("fooo")); + + // Make sure we got our match, end the match session and give the process a bit of time to get the DBus signal + QTRY_COMPARE_WITH_TIMEOUT(manager->matches().count(), 1, 2000); + manager->matchSessionComplete(); + QTest::qWait(500); + + const QStringList lifeCycleSteps = QString::fromLocal8Bit(process->readAllStandardOutput()).split(QLatin1Char('\n'), Qt::SkipEmptyParts); + const QStringList expectedLifeCycleSteps = { + QStringLiteral("Config"), + QStringLiteral("Matching:fooo"), + QStringLiteral("Teardown"), + }; + QCOMPARE(lifeCycleSteps, expectedLifeCycleSteps); + + // The query does not match our min letter count we set at runtime + launchQuery(QStringLiteral("foo")); + QVERIFY(manager->matches().isEmpty()); + // The query does not match our match regex we set at runtime + launchQuery(QStringLiteral("barfoo")); + QVERIFY(manager->matches().isEmpty()); +} + +void DBusRunnerTest::testRequestActionsOnceWildcards() +{ + initProperties(); + manager.reset(new RunnerManager()); // This case is special, because we want to load the runners manually + auto md = KPluginMetaData::fromDesktopFile(QFINDTESTDATA("dbusrunnertestmulti.desktop"), {QStringLiteral("plasma-runner.desktop")}); + QVERIFY(md.isValid()); + manager->loadRunner(md); + QCOMPARE(manager->runners().count(), 1); + launchQuery("foo"); + QVERIFY(manager->matches().isEmpty()); + QueryMatch match(manager->runners().constFirst()); + match.setId("test"); + match.setData(QStringList{"net.krunnertests.multi.a1"}); + QVERIFY(manager->actionsForMatch(match).isEmpty()); + manager->matchSessionComplete(); + + // We have started the process later and the actions should now be fetched when the match session is started + startDBusRunnerProcess({QStringLiteral("net.krunnertests.multi.a1")}, QStringLiteral("net.krunnertests.multi.a1")); + QTest::qWait(500); // Wait a bit for the runner to pick up the new service + + launchQuery("fooo"); + QVERIFY(!manager->matches().isEmpty()); + QVERIFY(!manager->actionsForMatch(match).isEmpty()); +} + QTEST_MAIN(DBusRunnerTest) #include "dbusrunnertest.moc" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/krunner-5.85.0/autotests/dbusrunnertestruntimeconfig.desktop new/krunner-5.86.0/autotests/dbusrunnertestruntimeconfig.desktop --- old/krunner-5.85.0/autotests/dbusrunnertestruntimeconfig.desktop 1970-01-01 01:00:00.000000000 +0100 +++ new/krunner-5.86.0/autotests/dbusrunnertestruntimeconfig.desktop 2021-09-04 17:48:31.000000000 +0200 @@ -0,0 +1,18 @@ +[Desktop Entry] +Name=DBus runner test +Comment=DBus runner test +X-KDE-ServiceTypes=Plasma/Runner +Type=Service +Icon=internet-web-browser +X-KDE-PluginInfo-Author=Some Developer [email protected] +X-KDE-PluginInfo-Name=dbusrunnertest +X-KDE-PluginInfo-Version=1.0 +X-KDE-PluginInfo-License=LGPL +X-KDE-PluginInfo-EnabledByDefault=true +X-Plasma-API=DBus2 +X-Plasma-DBusRunner-Service=net.krunnertests.dave +X-Plasma-DBusRunner-Path=/dave +X-Plasma-Request-Actions-Once=true +X-Plasma-Runner-Syntaxes=syntax1,syntax2 +X-Plasma-Runner-Syntax-Descriptions=description1,description2 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/krunner-5.85.0/autotests/testremoterunner.cpp new/krunner-5.86.0/autotests/testremoterunner.cpp --- old/krunner-5.85.0/autotests/testremoterunner.cpp 2021-08-04 17:53:33.000000000 +0200 +++ new/krunner-5.86.0/autotests/testremoterunner.cpp 2021-09-04 17:48:31.000000000 +0200 @@ -17,7 +17,7 @@ // Test DBus runner, if the search term contains "foo" it returns a match, otherwise nothing // Run prints a line to stdout -TestRemoteRunner::TestRemoteRunner(const QString &serviceName) +TestRemoteRunner::TestRemoteRunner(const QString &serviceName, bool showLifecycleMethodCalls) { new Krunner1Adaptor(this); qDBusRegisterMetaType<RemoteMatch>(); @@ -27,6 +27,7 @@ qDBusRegisterMetaType<RemoteImage>(); Q_ASSERT(QDBusConnection::sessionBus().registerService(serviceName)); Q_ASSERT(QDBusConnection::sessionBus().registerObject(QStringLiteral("/dave"), this)); + m_showLifecycleMethodCalls = showLifecycleMethodCalls; } static RemoteImage serializeImage(const QImage &image) @@ -90,11 +91,32 @@ std::cout.flush(); } +void TestRemoteRunner::Teardown() +{ + if (m_showLifecycleMethodCalls) { + std::cout << "Teardown" << std::endl; + std::cout.flush(); + } +} + +QVariantMap TestRemoteRunner::Config() +{ + if (m_showLifecycleMethodCalls) { + std::cout << "Config" << std::endl; + std::cout.flush(); + } + + return { + {"MatchRegex", "^fo"}, + {"MinLetterCount", 4}, + }; +} + int main(int argc, char **argv) { QCoreApplication app(argc, argv); const auto arguments = app.arguments(); - Q_ASSERT(arguments.count() == 2); - TestRemoteRunner r(arguments[1]); + Q_ASSERT(arguments.count() >= 2); + TestRemoteRunner r(arguments[1], arguments.count() == 3); app.exec(); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/krunner-5.85.0/autotests/testremoterunner.h new/krunner-5.86.0/autotests/testremoterunner.h --- old/krunner-5.85.0/autotests/testremoterunner.h 2021-08-04 17:53:33.000000000 +0200 +++ new/krunner-5.86.0/autotests/testremoterunner.h 2021-09-04 17:48:31.000000000 +0200 @@ -2,15 +2,21 @@ #include "../src/dbusutils_p.h" #include <QObject> +#include <QVariantMap> class TestRemoteRunner : public QObject { Q_OBJECT public: - explicit TestRemoteRunner(const QString &serviceName); + explicit TestRemoteRunner(const QString &serviceName, bool showLifecycleMethodCalls); public Q_SLOTS: RemoteActions Actions(); RemoteMatches Match(const QString &searchTerm); void Run(const QString &id, const QString &actionId); + void Teardown(); + QVariantMap Config(); + +private: + bool m_showLifecycleMethodCalls = false; }; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/krunner-5.85.0/metainfo.yaml new/krunner-5.86.0/metainfo.yaml --- old/krunner-5.85.0/metainfo.yaml 2021-08-04 17:53:33.000000000 +0200 +++ new/krunner-5.86.0/metainfo.yaml 2021-09-04 17:48:31.000000000 +0200 @@ -6,7 +6,7 @@ - name: Linux - name: FreeBSD - name: Windows - - name: MacOSX + - name: macOS portingAid: false deprecated: false release: true diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/krunner-5.85.0/src/CMakeLists.txt new/krunner-5.86.0/src/CMakeLists.txt --- old/krunner-5.85.0/src/CMakeLists.txt 2021-08-04 17:53:33.000000000 +0200 +++ new/krunner-5.86.0/src/CMakeLists.txt 2021-09-04 17:48:31.000000000 +0200 @@ -36,7 +36,7 @@ GROUP_BASE_NAME KF VERSION ${KF_VERSION} DEPRECATED_BASE_VERSION 0 - DEPRECATION_VERSIONS 5.28 5.71 5.72 5.73 5.76 5.77 5.79 5.81 5.82 5.85 + DEPRECATION_VERSIONS 5.28 5.71 5.72 5.73 5.76 5.77 5.79 5.81 5.82 5.85 5.86 EXCLUDE_DEPRECATED_BEFORE_AND_AT ${EXCLUDE_DEPRECATED_BEFORE_AND_AT} ) @@ -103,13 +103,11 @@ data/servicetypes/plasma-runner.desktop DESTINATION ${KDE_INSTALL_KSERVICETYPES5DIR}) -add_custom_target(copy_servicetypes) file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/bin/data/kservicetypes5) -add_custom_command(TARGET copy_servicetypes PRE_BUILD COMMAND +add_custom_command(TARGET KF5Runner PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/data/servicetypes/plasma-runner.desktop ${CMAKE_BINARY_DIR}/bin/data/kservicetypes5) -add_dependencies(KF5Runner copy_servicetypes) ecm_qt_install_logging_categories( EXPORT KRUNNER diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/krunner-5.85.0/src/abstractrunner.cpp new/krunner-5.86.0/src/abstractrunner.cpp --- old/krunner-5.85.0/src/abstractrunner.cpp 2021-08-04 17:53:33.000000000 +0200 +++ new/krunner-5.86.0/src/abstractrunner.cpp 2021-09-04 17:48:31.000000000 +0200 @@ -32,12 +32,14 @@ } #endif +#if KRUNNER_BUILD_DEPRECATED_SINCE(5, 86) AbstractRunner::AbstractRunner(const KPluginMetaData &pluginMetaData, QObject *parent) : QObject(parent) , d(new AbstractRunnerPrivate(this)) { d->init(pluginMetaData); } +#endif #if KRUNNER_BUILD_DEPRECATED_SINCE(5, 72) && KSERVICE_BUILD_DEPRECATED_SINCE(5, 0) AbstractRunner::AbstractRunner(const KService::Ptr service, QObject *parent) @@ -184,6 +186,7 @@ return match.isValid() ? match.actions() : QList<QAction *>(); } +#if KRUNNER_BUILD_DEPRECATED_SINCE(5, 86) QAction *AbstractRunner::addAction(const QString &id, const QIcon &icon, const QString &text) { QAction *a = new QAction(icon, text, this); @@ -217,6 +220,7 @@ qDeleteAll(d->actions); d->actions.clear(); } +#endif QMimeData *AbstractRunner::mimeDataForMatch(const QueryMatch &match) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/krunner-5.85.0/src/abstractrunner.h new/krunner-5.86.0/src/abstractrunner.h --- old/krunner-5.85.0/src/abstractrunner.h 2021-08-04 17:53:33.000000000 +0200 +++ new/krunner-5.86.0/src/abstractrunner.h 2021-09-04 17:48:31.000000000 +0200 @@ -441,6 +441,15 @@ friend class RunnerManager; friend class RunnerManagerPrivate; + /** + * Constructor for a KRunner plugin + * @param parent parent object for this runner + * @param pluginMetaData metadata that was embedded in the runner + * @param args for compatibility with KPluginFactory, should be passed on to the parent constructor + * @since 5.72 + */ + AbstractRunner(QObject *parent, const KPluginMetaData &pluginMetaData, const QVariantList &args); + #if KRUNNER_ENABLE_DEPRECATED_SINCE(5, 77) KRUNNER_DEPRECATED_VERSION(5, 77, "use AbstractRunner(QObject *, const KPluginMetaData &, const QVariantList &)") explicit AbstractRunner(QObject *parent = nullptr, const QString &path = QString()); @@ -455,10 +464,10 @@ explicit AbstractRunner(const KService::Ptr service, QObject *parent = nullptr); #endif #endif +#if KRUNNER_ENABLE_DEPRECATED_SINCE(5, 86) /// @since 5.72 explicit AbstractRunner(const KPluginMetaData &pluginMetaData, QObject *parent = nullptr); - /// @since 5.77 - AbstractRunner(QObject *parent, const KPluginMetaData &pluginMetaData, const QVariantList &args); +#endif #if KRUNNER_ENABLE_DEPRECATED_SINCE(5, 77) /// @deprecated Since 5.77, use AbstractRunner(QObject *, const KPluginMetaData &, const QVariantList &) KRUNNER_DEPRECATED_VERSION(5, 77, "use AbstractRunner(QObject *, const KPluginMetaData &, const QVariantList &)") @@ -517,15 +526,30 @@ */ virtual QList<QAction *> actionsForMatch(const Plasma::QueryMatch &match); +#if KRUNNER_ENABLE_DEPRECATED_SINCE(5, 86) /** * Creates and then adds an action to the action registry. * AbstractRunner assumes ownership of the created action. * + * @see QueryMatch::setActions + * @see actionsForMatch + * * @param id A unique identifier string * @param icon The icon to display * @param text The text to display * @return the created QAction + * @deprecated Since 5.86 create the QAction instance manually + * @code + * // in the runner class definition + * QList<QAction *> m_actions; + * // when initializing the runner, optionally set the date if needed + * auto action = new QAction(QIcon::fromTheme(iconName), text, this); + * m_actions << action; + * // when creating the match + * match.setActions(m_actions); + * @endcode */ + KRUNNER_DEPRECATED_VERSION(5, 86, "create the QAction instance manually") QAction *addAction(const QString &id, const QIcon &icon, const QString &text); /** @@ -536,7 +560,9 @@ * * @param id A unique identifier string * @param action The QAction to be stored + * @deprecated Since 5.86, create the QAction instance manually */ + KRUNNER_DEPRECATED_VERSION(5, 86, "create the QAction instance manually") void addAction(const QString &id, QAction *action); /** @@ -544,24 +570,33 @@ * AbstractRunner deletes the action once removed. * * @param id The id of the action to be removed + * @deprecated Since 5.86, deprecated for lack of usage */ + KRUNNER_DEPRECATED_VERSION(5, 86, "deprecated for lack of usage") void removeAction(const QString &id); /** * Returns the action associated with the id + * @deprecated Since 5.86, create the QAction instances manually and store them in a custom container instead */ + KRUNNER_DEPRECATED_VERSION(5, 86, "create the QAction instances manually and store them in a custom container instead") QAction *action(const QString &id) const; /** * Returns all registered actions + * @deprecated Since 5.86, create the QAction instances manually and store them in a custom container instead */ + KRUNNER_DEPRECATED_VERSION(5, 86, "create the QAction instances manually and store them in a custom container instead") QHash<QString, QAction *> actions() const; /** * Clears the action registry. * The action pool deletes the actions. + * @deprecated Since 5.86, use a custom container to store the QAction instances instead */ + KRUNNER_DEPRECATED_VERSION(5, 86, "use a custom container to store the QAction instances instead") void clearActions(); +#endif /** * Adds a registered syntax that this runner understands. This is used to diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/krunner-5.85.0/src/abstractrunnertest.h new/krunner-5.86.0/src/abstractrunnertest.h --- old/krunner-5.85.0/src/abstractrunnertest.h 2021-08-04 17:53:33.000000000 +0200 +++ new/krunner-5.86.0/src/abstractrunnertest.h 2021-09-04 17:48:31.000000000 +0200 @@ -3,7 +3,9 @@ SPDX-License-Identifier: LGPL-2.0-or-later */ -#include <KPluginLoader> +#ifndef PLASMA_ABSTRACTRUNNERTEST_H +#define PLASMA_ABSTRACTRUNNERTEST_H + #include <KPluginMetaData> #include <KRunner/AbstractRunner> #include <KRunner/RunnerManager> @@ -43,13 +45,12 @@ QVERIFY(md.isValid()); manager->loadRunner(md); #else - auto pluginMetaDatas = KPluginLoader::findPluginsById(QStringLiteral(KRUNNER_TEST_RUNNER_PLUGIN_DIR), - QFileInfo(QStringLiteral(KRUNNER_TEST_RUNNER_PLUGIN_NAME)).baseName()); - QCOMPARE(pluginMetaDatas.count(), 1); - KPluginMetaData runnerMetadata = pluginMetaDatas.first(); + auto metaData = KPluginMetaData::findPluginById(QStringLiteral(KRUNNER_TEST_RUNNER_PLUGIN_DIR), + QFileInfo(QStringLiteral(KRUNNER_TEST_RUNNER_PLUGIN_NAME)).baseName()); + QVERIFY(metaData.isValid()); // Set internal variables - manager->loadRunner(runnerMetadata); + manager->loadRunner(metaData); #endif QCOMPARE(manager->runners().count(), 1); runner = manager->runners().constFirst(); @@ -102,7 +103,7 @@ */ void killRunningDBusProcesses() { - for (auto &process : qAsConst(m_runningProcesses)) { + for (auto &process : std::as_const(m_runningProcesses)) { process->kill(); QVERIFY(process->waitForFinished()); } @@ -115,3 +116,5 @@ #endif }; } + +#endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/krunner-5.85.0/src/data/org.kde.krunner1.xml new/krunner-5.86.0/src/data/org.kde.krunner1.xml --- old/krunner-5.85.0/src/data/org.kde.krunner1.xml 2021-08-04 17:53:33.000000000 +0200 +++ new/krunner-5.86.0/src/data/org.kde.krunner1.xml 2021-09-04 17:48:31.000000000 +0200 @@ -1,6 +1,30 @@ <!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> <node> <interface name="org.kde.krunner1"> + <!-- + This method gets called when a match session is over. + It can be used to clear data which should not be kept in memory after a match session. + --> + <method name="Teardown"/> + + <!-- + This method can be used to set runner config at runtime. In case the service wildcard is used + the config is only for one service requested. + It gets only called when the X-Plasma-Api value is set to DBus2 + + Possible values for the response map are: + MatchRegex (String) + MinLetterCount (int) + TriggerWords (StringList) + Actions (RemoteActions), see X-Plasma-Request-Actions-Once property docs + + See API documentation of the AbstractRunner class for details about these values. + --> + <method name="Config"> + <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QVariantMap" /> + <arg name="config" type="{sv}" direction="out"> + </arg> + </method> <!-- Returns a list of actions supported by this runner. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/krunner-5.85.0/src/dbusrunner.cpp new/krunner-5.86.0/src/dbusrunner.cpp --- old/krunner-5.85.0/src/dbusrunner.cpp 2021-08-04 17:53:33.000000000 +0200 +++ new/krunner-5.86.0/src/dbusrunner.cpp 2021-09-04 17:48:31.000000000 +0200 @@ -16,24 +16,27 @@ #include <QDBusPendingReply> #include <QIcon> #include <QMutexLocker> +#include <qobjectdefs.h> #include "dbusutils_p.h" #include "krunner_debug.h" #define IFACE_NAME "org.kde.krunner1" -DBusRunner::DBusRunner(const KPluginMetaData &pluginMetaData, QObject *parent) - : Plasma::AbstractRunner(pluginMetaData, parent) +DBusRunner::DBusRunner(QObject *parent, const KPluginMetaData &pluginMetaData, const QVariantList &args) + : Plasma::AbstractRunner(parent, pluginMetaData, args) { qDBusRegisterMetaType<RemoteMatch>(); qDBusRegisterMetaType<RemoteMatches>(); qDBusRegisterMetaType<RemoteAction>(); qDBusRegisterMetaType<RemoteActions>(); qDBusRegisterMetaType<RemoteImage>(); + qRegisterMetaType<QMap<QString, RemoteActions>>(); QString requestedServiceName = pluginMetaData.value(QStringLiteral("X-Plasma-DBusRunner-Service")); m_path = pluginMetaData.value(QStringLiteral("X-Plasma-DBusRunner-Path")); m_hasUniqueResults = pluginMetaData.rawData().value(QStringLiteral("X-Plasma-Runner-Unique-Results")).toBool(); + m_callLifecycleMethods = pluginMetaData.value(QStringLiteral("X-Plasma-API")) == QLatin1String("DBus2"); if (requestedServiceName.isEmpty() || m_path.isEmpty()) { qCWarning(KRUNNER) << "Invalid entry:" << pluginMetaData.name(); @@ -76,11 +79,9 @@ // don't check when not wildcarded, as it could be used with DBus-activation m_matchingServices << requestedServiceName; } - if (pluginMetaData.rawData().value(QStringLiteral("X-Plasma-Request-Actions-Once")).toVariant().toBool()) { - requestActions(); - } else { - connect(this, &AbstractRunner::prepare, this, &DBusRunner::requestActions); - } + + m_requestActionsOnce = pluginMetaData.rawData().value(QStringLiteral("X-Plasma-Request-Actions-Once")).toVariant().toBool(); + connect(this, &AbstractRunner::teardown, this, &DBusRunner::teardown); // Load the runner syntaxes const QStringList syntaxes = pluginMetaData.rawData().value(QStringLiteral("X-Plasma-Runner-Syntaxes")).toVariant().toStringList(); @@ -95,34 +96,103 @@ DBusRunner::~DBusRunner() = default; -void DBusRunner::requestActions() +void DBusRunner::reloadConfiguration() +{ + // If we have already loaded a config, but the runner is told to reload it's config + if (m_callLifecycleMethods) { + suspendMatching(true); + requestConfig(); + } +} + +void DBusRunner::createQActionsFromRemoteActions(const QMap<QString, RemoteActions> remoteActions) { - clearActions(); - m_actions.clear(); + for (auto it = remoteActions.begin(), end = remoteActions.end(); it != end; it++) { + const QString service = it.key(); + const RemoteActions actions = it.value(); + qDeleteAll(m_actions[service]); + m_actions[service].clear(); + for (const RemoteAction &action : actions) { + auto a = new QAction(QIcon::fromTheme(action.iconName), action.text); + a->setData(action.id); + m_actions[service].append(a); + } + } +} + +void DBusRunner::teardown() +{ + if (m_matchWasCalled) { + for (const QString &service : std::as_const(m_matchingServices)) { + auto method = QDBusMessage::createMethodCall(service, m_path, QStringLiteral(IFACE_NAME), QStringLiteral("Teardown")); + QDBusConnection::sessionBus().asyncCall(method); + } + } + m_actionsForSessionRequested = false; + m_matchWasCalled = false; +} +QMap<QString, RemoteActions> DBusRunner::requestActions() +{ // in the multi-services case, register separate actions from each plugin in case they happen to be somehow different // then match together in matchForAction() + QMap<QString, RemoteActions> returnedActions; + for (const QString &service : std::as_const(m_matchingServices)) { + // if we only want to request the actions once and have done so we want to skip the service + // but in case it got newly loaded we need to request the actions, BUG: 435350 + if (m_requestActionsOnce) { + if (m_requestedActionServices.contains(service)) { + continue; + } else { + m_requestedActionServices << service; + } + } - for (const QString &service : qAsConst(m_matchingServices)) { auto getActionsMethod = QDBusMessage::createMethodCall(service, m_path, QStringLiteral(IFACE_NAME), QStringLiteral("Actions")); - QDBusPendingReply<RemoteActions> reply = QDBusConnection::sessionBus().asyncCall(getActionsMethod); + QDBusPendingReply<RemoteActions> reply = QDBusConnection::sessionBus().call(getActionsMethod); + if (!reply.isValid()) { + qCDebug(KRUNNER) << "Error requesting actions; calling" << service << " :" << reply.error().name() << reply.error().message(); + } else { + returnedActions.insert(service, reply.value()); + } + } + return returnedActions; +} - auto watcher = new QDBusPendingCallWatcher(reply); - connect(watcher, &QDBusPendingCallWatcher::finished, this, [this, watcher, service]() { - watcher->deleteLater(); - QDBusReply<RemoteActions> reply = *watcher; - if (!reply.isValid()) { - qCDebug(KRUNNER) << "Error requestion actions; calling" << service << " :" << reply.error().name() << reply.error().message(); - return; - } - const auto actions = reply.value(); - for (const RemoteAction &action : actions) { - auto a = addAction(action.id, QIcon::fromTheme(action.iconName), action.text); - a->setData(action.id); - m_actions[service].append(a); +void DBusRunner::requestConfig() +{ + const QString service = *m_matchingServices.constBegin(); + auto getConfigMethod = QDBusMessage::createMethodCall(service, m_path, QStringLiteral(IFACE_NAME), QStringLiteral("Config")); + QDBusPendingReply<QVariantMap> reply = QDBusConnection::sessionBus().asyncCall(getConfigMethod); + + auto watcher = new QDBusPendingCallWatcher(reply); + connect(watcher, &QDBusPendingCallWatcher::finished, this, [this, watcher, service]() { + watcher->deleteLater(); + QDBusReply<QVariantMap> reply = *watcher; + if (!reply.isValid()) { + suspendMatching(false); + qCDebug(KRUNNER) << "Error requesting config; calling" << service << " :" << reply.error().name() << reply.error().message(); + return; + } + const QVariantMap config = reply.value(); + for (auto it = config.cbegin(), end = config.cend(); it != end; ++it) { + if (it.key() == QLatin1String("MatchRegex")) { + QRegularExpression regex(it.value().toString()); + regex.optimize(); + setMatchRegex(regex); + } else if (it.key() == QLatin1String("MinLetterCount")) { + setMinLetterCount(it.value().toInt()); + } else if (it.key() == QLatin1String("TriggerWords")) { + setTriggerWords(it.value().toStringList()); + } else if (it.key() == QLatin1String("Actions")) { + const auto remoteActions = it.value().value<RemoteActions>(); + createQActionsFromRemoteActions(QMap<QString, RemoteActions>{{service, remoteActions}}); + m_actionsOnceRequested = true; + m_actionsForSessionRequested = true; } - }); - } + } + suspendMatching(false); + }); } void DBusRunner::match(Plasma::RunnerContext &context) @@ -131,11 +201,22 @@ { QMutexLocker lock(&m_mutex); services = m_matchingServices; + m_matchWasCalled = true; + + // Request the actions + if ((m_requestActionsOnce && !m_actionsOnceRequested) // We only want to fetch the actions once but haven't done so yet + || (!m_actionsForSessionRequested)) { // We want to fetch the actions for each match session + m_actionsOnceRequested = true; + m_actionsForSessionRequested = true; + auto actions = requestActions(); + const auto actionsArg = QArgument<QMap<QString, RemoteActions>>("QMap<QString, RemoteActions>", actions); + QMetaObject::invokeMethod(this, "createQActionsFromRemoteActions", actionsArg); + } } // we scope watchers to make sure the lambda that captures context by reference definitely gets disconnected when this function ends QList<QSharedPointer<QDBusPendingCallWatcher>> watchers; - for (const QString &service : qAsConst(services)) { + for (const QString &service : std::as_const(services)) { auto matchMethod = QDBusMessage::createMethodCall(service, m_path, QStringLiteral(IFACE_NAME), QStringLiteral("Match")); matchMethod.setArguments(QList<QVariant>({context.query()})); QDBusPendingReply<RemoteMatches> reply = QDBusConnection::sessionBus().asyncCall(matchMethod); @@ -196,7 +277,7 @@ Qt::DirectConnection); // process reply in the watcher's thread (aka the one running ::match not the one owning the runner) } // we're done matching when every service replies - for (auto w : qAsConst(watchers)) { + for (auto w : std::as_const(watchers)) { w->waitForFinished(); } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/krunner-5.85.0/src/dbusrunner_p.h new/krunner-5.86.0/src/dbusrunner_p.h --- old/krunner-5.85.0/src/dbusrunner_p.h 2021-08-04 17:53:33.000000000 +0200 +++ new/krunner-5.86.0/src/dbusrunner_p.h 2021-09-04 17:48:31.000000000 +0200 @@ -20,20 +20,33 @@ Q_OBJECT public: - explicit DBusRunner(const KPluginMetaData &pluginMetaData, QObject *parent = nullptr); + explicit DBusRunner(QObject *parent, const KPluginMetaData &pluginMetaData, const QVariantList &args); ~DBusRunner() override; void match(Plasma::RunnerContext &context) override; + void reloadConfiguration() override; void run(const Plasma::RunnerContext &context, const Plasma::QueryMatch &action) override; QList<QAction *> actionsForMatch(const Plasma::QueryMatch &match) override; +public Q_SLOTS: + void teardown(); + // This method should only be called from the main thread! + void createQActionsFromRemoteActions(const QMap<QString, RemoteActions> remoteActions); + private: - void requestActions(); - void setActions(const RemoteActions &remoteActions); + // Returns RemoteActions with service name as key + QMap<QString, RemoteActions> requestActions(); + void requestConfig(); static QImage decodeImage(const RemoteImage &remoteImage); QMutex m_mutex; // needed round any variable also accessed from Match QString m_path; QSet<QString> m_matchingServices; QHash<QString, QList<QAction *>> m_actions; bool m_hasUniqueResults = false; + bool m_requestActionsOnce = false; + bool m_actionsOnceRequested = false; + bool m_actionsForSessionRequested = false; + bool m_matchWasCalled = false; + bool m_callLifecycleMethods = false; + QSet<QString> m_requestedActionServices; }; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/krunner-5.85.0/src/runnercontext.cpp new/krunner-5.86.0/src/runnercontext.cpp --- old/krunner-5.85.0/src/runnercontext.cpp 2021-08-04 17:53:33.000000000 +0200 +++ new/krunner-5.86.0/src/runnercontext.cpp 2021-09-04 17:48:31.000000000 +0200 @@ -393,7 +393,7 @@ QList<QueryMatch> presentMatchList; LOCK_FOR_READ(d) - for (const QueryMatch &match : qAsConst(d->matches)) { + for (const QueryMatch &match : std::as_const(d->matches)) { if (match.runner() == runner) { presentMatchList << match; } @@ -405,7 +405,7 @@ } LOCK_FOR_WRITE(d) - for (const QueryMatch &match : qAsConst(presentMatchList)) { + for (const QueryMatch &match : std::as_const(presentMatchList)) { d->matches.removeAll(match); } UNLOCK(d) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/krunner-5.85.0/src/runnermanager.cpp new/krunner-5.86.0/src/runnermanager.cpp --- old/krunner-5.85.0/src/runnermanager.cpp 2021-08-04 17:53:33.000000000 +0200 +++ new/krunner-5.86.0/src/runnermanager.cpp 2021-09-04 17:48:31.000000000 +0200 @@ -63,9 +63,15 @@ matchChangeTimer.setSingleShot(true); delayTimer.setSingleShot(true); - QObject::connect(&matchChangeTimer, SIGNAL(timeout()), q, SLOT(matchesChanged())); - QObject::connect(&context, SIGNAL(matchesChanged()), q, SLOT(scheduleMatchesChanged())); - QObject::connect(&delayTimer, SIGNAL(timeout()), q, SLOT(unblockJobs())); + QObject::connect(&matchChangeTimer, &QTimer::timeout, q, [this]() { + matchesChanged(); + }); + QObject::connect(&context, &RunnerContext::matchesChanged, q, [this]() { + scheduleMatchesChanged(); + }); + QObject::connect(&delayTimer, &QTimer::timeout, q, [this]() { + unblockJobs(); + }); // Set up tracking of the last time matchesChanged was signalled lastMatchChangeSignalled.start(); @@ -217,7 +223,7 @@ while (it != searchJobs.end()) { auto &job = (*it); if (deadRunners.contains(job->runner())) { - QObject::disconnect(job.data(), SIGNAL(done(ThreadWeaver::JobPointer)), q, SLOT(jobDone(ThreadWeaver::JobPointer))); + QObject::disconnect(job.data(), &FindMatchesJob::done, q, nullptr); it = searchJobs.erase(it); deadJobs.insert(job); } else { @@ -260,8 +266,6 @@ const QString api = pluginMetaData.value(QStringLiteral("X-Plasma-API")); if (api.isEmpty()) { - KPluginLoader pluginLoader(pluginMetaData.fileName()); - if (KPluginFactory *factory = pluginLoader.factory()) { const QVariantList args { #if KRUNNER_BUILD_DEPRECATED_SINCE(5, 77) @@ -271,19 +275,24 @@ QVariant::fromValue(pluginMetaData), #endif }; - runner = factory->create<AbstractRunner>(q, args); - } else { - qCWarning(KRUNNER).nospace() << "Could not load runner " << pluginMetaData.name() << ":" << pluginLoader.errorString() - << " (library path was:" << pluginMetaData.fileName() << ")"; - } - } else if (api == QLatin1String("DBus")) { - runner = new DBusRunner(pluginMetaData, q); + auto res = KPluginFactory::instantiatePlugin<AbstractRunner>(pluginMetaData, q, args); + if (res) { + runner = res.plugin; + } else { + qCWarning(KRUNNER).nospace() << "Could not load runner " << pluginMetaData.name() << ":" << res.errorString + << " (library path was:" << pluginMetaData.fileName() << ")"; + } + } else if (api.startsWith(QLatin1String("DBus"))) { + runner = new DBusRunner(q, pluginMetaData, {}); } else { - runner = new AbstractRunner(pluginMetaData, q); + qCWarning(KRUNNER) << "Unknown X-Plasma-API requested for runner" << pluginMetaData.fileName(); + return nullptr; } if (runner) { - QObject::connect(runner, SIGNAL(matchingSuspended(bool)), q, SLOT(runnerMatchingSuspended(bool))); + QObject::connect(runner, &AbstractRunner::matchingSuspended, q, [this](bool state) { + runnerMatchingSuspended(state); + }); runner->init(); if (prepped) { Q_EMIT runner->prepare(); @@ -328,7 +337,7 @@ if (searchJobs.isEmpty() && oldSearchJobs.isEmpty()) { if (allRunnersPrepped) { - for (AbstractRunner *runner : qAsConst(runners)) { + for (AbstractRunner *runner : std::as_const(runners)) { Q_EMIT runner->teardown(); } @@ -361,12 +370,16 @@ void runnerMatchingSuspended(bool suspended) { - if (suspended || !prepped || teardownRequested) { + auto *runner = qobject_cast<AbstractRunner *>(q->sender()); + if (suspended || !prepped || teardownRequested || !runner) { return; } - if (auto *runner = qobject_cast<AbstractRunner *>(q->sender())) { - startJob(runner); + const QString query = context.query(); + if (singleMode || runner->minLetterCount() <= query.size()) { + if (singleMode || !runner->hasMatchRegex() || runner->matchRegex().match(query).hasMatch()) { + startJob(runner); + } } } @@ -378,7 +391,9 @@ } #endif QSharedPointer<FindMatchesJob> job(new FindMatchesJob(runner, &context, Queue::instance())); - QObject::connect(job.data(), SIGNAL(done(ThreadWeaver::JobPointer)), q, SLOT(jobDone(ThreadWeaver::JobPointer))); + QObject::connect(job.data(), &FindMatchesJob::done, q, [this](ThreadWeaver::JobPointer jobPtr) { + jobDone(jobPtr); + }); #if KRUNNER_BUILD_DEPRECATED_SINCE(5, 81) if (runner->speed() == AbstractRunner::SlowSpeed) { @@ -441,7 +456,7 @@ historyEntries.removeOne(a); } - for (const QString &deletedActivity : qAsConst(historyEntries)) { + for (const QString &deletedActivity : std::as_const(historyEntries)) { historyGroup.deleteEntry(deletedActivity); } historyGroup.sync(); @@ -568,7 +583,7 @@ QStringList list = d->stateData.readEntry("enabledCategories", QStringList()); if (list.isEmpty()) { list.reserve(d->runners.count()); - for (AbstractRunner *runner : qAsConst(d->runners)) { + for (AbstractRunner *runner : std::as_const(d->runners)) { list << runner->categories(); } } @@ -604,7 +619,9 @@ { if (!d->runners.contains(path)) { AbstractRunner *runner = new AbstractRunner(this, path); - connect(runner, SIGNAL(matchingSuspended(bool)), this, SLOT(runnerMatchingSuspended(bool))); + connect(runner, &AbstractRunner::matchingSuspended, this, [this](bool state) { + d->runnerMatchingSuspended(state); + }); d->runners.insert(path, runner); } } @@ -666,7 +683,7 @@ QStringList RunnerManager::singleModeAdvertisedRunnerIds() const { QStringList advertiseSingleRunnerIds; - for (auto *runner : qAsConst(d->runners)) { + for (auto *runner : std::as_const(d->runners)) { if (runner->metadata(RunnerReturnPluginMetaData).rawData().value(QStringLiteral("X-Plasma-AdvertiseSingleRunnerQueryMode")).toVariant().toBool()) { advertiseSingleRunnerIds << runner->id(); } @@ -754,10 +771,10 @@ return md.value(QStringLiteral("X-KDE-ParentApp")) == parentApp; }; - QVector<KPluginMetaData> pluginMetaDatas = KPluginLoader::findPlugins(QStringLiteral("kf5/krunner"), filterParentApp); + QVector<KPluginMetaData> pluginMetaDatas = KPluginMetaData::findPlugins(QStringLiteral("kf5/krunner"), filterParentApp); QSet<QString> knownRunnerIds; knownRunnerIds.reserve(pluginMetaDatas.size()); - for (const KPluginMetaData &pluginMetaData : qAsConst(pluginMetaDatas)) { + for (const KPluginMetaData &pluginMetaData : std::as_const(pluginMetaDatas)) { knownRunnerIds.insert(pluginMetaData.pluginId()); } @@ -798,10 +815,10 @@ QVector<KPluginMetaData> RunnerManager::runnerMetaDataList() { - QVector<KPluginMetaData> pluginMetaDatas = KPluginLoader::findPlugins(QStringLiteral("kf5/krunner")); + QVector<KPluginMetaData> pluginMetaDatas = KPluginMetaData::findPlugins(QStringLiteral("kf5/krunner")); QSet<QString> knownRunnerIds; knownRunnerIds.reserve(pluginMetaDatas.size()); - for (const KPluginMetaData &pluginMetaData : qAsConst(pluginMetaDatas)) { + for (const KPluginMetaData &pluginMetaData : std::as_const(pluginMetaDatas)) { knownRunnerIds.insert(pluginMetaData.pluginId()); } @@ -858,7 +875,7 @@ d->singleRunnerPrepped = true; } } else { - for (AbstractRunner *runner : qAsConst(d->runners)) { + for (AbstractRunner *runner : std::as_const(d->runners)) { if (!d->disabledRunnerIds.contains(runner->name())) { Q_EMIT runner->prepare(); } @@ -929,7 +946,7 @@ } const int queryLetterCount = term.count(); - for (Plasma::AbstractRunner *r : qAsConst(runnable)) { + for (Plasma::AbstractRunner *r : std::as_const(runnable)) { if (r->isMatchingSuspended()) { continue; } @@ -1019,14 +1036,14 @@ if (groupName == QLatin1String("Plugins")) { reloadConfiguration(); } else if (groupName == QLatin1String("Runners")) { - for (auto *runner : qAsConst(d->runners)) { + for (auto *runner : std::as_const(d->runners)) { // Signals from the KCM contain the component name, which is the X-KDE-PluginInfo-Name property if (changedNames.contains(runner->metadata(RunnerReturnPluginMetaData).pluginId().toUtf8())) { runner->reloadConfiguration(); } } } else if (group.parent().isValid() && group.parent().name() == QLatin1String("Runners")) { - for (auto *runner : qAsConst(d->runners)) { + for (auto *runner : std::as_const(d->runners)) { // If the same config group has been modified which gets created in AbstractRunner::config() if (groupName == runner->id()) { runner->reloadConfiguration(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/krunner-5.85.0/src/runnermanager.h new/krunner-5.86.0/src/runnermanager.h --- old/krunner-5.85.0/src/runnermanager.h 2021-08-04 17:53:33.000000000 +0200 +++ new/krunner-5.86.0/src/runnermanager.h 2021-09-04 17:48:31.000000000 +0200 @@ -454,11 +454,7 @@ void historyEnabledChanged(); private: - Q_PRIVATE_SLOT(d, void scheduleMatchesChanged()) - Q_PRIVATE_SLOT(d, void matchesChanged()) Q_PRIVATE_SLOT(d, void jobDone(ThreadWeaver::JobPointer)) - Q_PRIVATE_SLOT(d, void unblockJobs()) - Q_PRIVATE_SLOT(d, void runnerMatchingSuspended(bool)) std::unique_ptr<RunnerManagerPrivate> const d; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/krunner-5.85.0/src/runnersyntax.cpp new/krunner-5.86.0/src/runnersyntax.cpp --- old/krunner-5.85.0/src/runnersyntax.cpp 2021-08-04 17:53:33.000000000 +0200 +++ new/krunner-5.86.0/src/runnersyntax.cpp 2021-09-04 17:48:31.000000000 +0200 @@ -64,7 +64,7 @@ { QStringList queries; const QString termDesc(QLatin1Char('<') + searchTermDescription() + QLatin1Char('>')); - for (QString query : qAsConst(d->exampleQueries)) { + for (QString query : std::as_const(d->exampleQueries)) { queries << query.replace(QStringLiteral(":q:"), termDesc); }
