DataEngine & KPluginFactory

David Faure faure at kde.org
Tue Jun 25 10:39:08 UTC 2013


Le lundi 24 juin 2013 12:48:55 Sebastian Kügler a écrit :
> Hey,
> 
> As you know, I'm looking into what's needed for proper plugin support in
> KF5, trying to understand what's going on, and at least making our KDE4
> solution work for KF5. Qt's native plugin functionality is clearly lacking
> for our usecase, as it doesn't allow to have multiple instances of the same
> plugin type. (Say, it is possible to write a new QPA plugin, but you can't
> have a few dataengines loaded as plugins.)
> 
> So KPluginLoader seems to still work fine, but spits out a warning that the
> K_EXPORT_ macro should be ported to the new QPluing (Q_PLUGIN_METADATA)
> stuff -- which isn't suitable for our case. David suggested to pop
> Q_PLUGIN_METADATA into the K_EXPORT_ macro definition, but that apparently
> doesn't help. 

Well, it's not exactly what I suggested :)
K_EXPORT_ is typically in the .cpp file, while Q_PLUGIN_METADATA has to be 
seen by moc, i.e. in the header file.

The idea was more ... figuring out a way to mimick what Qt expects - a QObject 
class with Q_PLUGIN_METADATA, but in our case that qobject is KPluginFactory, 
not the plugin itself.

> Ignoring our home-made deprecation warning, it seems KPlugin* is still
> working.

Clearly I did too good a job with the hack in the macro. It works so people 
want to keep that hack :)

The problem is that it again creates a system that is incompatible with Qt's 
builtin plugin loading. With this hack, there's no .json file that Qt wants to 
use in order to find which plugins to load. So we'll need to keep our own 
description mechanism (.desktop files) and our own selection mechanism 
(ksycoca). I was hoping we could use Qt for all this, with .json files for the 
description (including all the stuff you find in KPluginInfo) and, json for 
querying capabilities (well, the querying is a bit more limited in Qt, better 
use subdirs for plugins of the same type, since there's no trader-query-
syntax, one has to check each plugin in the subdir).

So in the long run, I don't like keeping the current hack. We could of course 
"keep it for now" but porting to something else after a first release will be 
even more trouble (with the need for compat etc.).

My idea was: forget the KPlugin* stuff for a minute, look at a standard Qt5 
pure-Qt plugin, and from there try to elaborate a solution for the plugin 
object being a factory rather than a single object.
Once that's done, try to make it as close to KPluginFactory as possible :)
While doing that, you'll notice that there's no need for any K_EXPORT_ macro.
If you don't feel like doing this, I'll have to (but time is an issue...), 
because I think we should at least evaluate the option of doing something a 
lot more compatible with Qt5.

> So, on to the dataengine. There, we've changed the ctor from taking a
> (QObject*, QVariantMap) to (KPluginInfo, QObject*). The problem here is that
> this won't build, I suppose because the K_EXPORT_ macro expects (QObject*,
> QVariantMap)

Not the export macro, but KPluginFactory. Sure about QVariantMap? I see a 
QVariantList, rather.

   T *create(QObject *parent = 0, const QVariantList &args = QVariantList());

I don't understand why you have this issue now. This was already the case with 
KDE 4. How did you solve it there?

> , and indeed, adding such a ctor makes my timeengine load --
> with the wrong ctor, and obviously missing the KPluginInfo member. So, what
> do to here:
> 
> - Add previous ctor, but where to get the KPluginInfo from, or rather, how
> to get it into our class instance (we already retrieve it from KService)?
> 
> - How can we make it work with the (KPluginInfo, QObject*) signature?

You would need a custom factory deriving from KPluginFactory and 
reimplementing create(). Or you need to change KPluginFactory to expect such a 
ctor, but I'm afraid this would create a huge porting job, since it would mean 
porting all plugins everywhere, even if most of them don't need this.

We could actually have setService or setPluginInfo in KPluginFactory itself 
(and call it from KPluginLoader). I just gave it a try, there's a small issue 
with including kservice.h from kpluginfactory.h since kservice.h itself 
includes kpluginfactory.h (for the template methods). But assuming this is 
solved, we still have to have a way to get at the factory from the plugin.
I can't really find a solution for that :/
The plugin lives in a rather isolated world, with no access to the factory 
that created it...

Wait, we simply want to pass information to the plugin? That's exactly what 
the QVariantList is for. You can just stuff the KPluginInfo in there when 
calling create, and extract it again in the plugin constructor.

-- 
David Faure, faure at kde.org, http://www.davidfaure.fr
Working on KDE, in particular KDE Frameworks 5



More information about the Kde-frameworks-devel mailing list