[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-edu-devel
Subject:    Re: [kde-edu-devel] possible design math app
From:       Dominique Devriese <fritmebufstek () pandora ! be>
Date:       2002-08-11 16:23:01
[Download RAW message or body]

Eva Brucherseifer <eva@kde.org> writes:

> > This is my major problem with your design.  KParts are not meant for
> > this kind of thing.  They are idd a plugin architecture, but for _one_
> > specific sort of plugins: kparts are for viewing and editing
> > documents.  Their design and implementation reflect this goal.  Many
> > people seem to have misunderstood this, as we also have KonsolePart,
> > which is being used in ways that KParts were not designed for.  It
> > causes many problems, and weird workarounds for problems like what to
> > do with KPart methods like openURL etc.
> 
> That is not completly true. libkparts contains several classes,
> where there  
> are at the moment 3 classes ready for immidiate use:
> KParts::ReadOnlyPart, KParts::ReadWritePart, KParts::Plugin.
> You are completly right about the first two ones and actually that
> is what I  
> tried to say in my email, that they are not appropriate. 
> But Plugin might be the correct one, and if it is not sufficient
> (which I am  
> very sure about), then we need to implement our own KParts::EduPlugin.
> Maybe I used sometimes kparts as a general term for the kparts lib,
> which also  
> includes the plugin - maybe that caused the confusion....
>
Yes, idd, i was confused, however, i'm sorry to say that i don't think
the plugin stuff is usable either, here's why:

this comes from the documentation of KParts::Plugin:

 * A plugin is the way to add actions to an existing KParts application,
 * or to a @ref Part.

I think you are wrong to think that it is useful here, because:
1 the main part of it is its loading mechanism: it has a way to search
a directory for files, which it presents to the program as plugin
infos it can load.  This is imho not usable for KDEEdu since we want
desktop files with more information than the file name of the module
binary...  KParts::Plugin doesn't use desktop files at all..
2 The idea behind it is to load all the plugins at once and merge all 
their guis with the main program.  Plugins can be disabled from
loading with some KConfig stuff, but to turn this into what we want
would become a hack that would require more work than to write our own
plugin handling stuff..  The merging of the guis is definitely not
acceptable, we only want one gui merged at one moment...
3 if you look at the source of plugin.cpp, you'll see that almost all
of it would have to be altered to suit our needs.  I think that like
that it would be easier to just start over on our own...

> 
> >
> > What we need here aren't KParts, but normal plugins.  I would propose
> > you look at some stuff in kdelibs/interfaces/kregexpeditor together
> > with kdeutils/kregexpeditor.  I'll try to explain briefly how it
> > works:
> > 1 you define an abstract class containing the interface you want all
> > plugins to have.  This most of the time is rather easy, here's what i
> > think it should look like:
> >
> > class KEduPlugin
> > {
> >         QWidget* widget();
> >         KActionCollection& actionCollection();
> >         const QString uiRcFile();
> > };
> >
> > All plugins export ( using KGenericFactory and friends ) their own
> > subclass of this class, and install a Desktop file at an appropriate
> > place.  The shell finds plugins using KTrader, casts it to
> > KEduPlugin* and then uses it in some way..
> >
> > That's about it.  If you want to see a real-life implementation of
> > this, look at the kregexpeditor sources in
> > kdelibs/interfaces/kregexpeditor
> 
> I am glad about every example, so I'll have a look at it. But I think, 
> basically we are trying to say the same ;-)

not entirely..

>
> > > Here is the design:
> > >
> > > You have a shell, which implements educational concepts.
> > > This can be:
> > > learning something, with imidiate feedback if an answer is correct or
> > > not. training: do the excercises as fast as possible
> > > feedback at the end of a set of excercises
> > > some flashcard approach, where excercises with incorrect answers come up
> > > again
> > > exercises embedded in games
> > > statistics
> > > .... (whatever teachers come up with)
> >
> > this would work the same way...
> >
> > > This shell embeds widgets which each implement an excercise, like
> > > timestables,
> > > fractions, calculation of percentage, addition, substruction, etc. Each
> > > widget is a plugin. Its capabilites are configured in desktop files,
> > > as they
> > > exist for kparts:
> >
> > or other things for that matter ( e.g. kregexpeditor ;)
> 
>  as above ;-)

actually, KParts::Plugin doesn't use desktop files, if you read the
source, its loading mechanism only checks for files in a directory,
and allows you to load them by filename.  I do think we need desktop
files to allow us to show a name for the plugin before we load
it...

> 
> >
> > > -----------------------------
> > > [Desktop Entry]
> > > Name=TimestablesEduPlugin
> > > Type=Service
> > > ServiceTypes=KEduParts/MathLearning,KEduParts/MathTraining
> > > X-KDE-Library=libktimestables
> > > Icon=ktimestables
> > > -----------------------------
> >
> > this would stay entirely the same (except that i would change
> > KEduParts to KEduPlugins :)
> 
> yes, that would be more appropriate :-)

to avoid more name confusion.. :)
> 
> >
> > > The large difference to kparts is here, that kparts are based on
> > > mimetypes and
> > > that they always have an attached document. Kparts-plugins also exist,
> > > but they don't have widgets. So we need something new here.
> >
> > like an Interface together with KTrader stuff... ;)
> 
> Well, if KParts::Plugin can have widgets, I'd try to do it that way
> and extend  
> the interface in an inherited class.

that would of course be possible, but KParts::Plugin is actually a
very tiny class, the only added funtionality is 
1 the loading stuff which we can't use (see above)
2 some logic to find an xml file name from a library name, which would
be trivial to implement on our own
3 the fact that it inherits KXMLGUIClient and QObject, which we also
want, but that would again be trivial...

> 
> >
> > > So how does the shell know which edu-plugins there are to embed? For that
> > > kparts has the KTrader. KTrader uses the sycoca-database which scans all
> > > desktop files and builds a cache. You can use the KTrader class to ask
> > > for plugins which fulfill certain capabilites.
> > > But of course you can also have a shell which only embeds a special
> > > plugin (that way you still have the setup you have at the moment with a
> > > lot of small
> > > apps). You basically can use the same plugins in a lot of different
> > > ways.
> >
> > stays the same too..
> >
> > > But we are not finished yet. What we also need (and we also don't have it
> > > in kparts) is a communication between the shell and the plugin. The shell
> > > needs to be notified about the result of an exercise and the shell needs
> > > to tell the plugin to create a new excercise.
> > > I see 2 ways to do this:
> > > signals and slots
> > > 	the interface for the plugin contains predefined signals and
> > > slots for the
> > > 	communication, so the shell can connect them after loading the plugin
> > > 	and both shell and plugin can use these connections.
> > > DCOP (desktop communication protocol)
> > > 	the desktop communication protocol lets you send messages which are not
> > > 	defined in the interface. Each member of the communication can get a
> > > list of available dcop commands.
> > > The advantage of DCOP is, that you have reduced compile time
> > > dependencies. Still signals and slots might be easier in the beginning,
> > > so am in favour of that and if we need a more complex communication, we
> > > can still use DCOP later.
> >
> > This is the second thing i would like to react to:
> > 1 DCOP is for _interprocess_communication_.  Communication between
> > different processes.  It is _totally_unsuitable_ here.
> > 2 even signals/slots are unnecessary here.  You can just simply use
> > plain old function calls on the Interface object.
> > 3 I don't really see what you mean with "reduced compile time
> > dependencies".  Anyway, the Interface stuff is good here too, since
> > plugins only need the Interface header file to compile, and the same
> > goes for the shell app.
> 
> OK, I'll try to explain it more detailed:
> You have communication in 2 directions:
> 1) shell ----->  plugin
> 2) shell <-----  plugin
> 
> The first part is easy and simply uses the methods/slots of the
> interfaces of  
> the edu-plugin. But the second part is rather difficult because of these 
> reasons:
> the plugin doesn't know which type of shell it was loaded by and what it's 
> capabilites are. Well, you can transfer some information from the shell to 
> the plugin, but I'd regard it as rather nasty.

You can have shells be subclasses of a KEduShellProgram, which has
some functions.  You can pass these as arguments to the KEduPlugin's,
so they can use it to pass info, get info etc. in the normal, clean
C++ way...

> you want to have different interfaces in the shell, depending on the
> educational concept, so sometimes the plugin needs to transfer more
> data  
> back, sometimes not. Maybe not in the beginning of the
> implementation, but we  
> should keep things flexible.

shells can always do whatever they want with the info they receive,
and plugins can query the info they need...

> 
> So how do my 2 proposed concepts help?
> signals & slots
> The signals of a plugin can be used to transport data from the plugin to the 
> shell, slots for the other direction. The important thing for signals is:  
> They don't need to be connected, so if a shell isn't interested in the data, 
> it doesn't setup a connection.

a shell can provide an empty implementation for a method of the
KEduProgram Base class...

> Also signals& slots is the common way to do communication in QT/KDE (rather 
> than callbacks...), is well-known, easy-to-use and thus a good
> solution.

All this holds even more for c++ functions.  I tend to not like how
people always see uses for signal/slot stuff everywhere, and i think
it's most of the time unnecessary.  In general, if you don't intend
multiple objects to connect to a signal, you're imho wrong to want to
use signal/slot stuff, and should be using an interface class, so that
you get correct warnings at compile time, and not annoying debug
output on runtime, and cause it's a cleaner approach used in all
object-oriented programs..

> The difficult thing is only. Whenever you change the C++ interface of the 
> communication, your shells/plugins are not binary compatible anymore (this 
> also yields for plain function calls) :-( 

this is more a question of well designing your interface, imho.
Perhaps it would be a good idea to have some signal stuff, or a way to
allow for possible future extensions in the spirit of
KPart::browserExtension() ?

> DCOP
> With dcop you don't need to predifine the interface for the communication. 
> (Remember: for signals & slots you need to have all signals and
> slots in your
> basic interface description of the edupart - What happens, if you want to 
> transfer somethings special?). 

You're wrong here if you think that adding signals/slots isn't binary
compatible.  And exactly what do you mean by "something special" ?

> With dcop each member of the communication can "explore" the dcop
> interface of  
> the other member.

this also holds for signals/slots: "man qmetaobject" might help.
there are the functions QMetaObject::signalNames(), and
QMetaObject::slotNames(), which are quite similar to their DCOP
counterparts, only faster, cleaner and more suitable.

> In order to extend the communication capabilites of one 
> member, you don't need to change the central KParts::EduPlugin, but
> only the  
> dcop interface of a single shell or a signle plugin. And here comes
> the  
> "compile time dependency": you don't have to recompile all shells
> and parts  
> to use the new feature.

Neither do you have to with signals/slots.  There's a good reference
somewhere on developer.kde.org on binary compatibility, that you might
read...

> Instead you have a runtime dependency with
> check -  
> that means you can check if a method is available - how would you do that in 
> C++ without crashing the app?

there are lots of possibilities:
1 signal/slots stuff
2 virtual functions that can have empty implementations
3 a virtual method call( QCString function, void* args )
4 subclasses and dynamic_cast, but due to a gcc bug with dynamic
loading that is not usable ATM.
5 ... ?

> 
> The third method maybe is XML-RPC, but I don't know anything about
>it.

i read that it was very basic, very unextensible, and almost
completely obsoleted by DCOP..

> 
> Well, to conclude this discussion on communication:
> I am much in favour of first using signals&slots, because it's a concept 
> everyone knows. 

I agree that it might be useful, but it should be secondary to a good
design of the interface classes..

> If we experience problems, where it isn't enough (maybe also,
> because we get a  
> lot of plugins from outside of kdeedu and we don't want to brake 
> compatibility), we can always add DCOP.

as said, i disagree...

> 
> 
> >
> > > In order to have several excercise widgets in one shell we might use a
> > > QWidgetStack to hide the inactive excercises.
> >
> > hm... didn't know that one, but it seems appropriate, indeed.  Or
> > perhaps we could use a KTabCtl, to show things in different tab
> > pages...  But i am very bad at ui design... :)
> >
> > > The great advantage I see in such a design is the following:
> > > plugins can be reused
> >
> > idd
> >
> > > educational concepts don't need to be implemented over and over
> > > again
> >
> > hm.. could you give an example of that, cause i don't quite understand
> > what you mean, here...
> 
> Now each program (kbruch, kmathtool, kpercentage, ...) needs an own 
> implementation for statistics, the test modes etc. See also the list
> I gave  
> in the beginning of the first mail. 

Right, sorry i didn't get that...

> 
> >
> > > common look&feel
> >
> > err.. no: only the shell is always the same, as your plugins have
> > their own QWidget's, they can look any way they want.  Btw. the
> > KEduPlugin presents a KActionCollection and a rc file, so that
> > the shell's ui is adaptable by the plugins in the same way that it
> > works for KParts...
> 
> Yes sure - the KEduPlugin can look any way. But you also have
> widgets in your  
> shell, which are the interface for the educational concepts (like
> statistics,  
> like a start/stop button for the tests, like a wizard to setup a
> test, ....)

You're right here...

> 
> >
> > > So how would I proceed....
> > > first I'd take ktt (or any other little math app) into a kpart.
> > > implement a new interface class for kedupart (which would go into a
> > > new lib:
> > > libeduparts), inspired by the kparts code
> > > check with other KDE people if ktrader can be extended or reimplement
> > > something similar
> >
> > KTrader is not solely for KParts as it is now.  KTrader does not need
> > any additions..
> 
> even better :-)
> 

:)

> >
> > > How does that sound? Any comments/help/critizism is welcome!
> >
> > well, those were it :)
> > i hope you understand what i'm trying to explain, if not, please ask
> > me...
> 
> Well, thank you. I hope my explanations are a bit clearer
> now... sometimes a  
> bit of paper is really helpful ;-)

yeah, but nothing beats a good discussion :)
cheers
domi

-- 
Hey!!  Let's watch the' ELEVATOR go UP and DOWN at th' HILTON HOTEL!!
_______________________________________________
kde-edu-devel mailing list
kde-edu-devel@mail.kde.org
http://mail.kde.org/mailman/listinfo/kde-edu-devel
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic