Difference between revisions of "TDEConfig Module HOWTO"
m (Added categories, template "Applicable to TDE", cosmetic changes) |
m (- Applicable to TDE) |
||
(2 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
− | {{Applicable to TDE}} |
||
− | |||
A '''TDEConfig Module''' is a small library with a TDECModule subclass containing code which builds and support a interface for configuration tasks. The module is then encapsulated in a parent application, for example <tt>tdecmshell</tt>, <tt>KControl</tt> or a <tt>KCMultiDialog</tt>. |
A '''TDEConfig Module''' is a small library with a TDECModule subclass containing code which builds and support a interface for configuration tasks. The module is then encapsulated in a parent application, for example <tt>tdecmshell</tt>, <tt>KControl</tt> or a <tt>KCMultiDialog</tt>. |
||
Line 242: | Line 240: | ||
There are a number of additional things for convenience. |
There are a number of additional things for convenience. |
||
− | |||
=== tdecmshell === |
=== tdecmshell === |
||
Line 251: | Line 248: | ||
$ tdecmshell fonts colors |
$ tdecmshell fonts colors |
||
</syntaxhighlight> |
</syntaxhighlight> |
||
− | |||
=== KCMultiDialog === |
=== KCMultiDialog === |
||
Line 257: | Line 253: | ||
Sometimes, you may want to reuse your <tt>TDECModule</tt> inside an application. There are two ways to accomplish this: |
Sometimes, you may want to reuse your <tt>TDECModule</tt> inside an application. There are two ways to accomplish this: |
||
− | * Use <tt>KCMultiDialog</tt> (in <tt>tdelibs/tdeutils</tt>) |
+ | * Use <tt>KCMultiDialog</tt> (in <tt>tdelibs/tdeutils</tt>)<br>This is a simple dialog that can show an abitrary number of modules in a normal <tt>KDialogBase</tt>. The advantage is that you can control the behaviour and the results much easier that with a separate process. And as your module is a simple library, you can just link to it anyway.<br> |
* Call <code>tdecmshell [modules...]</code>. |
* Call <code>tdecmshell [modules...]</code>. |
||
− | |||
=== KCModuleContainer === |
=== KCModuleContainer === |
||
The class <tt>KCModuleContainer</tt> allows great flexibility with handling modules. The API docs explain it usage the best. |
The class <tt>KCModuleContainer</tt> allows great flexibility with handling modules. The API docs explain it usage the best. |
||
− | |||
== Debugging your module == |
== Debugging your module == |
Latest revision as of 10:12, 8 January 2023
A TDEConfig Module is a small library with a TDECModule subclass containing code which builds and support a interface for configuration tasks. The module is then encapsulated in a parent application, for example tdecmshell, KControl or a KCMultiDialog.
This HOWTO describes how to write TDEConfig Modules. This technology was originally designed for KControl. Although KControl is the application where the TDECModule tehnology is the most used, it is used in several other places as well, such as Kopete and Kontact. This HOWTO describes how to write config modules, regardless of where it will be used. TDEConfig Modules were originally called "KControl Modules".
If the TDECModule in question is intended for KControl the KControl Module Guidelines must be consulted. Much of it applies to KConfig Modules in general, it is probably a good read regardless of what application the KCM targets.
How to write a KConfig Module
Now to the practical side of the matter. Modules have to inherit from the class TDECModule, defined in kcmodule.h, which is part of the tdeui library. This class defines some important functions that are used in the communication between the framework and the module:
virtual void load();
This method is invoked whenever the module should read its configuration (most of the times from a config file) and update the user interface. This happens when the user clicks the "Reset" button in the control center, to undo all of his changes and restore the currently valid settings. NOTE that this is not called after the modules is loaded, so you probably want to call this method in the constructor.
virtual void save();
You might have guessed it: this function gets called when the user wants to save the settings in the user interface, updating the config files or wherever the configuration is stored. The method is called when the user clicks "Apply" or "Ok".
virtual void defaults();
This function is called to set the settings in the module to sensible default values. It gets called when hitting the "Defaults" button. The default values should probably be the same as the ones the application uses when started without a config file.
int buttons();
The module loader calls this function to decide which buttons should be displayed. For example, it does not make sense to display an "Apply" button for one of the information modules. The value returned can be set by modules using setButtons. E.g:
setButtons( KCModule::Ok | KCModule::Help );
will make sure that only the "Ok" and the "Help" button is enabled.
There is also two signals used by the modules:
void changed(bool state);
This signal should be emitted whenever the state of the modules changes. "state" is true, if the contents of the modules differ from the ones in the current configuration, "false" otherwise. For example, if the user changes a value, you emit changed(true). When the user reloads the systems settings, emit changed(false). The module loader uses this signal to keep track about unsaved changes in certain modules.
void quickHelpChanged();
Emit this signal whenever the module's quickhelp changes. Modules implemented as tabbed dialogs might want to implement per-tab quickhelp for example.
There is also a slot for convenience:
void changed();
Calling this slot is equal to emitting changed(true)
.
Making a module available
Ok, now that you have implemented your class with the module, you must make sure it can be accessed.
To achieve this, the preferred way is to simply use KGenericFactory. Don't forget to #include <kgenericfactory.h>
.
typedef KGenericFactory<body TQWidget> KDEDFactory;
K_EXPORT_COMPONENT_FACTORY( kcm_xyz, KDEDFactory( "kcm_xyz" ) );
If you get errors, make sure that the constructor of your derived class equals the one of the TDECModule baseclass (the TQStringList argument matters).
If you need to export more than one module per library, you have to use the old loader. That is, you need to create a function like this:
extern "C"
{
TDEModule *create_xyz(TQWidget *parent, const char *name)
{
return new XYZ(parent, name); // XYZ inherits from TDECModule
};
}
This function and the implementation of the module is then compiled as a shared library. If the name of your modules is 'xyz', the name of the library should be kcm_xyz(.la|.so)
and should be installed into $TDEDIR/lib/trinity
.
Initializing on startup
If your module needs to initialize on TDE session startup, you must have a construct like:
extern "C"
{
TDECModule *init_xyz(TQWidget *parent, const char *name)
{
// Do initialization here
};
}
Don't forget to add X-TDE-Init
to your desktop file. (see below)
Making a KCModule dynamically available
Sometimes it is of interest to hide a TDECModule when it does not have any use for the current situation, for example certain hardware or software is lacking. This is achieved by adding to the library:
extern "C"
{
TDECModule *test_xyz(TQWidget *parent, const char *name)
{
// Probing for hardware/software precense
return true; // If the TDECModule should show up, otherwise it should return false.
};
}
The desktop file must also contain "X-TDE-Test-Module=true" in order for this to work.
The TDECModule will now be "conditionally" loaded, for example when requested via KCMultiDialog, tdecmshell or KControl (as of 2004-03-21 not implemented in KControl).
The desktop file
To declare a TDECModule's existence a desktop file must be installed. Call it "kcm_modulename.desktop".
It could be a good idea to have a look at the desktop file standard.
A module's .desktop file supports the following .desktop directives:
Directive | Description |
---|---|
X-TDE-Library | This is the name of the library, without the kcm_ prefix. So in the example, the library name would be "xyz". |
X-TDE-FactoryName | This entry can be used to set the name of the factory function in the library. If you only have one TDECModule in a library this directive is not needed. If you have several modules in one library you will need a .desktop file for each TDECModule.
For example, if you have a library named kcm_frog.la with two modules, named "kermit" and "quak", you would have: X-KDE-Library=frog
X-KDE-FactoryName=kermit
in one of the .desktop files, and in the other: X-KDE-Library=frog
X-KDE-FactoryName=quak
The module loader would then call the "create_kermit" and "create_quak" functions respectively. |
X-TDE-RootOnly | If this is set to "true", the module must be executed with root permissions. The module loader will then show the module in greyed-out (disabled) state with a warning until the "modify" button is pressed which allows running the module in an root environment using tdesu and QXEmbed. |
X-TDE-ParentApp | The application you put in this entry determines in what situations it will show. For example, if the line says X-TDE-ParentApp=kcontrol the module will show up in KControl. It is very crucial the selected ParentApp is correct, otherwise the module show up in unnecessary places.
|
X-TDE-Init | If the module has to perform some action at system startup, use this entry to build the name of a function to call. if X-TDE-Init is "bell", for example, the function "init_bell" is called in the library indicated by X-TDE-Library. |
X-TDE-Test-Module | If the module has to perform some action at system startup, use this entry to build the name of a function to call. if X-TDE-Init is "bell", for example, the function "init_bell" is called in the library indicated by X-TDE-Library. |
NoDisplay | If this is set to true the module will not show up in kcontrol or when viewed with tdecmshell. This is usable when you need to do something at startup (X-TDE-Init etc.) but don't want the module to show up in kcontrol, e.g. the module has no GUI.
|
Name | This is 'labels' for the modules and fill the nodes in the three view. Please see the module guidelines on how to pick a good Name. |
Comment | This directive shows up in the main area in KControl if you select a top node in the three view. See the same section as for Name in the module guidelines for how to pick a good phrase. |
Categories | This describes where the module should be put in KControl's navigation. It should look like "Categories=QT;TDE;X;" where X is the category. A list of available categories, as well as which one to choose is found in the module guidelines. |
Icon | Specifies the icon for the module. |
Exec/Type | These two should say Exec=kcmshell modulename and Type=Application . Used for internal purposes
|
Keywords | A semi colon separated list containing words/phrases search functionality should trigger on. |
To summarize, a valid .desktop file must contain these entries:
- Name
- Icon
- Type=Application
- Exec=tdecmshell modulename
- Categories=QT;KDE;X; (replace X with your category)
- Keywords
- X-TDE-Library
- X-TDE-ParentApp
- Comment
And these are optional:
- X-TDE-Init
- X-TDE-Test-Module
- NoDisplay
- X-TDE-Root-Only
- X-TDE-Factory-Name
- DocPath
Any other directives(except the translators) can safely be removed, since they most likely are abundant or are leftovers from old KDE versions. For example, X-ModuleType was relevant for KDE 2.0 but not in any new versions.
What else do I need?
There are a number of additional things for convenience.
tdecmshell
Consider you want to run a module standalone. Call tdecmshell [module]
. For example, to get the font and the desktop color settings, use:
$ tdecmshell fonts colors
KCMultiDialog
Sometimes, you may want to reuse your TDECModule inside an application. There are two ways to accomplish this:
- Use KCMultiDialog (in tdelibs/tdeutils)
This is a simple dialog that can show an abitrary number of modules in a normal KDialogBase. The advantage is that you can control the behaviour and the results much easier that with a separate process. And as your module is a simple library, you can just link to it anyway.
- Call
tdecmshell [modules...]
.
KCModuleContainer
The class KCModuleContainer allows great flexibility with handling modules. The API docs explain it usage the best.
Debugging your module
You can attach gdb, valgrind or whatever to tdecmshell [yourmodule]
to track down leaks or crashes. If you need to trace it down inside kcontrol, make sure you pass it --nofork
on startup. You really want to use tdecmshell for debugging as long as your debugging does not involve debugging bad interaction with the kcontrol framework itself.
Copyright notice
Imported from KDE Developer Documentation SVN.
Copyright (C) 2003 Daniel Molkentin <molketin@kde.org> Copyright (C) 2004 Frans Englich <frans.englich@telia.com> Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".