• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdelibs API Reference
  • KDE Home
  • Contact Us
 

Plasma

  • sources
  • kde-4.12
  • kdelibs
  • plasma
pluginloader.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2010 Ryan Rix <ry@n.rix.si>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU Library General Public License as
6  * published by the Free Software Foundation; either version 2, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this program; if not, write to the
16  * Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  */
19 
20 #include "pluginloader.h"
21 
22 #include <kdebug.h>
23 #include <kglobal.h>
24 #include <kservice.h>
25 #include <kservicetypetrader.h>
26 #include <kstandarddirs.h>
27 #include <kplugininfo.h>
28 
29 #include "applet.h"
30 #include "abstractrunner.h"
31 #include "containment.h"
32 #include "packagestructure.h"
33 #include "popupapplet.h"
34 #include "private/applet_p.h"
35 #include "private/extenderapplet_p.h"
36 #include "private/service_p.h" // for NullService
37 #include "private/storage_p.h"
38 
39 namespace Plasma {
40 
41 static PluginLoader* s_pluginLoader = 0;
42 
43 class PluginLoaderPrivate
44 {
45 
46 };
47 
48 PluginLoader::PluginLoader()
49  : d(0)
50 {
51 }
52 
53 PluginLoader::~PluginLoader()
54 {
55  delete d;
56 }
57 
58 void PluginLoader::setPluginLoader(PluginLoader* loader)
59 {
60  if (!s_pluginLoader) {
61  s_pluginLoader = loader;
62  } else {
63  kDebug() << "Cannot set pluginLoader, already set!" << s_pluginLoader;
64  }
65 }
66 
67 PluginLoader *PluginLoader::pluginLoader()
68 {
69  if (!s_pluginLoader) {
70  // we have been called before any PluginLoader was set, so just use the default
71  // implementation. this prevents plugins from nefariously injecting their own
72  // plugin loader if the app doesn't
73  s_pluginLoader = new PluginLoader;
74  }
75 
76  return s_pluginLoader;
77 }
78 
79 Applet *PluginLoader::loadApplet(const QString &name, uint appletId, const QVariantList &args)
80 {
81  // the application-specific appletLoader failed to create an applet, here we try with our own logic.
82  if (name.isEmpty()) {
83  return 0;
84  }
85 
86  Applet *applet = internalLoadApplet(name, appletId, args);
87  if (applet) {
88  return applet;
89  }
90 
91  const QString constraint = QString("[X-KDE-PluginInfo-Name] == '%1'").arg(name);
92  KService::List offers = KServiceTypeTrader::self()->query("Plasma/Applet", constraint);
93 
94  bool isContainment = false;
95  if (offers.isEmpty()) {
96  //TODO: what would be -really- cool is offer to try and download the applet
97  // from the network at this point
98  offers = KServiceTypeTrader::self()->query("Plasma/Containment", constraint);
99  if (offers.count() > 0) {
100  isContainment = true;
101  }
102  }
103 
104  /* if (offers.count() > 1) {
105  kDebug() << "hey! we got more than one! let's blindly take the first one";
106  } */
107 
108  AppletPrivate::filterOffers(offers);
109  if (offers.isEmpty()) {
110  kDebug() << "offers is empty for " << name;
111  return 0;
112  }
113 
114  KService::Ptr offer = offers.first();
115 
116  if (appletId == 0) {
117  appletId = ++AppletPrivate::s_maxAppletId;
118  }
119 
120  QVariantList allArgs;
121  allArgs << offer->storageId() << appletId << args;
122 
123  if (!offer->property("X-Plasma-API").toString().isEmpty()) {
124  kDebug() << "we have a script using the"
125  << offer->property("X-Plasma-API").toString() << "API";
126  if (isContainment) {
127  return new Containment(0, allArgs);
128  } else {
129  if (offer->serviceTypes().contains("Plasma/Containment")) {
130  return new Containment(0, allArgs);
131  } else if (offer->serviceTypes().contains("Plasma/PopupApplet")) {
132  return new PopupApplet(0, allArgs);
133  } else {
134  return new Applet(0, allArgs);
135  }
136  }
137  }
138 
139  KPluginLoader plugin(*offer);
140 
141  if (!Plasma::isPluginVersionCompatible(plugin.pluginVersion()) &&
142  (name != "internal:extender")) {
143  return 0;
144  }
145 
146 
147  QString error;
148  if (name == "internal:extender") {
149  applet = new ExtenderApplet(0, allArgs);
150  } else {
151  applet = offer->createInstance<Plasma::Applet>(0, allArgs, &error);
152  }
153 
154  if (!applet) {
155  kWarning() << "Could not load applet" << name << "! reason given:" << error;
156  }
157 
158  return applet;
159 }
160 
161 DataEngine *PluginLoader::loadDataEngine(const QString &name)
162 {
163  DataEngine *engine = internalLoadDataEngine(name);
164  if (engine) {
165  return engine;
166  }
167 
168  // load the engine, add it to the engines
169  QString constraint = QString("[X-KDE-PluginInfo-Name] == '%1'").arg(name);
170  KService::List offers = KServiceTypeTrader::self()->query("Plasma/DataEngine",
171  constraint);
172  QString error;
173 
174  if (offers.isEmpty()) {
175  kDebug() << "offers are empty for " << name << " with constraint " << constraint;
176  } else {
177  QVariantList allArgs;
178  allArgs << offers.first()->storageId();
179  QString api = offers.first()->property("X-Plasma-API").toString();
180  if (api.isEmpty()) {
181  if (offers.first()) {
182  KPluginLoader plugin(*offers.first());
183  if (Plasma::isPluginVersionCompatible(plugin.pluginVersion())) {
184  engine = offers.first()->createInstance<Plasma::DataEngine>(0, allArgs, &error);
185  }
186  }
187  } else {
188  engine = new DataEngine(0, offers.first());
189  }
190  }
191 
192  if (!engine) {
193  kDebug() << "Couldn't load engine \"" << name << "\". Error given: " << error;
194  }
195 
196  return engine;
197 }
198 
199 AbstractRunner *PluginLoader::loadRunner(const QString &name)
200 {
201  // FIXME: RunnerManager is all wrapped around runner loading; that should be sorted out
202  // and the actual plugin loading added here
203  return internalLoadRunner(name);
204 }
205 
206 Service *PluginLoader::loadService(const QString &name, const QVariantList &args, QObject *parent)
207 {
208  Service *service = internalLoadService(name, args, parent);
209  if (service) {
210  return service;
211  }
212 
213  //TODO: scripting API support
214  if (name.isEmpty()) {
215  return new NullService(QString(), parent);
216  } else if (name == "org.kde.servicestorage") {
217  return new Storage(parent);
218  }
219 
220  QString constraint = QString("[X-KDE-PluginInfo-Name] == '%1'").arg(name);
221  KService::List offers = KServiceTypeTrader::self()->query("Plasma/Service", constraint);
222 
223  if (offers.isEmpty()) {
224  kDebug() << "offers is empty for " << name;
225  return new NullService(name, parent);
226  }
227 
228  KService::Ptr offer = offers.first();
229  QString error;
230 
231  if (Plasma::isPluginVersionCompatible(KPluginLoader(*offer).pluginVersion())) {
232  service = offer->createInstance<Plasma::Service>(parent, args, &error);
233  }
234 
235  if (!service) {
236  kDebug() << "Couldn't load Service \"" << name << "\"! reason given: " << error;
237  return new NullService(name, parent);
238  }
239 
240  if (service->name().isEmpty()) {
241  service->setName(name);
242  }
243 
244  return service;
245 }
246 
247 KPluginInfo::List PluginLoader::listAppletInfo(const QString &category, const QString &parentApp)
248 {
249  KPluginInfo::List list;
250 
251  if (parentApp.isEmpty() || parentApp == KGlobal::mainComponent().componentName()) {
252  list = internalAppletInfo(category);
253  }
254 
255  QString constraint = AppletPrivate::parentAppConstraint(parentApp);
256 
257  //note: constraint guaranteed non-empty from here down
258  if (category.isEmpty()) { //use all but the excluded categories
259  KConfigGroup group(KGlobal::config(), "General");
260  QStringList excluded = group.readEntry("ExcludeCategories", QStringList());
261  foreach (const QString &category, excluded) {
262  constraint.append(" and [X-KDE-PluginInfo-Category] != '").append(category).append("'");
263  }
264  } else { //specific category (this could be an excluded one - is that bad?)
265  constraint.append(" and ").append("[X-KDE-PluginInfo-Category] == '").append(category).append("'");
266  if (category == "Miscellaneous") {
267  constraint.append(" or (not exist [X-KDE-PluginInfo-Category] or [X-KDE-PluginInfo-Category] == '')");
268  }
269  }
270 
271  KService::List offers = KServiceTypeTrader::self()->query("Plasma/Applet", constraint);
272 
273  //now we have to do some manual filtering because the constraint can't handle everything
274  AppletPrivate::filterOffers(offers);
275 
276  //kDebug() << "Applet::listAppletInfo constraint was '" << constraint
277  // << "' which got us " << offers.count() << " matches";
278  return KPluginInfo::fromServices(offers);
279 }
280 
281 KPluginInfo::List PluginLoader::listDataEngineInfo(const QString &parentApp)
282 {
283  KPluginInfo::List list;
284 
285  if (parentApp.isEmpty() || parentApp == KGlobal::mainComponent().componentName()) {
286  list = internalDataEngineInfo();
287  }
288 
289  QString constraint;
290  if (parentApp.isEmpty()) {
291  constraint.append("not exist [X-KDE-ParentApp]");
292  } else {
293  constraint.append("[X-KDE-ParentApp] == '").append(parentApp).append("'");
294  }
295 
296  KService::List offers = KServiceTypeTrader::self()->query("Plasma/DataEngine", constraint);
297  return list + KPluginInfo::fromServices(offers);
298 }
299 
300 KPluginInfo::List PluginLoader::listRunnerInfo(const QString &parentApp)
301 {
302  KPluginInfo::List list;
303 
304  if (parentApp.isEmpty() || parentApp == KGlobal::mainComponent().componentName()) {
305  list = internalRunnerInfo();
306  }
307 
308  QString constraint;
309  if (parentApp.isEmpty()) {
310  constraint.append("not exist [X-KDE-ParentApp]");
311  } else {
312  constraint.append("[X-KDE-ParentApp] == '").append(parentApp).append("'");
313  }
314 
315  KService::List offers = KServiceTypeTrader::self()->query("Plasma/Runner", constraint);
316  return list + KPluginInfo::fromServices(offers);
317 }
318 
319 Applet* PluginLoader::internalLoadApplet(const QString &name, uint appletId, const QVariantList &args)
320 {
321  Q_UNUSED(name)
322  Q_UNUSED(appletId)
323  Q_UNUSED(args)
324  return 0;
325 }
326 
327 DataEngine* PluginLoader::internalLoadDataEngine(const QString &name)
328 {
329  Q_UNUSED(name)
330  return 0;
331 }
332 
333 AbstractRunner* PluginLoader::internalLoadRunner(const QString &name)
334 {
335  Q_UNUSED(name)
336  return 0;
337 }
338 
339 Service* PluginLoader::internalLoadService(const QString &name, const QVariantList &args, QObject *parent)
340 {
341  Q_UNUSED(name)
342  Q_UNUSED(args)
343  Q_UNUSED(parent)
344  return 0;
345 }
346 
347 KPluginInfo::List PluginLoader::internalAppletInfo(const QString &category) const
348 {
349  Q_UNUSED(category)
350  return KPluginInfo::List();
351 }
352 
353 KPluginInfo::List PluginLoader::internalDataEngineInfo() const
354 {
355  return KPluginInfo::List();
356 }
357 
358 KPluginInfo::List PluginLoader::internalRunnerInfo() const
359 {
360  return KPluginInfo::List();
361 }
362 
363 KPluginInfo::List PluginLoader::internalServiceInfo() const
364 {
365  return KPluginInfo::List();
366 }
367 
368 static KPluginInfo::List standardInternalInfo(const QString &type, const QString &category = QString())
369 {
370  QStringList files = KGlobal::dirs()->findAllResources("appdata",
371  "plasma/internal/" + type + "/*.desktop",
372  KStandardDirs::NoDuplicates);
373 
374  KPluginInfo::List allInfo = KPluginInfo::fromFiles(files);
375 
376  if (category.isEmpty() || allInfo.isEmpty()) {
377  return allInfo;
378  }
379 
380  KPluginInfo::List matchingInfo;
381  foreach (const KPluginInfo &info, allInfo) {
382  if (info.category().compare(category, Qt::CaseInsensitive) == 0) {
383  matchingInfo << info;
384  }
385  }
386 
387  return matchingInfo;
388 }
389 
390 KPluginInfo::List PluginLoader::standardInternalAppletInfo(const QString &category) const
391 {
392  return standardInternalInfo("applets", category);
393 }
394 
395 KPluginInfo::List PluginLoader::standardInternalDataEngineInfo() const
396 {
397  return standardInternalInfo("dataengines");
398 }
399 
400 KPluginInfo::List PluginLoader::standardInternalRunnerInfo() const
401 {
402  return standardInternalInfo("runners");
403 }
404 
405 KPluginInfo::List PluginLoader::standardInternalServiceInfo() const
406 {
407  return standardInternalInfo("services");
408 }
409 
410 } // Plasma Namespace
411 
Plasma::Service::setName
void setName(const QString &name)
Sets the name of the Service; useful for Services not loaded from plugins, which use the plugin name ...
Definition: service.cpp:318
Plasma::PluginLoader::loadDataEngine
DataEngine * loadDataEngine(const QString &name)
Load a DataEngine plugin.
Definition: pluginloader.cpp:161
Plasma::PluginLoader::pluginLoader
static PluginLoader * pluginLoader()
Return the active plugin loader.
Definition: pluginloader.cpp:67
abstractrunner.h
Plasma::PluginLoader::internalServiceInfo
virtual KPluginInfo::List internalServiceInfo() const
Returns a list of all known Runner implementations.
Definition: pluginloader.cpp:363
pluginloader.h
Plasma::PluginLoader::standardInternalServiceInfo
KPluginInfo::List standardInternalServiceInfo() const
Standardized mechanism for providing internal Applets by install .desktop files in $APPPDATA/plasma/i...
Definition: pluginloader.cpp:405
Plasma::AbstractRunner
An abstract base class for Plasma Runner plugins.
Definition: abstractrunner.h:63
Plasma::Service::name
QString name
Definition: service.h:97
Plasma::PluginLoader::loadRunner
AbstractRunner * loadRunner(const QString &name)
Load a Runner plugin.
Definition: pluginloader.cpp:199
Plasma::PluginLoader::internalRunnerInfo
virtual KPluginInfo::List internalRunnerInfo() const
Returns a list of all known Runner implementations.
Definition: pluginloader.cpp:358
containment.h
Plasma::PluginLoader::listAppletInfo
KPluginInfo::List listAppletInfo(const QString &category, const QString &parentApp=QString())
Returns a list of all known applets.
Definition: pluginloader.cpp:247
QObject
Plasma::Service
This class provides a generic API for write access to settings or services.
Definition: service.h:91
Plasma::PluginLoader::internalDataEngineInfo
virtual KPluginInfo::List internalDataEngineInfo() const
A re-implementable method that allows subclasses to provide additional DataEngines for DataEngineMana...
Definition: pluginloader.cpp:353
Plasma::isPluginVersionCompatible
bool isPluginVersionCompatible(unsigned int version)
Verifies that a plugin is compatible with plasma.
Definition: version.cpp:51
Plasma::Applet
The base Applet class.
Definition: applet.h:77
Plasma::PluginLoader::internalLoadRunner
virtual AbstractRunner * internalLoadRunner(const QString &name)
A re-implementable method that allows subclasses to override the default behaviour of loadRunner...
Definition: pluginloader.cpp:333
Plasma::PopupApplet
Allows applets to automatically 'collapse' into an icon when put in an panel, and is a convenient bas...
Definition: popupapplet.h:52
Plasma::PluginLoader::standardInternalRunnerInfo
KPluginInfo::List standardInternalRunnerInfo() const
Standardized mechanism for providing internal Applets by install .desktop files in $APPPDATA/plasma/i...
Definition: pluginloader.cpp:400
Plasma::DataEngine
Data provider for plasmoids (Plasma plugins)
Definition: dataengine.h:58
applet.h
Plasma::DataEngine::query
Q_INVOKABLE DataEngine::Data query(const QString &source) const
Gets the Data associated with a data source.
Definition: dataengine.cpp:133
Plasma::PluginLoader::loadApplet
Applet * loadApplet(const QString &name, uint appletId=0, const QVariantList &args=QVariantList())
Load an Applet plugin.
Definition: pluginloader.cpp:79
Plasma::s_pluginLoader
static PluginLoader * s_pluginLoader
Definition: pluginloader.cpp:41
Plasma::PluginLoader::setPluginLoader
static void setPluginLoader(PluginLoader *loader)
Set the plugin loader which will be queried for all loads.
Definition: pluginloader.cpp:58
Plasma::PluginLoader
This is an abstract base class which defines an interface to which Plasma's Applet Loading logic can ...
Definition: pluginloader.h:51
Plasma::PluginLoader::internalAppletInfo
virtual KPluginInfo::List internalAppletInfo(const QString &category) const
A re-implementable method that allows subclasses to provide additional applets for listAppletInfo...
Definition: pluginloader.cpp:347
Plasma::type
static QScriptValue type(QScriptContext *ctx, QScriptEngine *eng)
Definition: easingcurve.cpp:63
Plasma::PluginLoader::PluginLoader
PluginLoader()
Definition: pluginloader.cpp:48
Plasma::PluginLoader::loadService
Service * loadService(const QString &name, const QVariantList &args, QObject *parent=0)
Load a Service plugin.
Definition: pluginloader.cpp:206
Plasma::PluginLoader::listRunnerInfo
KPluginInfo::List listRunnerInfo(const QString &parentApp=QString())
Returns a list of all known Runner implementations.
Definition: pluginloader.cpp:300
packagestructure.h
Plasma::PluginLoader::listDataEngineInfo
KPluginInfo::List listDataEngineInfo(const QString &parentApp=QString())
Returns a list of all known DataEngines.
Definition: pluginloader.cpp:281
Plasma::standardInternalInfo
static KPluginInfo::List standardInternalInfo(const QString &type, const QString &category=QString())
Definition: pluginloader.cpp:368
Plasma::PluginLoader::internalLoadDataEngine
virtual DataEngine * internalLoadDataEngine(const QString &name)
A re-implementable method that allows subclasses to override the default behaviour of loadDataEngine...
Definition: pluginloader.cpp:327
Plasma::PluginLoader::standardInternalDataEngineInfo
KPluginInfo::List standardInternalDataEngineInfo() const
Standardized mechanism for providing internal Applets by install .desktop files in $APPPDATA/plasma/i...
Definition: pluginloader.cpp:395
Plasma::PluginLoader::~PluginLoader
virtual ~PluginLoader()
Definition: pluginloader.cpp:53
Plasma::Containment
The base class for plugins that provide backgrounds and applet grouping containers.
Definition: containment.h:72
popupapplet.h
Plasma::PluginLoader::standardInternalAppletInfo
KPluginInfo::List standardInternalAppletInfo(const QString &category) const
Standardized mechanism for providing internal Applets by install .desktop files in $APPPDATA/plasma/i...
Definition: pluginloader.cpp:390
Plasma::PluginLoader::internalLoadService
virtual Service * internalLoadService(const QString &name, const QVariantList &args, QObject *parent=0)
A re-implementable method that allows subclasses to override the default behaviour of loadService...
Definition: pluginloader.cpp:339
Plasma::PluginLoader::internalLoadApplet
virtual Applet * internalLoadApplet(const QString &name, uint appletId=0, const QVariantList &args=QVariantList())
A re-implementable method that allows subclasses to override the default behaviour of loadApplet...
Definition: pluginloader.cpp:319
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:48:33 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

Plasma

Skip menu "Plasma"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdelibs API Reference

Skip menu "kdelibs API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  • kjsembed
  •   WTF
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Nepomuk-Core
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal