An attempt at solving KControl's usability problems..

Frans Englich frans.englich at telia.com
Sun Jan 25 17:27:25 GMT 2004


On kde-usability I laid a proposal a couple of weeks ago for solving 
KControl's usability and maintenance problems. AFAICT it still needs to be 
shot down(explaining why it's a bad idea), and if that's not the case - 
embrasement. Basically, it needs a thorough review and feedback, especially 
since it's pretty invasive, affecting large parts of KDE.
The best way to get a grip on the proposal is to read this thread:
http://lists.kde.org/?l=kde-usability&m=107352838517059&w=2 
but instead of the files attached to that thread read the updated file 
attached to this mail. (That is KCM_CONVENTIONS)

Attached KCM_HOWTO is an update of kdebase/kcontrol/HOWTO, needs a review and 
some opinions.
In contrast to what the thread says, KCM_HOWTO and KCM_CONVENTIONS is probably 
best located on dev.kde.org.

Attached TODO could also be of interest - gives a indicator of what 
suggestions is circulating. (opinions very welcome)


Cheers,

			Frans

-------------- next part --------------
Copyright (C)  2004  Frans Englich <frans.englich at 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".

PLEASE NOTE: This is a draft so don't jump in your chair if something 
is unreasonable. But please tell the authors(kde-usability) if they are
unreasonable. Otherwise you will really have to jump in your chair.


This file describes the organisational layout and file structure for KDE's 
KCMs(KControl Modules) as well as design recommendations and conventions 
used.
Writing KCMs is covered in KCM_HOWTO.

These guidelines assumes a basic understanding of the technical side of 
Kcontrol and KCMs. This is covered in the KCM_HOWTO, which really should be read before this 
document. In case it does not cover your wondering, drop a line on kde-usability.

KControl, but most notable all the KCMs have had major problems, the 
usability aspect have been critical, large parts of the code have been 
half baked and poorly maintained as well as the development of the 
approximately 70 KCMs have been framented with no coordination.
These guidelines exists in the hope to correct these problems. It establishes 
guidelines and polices ranging from usability, such as naming and layout, to 
how to arange code and name files, in order to make life easier for 
the developers as well as promoting usability and code quality.
In order for this to succeed, these guidelines must be followed. But, it should 
not be foolishd followed, for example the naming recommendations is just 
recommendations, in case the name must be a little longer than average in 
order to be informative that is of course OK.
If there's an interest to not adhere to these guidelines the right way is not 
to just ignore the guidelines and go hacking away in an own style - KDE is a 
community project. As soon there is a case not covered in this guide, or the 
guidelines seemes to simply be wrong the issue should be raised on the 
mailinglist kde-usability so your idea can be peer reviewed and discussed, 
and these guidelines changed accordingly. As soon as 
you look at other KCMs in order to see how they behave or have solved 
a problem it probably means these guidelines have not covered that area and 
must be completed - raise the issue on kde-usability.
Suggestions and most of all questions, regarding these guidelines is very much 
appreciated, don't hesitate to to drop a line on kde-usability. Of course, don't 
edit this document, except for obvious typos without having reached consensus and 
agreement with other KDE developers.

If you need to get in contact with the maintainer for a particular KCM, that 
information can be obtained from PACKAGE/KCMs/README, where PACKAGE is the 
relevant KDE module, for example kdemultimedia. There you will also find 
information specific for that module's KCMs, such as design policies specific for 
that module.

A good KCM to study which follows these guidelines correctly can be found in
TODO :P


--- Directory Layout and Filename Conventions ---
In each KDE package which contains KCMs(for example kdenetwork) 
a top directory named "KCMs" exists which contains everything related to 
the KCM's for that package, regardless of what application or 
functionality the KCM represents.
Each "KCMs" directory contains a README file where the maintainers for the 
KCMs is listed as well as other information specific information for 
that package's KCMs.  For KCMs and their associated files a 
set of filename conventions exists:

* All the KCM's files resides in a sub directory of "KCMs". The 
name of that directory is the same as X-KDE-Library for that module.
Ie, if a KCM's desktop file contains "X-KDE-Library=kmix" all its 
files resides in "KCMs/kmix/".

* The name of the desktop file is the KCM's library name prefixed 
with "kcm_". All lower case. For example "kcm_kmix.desktop". 

* For compability reasons the old .desktop file(if any) must be kept 
as well as being installed. It goes fine to have two. In the next major 
KDE release the compability .desktop file will be removed. <!-- KDE4 -->

* If the KCM has an specific icon its basename should be 
the same as the library name prefixed with "kcm_". All lowercase.

* The main source file(containing the KCModule subclass) and its header 
must be named "main.cpp" and "main.h", respectively.

* The name of the .kcfg file shall be the name of the library name.
All lowercase. For example, "kmix.kcfg".

* The name of the .kcfgc file must be the name of the library name.
All lowercase. For example, "kmix.kcfgc".

* The name of the .ui file for the main widget(the KCM) shall be named
"main_widget.ui".

* All C++ files should have the extension ".cpp" and ".h", respectively.

* If the main widget in main_widget.ui must be sub 
classed, it should reside in "main_widget_impl.h" and 
"main_widget_impl.cpp", respectively.

* The name of the KCModule subclass should be the library name prepended 
with "KCM" and with the usual capitalization of key letters. For example, 
if the library name is "useraccount" the classname would be "KCMUserAccount".




--- Broad Design Hints ---
Keep the following in mind when adding or modifying existing KCMs:

* The content of an KCM may not be, from the user's point of view, 
application specific. KControl's purpose is to in a central place 
provide configuration for functionality which is global for KDE. 
Keeping application specific configuration in KControl simply makes 
it too big and bloated(people have already tried this). Technically, 
the functionality the KCM represents can be an application or isolated 
and separated but that is irrelevant - it is about how the users percepts 
and sees it, not how it is implemented.

* We don't want configuration. In a perfect world the default settings 
fits everyone and the hardware Just Works. This is not the case so 
we have KControl. 
But that is no reason to have unnecessary options and 
bloat in a KCM. For every configuration option you could ask: Is this 
option really, really necessary? Does a significant part of KDE's users need 
it? Was it implemented because it was a "cool" feature and fun to do? Does 
other KCMs have similar options which could be combined into a global 
one? Could the implementation be changed so the user does not have to take 
the (configuration) decision? 
The one with the simplest, and smallest amount of config options wins. Assuming 
functionality is sustained as well as it means usability is actually improved, 
of course.

* Don't make a KCM available in several places. For example, don't have an 
entry in one category while having the same KCM available as a tab in another
KCM. A bogus reason to doing this is it allows the user to access the 
functionality in different ways(a well established UI design principle). This is 
a bogus reason because from the user's perspective it 
is not percepted as different ways of accessing one unit of functionality - it 
appears as a doubled amount of options. In short, to the user the functionality 
in the two(or more..) places is not percepted as identical but different and thus confusing.
If you feel a need of doing this, it is an alarm bell for something is wrong. Perhaps 
you need to split up the functionality in different KCMs? Is the Name wrong? Perhaps even 
the top level categories are wrong. In either case, discussing it on kde-usability 
is a good idea.

* 
* Navigating with KControl among the KCM's is hard because it is monotone, all the 
KCM's looks roughly the same and involves the same widgets - it is hard distinguishing 
the different KCM's from each other. One way to counteract this is to personalize them 
and give them an individual touch so they easier puts a print in the user's memory. 
This can be accomplished by adding images, with relevant, easily associated motives. 
Images also gives an opportunity to affect the user emotionally. For example, 
if the the content is highly technical the image can be used to bring an feeling 
of confidence and assurance to the user. It could also lead in the opposite direction - 
steal focus and be distracting(especially if the image affects emotionally). The 
design and use of images needs deep consideration, in either case.


--- A Valid KCM ---
In order for an KCM to be good and valid it must conform to:

1) KDE Licensing Policy. Basically, a OSI approved license 
as well as correct license and copyright headers. For details see:
http://developer.kde.org/policies/licensepolicy.html

