Browse Source

Templated ctkServiceTracker for type safety.

Sascha Zelzer 14 years ago
parent
commit
6d89dce222
23 changed files with 422 additions and 287 deletions
  1. 9 9
      Libs/PluginFramework/CMakeLists.txt
  2. 2 2
      Libs/PluginFramework/Testing/FrameworkTest/ctkPluginFrameworkTestSuite.cpp
  3. 1 1
      Libs/PluginFramework/Testing/TestPlugins/pluginA2_test/ctkTestPluginAService.h
  4. 3 3
      Libs/PluginFramework/Testing/TestPlugins/pluginA2_test/ctkTestPluginA_p.h
  5. 1 1
      Libs/PluginFramework/Testing/TestPlugins/pluginA_test/ctkTestPluginAService.h
  6. 1 1
      Libs/PluginFramework/Testing/TestPlugins/pluginA_test/ctkTestPluginA_p.h
  7. 6 7
      Libs/PluginFramework/Testing/TestPlugins/pluginSL1_test/ctkActivatorSL1.cpp
  8. 8 7
      Libs/PluginFramework/Testing/TestPlugins/pluginSL1_test/ctkActivatorSL1_p.h
  9. 6 7
      Libs/PluginFramework/Testing/TestPlugins/pluginSL3_test/ctkActivatorSL3.cpp
  10. 8 5
      Libs/PluginFramework/Testing/TestPlugins/pluginSL3_test/ctkActivatorSL3_p.h
  11. 46 63
      Libs/PluginFramework/ctkPluginAbstractTracked.cpp
  12. 23 21
      Libs/PluginFramework/ctkPluginAbstractTracked_p.h
  13. 3 4
      Libs/PluginFramework/ctkServiceReference.h
  14. 86 60
      Libs/PluginFramework/ctkServiceTracker.cpp
  15. 63 16
      Libs/PluginFramework/ctkServiceTracker.h
  16. 6 4
      Libs/PluginFramework/ctkServiceTrackerCustomizer.h
  17. 22 16
      Libs/PluginFramework/ctkServiceTrackerPrivate.cpp
  18. 27 16
      Libs/PluginFramework/ctkServiceTrackerPrivate.h
  19. 26 24
      Libs/PluginFramework/ctkTrackedService.cpp
  20. 52 0
      Libs/PluginFramework/ctkTrackedServiceListener_p.h
  21. 14 15
      Libs/PluginFramework/ctkTrackedService_p.h
  22. 3 3
      Plugins/org.commontk.qtmobility.service/ctkQtMobilityServiceActivator.cpp
  23. 6 2
      Plugins/org.commontk.qtmobility.service/ctkQtMobilityServiceActivator_p.h

+ 9 - 9
Libs/PluginFramework/CMakeLists.txt

@@ -27,8 +27,8 @@ SET(KIT_SRCS
   ctkPluginFrameworkUtil.cpp
   ctkPluginManifest.cpp
   ctkPluginPrivate.cpp
-  ctkPluginTracker.cpp
-  ctkPluginTrackerPrivate.cpp
+  #ctkPluginTracker.cpp
+  #ctkPluginTrackerPrivate.cpp
   ctkPlugins.cpp
   ctkRequirePlugin.cpp
   ctkServiceEvent.cpp
@@ -38,13 +38,13 @@ SET(KIT_SRCS
   ctkServiceReferencePrivate.cpp
   ctkServiceRegistration.cpp
   ctkServiceRegistrationPrivate.cpp
-  ctkServiceTracker.cpp
-  ctkServiceTrackerCustomizer.h
-  ctkServiceTrackerPrivate.cpp
+  #ctkServiceTracker.cpp
+  #ctkServiceTrackerCustomizer.h
+  #ctkServiceTrackerPrivate.cpp
   ctkServices.cpp
   ctkServiceSlotEntry.cpp
-  ctkTrackedPlugin.cpp
-  ctkTrackedService.cpp
+  #ctkTrackedPlugin.cpp
+  #ctkTrackedService.cpp
   ctkPluginStorage.cpp
   ctkVersion.cpp
   ctkVersionRange.cpp
@@ -60,8 +60,8 @@ SET(KIT_SRCS
 SET(KIT_MOC_SRCS
   ctkPluginFrameworkListeners_p.h
   ctkServiceFactory.h
-  ctkTrackedPlugin_p.h
-  ctkTrackedService_p.h
+  #ctkTrackedPlugin_p.h
+  ctkTrackedServiceListener_p.h
 )
 
 # UI files

+ 2 - 2
Libs/PluginFramework/Testing/FrameworkTest/ctkPluginFrameworkTestSuite.cpp

@@ -254,7 +254,7 @@ void ctkPluginFrameworkTestSuite::frame025b()
   // Check if pluginA_test registered the expected service
   try
   {
-    ctkServiceReference sr1 = pc->getServiceReference("org.commontk.TestPluginAService");
+    ctkServiceReference sr1 = pc->getServiceReference("org.commontk.pluginAtest.TestPluginAService");
     QObject* o1 = pc->getService(sr1);
     QVERIFY2(o1 != 0, "no service object found");
 
@@ -294,7 +294,7 @@ void ctkPluginFrameworkTestSuite::frame025b()
 void ctkPluginFrameworkTestSuite::frame030b()
 {
   ctkServiceReference sr1
-      = pc->getServiceReference("org.commontk.TestPluginAService");
+      = pc->getServiceReference("org.commontk.pluginAtest.TestPluginAService");
 
   try
   {

+ 1 - 1
Libs/PluginFramework/Testing/TestPlugins/pluginA2_test/ctkTestPluginAService.h

@@ -30,6 +30,6 @@ struct ctkTestPluginAService
   virtual ~ctkTestPluginAService() {}
 };
 
-Q_DECLARE_INTERFACE(ctkTestPluginAService, "org.commontk.TestPluginAService")
+Q_DECLARE_INTERFACE(ctkTestPluginAService, "org.commontk.pluginA2test.TestPluginAService")
 
 #endif // CTKTESTPLUGINASERVICE_H

+ 3 - 3
Libs/PluginFramework/Testing/TestPlugins/pluginA2_test/ctkTestPluginA_p.h

@@ -37,13 +37,13 @@ class ctkTestPluginA : public QObject,
   Q_INTERFACES(ctkTestPluginAService)
 
 public:
-    ctkTestPluginA(ctkPluginContext* pc);
+  ctkTestPluginA(ctkPluginContext* pc);
 
-    void unregister();
+  void unregister();
 
 private:
 
-    ctkServiceRegistration* sr;
+  ctkServiceRegistration* sr;
 };
 
 #endif // CTKTESTPLUGINA_P_H

+ 1 - 1
Libs/PluginFramework/Testing/TestPlugins/pluginA_test/ctkTestPluginAService.h

@@ -30,6 +30,6 @@ struct ctkTestPluginAService
   virtual ~ctkTestPluginAService() {}
 };
 
-Q_DECLARE_INTERFACE(ctkTestPluginAService, "org.commontk.TestPluginAService")
+Q_DECLARE_INTERFACE(ctkTestPluginAService, "org.commontk.pluginAtest.TestPluginAService")
 
 #endif // CTKTESTPLUGINASERVICE_H

+ 1 - 1
Libs/PluginFramework/Testing/TestPlugins/pluginA_test/ctkTestPluginA_p.h

@@ -36,7 +36,7 @@ class ctkTestPluginA : public QObject,
   Q_INTERFACES(ctkTestPluginAService)
 
 public:
-    ctkTestPluginA(ctkPluginContext* pc);
+  ctkTestPluginA(ctkPluginContext* pc);
 };
 
 #endif // CTKTESTPLUGINA_P_H

+ 6 - 7
Libs/PluginFramework/Testing/TestPlugins/pluginSL1_test/ctkActivatorSL1.cpp

@@ -43,7 +43,7 @@ void ctkActivatorSL1::start(ctkPluginContext* context)
 
   context->registerService(this->metaObject()->className(), this);
 
-  tracker.reset(new ctkServiceTracker(context, "ctkFooService", this));
+  tracker.reset(new FooTracker(context, this));
   tracker->open();
 }
 
@@ -63,24 +63,23 @@ bool ctkActivatorSL1::serviceRemoved() const
   return _serviceRemoved;
 }
 
-QObject* ctkActivatorSL1::addingService(const ctkServiceReference& reference)
+ctkFooService* ctkActivatorSL1::addingService(const ctkServiceReference& reference)
 {
   _serviceAdded = true;
   qDebug() << "Adding reference =" << reference;
 
-  QObject* serviceObject = context->getService(reference);
-  ctkFooService* fooService = qobject_cast<ctkFooService*>(serviceObject);
+  ctkFooService* fooService = context->getService<ctkFooService>(reference);
   fooService->foo();
-  return serviceObject;
+  return fooService;
 }
 
-void ctkActivatorSL1::modifiedService(const ctkServiceReference& reference, QObject* service)
+void ctkActivatorSL1::modifiedService(const ctkServiceReference& reference, ctkFooService* service)
 {
   Q_UNUSED(reference)
   Q_UNUSED(service)
 }
 
-void ctkActivatorSL1::removedService(const ctkServiceReference& reference, QObject* service)
+void ctkActivatorSL1::removedService(const ctkServiceReference& reference, ctkFooService* service)
 {
   Q_UNUSED(service)
   _serviceRemoved = true;

+ 8 - 7
Libs/PluginFramework/Testing/TestPlugins/pluginSL1_test/ctkActivatorSL1_p.h

@@ -24,14 +24,15 @@
 #define CTKACTIVATORSL1_P_H
 
 #include <ctkPluginActivator.h>
-#include <ctkServiceTrackerCustomizer.h>
 #include <ctkServiceTracker.h>
 
 #include <QScopedPointer>
 
+class ctkFooService;
+
 class ctkActivatorSL1 :
     public QObject, public ctkPluginActivator,
-    public ctkServiceTrackerCustomizer
+    public ctkServiceTrackerCustomizer<ctkFooService*>
 {
   Q_OBJECT
   Q_INTERFACES(ctkPluginActivator)
@@ -49,17 +50,17 @@ public:
   bool serviceAdded() const;
   bool serviceRemoved() const;
 
-  QObject* addingService(const ctkServiceReference& reference);
-  void modifiedService(const ctkServiceReference& reference, QObject* service);
-  void removedService(const ctkServiceReference& reference, QObject* service);
+  ctkFooService* addingService(const ctkServiceReference& reference);
+  void modifiedService(const ctkServiceReference& reference, ctkFooService* service);
+  void removedService(const ctkServiceReference& reference, ctkFooService* service);
 
 private:
 
   bool _serviceAdded;
   bool _serviceRemoved;
 
-
-  QScopedPointer<ctkServiceTracker> tracker;
+  typedef ctkServiceTracker<ctkFooService*> FooTracker;
+  QScopedPointer<FooTracker> tracker;
   ctkPluginContext* context;
 
 }; // ctkActivatorSL1

+ 6 - 7
Libs/PluginFramework/Testing/TestPlugins/pluginSL3_test/ctkActivatorSL3.cpp

@@ -42,7 +42,7 @@ void ctkActivatorSL3::start(ctkPluginContext* context)
   this->context = context;
 
   context->registerService(this->metaObject()->className(), this);
-  tracker.reset(new ctkServiceTracker(context, "ctkFooService", this));
+  tracker.reset(new FooTracker(context, this));
   tracker->open();
 }
 
@@ -62,24 +62,23 @@ bool ctkActivatorSL3::serviceRemoved() const
   return _serviceRemoved;
 }
 
-QObject* ctkActivatorSL3::addingService(const ctkServiceReference& reference)
+ctkFooService* ctkActivatorSL3::addingService(const ctkServiceReference& reference)
 {
   _serviceAdded = true;
   qDebug() << "SL3: Adding reference =" << reference;
 
-  QObject* serviceObject = context->getService(reference);
-  ctkFooService* fooService = qobject_cast<ctkFooService*>(serviceObject);
+  ctkFooService* fooService = context->getService<ctkFooService>(reference);
   fooService->foo();
-  return serviceObject;
+  return fooService;
 }
 
-void ctkActivatorSL3::modifiedService(const ctkServiceReference& reference, QObject* service)
+void ctkActivatorSL3::modifiedService(const ctkServiceReference& reference, ctkFooService* service)
 {
   Q_UNUSED(reference)
   Q_UNUSED(service)
 }
 
