Bläddra i källkod

ENH: PluginFramework: added plugin and event bus classes

Sascha Zelzer 15 år sedan
förälder
incheckning
cb768296b2
37 ändrade filer med 1570 tillägg och 22 borttagningar
  1. 1 0
      CMakeLists.txt
  2. 12 0
      Libs/Core/CMakeLists.txt
  3. 77 0
      Libs/Core/EventBus/ctkEvent.cxx
  4. 43 0
      Libs/Core/EventBus/ctkEvent.h
  5. 29 0
      Libs/Core/EventBus/ctkEventBus.h
  6. 8 0
      Libs/Core/EventBus/ctkEventConstants.cxx
  7. 19 0
      Libs/Core/EventBus/ctkEventConstants.h
  8. 20 0
      Libs/Core/PluginFramework/ctkInternalSystemPlugin_p.h
  9. 72 0
      Libs/Core/PluginFramework/ctkLDAPSearchFilter.cxx
  10. 46 0
      Libs/Core/PluginFramework/ctkLDAPSearchFilter.h
  11. 59 0
      Libs/Core/PluginFramework/ctkPlugin.cxx
  12. 50 0
      Libs/Core/PluginFramework/ctkPlugin.h
  13. 2 2
      Libs/Core/PluginFramework/ctkPluginActivator.h
  14. 21 5
      Libs/Core/PluginFramework/ctkPluginContext.cxx
  15. 16 8
      Libs/Core/PluginFramework/ctkPluginContext.h
  16. 30 0
      Libs/Core/PluginFramework/ctkPluginFramework.h
  17. 28 3
      Libs/Core/PluginFramework/ctkPluginManager.cxx
  18. 20 0
      Libs/Core/PluginFramework/ctkPluginPrivate_p.h
  19. 135 0
      Libs/Core/PluginFramework/ctkPluginRepository.cxx
  20. 50 0
      Libs/Core/PluginFramework/ctkPluginRepository_p.h
  21. 32 0
      Libs/Core/PluginFramework/ctkServiceReference.cxx
  22. 28 0
      Libs/Core/PluginFramework/ctkServiceReference.h
  23. 20 0
      Libs/Core/PluginFramework/ctkServiceRegistration.cxx
  24. 24 0
      Libs/Core/PluginFramework/ctkServiceRegistration.h
  25. 174 0
      Libs/Core/PluginFramework/ctkVersion.cxx
  26. 214 0
      Libs/Core/PluginFramework/ctkVersion.h
  27. 3 2
      Plugins/org.commontk.cli/ctkCLIPlugin.cxx
  28. 2 2
      Plugins/org.commontk.cli/ctkCLIPlugin.h
  29. 31 0
      Plugins/org.commontk.eventbus/CMakeLists.txt
  30. 73 0
      Plugins/org.commontk.eventbus/ctkEventBusImpl.cxx
  31. 52 0
      Plugins/org.commontk.eventbus/ctkEventBusImpl_p.h
  32. 42 0
      Plugins/org.commontk.eventbus/ctkEventBusPlugin.cxx
  33. 32 0
      Plugins/org.commontk.eventbus/ctkEventBusPlugin_p.h
  34. 80 0
      Plugins/org.commontk.eventbus/ctkEventHandlerWrapper_p.h
  35. 5 0
      Plugins/org.commontk.eventbus/org_commontk_eventbus.qrc
  36. 11 0
      Plugins/org.commontk.eventbus/servicedescriptor.xml
  37. 9 0
      Plugins/org.commontk.eventbus/target_libraries.cmake

+ 1 - 0
CMakeLists.txt

@@ -129,6 +129,7 @@ SET(ctk_libs
 #
 SET(ctk_plugins
   org.commontk.cli
+  org.commontk.eventbus
   )
 
 #-----------------------------------------------------------------------------

+ 12 - 0
Libs/Core/CMakeLists.txt

@@ -45,8 +45,19 @@ SET(KIT_SRCS
   ctkUtils.h
 
   # PluginFramework sources
+  PluginFramework/ctkLDAPSearchFilter.cxx
+  PluginFramework/ctkPlugin.cxx
   PluginFramework/ctkPluginContext.cxx
   PluginFramework/ctkPluginManager.cxx
+  PluginFramework/ctkPluginRepository.cxx
+  PluginFramework/ctkServiceReference.cxx
+  PluginFramework/ctkServiceRegistration.cxx
+  #PluginFramework/ctkServiceRegistry.cxx
+  PluginFramework/ctkVersion.cxx
+
+  # EventBus sources
+  EventBus/ctkEvent.cxx
+  EventBus/ctkEventConstants.cxx
   )
 
 # Headers that should run through moc
@@ -55,6 +66,7 @@ SET(KIT_MOC_SRCS
 
   # PluginFramework headers
   PluginFramework/ctkPluginActivator.h
+
   )
 
 # UI files

+ 77 - 0
Libs/Core/EventBus/ctkEvent.cxx

@@ -0,0 +1,77 @@
+
+#include "ctkEvent.h"
+
+namespace ctk {
+
+  class EventPrivate {
+
+  public:
+
+    EventPrivate(const QString& topic, const LDAPSearchFilter::Dictionary& properties)
+      : ref(1), topic(topic), properties(properties)
+    {
+
+    }
+
+    QAtomicInt ref;
+    const QString topic;
+    const LDAPSearchFilter::Dictionary properties;
+
+  };
+
+
+  Event::Event(const QString& topic, const LDAPSearchFilter::Dictionary& properties)
+    : d(new EventPrivate(topic, properties))
+  {
+
+  }
+
+  /*
+   * This is fast thanks to implicit sharing
+   */
+  Event::Event(const Event &event)
+    : d(event.d)
+  {
+    d->ref.ref();
+  }
+
+  Event::~Event()
+  {
+    if (!d->ref.deref())
+      delete d;
+  }
+
+  bool Event::operator==(const Event& other) const
+  {
+    if (d == other.d)
+      return true;
+
+    if (d->topic == other.d->topic &&
+        d->properties == other.d->properties)
+      return true;
+
+    return false;
+  }
+
+  const QVariant& Event::property(const QString& name) const
+  {
+    d->properties[name];
+  }
+
+  QStringList Event::propertyNames() const
+  {
+    d->properties.keys();
+  }
+
+  const QString& Event::topic() const
+  {
+    d->topic;
+  }
+
+  bool Event::matches(const LDAPSearchFilter& filter) const
+  {
+    // TODO
+    return true;
+  }
+
+}

+ 43 - 0
Libs/Core/EventBus/ctkEvent.h

@@ -0,0 +1,43 @@
+#ifndef CTKEVENT_H
+#define CTKEVENT_H
+
+#include "CTKCoreExport.h"
+
+#include <QMap>
+#include <QVariant>
+#include <QStringList>
+
+#include <PluginFramework/ctkLDAPSearchFilter.h>
+
+namespace ctk {
+
+  class EventPrivate;
+
+  class CTK_CORE_EXPORT Event {
+
+  public:
+
+    typedef QMap<QString, QVariant> Properties;
+
+    //TODO: what are we doing about malformed topic strings? Use exceptions in CTK?
+    Event(const QString& topic, const LDAPSearchFilter::Dictionary& properties = Properties());
+    Event(const Event& event);
+    ~Event();
+
+    bool operator==(const Event& other) const;
+
+    const QVariant& property(const QString& name) const;
+    QStringList propertyNames() const;
+
+    const QString& topic() const;
+
+    bool matches(const LDAPSearchFilter& filter) const;
+
+  protected:
+
+    EventPrivate * const d;
+  };
+
+}
+
+#endif // CTKEVENT_H

+ 29 - 0
Libs/Core/EventBus/ctkEventBus.h

@@ -0,0 +1,29 @@
+#ifndef CTKEVENTBUS_H
+#define CTKEVENTBUS_H
+
+#include "ctkEvent.h"
+
+namespace ctk {
+
+  class EventBus {
+
+  public:
+
+    typedef QMap<QString, QVariant> Properties;
+
+    virtual ~EventBus() {}
+
+    virtual void postEvent(const Event& event) = 0;
+    virtual void sendEvent(const Event& event) = 0;
+
+    virtual void publishSignal(const QObject* publisher, const char* signal) = 0;
+
+    virtual void subscribeSlot(const QObject* subscriber, const char* member, const Properties& properties) = 0;
+
+  };
+
+}
+
+Q_DECLARE_INTERFACE(ctk::EventBus, "org.commontk.core.EventBus")
+
+#endif // CTKEVENTBUS_H

+ 8 - 0
Libs/Core/EventBus/ctkEventConstants.cxx

@@ -0,0 +1,8 @@
+#include "ctkEventConstants.h"
+
+namespace ctk {
+
+  const QString EventConstants::EVENT_TOPIC = "event.topics";
+  const QString EventConstants::EVENT_FILTER = "event.filter";
+
+}

+ 19 - 0
Libs/Core/EventBus/ctkEventConstants.h

@@ -0,0 +1,19 @@
+#ifndef CTKEVENTCONSTANTS_H
+#define CTKEVENTCONSTANTS_H
+
+#include <QString>
+
+#include "CTKCoreExport.h"
+
+namespace ctk {
+
+  struct CTK_CORE_EXPORT EventConstants {
+
+    static const QString EVENT_TOPIC; // = "event.topics"
+    static const QString EVENT_FILTER; // = "event.filter"
+
+  };
+
+}
+
+#endif // CTKEVENTCONSTANTS_H

+ 20 - 0
Libs/Core/PluginFramework/ctkInternalSystemPlugin_p.h

@@ -0,0 +1,20 @@
+#ifndef CTKINTERNALSYSTEMPLUGIN_P_H
+#define CTKINTERNALSYSTEMPLUGIN_P_H
+
+#include "ctkPlugin.h"
+
+namespace ctk {
+
+  class InternalSystemPluginPrivate;
+  class InternalSystemPlugin : public Plugin {
+
+  public:
+
+    void start();
+    void stop();
+
+  };
+
+}
+
+#endif // CTKINTERNALSYSTEMPLUGIN_P_H

+ 72 - 0
Libs/Core/PluginFramework/ctkLDAPSearchFilter.cxx

@@ -0,0 +1,72 @@
+/*
+ * ctkLDAPSearchFilter.cxx
+ *
+ *  Created on: Mar 28, 2010
+ *      Author: zelzer
+ */
+
+#include "ctkLDAPSearchFilter.h"
+
+namespace ctk {
+
+  class LDAPSearchFilterPrivate {
+  public:
+
+    LDAPSearchFilterPrivate()
+      : ref(1)
+    {}
+
+    QAtomicInt ref;
+
+  };
+
+  LDAPSearchFilter::LDAPSearchFilter(const QString& filter)
+    : d(new LDAPSearchFilterPrivate())
+  {
+
+  }
+
+  LDAPSearchFilter::LDAPSearchFilter(const LDAPSearchFilter& filter)
+    : d(filter.d)
+  {
+    d->ref.ref();
+  }
+
+  LDAPSearchFilter::~LDAPSearchFilter()
+  {
+    if (!d->ref.deref())
+      delete d;
+  }
+
+  bool LDAPSearchFilter::match(const Dictionary& dictionary) const
+  {
+    return true;
+  }
+
+  bool LDAPSearchFilter::matchCase(const Dictionary& dictionary) const
+  {
+    return true;
+  }
+
+  bool LDAPSearchFilter::operator==(const LDAPSearchFilter& other) const
+  {
+    // TODO
+    return true;
+  }
+
+  LDAPSearchFilter& LDAPSearchFilter::operator=(const LDAPSearchFilter& filter)
+  {
+    if (d != filter.d)
+    {
+      if (!d->ref.deref())
+        delete d;
+
+      d = filter.d;
+      d->ref.ref();
+    }
+
+    return *this;
+  }
+
+
+}

+ 46 - 0
Libs/Core/PluginFramework/ctkLDAPSearchFilter.h

@@ -0,0 +1,46 @@
+/*
+ * ctkLDAPSearchFilter.h
+ *
+ *  Created on: Mar 28, 2010
+ *      Author: zelzer
+ */
+
+#ifndef CTKLDAPSEARCHFILTER_H
+#define CTKLDAPSEARCHFILTER_H
+
+#include "CTKCoreExport.h"
+
+#include <QMap>
+#include <QString>
+#include <QVariant>
+
+namespace ctk {
+
+  class LDAPSearchFilterPrivate;
+
+  class CTK_CORE_EXPORT LDAPSearchFilter {
+
+  public:
+
+    typedef QMap<QString, QVariant> Dictionary;
+
+    LDAPSearchFilter(const QString& filter = "");
+    LDAPSearchFilter(const LDAPSearchFilter& filter);
+
+    ~LDAPSearchFilter();
+
+    bool match(const Dictionary& dictionary) const;
+    bool matchCase(const Dictionary& dictionary) const;
+
+    bool operator==(const LDAPSearchFilter& other) const;
+    LDAPSearchFilter& operator=(const LDAPSearchFilter& filter);
+
+  protected:
+
+    LDAPSearchFilterPrivate * d;
+
+  };
+
+}
+
+#endif // CTKLDAPSEARCHFILTER_H

+ 59 - 0
Libs/Core/PluginFramework/ctkPlugin.cxx

@@ -0,0 +1,59 @@
+#include "ctkPlugin.h"
+
+#include "ctkPluginPrivate_p.h"
+
+namespace ctk {
+
+  Plugin::Plugin()
+    : d_ptr(new PluginPrivate)
+  {
+
+  }
+
+  Plugin::Plugin(PluginPrivate& dd)
+    : d_ptr(&dd)
+  {
+
+  }
+
+  Plugin::~Plugin()
+  {
+    delete d_ptr;
+  }
+
+  Plugin::State Plugin::state() const
+  {
+    return ACTIVE;
+  }
+
+  void Plugin::start()
+  {
+
+  }
+
+  void Plugin::stop()
+  {
+
+  }
+
+  PluginContext* Plugin::getPluginContext() const
+  {
+
+  }
+
+  long Plugin::getPluginId() const
+  {
+    return 0;
+  }
+
+  QString Plugin::getSymbolicName() const
+  {
+
+  }
+
+  Version Plugin::getVersion() const
+  {
+
+  }
+
+}

+ 50 - 0
Libs/Core/PluginFramework/ctkPlugin.h

@@ -0,0 +1,50 @@
+#ifndef CTKPLUGIN_H
+#define CTKPLUGIN_H
+
+#include "ctkPluginContext.h"
+
+#include "ctkVersion.h"
+
+namespace ctk {
+
+  class PluginPrivate;
+  class Plugin {
+
+    Q_DECLARE_PRIVATE(Plugin)
+
+  public:
+
+    enum State {
+      UNINSTALLED,
+      INSTALLED,
+      RESOLVED,
+      STARTING,
+      STOPPING,
+      ACTIVE
+    };
+
+    State state() const;
+
+    virtual void start();
+
+    virtual void stop();
+
+    PluginContext* getPluginContext() const;
+
+    long getPluginId() const;
+
+    QString getSymbolicName() const;
+
+    Version getVersion() const;
+
+  protected:
+
+    PluginPrivate * const d_ptr;
+
+    Plugin();
+    Plugin(PluginPrivate& dd);
+  };
+
+}
+
+#endif // CTKPLUGIN_H

+ 2 - 2
Libs/Core/PluginFramework/ctkPluginActivator.h

@@ -20,8 +20,8 @@ namespace ctk {
 
     virtual ~PluginActivator() {};
 
-    virtual void start(PluginContext::Pointer context) = 0;
-    virtual void stop(PluginContext::Pointer context) = 0;
+    virtual void start(PluginContext* context) = 0;
+    virtual void stop(PluginContext* context) = 0;
 
   };
 

+ 21 - 5
Libs/Core/PluginFramework/ctkPluginContext.cxx

@@ -7,7 +7,8 @@
 
 #include "ctkPluginContext.h"
 
-#include <QServiceManager>
+#include "ctkServiceRegistration.h"
+#include "ctkServiceReference.h"
 
 namespace ctk {
 
@@ -16,7 +17,7 @@ namespace ctk {
 
   public:
 
-	  QServiceManager serviceManager;
+
   };
 
 
@@ -30,10 +31,25 @@ namespace ctk {
 	  delete d;
   }
 
-  QServiceInterfaceDescriptor PluginContext::getServiceDescriptor(const QString& interfaceName) const
+  ServiceRegistration PluginContext::registerService(const QStringList& clazzes, QObject* service, const ServiceProperties& properties)
+  {
+
+  }
+
+  QList<ServiceReference> PluginContext::getServiceReferences(const QString& clazz, const QString& filter)
   {
-	Q_D(const PluginContext);
-	return d->serviceManager.interfaceDefault(interfaceName);
+
   }
 
+  ServiceReference PluginContext::getServiceReference(const QString& clazz)
+  {
+
+  }
+
+  QObject* PluginContext::getService(const ServiceReference& reference)
+  {
+
+  }
+
+
 }

+ 16 - 8
Libs/Core/PluginFramework/ctkPluginContext.h

@@ -8,15 +8,17 @@
 #ifndef CTKPLUGINCONTEXT_H_
 #define CTKPLUGINCONTEXT_H_
 
-#include <QSharedPointer>
-#include <QServiceInterfaceDescriptor>
+#include <QHash>
+#include <QString>
+#include <QVariant>
 
 #include "CTKCoreExport.h"
 
-using namespace QtMobility;
 
 namespace ctk {
 
+  class ServiceRegistration;
+  class ServiceReference;
   class PluginContextPrivate;
 
   class CTK_CORE_EXPORT PluginContext
@@ -26,16 +28,22 @@ namespace ctk {
 
   public:
 
-    //TODO use a macro
-    typedef QSharedPointer<PluginContext> Pointer;
+    typedef QHash<QString, QVariant> ServiceProperties;
 
-    PluginContext();
-    virtual ~PluginContext();
+    ~PluginContext();
+
+    ServiceRegistration registerService(const QStringList& clazzes, QObject* service, const ServiceProperties& properties = ServiceProperties());
+
+    QList<ServiceReference> getServiceReferences(const QString& clazz, const QString& filter = QString());
 
-    QServiceInterfaceDescriptor getServiceDescriptor(const QString& interfaceName) const;
+    ServiceReference getServiceReference(const QString& clazz);
+
+    QObject* getService(const ServiceReference& reference);
 
   protected:
 
+    PluginContext();
+
     PluginContextPrivate * const d_ptr;
   };
 

+ 30 - 0
Libs/Core/PluginFramework/ctkPluginFramework.h

@@ -0,0 +1,30 @@
+#ifndef CTKPLUGINFRAMEWORK_H
+#define CTKPLUGINFRAMEWORK_H
+
+#include "ctkPlugin.h"
+
+#include "ctkPluginRepository_p.h"
+
+namespace ctk {
+
+  class PluginFramework
+  {
+
+  public:
+
+    void launch();
+    void shutdown();
+
+  protected:
+
+    bool active;
+    PluginRepository plugins;
+
+    ServiceRegistry serviceRegistry;
+
+    InternalSystemPlugin systemPlugin;
+  };
+
+}
+
+#endif // CTKPLUGINFRAMEWORK_H

+ 28 - 3
Libs/Core/PluginFramework/ctkPluginManager.cxx

@@ -26,7 +26,32 @@ public:
 PluginManager::PluginManager()
 : d_ptr(new PluginManagerPrivate())
 {
+  Q_D(PluginManager);
 
+  QString libName("CTKCore");
+  QLibrary lib(libName);
+  QFileInfo fileInfo(libName);
+  QString libBaseName(fileInfo.baseName());
+  if (libBaseName.startsWith("lib"))
+  {
+    libBaseName.remove(0, 3);
+  }
+  qDebug() << libBaseName;
+  lib.load();
+  if (lib.isLoaded())
+  {
+    QString xyz = QString(":/") + libBaseName + "/servicedescriptor.xml";
+    qDebug() << "resource string: " << xyz;
+    QFile serviceDescriptor(xyz);
+    qDebug() << "file exists: " << serviceDescriptor.exists();
+    qDebug() << "open returns:" << serviceDescriptor.open(QIODevice::ReadOnly);
+    qDebug() << "file open: " << serviceDescriptor.isOpen();
+    qDebug() << "file is readable: " << serviceDescriptor.isReadable();
+    //QByteArray serviceBA = serviceDescriptor.readAll();
+    //qDebug() << serviceBA;
+    qDebug() << "Service for " << libBaseName << " registered:" << d->serviceManager.addService(&serviceDescriptor);
+    lib.unload();
+  }
 }
 
 PluginManager::~PluginManager()
@@ -72,9 +97,9 @@ void PluginManager::startAllPlugins()
          qDebug() << "resource string: " << xyz;
          QFile serviceDescriptor(xyz);
          //qDebug() << "file exists: " << serviceDescriptor.exists();
-         //qDebug() << "open returns:" << serviceDescriptor.open(QIODevice::ReadOnly);
-         //qDebug() << "file open: " << serviceDescriptor.isOpen();
-         //qDebug() << "file is readable: " << serviceDescriptor.isReadable();
+         qDebug() << "open returns:" << serviceDescriptor.open(QIODevice::ReadOnly);
+         qDebug() << "file open: " << serviceDescriptor.isOpen();
+         qDebug() << "file is readable: " << serviceDescriptor.isReadable();
          //QByteArray serviceBA = serviceDescriptor.readAll();
          //qDebug() << serviceBA;
          qDebug() << "Service for " << libBaseName << " registered:" << d->serviceManager.addService(&serviceDescriptor);

+ 20 - 0
Libs/Core/PluginFramework/ctkPluginPrivate_p.h

@@ -0,0 +1,20 @@
+#ifndef CTKPLUGINPRIVATE_P_H
+#define CTKPLUGINPRIVATE_P_H
+
+namespace ctk {
+
+  class PluginPrivate {
+
+  public:
+
+    virtual ~PluginPrivate();
+
+    void load();
+
+    QHash<QString, QString> getHeaders(const QString& )
+
+  };
+
+}
+
+#endif // CTKPLUGINPRIVATE_P_H

+ 135 - 0
Libs/Core/PluginFramework/ctkPluginRepository.cxx

@@ -0,0 +1,135 @@
+#include "ctkPluginRepository_p.h"
+
+namespace ctk {
+
+  const QList<Plugin*>& PluginRepository::getPlugins() const
+  {
+    return pluginsByInstallOrder;
+  }
+
+  Plugin* PluginRepository::getPlugin(long pluginId) const
+  {
+    return pluginsById[pluginId];
+  }
+
+  QList<Plugin*> PluginRepository::getPlugins(const QString& symbolicName) const
+  {
+    return pluginsBySymbolicName[symbolicName];
+  }
+
+  Plugin* PluginRepository::getPlugin(const QString& symbolicName, const Version& version)
+  {
+    const QList<Plugin*>& plugins = getPlugins(symbolicName);
+    if (!plugins.isEmpty())
+    {
+      QListIterator<Plugin*> i(plugins);
+      while (i.hasNext())
+      {
+        Plugin* plugin = i.next();
+        if (plugin->getVersion() == version)
+        {
+          return plugin;
+        }
+      }
+    }
+    return 0;
+  }
+
+  void PluginRepository::add(Plugin* plugin)
+  {
+    pluginsByInstallOrder.push_back(plugin);
+    pluginsById.insert(plugin->getPluginId(), plugin);
+    addSymbolicName(plugin);
+  }
+
+  bool PluginRepository::remove(Plugin* plugin)
+  {
+    // remove by plugin id
+    int count = pluginsById.remove(plugin->getPluginId());
+    if (count == 0) return false;
+
+    // remove by install order
+    pluginsByInstallOrder.removeAll(plugin);
+    // remove by symbolic name
+    QString symbolicName = plugin->getSymbolicName();
+    if (symbolicName.isEmpty()) return true;
+    removeSymbolicName(symbolicName, plugin);
+    return true;
+  }
+
+  void PluginRepository::update(const QString& oldSymbolicName, Plugin* plugin)
+  {
+    if (!oldSymbolicName.isEmpty())
+    {
+      if (oldSymbolicName != plugin->getSymbolicName())
+      {
+        removeSymbolicName(oldSymbolicName, plugin);
+        addSymbolicName(plugin);
+      }
+    }
+    else
+    {
+      addSymbolicName(plugin);
+    }
+  }
+
+  void PluginRepository::removeAllPlugins() {
+    pluginsByInstallOrder.clear();
+    pluginsById.clear();
+    pluginsBySymbolicName.clear();
+  }
+
+  void PluginRepository::addSymbolicName(Plugin* plugin)
+  {
+    QString symbolicName = plugin->getSymbolicName();
+    if (symbolicName.isNull()) return;
+    QList<Plugin*>& plugins = pluginsBySymbolicName[symbolicName];
+    if (plugins.empty())
+    {
+      plugins.push_back(plugin);
+      return;
+    }
+
+    QList<Plugin*> list;
+    const Version& newVersion = plugin->getVersion();
+    bool added = false;
+    QListIterator<Plugin*> i(plugins);
+    while (i.hasNext())
+    {
+      Plugin* oldPlugin = i.next();
+      if (!added && newVersion.compare(oldPlugin->getVersion()) >= 0)
+      {
+        added = true;
+        list.push_back(plugin);
+      }
+      list.push_back(oldPlugin);
+    }
+    if (!added)
+    {
+      list.push_back(plugin);
+    }
+
+    pluginsBySymbolicName.insert(symbolicName, list);
+  }
+
+  void PluginRepository::removeSymbolicName(const QString& symbolicName, Plugin* plugin)
+  {
+    QList<Plugin*>& plugins = pluginsBySymbolicName[symbolicName];
+    if (plugins.isEmpty()) return;
+
+    // found some plugins with the global name.
+    // remove all references to the specified plugin.
+    QMutableListIterator<Plugin*> i(plugins);
+    while(i.hasNext())
+    {
+      if (i.next() == plugin)
+        i.remove();
+    }
+
+    if (plugins.isEmpty())
+    {
+      pluginsBySymbolicName.remove(symbolicName);
+    }
+  }
+
+}

+ 50 - 0
Libs/Core/PluginFramework/ctkPluginRepository_p.h

@@ -0,0 +1,50 @@
+#ifndef CTKPLUGINREPOSITORY_P_H
+#define CTKPLUGINREPOSITORY_P_H
+
+#include "ctkPlugin.h"
+
+#include "ctkVersion.h"
+
+#include <QList>
+#include <QHash>
+
+
+namespace ctk {
+
+  class PluginRepository {
+
+  private:
+
+    QList<Plugin*> pluginsByInstallOrder;
+    QHash<long, Plugin*> pluginsById;
+    QHash<QString, QList<Plugin*> > pluginsBySymbolicName;
+
+  public:
+
+    const QList<Plugin*>& getPlugins() const;
+
+    Plugin* getPlugin(long pluginId) const;
+
+    QList<Plugin*> getPlugins(const QString& symbolicName) const;
+
+    Plugin* getPlugin(const QString& symbolicName, const Version& version);
+
+    void add(Plugin* plugin);
+
+    bool remove(Plugin* plugin);
+
+    void update(const QString& oldSymbolicName, Plugin* plugin);
+
+    void removeAllPlugins();
+
+  private:
+
+    void addSymbolicName(Plugin* plugin);
+
+    void removeSymbolicName(const QString& symbolicName, Plugin* plugin);
+
+  };
+
+}
+
+#endif // CTKPLUGINREPOSITORY_P_H

+ 32 - 0
Libs/Core/PluginFramework/ctkServiceReference.cxx

@@ -0,0 +1,32 @@
+#include "ctkServiceReference.h"
+
+#include <QStringList>
+
+namespace ctk {
+
+  QVariant ServiceReference::getProperty(const QString& key) const
+  {
+    return QVariant();
+  }
+
+  QStringList ServiceReference::getPropertyKeys() const
+  {
+    return QStringList();
+  }
+
+  Plugin* ServiceReference::getPlugin() const
+  {
+    return 0;
+  }
+
+  QList<Plugin*> ServiceReference::getUsingPlugins() const
+  {
+    return QList<Plugin*>();
+  }
+
+  bool ServiceReference::operator<(const ServiceReference& reference) const
+  {
+    return false;
+  }
+
+}

+ 28 - 0
Libs/Core/PluginFramework/ctkServiceReference.h

@@ -0,0 +1,28 @@
+#ifndef CTKSERVICEREFERENCE_H
+#define CTKSERVICEREFERENCE_H
+
+#include <QVariant>
+
+#include "ctkPlugin.h"
+
+namespace ctk {
+
+  class ServiceReference {
+
+  public:
+
+    QVariant getProperty(const QString& key) const;
+
+    QStringList getPropertyKeys() const;
+
+    Plugin* getPlugin() const;
+
+    QList<Plugin*> getUsingPlugins() const;
+
+    bool operator<(const ServiceReference& reference) const;
+
+  };
+
+}
+
+#endif // CTKSERVICEREFERENCE_H

+ 20 - 0
Libs/Core/PluginFramework/ctkServiceRegistration.cxx

@@ -0,0 +1,20 @@
+#include "ctkServiceRegistration.h"
+
+namespace ctk {
+
+  ServiceReference ServiceRegistration::getReference() const
+  {
+
+  }
+
+  void ServiceRegistration::setProperties(const PluginContext::ServiceProperties& properties)
+  {
+
+  }
+
+  void ServiceRegistration::unregister() const
+  {
+
+  }
+
+}

+ 24 - 0
Libs/Core/PluginFramework/ctkServiceRegistration.h

@@ -0,0 +1,24 @@
+#ifndef CTKSERVICEREGISTRATION_H
+#define CTKSERVICEREGISTRATION_H
+
+#include "ctkPluginContext.h"
+
+#include "ctkServiceReference.h"
+
+namespace ctk {
+
+  class ServiceRegistration {
+
+  public:
+
+    ServiceReference getReference() const;
+
+    void setProperties(const PluginContext::ServiceProperties& properties);
+
+    void unregister() const;
+
+  };
+
+}
+
+#endif // CTKSERVICEREGISTRATION_H

+ 174 - 0
Libs/Core/PluginFramework/ctkVersion.cxx

@@ -0,0 +1,174 @@
+#include "ctkVersion.h"
+
+#include <QStringListIterator>
+
+namespace ctk {
+
+  const QString Version::SEPARATOR = ".";
+  const QRegExp Version::RegExp = QRegExp("[a-zA-Z0-9_\\-]*");
+  const Version Version::emptyVersion = Version(0, 0, 0);
+
+
+  void Version::validate()
+  {
+    valid = RegExp.exactMatch(qualifier);
+  }
+
+  Version::Version(unsigned int major, unsigned int minor, unsigned int micro)
+    : valid(true), major(major), minor(minor), micro(micro), qualifier("")
+  {
+
+  }
+
+  Version::Version(unsigned int major, unsigned int minor, unsigned int micro, const QString& qualifier)
+     : valid(false), major(major), minor(minor), micro(micro), qualifier(qualifier)
+  {
+    this->validate();
+  }
+
+  Version::Version(const QString& version)
+    : valid(false), major(0), minor(0), micro(0), qualifier("")
+  {
+    unsigned int maj = 0;
+    unsigned int min = 0;
+    unsigned int mic = 0;
+    QString qual("");
+
+    QStringList st = version.split(SEPARATOR);
+
+    if (st.empty()) return;
+
+    QStringListIterator i(st);
+
+    bool ok = true;
+    maj = i.next().toUInt(&ok);
+
+    if (i.hasNext())
+    {
+      min = i.next().toUInt(&ok);
+      if (i.hasNext())
+      {
+        mic = i.next().toUInt(&ok);
+        if (i.hasNext())
+        {
+          qual = i.next();
+          if (i.hasNext())
+          {
+             ok = false;
+          }
+        }
+      }
+    }
+
+    if (!ok) return;
+
+    major = maj;
+    minor = min;
+    micro = mic;
+    qualifier = qual;
+    this->validate();
+  }
+
+  Version::Version(const Version& version)
+  : valid(version.valid), major(version.major), minor(version.minor),
+    micro(version.micro), qualifier(version.qualifier)
+  {
+
+  }
+
+  Version Version::parseVersion(const QString& version)
+  {
+    if (version.isEmpty())
+    {
+      return emptyVersion;
+    }
+
+    QString version2 = version.trimmed();
+    if (version2.isEmpty())
+    {
+      return emptyVersion;
+    }
+
+    return Version(version2);
+  }
+
+  unsigned int Version::getMajor() const
+  {
+    return major;
+  }
+
+  unsigned int Version::getMinor() const
+  {
+    return minor;
+  }
+
+  unsigned int Version::getMicro() const
+  {
+    return micro;
+  }
+
+  QString Version::getQualifier() const
+  {
+    return qualifier;
+  }
+
+  QString Version::toString() const
+  {
+    QString result;
+    result += QString::number(major) + SEPARATOR + QString::number(minor) + SEPARATOR + QString::number(micro);
+    if (!qualifier.isEmpty())
+    {
+      result += SEPARATOR + qualifier;
+    }
+    return result;
+  }
+
+  bool Version::operator==(const Version& other) const
+  {
+    if (&other == this)
+    { // quicktest
+      return true;
+    }
+
+    return (major == other.major) && (minor == other.minor) && (micro
+        == other.micro) && qualifier == other.qualifier;
+  }
+
+  int Version::compare(const Version& other) const
+  {
+    if (&other == this)
+    { // quicktest
+      return 0;
+    }
+
+    if (major < other.major)
+    {
+      return -1;
+    }
+
+    if (major == other.major)
+    {
+
+      if (minor < other.minor)
+      {
+        return -1;
+      }
+
+      if (minor == other.minor)
+      {
+
+        if (micro < other.micro)
+        {
+          return -1;
+        }
+
+        if (micro == other.micro)
+        {
+          return qualifier.compare(other.qualifier);
+        }
+      }
+    }
+    return 1;
+  }
+
+}

+ 214 - 0
Libs/Core/PluginFramework/ctkVersion.h

@@ -0,0 +1,214 @@
+#ifndef CTKVERSION_H
+#define CTKVERSION_H
+
+#include <QString>
+#include <QRegExp>
+
+namespace ctk {
+
+  /**
+   * Version identifier for plug-ins and packages.
+   *
+   * <p>
+   * Version identifiers have four components.
+   * <ol>
+   * <li>Major version. A non-negative integer.</li>
+   * <li>Minor version. A non-negative integer.</li>
+   * <li>Micro version. A non-negative integer.</li>
+   * <li>Qualifier. A text string. See <code>Version(const QString&)</code> for the
+   * format of the qualifier string.</li>
+   * </ol>
+   *
+   * <p>
+   * <code>Version</code> objects are immutable.
+   *
+   * @Immutable
+   */
+
+  class Version {
+
+  private:
+
+    bool valid;
+
+    unsigned int major;
+    unsigned int minor;
+    unsigned int micro;
+    QString      qualifier;
+
+    static const QString SEPARATOR; //  = "."
+    static const QRegExp RegExp;
+
+
+    /**
+     * Called by the Version constructors to validate the version components.
+     *
+     * @return <code>true</code> if the validation was successfull, <code>false</code> otherwise.
+     */
+    void validate();
+
+  public:
+
+    /**
+     * The empty version "0.0.0".
+     */
+    static const Version emptyVersion;
+
+    /**
+     * Creates a version identifier from the specified numerical components.
+     *
+     * <p>
+     * The qualifier is set to the empty string.
+     *
+     * @param major Major component of the version identifier.
+     * @param minor Minor component of the version identifier.
+     * @param micro Micro component of the version identifier.
+     *
+     */
+    Version(unsigned int major, unsigned int minor, unsigned int micro);
+
+    /**
+     * Creates a version identifier from the specified components.
+     *
+     * @param major Major component of the version identifier.
+     * @param minor Minor component of the version identifier.
+     * @param micro Micro component of the version identifier.
+     * @param qualifier Qualifier component of the version identifier.
+     */
+    Version(unsigned int major, unsigned int minor, unsigned int micro, const QString& qualifier);
+
+    /**
+     * Created a version identifier from the specified string.
+     *
+     * <p>
+     * Here is the grammar for version strings.
+     *
+     * <pre>
+     * version ::= major('.'minor('.'micro('.'qualifier)?)?)?
+     * major ::= digit+
+     * minor ::= digit+
+     * micro ::= digit+
+     * qualifier ::= (alpha|digit|'_'|'-')+
+     * digit ::= [0..9]
+     * alpha ::= [a..zA..Z]
+     * </pre>
+     *
+     * There must be no whitespace in version.
+     *
+     * @param version string representation of the version identifier.
+     */
+    Version(const QString& version);
+
+    /**
+     * Create a version identifier from another.
+     *
+     * @param version Another version identifier
+     */
+    Version(const Version& version);
+
+
+    /**
+     * Parses a version identifier from the specified string.
+     *
+     * <p>
+     * See <code>Version(const QString&)</code> for the format of the version string.
+     *
+     * @param version string representation of the version identifier. Leading
+     *        and trailing whitespace will be ignored.
+     * @return A <code>Version</code> object representing the version
+     *         identifier. If <code>version</code> is the empty string
+     *         then <code>emptyVersion</code> will be
+     *         returned.
+     */
+    static Version parseVersion(const QString& version);
+
+    /**
+     * Returns if the version is valid.
+     */
+    bool isValid() const;
+
+    /**
+     * Returns the major component of this version identifier.
+     *
+     * @return The major component.
+     */
+    unsigned int getMajor() const;
+
+    /**
+     * Returns the minor component of this version identifier.
+     *
+     * @return The minor component.
+     */
+    unsigned int getMinor() const;
+
+    /**
+     * Returns the micro component of this version identifier.
+     *
+     * @return The micro component.
+     */
+    unsigned int getMicro() const;
+
+    /**
+     * Returns the qualifier component of this version identifier.
+     *
+     * @return The qualifier component.
+     */
+    QString getQualifier() const;
+
+    /**
+     * Returns the string representation of this version identifier.
+     *
+     * <p>
+     * The format of the version string will be <code>major.minor.micro</code>
+     * if qualifier is the empty string or
+     * <code>major.minor.micro.qualifier</code> otherwise.
+     *
+     * @return The string representation of this version identifier.
+     */
+    QString toString() const;
+
+    /**
+     * Compares this <code>Version</code> object to another object.
+     *
+     * <p>
+     * A version is considered to be <b>equal to </b> another version if the
+     * major, minor and micro components are equal and the qualifier component
+     * is equal.
+     *
+     * @param object The <code>Version</code> object to be compared.
+     * @return <code>true</code> if <code>object</code> is a
+     *         <code>Version</code> and is equal to this object;
+     *         <code>false</code> otherwise.
+     */
+    bool operator==(const Version& object) const;
+
+    /**
+     * Compares this <code>Version</code> object to another object.
+     *
+     * <p>
+     * A version is considered to be <b>less than </b> another version if its
+     * major component is less than the other version's major component, or the
+     * major components are equal and its minor component is less than the other
+     * version's minor component, or the major and minor components are equal
+     * and its micro component is less than the other version's micro component,
+     * or the major, minor and micro components are equal and it's qualifier
+     * component is less than the other version's qualifier component (using
+     * <code>std::string::compare</code>).
+     *
+     * <p>
+     * A version is considered to be <b>equal to</b> another version if the
+     * major, minor and micro components are equal and the qualifier component
+     * is equal.
+     *
+     * @param object The <code>Version</code> object to be compared.
+     * @return A negative integer, zero, or a positive integer if this object is
+     *         less than, equal to, or greater than the specified
+     *         <code>Version</code> object.
+     */
+    int compare(const Version& object) const;
+
+  };
+
+}
+
+#endif // CTKVERSION_H

+ 3 - 2
Plugins/org.commontk.cli/ctkCLIPlugin.cxx

@@ -8,17 +8,18 @@
 #include "ctkCLIPlugin.h"
 
 #include <QtPlugin>
+#include <QServiceInterfaceDescriptor>
 
 #include <iostream>
 
 namespace ctk {
 
-  void CLIPlugin::start(PluginContext::Pointer context)
+  void CLIPlugin::start(PluginContext* context)
   {
     std::cout << "Plugin A started\n";
   }
 
-  void CLIPlugin::stop(PluginContext::Pointer context)
+  void CLIPlugin::stop(PluginContext* context)
   {
     std::cout << "Plugin B stopped\n";
   }

+ 2 - 2
Plugins/org.commontk.cli/ctkCLIPlugin.h

@@ -25,8 +25,8 @@ namespace ctk {
 
   public:
 
-    void start(PluginContext::Pointer context);
-    void stop(PluginContext::Pointer context);
+    void start(PluginContext* context);
+    void stop(PluginContext* context);
 
     QObject* createInstance(const QServiceInterfaceDescriptor& descriptor,
                             QServiceContext* context,

+ 31 - 0
Plugins/org.commontk.eventbus/CMakeLists.txt

@@ -0,0 +1,31 @@
+PROJECT(org_commontk_eventbus)
+
+SET(PLUGIN_export_directive "org_commontk_eventbus_EXPORT")
+
+SET(PLUGIN_SRCS
+  ctkEventBusImpl.cxx
+  ctkEventBusPlugin.cxx
+)
+
+SET(PLUGIN_MOC_SRCS
+  ctkEventBusImpl_p.h
+  ctkEventBusPlugin_p.h
+  ctkEventHandlerWrapper_p.h
+)
+
+SET(PLUGIN_resources
+  org_commontk_eventbus.qrc
+)
+
+SET(LIBRARY_OUTPUT_PATH ${LIBRARY_OUTPUT_PATH}/Plugins)
+
+ctkMacroGetTargetLibraries(PLUGIN_target_libraries)
+
+ctkMacroBuildQtPlugin(
+  NAME ${PROJECT_NAME}
+  EXPORT_DIRECTIVE ${PLUGIN_export_directive}
+  SRCS ${PLUGIN_SRCS}
+  MOC_SRCS ${PLUGIN_MOC_SRCS}
+  RESOURCES ${PLUGIN_resources}
+  TARGET_LIBRARIES ${PLUGIN_target_libraries}
+)

+ 73 - 0
Plugins/org.commontk.eventbus/ctkEventBusImpl.cxx

@@ -0,0 +1,73 @@
+#include "ctkEventBusImpl_p.h"
+
+#include <QSetIterator>
+
+#include "ctkEventHandlerWrapper_p.h"
+
+namespace ctk {
+
+  EventBusImpl* EventBusImpl::instance()
+  {
+    static EventBusImpl inst;
+    return &inst;
+  }
+
+  EventBusImpl::EventBusImpl()
+  {
+
+  }
+
+  void EventBusImpl::postEvent(const Event& event)
+  {
+    dispatchEvent(event, true);
+  }
+
+  void EventBusImpl::sendEvent(const Event& event)
+  {
+    dispatchEvent(event, false);
+  }
+
+  void EventBusImpl::publishSignal(const QObject* publisher, const char* signal)
+  {
+
+  }
+
+  void EventBusImpl::subscribeSlot(const QObject* subscriber, const char* member, const Properties& properties)
+  {
+
+    // TODO check for duplicates
+
+    EventHandlerWrapper* wrapper = new EventHandlerWrapper(subscriber, member, properties);
+    if (wrapper->init())
+    {
+      bucket(wrapper);
+    }
+  }
+
+  void EventBusImpl::dispatchEvent(const Event& event, bool isAsync)
+  {
+    QString topic = event.topic();
+
+    QSet<EventHandlerWrapper*> eventHandlers = this->handlers(topic);
+    if (eventHandlers.empty()) return;
+
+    QSetIterator<EventHandlerWrapper*> iter(eventHandlers);
+    while (iter.hasNext())
+    {
+      iter.next()->handleEvent(event);
+    }
+  }
+
+  void EventBusImpl::bucket(EventHandlerWrapper* wrapper)
+  {
+    // TODO bucket logic
+    globalWildcard.push_back(wrapper);
+  }
+
+  QSet<EventHandlerWrapper*> EventBusImpl::handlers(const QString& topic)
+  {
+    // TODO
+    return globalWildcard.toSet();
+  }
+
+}

+ 52 - 0
Plugins/org.commontk.eventbus/ctkEventBusImpl_p.h

@@ -0,0 +1,52 @@
+#ifndef CTKEVENTBUSIMPL_H
+#define CTKEVENTBUSIMPL_H
+
+#include <EventBus/ctkEventBus.h>
+
+#include <QList>
+#include <QHash>
+#include <QSet>
+
+namespace ctk {
+
+  class EventHandlerWrapper;
+
+  class EventBusImpl : public QObject,
+                       public EventBus
+  {
+    Q_OBJECT
+    Q_INTERFACES(ctk::EventBus)
+
+  public:
+
+    static EventBusImpl* instance();
+
+    void postEvent(const Event& event);
+    void sendEvent(const Event& event);
+
+    void publishSignal(const QObject* publisher, const char* signal);
+
+    void subscribeSlot(const QObject* subscriber, const char* member, const Properties& properties);
+
+  protected:
+
+    typedef QList<EventHandlerWrapper*> HandlerList;
+
+    HandlerList globalWildcard;
+
+    QHash<QString, HandlerList> topicName;
+
+    void dispatchEvent(const Event& event, bool isAsync);
+
+    void bucket(EventHandlerWrapper* wrapper);
+
+    QSet<EventHandlerWrapper*> handlers(const QString& topic);
+
+  private:
+
+    EventBusImpl();
+  };
+
+}
+
+#endif // CTKEVENTBUSIMPL_H

+ 42 - 0
Plugins/org.commontk.eventbus/ctkEventBusPlugin.cxx

@@ -0,0 +1,42 @@
+/*
+ * ctkEventBusPlugin.cxx
+ *
+ *  Created on: Mar 29, 2010
+ *      Author: zelzer
+ */
+
+#include "ctkEventBusPlugin_p.h"
+
+#include <QtPlugin>
+#include <QServiceInterfaceDescriptor>
+
+#include "ctkEventBusImpl_p.h"
+
+#include <iostream>
+
+namespace ctk {
+
+  void EventBusPlugin::start(PluginContext* context)
+  {
+    std::cout << "ctkCore Plugin started\n";
+  }
+
+  void EventBusPlugin::stop(PluginContext* context)
+  {
+    std::cout << "ctkCore Plugin stopped\n";
+  }
+
+  QObject* EventBusPlugin::createInstance(const QServiceInterfaceDescriptor& descriptor,
+                              QServiceContext* context,
+                              QAbstractSecuritySession* session)
+  {
+    std::cout << "Creating service instance for " << descriptor.interfaceName().toStdString() << std::endl;
+    if (descriptor.interfaceName() == "org.commontk.core.EventBus")
+    {
+      return EventBusImpl::instance();
+    }
+  }
+
+Q_EXPORT_PLUGIN2(org_commontk_eventbus, EventBusPlugin)
+
+}

+ 32 - 0
Plugins/org.commontk.eventbus/ctkEventBusPlugin_p.h

@@ -0,0 +1,32 @@
+#ifndef CTKEVENTBUSPLUGIN_H
+#define CTKEVENTBUSPLUGIN_H
+
+#include <PluginFramework/ctkPluginActivator.h>
+
+#include <QServicePluginInterface>
+
+using namespace QtMobility;
+
+namespace ctk {
+
+  class EventBusPlugin : public QObject,
+                     public PluginActivator,
+                     public QServicePluginInterface
+  {
+    Q_OBJECT
+    Q_INTERFACES(ctk::PluginActivator QtMobility::QServicePluginInterface)
+
+  public:
+
+    void start(PluginContext* context);
+    void stop(PluginContext* context);
+
+    QObject* createInstance(const QServiceInterfaceDescriptor& descriptor,
+                            QServiceContext* context,
+                            QAbstractSecuritySession* session);
+
+  };
+
+}
+
+#endif // CTKEVENTBUSPLUGIN_H

+ 80 - 0
Plugins/org.commontk.eventbus/ctkEventHandlerWrapper_p.h

@@ -0,0 +1,80 @@
+#ifndef CTKEVENTHANDLERWRAPPER_P_H
+#define CTKEVENTHANDLERWRAPPER_P_H
+
+#include <QStringList>
+
+#include <EventBus/ctkEventBus.h>
+#include <EventBus/ctkEventConstants.h>
+#include <PluginFramework/ctkLDAPSearchFilter.h>
+
+#include <iostream>
+
+namespace ctk {
+
+  class EventHandlerWrapper : public QObject {
+
+    Q_OBJECT
+
+  private:
+
+    EventBus::Properties properties;
+    QStringList topicList;
+    LDAPSearchFilter filter;
+
+  public:
+
+    EventHandlerWrapper(const QObject* subscriber, const char* handler, const EventBus::Properties& properties)
+      : properties(properties)
+    {
+      connect(this, SIGNAL(notifySubscriber(Event)), subscriber, handler);
+    }
+
+    QStringList topics() const
+    {
+      return topicList;
+    }
+
+    bool init()
+    {
+      topicList.clear();
+
+      // Get topic names
+      QVariant v = properties[EventConstants::EVENT_TOPIC];
+      topicList = v.toStringList();
+
+      if (topicList.empty())
+      {
+        return false;
+      }
+
+      v = properties[EventConstants::EVENT_FILTER];
+      filter = LDAPSearchFilter(v.toString());
+    }
+
+    void handleEvent(const Event& event /*, const Permission& perm */)
+    {
+      if (!event.matches(filter)) return;
+
+      // should do permissions checks now somehow
+      // ...
+
+      try {
+        emit notifySubscriber(event);
+      }
+      catch (const std::exception& e)
+      {
+        // TODO logging
+        std::cerr << "Exception occured during publishing " << qPrintable(event.topic()) << ": " << e.what() << std::endl;
+      }
+
+    }
+
+  signals:
+
+    void notifySubscriber(const Event&);
+
+  };
+
+}
+
+#endif // CTKEVENTHANDLERWRAPPER_P_H

+ 5 - 0
Plugins/org.commontk.eventbus/org_commontk_eventbus.qrc

@@ -0,0 +1,5 @@
+<RCC>
+    <qresource prefix="/org_commontk_eventbus">
+        <file>servicedescriptor.xml</file>
+    </qresource>
+</RCC>

+ 11 - 0
Plugins/org.commontk.eventbus/servicedescriptor.xml

@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<service>
+  <name>ctkEventBus</name>
+    <filepath>libCTKCore</filepath>
+    <interface>
+      <name>org.commontk.core.EventBus</name>
+      <version>1.0</version>
+      <capabilities></capabilities>
+      <description>Interface for the CTK event bus</description>
+    </interface>
+</service>

+ 9 - 0
Plugins/org.commontk.eventbus/target_libraries.cmake

@@ -0,0 +1,9 @@
+#
+# See CMake/ctkMacroGetTargetLibraries.cmake
+# 
+# This file should list the libraries required to build the current CTK application.
+# 
+
+SET(target_libraries
+  CTKCore
+  )