2) KDE User Interface Guidelines. Please see:
http://developer.kde.org/documentation/standards/kde/style/basics/index.html

3) The conventions and recommendations in this file.

4) A valid .desktop file. If you are not 110% sure of what you're doing, 
validate with freedesktop's desktop-file-utils:
http://www.freedesktop.org/Software/desktop-file-utils

If the KCM does not conform, it is considered a broken KCM.


--- Words and Phrases ---
When picking or changing a name(that is the Name directive in TODO rephrase
the .desktop file) for a KCM it is good idea keeping the 
following issues in mind in order to promote usability and 
consistency between the modules:
When picking phrases for the Name and Categories .desktop directives as well 
as other texts for the KCM, the following issues must be kept in mind:

* Try to keep the phrase short. Shorter phrases is easier and
faster to interpret and give better options for designing the layout. 
From a esthetically perspective it also looks cleaner and simpler.

* Avoid complex phrases involving backslashes("/)" and paranteses
for the same reasons as above. It also makes translations more 
accurate.

* Use "Monitor" instead of "Display". The main reason is simply 
consistency but Monitor is preferred because it is not a verb 
(easier to translate and non ambiguous) as well as it more directly refers to 
physical Monitor - the word Display has more denotations. A negative 
side is that people tends to associate with "old" CRT monitors, 
while there now a days exists exists all kind of fancy stuff 
like TFT screens. For some users this does not cause a problem. I for 
example, are well aware of that those nifty things only exists in my 
imagination.

* Generally speaking, use "Hardware" instead of "Peripherals". Hardware 
is less technical and not as abstract as Peripherals. Everything 
classified as Peripherals also classifies as Hardware, and thus the 
substitution can't be misinforming, although possible vague(but that can also be 
a good thing). There is strictly speaking cases where Peripherals 
is more semantically correct but the usability aspect of the choice 
must be deeply considered. 

* Avoid including words like "Management" and "Configuration" etc. 
since it is abundant - KControl is all about that, which the user 
already is aware of. Furthermore, such terms does not inform the 
user about what your module contains, except that it is for 
configuration or management(and that is already clear since it is 
in KControl).
Another reason is that it makes it more cumbersome for the user to 
find what he/she wants. For example, if the user looks for monitor 
settings the word "monitor" is looked for, not "settings". Thus, 
the phrase "Monitor" can look incomplete and half baked compared to 
"monitor Settings" but actually fullfills its purpose better than the 
latter.
Another example, pick "Sony Vaio Laptop" in front of "Sony Vaio Laptop 
Hardware Configuration" since the user already knows it's about
Configuration and Hardware.

* KControl as the rest of KDE targets a wide audience where a 
majority(to say the least) of the users does not have technical 
expertise. In order to have a compelling interface it is important 
to avoid technical and "scary" terms. The goal is to reach the user and 
communicate successfully - that is not succeeded by using words 
the user does not understand.

--- Selecting a Category ---
TODO Document the different categories and provide information about when to 
choose category A in front of B, etc.

TODO Some guideline specifying how to classify, ie. should the energy/power settings 
reside under a "Power Control" toplevel entry or under "Hardware/Monitor"?

	X-KDE-settings-looknfeel	Appearance & Themes
	X-KDE-settings-desktop		Desktop
	X-KDE-settings-network		Internet & Network
	X-KDE-settings-webbrowsing	Web Browser
	(submenu of Internet & Network)
	X-KDE-settings-components	KDE Components
	X-KDE-settings-peripherals	Peripherals
	X-KDE-settings-power		Power Control
	X-KDE-settings-accessibility	Regional & Accessibility
	X-KDE-settings-security		Security & Privacy
	X-KDE-settings-sound		Sound & Multimedia
	X-KDE-settings-system		System & Administration

As of rule of thumb, it is a good idea ensuring each category stays around 5 
entries(KCMs) each. It is also preferred to have roughly the same amount in each 
category. This makes it easier to use different KControl layouts as well as each 
"portion" is not too big to interpret and makes it easier to remember. This should 
be taken lightly, but can be good to keep in mind when case otherwise is "tie". As 
a side note, this has nothing to do with Millers's 7+-2 theory.



--- Technical Recommendations ---
When building a new KCM or improving an old one, a set of
KDE technologies is preferred in front of others:

