1 /*=============================================================================
2 
3   Library: CTK
4 
5   Copyright (c) German Cancer Research Center,
6     Division of Medical and Biological Informatics
7 
8   Licensed under the Apache License, Version 2.0 (the "License");
9   you may not use this file except in compliance with the License.
10   You may obtain a copy of the License at
11 
12     http://www.apache.org/licenses/LICENSE-2.0
13 
14   Unless required by applicable law or agreed to in writing, software
15   distributed under the License is distributed on an "AS IS" BASIS,
16   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   See the License for the specific language governing permissions and
18   limitations under the License.
19 
20 =============================================================================*/
21 
22 #include "ctkPlugin_p.h"
23 #include "ctkPluginContext.h"
24 #include "ctkPluginContext_p.h"
25 #include "ctkPluginFrameworkContext_p.h"
26 
27 #include "ctkServices_p.h"
28 #include "ctkServiceRegistration.h"
29 #include "ctkServiceReference.h"
30 #include "ctkServiceReference_p.h"
31 
32 #include <stdexcept>
33 
34 //----------------------------------------------------------------------------
ctkPluginContextPrivate(ctkPluginPrivate * plugin)35 ctkPluginContextPrivate::ctkPluginContextPrivate(ctkPluginPrivate* plugin)
36   : plugin(plugin)
37 {}
38 
39 //----------------------------------------------------------------------------
isPluginContextValid() const40 void ctkPluginContextPrivate::isPluginContextValid() const
41 {
42   if (!plugin) {
43     throw ctkIllegalStateException("This plugin context is no longer valid");
44   }
45 }
46 
47 //----------------------------------------------------------------------------
invalidate()48 void ctkPluginContextPrivate::invalidate()
49 {
50   plugin = 0;
51 }
52 
53 //----------------------------------------------------------------------------
ctkPluginContext(ctkPluginPrivate * plugin)54 ctkPluginContext::ctkPluginContext(ctkPluginPrivate* plugin)
55   : d_ptr(new ctkPluginContextPrivate(plugin))
56 {}
57 
58 //----------------------------------------------------------------------------
~ctkPluginContext()59 ctkPluginContext::~ctkPluginContext()
60 {
61   Q_D(ctkPluginContext);
62   delete d;
63 }
64 
65 //----------------------------------------------------------------------------
getProperty(const QString & key) const66 QVariant ctkPluginContext::getProperty(const QString& key) const
67 {
68   Q_D(const ctkPluginContext);
69   d->isPluginContextValid();
70   return d->plugin->fwCtx->props.value(key);
71 }
72 
73 //----------------------------------------------------------------------------
getPlugin() const74 QSharedPointer<ctkPlugin> ctkPluginContext::getPlugin() const
75 {
76   Q_D(const ctkPluginContext);
77   d->isPluginContextValid();
78   return d->plugin->q_func();
79 }
80 
81 //----------------------------------------------------------------------------
getPlugin(long id) const82 QSharedPointer<ctkPlugin> ctkPluginContext::getPlugin(long id) const
83 {
84   Q_D(const ctkPluginContext);
85   return d->plugin->fwCtx->plugins->getPlugin(id);
86 }
87 
88 //----------------------------------------------------------------------------
getPlugins() const89 QList<QSharedPointer<ctkPlugin> > ctkPluginContext::getPlugins() const
90 {
91   Q_D(const ctkPluginContext);
92   d->isPluginContextValid();
93   return d->plugin->fwCtx->plugins->getPlugins();
94 }
95 
96 //----------------------------------------------------------------------------
installPlugin(const QUrl & location,QIODevice * in)97 QSharedPointer<ctkPlugin> ctkPluginContext::installPlugin(const QUrl& location, QIODevice* in)
98 {
99   Q_D(ctkPluginContext);
100   d->isPluginContextValid();
101   return d->plugin->fwCtx->plugins->install(location, in);
102 }
103 
104 //----------------------------------------------------------------------------
getDataFile(const QString & filename)105 QFileInfo ctkPluginContext::getDataFile(const QString& filename)
106 {
107   Q_D(ctkPluginContext);
108   d->isPluginContextValid();
109   QDir dataRoot(d->plugin->getDataRoot().absolutePath());
110   if (!dataRoot.exists())
111   {
112     if (!dataRoot.mkpath(dataRoot.absolutePath()))
113     {
114       qWarning() << "Could not create persistent storage area:" << dataRoot.absolutePath();
115     }
116   }
117   return QFileInfo(dataRoot.absolutePath() + '/' + filename);
118 }
119 
120 //----------------------------------------------------------------------------
registerService(const QStringList & clazzes,QObject * service,const ctkDictionary & properties)121 ctkServiceRegistration ctkPluginContext::registerService(const QStringList& clazzes, QObject* service, const ctkDictionary& properties)
122 {
123   Q_D(ctkPluginContext);
124   d->isPluginContextValid();
125   return d->plugin->fwCtx->services->registerService(d->plugin, clazzes, service, properties);
126 }
127 
128 //----------------------------------------------------------------------------
registerService(const char * clazz,QObject * service,const ctkDictionary & properties)129 ctkServiceRegistration ctkPluginContext::registerService(const char* clazz, QObject* service, const ctkDictionary& properties)
130 {
131   Q_D(ctkPluginContext);
132   d->isPluginContextValid();
133   QStringList clazzes;
134   clazzes.append(clazz);
135   return d->plugin->fwCtx->services->registerService(d->plugin, clazzes, service, properties);
136 }
137 
138 //----------------------------------------------------------------------------
getServiceReferences(const QString & clazz,const QString & filter)139 QList<ctkServiceReference> ctkPluginContext::getServiceReferences(const QString& clazz, const QString& filter)
140 {
141   Q_D(ctkPluginContext);
142   d->isPluginContextValid();
143   return d->plugin->fwCtx->services->get(clazz, filter, 0);
144 }
145 
146 //----------------------------------------------------------------------------
getServiceReference(const QString & clazz)147 ctkServiceReference ctkPluginContext::getServiceReference(const QString& clazz)
148 {
149   Q_D(ctkPluginContext);
150   d->isPluginContextValid();
151   return d->plugin->fwCtx->services->get(d->plugin, clazz);
152 }
153 
154 //----------------------------------------------------------------------------
getService(const ctkServiceReference & reference)155 QObject* ctkPluginContext::getService(const ctkServiceReference& reference)
156 {
157   Q_D(ctkPluginContext);
158   d->isPluginContextValid();
159 
160   if (!reference)
161   {
162     throw ctkInvalidArgumentException("Default constructed ctkServiceReference is not a valid input to getService()");
163   }
164   ctkServiceReference internalRef(reference);
165   return internalRef.d_func()->getService(d->plugin->q_func());
166 }
167 
168 //----------------------------------------------------------------------------
ungetService(const ctkServiceReference & reference)169 bool ctkPluginContext::ungetService(const ctkServiceReference& reference)
170 {
171   Q_D(ctkPluginContext);
172   d->isPluginContextValid();
173   ctkServiceReference ref = reference;
174   return ref.d_func()->ungetService(d->plugin->q_func(), true);
175 }
176 
177 //----------------------------------------------------------------------------
connectPluginListener(const QObject * receiver,const char * slot,Qt::ConnectionType type)178 bool ctkPluginContext::connectPluginListener(const QObject* receiver, const char* slot,
179                                              Qt::ConnectionType type)
180 {
181   Q_D(ctkPluginContext);
182   d->isPluginContextValid();
183   // TODO check permissions for a direct connection
184   if (type == Qt::DirectConnection || type == Qt::BlockingQueuedConnection)
185   {
186     return receiver->connect(&(d->plugin->fwCtx->listeners), SIGNAL(pluginChangedDirect(ctkPluginEvent)), slot, type);
187   }
188   else if (type == Qt::QueuedConnection)
189   {
190     return receiver->connect(&(d->plugin->fwCtx->listeners), SIGNAL(pluginChangedQueued(ctkPluginEvent)), slot, type);
191   }
192   else
193   {
194     throw ctkInvalidArgumentException("Only Qt::DirectConnection, Qt::QueuedConnection, or Qt::BlockingQueuedConnection are allowed as type argument.");
195   }
196 }
197 
198 //----------------------------------------------------------------------------
disconnectPluginListener(const QObject * receiver,const char * slot)199 void ctkPluginContext::disconnectPluginListener(const QObject *receiver, const char* slot)
200 {
201   Q_D(ctkPluginContext);
202   d->isPluginContextValid();
203 
204   QObject::disconnect(&(d->plugin->fwCtx->listeners), SIGNAL(pluginChangedDirect(ctkPluginEvent)), receiver, slot);
205   QObject::disconnect(&(d->plugin->fwCtx->listeners), SIGNAL(pluginChangedQueued(ctkPluginEvent)), receiver, slot);
206 }
207 
208 //----------------------------------------------------------------------------
connectFrameworkListener(const QObject * receiver,const char * slot,Qt::ConnectionType type)209 bool ctkPluginContext::connectFrameworkListener(const QObject* receiver, const char* slot, Qt::ConnectionType type)
210 {
211   Q_D(ctkPluginContext);
212   d->isPluginContextValid();
213   // TODO check permissions for a direct connection
214   return receiver->connect(&(d->plugin->fwCtx->listeners), SIGNAL(frameworkEvent(ctkPluginFrameworkEvent)), slot, type);
215 }
216 
217 //----------------------------------------------------------------------------
disconnectFrameworkListener(const QObject * receiver,const char * slot)218 void ctkPluginContext::disconnectFrameworkListener(const QObject *receiver, const char* slot)
219 {
220   Q_D(ctkPluginContext);
221   d->isPluginContextValid();
222 
223   QObject::disconnect(&(d->plugin->fwCtx->listeners), SIGNAL(frameworkEvent(ctkPluginFrameworkEvent)), receiver, slot);
224 }
225 
226 //----------------------------------------------------------------------------
connectServiceListener(QObject * receiver,const char * slot,const QString & filter)227 void ctkPluginContext::connectServiceListener(QObject* receiver, const char* slot,
228                                              const QString& filter)
229 {
230   Q_D(ctkPluginContext);
231   d->isPluginContextValid();
232   d->plugin->fwCtx->listeners.addServiceSlot(getPlugin(), receiver, slot, filter);
233 }
234 
235 //----------------------------------------------------------------------------
disconnectServiceListener(QObject * receiver,const char * slot)236 void ctkPluginContext::disconnectServiceListener(QObject* receiver,
237                                                 const char* slot)
238 {
239   Q_D(ctkPluginContext);
240   d->isPluginContextValid();
241   d->plugin->fwCtx->listeners.removeServiceSlot(getPlugin(), receiver, slot);
242 }
243