diff --git a/src/common/database/Database.h b/src/common/database/Database.h index 19771e7..38e6d09 100644 --- a/src/common/database/Database.h +++ b/src/common/database/Database.h @@ -1,152 +1,152 @@ /* * Copyright 2014 Ivan Cukic * * 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) 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 14 of version 3 of the license. * * 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, see . */ #ifndef COMMON_DATABASE_H #define COMMON_DATABASE_H #include #include #include #include namespace Common { class Database { public: typedef std::shared_ptr Ptr; enum Source { ResourcesDatabase }; enum OpenMode { ReadWrite, ReadOnly }; static Ptr instance(Source source, OpenMode openMode); QSqlQuery execQueries(const QStringList &queries) const; QSqlQuery execQuery(const QString &query, bool ignoreErrors = false) const; QSqlQuery createQuery() const; void setPragma(const QString &pragma); QVariant pragma(const QString &pragma) const; QVariant value(const QString &query) const; // For debugging purposes only QString lastQuery() const; ~Database(); Database(); friend class Locker; class Locker { public: explicit Locker(Database &database); ~Locker(); private: QSqlDatabase &m_database; }; #define DATABASE_TRANSACTION(A) \ /* enable this for debugging only: qCDebug(KAMD_LOG_RESOURCES) << "Location:" << __FILE__ << __LINE__; */ \ Common::Database::Locker lock(A) private: D_PTR; }; template QString parseStarPattern(const QString &pattern, const QString &joker, EscapeFunction escape) { const auto begin = pattern.constBegin(); const auto end = pattern.constEnd(); auto currentStart = pattern.constBegin(); auto currentPosition = pattern.constBegin(); bool isEscaped = false; // This should be available in the QString class... auto stringFromIterators = [&](const QString::const_iterator ¤tStart, const QString::const_iterator ¤tPosition) { return pattern.mid( std::distance(begin, currentStart), std::distance(currentStart, currentPosition)); }; // Escaping % and _ for sql like // auto escape = [] (QString str) { // return str.replace("%", "\\%").replace("_", "\\_"); // }; QString resultPattern; resultPattern.reserve(pattern.size() * 1.5); for (; currentPosition != end; ++currentPosition) { if (isEscaped) { // Just skip the current character isEscaped = false; - } else if (*currentPosition == '\\') { + } else if (*currentPosition == QLatin1Char('\\')) { // Skip two characters isEscaped = true; - } else if (*currentPosition == '*') { + } else if (*currentPosition == QLatin1Char('*')) { // Replacing the star with the sql like joker - % resultPattern.append(escape(stringFromIterators( currentStart, currentPosition)) + joker); currentStart = currentPosition + 1; } else { // This one is boring, nothing to do } } if (currentStart != currentPosition) { resultPattern.append(escape(stringFromIterators( currentStart, currentPosition))); } return resultPattern; } inline QString escapeSqliteLikePattern(QString pattern) { return pattern.replace(QLatin1String("%"), QLatin1String("\\%")).replace(QLatin1String("_"), QLatin1String("\\_")); } inline QString starPatternToLike(const QString &pattern) { return parseStarPattern(pattern, QStringLiteral("%"), escapeSqliteLikePattern); } inline QRegExp starPatternToRegex(const QString &pattern) { return QRegExp(parseStarPattern(pattern, QStringLiteral(".*"), QRegExp::escape)); } } // namespace Common #endif // COMMON_DATABASE_H diff --git a/src/service/Activities.cpp b/src/service/Activities.cpp index b1a7af5..7c1c733 100644 --- a/src/service/Activities.cpp +++ b/src/service/Activities.cpp @@ -1,599 +1,599 @@ /* * Copyright (C) 2010 - 2016 by Ivan Cukic * * 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) 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 14 of version 3 of the license. * * 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, see . */ // Self #include #include "Activities.h" #include "Activities_p.h" // Qt #include #include #include #include #include #include // KDE #include #include #include #include #include // Utils #include #include // Local #include "DebugActivities.h" #include "activitiesadaptor.h" #include "ksmserver/KSMServer.h" #include "common/dbus/common.h" // Private #define ACTIVITY_MANAGER_CONFIG_FILE_NAME QStringLiteral("kactivitymanagerdrc") Activities::Private::KDE4ConfigurationTransitionChecker::KDE4ConfigurationTransitionChecker() { // Checking whether we need to transfer the KActivities/KDE4 // configuration file to the new location. const QString newConfigLocation = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) - + '/' + ACTIVITY_MANAGER_CONFIG_FILE_NAME; + + QLatin1Char('/') + ACTIVITY_MANAGER_CONFIG_FILE_NAME; if (QFile(newConfigLocation).exists()) { return; } // Testing for kdehome Kdelibs4Migration migration; if (!migration.kdeHomeFound()) { return; } - QString oldConfigFile(migration.locateLocal("config", "activitymanagerrc")); + QString oldConfigFile(migration.locateLocal("config", QStringLiteral("activitymanagerrc"))); if (!oldConfigFile.isEmpty()) { QFile(oldConfigFile).copy(newConfigLocation); } } Activities::Private::Private(Activities *parent) : kde4ConfigurationTransitionChecker() , config(QStringLiteral("kactivitymanagerdrc")) , q(parent) { // qCDebug(KAMD_ACTIVITIES) << "Using this configuration file:" // << config.name() // << config.locationType() // << QStandardPaths::standardLocations(config.locationType()) // ; // Reading activities from the config file. // Saving only the running activities means that if we have any // errors in the config, we might end up with all activities // stopped const auto defaultState = !mainConfig().hasKey("runningActivities") ? Activities::Running : !mainConfig().hasKey("stoppedActivities") ? Activities::Stopped : Activities::Running; const auto runningActivities = mainConfig().readEntry("runningActivities", QStringList()).toSet(); const auto stoppedActivities = mainConfig().readEntry("stoppedActivities", QStringList()).toSet(); // Do we have a running activity? bool atLeastOneRunning = false; for (const auto &activity: activityNameConfig().keyList()) { auto state = runningActivities.contains(activity) ? Activities::Running : stoppedActivities.contains(activity) ? Activities::Stopped : defaultState; activities[activity] = state; if (state == Activities::Running) { atLeastOneRunning = true; } } // Is this our first start? if (activities.isEmpty()) { // We need to add this only after the service has been properly started - KConfigGroup cg(KSharedConfig::openConfig("kdeglobals"), "Activities"); + KConfigGroup cg(KSharedConfig::openConfig(QStringLiteral("kdeglobals")), QStringLiteral("Activities")); //NOTE: config key still singular for retrocompatibility const QStringList names = cg.readEntry("defaultActivityName", QStringList{i18n("Default")}); for (const auto &name : names) { QMetaObject::invokeMethod( q, "AddActivity", Qt::QueuedConnection, Q_ARG(QString, name)); } } else if (!atLeastOneRunning) { // If we have no running activities, but we have activities, // we are in a problem. This should not happen unless the // configuration file is in a big problem and told us there // are no running activities, and enlists all of them as stopped. // In that case, we will pretend all of them are running qCWarning(KAMD_LOG_ACTIVITIES) << "The config file enlisted all activities as stopped"; for (const auto &keys: activities.keys()) { activities[keys] = Activities::Running; } } } void Activities::Private::loadLastActivity() { // This is called from constructor, no need for locking // If there are no public activities, try to load the last used activity const auto lastUsedActivity = mainConfig().readEntry("currentActivity", QString()); setCurrentActivity( (lastUsedActivity.isEmpty() && activities.size() > 0) ? activities.keys().at(0) : lastUsedActivity); } Activities::Private::~Private() { configSync(); } bool Activities::Private::setCurrentActivity(const QString &activity) { { // There is nothing expensive in this block, not a problem to lock QWriteLocker lock(&activitiesLock); // Should we change the activity at all? if (currentActivity == activity) { return true; } // If the activity is empty, this means we are entering a limbo state if (activity.isEmpty()) { currentActivity.clear(); emit q->CurrentActivityChanged(currentActivity); return true; } // Does the requested activity exist? if (!activities.contains(activity)) { return false; } } // Start activity q->StartActivity(activity); // Saving the current activity, and notifying // clients of the change currentActivity = activity; mainConfig().writeEntry("currentActivity", activity); scheduleConfigSync(); emit q->CurrentActivityChanged(activity); return true; } QString Activities::Private::addActivity(const QString &name) { QString activity; if (name.isEmpty()) { Q_ASSERT(!name.isEmpty()); return activity; } int activitiesCount = 0; { QWriteLocker lock(&activitiesLock); // Ensuring a new Uuid. The loop should usually end after only // one iteration while (activity.isEmpty() || activities.contains(activity)) { activity = QUuid::createUuid().toString().mid(1, 36); } // Saves the activity info to the config activities[activity] = Invalid; activitiesCount = activities.size(); } setActivityState(activity, Running); q->SetActivityName(activity, name); emit q->ActivityAdded(activity); scheduleConfigSync(); if (activitiesCount == 1) { q->SetCurrentActivity(activity); } return activity; } void Activities::Private::removeActivity(const QString &activity) { Q_ASSERT(!activity.isEmpty()); // Sanity checks { QWriteLocker lock(&activitiesLock); if (!activities.contains(activity)) { return; } // Is somebody trying to remove the last activity? if (activities.size() == 1) { return; } } // If the activity is running, stash it q->StopActivity(activity); setActivityState(activity, Activities::Invalid); bool currentActivityDeleted = false; { QWriteLocker lock(&activitiesLock); // Removing the activity activities.remove(activity); // If the removed activity was the current one, // set another activity as current currentActivityDeleted = (currentActivity == activity); } activityNameConfig().deleteEntry(activity); activityDescriptionConfig().deleteEntry(activity); activityIconConfig().deleteEntry(activity); if (currentActivityDeleted) { ensureCurrentActivityIsRunning(); } emit q->ActivityRemoved(activity); QMetaObject::invokeMethod(q, "ActivityRemoved", Qt::QueuedConnection, Q_ARG(QString, activity)); QMetaObject::invokeMethod(this, "configSync", Qt::QueuedConnection); } void Activities::Private::scheduleConfigSync() { static const auto shortInterval = 1000; // If the timer is not running, or has a longer interval than we need, // start it // Note: If you want to add multiple different delays for different // events based on the importance of how quickly something needs // to be synced to the config, don't. Since the QTimer lives in a // separate thread, we have to communicate with it in via // queued connections, which means that we don't know whether // the timer was already started when this method was invoked, // we do not know whether the interval is properly set etc. if (!configSyncTimer.isActive()) { QMetaObject::invokeMethod( &configSyncTimer, "start", Qt::QueuedConnection, Q_ARG(int, shortInterval)); } } void Activities::Private::configSync() { // Stop the timer and reset the interval to zero QMetaObject::invokeMethod(&configSyncTimer, "stop", Qt::QueuedConnection); config.sync(); } void Activities::Private::setActivityState(const QString &activity, Activities::State state) { bool configNeedsUpdating = false; { QWriteLocker lock(&activitiesLock); Q_ASSERT(activities.contains(activity)); if (activities.value(activity) == state) { return; } // Treating 'Starting' as 'Running', and 'Stopping' as 'Stopped' // as far as the config file is concerned configNeedsUpdating = ((activities[activity] & 4) != (state & 4)); activities[activity] = state; } switch (state) { case Activities::Running: emit q->ActivityStarted(activity); break; case Activities::Stopped: emit q->ActivityStopped(activity); break; default: break; } emit q->ActivityStateChanged(activity, state); if (configNeedsUpdating) { QReadLocker lock(&activitiesLock); mainConfig().writeEntry("runningActivities", activities.keys(Activities::Running) + activities.keys(Activities::Starting)); mainConfig().writeEntry("stoppedActivities", activities.keys(Activities::Stopped) + activities.keys(Activities::Stopping)); scheduleConfigSync(); } } void Activities::Private::ensureCurrentActivityIsRunning() { // If the current activity is not running, // make some other activity current const auto runningActivities = q->ListActivities(Activities::Running); if (!runningActivities.contains(currentActivity) && runningActivities.size() > 0) { setCurrentActivity(runningActivities.first()); } } void Activities::Private::activitySessionStateChanged(const QString &activity, int status) { QString currentActivity = this->currentActivity; { QReadLocker lock(&activitiesLock); if (!activities.contains(activity)) { return; } } switch (status) { case KSMServer::Started: case KSMServer::FailedToStop: setActivityState(activity, Activities::Running); break; case KSMServer::Stopped: setActivityState(activity, Activities::Stopped); if (currentActivity == activity) { ensureCurrentActivityIsRunning(); } break; } QMetaObject::invokeMethod(this, "configSync", Qt::QueuedConnection); } // Main Activities::Activities(QObject *parent) : Module(QStringLiteral("activities"), parent) , d(this) { qCDebug(KAMD_LOG_ACTIVITIES) << "Starting the KDE Activity Manager daemon" << QDateTime::currentDateTime(); // Basic initialization //////////////////////////////////////////////////// // Initializing D-Bus service new ActivitiesAdaptor(this); KDBusConnectionPool::threadConnection().registerObject( KAMD_DBUS_OBJECT_PATH(Activities), this); // Initializing config qCDebug(KAMD_LOG_ACTIVITIES) << "Config timer connecting..."; d->connect(&d->configSyncTimer, SIGNAL(timeout()), SLOT(configSync()), Qt::QueuedConnection); d->configSyncTimer.setSingleShot(true); d->ksmserver = new KSMServer(this); d->connect(d->ksmserver, SIGNAL(activitySessionStateChanged(QString, int)), SLOT(activitySessionStateChanged(QString, int))); // Loading the last used activity, if possible d->loadLastActivity(); } Activities::~Activities() { } QString Activities::CurrentActivity() const { QReadLocker lock(&d->activitiesLock); return d->currentActivity; } bool Activities::SetCurrentActivity(const QString &activity) { // Public method can not put us in a limbo state if (activity.isEmpty()) { return false; } return d->setCurrentActivity(activity); } QString Activities::AddActivity(const QString &name) { // We do not care about authorization if this is the first start if (!d->activities.isEmpty() && - !KAuthorized::authorize("plasma-desktop/add_activities")) { + !KAuthorized::authorize(QStringLiteral("plasma-desktop/add_activities"))) { return QString(); } return d->addActivity(name); } void Activities::RemoveActivity(const QString &activity) { - if (!KAuthorized::authorize("plasma-desktop/add_activities")) { + if (!KAuthorized::authorize(QStringLiteral("plasma-desktop/add_activities"))) { return; } d->removeActivity(activity); } QStringList Activities::ListActivities() const { QReadLocker lock(&d->activitiesLock); return d->activities.keys(); } QStringList Activities::ListActivities(int state) const { QReadLocker lock(&d->activitiesLock); return d->activities.keys((State)state); } QList Activities::ListActivitiesWithInformation() const { using namespace kamd::utils; // Mapping activity ids to info return as_collection>( ListActivities() | transformed(&Activities::ActivityInformation, this) ); } ActivityInfo Activities::ActivityInformation(const QString &activity) const { return ActivityInfo { activity, ActivityName(activity), ActivityDescription(activity), ActivityIcon(activity), ActivityState(activity) }; } #define CREATE_GETTER_AND_SETTER(What) \ QString Activities::Activity##What(const QString &activity) const \ { \ QReadLocker lock(&d->activitiesLock); \ return d->activities.contains(activity) ? d->activity##What(activity) \ : QString(); \ } \ \ void Activities::SetActivity##What(const QString &activity, \ const QString &value) \ { \ { \ QReadLocker lock(&d->activitiesLock); \ if (value == d->activity##What(activity) \ || !d->activities.contains(activity)) { \ return; \ } \ } \ \ d->activity##What##Config().writeEntry(activity, value); \ d->scheduleConfigSync(); \ \ emit Activity##What##Changed(activity, value); \ emit ActivityChanged(activity); \ } CREATE_GETTER_AND_SETTER(Name) CREATE_GETTER_AND_SETTER(Description) CREATE_GETTER_AND_SETTER(Icon) #undef CREATE_GETTE_AND_SETTERR // Main void Activities::StartActivity(const QString &activity) { { QReadLocker lock(&d->activitiesLock); if (!d->activities.contains(activity) || d->activities[activity] != Stopped) { return; } } d->setActivityState(activity, Starting); d->ksmserver->startActivitySession(activity); } void Activities::StopActivity(const QString &activity) { { QReadLocker lock(&d->activitiesLock); if (!d->activities.contains(activity) || d->activities[activity] == Stopped || d->activities.size() == 1 || d->activities.keys(Activities::Running).size() <= 1 ) { return; } } d->setActivityState(activity, Stopping); d->ksmserver->stopActivitySession(activity); } int Activities::ActivityState(const QString &activity) const { QReadLocker lock(&d->activitiesLock); return d->activities.contains(activity) ? d->activities[activity] : Invalid; } diff --git a/src/service/Application.cpp b/src/service/Application.cpp index 80d2753..42b84ba 100644 --- a/src/service/Application.cpp +++ b/src/service/Application.cpp @@ -1,430 +1,430 @@ /* * Copyright (C) 2010 - 2016 by Ivan Cukic * * 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) 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 14 of version 3 of the license. * * 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, see . */ // Self #include #include "Application.h" // Qt #include #include #include #include #include #include // KDE // #include // #include // #include #include #include #include #include #include // Boost and utils #include #include #include // System #include #include #include #include // Local #include "Activities.h" #include "Resources.h" #include "Features.h" #include "Config.h" #include "Plugin.h" #include "DebugApplication.h" #include "common/dbus/common.h" namespace { QList s_moduleThreads; } // Runs a QObject inside a QThread template T *runInQThread() { T *object = new T(); class Thread : public QThread { public: Thread(T *ptr = nullptr) : QThread() , object(ptr) { } void run() override { std::unique_ptr o(object); exec(); } private: T *object; } *thread = new Thread(object); s_moduleThreads << thread; object->moveToThread(thread); thread->start(); return object; } class Application::Private { public: Private() { } static inline bool isPluginEnabled(const KConfigGroup &config, const KPluginMetaData& plugin) { const auto pluginName = plugin.pluginId(); qCDebug(KAMD_LOG_APPLICATION) << "Plugin Name is " << pluginName << plugin.fileName(); - if (pluginName == "org.kde.ActivityManager.ResourceScoring") { + if (pluginName == QLatin1String("org.kde.ActivityManager.ResourceScoring")) { // SQLite plugin is necessary for the proper workspace behaviour return true; } else { - return config.readEntry(pluginName + "Enabled", plugin.isEnabledByDefault()); + return config.readEntry(pluginName + QStringLiteral("Enabled"), plugin.isEnabledByDefault()); } } bool loadPlugin(const KPluginMetaData& plugin); Resources *resources; Activities *activities; Features *features; QStringList pluginIds; QList plugins; static Application *s_instance; }; Application *Application::Private::s_instance = nullptr; Application::Application(int &argc, char **argv) : QApplication(argc, argv) { } void Application::init() { if (!KDBusConnectionPool::threadConnection().registerService( KAMD_DBUS_SERVICE)) { QCoreApplication::exit(EXIT_SUCCESS); } // KAMD is a daemon, if it crashes it is not a problem as // long as it restarts properly // TODO: Restart on crash // KCrash::setFlags(KCrash::AutoRestart); d->resources = runInQThread(); d->activities = runInQThread(); d->features = runInQThread(); /* d->config */ new Config(this); // this does not need a separate thread QMetaObject::invokeMethod(this, "loadPlugins", Qt::QueuedConnection); - QDBusConnection::sessionBus().registerObject("/ActivityManager", this, + QDBusConnection::sessionBus().registerObject(QStringLiteral("/ActivityManager"), this, QDBusConnection::ExportAllSlots); } bool Application::Private::loadPlugin(const KPluginMetaData& plugin) { if (!plugin.isValid()) { qCWarning(KAMD_LOG_APPLICATION) << "[ FAILED ] plugin offer not valid"; return false; } if (pluginIds.contains(plugin.pluginId())) { qCDebug(KAMD_LOG_APPLICATION) << "[ OK ] already loaded: " << plugin.pluginId(); return true; } KPluginLoader loader(plugin.fileName()); KPluginFactory* factory = loader.factory(); if (!factory) { qCWarning(KAMD_LOG_APPLICATION) << "[ FAILED ] Could not load KPluginFactory for:" << plugin.pluginId() << loader.errorString(); return false; } auto pluginInstance = factory->create(); auto &modules = Module::get(); if (pluginInstance) { bool success = pluginInstance->init(modules); if (success) { pluginIds << plugin.pluginId(); plugins << pluginInstance; qCDebug(KAMD_LOG_APPLICATION) << "[ OK ] loaded: " << plugin.pluginId(); return true; } else { qCWarning(KAMD_LOG_APPLICATION) << "[ FAILED ] init: " << plugin.pluginId() << loader.errorString(); // TODO: Show a notification for a plugin that failed to load delete pluginInstance; return false; } } else { qCWarning(KAMD_LOG_APPLICATION) << "[ FAILED ] loading: " << plugin.pluginId() << loader.errorString(); // TODO: Show a notification for a plugin that failed to load return false; } } void Application::loadPlugins() { using namespace std::placeholders; const auto config = KSharedConfig::openConfig(QStringLiteral("kactivitymanagerdrc")) ->group("Plugins"); const auto offers = KPluginLoader::findPlugins(QStringLiteral(KAMD_PLUGIN_DIR), std::bind(Private::isPluginEnabled, config, _1)); qCDebug(KAMD_LOG_APPLICATION) << "Found" << offers.size() << "enabled plugins:"; for (const auto &offer : offers) { d->loadPlugin(offer); } } bool Application::loadPlugin(const QString &pluginId) { auto offers = KPluginLoader::findPluginsById(QStringLiteral(KAMD_PLUGIN_DIR), pluginId); if (offers.isEmpty()) { qCWarning(KAMD_LOG_APPLICATION) << "[ FAILED ] not found: " << pluginId; return false; } return d->loadPlugin(offers.first()); } Application::~Application() { qCDebug(KAMD_LOG_APPLICATION) << "Cleaning up..."; // Waiting for the threads to finish for (const auto thread : s_moduleThreads) { thread->quit(); thread->wait(); delete thread; } // Deleting plugin objects for (const auto plugin : d->plugins) { delete plugin; } Private::s_instance = nullptr; } int Application::newInstance() { //We don't want to show the mainWindow() return 0; } Activities &Application::activities() const { return *d->activities; } Resources &Application::resources() const { return *d->resources; } // void Application::quit() // { // if (Private::s_instance) { // Private::s_instance->exit(); // delete Private::s_instance; // } // } void Application::quit() { QApplication::quit(); } #include "Version.h" QString Application::serviceVersion() const { return KACTIVITIES_VERSION_STRING; } // Leaving object oriented world :) namespace { template Return callOnRunningService(const QString &method) { - static QDBusInterface remote(KAMD_DBUS_SERVICE, "/ActivityManager", - "org.kde.ActivityManager.Application"); + static QDBusInterface remote(KAMD_DBUS_SERVICE, QStringLiteral("/ActivityManager"), + QStringLiteral("org.kde.ActivityManager.Application")); QDBusReply reply = remote.call(method); return (Return)reply; } QString runningServiceVersion() { - return callOnRunningService("serviceVersion"); + return callOnRunningService(QStringLiteral("serviceVersion")); } bool isServiceRunning() { return QDBusConnection::sessionBus().interface()->isServiceRegistered( KAMD_DBUS_SERVICE); } } int main(int argc, char **argv) { // Disable session management for this process qunsetenv("SESSION_MANAGER"); QGuiApplication::setDesktopSettingsAware(false); Application application(argc, argv); application.setApplicationName(QStringLiteral("ActivityManager")); application.setOrganizationDomain(QStringLiteral("kde.org")); // KAboutData about("kactivitymanagerd", nullptr, ki18n("KDE Activity Manager"), "3.0", // ki18n("KDE Activity Management Service"), // KAboutData::License_GPL, // ki18n("(c) 2010, 2011, 2012 Ivan Cukic"), KLocalizedString(), // "http://www.kde.org/"); // KCmdLineArgs::init(argc, argv, &about); const auto arguments = application.arguments(); if (arguments.size() == 0) { QCoreApplication::exit(EXIT_FAILURE); - } else if (arguments.size() != 1 && (arguments.size() != 2 || arguments[1] == "--help")) { + } else if (arguments.size() != 1 && (arguments.size() != 2 || arguments[1] == QLatin1String("--help"))) { QTextStream(stdout) << "start\tStarts the service\n" << "stop\tStops the server\n" << "status\tPrints basic server information\n" << "start-daemon\tStarts the service without forking (use with caution)\n" << "--help\tThis help message\n"; QCoreApplication::exit(EXIT_SUCCESS); - } else if (arguments.size() == 1 || arguments[1] == "start") { + } else if (arguments.size() == 1 || arguments[1] == QLatin1String("start")) { // Checking whether the service is already running if (isServiceRunning()) { QTextStream(stdout) << "Already running\n"; QCoreApplication::exit(EXIT_SUCCESS); } // Creating the watcher, but not on the wall QDBusServiceWatcher watcher(KAMD_DBUS_SERVICE, QDBusConnection::sessionBus(), QDBusServiceWatcher::WatchForRegistration); QObject::connect(&watcher, &QDBusServiceWatcher::serviceRegistered, [] (const QString &service) { QTextStream(stdout) << "Service started, version: " << runningServiceVersion() << "\n"; QCoreApplication::exit(EXIT_SUCCESS); }); // Starting the dameon QProcess::startDetached( - KAMD_FULL_BIN_DIR "/kactivitymanagerd", - QStringList{"start-daemon"} + QLatin1String(KAMD_FULL_BIN_DIR "/kactivitymanagerd"), + QStringList{QStringLiteral("start-daemon")} ); return application.exec(); - } else if (arguments[1] == "stop") { + } else if (arguments[1] == QLatin1String("stop")) { if (!isServiceRunning()) { QTextStream(stdout) << "Service not running\n"; QCoreApplication::exit(EXIT_SUCCESS); } - callOnRunningService("quit"); + callOnRunningService(QStringLiteral("quit")); QTextStream(stdout) << "Service stopped\n"; return EXIT_SUCCESS; - } else if (arguments[1] == "status") { + } else if (arguments[1] == QLatin1String("status")) { // Checking whether the service is already running if (isServiceRunning()) { QTextStream(stdout) << "The service is running, version: " << runningServiceVersion() << "\n"; } else { QTextStream(stdout) << "The service is not running\n"; } return EXIT_SUCCESS; - } else if (arguments[1] == "start-daemon") { + } else if (arguments[1] == QLatin1String("start-daemon")) { // Really starting the activity manager KDBusService service(KDBusService::Unique); application.init(); return application.exec(); } else { QTextStream(stdout) << "Unrecognized command: " << arguments[1] << '\n'; return EXIT_FAILURE; } } QStringList Application::loadedPlugins() const { return d->pluginIds; } diff --git a/src/service/Config.cpp b/src/service/Config.cpp index 5a742ef..59ed3c8 100644 --- a/src/service/Config.cpp +++ b/src/service/Config.cpp @@ -1,82 +1,82 @@ /* * Copyright (C) 2015 - 2016 by Ivan Cukic * * 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) 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 14 of version 3 of the license. * * 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, see . */ #include #include #include #include #include #include class Config::Private { public: Private(Config *parent) : q(parent) , mainConfigFile(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + QStringLiteral("/kactivitymanagerdrc")) , pluginConfigFile(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + QStringLiteral("/kactivitymanagerd-pluginsrc")) { using namespace std::placeholders; watcher.addFile(mainConfigFile); watcher.addFile(pluginConfigFile); QObject::connect( &watcher, &KDirWatch::created, q, std::bind(&Private::configFileChanged, this, _1)); QObject::connect( &watcher, &KDirWatch::dirty, q, std::bind(&Private::configFileChanged, this, _1)); } void configFileChanged(const QString &file) { if (file == pluginConfigFile) { emit q->pluginConfigChanged(); } else { emit q->mainConfigChanged(); } } KDirWatch watcher; private: Config * const q; const QString mainConfigFile; const QString pluginConfigFile; }; Config::Config(QObject *parent) - : Module("config", parent) + : Module(QStringLiteral("config"), parent) , d(this) { } Config::~Config() { } diff --git a/src/service/plugins/runapplication/RunApplicationPlugin.cpp b/src/service/plugins/runapplication/RunApplicationPlugin.cpp index 49ca53b..c76c069 100644 --- a/src/service/plugins/runapplication/RunApplicationPlugin.cpp +++ b/src/service/plugins/runapplication/RunApplicationPlugin.cpp @@ -1,137 +1,137 @@ /* * Copyright (C) 2012, 2013, 2014 Ivan Cukic * * 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, see . */ #include "RunApplicationPlugin.h" #include #include #include #include #include #include #include "DebugApplication.h" #include namespace { enum ActivityState { Running = 2, Stopped = 4 }; } KAMD_EXPORT_PLUGIN(runapplicationplugin, RunApplicationPlugin, "kactivitymanagerd-plugin-runapplication.json") RunApplicationPlugin::RunApplicationPlugin(QObject *parent, const QVariantList &args) : Plugin(parent) , m_activitiesService(nullptr) { Q_UNUSED(args); - setName("org.kde.ActivityManager.RunApplication"); + setName(QStringLiteral("org.kde.ActivityManager.RunApplication"=); } RunApplicationPlugin::~RunApplicationPlugin() { } bool RunApplicationPlugin::init(QHash &modules) { Plugin::init(modules); - m_activitiesService = modules["activities"]; + m_activitiesService = modules[QStringLiteral("activities")]; connect(m_activitiesService, SIGNAL(CurrentActivityChanged(QString)), this, SLOT(currentActivityChanged(QString))); connect(m_activitiesService, SIGNAL(ActivityStateChanged(QString, int)), this, SLOT(activityStateChanged(QString, int))); const auto currentActivity = Plugin::retrieve( - m_activitiesService, "CurrentActivity", "QString"); + m_activitiesService, QStringLiteral("CurrentActivity"), QStringLiteral("QString")); currentActivityChanged(currentActivity); return true; } QString RunApplicationPlugin::activityDirectory(const QString &activity) const { return QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) - + QStringLiteral("/kactivitymanagerd/activities/") + activity + '/'; + + QStringLiteral("/kactivitymanagerd/activities/") + activity + QLatin1Char('/'); } void RunApplicationPlugin::currentActivityChanged(const QString &activity) { if (m_currentActivity == activity) { return; } if (!m_currentActivity.isEmpty()) { - executeIn(activityDirectory(activity) + "deactivated"); + executeIn(activityDirectory(activity) + QStringLiteral("deactivated")); } m_currentActivity = activity; - executeIn(activityDirectory(activity) + "activated"); + executeIn(activityDirectory(activity) + QStringLiteral("activated")); if (!m_previousActivities.contains(activity)) { // This is the first time we have switched // to this activity in the current session, // pretending it has just been started activityStateChanged(activity, Running); m_previousActivities << activity; } } void RunApplicationPlugin::activityStateChanged(const QString &activity, int state) { auto directory = (state == Running) ? QStringLiteral("started") : (state == Stopped) ? QStringLiteral("stopped") : QString(); if (directory == "") { return; } executeIn(activityDirectory(activity) + directory); } void RunApplicationPlugin::executeIn(const QString &path) const { QDir directory(path); for (const auto& item: directory.entryList(QDir::Files)) { QString filePath = directory.filePath(item); KService service(filePath); if (service.isValid() && service.isApplication()) { qCDebug(KAMD_LOG_APPLICATION) << "Starting: " << service.exec(); QProcess::startDetached(service.exec()); } else { qCDebug(KAMD_LOG_APPLICATION) << "Openning file: " << QUrl::fromLocalFile(filePath); QDesktopServices::openUrl(QUrl::fromLocalFile(filePath)); } } } // void RunApplicationPlugin::activityRemoved(const QString &activity) // { // // TODO: Clean up the directory // } #include "RunApplicationPlugin.moc"