* Use .ui files instead of handcrafted
Graphical user interfaces designed with QT Designer is preferred
instead of handwritten ones because 1) It allows people without 
C++ experience to modify GUIs; 2) It is safer since it is not 
manually written code; 3) It allows more obtrusive changes to be 
done in code freezes; and 4) Faster development.

* KConfigXT framework instead of handcrafted configuration code
The rationalis is similar to the above with notable addition: It 
saves disk space on installed clients.



--- Breif History ---
This structuring of KCMs and the policies were started around the 
release of KDE 3.1 since the KControl/KCM situation had been unbearable 
since KDE 3.0. Some fresh thinking was needed.


-------------- next part --------------

Copyright (C)  2003  Daniel Molkentin <molketin at kde.org>

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".


The KDE Control Center
======================

Author: Daniel Molkentin <molkentin at kde.org>
	The author of this document, as well as the person 
	you should redirect your questions to, if this document 
	does not answer them.

This file describes how to write KControl Modules(KCMs). 
Please also read KCM_CONVENTIONS before modifying or writing 
KCMs since it contains guidelines and design rules which must be
followed.

The KDE Control Center is a central application that allows a 
user to:

a) change user specific settings
b) change KDE specific system settings
c) change system settings

The functionality is provided by a great number of KControl 
Modules that are embedded into a framework application 
called "kcontrol".


How to write a KControl Module
------------------------------

The mechanism to implement kcontrol modules changed quite a bit since 
KDE 2.0. In KDE 1.x the modules have been implemented as separate
processes that were swallowed into the control center. This had several
advantages, as well as disadvantages:

+ modules could run standalone
+ broken modules (segfaulting) left the framework untouched
- focus handling was hard to achive
- layout management was a pain
- communication between modules and framework was inefficient

To overcome the problems, modules from KDE 2.0 on are implemented as 
simple shared libraries that are loaded, at runtime, into the process
of the frame application. This solves all of the disadvantages.
To allow modules to run "standalone", there is a wrapper application
"kcmshell". What is left is the problem of segfaulting modules; the
solution is simple: don't let your modules segfault! :-)


Now to the practical side of things: Modules have to inherit from the
class KCModule, defined in kcmodule.h, which is part of kdeui.
This class defines some important functions that are used in the
communication between framework and 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 control center 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 a signal 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 control center uses
this signal to keep track about unsaved changes in certain modules.


How to make a module available?
-------------------------------

Ok, now that you have implemented your class with the module, you
must make sure it can be accessed from the control center. 

To achieve this, the preferred way since KDE 3.0 is to simply use 
KGenericFactory. Don't forget to #include <kgenericfactory.h>.

typedef KGenericFactory<MyKCModule, QWidget> KDEDFactory;
K_EXPORT_COMPONENT_FACTORY( kcm_xyz, KDEDFactory( "kcmxyz" ) );

