[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    [kactivities/ivan/plugin-refactor] service: GlobalShortcuts plugin online
From:       Ivan Čukić <ivan.cukic () kde ! org>
Date:       2012-07-02 15:38:31
Message-ID: 20120702153831.A72F6A60A6 () git ! kde ! org
[Download RAW message or body]

Git commit be6e2437bbcfe11e0dd0986481a358656487ff4a by Ivan Čukić.
Committed on 01/07/2012 at 18:32.
Pushed by ivan into branch 'ivan/plugin-refactor'.

GlobalShortcuts plugin online

M  +51   -26   service/Application.cpp
M  +7    -1    service/Application.h
M  +0    -7    service/CMakeLists.txt
M  +6    -0    service/Plugin.cpp
M  +4    -0    service/Plugin.h
M  +1    -1    service/Resources.cpp
M  +2    -2    service/plugins/CMakeLists.txt
M  +98   -54   service/plugins/globalshortcuts/globalshortcuts.cpp
M  +22   -20   service/plugins/globalshortcuts/globalshortcuts.h
C  +7    -15   service/utils/val.h [from: service/Plugin.cpp - 072% similarity]     \
[License: GPL]

http://commits.kde.org/kactivities/be6e2437bbcfe11e0dd0986481a358656487ff4a

diff --git a/service/Application.cpp b/service/Application.cpp
index 8efdd79..8723b48 100644
--- a/service/Application.cpp
+++ b/service/Application.cpp
@@ -1,5 +1,5 @@
 /*
- *   Copyright (C) 2010 Ivan Cukic <ivan.cukic(at)kde.org>
+ *   Copyright (C) 2010, 2011, 2012 Ivan Cukic <ivan.cukic(at)kde.org>
  *
  *   This program is free software; you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License version 2,
@@ -27,6 +27,8 @@
 #include <KAboutData>
 #include <KCmdLineArgs>
 #include <KServiceTypeTrader>
+#include <KSharedConfig>
+#include <KConfigGroup>
 
 #include <Activities.h>
 #include <Resources.h>
@@ -41,6 +43,7 @@
 #include <utils/nullptr.h>
 #include <utils/override_macro.h>
 #include <utils/d_ptr_implementation.h>
+#include <utils/val.h>
 
 static QList < QThread * > s_moduleThreads;
 
@@ -93,19 +96,21 @@ public:
     Activities * activities;
     Features   * features;
 
-    QList < Plugin * > backends;
+    QList < Plugin * > plugins;
+
+    static Application * s_instance;
 
 };
 
+Application * Application::Private::s_instance = nullptr;
+
 Application::Application()
     : KUniqueApplication(), d()
 {
     // TODO: We should move away from any GUI code
     setQuitOnLastWindowClosed(false);
 
-    QDBusConnection dbus = QDBusConnection::sessionBus();
-
-    if (!dbus.registerService("org.kde.ActivityManager")) {
+    if (!QDBusConnection::sessionBus().registerService("org.kde.ActivityManager")) {
         qDebug() << "There can be only one running instance of Activity Manager";
         exit(0);
     }
@@ -115,13 +120,17 @@ Application::Application()
     // NOTE: We have a custom crash handler
     KCrash::setFlags(KCrash::AutoRestart);
 
-    // Loading the plugins
+    QMetaObject::invokeMethod(this, "loadPlugins", Qt::QueuedConnection);
+}
 
-    KService::List offers = \
KServiceTypeTrader::self()->query("ActivityManager/Plugin"); +void \
Application::loadPlugins() +{
+    val offers = KServiceTypeTrader::self()->query("ActivityManager/Plugin");
+    auto disabledPlugins = \
Plugin::config()->group("Global").readEntry("disabledPlugins", QStringList());  
-    QStringList disabledPlugins; // TODO: = \
shared->pluginConfig("Global").readEntry("disabledPlugins", QStringList()); +    // \
Adding overriden plugins into the list of disabled ones  
-    foreach (const KService::Ptr & service, offers) {
+    foreach (val & service, offers) {
         if (!disabledPlugins.contains(service->library())) {
             disabledPlugins.append(
                     service->property("X-ActivityManager-PluginOverrides", \
QVariant::StringList).toStringList() @@ -129,22 +138,20 @@ Application::Application()
         }
     }
 
-    foreach (const KService::Ptr & service, offers) {
+    // Loading plugins and initializing them
+
+    foreach (val & service, offers) {
         if (disabledPlugins.contains(service->library())) {
             continue;
         }
 
-        // kDebug() << "Loading plugin:"
-        //     << service->name() << service->storageId() << service->library()
-        //     << service->property("X-ActivityManager-PluginType", \
                QVariant::String);
-
-        KPluginFactory * factory = KPluginLoader(service->library()).factory();
+        val factory = KPluginLoader(service->library()).factory();
 
         if (!factory) {
             continue;
         }
 
-        Plugin * plugin = factory->create < Plugin > (this);
+        val plugin = factory->create < Plugin > (this);
 
         if (plugin) {
             plugin->init(
@@ -153,24 +160,29 @@ Application::Application()
                 d->features
                 );
 
-            d->backends << plugin;
+            d->plugins << plugin;
 
-        } else {
-            // kDebug() << "Failed to load plugin:" << service->name();
         }
-
     }
-
 }
 
 Application::~Application()
 {
-    foreach (QThread * thread, s_moduleThreads) {
+    qDebug() << "Killing the plugins";
+
+    foreach (val plugin, d->plugins) {
+        qDebug() << plugin->metaObject()->className();
+        delete plugin;
+    }
+
+    foreach (val thread, s_moduleThreads) {
         thread->quit();
         thread->wait();
 
         delete thread;
     }
+
+    Private::s_instance = nullptr;
 }
 
 Activities & Application::activities() const
@@ -183,14 +195,25 @@ Resources & Application::resources()  const
     return *d->resources;
 }
 
+Application * Application::self()
+{
+    if (!Private::s_instance) {
+        Private::s_instance = new Application();
+    }
+
+    return Private::s_instance;
+}
 
-Application & Application::self()
+void Application::quit()
 {
-    static Application s_application;
-    return s_application;
+    if (Private::s_instance) {
+        Private::s_instance->exit();
+        delete Private::s_instance;
+    }
 }
 
 
+
 // Leaving object oriented world :)
 
 static void initSignalCatching();
@@ -207,7 +230,7 @@ int main(int argc, char ** argv)
     KCmdLineArgs::init(argc, argv, &about);
     initSignalCatching();
 
-    return Application::self().exec();
+    return Application::self()->exec();
 }
 
 // Signal handling
@@ -216,6 +239,8 @@ static void signalHandler(int sig)
     // TODO:
     // Jobs::Encryption::Common::unmountAll();
 
+    Application::quit();
+
     // something (probably ksmserver) has asked us to terminate.
     // If it is really ksmserver then the user is probably logging out, so we
     // had better gently stop now than be killed.
diff --git a/service/Application.h b/service/Application.h
index 568ad0f..0a261f0 100644
--- a/service/Application.h
+++ b/service/Application.h
@@ -32,16 +32,22 @@ class Features;
  * Application
  */
 class Application: public KUniqueApplication {
+    Q_OBJECT
+
 public:
     Application();
     virtual ~Application();
 
-    static Application & self();
+    static Application * self();
+    static void quit();
 
     Resources  & resources()  const;
     Activities & activities() const;
     Features   & features()   const;
 
+private Q_SLOTS:
+    void loadPlugins();
+
 private:
     D_PTR;
 };
diff --git a/service/CMakeLists.txt b/service/CMakeLists.txt
index 6adea4a..17432d1 100644
--- a/service/CMakeLists.txt
+++ b/service/CMakeLists.txt
@@ -88,13 +88,6 @@ set (activity_manager_SRCS
 
     Event.cpp
 
-    #    ActivityManager.cpp
-    #    NepomukActivityManager.cpp
-    #    EventProcessor.cpp
-    #    Plugin.cpp
-    #    Event.cpp
-    #    SharedInfo.cpp
-
     jobs/Job.cpp
     jobs/JobFactory.cpp
 
diff --git a/service/Plugin.cpp b/service/Plugin.cpp
index 7c4d87c..5ba75b9 100644
--- a/service/Plugin.cpp
+++ b/service/Plugin.cpp
@@ -32,3 +32,9 @@ bool Plugin::init(QObject *, QObject *, QObject *)
 {
     return true;
 }
+
+KSharedConfig::Ptr Plugin::config()
+{
+    return KSharedConfig::openConfig("activitymanager-pluginsrc");
+}
+
diff --git a/service/Plugin.h b/service/Plugin.h
index d82e1e8..f5119b8 100644
--- a/service/Plugin.h
+++ b/service/Plugin.h
@@ -23,8 +23,10 @@
 #include <kdemacros.h>
 #include <KPluginFactory>
 #include <KPluginLoader>
+#include <KSharedConfig>
 
 #include "Event.h"
+#include <memory>
 
 #define KAMD_EXPORT_PLUGIN(ClassName, AboutData)                       \
     K_PLUGIN_FACTORY(ClassName##Factory, registerPlugin<ClassName>();) \
@@ -47,6 +49,8 @@ public:
             QObject * features
         );
 
+    static KSharedConfig::Ptr config();
+
 };
 
 #endif // PLUGIN_H
diff --git a/service/Resources.cpp b/service/Resources.cpp
index 5284b2c..bb5a79b 100644
--- a/service/Resources.cpp
+++ b/service/Resources.cpp
@@ -47,7 +47,7 @@
 // TODO
 static QString CurrentActivity()
 {
-    return Application::self().activities().CurrentActivity();
+    return Application::self()->activities().CurrentActivity();
 }
 
 // Convenience functions that check whether the proper activity id is passed
diff --git a/service/plugins/CMakeLists.txt b/service/plugins/CMakeLists.txt
index df0ab61..e6ae318 100644
--- a/service/plugins/CMakeLists.txt
+++ b/service/plugins/CMakeLists.txt
@@ -1,8 +1,8 @@
 macro_optional_add_subdirectory(slc)
 # macro_optional_add_subdirectory(activityranking)
 # macro_optional_add_subdirectory(sqlite)
-# macro_optional_add_subdirectory(globalshortcuts)
-#
+macro_optional_add_subdirectory(globalshortcuts)
+
 # get_property(KACTIVITIES_BUILD_NEPOMUK_PLUGIN GLOBAL PROPERTY \
KACTIVITIES_BUILD_NEPOMUK_PLUGIN)  # get_property(KACTIVITIES_BUILD_DUMMY_PLUGIN \
GLOBAL PROPERTY KACTIVITIES_BUILD_DUMMY_PLUGIN)  #
diff --git a/service/plugins/globalshortcuts/globalshortcuts.cpp \
b/service/plugins/globalshortcuts/globalshortcuts.cpp index f4cc2e4..38973ce 100644
--- a/service/plugins/globalshortcuts/globalshortcuts.cpp
+++ b/service/plugins/globalshortcuts/globalshortcuts.cpp
@@ -1,5 +1,6 @@
 /*
- *   Copyright (C) 2012 Makis Marimpis makhsm@gmail.com
+ *   Copyright (C) 2012 Ivan Cukic <ivan.cukic@kde.org>
+ *   Copyright (C) 2012 Makis Marimpis <makhsm@gmail.com>
  *
  *   This program is free software; you can redistribute it and/or
  *   modify it under the terms of the GNU General Public License as
@@ -17,94 +18,137 @@
 
 #include "globalshortcuts.h"
 
+#include <QMetaObject>
+#include <QStringList>
+#include <QString>
+
 #include <KDebug>
+// #include <KGlobalAccel>
+
+#include <utils/val.h>
 
+val objectNamePattern       = QString("switch-to-activity-%1");
+val objectNamePatternLength = objectNamePattern.length() - 2;
 
 GlobalShortcutsPlugin::GlobalShortcutsPlugin(QObject * parent, const QVariantList & \
args)  : Plugin(parent),
+      m_activitiesService(nullptr),
       m_signalMapper(new QSignalMapper(this)),
       m_actionCollection(new KActionCollection(this))
 {
     Q_UNUSED(args)
 }
 
-bool GlobalShortcutsPlugin::init()
+GlobalShortcutsPlugin::~GlobalShortcutsPlugin()
 {
-    // All plugins are loaded from ActivityManager's ctor and this one
-    // specifically makes use of some functionality (e.g. listing all activities
-    // via dbus) that is provided after ActivityManager's ctor is called.
-    // So we queue the real inialization in a slot, for invocation
-    // at a later time - when the application enter the main event loop.
-    QMetaObject::invokeMethod(this, "realInit", Qt::QueuedConnection);
-
-    return true;
+    m_actionCollection->clear();
 }
 
-GlobalShortcutsPlugin::~GlobalShortcutsPlugin()
+bool GlobalShortcutsPlugin::init(
+        QObject * activities,
+        QObject * resources,
+        QObject * features
+    )
 {
+    m_activitiesService = activities;
+
+    QStringList activitiesList;
+
+    QMetaObject::invokeMethod(
+        m_activitiesService, "ListActivities", Qt::DirectConnection,
+        Q_RETURN_ARG(QStringList, activitiesList)
+    );
+
+    foreach (val & activityId, activitiesList) {
+        activityAdded(activityId);
+    }
+
+    connect(
+        m_signalMapper, SIGNAL(mapped(QString)),
+        m_activitiesService, SLOT(SetCurrentActivity(QString)),
+        Qt::QueuedConnection
+    );
+
+    m_actionCollection->readSettings();
+
+    foreach (val action, m_actionCollection->actions()) {
+        qDebug() << "Testing whether" << \
action->objectName().mid(objectNamePatternLength) +            << "is in" << \
activitiesList; +        if \
(!activitiesList.contains(action->objectName().mid(objectNamePatternLength))) { +     \
qDebug() << "It is not!"; +            m_actionCollection->removeAction(action);
+        }
+    }
+
+    m_actionCollection->writeSettings();
+
+    // connect(KGlobalAccel::self(), SIGNAL(destroyed()),
+    //         this, SLOT(globalAccelDied()));
+
+    return true;
 }
 
-void GlobalShortcutsPlugin::realInit()
+// void GlobalShortcutsPlugin::globalAccelDied()
+// {
+//     qDebug() << "---------------------------------------------------------------";
 +//     qDebug() << "Something freaky happened - global accel died before the \
plugin"; +//     qDebug() << \
"---------------------------------------------------------------"; +//     // int i = \
0; i = i/i; +// }
+
+void GlobalShortcutsPlugin::activityAdded(const QString & activityId)
 {
-    m_dbusInterface = new QDBusInterface("org.kde.kactivitymanagerd",
-                                         "/ActivityManager",
-                                         "org.kde.ActivityManager",
-                                          QDBusConnection::sessionBus(),
-                                          this);
+    qDebug() << "Added this activity:" << activityName(activityId) << "(" << \
activityId << ")"; +
+    val action = m_actionCollection->addAction(
+            objectNamePattern.arg(activityId)
+        );
 
-    QDBusPendingCall call = m_dbusInterface->asyncCall("ListActivities");
-    QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher(call, this);
+    action->setText(i18nc("@action", "Switch to activity \"%1\"", \
activityName(activityId))); +    action->setGlobalShortcut(KShortcut());
 
-    connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
-            this, SLOT(listActivitiesFinished(QDBusPendingCallWatcher*)));
+    connect(action, SIGNAL(triggered()), m_signalMapper, SLOT(map()));
+    m_signalMapper->setMapping(action, activityId);
+
+    m_actionCollection->writeSettings();
 }
 
-void GlobalShortcutsPlugin::listActivitiesFinished(QDBusPendingCallWatcher * \
watcher) +void GlobalShortcutsPlugin::activityRemoved(const QString & activityId)
 {
-    QDBusPendingReply<QStringList> reply = *watcher;
+    qDebug() << "Removed this activity:" << activityName(activityId) << "(" << \
activityId << ")";  
-    if (reply.isValid()) {
-        m_activities = reply.argumentAt<0>();
-        updateNextActivityName(nullptr);
+    foreach (val action, m_actionCollection->actions()) {
+        if (activityId == action->objectName().mid(objectNamePatternLength)) {
+            m_actionCollection->removeAction(action);
+        }
     }
 
-    watcher->deleteLater();
+    m_actionCollection->writeSettings();
 }
 
-void GlobalShortcutsPlugin::updateNextActivityName(QDBusPendingCallWatcher * \
watcher) +void GlobalShortcutsPlugin::activityChanged(const QString & activityId)
 {
-    if (watcher) {
-        QDBusPendingReply<QString> reply = *watcher;
-
-        if (reply.isValid()) {
-            KAction * action = \
m_actionCollection->addAction(QString("switch-to-activity-%1").arg(watcher->property("activity").toString()));
                
-            action->setText(i18nc("@action", "Switch to activity \"%1\"", \
                reply.value()));
-            action->setGlobalShortcut(KShortcut());
-            connect(action, SIGNAL(triggered()), m_signalMapper, SLOT(map()));
-            m_signalMapper->setMapping(action, \
                watcher->property("activity").toString());
-        }
+    qDebug() << "Changed title of this activity:" << activityName(activityId) << "(" \
<< activityId << ")";  
-        watcher->deleteLater();
+    foreach (val action, m_actionCollection->actions()) {
+        if (activityId == action->objectName().mid(objectNamePatternLength)) {
+            action->setText(i18nc("@action", "Switch to activity \"%1\"", \
activityName(activityId))); +        }
     }
+}
 
-    if (m_activities.isEmpty()) {
-        connect(m_signalMapper, SIGNAL(mapped(QString)), this, \
                SLOT(setCurrentActivity(QString)));
-        m_actionCollection->readSettings();
-        return;
-    }
+QString GlobalShortcutsPlugin::activityName(const QString & activityId) const
+{
+    QString activityName;
 
-    QString activity = m_activities.takeFirst();
-    QDBusPendingReply<QString> reply = m_dbusInterface->asyncCall("ActivityName", \
activity); +    QMetaObject::invokeMethod(
+        m_activitiesService, "ActivityName", Qt::DirectConnection,
+        Q_RETURN_ARG(QString, activityName),
+        Q_ARG(QString, activityId)
+    );
 
-    QDBusPendingCallWatcher* watcher2 = new QDBusPendingCallWatcher(reply, this);
-    watcher2->setProperty("activity", activity);
-    connect(watcher2, SIGNAL(finished(QDBusPendingCallWatcher*)),
-            this, SLOT(updateNextActivityName(QDBusPendingCallWatcher*)));
+    return activityName;
 }
 
-void GlobalShortcutsPlugin::setCurrentActivity(const QString & activity)
-{
-    m_dbusInterface->asyncCall("SetCurrentActivity", activity);
-}
 
 KAMD_EXPORT_PLUGIN(GlobalShortcutsPlugin, "activitymanger_plugin_globalshortcuts")
diff --git a/service/plugins/globalshortcuts/globalshortcuts.h \
b/service/plugins/globalshortcuts/globalshortcuts.h index 657f0f7..f11704c 100644
--- a/service/plugins/globalshortcuts/globalshortcuts.h
+++ b/service/plugins/globalshortcuts/globalshortcuts.h
@@ -1,5 +1,6 @@
 /*
- *   Copyright (C) 2012 Makis Marimpis makhsm@gmail.com
+ *   Copyright (C) 2012 Makis Marimpis <makhsm@gmail.com>
+ *   Copyright (C) 2012 Ivan Cukic <ivan.cukic@kde.org>
  *
  *   This program is free software; you can redistribute it and/or
  *   modify it under the terms of the GNU General Public License as
@@ -22,39 +23,40 @@
 #include <KAction>
 #include <KGlobalSettings>
 #include <KLocalizedString>
-#include <QtDBus/QDBusConnection>
-#include <QtDBus/QDBusInterface>
-#include <QtDBus/QDBusMessage>
-#include <QtDBus/QDBusReply>
-#include <QtDBus/QDBusPendingCall>
-#include <QtDBus/QDBusPendingCallWatcher>
 #include <QSignalMapper>
 #include <QList>
 
 #include "../../Plugin.h"
 
+#include <utils/override_macro.h>
+
 class GlobalShortcutsPlugin: public Plugin
 {
     Q_OBJECT
 
 public:
-    GlobalShortcutsPlugin(QObject *parent, const QVariantList & args);
-    ~GlobalShortcutsPlugin();
+    GlobalShortcutsPlugin(QObject * parent, const QVariantList & args);
+    virtual ~GlobalShortcutsPlugin();
+
+    virtual bool init(
+            QObject * activities,
+            QObject * resources,
+            QObject * features
+        ) _override;
 
-    virtual bool init() _override;
+private Q_SLOTS:
+    void activityAdded(const QString & activityId);
+    void activityRemoved(const QString & activityId);
+    void activityChanged(const QString & activityId);
 
-private slots:
-    void realInit();
-    void listActivitiesFinished(QDBusPendingCallWatcher * watcher);
-    void updateNextActivityName(QDBusPendingCallWatcher * watcher);
-    void setCurrentActivity(const QString & activity);
+    // void globalAccelDied();
 
 private:
-    QDBusInterface* m_dbusInterface;
-    QStringList m_activities;
-    QSignalMapper* m_signalMapper;
-    QList<KAction*> m_actions;
-    KActionCollection* m_actionCollection;
+    inline QString activityName(const QString & activityId) const;
+
+    QObject * m_activitiesService;
+    QSignalMapper * m_signalMapper;
+    KActionCollection * m_actionCollection;
 };
 
 #endif // PLUGINS_GLOBAL_SHORTCUTS_GLOBAL_SHORTCUTS_H
diff --git a/service/Plugin.cpp b/service/utils/val.h
similarity index 72%
copy from service/Plugin.cpp
copy to service/utils/val.h
index 7c4d87c..64b4d23 100644
--- a/service/Plugin.cpp
+++ b/service/utils/val.h
@@ -1,5 +1,5 @@
 /*
- *   Copyright (C) 2011 Ivan Cukic <ivan.cukic(at)kde.org>
+ *   Copyright (C) 2012 Ivan Cukic <ivan.cukic(at)kde.org>
  *
  *   This program is free software; you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License version 2,
@@ -13,22 +13,14 @@
  *
  *   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.,
+ *   Free Software Foundation,3 Inc.,
  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 
-#include "Plugin.h"
+#ifndef UTILS_VAL_H
+#define UTILS_VAL_H
 
-Plugin::Plugin(QObject * parent)
-    : QObject(parent)
-{
-}
+/// Declares a value. Alias for const auto
+#define val const auto
 
-Plugin::~Plugin()
-{
-}
-
-bool Plugin::init(QObject *, QObject *, QObject *)
-{
-    return true;
-}
+#endif // UTILS_VAL_H


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic