From kde-core-devel Mon Mar 15 01:09:09 2004 From: Frans Englich Date: Mon, 15 Mar 2004 01:09:09 +0000 To: kde-core-devel Subject: Extending KCModuleProxy Message-Id: <200403150209.09556.frans.englich () telia ! com> X-MARC-Message: https://marc.info/?l=kde-core-devel&m=107931274802076 MIME-Version: 1 Content-Type: multipart/mixed; boundary="--Boundary-00=_1IQVAOMQDPlYJLX" --Boundary-00=_1IQVAOMQDPlYJLX Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline I've done some KCM work lately, namely trying to disentangle all the various helper classes, wrapper classes etc. related to using KCMs. (all patches are from top level dir) In kdelibs/kutils/ there's KCModuleProxy, and KControl has its own ProxyWidget in kdebase/KControl/. Both tries to achieve the same thing but the latter is the useful one. Attached kcmultidialog.diff merges both these into KCModuleProxy. In short, more functionality and power in kdelibs and a lighter KControl - the KCM technology is afterall quite generic. This has the following advantages: * Obsoletes quite some duplicated code and some dead code paths in KControl. * All cases where KCMs are used behaves now consistently. For example, bug #72112. That means, all configure dialogs should at least be useful(but not as in comfortable) for 800x600 users(which use KCMs). * All cases which uses KCModuleProxy can now load root KCMs. This further extends integration and flexibility, the line between root and non-root is blurred. For example, k3b can put its Setup2 KCM in its usual configure dialog(and remove it from KControl if that's not already done). * kcmshell becomes an independent app(from KControl) and can be moved to kdelibs(since it is infrastructure). * Good error reporting(which is quite confusing currently) making KCMs easier to code. I would say the code is butt ugly. Doing this merge was a mess - a KCModule in KControl is wrapped in about 5-6(?) classes and this was squeezed into place with KCModuleProxy's own proxy system. BC is kept(right? :). It needs a thorough code review. (Waldo, Walter?). Yes, you will have to look very far for something uglier. Attached kstdgui.diff adds some supporting kstdguiitems. Ok, all that mess was necessary to create the class KCModuleContainer(attached kcmodulecontainer.{cpp,h}), a subclass of KCModule. It is very simple - its constructor(s) takes a list of modules and then builds a KCModule with tabs holding the requested KCMs. This is what the Monitor KCM does but KCModuleContainer is a little bit more elaborated - the comment text in the tooltip, icon on the tab, efficient saving etc. Since it uses KCModuleProxy this one can handle root KCMs. With it follows a macro, used for example like this: KCMODULECONTAINER("randr, kgamma, energy, xinerama", monitor ) Accompanied by a desktop file it results principally in the same as the Monitor kcm which replaces kdebase/kcontrol/display/*. One small detail but worth to notice is that it silently drops requested KCMs which does not exist. For example, we can move kgamma to kdegraphics and kdebase will work just fine. When kdegraphics gets installed it automagically gets added to the Monitor KCM. The macro expands to a factory declaration which creates a KCModuleContainer object. If the module needs to do probing on construction, whether some hardware is available or not, this can be achieved by subclassing KCModuleContainer and doing addModule() manually. But this is of course not the the Right Thing - discussed at the end. When this class/macro is used in the right situations it is very powerful. Some examples: KCMODULECONTAINER("kcmfontinst, fonts", fonts ) Groups all font related in one kcm. Another potential use: KCMODULECONTAINER("kcmkded, componentchooser, kresources", resources ) Results in a KCM, called for example "Software Components" containing 3 tabs - "Service Manager", "KDE Resource Configuration" and "Component Chooser". It solves some problems quite nicely but it clearly has its limitations - the tab widget is not exactly the most user friendly out there as well as KCMs which already has tabs can not be used(but hey, that haven't hindered people before). This class too makes in general the KCM technology stronger and more flexible. For example, one could totally rebuild the KControl layout by only editing KCMODULECONTAINER macros and desktop files - safe, easy and quick. Handy for distributors. This also means that the KCM technology can be used in a slightly different way. For example: Each KCM is written in a "atomic" way - they take care of one thing very well. Then a KCMODULECONTAINER sews them together into one unit, while applications still can be very specific about what KCM/functionality they want to add to their configure dialog(or they could create their own container macro), thus skipping unnecessary options. I haven't ported kcmshell nor KControl to the new Proxy class since I don't know what will be applied/rejected etc. It shouldn't need much work(kcmshell also needs a thorough overlook, it's rather buggy). KControl startup time should also increase since ConfigModule and ProxyWidget can be removed(and a pointer list is all needed instead of instantiating a ConfigModule object for each KCM). I estimate the speed difference would not be very big. Further, some thoughts on KDE4 stuff: * KCMs really need to be able to tell if they should be shown or not( that is, probe for hardware/software). This could be accomplished by adding to KCModule: static virtual bool loadMe() { return true; } (or similar) Support in KCModuleContainer/KCMultiDialog would be easy, and I have some ideas how it would also be possible for "real", independent KCMs without killing KControl startup performance(hiding laptop KCMs etc)... * All the KCM stuff starts to become quite big.. I know absolutely nothing about this kind of questions - would it be suiteable to have a KCM library? * I think it could be a good idea to improve how root KCMs are handled - currently it is a little rough, by simply loading the whole kcm with root prevs. Sometimes the KCM knows better when/how what root privileges it needs. A KCM should be able to tell runtime about its root prevs needs. Comments? Cheers, Frans --Boundary-00=_1IQVAOMQDPlYJLX Content-Type: application/x-tgz; name="kcm.tar.gz" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="kcm.tar.gz" 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 oSH/7oeK --Boundary-00=_1IQVAOMQDPlYJLX--