-void ctkActivatorSL3::removedService(const ctkServiceReference& reference, QObject* service)
+void ctkActivatorSL3::removedService(const ctkServiceReference& reference, ctkFooService* service)
 {
   Q_UNUSED(service)
   _serviceRemoved = true;

+ 8 - 5
Libs/PluginFramework/Testing/TestPlugins/pluginSL3_test/ctkActivatorSL3_p.h

@@ -29,9 +29,11 @@
 
 #include <QScopedPointer>
 
+class ctkFooService;
+
 class ctkActivatorSL3 :
     public QObject, public ctkPluginActivator,
-    public ctkServiceTrackerCustomizer
+    public ctkServiceTrackerCustomizer<ctkFooService*>
 {
   Q_OBJECT
   Q_INTERFACES(ctkPluginActivator)
@@ -49,16 +51,17 @@ public:
   bool serviceAdded() const;
   bool serviceRemoved() const;
 
-  QObject* addingService(const ctkServiceReference& reference);
-  void modifiedService(const ctkServiceReference& reference, QObject* service);
-  void removedService(const ctkServiceReference& reference, QObject* service);
+  ctkFooService* addingService(const ctkServiceReference& reference);
+  void modifiedService(const ctkServiceReference& reference, ctkFooService* service);
+  void removedService(const ctkServiceReference& reference, ctkFooService* service);
 
 private:
 
   bool _serviceAdded;
   bool _serviceRemoved;
 
-  QScopedPointer<ctkServiceTracker> tracker;
+  typedef ctkServiceTracker<ctkFooService*> FooTracker;
+  QScopedPointer<FooTracker> tracker;
   ctkPluginContext* context;
 
 

+ 46 - 63
Libs/PluginFramework/ctkPluginAbstractTracked.cpp

@@ -24,37 +24,37 @@
 
 #include <QDebug>
 
-template<class Item, class Related>
-const bool ctkPluginAbstractTracked<Item,Related>::DEBUG	= true;
+template<class S, class T, class R>
+const bool ctkPluginAbstractTracked<S,T,R>::DEBUG	= true;
 
-template<class Item, class Related>
-ctkPluginAbstractTracked<Item,Related>::ctkPluginAbstractTracked()
+template<class S, class T, class R>
+ctkPluginAbstractTracked<S,T,R>::ctkPluginAbstractTracked()
 {
   closed = false;
 }
 
-template<class Item, class Related>
-ctkPluginAbstractTracked<Item,Related>::~ctkPluginAbstractTracked()
+template<class S, class T, class R>
+ctkPluginAbstractTracked<S,T,R>::~ctkPluginAbstractTracked()
 {
 
 }
 
-template<class Item, class Related>
-bool ctkPluginAbstractTracked<Item,Related>::wait(unsigned long timeout)
+template<class S, class T, class R>
+bool ctkPluginAbstractTracked<S,T,R>::wait(unsigned long timeout)
 {
   return waitCond.wait(this, timeout);
 }
 
-template<class Item, class Related>
-void ctkPluginAbstractTracked<Item,Related>::wakeAll()
+template<class S, class T, class R>
+void ctkPluginAbstractTracked<S,T,R>::wakeAll()
 {
   waitCond.wakeAll();
 }
 
-template<class Item, class Related>
-void ctkPluginAbstractTracked<Item,Related>::setInitial(const QList<Item>& list)
+template<class S, class T, class R>
+void ctkPluginAbstractTracked<S,T,R>::setInitial(const QList<S>& list)
 {
-  foreach (Item item, list)
+  foreach (S item, list)
   {
     if (DEBUG)
     {
@@ -64,29 +64,12 @@ void ctkPluginAbstractTracked<Item,Related>::setInitial(const QList<Item>& list)
   }
 }
 
-//template<class Item, class Related>
-//void ctkPluginAbstractTracked<Item,Related>::setInitial(const QList<QSharedPointer<Item> >& list)
-//{
-//  foreach (Item* item, list)
-//  {
-//    if (item == 0)
-//    {
-//      continue;
-//    }
-//    if (DEBUG)
-//    {
-//      qDebug() << "ctkPluginAbstractTracked::setInitial:" << item;
-//    }
-//    initial.push_back(item);
-//  }
-//}
-
-template<class Item, class Related>
-void ctkPluginAbstractTracked<Item,Related>::trackInitial()
+template<class S, class T, class R>
+void ctkPluginAbstractTracked<S,T,R>::trackInitial()
 {
   while (true)
   {
-    Item item(0);
+    S item(0);
     {
       QMutexLocker lock(this);
       if (closed || (initial.size() == 0))
@@ -101,7 +84,7 @@ void ctkPluginAbstractTracked<Item,Related>::trackInitial()
        * within this synchronized block.
        */
       item = initial.takeFirst();
-      if (tracked.value(item).isValid())
+      if (tracked.value(item))
       {
         /* if we are already tracking this item */
         if (DEBUG)
@@ -127,7 +110,7 @@ void ctkPluginAbstractTracked<Item,Related>::trackInitial()
     {
       qDebug() << "ctkPluginAbstractTracked::trackInitial: " << item;
     }
-    trackAdding(item, Related());
+    trackAdding(item, R());
     /*
      * Begin tracking it. We call trackAdding
      * since we have already put the item in the
@@ -136,16 +119,16 @@ void ctkPluginAbstractTracked<Item,Related>::trackInitial()
   }
 }
 
-template<class Item, class Related>
-void ctkPluginAbstractTracked<Item,Related>::close()
+template<class S, class T, class R>
+void ctkPluginAbstractTracked<S,T,R>::close()
 {
   closed = true;
 }
 
-template<class Item, class Related>
-void ctkPluginAbstractTracked<Item,Related>::track(Item item, Related related)
+template<class S, class T, class R>
+void ctkPluginAbstractTracked<S,T,R>::track(S item, R related)
 {
-  QVariant object;
+  T object(0);
   {
     QMutexLocker lock(this);
     if (closed)
@@ -153,7 +136,7 @@ void ctkPluginAbstractTracked<Item,Related>::track(Item item, Related related)
       return;
     }
     object = tracked.value(item);
-    if (object.isNull())
+    if (!object)
     { /* we are not tracking the item */
       if (adding.contains(item))
       {
@@ -176,7 +159,7 @@ void ctkPluginAbstractTracked<Item,Related>::track(Item item, Related related)
     }
   }
 
-  if (object.isNull())
+  if (!object)
   { /* we are not tracking the item */
     trackAdding(item, related);
   }
@@ -191,10 +174,10 @@ void ctkPluginAbstractTracked<Item,Related>::track(Item item, Related related)
   }
 }
 
-template<class Item, class Related>
-void ctkPluginAbstractTracked<Item,Related>::untrack(Item item, Related related)
+template<class S, class T, class R>
+void ctkPluginAbstractTracked<S,T,R>::untrack(S item, R related)
 {
-  QVariant object;
+  T object(0);
   {
     QMutexLocker lock(this);
     if (initial.removeOne(item))
@@ -227,7 +210,7 @@ void ctkPluginAbstractTracked<Item,Related>::untrack(Item item, Related related)
                      * must remove from tracker before
                      * calling customizer callback
                      */
-    if (object.isNull())
+    if (!object)
     { /* are we actually tracking the item */
       return;
     }
@@ -245,38 +228,38 @@ void ctkPluginAbstractTracked<Item,Related>::untrack(Item item, Related related)
    */
 }
 
-template<class Item, class Related>
-int ctkPluginAbstractTracked<Item,Related>::size() const
+template<class S, class T, class R>
+int ctkPluginAbstractTracked<S,T,R>::size() const
 {
   return tracked.size();
 }
 
-template<class Item, class Related>
-QVariant ctkPluginAbstractTracked<Item,Related>::getCustomizedObject(Item item) const
+template<class S, class T, class R>
+T ctkPluginAbstractTracked<S,T,R>::getCustomizedObject(S item) const
 {
   return tracked.value(item);
 }
 
-template<class Item, class Related>
-QList<Item> ctkPluginAbstractTracked<Item,Related>::getTracked() const
+template<class S, class T, class R>
+QList<S> ctkPluginAbstractTracked<S,T,R>::getTracked() const
 {
   return tracked.keys();
 }
 
-template<class Item, class Related>
-void ctkPluginAbstractTracked<Item,Related>::modified()
+template<class S, class T, class R>
+void ctkPluginAbstractTracked<S,T,R>::modified()
 {
   trackingCount.ref();
 }
 
-template<class Item, class Related>
-int ctkPluginAbstractTracked<Item,Related>::getTrackingCount() const
+template<class S, class T, class R>
+int ctkPluginAbstractTracked<S,T,R>::getTrackingCount() const
 {
   return trackingCount;
 }
 
-template<class Item, class Related>
-bool ctkPluginAbstractTracked<Item,Related>::customizerAddingFinal(Item item, const QVariant& custom)
+template<class S, class T, class R>
+bool ctkPluginAbstractTracked<S,T,R>::customizerAddingFinal(S item, const T& custom)
 {
   QMutexLocker lock(this);
   if (adding.removeOne(item) && !closed)
@@ -285,7 +268,7 @@ bool ctkPluginAbstractTracked<Item,Related>::customizerAddingFinal(Item item, co
      * if the item was not untracked during the customizer
      * callback
      */
-    if (!custom.isNull())
+    if (custom)
     {
       tracked.insert(item, custom);
       modified(); /* increment modification count */
@@ -299,14 +282,14 @@ bool ctkPluginAbstractTracked<Item,Related>::customizerAddingFinal(Item item, co
   }
 }
 
-template<class Item, class Related>
-void ctkPluginAbstractTracked<Item,Related>::trackAdding(Item item, Related related)
+template<class S, class T, class R>
+void ctkPluginAbstractTracked<S,T,R>::trackAdding(S item, R related)
 {
   if (DEBUG)
   {
     qDebug() << "ctkPluginAbstractTracked::trackAdding:" << item;
   }
-  QVariant object;
+  T object(0);
   bool becameUntracked = false;
   /* Call customizer outside of synchronized region */
   try
@@ -327,7 +310,7 @@ void ctkPluginAbstractTracked<Item,Related>::trackAdding(Item item, Related rela
   /*
    * The item became untracked during the customizer callback.
    */
-  if (becameUntracked && (!object.isNull()))
+  if (becameUntracked && object)
   {
     if (DEBUG)
     {

+ 23 - 21
Libs/PluginFramework/ctkPluginAbstractTracked_p.h

@@ -37,9 +37,12 @@
  * tracked items. This is not a public class. It is only for use by the
  * implementation of the Tracker class.
  *
+ * @tparam S The tracked item. It is the key.
+ * @tparam T The value mapped to the tracked item.
+ * @tparam R The reason the tracked item is  being tracked or untracked.
  * @ThreadSafe
  */
-template<class Item, class Related>
+template<class S, class T, class R>
 class ctkPluginAbstractTracked : public QMutex
 {
 
@@ -69,8 +72,7 @@ public:
    *        entries in the list are ignored.
    * @GuardedBy this
    */
-  void setInitial(const QList<Item>& list);
-  //void setInitial(const QList<Item*>& list);
+  void setInitial(const QList<S>& list);
 
   /**
    * Track the initial list of items. This is called after events can begin to
@@ -90,18 +92,18 @@ public:
   /**
    * Begin to track an item.
    *
-   * @param item Item to be tracked.
+   * @param item S to be tracked.
    * @param related Action related object.
    */
-  void track(Item item, Related related);
+  void track(S item, R related);
 
   /**
    * Discontinue tracking the item.
    *
-   * @param item Item to be untracked.
+   * @param item S to be untracked.
    * @param related Action related object.
    */
-  void untrack(Item item, Related related);
+  void untrack(S item, R related);
 
   /**
    * Returns the number of tracked items.
@@ -120,7 +122,7 @@ public:
    *
    * @GuardedBy this
    */
-  QVariant getCustomizedObject(Item item) const;
+  T getCustomizedObject(S item) const;
 
   /**
    * Return the list of tracked items.
@@ -128,7 +130,7 @@ public:
    * @return The tracked items.
    * @GuardedBy this
    */
-  QList<Item> getTracked() const;
+  QList<S> getTracked() const;
 
   /**
    * Increment the modification count. If this method is overridden, the
@@ -154,12 +156,12 @@ public:
    * Call the specific customizer adding method. This method must not be
    * called while synchronized on this object.
    *
-   * @param item Item to be tracked.
+   * @param item S to be tracked.
    * @param related Action related object.
    * @return Customized object for the tracked item or <code>null</code> if
    *         the item is not to be tracked.
    */
-  virtual QVariant customizerAdding(Item item, Related related) = 0;
+  virtual T customizerAdding(S item, const R& related) = 0;
 
   /**
    * Call the specific customizer modified method. This method must not be
@@ -169,8 +171,8 @@ public:
    * @param related Action related object.
    * @param object Customized object for the tracked item.
    */
-  virtual void customizerModified(Item item, Related related,
-      QVariant object) = 0;
+  virtual void customizerModified(S item, const R& related,
+                                  T object) = 0;
 
   /**
    * Call the specific customizer removed method. This method must not be
@@ -180,8 +182,8 @@ public:
    * @param related Action related object.
    * @param object Customized object for the tracked item.
    */
-  virtual void customizerRemoved(Item item, Related related,
-      QVariant object) = 0;
+  virtual void customizerRemoved(S item, const R& related,
+                                 T object) = 0;
 
   /**
    * List of items in the process of being added. This is used to deal with
@@ -197,7 +199,7 @@ public:
    *
    * @GuardedBy this
    */
-  QList<Item> adding;
+  QList<S> adding;
 
   /**
    * true if the tracked object is closed.
@@ -224,17 +226,17 @@ public:
    *
    * @GuardedBy this
    */
-  QLinkedList<Item>	initial;
+  QLinkedList<S>	initial;
 
   /**
    * Common logic to add an item to the tracker used by track and
    * trackInitial. The specified item must have been placed in the adding list
    * before calling this method.
    *
-   * @param item Item to be tracked.
+   * @param item S to be tracked.
    * @param related Action related object.
    */
-  void trackAdding(Item item, Related related);
+  void trackAdding(S item, R related);
 
 private:
 
@@ -245,7 +247,7 @@ private:
    *
    * @GuardedBy this
    */
-  QHash<Item, QVariant> tracked;
+  QHash<S, T> tracked;
 
   /**
    * Modification count. This field is initialized to zero and incremented by
@@ -255,7 +257,7 @@ private:
    */
   QAtomicInt trackingCount;
 
-  bool customizerAddingFinal(Item item, const QVariant& custom);
+  bool customizerAddingFinal(S item, const T& custom);
 
 };
 

+ 3 - 4
Libs/PluginFramework/ctkServiceReference.h

@@ -32,7 +32,6 @@
 class ctkServiceRegistrationPrivate;
 class ctkServiceReferencePrivate;
 class ctkServiceEvent;
-template<class Item, class Related> class ctkPluginAbstractTracked;
 
 /**
  * A reference to a service.
@@ -180,9 +179,9 @@ protected:
   friend class ctkPluginContext;
   friend class ctkPluginPrivate;
   friend class ctkPluginFrameworkListeners;
-  friend class ctkServiceTrackerPrivate;
-  friend class ctkServiceTracker;
-  friend class ctkPluginAbstractTracked<ctkServiceReference, ctkServiceEvent>;
+  template<class S, class T> friend class ctkServiceTracker;
+  template<class S, class T> friend class ctkServiceTrackerPrivate;
+  template<class S, class R, class T> friend class ctkPluginAbstractTracked;
 
   ctkServiceReference(ctkServiceRegistrationPrivate* reg);
 

+ 86 - 60
Libs/PluginFramework/ctkServiceTracker.cpp

@@ -20,7 +20,6 @@
 =============================================================================*/
 
 
-#include "ctkServiceTracker.h"
 #include "ctkServiceTrackerPrivate.h"
 #include "ctkTrackedService_p.h"
 #include "ctkServiceException.h"
@@ -34,33 +33,46 @@
 #include <limits>
 
 
-ctkServiceTracker::~ctkServiceTracker()
+template<class S, class T>
+ctkServiceTracker<S,T>::~ctkServiceTracker()
 {
 }
 
-ctkServiceTracker::ctkServiceTracker(ctkPluginContext* context,
-                  const ctkServiceReference& reference,
-                  ctkServiceTrackerCustomizer* customizer)
-  : d_ptr(new ctkServiceTrackerPrivate(this, context, reference, customizer))
+template<class S, class T>
+ctkServiceTracker<S,T>::ctkServiceTracker(ctkPluginContext* context,
+                                          const ctkServiceReference& reference,
+                                          ServiceTrackerCustomizer* customizer)
+  : d_ptr(new ServiceTrackerPrivate(this, context, reference, customizer))
 {
 }
 
-ctkServiceTracker::ctkServiceTracker(ctkPluginContext* context, const QString& clazz,
-                      ctkServiceTrackerCustomizer* customizer)
-  : d_ptr(new ctkServiceTrackerPrivate(this, context, clazz, customizer))
+template<class S, class T>
+ctkServiceTracker<S,T>::ctkServiceTracker(ctkPluginContext* context, const QString& clazz,
+                                          ServiceTrackerCustomizer* customizer)
+  : d_ptr(new ServiceTrackerPrivate(this, context, clazz, customizer))
 {
 }
 
-ctkServiceTracker::ctkServiceTracker(ctkPluginContext* context, const ctkLDAPSearchFilter& filter,
-                      ctkServiceTrackerCustomizer* customizer)
-  : d_ptr(new ctkServiceTrackerPrivate(this, context, filter, customizer))
+template<class S, class T>
+ctkServiceTracker<S,T>::ctkServiceTracker(ctkPluginContext* context, const ctkLDAPSearchFilter& filter,
+                                          ServiceTrackerCustomizer* customizer)
+  : d_ptr(new ServiceTrackerPrivate(this, context, filter, customizer))
 {
 }
 
-void ctkServiceTracker::open()
+template<class S, class T>
+ctkServiceTracker<S,T>::ctkServiceTracker(ctkPluginContext *context, ctkServiceTrackerCustomizer<T> *customizer)
+  : d_ptr(new ServiceTrackerPrivate(this, context, qobject_interface_iid<S>(), customizer))
 {
-  Q_D(ctkServiceTracker);
-  QSharedPointer<ctkTrackedService> t;
+  const char* clazz = qobject_interface_iid<S>();
+  if (clazz == 0) throw ctkServiceException("The service interface class has no Q_DECLARE_INTERFACE macro");
+}
+
+template<class S, class T>
+void ctkServiceTracker<S,T>::open()
+{
+  Q_D(ServiceTracker);
+  QSharedPointer<TrackedService> t;
   {
     QMutexLocker lock(&d->mutex);
     if (d->trackedService)
@@ -70,10 +82,11 @@ void ctkServiceTracker::open()
 
     if (d->DEBUG)
     {
-      qDebug() << "ctkServiceTracker::open: " << d->filter;
+      qDebug() << "ctkServiceTracker<S,T>::open: " << d->filter;
     }
 
-    t = QSharedPointer<ctkTrackedService>(new ctkTrackedService(this, d->customizer));
+    t = QSharedPointer<TrackedService>(
+          new TrackedService(this, d->customizer));
     {
       QMutexLocker lockT(t.data());
       try {
@@ -110,10 +123,11 @@ void ctkServiceTracker::open()
   t->trackInitial(); /* process the initial references */
 }
 
-void ctkServiceTracker::close()
+template<class S, class T>
+void ctkServiceTracker<S,T>::close()
 {
-  Q_D(ctkServiceTracker);
-  QSharedPointer<ctkTrackedService> outgoing;
+  Q_D(ServiceTracker);
+  QSharedPointer<TrackedService> outgoing;
   QList<ctkServiceReference> references;
   {
     QMutexLocker lock(&d->mutex);
@@ -124,7 +138,7 @@ void ctkServiceTracker::close()
     }
     if (d->DEBUG)
     {
-      qDebug() << "ctkServiceTracker::close:" << d->filter;
+      qDebug() << "ctkServiceTracker<S,T>::close:" << d->filter;
     }
     outgoing->close();
     references = getServiceReferences();
@@ -153,19 +167,20 @@ void ctkServiceTracker::close()
     QMutexLocker lock(&d->mutex);
     if ((d->cachedReference.getPlugin().isNull()) && (d->cachedService == 0))
     {
-      qDebug() << "ctkServiceTracker::close[cached cleared]:"
+      qDebug() << "ctkServiceTracker<S,T>::close[cached cleared]:"
           << d->filter;
     }
   }
 }
 
-QObject* ctkServiceTracker::waitForService(unsigned long timeout)
+template<class S, class T>
+T ctkServiceTracker<S,T>::waitForService(unsigned long timeout)
 {
-  Q_D(ctkServiceTracker);
-  QObject* object = getService();
+  Q_D(ServiceTracker);
+  T object = getService();
   while (object == 0)
   {
-    QSharedPointer<ctkTrackedService> t = d->tracked();
+    QSharedPointer<TrackedService> t = d->tracked();
     if (t.isNull())
     { /* if ServiceTracker is not open */
       return 0;
@@ -186,10 +201,11 @@ QObject* ctkServiceTracker::waitForService(unsigned long timeout)
   return object;
 }
 
-QList<ctkServiceReference> ctkServiceTracker::getServiceReferences() const
+template<class S, class T>
+QList<ctkServiceReference> ctkServiceTracker<S,T>::getServiceReferences() const
 {
-  Q_D(const ctkServiceTracker);
-  QSharedPointer<ctkTrackedService> t = d->tracked();
+  Q_D(const ServiceTracker);
+  QSharedPointer<TrackedService> t = d->tracked();
   if (t.isNull())
   { /* if ServiceTracker is not open */
     return QList<ctkServiceReference>();
@@ -204,9 +220,10 @@ QList<ctkServiceReference> ctkServiceTracker::getServiceReferences() const
   }
 }
 
-ctkServiceReference ctkServiceTracker::getServiceReference() const
+template<class S, class T>
+ctkServiceReference ctkServiceTracker<S,T>::getServiceReference() const
 {
-  Q_D(const ctkServiceTracker);
+  Q_D(const ServiceTracker);
   ctkServiceReference reference(0);
   {
     QMutexLocker lock(&d->mutex);
@@ -216,14 +233,14 @@ ctkServiceReference ctkServiceTracker::getServiceReference() const
   {
     if (d->DEBUG)
     {
-      qDebug() << "ctkServiceTracker::getServiceReference[cached]:"
+      qDebug() << "ctkServiceTracker<S,T>::getServiceReference[cached]:"
                    << d->filter;
     }
     return reference;
   }
   if (d->DEBUG)
   {
-    qDebug() << "ctkServiceTracker::getServiceReference:" << d->filter;
+    qDebug() << "ctkServiceTracker<S,T>::getServiceReference:" << d->filter;
   }
   QList<ctkServiceReference> references = getServiceReferences();
   int length = references.size();
@@ -283,24 +300,26 @@ ctkServiceReference ctkServiceTracker::getServiceReference() const
   }
 }
 
-QObject* ctkServiceTracker::getService(const ctkServiceReference& reference) const
+template<class S, class T>
+T ctkServiceTracker<S,T>::getService(const ctkServiceReference& reference) const
 {
-  Q_D(const ctkServiceTracker);
-  QSharedPointer<ctkTrackedService> t = d->tracked();
+  Q_D(const ServiceTracker);
+  QSharedPointer<TrackedService> t = d->tracked();
   if (t.isNull())
   { /* if ServiceTracker is not open */
     return 0;
   }
   {
     QMutexLocker lockT(t.data());
-    return t->getCustomizedObject(reference).value<QObject*>();
+    return t->getCustomizedObject(reference);
   }
 }
 
-QList<QObject*> ctkServiceTracker::getServices() const
+template<class S, class T>
+QList<T> ctkServiceTracker<S,T>::getServices() const
 {
-  Q_D(const ctkServiceTracker);
-  QSharedPointer<ctkTrackedService> t = d->tracked();
+  Q_D(const ServiceTracker);
+  QSharedPointer<TrackedService> t = d->tracked();
   if (t.isNull())
   { /* if ServiceTracker is not open */
     return QList<QObject*>();
@@ -317,22 +336,23 @@ QList<QObject*> ctkServiceTracker::getServices() const
   }
 }
 
-QObject* ctkServiceTracker::getService() const
+template<class S, class T>
+T ctkServiceTracker<S,T>::getService() const
 {
-  Q_D(const ctkServiceTracker);
-  QObject* service = d->cachedService;
+  Q_D(const ServiceTracker);
+  T service = d->cachedService;
   if (service != 0)
   {
     if (d->DEBUG)
     {
-      qDebug() << "ctkServiceTracker::getService[cached]:"
+      qDebug() << "ctkServiceTracker<S,T>::getService[cached]:"
                    << d->filter;
     }
     return service;
   }
   if (d->DEBUG)
   {
-    qDebug() << "ctkServiceTracker::getService:" << d->filter;
+    qDebug() << "ctkServiceTracker<S,T>::getService:" << d->filter;
   }
 
   try
@@ -350,10 +370,11 @@ QObject* ctkServiceTracker::getService() const
   }
 }
 
-void ctkServiceTracker::remove(const ctkServiceReference& reference)
+template<class S, class T>
+void ctkServiceTracker<S,T>::remove(const ctkServiceReference& reference)
 {
-  Q_D(ctkServiceTracker);
-  QSharedPointer<ctkTrackedService> t = d->tracked();
+  Q_D(ServiceTracker);
+  QSharedPointer<TrackedService> t = d->tracked();
   if (t.isNull())
   { /* if ServiceTracker is not open */
     return;
@@ -361,10 +382,11 @@ void ctkServiceTracker::remove(const ctkServiceReference& reference)
   t->untrack(reference, ctkServiceEvent());
 }
 
-int ctkServiceTracker::size() const
+template<class S, class T>
+int ctkServiceTracker<S,T>::size() const
 {
-  Q_D(const ctkServiceTracker);
-  QSharedPointer<ctkTrackedService> t = d->tracked();
+  Q_D(const ServiceTracker);
+  QSharedPointer<TrackedService> t = d->tracked();
   if (t.isNull())
   { /* if ServiceTracker is not open */
     return 0;
@@ -375,10 +397,11 @@ int ctkServiceTracker::size() const
   }
 }
 
-int ctkServiceTracker::getTrackingCount() const
+template<class S, class T>
+int ctkServiceTracker<S,T>::getTrackingCount() const
 {
-  Q_D(const ctkServiceTracker);
-  QSharedPointer<ctkTrackedService> t = d->tracked();
+  Q_D(const ServiceTracker);
+  QSharedPointer<TrackedService> t = d->tracked();
   if (t.isNull())
   { /* if ServiceTracker is not open */
     return -1;
@@ -389,23 +412,26 @@ int ctkServiceTracker::getTrackingCount() const
   }
 }
 
-QObject* ctkServiceTracker::addingService(const ctkServiceReference& reference)
+template<class S, class T>
+T ctkServiceTracker<S,T>::addingService(const ctkServiceReference& reference)
 {
-  Q_D(ctkServiceTracker);
-  return d->context->getService(reference);
+  Q_D(ServiceTracker);
+  return qobject_cast<T>(d->context->getService(reference));
 }
 
-void ctkServiceTracker::modifiedService(const ctkServiceReference& reference, QObject* service)
+template<class S, class T>
+void ctkServiceTracker<S,T>::modifiedService(const ctkServiceReference& reference, T service)
 {
   Q_UNUSED(reference)
   Q_UNUSED(service)
   /* do nothing */
 }
 
-void ctkServiceTracker::removedService(const ctkServiceReference& reference, QObject* service)
+template<class S, class T>
+void ctkServiceTracker<S,T>::removedService(const ctkServiceReference& reference, T service)
 {
   Q_UNUSED(service)
 
-  Q_D(ctkServiceTracker);
+  Q_D(ServiceTracker);
   d->context->ungetService(reference);
 }

+ 63 - 16
Libs/PluginFramework/ctkServiceTracker.h

@@ -31,8 +31,9 @@
 #include "ctkServiceTrackerCustomizer.h"
 #include "ctkLDAPSearchFilter.h"
 
+template<class S, class T> class ctkTrackedService;
+template<class S, class T> class ctkServiceTrackerPrivate;
 class ctkPluginContext;
-class ctkServiceTrackerPrivate;
 
 /**
  * The <code>ctkServiceTracker</code> class simplifies using services from the
@@ -57,9 +58,18 @@ class ctkServiceTrackerPrivate;
  * <code>ctkServiceTrackerCustomizer</code> implementations must also be
  * thread-safe.
  *
- * @ThreadSafe
+ * \tparam S The type of the service being tracked. The type must be an
+ *         assignable datatype. Further, if the
+ *         <code>ctkServiceTracker(ctkPluginContext*, ctkServiceTrackerCustomizer<T>*)</code>
+ *         constructor is used, the type must have an associated interface id via
+ *         Q_DECLARE_INTERFACE.
+ * \tparam T The type of the tracked object. The type must be an assignable
+ *         datatype, provide a boolean conversion function, and provide
+ *         a constructor and an assignment operator which can handle 0 as an argument.
+ * \threadsafe
  */
-class CTK_PLUGINFW_EXPORT ctkServiceTracker : protected ctkServiceTrackerCustomizer
+template<class S = QObject*, class T = S>
+class ctkServiceTracker : protected ctkServiceTrackerCustomizer<T>
 {
 public:
 
@@ -89,7 +99,7 @@ public:
    */
   ctkServiceTracker(ctkPluginContext* context,
                     const ctkServiceReference& reference,
-                    ctkServiceTrackerCustomizer* customizer = 0);
+                    ctkServiceTrackerCustomizer<T>* customizer = 0);
 
   /**
    * Create a <code>ctkServiceTracker</code> on the specified class name.
@@ -112,7 +122,7 @@ public:
    *        takes ownership of the customizer.
    */
   ctkServiceTracker(ctkPluginContext* context, const QString& clazz,
-                        ctkServiceTrackerCustomizer* customizer = 0);
+                    ctkServiceTrackerCustomizer<T>* customizer = 0);
 
   /**
    * Create a <code>ctkServiceTracker</code> on the specified
@@ -136,7 +146,28 @@ public:
    *        takes ownership of the customizer.
    */
   ctkServiceTracker(ctkPluginContext* context, const ctkLDAPSearchFilter& filter,
-                        ctkServiceTrackerCustomizer* customizer = 0);
+                    ctkServiceTrackerCustomizer<T>* customizer = 0);
+
+  /**
+   * Create a <code>ctkServiceTracker</code> on the class template
+   * argument S.
+   *
+   * <p>
+   * Services registered under the interface name of the class template
+   * argument S will be tracked by this <code>ctkServiceTracker</code>.
+   *
+   * @param context The <code>ctkPluginContext</code> against which the tracking
+   *        is done.
+   * @param customizer The customizer object to call when services are added,
+   *        modified, or removed in this <code>ctkServiceTracker</code>. If
+   *        customizer is null, then this <code>ctkServiceTracker</code> will be
+   *        used as the <code>ctkServiceTrackerCustomizer</code> and this
+   *        <code>ctkServiceTracker</code> will call the
+   *        <code>ctkServiceTrackerCustomizer</code> methods on itself. If the
+   *        customizer is not <code>null</code>, this <code>ctkServiceTracker</code>
+   *        takes ownership of the customizer.
+   */
+  ctkServiceTracker(ctkPluginContext* context, ctkServiceTrackerCustomizer<T>* customizer = 0);
 
   /**
    * Open this <code>ctkServiceTracker</code> and begin tracking services.
@@ -184,7 +215,7 @@ public:
    *        method will wait indefinitely.
    * @return Returns the result of getService().
    */
-  QObject* waitForService(unsigned long timeout);
+  T waitForService(unsigned long timeout);
 
   /**
    * Return a list of <code>ctkServiceReference</code>s for all services being
@@ -225,7 +256,7 @@ public:
    *         by the specified <code>ctkServiceReference</code> is not being
    *         tracked.
    */
-  QObject* getService(const ctkServiceReference& reference) const;
+  T getService(const ctkServiceReference& reference) const;
 
   /**
    * Return a list of service objects for all services being tracked by this
@@ -240,7 +271,7 @@ public:
    * @return A list of service objects or an empty list if no services
    *         are being tracked.
    */
-  QList<QObject*> getServices() const;
+  QList<T> getServices() const;
 
   /**
    * Returns a service object for one of the services being tracked by this
@@ -253,7 +284,7 @@ public:
    * @return A service object or <code>null</code> if no services are being
    *         tracked.
    */
-  QObject* getService() const;
+  T getService() const;
 
   /**
    * Remove a service from this <code>ctkServiceTracker</code>.
@@ -324,7 +355,7 @@ protected:
    *         <code>ctlServiceTracker</code>.
    * @see ctkServiceTrackerCustomizer::addingService(const ctkServiceReference&)
    */
-  QObject* addingService(const ctkServiceReference& reference);
+  T addingService(const ctkServiceReference& reference);
 
   /**
    * Default implementation of the
@@ -341,7 +372,7 @@ protected:
    * @param service The service object for the modified service.
    * @see ctkServiceTrackerCustomizer::modifiedService(const ctkServiceReference&, QObject*)
    */
-  void modifiedService(const ctkServiceReference& reference, QObject* service);
+  void modifiedService(const ctkServiceReference& reference, T service);
 
   /**
    * Default implementation of the
@@ -364,15 +395,31 @@ protected:
    * @param service The service object for the removed service.
    * @see ctkServiceTrackerCustomizer::removedService(const ServiceReference&, QObject*)
    */
-  void removedService(const ctkServiceReference& reference, QObject* service);
+  void removedService(const ctkServiceReference& reference, T service);
 
 private:
 
-  friend class ctkTrackedService;
+  typedef ctkServiceTracker<S,T> ServiceTracker;
+  typedef ctkTrackedService<S,T> TrackedService;
+  typedef ctkServiceTrackerPrivate<S,T> ServiceTrackerPrivate;
+  typedef ctkServiceTrackerCustomizer<T> ServiceTrackerCustomizer;
+
+  friend class ctkTrackedService<S,T>;
+  friend class ctkServiceTrackerPrivate<S,T>;
 
-  Q_DECLARE_PRIVATE(ctkServiceTracker)
+  inline ServiceTrackerPrivate* d_func()
+  {
+    return reinterpret_cast<ServiceTrackerPrivate*>(qGetPtrHelper(d_ptr));
+  }
 
-  const QScopedPointer<ctkServiceTrackerPrivate> d_ptr;
+  inline const ServiceTrackerPrivate* d_func() const
+  {
+    return reinterpret_cast<const ServiceTrackerPrivate*>(qGetPtrHelper(d_ptr));
+  }
+
+  const QScopedPointer<ServiceTrackerPrivate> d_ptr;
 };
 
+#include "ctkServiceTracker.cpp"
+
 #endif // CTKSERVICETRACKER_H

+ 6 - 4
Libs/PluginFramework/ctkServiceTrackerCustomizer.h

@@ -52,8 +52,10 @@
  * <code>ctkServiceTrackerCustomizer</code> implementations must also be
  * thread-safe.
  *
- * @ThreadSafe
+ * \tparam T The type of the tracked object.
+ * \threadsafe
  */
+template<class T = QObject*>
 struct ctkServiceTrackerCustomizer {
 
   virtual ~ctkServiceTrackerCustomizer() {}
@@ -76,7 +78,7 @@ struct ctkServiceTrackerCustomizer {
    *         service or <code>0</code> if the specified referenced service
    *         should not be tracked.
    */
-  virtual QObject* addingService(const ctkServiceReference& reference) = 0;
+  virtual T addingService(const ctkServiceReference& reference) = 0;
 
   /**
    * A service tracked by the <code>ctkServiceTracker</code> has been modified.
@@ -88,7 +90,7 @@ struct ctkServiceTrackerCustomizer {
    * @param reference The reference to the service that has been modified.
    * @param service The service object for the specified referenced service.
    */
-  virtual void modifiedService(const ctkServiceReference& reference, QObject* service) = 0;
+  virtual void modifiedService(const ctkServiceReference& reference, T service) = 0;
 
   /**
    * A service tracked by the <code>ctkServiceTracker</code> has been removed.
@@ -100,7 +102,7 @@ struct ctkServiceTrackerCustomizer {
    * @param reference The reference to the service that has been removed.
    * @param service The service object for the specified referenced service.
    */
-  virtual void removedService(const ctkServiceReference& reference, QObject* service) = 0;
+  virtual void removedService(const ctkServiceReference& reference, T service) = 0;
 };
 
 #endif // CTKSERVICETRACKERCUSTOMIZER_H

+ 22 - 16
Libs/PluginFramework/ctkServiceTrackerPrivate.cpp

@@ -20,22 +20,22 @@
 =============================================================================*/
 
 
-#include "ctkServiceTrackerPrivate.h"
 #include "ctkTrackedService_p.h"
 
 #include "ctkPluginContext.h"
 #include "ctkPluginConstants.h"
 #include "ctkLDAPSearchFilter.h"
-#include "ctkServiceTracker.h"
 
 #include <stdexcept>
 
-const bool ctkServiceTrackerPrivate::DEBUG	= true;
+template<class S, class T>
+const bool ctkServiceTrackerPrivate<S,T>::DEBUG	= true;
 
-ctkServiceTrackerPrivate::ctkServiceTrackerPrivate(
-    ctkServiceTracker* st, ctkPluginContext* context,
+template<class S, class T>
+ctkServiceTrackerPrivate<S,T>::ctkServiceTrackerPrivate(
+    ctkServiceTracker<S,T>* st, ctkPluginContext* context,
     const ctkServiceReference& reference,
-    ctkServiceTrackerCustomizer* customizer)
+    ctkServiceTrackerCustomizer<T>* customizer)
   : context(context), customizer(customizer), trackReference(reference),
     trackedService(0), cachedReference(0), cachedService(0), q_ptr(st)
 {
@@ -57,10 +57,11 @@ ctkServiceTrackerPrivate::ctkServiceTrackerPrivate(
   }
 }
 
-ctkServiceTrackerPrivate::ctkServiceTrackerPrivate(
-    ctkServiceTracker* st,
+template<class S, class T>
+ctkServiceTrackerPrivate<S,T>::ctkServiceTrackerPrivate(
+    ctkServiceTracker<S,T>* st,
     ctkPluginContext* context, const QString& clazz,
-    ctkServiceTrackerCustomizer* customizer)
+    ctkServiceTrackerCustomizer<T>* customizer)
       : context(context), customizer(customizer), trackClass(clazz),
         trackReference(0), trackedService(0), cachedReference(0),
         cachedService(0), q_ptr(st)
@@ -84,10 +85,11 @@ ctkServiceTrackerPrivate::ctkServiceTrackerPrivate(
   }
 }
 
-ctkServiceTrackerPrivate::ctkServiceTrackerPrivate(
-    ctkServiceTracker* st,
+template<class S, class T>
+ctkServiceTrackerPrivate<S,T>::ctkServiceTrackerPrivate(
+    ctkServiceTracker<S,T>* st,
     ctkPluginContext* context, const ctkLDAPSearchFilter& filter,
-    ctkServiceTrackerCustomizer* customizer)
+    ctkServiceTrackerCustomizer<T>* customizer)
       : context(context), filter(filter), customizer(customizer),
         listenerFilter(filter.toString()), trackReference(0),
         trackedService(0), cachedReference(0), cachedService(0), q_ptr(st)
@@ -99,7 +101,8 @@ ctkServiceTrackerPrivate::ctkServiceTrackerPrivate(
   }
 }
 
-ctkServiceTrackerPrivate::~ctkServiceTrackerPrivate()
+template<class S, class T>
+ctkServiceTrackerPrivate<S,T>::~ctkServiceTrackerPrivate()
 {
   if (customizer != q_func())
   {
@@ -107,18 +110,21 @@ ctkServiceTrackerPrivate::~ctkServiceTrackerPrivate()
   }
 }
 
-QList<ctkServiceReference> ctkServiceTrackerPrivate::getInitialReferences(const QString& className,
+template<class S, class T>
+QList<ctkServiceReference> ctkServiceTrackerPrivate<S,T>::getInitialReferences(const QString& className,
                                                 const QString& filterString)
 {
   return context->getServiceReferences(className, filterString);
 }
 
-QSharedPointer<ctkTrackedService> ctkServiceTrackerPrivate::tracked() const
+template<class S, class T>
+QSharedPointer<ctkTrackedService<S,T> > ctkServiceTrackerPrivate<S,T>::tracked() const
 {
   return trackedService;
 }
 
-void ctkServiceTrackerPrivate::modified()
+template<class S, class T>
+void ctkServiceTrackerPrivate<S,T>::modified()
 {
   cachedReference = 0; /* clear cached value */
   cachedService = 0; /* clear cached value */

+ 27 - 16
Libs/PluginFramework/ctkServiceTrackerPrivate.h

@@ -29,27 +29,26 @@
 #include <QMutex>
 #include <QSharedPointer>
 
-class ctkServiceTracker;
-class ctkTrackedService;
-struct ctkServiceTrackerCustomizer;
 
-class ctkServiceTrackerPrivate {
+template<class S, class T>
+class ctkServiceTrackerPrivate
+{
 
 public:
 
-  ctkServiceTrackerPrivate(ctkServiceTracker* st,
+  ctkServiceTrackerPrivate(ctkServiceTracker<S,T>* st,
                            ctkPluginContext* context,
                            const ctkServiceReference& reference,
-                           ctkServiceTrackerCustomizer* customizer);
+                           ctkServiceTrackerCustomizer<T>* customizer);
 
-  ctkServiceTrackerPrivate(ctkServiceTracker* st,
+  ctkServiceTrackerPrivate(ctkServiceTracker<S,T>* st,
       ctkPluginContext* context, const QString& clazz,
-      ctkServiceTrackerCustomizer* customizer);
+      ctkServiceTrackerCustomizer<T>* customizer);
 
   ctkServiceTrackerPrivate(
-      ctkServiceTracker* st,
+      ctkServiceTracker<S,T>* st,
       ctkPluginContext* context, const ctkLDAPSearchFilter& filter,
-      ctkServiceTrackerCustomizer* customizer);
+      ctkServiceTrackerCustomizer<T>* customizer);
 
   ~ctkServiceTrackerPrivate();
 
@@ -85,7 +84,7 @@ public:
   /**
    * The <code>ctkServiceTrackerCustomizer</code> for this tracker.
    */
-  ctkServiceTrackerCustomizer* customizer;
+  ctkServiceTrackerCustomizer<T>* customizer;
 
   /**
    * Filter string for use when adding the ServiceListener. If this field is
@@ -110,7 +109,7 @@ public:
    * Tracked services: <code>ctkServiceReference</code> -> customized Object and
    * <code>ctkServiceSlotEntry</code> object
    */
-  QSharedPointer<ctkTrackedService> trackedService;
+  QSharedPointer<ctkTrackedService<S,T> > trackedService;
 
   /**
    * Accessor method for the current ctkTrackedService object. This method is only
@@ -119,7 +118,7 @@ public:
    *
    * @return The current Tracked object.
    */
-  QSharedPointer<ctkTrackedService> tracked() const;
+  QSharedPointer<ctkTrackedService<S,T> > tracked() const;
 
   /**
    * Called by the ctkTrackedService object whenever the set of tracked services is
@@ -142,16 +141,28 @@ public:
    *
    * This field is volatile since it is accessed by multiple threads.
    */
-  mutable QObject* volatile cachedService;
+  mutable T volatile cachedService;
 
   mutable QMutex mutex;
 
 private:
 
-  Q_DECLARE_PUBLIC(ctkServiceTracker)
+  inline ctkServiceTracker<S,T>* q_func()
+  {
+    return static_cast<ctkServiceTracker<S,T> *>(q_ptr);
+  }
 
-  ctkServiceTracker * const q_ptr;
+  inline const ctkServiceTracker<S,T>* q_func() const
+  {
+    return static_cast<const ctkServiceTracker<S,T> *>(q_ptr);
+  }
+
+  friend class ctkServiceTracker<S,T>;
+
+  ctkServiceTracker<S,T> * const q_ptr;
 
 };
 
+#include "ctkServiceTrackerPrivate.cpp"
+
 #endif // CTKSERVICETRACKERPRIVATE_H

+ 26 - 24
Libs/PluginFramework/ctkTrackedService.cpp

@@ -20,25 +20,22 @@
 =============================================================================*/
 
 
-#include "ctkTrackedService_p.h"
-
-#include "ctkServiceTracker.h"
-#include "ctkServiceTrackerPrivate.h"
-
-ctkTrackedService::ctkTrackedService(ctkServiceTracker* serviceTracker,
-                  ctkServiceTrackerCustomizer* customizer)
+template<class S, class T>
+ctkTrackedService<S,T>::ctkTrackedService(ctkServiceTracker<S,T>* serviceTracker,
+                  ctkServiceTrackerCustomizer<T>* customizer)
   : serviceTracker(serviceTracker), customizer(customizer)
 {
 
 }
 
-void ctkTrackedService::serviceChanged(const ctkServiceEvent& event)
+template<class S, class T>
+void ctkTrackedService<S,T>::serviceChanged(const ctkServiceEvent& event)
 {
   /*
    * Check if we had a delayed call (which could happen when we
    * close).
    */
-  if (closed)
+  if (this->closed)
   {
     return;
   }
@@ -57,7 +54,7 @@ void ctkTrackedService::serviceChanged(const ctkServiceEvent& event)
     {
       if (!serviceTracker->d_func()->listenerFilter.isNull())
       { // service listener added with filter
-        track(reference, event);
+        this->track(reference, event);
         /*
        * If the customizer throws an unchecked exception, it
        * is safe to let it propagate
@@ -67,7 +64,7 @@ void ctkTrackedService::serviceChanged(const ctkServiceEvent& event)
       { // service listener added without filter
         if (serviceTracker->d_func()->filter.match(reference))
         {
-          track(reference, event);
+          this->track(reference, event);
           /*
          * If the customizer throws an unchecked exception,
          * it is safe to let it propagate
@@ -75,7 +72,7 @@ void ctkTrackedService::serviceChanged(const ctkServiceEvent& event)
         }
         else
         {
-          untrack(reference, event);
+          this->untrack(reference, event);
           /*
          * If the customizer throws an unchecked exception,
          * it is safe to let it propagate
@@ -86,7 +83,7 @@ void ctkTrackedService::serviceChanged(const ctkServiceEvent& event)
     }
   case ctkServiceEvent::MODIFIED_ENDMATCH :
   case ctkServiceEvent::UNREGISTERING :
-    untrack(reference, event);
+    this->untrack(reference, event);
     /*
      * If the customizer throws an unchecked exception, it is
      * safe to let it propagate
@@ -95,30 +92,35 @@ void ctkTrackedService::serviceChanged(const ctkServiceEvent& event)
   }
 }
 
-void ctkTrackedService::modified()
+template<class S, class T>
+void ctkTrackedService<S,T>::modified()
 {
   Superclass::modified(); /* increment the modification count */
   serviceTracker->d_func()->modified();
 }
 
-QVariant ctkTrackedService::customizerAdding(ctkServiceReference item, ctkServiceEvent related)
+template<class S, class T>
+T ctkTrackedService<S,T>::customizerAdding(ctkServiceReference item,
+                                           const ctkServiceEvent& related)
 {
   Q_UNUSED(related)
-  QVariant var;
-  var.setValue(customizer->addingService(item));
-  return var;
+  return customizer->addingService(item);
 }
 
-void ctkTrackedService::customizerModified(ctkServiceReference item,
-                        ctkServiceEvent related, QVariant object)
+template<class S, class T>
+void ctkTrackedService<S,T>::customizerModified(ctkServiceReference item,
+                                                const ctkServiceEvent& related,
+                                                T object)
 {
   Q_UNUSED(related)
-  customizer->modifiedService(item, object.value<QObject*>());
+  customizer->modifiedService(item, object);
 }
 
-void ctkTrackedService::customizerRemoved(ctkServiceReference item,
-                       ctkServiceEvent related, QVariant object)
+template<class S, class T>
+void ctkTrackedService<S,T>::customizerRemoved(ctkServiceReference item,
+                                               const ctkServiceEvent& related,
+                                               T object)
 {
   Q_UNUSED(related)
-  customizer->removedService(item, object.value<QObject*>());
+  customizer->removedService(item, object);
 }

+ 52 - 0
Libs/PluginFramework/ctkTrackedServiceListener_p.h

@@ -0,0 +1,52 @@
+/*=============================================================================
+
+  Library: CTK
+
+  Copyright (c) German Cancer Research Center,
+    Division of Medical and Biological Informatics
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+=============================================================================*/
+
+
+#ifndef CTKTRACKEDSERVICELISTENER_P_H
+#define CTKTRACKEDSERVICELISTENER_P_H
+
+#include <QObject>
+
+#include "ctkServiceEvent.h"
+
+class CTK_PLUGINFW_EXPORT ctkTrackedServiceListener : public QObject
+{
+  Q_OBJECT
+
+public:
+  ctkTrackedServiceListener(QObject *parent = 0)
+    : QObject(parent)
+  {}
+
+public slots:
+
+  /**
+   * Slot connected to service events for the
+   * <code>ctkServiceTracker</code> class. This method must NOT be
+   * synchronized to avoid deadlock potential.
+   *
+   * @param event <code>ctkServiceEvent</code> object from the framework.
+   */
+  virtual void serviceChanged(const ctkServiceEvent& event) = 0;
+
+};
+
+#endif // CTKTRACKEDSERVICELISTENER_P_H

+ 14 - 15
Libs/PluginFramework/ctkTrackedService_p.h

@@ -23,22 +23,19 @@
 #ifndef CTKTRACKEDSERVICE_P_H
 #define CTKTRACKEDSERVICE_P_H
 
+#include "ctkTrackedServiceListener_p.h"
 #include "ctkPluginAbstractTracked_p.h"
 #include "ctkServiceEvent.h"
 
-class ctkServiceTracker;
-struct ctkServiceTrackerCustomizer;
 
-class ctkTrackedService : public QObject,
-    public ctkPluginAbstractTracked<ctkServiceReference, ctkServiceEvent>
+template<class S, class T>
+class ctkTrackedService : public ctkTrackedServiceListener,
+    public ctkPluginAbstractTracked<ctkServiceReference, T, ctkServiceEvent>
 {
-  Q_OBJECT
 
 public:
-  ctkTrackedService(ctkServiceTracker* serviceTracker,
-                    ctkServiceTrackerCustomizer* customizer);
-
-public slots:
+  ctkTrackedService(ctkServiceTracker<S,T>* serviceTracker,
+                    ctkServiceTrackerCustomizer<T>* customizer);
 
   /**
    * Slot connected to service events for the
@@ -51,10 +48,10 @@ public slots:
 
 private:
 
-  typedef ctkPluginAbstractTracked<ctkServiceReference, ctkServiceEvent> Superclass;
+  typedef ctkPluginAbstractTracked<ctkServiceReference, T, ctkServiceEvent> Superclass;
 
-  ctkServiceTracker* serviceTracker;
-  ctkServiceTrackerCustomizer* customizer;
+  ctkServiceTracker<S,T>* serviceTracker;
+  ctkServiceTrackerCustomizer<T>* customizer;
 
   /**
    * Increment the tracking count and tell the tracker there was a
@@ -73,7 +70,7 @@ private:
    * @return Customized object for the tracked item or <code>null</code>
    *         if the item is not to be tracked.
    */
-  QVariant customizerAdding(ctkServiceReference item, ctkServiceEvent related);
+  T customizerAdding(ctkServiceReference item, const ctkServiceEvent& related);
 
   /**
    * Call the specific customizer modified method. This method must not be
@@ -84,7 +81,7 @@ private:
    * @param object Customized object for the tracked item.
    */
   void customizerModified(ctkServiceReference item,
-                          ctkServiceEvent related, QVariant object) ;
+                          const ctkServiceEvent& related, T object) ;
 
   /**
    * Call the specific customizer removed method. This method must not be
@@ -95,7 +92,9 @@ private:
    * @param object Customized object for the tracked item.
    */
   void customizerRemoved(ctkServiceReference item,
-                         ctkServiceEvent related, QVariant object) ;
+                         const ctkServiceEvent& related, T object) ;
 };
 
+#include "ctkTrackedService.cpp"
+
 #endif // CTKTRACKEDSERVICE_P_H

+ 3 - 3
Plugins/org.commontk.qtmobility.service/ctkQtMobilityServiceActivator.cpp

@@ -15,11 +15,11 @@
 
 #include <QtPlugin>
 
-ctkServiceTracker* ctkQtMobilityServiceActivator::logTracker = 0;
+ctkQtMobilityServiceActivator::LogTracker* ctkQtMobilityServiceActivator::logTracker = 0;
 
 void ctkQtMobilityServiceActivator::start(ctkPluginContext* context)
 {
-  logTracker = new ctkServiceTracker(context, "ctkLogService");
+  logTracker = new LogTracker(context);
   logTracker->open();
   mobsr = new ctkQtMobilityServiceRuntime(context);
   mobsr->start();
@@ -51,7 +51,7 @@ ctkLogService* ctkQtMobilityServiceActivator::getLogService()
     return 0;
   }
 
-  return qobject_cast<ctkLogService*>(logTracker->getService());
+  return logTracker->getService();
 }
 
 void ctkQtMobilityServiceActivator::logError(ctkPluginContext* pc, const QString& msg, std::exception* e)

+ 6 - 2
Plugins/org.commontk.qtmobility.service/ctkQtMobilityServiceActivator_p.h

@@ -3,8 +3,10 @@
 
 #include <ctkPluginActivator.h>
 
+class QObject;
+
 class ctkLogService;
-class ctkServiceTracker;
+template<class S, class T> class ctkServiceTracker;
 class ctkQtMobilityServiceRuntime;
 
 class ctkQtMobilityServiceActivator : public QObject,
@@ -31,7 +33,9 @@ private:
 
   ctkQtMobilityServiceRuntime* mobsr;
 
-  static ctkServiceTracker* logTracker;
+  typedef ctkServiceTracker<ctkLogService*,ctkLogService*> LogTracker;
+
+  static LogTracker* logTracker;
 
 };