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