kdevelop component factories

Simon Hausmann hausmann at kde.org
Sun Apr 7 20:20:05 UTC 2002


Hi,

(kdevelop == gideon in this mail -- and: warning, long mail :)

Currently writing a kdevelop component involves a lot of copy&paste.
The *factory.cpp/h files are almost always 99% copy&paste, and
duplicated code is bad, very bad.

I tried to address this very problem for 'normal' KDE components,
for KDE 3. So for simple plugin like objects it boils down to the
instantiating of a template called KGenericFactory, for gui parts
there's a more advanced KParts::GenericFactory, allowing the
complete removal of those foofactory.cpp/h files.

There are some minor constraints to plugins/parts using these
templates though.

Either way looking at gideon I see a lot of *factory files, too, and
I would like to work on getting rid of these (unless someone
objects, of course :)

KDevelop is special in two aspects though:

1) There's a KDevFactory, which exists for the purpose of
   conveniently passing a reference of the central KDevApi object to
   components.

2) KDevelop Parts (of KDevPart type) are not parts in the strict
   sense of how they are meant. The original idea of a part is that
   it represents a document and that there's a separate view object
   (of QWidget type) for it. KDevPart 'disables' this functionality
   (by making setWidget/widget private) . 

These two points make a switch to KGenericFactory a bit more
difficult, requiring source incompatible changes in some ways.

I don't want to press this change in. If anyone doesn't like the
idea or the changes involved in it or doesn't see any advantage then
just say so. But let me first elaborate on what changes I'm thinking
of :)

Of the two mentioned points the first one is kind of a typical
problem. I tried to address this in the KGenericFactory template, by
introducing a second template argument. That template argument
influences how the 'generated' KLibFactory calls the constructor of
the component. In fact it specifies the type of the parent object,
which needs to inherit from QObject. It's kind of a backdoor:

typedef KGenericFactory< FooPlugin, KDevApi > FooFactory;

With this instantiation FooPlugin needs to provide the following
constructor:

FooPlugin( KDevApi *parent, const char *name, const QStringList &args );

The factory will call it, if the passed classname in the create call
is 'FooPlugin' and if the parent Qt object inherits from KDevApi,
allowing a safe cast. The args string list is just passed on from
create() .

Applying this feature to kdevelop would solve the first mentioned
point, but it would also mean that kdevelop parts are always child
objects of the KDevApi object. I don't think that's necessarily a
bad thing, because it makes it easy for other plugins to look for
other plugins by just using QObject::child() on the devapi object.
But then again, I might overlook something and maybe it's a bad
idea. Bernd, what do you think?

The second point is a bit more difficult. KGF knows that a
KParts::Part construction is difference in the sense that there are
two objects that make up a part: The part and the view. Hence for
parts KGF tries to call a constructor like:

Foo( QWidget *parentWidget, const char *widgetName, 
     QObject *parent, const char *name,
     const QStringList &args );

This doesn't fit very well with KDevPart as the
parentWidget/widgetName arguments are unused, but still required
when using the template.

The only solution that comes to my mind is to change the inheritance
of KDevPart, to make it not inherit from KParts::Part anymore, but
to make it multiply inherit from QObject and KXMLGUIClient. (maybe
it should be called KDevPlugin then?)

And somehow I think that would make sense. The reason why
KParts::Part as base interface exists is to implement the idea of
graphical components, that can have a state like being active or
inactive, with the activation being handled by a PartManager. By
KDevPart design this is not the case for kdevelop components, as they
don't have a widget. They still are GUI components in the sense that
they provide menu/toolbar items though.

To summarize in short my intention behind this design change
proposal:

1) It would make writing kdevelop components easier because it
involves no copy&paste of a good chunk of lines of factory code.

2) It automagically helps to avoid that famous bug when writing
shlib components with regard to internationalization: KGF takes care
of calling insertCatalogue() with the instance name.

Any opinions on that?

(I'd be happy to work on implementing these plans, and with possibly
using KDevPlugin as new interface even an incremental transition
should be possible)


Simon




More information about the KDevelop-devel mailing list