If you get errors, make sure that the constructor of your derived class
equals the one of the KCModule baseclass (yes, the QStringList 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"
{
  KCModule *create_xyz(QWidget *parent, const char *name)
  {
    return new XYZ(parent, name); // XYZ inherits from KCModule
  };
}

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 $KDEDIR/lib/kde3. (Ok, beat me for the KDEDIR, 
but you all know what I mean, don't you? :)

Use "kde_module_LTLIBRARIES = kcm_xyz.la" for that in your Makefile.am.
Don't call it libkcm_xyz as that is deprecated since KDE 3.0.
Further issues regarding Makefile.am writing is hopefully  covered in the
Makefile.am HOWTO:
http://developer.kde.org/documentation/other/makefile_am_howto.html



Initialize things on startup
----------------------------

If your module needs to initialize things on startup, you must have a 
construct like:

extern "C"
{
  KCModule *init_xyz(QWidget *parent, const char *name)
  {
    // to startup stuff here
  };
}

Don't forget to add X-KDE-Init to your desktop file! (see next chapter)


The .desktop entry
------------------

To make the control center find the module, it needs a .desktop
entry. This has to be placed under:

$KDEDIR/applnk/Settings/...

so put it in kdebase/applnk/Settings... to have it installed.

It could be a good idea to know the basics of the .desktop standard. 
It is very easy to read and quite short:
http://www.freedesktop.org/Standards/desktop-entry-spec

A KCM's .desktop file supports the following .desktop directives:

X-KDE-Library

	This is the name of the library, without the kcm_ prefix.
	So in the example, the library name would be "xyz".

X-KDE-FactoryName

	This entry can be used to set the name of the factory
  	function in the library. Usually, this is the same as
	the Library, but if you want to have more than
	one module in one library, you need this entry.
	To make it clear, if you have several KCMs in one library
	you will need a .desktop file for each KCM.

	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 control center would then call the "create_kermit" and
	"create_quak" functions respectively.

X-KDE-RootOnly

	If this is set to "true", the module must be executed
	with root permissions. The control center 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 kdesu and QXEmbed.
   
X-KDE-ParentApp
	
	This one should be set to "kcontrol" and tells what KSycocaGroup 
	the module will belong to. Eg., there is a sycoca group called kcontrol 
	which all KCM's(since they have a "X-KDE-ParentApp=kcontrol") belongs 
	to which KControl then can look up in order to list all modules.

X-KDE-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-KDE-Init is "bell", for example, the function
	"init_bell" is called in the library indicated by
	X-KDE-Library.

NoDisplay

	If this is set to true the module will not show up in
	kcontrol or when viewed with kcmshell. This is usable when
	you need to do something at startup(X-KDE-Init etc.) but 
	don't want the module to show up in kcontrol, eg. the module
	has no GUI.

Name

	This is 'labels' for the KCMs and fill the nodes in the three 
	view. Please see KCM_CONVENTIONS 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 KCM_CONVENTIONS for how to pick a good phrase.

Categories

	This describes where the KCM should be put in KControl's 
	navigation. It should look like "Categories=QT;KDE;X;" where 
	X is the category. A list of available categories, as well as 
	which one to choose is found in KCM_CONVENTIONS.


Icon
	Specifies the icon for the module.

Exec/Type

	These two should say "Exec=kcmshell dir/file" and 
	"Type=Application". If you run the KCM from its .desktop 
	file, as opposed to KControl these two directives tells 
	KDE what to do.

Keywords

	A semi colon separated list containing words/phrases 
	KControl's search tab should trigger on.

To summarize, a valid .desktop file must contain these entries:
* Name
* Comment
* Icon
* Exec=kcmshell dir/file // Replace dir/file
* Type=Application
* Categories=QT;KDE;X; // Replace X
* Keywords
* X-KDE-Library
* X-KDE-ParentApp=kcontrol

The following directives are optional:
* X-KDE-Init
* NoDisplay
* X-KDE-Root-Only
* X-KDE-Factory-Name
* DocPath TODO

Any other directives(except the translator's :) can safely be 
removed, since they most ikely are abundant or are left over's 
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. 

- kcmshell

Consider you want to run a module standalone, without the control
center. You can no longer call the module, as it is a library
now. Instead, call "kcmshell module". For example, to get the
font and the desktop color settings, use

  kcmshell fonts colors

If kcmshell for some reason couldn't load on of the modules, it will 
silently be ignored. <!--TODO: Do we really want that behavior? :)) -->

- multiple instances of kcontrol

With the new control center, it is no longer possible to have multiple
instances in the control center.

- KCDialog

Sometimes, you may want to reuse your control center modules
inside an application. There are two ways to accomplish this:

a) call "kcmshell modules"

to run the module as a separate program.

b) use "KCMultiDialog" (in kdelibs/kutils)

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. 

Debugging your module
---------------------

You can attach gdb, valgrind or whatever to kcmshell <yourmodule> to track 
down leaks or crashes. If you need to trace it down inside kcontrol, make
sure you pass --nofork to kontrol on startup. Anyway, you really want to use 
kcmshell for debugging as long as your debugging does not involve debugging bad
interaction with the kcontrol framework itself.




-------------- next part --------------
A non-text attachment was scrubbed...
Name: TODO
Type: text/x-c++src
Size: 6745 bytes
Desc: not available
URL: <http://mail.kde.org/pipermail/kde-core-devel/attachments/20040125/d1737016/attachment.c>


More information about the kde-core-devel mailing list