<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="http://techbase.kde.org/skins/common/feed.css?0.2"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
		<id>http://techbase.kde.org/api.php?action=feedcontributions&amp;user=Rememberme&amp;feedformat=atom</id>
		<title>KDE TechBase - User contributions [en]</title>
		<link rel="self" type="application/atom+xml" href="http://techbase.kde.org/api.php?action=feedcontributions&amp;user=Rememberme&amp;feedformat=atom"/>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Special:Contributions/Rememberme"/>
		<updated>2013-05-26T06:28:20Z</updated>
		<subtitle>User contributions</subtitle>
		<generator>MediaWiki 1.20.2</generator>

	<entry>
		<id>http://techbase.kde.org/Projects/Plasma/SynoxiDesktopInteractionPrinciples</id>
		<title>Projects/Plasma/SynoxiDesktopInteractionPrinciples</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Projects/Plasma/SynoxiDesktopInteractionPrinciples"/>
				<updated>2009-02-23T19:16:35Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Synoxi Desktop Interaction Principles ==&lt;br /&gt;
&lt;br /&gt;
This is a preliminary Version of my Dektop Interaction Principles. These are aimed to provide a high usability and consistency. They're also supposed to reduce the stress of looking for ones files. This is archieved thruogh its non-hierarchic file visualization management. I have already made some mockups for the panel.&lt;br /&gt;
&lt;br /&gt;
=== The Principles ===&lt;br /&gt;
&lt;br /&gt;
1.What you see is what you get: Icons don't represent the file, they are the file&lt;br /&gt;
&lt;br /&gt;
2.No hierarchic Folder Arrangement: All Views a user gets are virtual folders and represent all files who match a certain criteria (e.g. all Pictures / all Files edited last week / all Files sent to me by Peter) This includes semantic information. A user doesn't want to care about WHERE to save his files, he cares about the content. So a file save dialogue would ask for additional metadata rather than a place to save.&lt;br /&gt;
&lt;br /&gt;
3.There are 3 types of objects for the user. These types will be called states further on: “Empty Objects” (create new file of a certain type) represented by an icon, “Closed Objects” (closed files)  represented by a preview and “Open Objects” (open windows) represented by the window itself. A minimized Window is treated as a closed object. It is just placed in a special containment (see point 4 for visualization details of objects). &lt;br /&gt;
&lt;br /&gt;
4.“Containers” are virtual views that collect various information about objects and are able to filter them in awareness of these. They are the general way of representing objects. They are aware of the state of an object (empty or new / closed / open). Containers act like a folder view that looks for data that matches filter criteria. It has to be very easy to customize them → reasonable set of filters visible (depending on which filters are already in use). To add or remove a criteria you can drag and drop from a list. This idea of filters is shared among all file views.&lt;br /&gt;
&lt;br /&gt;
5.A user can interact with an object by holding the mouse or finger over the object for a certain amount of time (1-2 s) or by right clicking. Then, a menu appears. It shows contextual actions (delete / duplicate / rate / tag / send to …), semantic information (which can depend on the filters used in the container) and gathers all notifications for an object. Notifications are treated similarly as tags and can have actions associated with them, as have tags.&lt;br /&gt;
An object can call for attention by sending a visual and/or audible signal – it can also open parts of its menu (the notification area) by itself, if there is urgent information. By hovering this partial menu, the full menu is shown.&lt;br /&gt;
&lt;br /&gt;
6.No systemtray exclusive notifications. All objects (which to the user are pieces of information with actions associated to them) are treated the same (from a visualization point of view). The information belongs to the object associated with it. &lt;br /&gt;
Application Notifications are stuck to the objects representation, be it an open or closed object.&lt;br /&gt;
&lt;br /&gt;
7.Containers are no Window switchers. There is the window switcher applet or composite animation for that. Containers are used to look at and change the state of objects. So they can open a closed object or create an empty one. There can still be a window switcher applet.&lt;br /&gt;
&lt;br /&gt;
8.You don't start an application, you start a task. If you have  several applications, you can choose between them. The user doesn't care about applications, they just want it to work. The user wants to write a new text document as opposed to opening a certain application that can edit text documents.&lt;br /&gt;
So applications are started by clicking on a certain task which is represented by an icon. By staying on the icon for a while (1-2 seconds) an action menu is shown (see point 4)&lt;br /&gt;
Every action a user does is a task. Tasks can be dragged into the application launcher bar.&lt;br /&gt;
9.When a new notification arrives from a process, of whom there is no visible object, a new task appears in the task bar.(!English relative clause!?) It has a pop-up that shows the message. By hovering, a full context menu appears. It shows more information and allows for more actions.&lt;br /&gt;
&lt;br /&gt;
10.New Tasks (application sessions) are treated the same way as closed documents or windows (open documents) are, because to the user, they basically represent empty documents or empty sessions of a chat application or an new browser page.&lt;br /&gt;
&lt;br /&gt;
11.Closed Objects, Windows and new Tasks have to be distinguishable. It is important to have useful and intuitive filters.&lt;br /&gt;
&lt;br /&gt;
12.An open file has to have the same contextual menu as a closed one. The problem here are notifications: In this file-centric system a notification would have to be attached to the application itself. This has to be either aggregated in a menu or attached to the bottom / top of the window. The former seems to be more viable.&lt;br /&gt;
&lt;br /&gt;
13.Closing a window NEVER is a destructive task. It has nothing to do with deleting a file. A new file is saved automatically. By closing an application that has unsaved changes, the changes are saved automatically. Change History has to be preserved. Deleting a file is done by using the objects context menu.&lt;br /&gt;
&lt;br /&gt;
=== Mockups ===&lt;br /&gt;
&lt;br /&gt;
==== Panel ====&lt;br /&gt;
&lt;br /&gt;
Here some Mockups of a possible panel:&lt;br /&gt;
&lt;br /&gt;
[[Image:SinoxyMockup1.png]]&lt;br /&gt;
&lt;br /&gt;
The user is hovering over the &amp;quot;new text document&amp;quot; icon. Not much to see here.&lt;br /&gt;
&lt;br /&gt;
===== Notifications =====&lt;br /&gt;
&lt;br /&gt;
[[Image:SinoxyMockup2.png]]&lt;br /&gt;
&lt;br /&gt;
This is slightly more intresting: Here, a task is calling for attention. Two new mails have arrived and the user is being informed. Hovering the icon or the notification will cause this:&lt;br /&gt;
&lt;br /&gt;
[[Image:SinoxyMockup3.png]]&lt;br /&gt;
&lt;br /&gt;
Here the user is presented with options. 1) Open the Mail application 2) ignore the notification (the dialog will disappear).&lt;br /&gt;
&lt;br /&gt;
This behaviour for notifications also applies for tasks who are not in the panel. All notifications for new or closed tasks appear this way.&lt;br /&gt;
&lt;br /&gt;
Minimized windows can also call for attention with a dialog and an associated action menu.&lt;br /&gt;
&lt;br /&gt;
===== Manage Lots of Tasks =====&lt;br /&gt;
&lt;br /&gt;
A problem with this kind of application starting behaviour is how to handle big masses of applications (or in sinoxy &amp;quot;tasks&amp;quot;). In Sinoxy this problem is solved by being able to invoke an extender who displays all tasks available on the system (Partially this is also solved by grouping applications, who have the same purpose, under one &amp;quot;task&amp;quot;). To invoke this extender, you click on the KDE-icon. Herefrom you can drag tasks to the panel and also start them directly. &lt;br /&gt;
&lt;br /&gt;
[[Image:SinoxyMockup4.png]]&lt;br /&gt;
&lt;br /&gt;
Probably, a search mechanism would be very convenient.&lt;br /&gt;
&lt;br /&gt;
=== What this would mean for plasma ===&lt;br /&gt;
&lt;br /&gt;
Some of these changes can probably already be archieved by creating a new plasmoid.&lt;br /&gt;
&lt;br /&gt;
But still some things would require a change in the theming system. What I showed in these mockups cannot be reproduced at the moment.&lt;br /&gt;
&lt;br /&gt;
The notification system would probably require some work too. I can see that there is some work going here, probably this improves the situation.&lt;br /&gt;
&lt;br /&gt;
Needed are a new minimized task manager applet and a new task starting applet (I haven't talked about that yet). Folder view needs improvement.&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/User:Rememberme</id>
		<title>User:Rememberme</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/User:Rememberme"/>
				<updated>2009-02-23T19:01:55Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I am currently working on the Synoxy Desktop Interaction Principles.&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Projects/Plasma/SynoxiDesktopInteractionPrinciples</id>
		<title>Projects/Plasma/SynoxiDesktopInteractionPrinciples</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Projects/Plasma/SynoxiDesktopInteractionPrinciples"/>
				<updated>2009-02-23T18:43:13Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Synoxi Desktop Interaction Principles ==&lt;br /&gt;
&lt;br /&gt;
This is a preliminary Version of my Dektop Interaction Principles. These are aimed to provide a high usability and consistency. They're also supposed to reduce the stress of looking for ones files. This is archieved thruogh its non-hierarchic file visualization management.&lt;br /&gt;
&lt;br /&gt;
=== The Principles ===&lt;br /&gt;
&lt;br /&gt;
1.What you see is what you get: Icons don't represent the file, they are the file&lt;br /&gt;
&lt;br /&gt;
2.No hierarchic Folder Arrangement: All Views a user gets are virtual folders and represent all files who match a certain criteria (e.g. all Pictures / all Files edited last week / all Files sent to me by Peter) This includes semantic information. A user doesn't want to care about WHERE to save his files, he cares about the content. So a file save dialogue would ask for additional metadata rather than a place to save.&lt;br /&gt;
&lt;br /&gt;
3.There are 3 types of objects for the user. These types will be called states further on: “Empty Objects” (create new file of a certain type) represented by an icon, “Closed Objects” (closed files)  represented by a preview and “Open Objects” (open windows) represented by the window itself. A minimized Window is treated as a closed object. It is just placed in a special containment (see point 4 for visualization details of objects). &lt;br /&gt;
&lt;br /&gt;
4.“Containers” are virtual views that collect various information about objects and are able to filter them in awareness of these. They are the general way of representing objects. They are aware of the state of an object (empty or new / closed / open). Containers act like a folder view that looks for data that matches filter criteria. It has to be very easy to customize them → reasonable set of filters visible (depending on which filters are already in use). To add or remove a criteria you can drag and drop from a list. This idea of filters is shared among all file views.&lt;br /&gt;
&lt;br /&gt;
5.A user can interact with an object by holding the mouse or finger over the object for a certain amount of time (1-2 s) or by right clicking. Then, a menu appears. It shows contextual actions (delete / duplicate / rate / tag / send to …), semantic information (which can depend on the filters used in the container) and gathers all notifications for an object. Notifications are treated similarly as tags and can have actions associated with them, as have tags.&lt;br /&gt;
An object can call for attention by sending a visual and/or audible signal – it can also open parts of its menu (the notification area) by itself, if there is urgent information. By hovering this partial menu, the full menu is shown.&lt;br /&gt;
&lt;br /&gt;
6.No systemtray exclusive notifications. All objects (which to the user are pieces of information with actions associated to them) are treated the same (from a visualization point of view). The information belongs to the object associated with it. &lt;br /&gt;
Application Notifications are stuck to the objects representation, be it an open or closed object.&lt;br /&gt;
&lt;br /&gt;
7.Containers are no explicit Window switchers. There is the window switcher applet or composite animation for that. Containers are used to look at and change the state of objects. So they can open a closed object or create an empty one. There can still be a window switcher applet.&lt;br /&gt;
&lt;br /&gt;
8.You don't start an application, you start a task. If you have  several applications, you can choose between them. The user doesn't care about applications, they just want it to work. The user wants to write a new text document as opposed to opening a certain application that can edit text documents.&lt;br /&gt;
So applications are started by clicking on a certain task which is represented by an icon. By staying on the icon for a while (1-2 seconds) an action menu is shown (see point 4)&lt;br /&gt;
Every action a user does is a task. Tasks can be dragged into the application launcher bar.&lt;br /&gt;
9.When a new notification arrives from a process, of whom there is no visible object, a new task appears in the task bar.(!English relative clause!?) It has a pop-up that shows the message. By hovering, a full context menu appears. It shows more information and allows for more actions.&lt;br /&gt;
&lt;br /&gt;
10.New Tasks (application sessions) are treated the same way as closed documents or windows (open documents) are, because to the user, they basically represent empty documents or empty sessions of a chat application or an new browser page.&lt;br /&gt;
&lt;br /&gt;
11.Closed Objects, Windows and new Tasks have to be distinguishable. It is important to have useful and intuitive filters.&lt;br /&gt;
&lt;br /&gt;
12.An open file has to have the same contextual menu as a closed one. The problem here are notifications: In this file-centric system a notification would have to be attached to the application itself. This has to be either aggregated in a menu or attached to the bottom / top of the window. The former seems to be more viable.&lt;br /&gt;
&lt;br /&gt;
13.Closing a window NEVER is a destructive task. It has nothing to do with deleting a file. A new file is saved automatically. By closing an application that has unsaved changes, the changes are saved automatically. Change History has to be preserved. Deleting a file is done by using the objects context menu.&lt;br /&gt;
&lt;br /&gt;
=== Mockups ===&lt;br /&gt;
&lt;br /&gt;
==== Panel ====&lt;br /&gt;
&lt;br /&gt;
Here some Mockups of a possible panel:&lt;br /&gt;
&lt;br /&gt;
[[Image:SinoxyMockup1.png]]&lt;br /&gt;
&lt;br /&gt;
The user is hovering over the &amp;quot;new text document&amp;quot; icon. Not much to see here.&lt;br /&gt;
&lt;br /&gt;
===== Notifications =====&lt;br /&gt;
&lt;br /&gt;
[[Image:SinoxyMockup2.png]]&lt;br /&gt;
&lt;br /&gt;
This is slightly more intresting: Here, a task is calling for attention. Two new mails have arrived and the user is being informed. Hovering the icon or the notification will cause this:&lt;br /&gt;
&lt;br /&gt;
[[Image:SinoxyMockup3.png]]&lt;br /&gt;
&lt;br /&gt;
Here the user is presented with options. 1) Open the Mail application 2) ignore the notification (the dialog will disappear).&lt;br /&gt;
&lt;br /&gt;
This behaviour for notifications also applies for tasks who are not in the panel. All notifications for new or closed tasks appear this way.&lt;br /&gt;
&lt;br /&gt;
Minimized windows can also call for attention with a dialog and an associated action menu.&lt;br /&gt;
&lt;br /&gt;
===== Manage Lots of Tasks =====&lt;br /&gt;
&lt;br /&gt;
A problem with this kind of application starting behaviour is how to handle big masses of applications (or in sinoxy &amp;quot;tasks&amp;quot;). In Sinoxy this problem is solved by being able to invoke a dialog who displays all tasks available on the system (Partially this is also solved by grouping applications, who have the same purpose, under one &amp;quot;task&amp;quot;). To invoke this dialog, you click on the KDE-icon. Herefrom you can drag tasks to the panel and also start them directly. &lt;br /&gt;
&lt;br /&gt;
[[Image:SinoxyMockup4.png]]&lt;br /&gt;
&lt;br /&gt;
Probably, a search mechanism would be very convenient.&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Projects/Plasma/SynoxiDesktopInteractionPrinciples</id>
		<title>Projects/Plasma/SynoxiDesktopInteractionPrinciples</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Projects/Plasma/SynoxiDesktopInteractionPrinciples"/>
				<updated>2009-02-23T18:31:16Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: /* Mockups */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Synoxi Desktop Interaction Principles ==&lt;br /&gt;
&lt;br /&gt;
This is a preliminary Version of my Dektop Interaction Principles. These are aimed to provide a high usability and consistency. They're also supposed to reduce the stress of looking for ones files. This is archieved thruogh its non-hierarchic file visualization management.&lt;br /&gt;
&lt;br /&gt;
=== The Principles ===&lt;br /&gt;
&lt;br /&gt;
1.What you see is what you get: Icons don't represent the file, they are the file&lt;br /&gt;
&lt;br /&gt;
2.No hierarchic Folder Arrangement: All Views a user gets are virtual folders and represent all files who match a certain criteria (e.g. all Pictures / all Files edited last week / all Files sent to me by Peter) This includes semantic information. A user doesn't want to care about WHERE to save his files, he cares about the content. So a file save dialogue would ask for additional metadata rather than a place to save.&lt;br /&gt;
&lt;br /&gt;
3.There are 3 types of objects for the user. These types will be called states further on: “Empty Objects” (create new file of a certain type) represented by an icon, “Closed Objects” (closed files)  represented by a preview and “Open Objects” (open windows) represented by the window itself. A minimized Window is treated as a closed object. It is just placed in a special containment (see point 4 for visualization details of objects). &lt;br /&gt;
&lt;br /&gt;
4.“Containers” are virtual views that collect various information about objects and are able to filter them in awareness of these. They are the general way of representing objects. They are aware of the state of an object (empty or new / closed / open). Containers act like a folder view that looks for data that matches filter criteria. It has to be very easy to customize them → reasonable set of filters visible (depending on which filters are already in use). To add or remove a criteria you can drag and drop from a list. This idea of filters is shared among all file views.&lt;br /&gt;
&lt;br /&gt;
5.A user can interact with an object by holding the mouse or finger over the object for a certain amount of time (1-2 s) or by right clicking. Then, a menu appears. It shows contextual actions (delete / duplicate / rate / tag / send to …), semantic information (which can depend on the filters used in the container) and gathers all notifications for an object. Notifications are treated similarly as tags and canhave actions associated with them, as have tags.&lt;br /&gt;
An object can call for attention by sending a visual and/or audible signal – it can also open parts of its menu (the notification area) by itself, if there is urgent information. By hovering this partial menu, the full menu is shown.&lt;br /&gt;
&lt;br /&gt;
6.No systemtray exclusive notifications. All objects (which to the user are pieces of information with actions associated to them) are treated the same (from a visualization point of view). The information belongs to the object associated with it. &lt;br /&gt;
Application Notifications are stuck to the objects representation, be it an open or closed object.&lt;br /&gt;
&lt;br /&gt;
7.Containers are no explicit Window switchers. There is the window switcher applet or composite animation for that. Containers are used to look at and change the state of objects. So they can open a closed object or create an empty one. There can still be a window switcher applet.&lt;br /&gt;
&lt;br /&gt;
8.You don't start an application, you start a task. If you have  several applications, you can choose between them. The user doesn't care about applications, they just want it to work. The user wants to write a new text document as opposed to opening a certain application that can edit text documents.&lt;br /&gt;
So applications are started by clicking on a certain task which is represented by an icon. By staying on the icon for a while (1-2 seconds) an action menu is shown (see point 4)&lt;br /&gt;
Every action a user does is a task. Tasks can be dragged into the application launcher bar.&lt;br /&gt;
9.When a new notification arrives from a process, of whom there is no visible object, a new task appears in the task bar.(!English relative clause!?) It has a pop-up that shows the message. By hovering, a full context menu appears. It shows more information and allows for more actions.&lt;br /&gt;
&lt;br /&gt;
10.New Tasks (application sessions) are treated the same way as closed documents or windows (open documents) are, because to the user, they basically represent empty documents or empty sessions of a chat application or an new browser page.&lt;br /&gt;
&lt;br /&gt;
11.Closed Objects, Windows and new Tasks have to be distinguishable. It is important to have useful and intuitive filters.&lt;br /&gt;
&lt;br /&gt;
12.An open file has to have the same contextual menu as a closed one. The problem here are notifications: In this file-centric system a notification would have to be attached to the application itself. This has to be either aggregated in a menu or attached to the bottom / top of the window. The former seems to be more viable.&lt;br /&gt;
&lt;br /&gt;
13.Closing a window NEVER is a destructive task. It has nothing to do with deleting a file. A new file is saved automatically. By closing an application that has unsaved changes, the changes are saved automatically. Change History has to be preserved. Deleting a file is done by using the objects context menu.&lt;br /&gt;
&lt;br /&gt;
=== Mockups ===&lt;br /&gt;
&lt;br /&gt;
==== Panel ====&lt;br /&gt;
&lt;br /&gt;
Here some Mockups of a possible panel:&lt;br /&gt;
&lt;br /&gt;
[[Image:SinoxyMockup1.png]]&lt;br /&gt;
&lt;br /&gt;
The user is hovering over the &amp;quot;new text document&amp;quot; icon. Not much to see here.&lt;br /&gt;
&lt;br /&gt;
===== Notifications =====&lt;br /&gt;
&lt;br /&gt;
[[Image:SinoxyMockup2.png]]&lt;br /&gt;
&lt;br /&gt;
This is slightly more intresting: Here, a task is calling for attention. Two new mails have arrived and the user is being informed. Hovering the icon or the notification will cause this:&lt;br /&gt;
&lt;br /&gt;
[[Image:SinoxyMockup3.png]]&lt;br /&gt;
&lt;br /&gt;
Here the user is presented with options. 1) Open the Mail application 2) ignore the notification (the dialog will disappear).&lt;br /&gt;
&lt;br /&gt;
This behaviour for notifications also applies for tasks who are not in the panel. All notifications for new or closed tasks appear this way.&lt;br /&gt;
&lt;br /&gt;
Minimized windows can also call for attention with a dialog and an associated action menu.&lt;br /&gt;
&lt;br /&gt;
===== Manage Lots of Tasks =====&lt;br /&gt;
&lt;br /&gt;
A problem with this kind of application starting behaviour is how to handle big masses of applications (or in sinoxy &amp;quot;tasks&amp;quot;). In Sinoxy this problem is solved by being able to invoke a dialog who displays all tasks available on the system (Partially this is also solved by grouping applications, who have the same purpose, under one &amp;quot;task&amp;quot;). To invoke this dialog, you click on the KDE-icon. Herefrom you can drag tasks to the panel and also start them directly. &lt;br /&gt;
&lt;br /&gt;
[[Image:SinoxyMockup4.png]]&lt;br /&gt;
&lt;br /&gt;
Probably, a search mechanism would be very convenient.&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Projects/Plasma/SynoxiDesktopInteractionPrinciples</id>
		<title>Projects/Plasma/SynoxiDesktopInteractionPrinciples</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Projects/Plasma/SynoxiDesktopInteractionPrinciples"/>
				<updated>2009-02-23T18:22:38Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Synoxi Desktop Interaction Principles ==&lt;br /&gt;
&lt;br /&gt;
This is a preliminary Version of my Dektop Interaction Principles. These are aimed to provide a high usability and consistency. They're also supposed to reduce the stress of looking for ones files. This is archieved thruogh its non-hierarchic file visualization management.&lt;br /&gt;
&lt;br /&gt;
=== The Principles ===&lt;br /&gt;
&lt;br /&gt;
1.What you see is what you get: Icons don't represent the file, they are the file&lt;br /&gt;
&lt;br /&gt;
2.No hierarchic Folder Arrangement: All Views a user gets are virtual folders and represent all files who match a certain criteria (e.g. all Pictures / all Files edited last week / all Files sent to me by Peter) This includes semantic information. A user doesn't want to care about WHERE to save his files, he cares about the content. So a file save dialogue would ask for additional metadata rather than a place to save.&lt;br /&gt;
&lt;br /&gt;
3.There are 3 types of objects for the user. These types will be called states further on: “Empty Objects” (create new file of a certain type) represented by an icon, “Closed Objects” (closed files)  represented by a preview and “Open Objects” (open windows) represented by the window itself. A minimized Window is treated as a closed object. It is just placed in a special containment (see point 4 for visualization details of objects). &lt;br /&gt;
&lt;br /&gt;
4.“Containers” are virtual views that collect various information about objects and are able to filter them in awareness of these. They are the general way of representing objects. They are aware of the state of an object (empty or new / closed / open). Containers act like a folder view that looks for data that matches filter criteria. It has to be very easy to customize them → reasonable set of filters visible (depending on which filters are already in use). To add or remove a criteria you can drag and drop from a list. This idea of filters is shared among all file views.&lt;br /&gt;
&lt;br /&gt;
5.A user can interact with an object by holding the mouse or finger over the object for a certain amount of time (1-2 s) or by right clicking. Then, a menu appears. It shows contextual actions (delete / duplicate / rate / tag / send to …), semantic information (which can depend on the filters used in the container) and gathers all notifications for an object. Notifications are treated similarly as tags and canhave actions associated with them, as have tags.&lt;br /&gt;
An object can call for attention by sending a visual and/or audible signal – it can also open parts of its menu (the notification area) by itself, if there is urgent information. By hovering this partial menu, the full menu is shown.&lt;br /&gt;
&lt;br /&gt;
6.No systemtray exclusive notifications. All objects (which to the user are pieces of information with actions associated to them) are treated the same (from a visualization point of view). The information belongs to the object associated with it. &lt;br /&gt;
Application Notifications are stuck to the objects representation, be it an open or closed object.&lt;br /&gt;
&lt;br /&gt;
7.Containers are no explicit Window switchers. There is the window switcher applet or composite animation for that. Containers are used to look at and change the state of objects. So they can open a closed object or create an empty one. There can still be a window switcher applet.&lt;br /&gt;
&lt;br /&gt;
8.You don't start an application, you start a task. If you have  several applications, you can choose between them. The user doesn't care about applications, they just want it to work. The user wants to write a new text document as opposed to opening a certain application that can edit text documents.&lt;br /&gt;
So applications are started by clicking on a certain task which is represented by an icon. By staying on the icon for a while (1-2 seconds) an action menu is shown (see point 4)&lt;br /&gt;
Every action a user does is a task. Tasks can be dragged into the application launcher bar.&lt;br /&gt;
9.When a new notification arrives from a process, of whom there is no visible object, a new task appears in the task bar.(!English relative clause!?) It has a pop-up that shows the message. By hovering, a full context menu appears. It shows more information and allows for more actions.&lt;br /&gt;
&lt;br /&gt;
10.New Tasks (application sessions) are treated the same way as closed documents or windows (open documents) are, because to the user, they basically represent empty documents or empty sessions of a chat application or an new browser page.&lt;br /&gt;
&lt;br /&gt;
11.Closed Objects, Windows and new Tasks have to be distinguishable. It is important to have useful and intuitive filters.&lt;br /&gt;
&lt;br /&gt;
12.An open file has to have the same contextual menu as a closed one. The problem here are notifications: In this file-centric system a notification would have to be attached to the application itself. This has to be either aggregated in a menu or attached to the bottom / top of the window. The former seems to be more viable.&lt;br /&gt;
&lt;br /&gt;
13.Closing a window NEVER is a destructive task. It has nothing to do with deleting a file. A new file is saved automatically. By closing an application that has unsaved changes, the changes are saved automatically. Change History has to be preserved. Deleting a file is done by using the objects context menu.&lt;br /&gt;
&lt;br /&gt;
=== Mockups ===&lt;br /&gt;
&lt;br /&gt;
Here some Mockups of a possible panel:&lt;br /&gt;
&lt;br /&gt;
[[Image:SinoxyMockup1.png]]&lt;br /&gt;
&lt;br /&gt;
The user is hovering over the &amp;quot;new text document&amp;quot; icon. Not much to see here.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:SinoxyMockup2.png]]&lt;br /&gt;
&lt;br /&gt;
This is slightly more intresting: Here a task is calling for attention. Two new mails have arrived and the user is being informed. Hovering the icon or the notification will cause this:&lt;br /&gt;
&lt;br /&gt;
[[Image:SinoxyMockup3.png]]&lt;br /&gt;
&lt;br /&gt;
Here the user is presented with options. 1) Open the Mail application 2) ignore the notification (the dialog will disappear).&lt;br /&gt;
&lt;br /&gt;
This behaviour for notifications also applies for tasks who are not in the panel. All notifications for new or closed tasks appear this way.&lt;br /&gt;
&lt;br /&gt;
Minimized windows can also call for attention with a dialog and an associated action menu.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A problem with this kind of application starting behaviour is how to handle big masses of applications (or in sinoxy &amp;quot;tasks&amp;quot;). In Sinoxy this problem is solved by being able to invoke a dialog who displays all tasks available on the system (Partially this is also solved by grouping applications, who have the same purpose, under one &amp;quot;task&amp;quot;). To invoke this dialog, you click on the KDE-icon. Herefrom you can drag tasks to the panel and also start them directly. &lt;br /&gt;
&lt;br /&gt;
[[Image:SinoxyMockup4.png]]&lt;br /&gt;
&lt;br /&gt;
Probably, a search mechanism would be very convenient.&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Projects/Plasma/SynoxiDesktopInteractionPrinciples</id>
		<title>Projects/Plasma/SynoxiDesktopInteractionPrinciples</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Projects/Plasma/SynoxiDesktopInteractionPrinciples"/>
				<updated>2009-02-23T17:47:49Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Synoxi Desktop Interaction Principles:&lt;br /&gt;
&lt;br /&gt;
This is a preliminary Version of my Dektop Interaction Principles. These are aimed to provide a high usability and consistency. They're also supposed to reduce the stress of looking for ones files. This is archieved thruogh its non-hierarchic file visualization management.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
1.What you see is what you get: Icons don't represent the file, they are the file&lt;br /&gt;
&lt;br /&gt;
2.No hierarchic Folder Arrangement: All Views a user gets are virtual folders and represent all files who match a certain criteria (e.g. all Pictures / all Files edited last week / all Files sent to me by Peter) This includes semantic information. A user doesn't want to care about WHERE to save his files, he cares about the content. So a file save dialogue would ask for additional metadata rather than a place to save.&lt;br /&gt;
&lt;br /&gt;
3.There are 3 types of objects for the user. These types will be called states further on: “Empty Objects” (create new file of a certain type) represented by an icon, “Closed Objects” (closed files)  represented by a preview and “Open Objects” (open windows) represented by the window itself. A minimized Window is treated as a closed object. It is just placed in a special containment (see point 4 for visualization details of objects). &lt;br /&gt;
&lt;br /&gt;
4.“Containers” are virtual views that collect various information about objects and are able to filter them in awareness of these. They are the general way of representing objects. They are aware of the state of an object (empty or new / closed / open). Containers act like a folder view that looks for data that matches filter criteria. It has to be very easy to customize them → reasonable set of filters visible (depending on which filters are already in use). To add or remove a criteria you can drag and drop from a list. This idea of filters is shared among all file views.&lt;br /&gt;
&lt;br /&gt;
5.A user can interact with an object by holding the mouse or finger over the object for a certain amount of time (1-2 s) or by right clicking. Then, a menu appears. It shows contextual actions (delete / duplicate / rate / tag / send to …), semantic information (which can depend on the filters used in the container) and gathers all notifications for an object. Notifications are treated similarly as tags and canhave actions associated with them, as have tags.&lt;br /&gt;
An object can call for attention by sending a visual and/or audible signal – it can also open parts of its menu (the notification area) by itself, if there is urgent information. By hovering this partial menu, the full menu is shown.&lt;br /&gt;
&lt;br /&gt;
6.No systemtray exclusive notifications. All objects (which to the user are pieces of information with actions associated to them) are treated the same (from a visualization point of view). The information belongs to the object associated with it. &lt;br /&gt;
Application Notifications are stuck to the objects representation, be it an open or closed object.&lt;br /&gt;
&lt;br /&gt;
7.Containers are no explicit Window switchers. There is the window switcher applet or composite animation for that. Containers are used to look at and change the state of objects. So they can open a closed object or create an empty one. There can still be a window switcher applet.&lt;br /&gt;
&lt;br /&gt;
8.You don't start an application, you start a task. If you have  several applications, you can choose between them. The user doesn't care about applications, they just want it to work. The user wants to write a new text document as opposed to opening a certain application that can edit text documents.&lt;br /&gt;
So applications are started by clicking on a certain task which is represented by an icon. By staying on the icon for a while (1-2 seconds) an action menu is shown (see point 4)&lt;br /&gt;
Every action a user does is a task. Tasks can be dragged into the application launcher bar.&lt;br /&gt;
9.When a new notification arrives from a process, of whom there is no visible object, a new task appears in the task bar.(!English relative clause!?) It has a pop-up that shows the message. By hovering, a full context menu appears. It shows more information and allows for more actions.&lt;br /&gt;
&lt;br /&gt;
10.New Tasks (application sessions) are treated the same way as closed documents or windows (open documents) are, because to the user, they basically represent empty documents or empty sessions of a chat application or an new browser page.&lt;br /&gt;
&lt;br /&gt;
11.Closed Objects, Windows and new Tasks have to be distinguishable. It is important to have useful and intuitive filters.&lt;br /&gt;
&lt;br /&gt;
12.An open file has to have the same contextual menu as a closed one. The problem here are notifications: In this file-centric system a notification would have to be attached to the application itself. This has to be either aggregated in a menu or attached to the bottom / top of the window. The former seems to be more viable.&lt;br /&gt;
&lt;br /&gt;
13.Closing a window NEVER is a destructive task. It has nothing to do with deleting a file. A new file is saved automatically. By closing an application that has unsaved changes, the changes are saved automatically. Change History has to be preserved. Deleting a file is done by using the objects context menu.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Here some Mockups of a possible panel:&lt;br /&gt;
&lt;br /&gt;
[[Image:SinoxyMockup1.png]]&lt;br /&gt;
&lt;br /&gt;
The user is hovering over the &amp;quot;new text document&amp;quot; icon. Not much to see here.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:SinoxyMockup2.png]]&lt;br /&gt;
&lt;br /&gt;
This is slightly more intresting: Here a task is calling for attention. Two new mails have arrived and the user is being informed. Hovering the icon or the notification will cause this:&lt;br /&gt;
&lt;br /&gt;
[[Image:SinoxyMockup3.png]]&lt;br /&gt;
&lt;br /&gt;
Here the user is presented with options. 1) Open the Mail application 2) ignore the notification (the dialog will disappear).&lt;br /&gt;
&lt;br /&gt;
This behaviour for notifications also applies for tasks who are not in the panel. All notifications for new or closed tasks appear this way.&lt;br /&gt;
&lt;br /&gt;
Minimized windows can also call for attention with a dialog and an associated action menu.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A problem with this kind of application starting behaviour is how to handle big masses of applications (or in sinoxy &amp;quot;tasks&amp;quot;). In Sinoxy this problem is solved by being able to invoke a dialog who displays all tasks available on the system (Partially this is also solved by grouping applications, who have the same purpose, under one &amp;quot;task&amp;quot;). To invoke this dialog, you click on the KDE-icon. Herefrom you can drag tasks to the panel and also start them directly. &lt;br /&gt;
&lt;br /&gt;
[[Image:SinoxyMockup4.png]]&lt;br /&gt;
&lt;br /&gt;
Probably, a search mechanism would be very convenient.&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/File:SinoxyMockup4.png</id>
		<title>File:SinoxyMockup4.png</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/File:SinoxyMockup4.png"/>
				<updated>2009-02-23T17:36:58Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: mockup for sinoxy desktop&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;mockup for sinoxy desktop&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Projects/Plasma/SynoxiDesktopInteractionPrinciples</id>
		<title>Projects/Plasma/SynoxiDesktopInteractionPrinciples</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Projects/Plasma/SynoxiDesktopInteractionPrinciples"/>
				<updated>2009-02-23T17:36:12Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Synoxi Desktop Interaction Principles:&lt;br /&gt;
&lt;br /&gt;
This is a preliminary Version of my Dektop Interaction Principles. These are aimed to provide a high usability and consistency. They're also supposed to reduce the stress of looking for ones files. This is archieved thruogh its non-hierarchic file visualization management.&lt;br /&gt;
I admit it might seem a bite vague now; I will provide some mockups and application examples.&lt;br /&gt;
&lt;br /&gt;
1.What you see is what you get: Icons don't represent the file, they are the file&lt;br /&gt;
&lt;br /&gt;
2.No hierarchic Folder Arrangement: All Views a user gets are virtual folders and represent all files who match a certain criteria (e.g. all Pictures / all Files edited last week / all Files sent to me by Peter) This includes semantic information. A user doesn't want to care about WHERE to save his files, he cares about the content. So a file save dialogue would ask for additional metadata rather than a place to save.&lt;br /&gt;
&lt;br /&gt;
3.There are 3 types of objects for the user. These types will be called states further on: “Empty Objects” (create new file of a certain type) represented by an icon, “Closed Objects” (closed files)  represented by a preview and “Open Objects” (open windows) represented by the window itself. A minimized Window is treated as a closed object. It is just placed in a special containment (see point 4 for visualization details of objects). &lt;br /&gt;
&lt;br /&gt;
4.“Containers” are virtual views that collect various information about objects and are able to filter them in awareness of these. They are the general way of representing objects. They are aware of the state of an object (empty or new / closed / open). Containers act like a folder view that looks for data that matches filter criteria. It has to be very easy to customize them → reasonable set of filters visible (depending on which filters are already in use). To add or remove a criteria you can drag and drop from a list. This idea of filters is shared among all file views.&lt;br /&gt;
&lt;br /&gt;
5.A user can interact with an object by holding the mouse or finger over the object for a certain amount of time (1-2 s) or by right clicking. Then, a menu appears. It shows contextual actions (delete / duplicate / rate / tag / send to …), semantic information (which can depend on the filters used in the container) and gathers all notifications for an object. Notifications are treated similarly as tags and canhave actions associated with them, as have tags.&lt;br /&gt;
An object can call for attention by sending a visual and/or audible signal – it can also open parts of its menu (the notification area) by itself, if there is urgent information. By hovering this partial menu, the full menu is shown.&lt;br /&gt;
&lt;br /&gt;
6.No systemtray exclusive notifications. All objects (which to the user are pieces of information with actions associated to them) are treated the same (from a visualization point of view). The information belongs to the object associated with it. &lt;br /&gt;
Application Notifications are stuck to the objects representation, be it an open or closed object.&lt;br /&gt;
&lt;br /&gt;
7.Containers are no explicit Window switchers. There is the window switcher applet or composite animation for that. Containers are used to look at and change the state of objects. So they can open a closed object or create an empty one. There can still be a window switcher applet.&lt;br /&gt;
&lt;br /&gt;
8.You don't start an application, you start a task. If you have  several applications, you can choose between them. The user doesn't care about applications, they just want it to work. The user wants to write a new text document as opposed to opening a certain application that can edit text documents.&lt;br /&gt;
So applications are started by clicking on a certain task which is represented by an icon. By staying on the icon for a while (1-2 seconds) an action menu is shown (see point 4)&lt;br /&gt;
Every action a user does is a task. Tasks can be dragged into the application launcher bar.&lt;br /&gt;
9.When a new notification arrives from a process, of whom there is no visible object, a new task appears in the task bar.(!English relative clause!?) It has a pop-up that shows the message. By hovering, a full context menu appears. It shows more information and allows for more actions.&lt;br /&gt;
&lt;br /&gt;
10.New Tasks (application sessions) are treated the same way as closed documents or windows (open documents) are, because to the user, they basically represent empty documents or empty sessions of a chat application or an new browser page.&lt;br /&gt;
&lt;br /&gt;
11.Closed Objects, Windows and new Tasks have to be distinguishable. It is important to have useful and intuitive filters.&lt;br /&gt;
&lt;br /&gt;
12.An open file has to have the same contextual menu as a closed one. The problem here are notifications: In this file-centric system a notification would have to be attached to the application itself. This has to be either aggregated in a menu or attached to the bottom / top of the window. The former seems to be more viable.&lt;br /&gt;
&lt;br /&gt;
13.Closing a window NEVER is a destructive task. It has nothing to do with deleting a file. A new file is saved automatically. By closing an application that has unsaved changes, the changes are saved automatically. Change History has to be preserved. Deleting a file is done by using the objects context menu.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Here some Mockups of a possible panel:&lt;br /&gt;
&lt;br /&gt;
[[Image:SinoxyMockup1.png]]&lt;br /&gt;
&lt;br /&gt;
The user is hovering over the &amp;quot;new text document&amp;quot; icon. Not much to see here.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:SinoxyMockup2.png]]&lt;br /&gt;
&lt;br /&gt;
This is slightly more intresting: Here a task is calling for attention. Two new mails have arrived and the user is being informed. Hovering the icon or the notification will cause this:&lt;br /&gt;
&lt;br /&gt;
[[Image:SinoxyMockup3.png]]&lt;br /&gt;
&lt;br /&gt;
Here the user is presented with options. 1) Open the Mail application 2) ignore the notification (the dialog will disappear).&lt;br /&gt;
&lt;br /&gt;
This behaviour for notifications also applies for tasks who are not in the panel. All notifications for new or closed tasks appear this way.&lt;br /&gt;
&lt;br /&gt;
Minimized windows can also call for attention with a dialog and an associated action menu.&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/File:SinoxyMockup3.png</id>
		<title>File:SinoxyMockup3.png</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/File:SinoxyMockup3.png"/>
				<updated>2009-02-23T17:31:09Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: mockup for sinoxy desktop&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;mockup for sinoxy desktop&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/File:SinoxyMockup2.png</id>
		<title>File:SinoxyMockup2.png</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/File:SinoxyMockup2.png"/>
				<updated>2009-02-23T17:28:46Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: mockup for sinoxy desktop&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;mockup for sinoxy desktop&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/File:SinoxyMockup1.png</id>
		<title>File:SinoxyMockup1.png</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/File:SinoxyMockup1.png"/>
				<updated>2009-02-23T17:26:47Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Projects/Plasma/SynoxiDesktopInteractionPrinciples</id>
		<title>Projects/Plasma/SynoxiDesktopInteractionPrinciples</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Projects/Plasma/SynoxiDesktopInteractionPrinciples"/>
				<updated>2009-02-23T17:25:38Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Synoxi Desktop Interaction Principles:&lt;br /&gt;
&lt;br /&gt;
This is a preliminary Version of my Dektop Interaction Principles. These are aimed to provide a high usability and consistency. They're also supposed to reduce the stress of looking for ones files. This is archieved thruogh its non-hierarchic file visualization management.&lt;br /&gt;
I admit it might seem a bite vague now; I will provide some mockups and application examples.&lt;br /&gt;
&lt;br /&gt;
1.What you see is what you get: Icons don't represent the file, they are the file&lt;br /&gt;
&lt;br /&gt;
2.No hierarchic Folder Arrangement: All Views a user gets are virtual folders and represent all files who match a certain criteria (e.g. all Pictures / all Files edited last week / all Files sent to me by Peter) This includes semantic information. A user doesn't want to care about WHERE to save his files, he cares about the content. So a file save dialogue would ask for additional metadata rather than a place to save.&lt;br /&gt;
&lt;br /&gt;
3.There are 3 types of objects for the user. These types will be called states further on: “Empty Objects” (create new file of a certain type) represented by an icon, “Closed Objects” (closed files)  represented by a preview and “Open Objects” (open windows) represented by the window itself. A minimized Window is treated as a closed object. It is just placed in a special containment (see point 4 for visualization details of objects). &lt;br /&gt;
&lt;br /&gt;
4.“Containers” are virtual views that collect various information about objects and are able to filter them in awareness of these. They are the general way of representing objects. They are aware of the state of an object (empty or new / closed / open). Containers act like a folder view that looks for data that matches filter criteria. It has to be very easy to customize them → reasonable set of filters visible (depending on which filters are already in use). To add or remove a criteria you can drag and drop from a list. This idea of filters is shared among all file views.&lt;br /&gt;
&lt;br /&gt;
5.A user can interact with an object by holding the mouse or finger over the object for a certain amount of time (1-2 s) or by right clicking. Then, a menu appears. It shows contextual actions (delete / duplicate / rate / tag / send to …), semantic information (which can depend on the filters used in the container) and gathers all notifications for an object. Notifications are treated similarly as tags and canhave actions associated with them, as have tags.&lt;br /&gt;
An object can call for attention by sending a visual and/or audible signal – it can also open parts of its menu (the notification area) by itself, if there is urgent information. By hovering this partial menu, the full menu is shown.&lt;br /&gt;
&lt;br /&gt;
6.No systemtray exclusive notifications. All objects (which to the user are pieces of information with actions associated to them) are treated the same (from a visualization point of view). The information belongs to the object associated with it. &lt;br /&gt;
Application Notifications are stuck to the objects representation, be it an open or closed object.&lt;br /&gt;
&lt;br /&gt;
7.Containers are no explicit Window switchers. There is the window switcher applet or composite animation for that. Containers are used to look at and change the state of objects. So they can open a closed object or create an empty one. There can still be a window switcher applet.&lt;br /&gt;
&lt;br /&gt;
8.You don't start an application, you start a task. If you have  several applications, you can choose between them. The user doesn't care about applications, they just want it to work. The user wants to write a new text document as opposed to opening a certain application that can edit text documents.&lt;br /&gt;
So applications are started by clicking on a certain task which is represented by an icon. By staying on the icon for a while (1-2 seconds) an action menu is shown (see point 4)&lt;br /&gt;
Every action a user does is a task. Tasks can be dragged into the application launcher bar.&lt;br /&gt;
9.When a new notification arrives from a process, of whom there is no visible object, a new task appears in the task bar.(!English relative clause!?) It has a pop-up that shows the message. By hovering, a full context menu appears. It shows more information and allows for more actions.&lt;br /&gt;
&lt;br /&gt;
10.New Tasks (application sessions) are treated the same way as closed documents or windows (open documents) are, because to the user, they basically represent empty documents or empty sessions of a chat application or an new browser page.&lt;br /&gt;
&lt;br /&gt;
11.Closed Objects, Windows and new Tasks have to be distinguishable. It is important to have useful and intuitive filters.&lt;br /&gt;
&lt;br /&gt;
12.An open file has to have the same contextual menu as a closed one. The problem here are notifications: In this file-centric system a notification would have to be attached to the application itself. This has to be either aggregated in a menu or attached to the bottom / top of the window. The former seems to be more viable.&lt;br /&gt;
&lt;br /&gt;
13.Closing a window NEVER is a destructive task. It has nothing to do with deleting a file. A new file is saved automatically. By closing an application that has unsaved changes, the changes are saved automatically. Change History has to be preserved. Deleting a file is done by using the objects context menu.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Here some Mockups of a possible panel:&lt;br /&gt;
&lt;br /&gt;
[[Image:Mockup1.png]]&lt;br /&gt;
&lt;br /&gt;
The user is hovering over the &amp;quot;new text document&amp;quot; icon.&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/File:Mockup1.png</id>
		<title>File:Mockup1.png</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/File:Mockup1.png"/>
				<updated>2009-02-23T17:20:58Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: Possible Standard Panel view for Sinoxy (Mockup).
Create new text document is hovered.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Possible Standard Panel view for Sinoxy (Mockup).&lt;br /&gt;
Create new text document is hovered.&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Projects/Plasma/SynoxiDesktopInteractionPrinciples</id>
		<title>Projects/Plasma/SynoxiDesktopInteractionPrinciples</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Projects/Plasma/SynoxiDesktopInteractionPrinciples"/>
				<updated>2009-02-04T21:56:27Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: This is a preliminary Version of my Dektop Interaction Principles&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Synoxi Desktop Interaction Principles:&lt;br /&gt;
&lt;br /&gt;
This is a preliminary Version of my Dektop Interaction Principles. These are aimed to provide a high usability and consistency. They're also supposed to reduce the stress of looking for ones files. This is archieved thruogh its non-hierarchic file visualization management.&lt;br /&gt;
I admit it might seem a bite vague now; I will provide some mockups and application examples.&lt;br /&gt;
&lt;br /&gt;
1.What you see is what you get: Icons don't represent the file, they are the file&lt;br /&gt;
&lt;br /&gt;
2.No hierarchic Folder Arrangement: All Views a user gets are virtual folders and represent all files who match a certain criteria (e.g. all Pictures / all Files edited last week / all Files sent to me by Peter) This includes semantic information. A user doesn't want to care about WHERE to save his files, he cares about the content. So a file save dialogue would ask for additional metadata rather than a place to save.&lt;br /&gt;
&lt;br /&gt;
3.There are 3 types of objects for the user. These types will be called states further on: “Empty Objects” (create new file of a certain type) represented by an icon, “Closed Objects” (closed files)  represented by a preview and “Open Objects” (open windows) represented by the window itself. A minimized Window is treated as a closed object. It is just placed in a special containment (see point 4 for visualization details of objects). &lt;br /&gt;
&lt;br /&gt;
4.“Containers” are virtual views that collect various information about objects and are able to filter them in awareness of these. They are the general way of representing objects. They are aware of the state of an object (empty or new / closed / open). Containers act like a folder view that looks for data that matches filter criteria. It has to be very easy to customize them → reasonable set of filters visible (depending on which filters are already in use). To add or remove a criteria you can drag and drop from a list. This idea of filters is shared among all file views.&lt;br /&gt;
&lt;br /&gt;
5.A user can interact with an object by holding the mouse or finger over the object for a certain amount of time (1-2 s) or by right clicking. Then, a menu appears. It shows contextual actions (delete / duplicate / rate / tag / send to …), semantic information (which can depend on the filters used in the container) and gathers all notifications for an object. Notifications are treated similarly as tags and canhave actions associated with them, as have tags.&lt;br /&gt;
An object can call for attention by sending a visual and/or audible signal – it can also open parts of its menu (the notification area) by itself, if there is urgent information. By hovering this partial menu, the full menu is shown.&lt;br /&gt;
&lt;br /&gt;
6.No systemtray exclusive notifications. All objects (which to the user are pieces of information with actions associated to them) are treated the same (from a visualization point of view). The information belongs to the object associated with it. &lt;br /&gt;
Application Notifications are stuck to the objects representation, be it an open or closed object.&lt;br /&gt;
&lt;br /&gt;
7.Containers are no explicit Window switchers. There is the window switcher applet or composite animation for that. Containers are used to look at and change the state of objects. So they can open a closed object or create an empty one. There can still be a window switcher applet.&lt;br /&gt;
&lt;br /&gt;
8.You don't start an application, you start a task. If you have  several applications, you can choose between them. The user doesn't care about applications, they just want it to work. The user wants to write a new text document as opposed to opening a certain application that can edit text documents.&lt;br /&gt;
So applications are started by clicking on a certain task which is represented by an icon. By staying on the icon for a while (1-2 seconds) an action menu is shown (see point 4)&lt;br /&gt;
Every action a user does is a task. Tasks can be dragged into the application launcher bar.&lt;br /&gt;
9.When a new notification arrives from a process, of whom there is no visible object, a new task appears in the task bar.(!English relative clause!?) It has a pop-up that shows the message. By hovering, a full context menu appears. It shows more information and allows for more actions.&lt;br /&gt;
&lt;br /&gt;
10.New Tasks (application sessions) are treated the same way as closed documents or windows (open documents) are, because to the user, they basically represent empty documents or empty sessions of a chat application or an new browser page.&lt;br /&gt;
&lt;br /&gt;
11.Closed Objects, Windows and new Tasks have to be distinguishable. It is important to have useful and intuitive filters.&lt;br /&gt;
&lt;br /&gt;
12.An open file has to have the same contextual menu as a closed one. The problem here are notifications: In this file-centric system a notification would have to be attached to the application itself. This has to be either aggregated in a menu or attached to the bottom / top of the window. The former seems to be more viable.&lt;br /&gt;
&lt;br /&gt;
13.Closing a window NEVER is a destructive task. It has nothing to do with deleting a file. A new file is saved automatically. By closing an application that has unsaved changes, the changes are saved automatically. Change History has to be preserved. Deleting a file is done by using the objects context menu.&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials/KConfig_(de)</id>
		<title>Development/Tutorials/KConfig (de)</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials/KConfig_(de)"/>
				<updated>2008-05-26T18:35:29Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:I18n/Language Navigation Bar|Development/Tutorials/KConfig}}&lt;br /&gt;
&lt;br /&gt;
{{TutorialBrowser (de)|&lt;br /&gt;
&lt;br /&gt;
series=KConfig|&lt;br /&gt;
&lt;br /&gt;
name=Einführung in KConfig|&lt;br /&gt;
&lt;br /&gt;
pre=Keine|&lt;br /&gt;
&lt;br /&gt;
next=[[../Using_KConfig_XT (de)|Benutzen von KConfig XT]]|&lt;br /&gt;
&lt;br /&gt;
reading=Keine&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{improve (de)}}&lt;br /&gt;
&lt;br /&gt;
== Zusammenfassung ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dieser Artikel beschäftigt sich mir dem KDE Einstellungdaten-System, angefangen mit einer Übersicht über den grundlegenden Aufbau aus der Sicht eines Entwicklers. Es wirft ausserdem einen Blick auf jede der Klassen, die für die Entwicklung von Anwendungen relevant sind und fährt dann mit kiosk (Benutzer- und Gruppenprofile) Integration fort.&lt;br /&gt;
&lt;br /&gt;
== Grundlegender Aufbau ==&lt;br /&gt;
&lt;br /&gt;
KConfig ist ausgelegt um das Konzept vom eigentlichen Speichern und Auffinden von Konfigurationsdaten hinter eine Programmierschnittstelle zu abstrahieren die es ermöglicht, auf einfache Weise Informationen abzurufen und zu setzen. Wo oder in welcher Form Daten gespeichert werden ist für eine Anwendung die KConfig benutzt irrelevant.&lt;br /&gt;
&lt;br /&gt;
Das behält alle KDE Anwendungen konsistent in ihrer Art, Konfigurationen handzuhaben und nimmt einem Anwendungs-Entwickler die Arbeit so ein System von Grund auf neu zu schreiben, was ein sehr fehleranfälliger Prozess sein kann.&lt;br /&gt;
&lt;br /&gt;
Jedes KConfig Objekt verkörpert ein einziges Konfigurationsobjekt. Jedes Konfigurationsobjekt ist durch seinen einzigartigen Namen gekennzeichnet und kann von mehreren lokalen oder externen Daten oder Services gelesen werden. Jede Anwendung hat standardmässig ein zugehöriges Konfigurationsobjekt und es gibt auch ein globales Konfigurationsobjekt.&lt;br /&gt;
&lt;br /&gt;
Diese Konfigurationsobjekte sind nach einer zweistufigen Hierarchie getrennt: Gruppen und Schlüssel. Ein Konfigurationsobjekt kann eine beliebige Anzahl an Gruppen haben und jede Gruppe kann einen oder mehrere Schlüssel mit zugehörigen Werten haben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die gespeicherten Werte können aus beliebig vielen verschiedenen Datentypen bestehen. Sie werden gespeichert und abgerufen als das Objekt selbst. Zum Beispiel wird ein {{qt|QObject}}-Objekt direkt einem Konfigurationsobjekt übergeben, wenn es einen Farbwert speichert und wenn ein Farbwert abgerufen wird, wird ein {{qt|QObject}}-Objekt zurückgegeben.&lt;br /&gt;
&lt;br /&gt;
Anwendungen selbst müssen sich deshalb nicht um das Gliedern und Entgliedern von Objekten kümmern.&lt;br /&gt;
&lt;br /&gt;
== Die KConfig Klasse ==&lt;br /&gt;
&lt;br /&gt;
Das {{class|KConfig}}-Objekt wird benutzt um ein bestehendes Konfigurationsobjekt anzusteuern. Es gibt eine Reihe von Möglichkeiten ein Konfigurationsobjekt zu erstellen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
// ein einfaches, altes lesen/schreiben Konfigurationsobjekt&lt;br /&gt;
KConfig config(&amp;quot;myapprc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// eine bestimmte Datei im Dateisystem&lt;br /&gt;
// currently must be an INI style file&lt;br /&gt;
KConfig fullPath(&amp;quot;/etc/kderc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// nicht mit globalen Werten verflochten&lt;br /&gt;
KConfig globalFree( &amp;quot;localsrc&amp;quot;, KConfig::NoGlobals );&lt;br /&gt;
&lt;br /&gt;
// nicht mit globalen Werten orde der $KDEDIRS Hierarchie verflochten&lt;br /&gt;
KConfig simpleConfig( &amp;quot;simplerc&amp;quot;, KConfig::SimpleConfig );&lt;br /&gt;
&lt;br /&gt;
// Komponenten-spezifische Konfiguration, in diesem Fall ein Plugin&lt;br /&gt;
KConfig pluginConfig( componentData(), &amp;quot;pluginrc&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
// Ausserhalb der normalen Konfigurations-Ressource&lt;br /&gt;
KConfig dataResource( &amp;quot;data&amp;quot;, &amp;quot;myapp/somefile&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{note (de)|wie soll &amp;quot;merged&amp;quot; in den folgenden Fällen übersetzt werden? &amp;lt;br&amp;gt; &amp;lt;tt&amp;gt;&amp;quot;verschmolzen&amp;quot; oder &amp;quot;verflochten&amp;quot;&amp;lt;/tt&amp;gt; &amp;lt;br&amp;gt; der Anwendung selber transparent&amp;quot; tönt auch nicht sehr gut}}&lt;br /&gt;
&lt;br /&gt;
Das Kconfig Objekt, das wir auf Zeile 2 erstellen ist ein gewöhnliches Konfigurationsobjekt. Wir können Werte aus ihm lesen, neue Einträge schreiben und nach verschiedenen Eigenschaften des Objekts fragen. Dieses Objekt wird aus der Konfigurations-Ressource geladen, wie es durch {{class|KStandardDirs}} bestimmt wird, das heisst, dass jede Instanz des &amp;lt;tt&amp;gt;myapprc&amp;lt;/tt&amp;gt;-Objekts in jedem der Ordner in der Konfigurations-Ressourcen-Hierarchie verschmolzen werden um die Werte zu erzeugen, die in diesem Objekt gesehen werden. So werden Systemweite und &lt;br /&gt;
pro-Benutzer/Gruppen Profile erstellt und unterstützt. Das alles geschieht der Anwendung selber transparent.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{tip| Für mehr Informationen, wie das Verschmelzen funktioniert, siehe diesen Artikel über die [[KDE System Administration/KDE_Filesystem_Hierarchy|KDE Dateisystem Hierarchie]].}}&lt;br /&gt;
&lt;br /&gt;
Auf Zeile 6 öffnen wir eine bestimmte Lokale Datei, in diesem Fall {{path|/etc/kderc}}. Das führt kein Verschmelzen von Werten aus und erwartet eine Datei im INI Format.&lt;br /&gt;
&lt;br /&gt;
Zeile 9 erzeugt ein Konfigurationsobjekt, dass nicht mit dem globalen &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt;-Konfigurationsobjekt verflochten ist,  während das Konfigurationsobjekt auf Zeile 12 zusätzlich mit keinem der Dateien in der &amp;lt;tt&amp;gt;$KDEDIRS&amp;lt;/tt&amp;gt;-Hierarchie verflochten ist. Das kann die Leistung spürbar verbessern, falls man einfach nur Werte aus einer einfachen Konfuguration liest und globale Werte keine Rolle spielen.&lt;br /&gt;
&lt;br /&gt;
Zeile 15 erzeugt ein Konfigurationsobjekt unter Benutzung des {{class|KComponentData}}-Objekts das zu einem Plugin oder einer anderen Komponente gehört. Das Plugin kann verschiedene Ordner aufweisen, die in seinen {{class|KStandardDirs}} definiert sind und das ist eine Möglichkeit sich zu versichern, dass {{class|KConfig}} das respektiert.&lt;br /&gt;
&lt;br /&gt;
Und schliesslich auf Zeile 18 erzeugen wir ein Konfigurationsobjekt, das nicht in der &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt;-Ressource sondern in der &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt;-Ressource existiert. Man kann kann auf diese Weise jede Ressource verwenden, von denen {{class|KStandardDirs}} Kenntnis hat, auch solche die während der Laufzeit hinzugefügt werden.&lt;br /&gt;
&lt;br /&gt;
=== Spezielle Konfigurationsobjekte ===&lt;br /&gt;
&lt;br /&gt;
Jede Anwendung hat sein eigenes Konfigurationsobjekt das den Namen benutzt, der von {{class|KAboutData}} bereitgestellt wird mit angehängtem &amp;quot;rc&amp;quot;. Also hätte eine Anwendung mit dem Namen &amp;quot;myapp&amp;quot; das Standard-Konfigurationsobjekt &amp;quot;myapprc&amp;quot;. Dieses Konfigurationsobjekt kann auf diese Weise aufgerufen werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KComponentData&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
#include &amp;lt;KGlobal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    // beachten sie, dass dies eigentlich ein KSharedConfig ist&lt;br /&gt;
    // mehr über diese Klasse siehe weiter unten&lt;br /&gt;
    KConfig* config = KGlobal::config();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Auf das Standard-Konfigurationsobjekt für die Anwendung wird zugegriffen, wenn kein Name definiert wurde, als das {{class|KConfig}}-Objekt erzeugt wurde. Also könnten wir stattdessen auch das tun:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    KConfig config;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zusätzlich könnte jede Komponente sein eigenes Konfigurationsobjekt haben. Auf dieses wird normalerweise durch die &amp;lt;tt&amp;gt;componentData()&amp;lt;/tt&amp;gt; des Plugins zugegriffen, anstatt durch die &amp;lt;tt&amp;gt;{{class|KGlobal}}::mainComponent()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Und schliesslich gibt es noch ein globales Konfigurationsobjekt, &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt;, das von jeder Anwendung verwendet wird. Es enthält Informationen wie die Standard-Tatenkombinationen für verschiedene Aktionen. Es wird in das Konfigurationsobjekt &amp;quot;gemischt&amp;quot; wenn der &amp;lt;tt&amp;gt;KConfig::IncludeGlobals&amp;lt;/tt&amp;gt; Bitschalter dem {{class|KConfig}} Konstruktor übergeben wird, was standardmässig der Fall ist.&lt;br /&gt;
&lt;br /&gt;
=== Allgemein nützliche Methoden ===&lt;br /&gt;
&lt;br /&gt;
Um den momentanen Zustand des Konfigurationsobjektes zu speichern, rufen wir die &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt;-Methode auf. Diese Methode wird also aufgerufen, wenn ein Objekt zerstört wird. Falls keine Änderungen gemacht wurden, oder die Ressource weist sich als nicht beschreibbar aus (Wenn der Benutzer zum Beispiel nicht genug Rechte hat, um die Datei zu bearbeiten), dann wird keine Beschäftigung der Festplatte hervorgerufen. &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; verschmilzt Änderungen die gleichzeitig von anderen Prozessen ausgeführt werden - lokale Änderungen haben aber trotzdem Vorrang.&lt;br /&gt;
&lt;br /&gt;
Wenn wir sicher gehen wollen, dass wir die aktuellsten Werte von der Festplatte haben, dann rufen wir &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt; auf, welches &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; aufruft und dann die Daten von der Festplatte aktualisiert.&lt;br /&gt;
&lt;br /&gt;
Falls wir verhindern müssen, dass das Konfigurationsobjekt bereits gemachte Änderungen nicht auf die Festplatte speichert, müssen wir &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt; aufrufen. Ein besonderer Anwendungsfall ist es, die Konfiguration zum Festplatten-Zustand zurückzusetzen indem man &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt; gefolgt von &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt; aufruft.&lt;br /&gt;
&lt;br /&gt;
Alle Gruppen in einem Konfigurationsobjekt aufzurufen ist so einfach wie hier in diesem Code-Abschnitt &amp;lt;tt&amp;gt;groupList()&amp;lt;/tt&amp;gt; aufzurufen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::mainComponent().config();&lt;br /&gt;
&lt;br /&gt;
foreach ( const QString&amp;amp; group, config.groupList() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;next group:&amp;quot; &amp;lt;&amp;lt; group;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== KSharedConfig ==&lt;br /&gt;
&lt;br /&gt;
Die {{class|KSharedConfig}} Klasse ist eine Referenz-gezählte Version von {{class|KConfig}}. Darum stellt es eine Möglichkeit bereit, das selbe Konfigurationsobjekt von unterschiedlichen Orten zu referenzieren ohne zusätzlich die Objekte trennen zu müssen oder sich um die Synchronisation des Schreibvorgangs zu kümmern, selbst wenn das Konfigurationsobjekt von verschiedenen Code-Pfaden aktualisiert wird.&lt;br /&gt;
&lt;br /&gt;
Auf ein {{class|KSharedConfig}}-Objekt zuzugreifen ist so einfach wie das hier:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KSharedConfigPtr config = KSharedConfig::openConfig();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;openConfig()&amp;lt;/tt&amp;gt; nimmt die selben Parameter wie {{class|KConfig}}'s Konstruktoren, was es einem ermöglicht zu definieren, welche Konfigurationsdatei zu öffnen und Markierungen das Verschmelzen von nicht-&amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt;-Ressourcen zu kontrollieren.  &lt;br /&gt;
&lt;br /&gt;
Es wird grundsätzlich empfohlen {{class|KSharedConfig}} anstatt {{class|KConfig}} selbst zu benutzen, und auch das Objekt, das von {{class|KComponentData}} zurückgegeben wird ist in der Tat ein {{class|KSharedConfig}}-Objekt.&lt;br /&gt;
&lt;br /&gt;
== KConfigGroup ==&lt;br /&gt;
&lt;br /&gt;
Nun da wir ein Konfigurationsobjekt haben, ist der nächste Schritt es tatsächlich zu nutzen. Das erste, das wir tun müssen, ist zu bestimmen, auf welche Gruppe von Schlüssel-/Wertepaare wir in unserem Objekt zugreifen wollen. Wir tun das, indem wir ein KConfigGroup-Objekt erstellen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig config;&lt;br /&gt;
KConfigGroup generalGroup( &amp;amp;config, &amp;quot;General&amp;quot; );&lt;br /&gt;
KConfigGroup colorsGroup = config.group( &amp;quot;Colors&amp;quot; ); // ...oder so ähnlich...&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Man kann{{class|KConfigGroup}} {{class|KConfig}}- oder {{class|KSharedConfig}}-Objekte übergeben.&lt;br /&gt;
&lt;br /&gt;
Konfigurationsgruppen können ebenfalls verschachtelt werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfigGroup subGroup1( &amp;amp;generalGroup, &amp;quot;LessGeneral&amp;quot; );&lt;br /&gt;
KConfigGroup subGroup2 = colorsGroup.group( &amp;quot;Dialogs&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Lesen von Einträgen ==&lt;br /&gt;
&lt;br /&gt;
Wenn man erst einmal ein {{class|KConfigGroup}}-Objekt erstellt hat, ist das Lesen von Einträgen ziemlich einfach:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
QString accountName = generalGroup.readEntry( &amp;quot;Account&amp;quot;,&lt;br /&gt;
                                              QString() );&lt;br /&gt;
QColor color = colorsGroup.readEntry( &amp;quot;background&amp;quot;,&lt;br /&gt;
                                      Qt::white );&lt;br /&gt;
QStringList list = generalGroup.readEntry( &amp;quot;List&amp;quot;,&lt;br /&gt;
                                           QStringList() );&lt;br /&gt;
QString path = generalGroup.readPathEntry( &amp;quot;SaveTo&amp;quot;,&lt;br /&gt;
                                           defaultPath );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wie man hier oben sehen kann, kann man Lesevorgänge von verschiedenen {{class|KConfigGroup}}-Objekten, die auf dem selben {{class|KConfig}}-Objekt erstellt wurden, problemlos mischen. Die Lese-Methoden nehmen den Schlüssel, der Gross- und Kleinschreibung unterscheidet, als erstes Argument und den Standardwert als zweites Argument. Dieses Argument bestimmt auch welche Art von Daten, also z.B. eine Farbe in Zeile 3, erwartet wird und auch die Art von Objekt, die zurückgegeben werden soll.Das zurückgegebene Objekt wird in eine {{qt|QVariant}} gepackt um diese Hexerei zu ermöglichen. &lt;br /&gt;
&lt;br /&gt;
Es gibt eine Anzahl von speziellen Methoden, zum Beispiel &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt;, das einen Datei-Systempfad zurückgibt. Es ist entscheidend, dass man &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; benutzt, wenn man nach einem Pfad fragt, das es Funktionen wie Erreichbarkeits-Profile ermöglicht richtig zu funktionieren.&lt;br /&gt;
&lt;br /&gt;
Wenn kein solcher Schlüssel im Konfigurationsobjekt existiert, dann wird stattdessen der Standardwert zurückgegeben. Falls es eine lokalisierte (d.h. in eine andere Sprache übersetzte) Version für den Schlüssel gibt, die der eingestellten Sprache entspricht, dann wird diese zurückgegeben.&lt;br /&gt;
&lt;br /&gt;
== Schreiben neuer Einträge ==&lt;br /&gt;
&lt;br /&gt;
Neue Werte zu definieren ist ähnlich einfach:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
generalGroup.writeEntry( &amp;quot;Account&amp;quot;, accountName );&lt;br /&gt;
generalGroup.writePathEntry( &amp;quot;SaveTo&amp;quot;, savePath );&lt;br /&gt;
colorGroup.writeEntry( &amp;quot;background&amp;quot;, color );&lt;br /&gt;
generalGroup.config()-&amp;gt;sync();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beachten sie die Benutzung von &amp;lt;tt&amp;gt;writePathEntry&amp;lt;/tt&amp;gt; und wie die Art von Objekt, das wir benutzen, wie zum Beispiel {{qt|QColor}} auf Zeile 3, bestimmt, wie die Daten angeordnet werden. Zusätzlich, wenn wir mit den Einträgen fertig sind, muss &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; auf das Konfigurationsobjekt ausgeführt werden, um es auf die Festplatte zu speichern. Man kann auch einfach warten, bis das Objekt zerstört wird, was falls nötig automatisch einen &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; auslöst.&lt;br /&gt;
&lt;br /&gt;
== KDesktopFile: Ein besonderer Fall ==&lt;br /&gt;
&lt;br /&gt;
Wann ist eine Konfigurationsdatei keine Konfigurationsdatei? Wenn es eine [http://freedesktop.org/wiki/Standards_2fdesktop_2dentry_2dspec Desktop-Datei] ist. Diese Dateien, die im Grunde genommen Konfigurationsdateien sind, werden benutzt um Einträge für Anwendungsmenüs, Dateitypen, Plugins und verschiedene Services.&lt;br /&gt;
&lt;br /&gt;
Wenn auf eine .desktop Datei zugegriffen wird, sollte man stattdessen die  {{class|KDesktopFile}}-Klasse verwenden, die, während eine {{class|KConfig}}-Klasse über alle oben genannten Ressourcen verfügt, über eine Anzahl von Methoden verfügt, um das Zugreifen auf Standard-Attribute dieser Dateien konsistent und zuverlässig zu machen.&lt;br /&gt;
&lt;br /&gt;
== Kiosk: Abriegelung und Benutzer-/Gruppenprofile ==&lt;br /&gt;
&lt;br /&gt;
KConfig stellt eine Reihe von leistungsstarken Abriegelungs- und Konfigurations-Definitionen bereit, insgesamt als &amp;quot;Kiosk&amp;quot; bekannt, worauf viele System-Administratoren und -Integratoren basieren. Während ein Grossteil dieses Systems der Anwendung transparent bereitgestellt wird, ist es möglich dass man den Schreib/Lese-Status eines Konfigurationsobjekts prüfen will.&lt;br /&gt;
&lt;br /&gt;
Einträge in Konfigurationsobjekten die mithilfe von Kiosk abgeriegelt sind, werden &amp;quot;unveränderlich&amp;quot; genannt. Eine Anwendung kann nach der Unveränderlichkeit von ganzen Konfigurationsobjekten, Gruppen oder Schlüsseln, wie in diesem Beispiel gezeigt, fragen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::config();&lt;br /&gt;
&lt;br /&gt;
if ( config-&amp;gt;isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;Konfigurationsobjekt ist unveränderlich&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
KConfigGroup group(config, &amp;quot;General&amp;quot;);&lt;br /&gt;
if ( group.isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;Die Gruppe 'General' ist unveränderlich&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if ( group.entryIsImmutable(&amp;quot;URL&amp;quot;) ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;Der URL Eintrag in der Gruppe 'General' ist unveränderlich&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das kann in gewissen Situationen, wo eine Aktion ausgeführt werden soll, falls ein Objekt unveränderlich ist.&lt;br /&gt;
&lt;br /&gt;
== KConfig XT ==&lt;br /&gt;
&lt;br /&gt;
Es gibt einen Weg, gewisse Anwendungsfälle von KConfig einfacher, schneller und zuverlässiger zu  machen: KConfig XT. Im Bestimmten kann KConfig XT bei Hauptanwendungs- oder Plug-In-Konfigurationsobjekten und bei Konfigurationsdialogen und anderen Benutzeroberflächen mit diesen Werten sehr hilfreich sein. Es dokumentiert gleichzeitig auch alle verfügbaren Konfigurations-Optionen, was alle System-Administratoren und -Integratoren, die KDE benutzen so viel glücklicher macht.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[../Using_KConfig_XT_(de)|Die nächste Anleitung handelt über KConfig XT und seine Verwendung.]]&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Talk:Development/Tutorials/Plasma/ThemeDetails</id>
		<title>Talk:Development/Tutorials/Plasma/ThemeDetails</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Talk:Development/Tutorials/Plasma/ThemeDetails"/>
				<updated>2008-03-14T14:51:51Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: New page: Shouldn't this be added to Tutorials in some kind of way (e.g. &amp;quot;create Plasma themes&amp;quot;)?&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Shouldn't this be added to Tutorials in some kind of way (e.g. &amp;quot;create Plasma themes&amp;quot;)?&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials/Updating_KConfig_Files_(de)</id>
		<title>Development/Tutorials/Updating KConfig Files (de)</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials/Updating_KConfig_Files_(de)"/>
				<updated>2008-02-23T11:11:34Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:I18n/Language Navigation Bar|Development/Tutorials/Updating_KConfig_Files}}&lt;br /&gt;
{{TutorialBrowser|&lt;br /&gt;
&lt;br /&gt;
series=KConfig|&lt;br /&gt;
&lt;br /&gt;
pre=[[../KConfig| Einführung in KConfig (de)]]|&lt;br /&gt;
&lt;br /&gt;
name=Aktualisieren von KConfig Dateien|&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{improve (de)}}&lt;br /&gt;
&lt;br /&gt;
=KConfig Update=&lt;br /&gt;
&lt;br /&gt;
Diese Seite beschreibt wie ein Entwickler den KConfig-Aktualisierungs-Mechanismus (kconf_update), der in kdelibs verfügbar ist, verwenden kann, um eine bereits existierende Konfigurationsdatei eines Benutzers zu aktualisieren um sich an Änderungen die am Format der Standard-Datei vorgenommen wurden anzupassen.&lt;br /&gt;
&lt;br /&gt;
==Warum sollte man Kconfig Update Benutzen?==&lt;br /&gt;
&lt;br /&gt;
..todo&lt;br /&gt;
&lt;br /&gt;
Over time applications sometimes need to rearrange the way configuration options are stored. Since such an update shouldn't influence the configuration options that the user has selected, the application must take care that the options stored in the old way will still be honored.&lt;br /&gt;
&lt;br /&gt;
What used to happen is that the application looks up both the old and the&lt;br /&gt;
new configuration option and then decides which one to use. This method has several drawbacks:&lt;br /&gt;
* The application may need to read more configuration files than strictly needed, resulting in a slower startup.&lt;br /&gt;
* The application becomes bigger with code that will only be used once.&lt;br /&gt;
&lt;br /&gt;
kconf_update addresses these problems by offering a framework to update configuration files without adding code to the application itself.&lt;br /&gt;
&lt;br /&gt;
==How it works==&lt;br /&gt;
&lt;br /&gt;
Applications can install so called &amp;quot;update files&amp;quot; under&lt;br /&gt;
{{Path|$KDEDIR/share/apps/kconf_update.}} An update file has {{Path|.upd}} as an extension and contains instructions for transferring/converting configuration information from one place to another.&lt;br /&gt;
&lt;br /&gt;
Updating the configuration happens automatically, either when KDE gets started&lt;br /&gt;
or when kded detects a new update file in the above mentioned location.&lt;br /&gt;
&lt;br /&gt;
Update files are separated into sections. Each section has an id. When a&lt;br /&gt;
section describing a configuration change has been applied, the id will be&lt;br /&gt;
stored in the file {{Path|kconf_updaterc}}. This information is used to make sure that a configuration update is only performed once.&lt;br /&gt;
&lt;br /&gt;
If you overwrite an existing update file with a new version that contains a&lt;br /&gt;
new section, only the update instructions from this extra section will be&lt;br /&gt;
performed.&lt;br /&gt;
&lt;br /&gt;
==File format of the update file==&lt;br /&gt;
&lt;br /&gt;
Empty lines or lines that start with '#' are considered comments&lt;br /&gt;
Commas (,) are used to seperate fields and may not occur as part&lt;br /&gt;
of any field and all of the keywords are case-sensitive, i.e. you&lt;br /&gt;
cannot say &amp;quot;key&amp;quot; instead of &amp;quot;Key&amp;quot; for example.&lt;br /&gt;
&lt;br /&gt;
For the rest the file is parsed and executed sequentially from top to bottom.&lt;br /&gt;
Each line can contain one entry. The following entries are recognized:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;Id=&amp;lt;id&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With &amp;lt;id&amp;gt; identifying the group of update entries that follows. Once a group&lt;br /&gt;
of entries have been applied, their &amp;lt;id&amp;gt; is stored and this group of entries&lt;br /&gt;
will not be applied again.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
File=&amp;lt;oldfile&amp;gt;,&amp;lt;newfile&amp;gt;&lt;br /&gt;
File=&amp;lt;oldfile&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that configuration information is read from &amp;lt;oldfile&amp;gt; and written&lt;br /&gt;
to &amp;lt;newfile&amp;gt;. If you only specify &amp;lt;oldfile&amp;gt;, the information is read from&lt;br /&gt;
and as written to &amp;lt;oldfile&amp;gt;. Note that if the file does not exist&lt;br /&gt;
at the time kconf_update first checks, no related update will be performed.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Script=&amp;lt;script&amp;gt;[,&amp;lt;interpreter&amp;gt;]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;script&amp;gt; is the program that will be performing the updates. All entries from &amp;lt;oldfile&amp;gt; are piped into &amp;lt;script&amp;gt;. The output of &amp;lt;script&amp;gt;is used as new entries for &amp;lt;newfile&amp;gt;. Existing entries can be deleted by adding lines with &amp;quot;# DELETE [group]key&amp;quot; in the output of the script. To delete a whole group use &amp;quot;# DELETEGROUP [group]&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
There are two types of kconf_update scripts:&lt;br /&gt;
*Non-Compiled&lt;br /&gt;
*Compiled&lt;br /&gt;
&lt;br /&gt;
If &amp;lt;script&amp;gt; is written in a non-compiled language (such as ruby or perl), then it should be installed into &lt;br /&gt;
{{Path|${KCONF_UPDATE_INSTALL_DIR} }}. &lt;br /&gt;
&lt;br /&gt;
If &amp;lt;script&amp;gt; is a compiled application, it should be installed in {{Path|${BIN_INSTALL_DIR}/kconf_update_bin}}&lt;br /&gt;
&lt;br /&gt;
If the script command is issued after a &amp;quot;Group&amp;quot; command the behavior is slightly&lt;br /&gt;
different:&lt;br /&gt;
&lt;br /&gt;
All entries from &amp;lt;oldfile&amp;gt; in &amp;lt;oldgroup&amp;gt; are piped into &amp;lt;script&amp;gt;. The output&lt;br /&gt;
of script is used as new entries for &amp;lt;newfile&amp;gt; in &amp;lt;newgroup&amp;gt;, unless a different&lt;br /&gt;
group is specified with &amp;quot;[group]&amp;quot;. Existing entries can be deleted from&lt;br /&gt;
&amp;lt;oldgroup&amp;gt; by adding lines with &amp;quot;# DELETE key&amp;quot; in the output of the script.·&lt;br /&gt;
To delete &amp;lt;oldgroup&amp;gt; use &amp;quot;# DELETEGROUP&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;interpreter&amp;gt; can be something like &amp;quot;perl&amp;quot; or &amp;quot;ruby&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
It is also possible to have a script command without specifying &amp;lt;oldfile&amp;gt; or &amp;lt;newfile&amp;gt;. In that case the script is run but it will not be fed any input and its output will simply be discarded.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ScriptArguments=&amp;lt;arguments&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If specified, the arguments will be passed to &amp;lt;script&amp;gt;.&lt;br /&gt;
IMPORTANT: It has to be specified before Script=.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Group=&amp;lt;oldgroup&amp;gt;,&amp;lt;newgroup&amp;gt;&lt;br /&gt;
Group=&amp;lt;oldgroup&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that configuration information is read from the group &amp;lt;oldgroup&amp;gt;&lt;br /&gt;
and written to &amp;lt;newgroup&amp;gt;. If you only specify &amp;lt;oldgroup&amp;gt;, the information&lt;br /&gt;
is read from as well as written to &amp;lt;oldgroup&amp;gt;. You can use &amp;lt;default&amp;gt; to&lt;br /&gt;
specify keys that are not under any group.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
RemoveGroup=&amp;lt;oldgroup&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that &amp;lt;oldgroup&amp;gt; is removed entirely. This can be used&lt;br /&gt;
to remove obsolete entries or to force a revert to default values.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Options=&amp;lt;option1&amp;gt;, &amp;lt;option2&amp;gt;,&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With this entry you can specify options that apply to the next &amp;quot;Script&amp;quot;,&lt;br /&gt;
&amp;quot;Key&amp;quot; or &amp;quot;AllKeys&amp;quot; entry (only to the first!). Possible options are:&lt;br /&gt;
&lt;br /&gt;
*&amp;quot;copy&amp;quot; Copy the configuration item instead of moving it. This means that&lt;br /&gt;
the configuration item will not be deleted from &amp;lt;oldfile&amp;gt;/&amp;lt;oldgroup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;quot;overwrite&amp;quot; Normally, a configuration item is not moved if an item with the&lt;br /&gt;
new name already exists. When this option is specified the old configuration item will overwrite any existing item.&lt;br /&gt;
&lt;br /&gt;
Key=&amp;lt;oldkey&amp;gt;,&amp;lt;newkey&amp;gt;&lt;br /&gt;
Key=&amp;lt;oldkey&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that configuration information is read from the key &amp;lt;oldkey&amp;gt;&lt;br /&gt;
and written to &amp;lt;newkey&amp;gt;. If you only specify &amp;lt;oldkey&amp;gt;, the information&lt;br /&gt;
is read from as well as written to &amp;lt;oldkey&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
AllKeys&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that all configuration information in the selected group should&lt;br /&gt;
be moved (All keys).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
AllGroups&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that all configuration information from all keys in ALL·&lt;br /&gt;
groups should be moved.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
RemoveKey=&amp;lt;oldkey&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that &amp;lt;oldkey&amp;gt; is removed from the selected group. This can be used&lt;br /&gt;
to remove obsolete entries or to force a revert to default values.&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials/Updating_KConfig_Files_(de)</id>
		<title>Development/Tutorials/Updating KConfig Files (de)</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials/Updating_KConfig_Files_(de)"/>
				<updated>2008-02-23T11:09:48Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: Initial Translation&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:I18n/Language Navigation Bar|Development/Tutorials/Updating_KConfig_Files}}&lt;br /&gt;
{{TutorialBrowser|&lt;br /&gt;
&lt;br /&gt;
series=KConfig|&lt;br /&gt;
&lt;br /&gt;
pre=[[../KConfig| Einführung in KConfig]]|&lt;br /&gt;
&lt;br /&gt;
name=Aktualisieren von KConfig Dateien|&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=KConfig Update=&lt;br /&gt;
&lt;br /&gt;
Diese Seite beschreibt wie ein Entwickler den KConfig-Aktualisierungs-Mechanismus (kconf_update), der in kdelibs verfügbar ist, verwenden kann, um eine bereits existierende Konfigurationsdatei eines Benutzers zu aktualisieren um sich an Änderungen die am Format der Standard-Datei vorgenommen wurden anzupassen.&lt;br /&gt;
&lt;br /&gt;
==Warum sollte man Kconfig Update Benutzen?==&lt;br /&gt;
&lt;br /&gt;
...todo&lt;br /&gt;
&lt;br /&gt;
Over time applications sometimes need to rearrange the way configuration options are stored. Since such an update shouldn't influence the configuration options that the user has selected, the application must take care that the options stored in the old way will still be honored.&lt;br /&gt;
&lt;br /&gt;
What used to happen is that the application looks up both the old and the&lt;br /&gt;
new configuration option and then decides which one to use. This method has several drawbacks:&lt;br /&gt;
* The application may need to read more configuration files than strictly needed, resulting in a slower startup.&lt;br /&gt;
* The application becomes bigger with code that will only be used once.&lt;br /&gt;
&lt;br /&gt;
kconf_update addresses these problems by offering a framework to update configuration files without adding code to the application itself.&lt;br /&gt;
&lt;br /&gt;
==How it works==&lt;br /&gt;
&lt;br /&gt;
Applications can install so called &amp;quot;update files&amp;quot; under&lt;br /&gt;
{{Path|$KDEDIR/share/apps/kconf_update.}} An update file has {{Path|.upd}} as an extension and contains instructions for transferring/converting configuration information from one place to another.&lt;br /&gt;
&lt;br /&gt;
Updating the configuration happens automatically, either when KDE gets started&lt;br /&gt;
or when kded detects a new update file in the above mentioned location.&lt;br /&gt;
&lt;br /&gt;
Update files are separated into sections. Each section has an id. When a&lt;br /&gt;
section describing a configuration change has been applied, the id will be&lt;br /&gt;
stored in the file {{Path|kconf_updaterc}}. This information is used to make sure that a configuration update is only performed once.&lt;br /&gt;
&lt;br /&gt;
If you overwrite an existing update file with a new version that contains a&lt;br /&gt;
new section, only the update instructions from this extra section will be&lt;br /&gt;
performed.&lt;br /&gt;
&lt;br /&gt;
==File format of the update file==&lt;br /&gt;
&lt;br /&gt;
Empty lines or lines that start with '#' are considered comments&lt;br /&gt;
Commas (,) are used to seperate fields and may not occur as part&lt;br /&gt;
of any field and all of the keywords are case-sensitive, i.e. you&lt;br /&gt;
cannot say &amp;quot;key&amp;quot; instead of &amp;quot;Key&amp;quot; for example.&lt;br /&gt;
&lt;br /&gt;
For the rest the file is parsed and executed sequentially from top to bottom.&lt;br /&gt;
Each line can contain one entry. The following entries are recognized:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;Id=&amp;lt;id&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With &amp;lt;id&amp;gt; identifying the group of update entries that follows. Once a group&lt;br /&gt;
of entries have been applied, their &amp;lt;id&amp;gt; is stored and this group of entries&lt;br /&gt;
will not be applied again.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
File=&amp;lt;oldfile&amp;gt;,&amp;lt;newfile&amp;gt;&lt;br /&gt;
File=&amp;lt;oldfile&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that configuration information is read from &amp;lt;oldfile&amp;gt; and written&lt;br /&gt;
to &amp;lt;newfile&amp;gt;. If you only specify &amp;lt;oldfile&amp;gt;, the information is read from&lt;br /&gt;
and as written to &amp;lt;oldfile&amp;gt;. Note that if the file does not exist&lt;br /&gt;
at the time kconf_update first checks, no related update will be performed.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Script=&amp;lt;script&amp;gt;[,&amp;lt;interpreter&amp;gt;]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;script&amp;gt; is the program that will be performing the updates. All entries from &amp;lt;oldfile&amp;gt; are piped into &amp;lt;script&amp;gt;. The output of &amp;lt;script&amp;gt;is used as new entries for &amp;lt;newfile&amp;gt;. Existing entries can be deleted by adding lines with &amp;quot;# DELETE [group]key&amp;quot; in the output of the script. To delete a whole group use &amp;quot;# DELETEGROUP [group]&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
There are two types of kconf_update scripts:&lt;br /&gt;
*Non-Compiled&lt;br /&gt;
*Compiled&lt;br /&gt;
&lt;br /&gt;
If &amp;lt;script&amp;gt; is written in a non-compiled language (such as ruby or perl), then it should be installed into &lt;br /&gt;
{{Path|${KCONF_UPDATE_INSTALL_DIR} }}. &lt;br /&gt;
&lt;br /&gt;
If &amp;lt;script&amp;gt; is a compiled application, it should be installed in {{Path|${BIN_INSTALL_DIR}/kconf_update_bin}}&lt;br /&gt;
&lt;br /&gt;
If the script command is issued after a &amp;quot;Group&amp;quot; command the behavior is slightly&lt;br /&gt;
different:&lt;br /&gt;
&lt;br /&gt;
All entries from &amp;lt;oldfile&amp;gt; in &amp;lt;oldgroup&amp;gt; are piped into &amp;lt;script&amp;gt;. The output&lt;br /&gt;
of script is used as new entries for &amp;lt;newfile&amp;gt; in &amp;lt;newgroup&amp;gt;, unless a different&lt;br /&gt;
group is specified with &amp;quot;[group]&amp;quot;. Existing entries can be deleted from&lt;br /&gt;
&amp;lt;oldgroup&amp;gt; by adding lines with &amp;quot;# DELETE key&amp;quot; in the output of the script.·&lt;br /&gt;
To delete &amp;lt;oldgroup&amp;gt; use &amp;quot;# DELETEGROUP&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;interpreter&amp;gt; can be something like &amp;quot;perl&amp;quot; or &amp;quot;ruby&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
It is also possible to have a script command without specifying &amp;lt;oldfile&amp;gt; or &amp;lt;newfile&amp;gt;. In that case the script is run but it will not be fed any input and its output will simply be discarded.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ScriptArguments=&amp;lt;arguments&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If specified, the arguments will be passed to &amp;lt;script&amp;gt;.&lt;br /&gt;
IMPORTANT: It has to be specified before Script=.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Group=&amp;lt;oldgroup&amp;gt;,&amp;lt;newgroup&amp;gt;&lt;br /&gt;
Group=&amp;lt;oldgroup&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that configuration information is read from the group &amp;lt;oldgroup&amp;gt;&lt;br /&gt;
and written to &amp;lt;newgroup&amp;gt;. If you only specify &amp;lt;oldgroup&amp;gt;, the information&lt;br /&gt;
is read from as well as written to &amp;lt;oldgroup&amp;gt;. You can use &amp;lt;default&amp;gt; to&lt;br /&gt;
specify keys that are not under any group.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
RemoveGroup=&amp;lt;oldgroup&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that &amp;lt;oldgroup&amp;gt; is removed entirely. This can be used&lt;br /&gt;
to remove obsolete entries or to force a revert to default values.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Options=&amp;lt;option1&amp;gt;, &amp;lt;option2&amp;gt;,&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With this entry you can specify options that apply to the next &amp;quot;Script&amp;quot;,&lt;br /&gt;
&amp;quot;Key&amp;quot; or &amp;quot;AllKeys&amp;quot; entry (only to the first!). Possible options are:&lt;br /&gt;
&lt;br /&gt;
*&amp;quot;copy&amp;quot; Copy the configuration item instead of moving it. This means that&lt;br /&gt;
the configuration item will not be deleted from &amp;lt;oldfile&amp;gt;/&amp;lt;oldgroup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;quot;overwrite&amp;quot; Normally, a configuration item is not moved if an item with the&lt;br /&gt;
new name already exists. When this option is specified the old configuration item will overwrite any existing item.&lt;br /&gt;
&lt;br /&gt;
Key=&amp;lt;oldkey&amp;gt;,&amp;lt;newkey&amp;gt;&lt;br /&gt;
Key=&amp;lt;oldkey&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that configuration information is read from the key &amp;lt;oldkey&amp;gt;&lt;br /&gt;
and written to &amp;lt;newkey&amp;gt;. If you only specify &amp;lt;oldkey&amp;gt;, the information&lt;br /&gt;
is read from as well as written to &amp;lt;oldkey&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
AllKeys&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that all configuration information in the selected group should&lt;br /&gt;
be moved (All keys).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
AllGroups&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that all configuration information from all keys in ALL·&lt;br /&gt;
groups should be moved.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
RemoveKey=&amp;lt;oldkey&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that &amp;lt;oldkey&amp;gt; is removed from the selected group. This can be used&lt;br /&gt;
to remove obsolete entries or to force a revert to default values.&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials/KConfig_(de)</id>
		<title>Development/Tutorials/KConfig (de)</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials/KConfig_(de)"/>
				<updated>2008-02-23T10:59:47Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: /* Die KConfig Klasse */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:I18n/Language Navigation Bar|Development/Tutorials/KConfig}}&lt;br /&gt;
&lt;br /&gt;
{{TutorialBrowser (de)|&lt;br /&gt;
&lt;br /&gt;
series=KConfig|&lt;br /&gt;
&lt;br /&gt;
name=Einführung in KConfig|&lt;br /&gt;
&lt;br /&gt;
pre=Keine|&lt;br /&gt;
&lt;br /&gt;
next=[[../Using_KConfig_XT (de)|Benutzen von KConfig XT]]|&lt;br /&gt;
&lt;br /&gt;
reading=Keine&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{improve (de)}}&lt;br /&gt;
&lt;br /&gt;
== Zusammenfassung ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dieser Artikel beschäftigt sich mir dem KDE Einstellungdaten-System, angefangen mit einer Übersicht über den grundlegenden Aufbau aus der Sicht eines Entwicklers. Es wirft ausserdem einen Blick auf jede der Klassen, die für die Entwicklung von Anwendungen relevant sind und fährt dann mit kiosk (Benutzer- und Gruppenprofile) Integration fort.&lt;br /&gt;
&lt;br /&gt;
== Grundlegender Aufbau ==&lt;br /&gt;
&lt;br /&gt;
KConfig ist ausgelegt um das Konzept vom eigentlichen Speichern und Auffinden von Konfigurationsdaten hinter eine Programmierschnittstelle zu abstrahieren die es ermöglicht, auf einfache Weise Informationen abzurufen und zu setzen. Wo oder in welcher Form Daten gespeichert werden ist für eine Anwendung die KConfig benutzt irrelevant.&lt;br /&gt;
&lt;br /&gt;
Das behält alle KDE Anwendungen konsistent in ihrer Art, Konfigurationen handzuhaben und nimmt einem Anwendungs-Entwickler die Arbeit so ein System von Grund auf neu zu schreiben, was ein sehr fehleranfälliger Prozess sein kann.&lt;br /&gt;
&lt;br /&gt;
Jedes KConfig Objekt verkörpert ein einziges Konfigurationsobjekt. Jedes Konfigurationsobjekt ist durch seinen einzigartigen Namen gekennzeichnet und kann von mehreren lokalen oder externen Daten oder Services gelesen werden. Jede Anwendung hat standardmässig ein zugehöriges Konfigurationsobjekt und es gibt auch ein globales Konfigurationsobjekt.&lt;br /&gt;
&lt;br /&gt;
Diese Konfigurationsobjekte sind nach einer zweistufigen Hierarchie getrennt: Gruppen und Schlüssel. Ein Konfigurationsobjekt kann eine beliebige Anzahl an Gruppen haben und jede Gruppe kann einen oder mehrere Schlüssel mit zugehörigen Werten haben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die gespeicherten Werte können aus beliebig vielen verschiedenen Datentypen bestehen. Sie werden gespeichert und abgerufen als das Objekt selbst. Zum Beispiel wird ein {{qt|QObject}}-Objekt direkt einem Konfigurationsobjekt übergeben, wenn es einen Farbwert speichert und wenn ein Farbwert abgerufen wird, wird ein {{qt|QObject}}-Objekt zurückgegeben.&lt;br /&gt;
&lt;br /&gt;
Anwendungen selbst müssen sich deshalb nicht um das Gliedern und Entgliedern von Objekten kümmern.&lt;br /&gt;
&lt;br /&gt;
== Die KConfig Klasse ==&lt;br /&gt;
&lt;br /&gt;
Das {{class|KConfig}}-Objekt wird benutzt um ein bestehendes Konfigurationsobjekt anzusteuern. Es gibt eine Reihe von Möglichkeiten ein Konfigurationsobjekt zu erstellen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
// ein einfaches, altes lesen/schreiben Konfigurationsobjekt&lt;br /&gt;
KConfig config(&amp;quot;myapprc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// eine bestimmte Datei im Dateisystem&lt;br /&gt;
// currently must be an INI style file&lt;br /&gt;
KConfig fullPath(&amp;quot;/etc/kderc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// nicht mit globalen Werten verflochten&lt;br /&gt;
KConfig globalFree( &amp;quot;localsrc&amp;quot;, KConfig::NoGlobals );&lt;br /&gt;
&lt;br /&gt;
// nicht mit globalen Werten orde der $KDEDIRS Hierarchie verflochten&lt;br /&gt;
KConfig simpleConfig( &amp;quot;simplerc&amp;quot;, KConfig::SimpleConfig );&lt;br /&gt;
&lt;br /&gt;
// Komponenten-spezifische Konfiguration, in diesem Fall ein Plugin&lt;br /&gt;
KConfig pluginConfig( componentData(), &amp;quot;pluginrc&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
// Ausserhalb der normalen Konfigurations-Ressource&lt;br /&gt;
KConfig dataResource( &amp;quot;data&amp;quot;, &amp;quot;myapp/somefile&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{note (de)|wie soll &amp;quot;merged&amp;quot; in den folgenden Fällen übersetzt werden? &amp;lt;br&amp;gt; &amp;lt;tt&amp;gt;&amp;quot;verschmolzen&amp;quot; oder &amp;quot;verflochten&amp;quot;&amp;lt;/tt&amp;gt; &amp;lt;br&amp;gt; der Anwendung selber transparent&amp;quot; tönt auch nicht sehr gut}}&lt;br /&gt;
&lt;br /&gt;
Das Kconfig Objekt, das wir auf Zeile 2 erstellen ist ein gewöhnliches Konfigurationsobjekt. Wir können Werte aus ihm lesen, neue Einträge schreiben und nach verschiedenen Eigenschaften des Objekts fragen. Dieses Objekt wird aus der Konfigurations-Ressource geladen, wie es durch {{class|KStandardDirs}} bestimmt wird, das heisst, dass jede Instanz des &amp;lt;tt&amp;gt;myapprc&amp;lt;/tt&amp;gt;-Objekts in jedem der Ordner in der Konfigurations-Ressourcen-Hierarchie verschmolzen werden um die Werte zu erzeugen, die in diesem Objekt gesehen werden. So werden Systemweite und &lt;br /&gt;
pro-Benutzer/Gruppen Profile erstellt und unterstützt. Das alles geschieht der Anwendung selber transparent.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{tip| Für mehr Informationen, wie das Verschmelzen funktioniert, siehe diesen Artikel über die [[KDE System Administration/KDE_Filesystem_Hierarchy|KDE Dateisystem Hierarchie]].}}&lt;br /&gt;
&lt;br /&gt;
Auf Zeile 6 öffnen wir eine bestimmte Lokale Datei, in diesem Fall {{path|/etc/kderc}}. Das führt kein Verschmelzen von Werten aus und erwartet eine Datei im INI Format.&lt;br /&gt;
&lt;br /&gt;
Zeile 9 erzeugt ein Konfigurationsobjekt, dass nicht mit dem globalen &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt;-Konfigurationsobjekt verflochten ist,  während das Konfigurationsobjekt auf Zeile 12 zusätzlich mit keinem der Dateien in der &amp;lt;tt&amp;gt;$KDEDIRS&amp;lt;/tt&amp;gt;-Hierarchie verflochten ist. Das kann die Leistung spürbar verbessern, falls man einfach nur Werte aus einer einfachen Konfuguration liest und globale Werte keine Rolle spielen.&lt;br /&gt;
&lt;br /&gt;
Zeile 15 erzeugt ein Konfigurationsobjekt unter Benutzung des {{class|KComponentData}}-Objekts das zu einem Plugin oder einer anderen Komponente gehört. Das Plugin kann verschiedene Ordner aufweisen, die in seinen {{class|KStandardDirs}} definiert sind und das ist eine Möglichkeit sich zu versichern, dass {{class|KConfig}} das respektiert.&lt;br /&gt;
&lt;br /&gt;
Und schliesslich auf Zeile 18 erzeugen wir ein Konfigurationsobjekt, das nicht in der &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt;-Ressource sondern in der &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt;-Ressource existiert. Man kann kann auf diese Weise jede Ressource verwenden, von denen {{class|KStandardDirs}} Kenntnis hat, auch solche die während der Laufzeit hinzugefügt werden.&lt;br /&gt;
&lt;br /&gt;
=== Spezielle Konfigurationsobjekte ===&lt;br /&gt;
&lt;br /&gt;
Jede Anwendung hat sein eigenes Konfigurationsobjekt das den Namen benutzt, der von {{class|KAboutData}} bereitgestellt wird mit angehängtem &amp;quot;rc&amp;quot;. Also hätte eine Anwendung mit dem Namen &amp;quot;myapp&amp;quot; das Standard-Konfigurationsobjekt &amp;quot;myapprc&amp;quot;. Dieses Konfigurationsobjekt kann auf diese Weise aufgerufen werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KComponentData&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
#include &amp;lt;KGlobal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    // beachten sie, dass dies eigentlich ein KSharedConfig ist&lt;br /&gt;
    // mehr über diese Klasse siehe weiter unten&lt;br /&gt;
    KConfig* config = KGlobal::config();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Auf das Standard-Konfigurationsobjekt für die Anwendung wird zugegriffen, wenn kein Name definiert wurde, als das {{class|KConfig}}-Objekt erzeugt wurde. Also könnten wir stattdessen auch das tun:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    KConfig config;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zusätzlich könnte jede Komponente sein eigenes Konfigurationsobjekt haben. Auf dieses wird normalerweise durch die &amp;lt;tt&amp;gt;componentData()&amp;lt;/tt&amp;gt; des Plugins zugegriffen, anstatt durch die &amp;lt;tt&amp;gt;{{class|KGlobal}}::mainComponent()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Und schliesslich gibt es noch ein globales Konfigurationsobjekt, &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt;, das von jeder Anwendung verwendet wird. Es enthält Informationen wie die Standard-Tatenkombinationen für verschiedene Aktionen. Es wird in das Konfigurationsobjekt &amp;quot;gemischt&amp;quot; wenn der &amp;lt;tt&amp;gt;KConfig::IncludeGlobals&amp;lt;/tt&amp;gt; Bitschalter dem {{class|KConfig}} Konstruktor übergeben wird, was standardmässig der Fall ist.&lt;br /&gt;
&lt;br /&gt;
=== Allgemein nützliche Methoden ===&lt;br /&gt;
&lt;br /&gt;
Um den momentanen Zustand des Konfigurationsobjektes zu speichern, rufen wir die &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt;-Methode auf. Diese Methode wird also aufgerufen, wenn ein Objekt zerstört wird. Falls keine Änderungen gemacht wurden, oder die Ressource weist sich als nicht beschreibbar aus (Wenn der Benutzer zum Beispiel nicht genug Rechte hat, um die Datei zu bearbeiten), dann wird keine Beschäftigung der Festplatte hervorgerufen. &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; verschmilzt Änderungen die gleichzeitig von anderen Prozessen ausgeführt werden - lokale Änderungen haben aber trotzdem Vorrang.&lt;br /&gt;
&lt;br /&gt;
Wenn wir sicher gehen wollen, dass wir die aktuellsten Werte von der Festplatte haben, dann rufen wir &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt; auf, welches &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; aufruft und dann die Daten von der Festplatte aktualisiert.&lt;br /&gt;
&lt;br /&gt;
Falls wir verhindern müssen, dass das Konfigurationsobjekt bereits gemachte Änderungen nicht auf die Festplatte speichert, müssen wir &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt; aufrufen. Ein besonderer Anwendungsfall ist es, die Konfiguration zum Festplatten-Zustand zurückzusetzen indem man &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt; gefolgt von &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt; aufruft.&lt;br /&gt;
&lt;br /&gt;
Alle Gruppen in einem Konfigurationsobjekt aufzurufen ist so einfach wie hier in diesem Code-Abschnitt &amp;lt;tt&amp;gt;groupList()&amp;lt;/tt&amp;gt; aufzurufen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::mainComponent().config();&lt;br /&gt;
&lt;br /&gt;
foreach ( const QString&amp;amp; group, config.groupList() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;next group:&amp;quot; &amp;lt;&amp;lt; group;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== KSharedConfig ==&lt;br /&gt;
&lt;br /&gt;
Die {{class|KSharedConfig}} Klasse ist eine Referenz-gezählte Version von {{class|KConfig}}. Darum stellt es eine Möglichkeit bereit, das selbe Konfigurationsobjekt von unterschiedlichen Orten zu referenzieren ohne zusätzlich die Objekte trennen zu müssen oder sich um die Synchronisation des Schreibvorgangs zu kümmern, selbst wenn das Konfigurationsobjekt von verschiedenen Code-Pfaden aktualisiert wird.&lt;br /&gt;
&lt;br /&gt;
Auf ein {{class|KSharedConfig}}-Objekt zuzugreifen ist so einfach wie das hier:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KSharedConfigPtr config = KSharedConfig::openConfig();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;openConfig()&amp;lt;/tt&amp;gt; nimmt die selben Parameter wie {{class|KConfig}}'s Konstruktoren, was es einem ermöglicht zu definieren, welche Konfigurationsdatei zu öffnen und Markierungen das Verschmelzen von nicht-&amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt;-Ressourcen zu kontrollieren.  &lt;br /&gt;
&lt;br /&gt;
Es wird grundsätzlich empfohlen {{class|KSharedConfig}} anstatt {{class|KConfig}} selbst zu benutzen, und auch das Objekt, das von {{class|KComponentData}} zurückgegeben wird ist in der Tat ein {{class|KSharedConfig}}-Objekt.&lt;br /&gt;
&lt;br /&gt;
== KConfigGroup ==&lt;br /&gt;
&lt;br /&gt;
Nun da wir ein Konfigurationsobjekt haben, ist der nächste Schritt es tatsächlich zu nutzen. Das erste, das wir tun müssen, ist zu bestimmen, auf welche Gruppe von Schlüssel-/Wertepaare wir in unserem Objekt zugreifen wollen. Wir tun das, indem wir ein KConfigGroup-Objekt erstellen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig config;&lt;br /&gt;
KConfigGroup generalGroup( &amp;amp;config, &amp;quot;General&amp;quot; );&lt;br /&gt;
KConfigGroup colorsGroup = config.group( &amp;quot;Colors&amp;quot; ); // ...oder so ähnlich...&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Man kann{{class|KConfigGroup}} {{class|KConfig}}- oder {{class|KSharedConfig}}-Objekte übergeben.&lt;br /&gt;
&lt;br /&gt;
Konfigurationsgruppen können ebenfalls verschachtelt werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfigGroup subGroup1( &amp;amp;generalGroup, &amp;quot;LessGeneral&amp;quot; );&lt;br /&gt;
KConfigGroup subGroup2 = colorsGroup.group( &amp;quot;Dialogs&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Lesen von Einträgen ==&lt;br /&gt;
&lt;br /&gt;
Wenn man erst einmal ein {{class|KConfigGroup}}-Objekt erstellt hat, ist das Lesen von Einträgen ziemlich einfach:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
QString accountName = generalGroup.readEntry( &amp;quot;Account&amp;quot;,&lt;br /&gt;
                                              QString() );&lt;br /&gt;
QColor color = colorsGroup.readEntry( &amp;quot;background&amp;quot;,&lt;br /&gt;
                                      Qt::white );&lt;br /&gt;
QStringList list = generalGroup.readEntry( &amp;quot;List&amp;quot;,&lt;br /&gt;
                                           QStringList() );&lt;br /&gt;
QString path = generalGroup.readPathEntry( &amp;quot;SaveTo&amp;quot;,&lt;br /&gt;
                                           defaultPath );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wie man hier oben sehen kann, kann man Lesevorgänge von verschiedenen {{class|KConfigGroup}}-Objekten, die auf dem selben {{class|KConfig}}-Objekt erstellt wurden, problemlos mischen. Die Lese-Methoden nehmen den Schlüssel, der Gross- und Kleinschreibung unterscheidet, als erstes Argument und den Standardwert als zweites Argument. Dieses Argument bestimmt auch welche Art von Daten, also z.B. eine Farbe in Zeile 3, erwartet wird und auch die Art von Objekt, die zurückgegeben werden soll.Das zurückgegebene Objekt wird in eine {{qt|QVariant}} gepackt um diese Hexerei zu ermöglichen. &lt;br /&gt;
&lt;br /&gt;
Es gibt eine Anzahl von speziellen Methoden, zum Beispiel &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt;, das einen Datei-Systempfad zurückgibt. Es ist entscheidend, dass man &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; benutzt, wenn man nach einem Pfad fragt, das es Funktionen wie Erreichbarkeits-Profile ermöglicht richtig zu funktionieren.&lt;br /&gt;
&lt;br /&gt;
Wenn kein solcher Schlüssel im Konfigurationsobjekt existiert, dann wird stattdessen der Standardwert zurückgegeben. Falls es eine lokalisierte (d.h. in eine andere Sprache übersetzte) Version für den Schlüssel gibt, die der eingestellten Sprache entspricht, dann wird diese zurückgegeben.&lt;br /&gt;
&lt;br /&gt;
== Schreiben neuer Einträge ==&lt;br /&gt;
&lt;br /&gt;
Neue Werte zu definieren ist ähnlich einfach:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
generalGroup.writeEntry( &amp;quot;Account&amp;quot;, accountName );&lt;br /&gt;
generalGroup.writePathEntry( &amp;quot;SaveTo&amp;quot;, savePath );&lt;br /&gt;
colorGroup.writeEntry( &amp;quot;background&amp;quot;, color );&lt;br /&gt;
generalGroup.config()-&amp;gt;sync();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beachten sie die Benutzung von &amp;lt;tt&amp;gt;writePathEntry&amp;lt;/tt&amp;gt; und wie die Art von Objekt, das wir benutzen, wie zum Beispiel {{qt|QColor}} auf Zeile 3, bestimmt, wie die Daten angeordnet werden. Zusätzlich, wenn wir mit den Einträgen fertig sind, muss &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; auf das Konfigurationsobjekt ausgeführt werden, um es auf die Festplatte zu speichern. Man kann auch einfach warten, bis das Objekt zerstört wird, was falls nötig automatisch einen &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; auslöst.&lt;br /&gt;
&lt;br /&gt;
== KDesktopFile: Ein besonderer Fall ==&lt;br /&gt;
&lt;br /&gt;
Wann ist eine Konfigurationsdatei keine Konfigurationsdatei? Wenn es eine [http://freedesktop.org/wiki/Standards_2fdesktop_2dentry_2dspec Desktop-Datei] ist. Diese Dateien, die im Grunde genommen Konfigurationsdateien sind, werden benutzt um Einträge für Anwendungsmenüs, Dateitypen, Plugins und verschiedene Services.&lt;br /&gt;
&lt;br /&gt;
Wenn auf eine .desktop Datei zugegriffen wird, sollte man stattdessen die  {{class|KDesktopFile}}-Klasse verwenden, die, während eine {{class|KConfig}}-Klasse über alle oben genannten Ressourcen verfügt, über eine Anzahl von Methoden verfügt, um das Zugreifen auf Standard-Attribute dieser Dateien konsistent und zuverlässig zu machen.&lt;br /&gt;
&lt;br /&gt;
== Kiosk: Abriegelung und Benutzer-/Gruppenprofile ==&lt;br /&gt;
&lt;br /&gt;
KConfig stellt eine Reihe von leistungsstarken Abriegelungs- und Konfigurations-Definitionen bereit, insgesamt als &amp;quot;Kiosk&amp;quot; bekannt, worauf viele System-Administratoren und -Integratoren basieren. Während ein Grossteil dieses Systems der Anwendung transparent bereitgestellt wird, ist es möglich dass man den Schreib/Lese-Status eines Konfigurationsobjekts prüfen will.&lt;br /&gt;
&lt;br /&gt;
Einträge in Konfigurationsobjekten die mithilfe von Kiosk abgeriegelt sind, werden &amp;quot;unveränderlich&amp;quot; genannt. Eine Anwendung kann nach der Unveränderlichkeit von ganzen Konfigurationsobjekten, Gruppen oder Schlüsseln, wie in diesem Beispiel gezeigt, fragen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::config();&lt;br /&gt;
&lt;br /&gt;
if ( config-&amp;gt;isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;Konfigurationsobjekt ist unveränderlich&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
KConfigGroup group(config, &amp;quot;General&amp;quot;);&lt;br /&gt;
if ( group.isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;Die Gruppe 'General' ist unveränderlich&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if ( group.entryIsImmutable(&amp;quot;URL&amp;quot;) ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;Der URL Eintrag in der Gruppe 'General' ist unveränderlich&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das kann in gewissen Situationen, wo eine Aktion ausgeführt werden soll, falls ein Objekt unveränderlich ist.&lt;br /&gt;
&lt;br /&gt;
== KConfig XT ==&lt;br /&gt;
&lt;br /&gt;
Es gibt einen Weg, gewisse Anwendungsfälle von KConfig einfacher, schneller und zuverlässiger zu  machen: KConfig XT. Im Bestimmten kann KConfig XT bei Hauptanwendungs- oder Plug-In-Konfigurationsobjekten und bei Konfigurationsdialogen und anderen Benutzeroberflächen mit diesen Werten sehr hilfreich sein. Es dokumentiert gleichzeitig auch alle verfügbaren Konfigurations-Optionen, was alle System-Administratoren und -Integratoren, die KDE benutzen so viel glücklicher macht.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[../Using_KConfig_XT_(de)|Die nächste Anleitung handelt über KConfig XT und wie es zu benutzen.]]&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials/KConfig_(de)</id>
		<title>Development/Tutorials/KConfig (de)</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials/KConfig_(de)"/>
				<updated>2008-02-23T10:58:59Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: /* Die KConfig Klasse */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:I18n/Language Navigation Bar|Development/Tutorials/KConfig}}&lt;br /&gt;
&lt;br /&gt;
{{TutorialBrowser (de)|&lt;br /&gt;
&lt;br /&gt;
series=KConfig|&lt;br /&gt;
&lt;br /&gt;
name=Einführung in KConfig|&lt;br /&gt;
&lt;br /&gt;
pre=Keine|&lt;br /&gt;
&lt;br /&gt;
next=[[../Using_KConfig_XT (de)|Benutzen von KConfig XT]]|&lt;br /&gt;
&lt;br /&gt;
reading=Keine&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{improve (de)}}&lt;br /&gt;
&lt;br /&gt;
== Zusammenfassung ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dieser Artikel beschäftigt sich mir dem KDE Einstellungdaten-System, angefangen mit einer Übersicht über den grundlegenden Aufbau aus der Sicht eines Entwicklers. Es wirft ausserdem einen Blick auf jede der Klassen, die für die Entwicklung von Anwendungen relevant sind und fährt dann mit kiosk (Benutzer- und Gruppenprofile) Integration fort.&lt;br /&gt;
&lt;br /&gt;
== Grundlegender Aufbau ==&lt;br /&gt;
&lt;br /&gt;
KConfig ist ausgelegt um das Konzept vom eigentlichen Speichern und Auffinden von Konfigurationsdaten hinter eine Programmierschnittstelle zu abstrahieren die es ermöglicht, auf einfache Weise Informationen abzurufen und zu setzen. Wo oder in welcher Form Daten gespeichert werden ist für eine Anwendung die KConfig benutzt irrelevant.&lt;br /&gt;
&lt;br /&gt;
Das behält alle KDE Anwendungen konsistent in ihrer Art, Konfigurationen handzuhaben und nimmt einem Anwendungs-Entwickler die Arbeit so ein System von Grund auf neu zu schreiben, was ein sehr fehleranfälliger Prozess sein kann.&lt;br /&gt;
&lt;br /&gt;
Jedes KConfig Objekt verkörpert ein einziges Konfigurationsobjekt. Jedes Konfigurationsobjekt ist durch seinen einzigartigen Namen gekennzeichnet und kann von mehreren lokalen oder externen Daten oder Services gelesen werden. Jede Anwendung hat standardmässig ein zugehöriges Konfigurationsobjekt und es gibt auch ein globales Konfigurationsobjekt.&lt;br /&gt;
&lt;br /&gt;
Diese Konfigurationsobjekte sind nach einer zweistufigen Hierarchie getrennt: Gruppen und Schlüssel. Ein Konfigurationsobjekt kann eine beliebige Anzahl an Gruppen haben und jede Gruppe kann einen oder mehrere Schlüssel mit zugehörigen Werten haben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die gespeicherten Werte können aus beliebig vielen verschiedenen Datentypen bestehen. Sie werden gespeichert und abgerufen als das Objekt selbst. Zum Beispiel wird ein {{qt|QObject}}-Objekt direkt einem Konfigurationsobjekt übergeben, wenn es einen Farbwert speichert und wenn ein Farbwert abgerufen wird, wird ein {{qt|QObject}}-Objekt zurückgegeben.&lt;br /&gt;
&lt;br /&gt;
Anwendungen selbst müssen sich deshalb nicht um das Gliedern und Entgliedern von Objekten kümmern.&lt;br /&gt;
&lt;br /&gt;
== Die KConfig Klasse ==&lt;br /&gt;
&lt;br /&gt;
Das {{class|KConfig}}-Objekt wird benutzt um ein bestehendes Konfigurationsobjekt anzusteuern. Es gibt eine Reihe von Möglichkeiten ein Konfigurationsobjekt zu erstellen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
// ein einfaches, altes lesen/schreiben Konfigurationsobjekt&lt;br /&gt;
KConfig config(&amp;quot;myapprc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// eine bestimmte Datei im Dateisystem&lt;br /&gt;
// currently must be an INI style file&lt;br /&gt;
KConfig fullPath(&amp;quot;/etc/kderc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// nicht mit globalen Werten verflochten&lt;br /&gt;
KConfig globalFree( &amp;quot;localsrc&amp;quot;, KConfig::NoGlobals );&lt;br /&gt;
&lt;br /&gt;
// nicht mit globalen Werten orde der $KDEDIRS Hierarchie verflochten&lt;br /&gt;
KConfig simpleConfig( &amp;quot;simplerc&amp;quot;, KConfig::SimpleConfig );&lt;br /&gt;
&lt;br /&gt;
// Komponenten-spezifische Konfiguration, in diesem Fall ein Plugin&lt;br /&gt;
KConfig pluginConfig( componentData(), &amp;quot;pluginrc&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
// Ausserhalb der normalen Konfigurations-Ressource&lt;br /&gt;
KConfig dataResource( &amp;quot;data&amp;quot;, &amp;quot;myapp/somefile&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{note (de)|wie soll &amp;quot;merged&amp;quot; in den folgenden Fällen übersetzt werden? &amp;lt;br&amp;gt; &amp;lt;tt&amp;gt;&amp;quot;verschmolzen&amp;quot; oder &amp;quot;verflochten&amp;quot;&amp;lt;/tt&amp;gt; &amp;lt;br&amp;gt; der Anwendung selber transparent&amp;quot; tönt auch nicht sehr gut}}&lt;br /&gt;
&lt;br /&gt;
Das Kconfig Objekt, das wir auf Zeile 2 erstellen ist ein gewöhnliches Konfigurationsobjekt. Wir können Werte aus ihm lesen, neue Einträge schreiben und nach verschiedenen Eigenschaften des Objekts fragen. Dieses Objekt wird aus der Konfigurations-Ressource geladen, wie es durch {{class|KStandardDirs}} bestimmt wird, das heisst, dass jede Instanz des &amp;lt;tt&amp;gt;myapprc&amp;lt;/tt&amp;gt;-Objekts in jedem der Ordner in der Konfigurations-Ressourcen-Hierarchie verschmolzen werden um die Werte zu erzeugen, die in diesem Objekt gesehen werden. So werden Systemweite und &lt;br /&gt;
pro-Benutzer/Gruppen Profile erstellt und unterstützt. Das alles geschieht der Anwendung selber transparent.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{tip| Für mehr Informationen, wie das Verschmelzen funktioniert, siehe diesen Artikel über die [[KDE System Administration/KDE_Filesystem_Hierarchy|KDE Dateisystem Hierarchie]].}}&lt;br /&gt;
&lt;br /&gt;
Auf Zeile 6 öffnen wir eine bestimmte Lokale Datei, in diesem Fall {{path|/etc/kderc}}. Das führt kein verschmelzen von Werten aus und erwartet eine Datei im INI Format.&lt;br /&gt;
&lt;br /&gt;
Zeile 9 erzeugt ein Konfigurationsobjekt, dass nicht mit dem globalen &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt;-Konfigurationsobjekt verflochten ist,  während das Konfigurationsobjekt auf Zeile 12 zusätzlich mit keinem der Dateien in der &amp;lt;tt&amp;gt;$KDEDIRS&amp;lt;/tt&amp;gt;-Hierarchie verflochten ist. Das kann die Leistung spürbar verbessern, falls man einfach nur Werte aus einer einfachen Konfuguration liest und globale Werte keine Rolle spielen.&lt;br /&gt;
&lt;br /&gt;
Zeile 15 erzeugt ein Konfigurationsobjekt unter Benutzung des {{class|KComponentData}}-Objekts das zu einem Plugin oder einer anderen Komponente gehört. Das Plugin kann verschiedene Ordner aufweisen, die in seinen {{class|KStandardDirs}} definiert sind und das ist eine Möglichkeit sich zu versichern, dass {{class|KConfig}} das respektiert.&lt;br /&gt;
&lt;br /&gt;
Und schliesslich auf Zeile 18 erzeugen wir ein Konfigurationsobjekt, das nicht in der &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt;-Ressource sondern in der &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt;-Ressource existiert. Man kann kann auf diese Weise jede Ressource verwenden, von denen {{class|KStandardDirs}} Kenntnis hat, auch solche die während der Laufzeit hinzugefügt werden.&lt;br /&gt;
&lt;br /&gt;
=== Spezielle Konfigurationsobjekte ===&lt;br /&gt;
&lt;br /&gt;
Jede Anwendung hat sein eigenes Konfigurationsobjekt das den Namen benutzt, der von {{class|KAboutData}} bereitgestellt wird mit angehängtem &amp;quot;rc&amp;quot;. Also hätte eine Anwendung mit dem Namen &amp;quot;myapp&amp;quot; das Standard-Konfigurationsobjekt &amp;quot;myapprc&amp;quot;. Dieses Konfigurationsobjekt kann auf diese Weise aufgerufen werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KComponentData&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
#include &amp;lt;KGlobal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    // beachten sie, dass dies eigentlich ein KSharedConfig ist&lt;br /&gt;
    // mehr über diese Klasse siehe weiter unten&lt;br /&gt;
    KConfig* config = KGlobal::config();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Auf das Standard-Konfigurationsobjekt für die Anwendung wird zugegriffen, wenn kein Name definiert wurde, als das {{class|KConfig}}-Objekt erzeugt wurde. Also könnten wir stattdessen auch das tun:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    KConfig config;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zusätzlich könnte jede Komponente sein eigenes Konfigurationsobjekt haben. Auf dieses wird normalerweise durch die &amp;lt;tt&amp;gt;componentData()&amp;lt;/tt&amp;gt; des Plugins zugegriffen, anstatt durch die &amp;lt;tt&amp;gt;{{class|KGlobal}}::mainComponent()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Und schliesslich gibt es noch ein globales Konfigurationsobjekt, &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt;, das von jeder Anwendung verwendet wird. Es enthält Informationen wie die Standard-Tatenkombinationen für verschiedene Aktionen. Es wird in das Konfigurationsobjekt &amp;quot;gemischt&amp;quot; wenn der &amp;lt;tt&amp;gt;KConfig::IncludeGlobals&amp;lt;/tt&amp;gt; Bitschalter dem {{class|KConfig}} Konstruktor übergeben wird, was standardmässig der Fall ist.&lt;br /&gt;
&lt;br /&gt;
=== Allgemein nützliche Methoden ===&lt;br /&gt;
&lt;br /&gt;
Um den momentanen Zustand des Konfigurationsobjektes zu speichern, rufen wir die &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt;-Methode auf. Diese Methode wird also aufgerufen, wenn ein Objekt zerstört wird. Falls keine Änderungen gemacht wurden, oder die Ressource weist sich als nicht beschreibbar aus (Wenn der Benutzer zum Beispiel nicht genug Rechte hat, um die Datei zu bearbeiten), dann wird keine Beschäftigung der Festplatte hervorgerufen. &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; verschmilzt Änderungen die gleichzeitig von anderen Prozessen ausgeführt werden - lokale Änderungen haben aber trotzdem Vorrang.&lt;br /&gt;
&lt;br /&gt;
Wenn wir sicher gehen wollen, dass wir die aktuellsten Werte von der Festplatte haben, dann rufen wir &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt; auf, welches &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; aufruft und dann die Daten von der Festplatte aktualisiert.&lt;br /&gt;
&lt;br /&gt;
Falls wir verhindern müssen, dass das Konfigurationsobjekt bereits gemachte Änderungen nicht auf die Festplatte speichert, müssen wir &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt; aufrufen. Ein besonderer Anwendungsfall ist es, die Konfiguration zum Festplatten-Zustand zurückzusetzen indem man &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt; gefolgt von &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt; aufruft.&lt;br /&gt;
&lt;br /&gt;
Alle Gruppen in einem Konfigurationsobjekt aufzurufen ist so einfach wie hier in diesem Code-Abschnitt &amp;lt;tt&amp;gt;groupList()&amp;lt;/tt&amp;gt; aufzurufen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::mainComponent().config();&lt;br /&gt;
&lt;br /&gt;
foreach ( const QString&amp;amp; group, config.groupList() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;next group:&amp;quot; &amp;lt;&amp;lt; group;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== KSharedConfig ==&lt;br /&gt;
&lt;br /&gt;
Die {{class|KSharedConfig}} Klasse ist eine Referenz-gezählte Version von {{class|KConfig}}. Darum stellt es eine Möglichkeit bereit, das selbe Konfigurationsobjekt von unterschiedlichen Orten zu referenzieren ohne zusätzlich die Objekte trennen zu müssen oder sich um die Synchronisation des Schreibvorgangs zu kümmern, selbst wenn das Konfigurationsobjekt von verschiedenen Code-Pfaden aktualisiert wird.&lt;br /&gt;
&lt;br /&gt;
Auf ein {{class|KSharedConfig}}-Objekt zuzugreifen ist so einfach wie das hier:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KSharedConfigPtr config = KSharedConfig::openConfig();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;openConfig()&amp;lt;/tt&amp;gt; nimmt die selben Parameter wie {{class|KConfig}}'s Konstruktoren, was es einem ermöglicht zu definieren, welche Konfigurationsdatei zu öffnen und Markierungen das Verschmelzen von nicht-&amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt;-Ressourcen zu kontrollieren.  &lt;br /&gt;
&lt;br /&gt;
Es wird grundsätzlich empfohlen {{class|KSharedConfig}} anstatt {{class|KConfig}} selbst zu benutzen, und auch das Objekt, das von {{class|KComponentData}} zurückgegeben wird ist in der Tat ein {{class|KSharedConfig}}-Objekt.&lt;br /&gt;
&lt;br /&gt;
== KConfigGroup ==&lt;br /&gt;
&lt;br /&gt;
Nun da wir ein Konfigurationsobjekt haben, ist der nächste Schritt es tatsächlich zu nutzen. Das erste, das wir tun müssen, ist zu bestimmen, auf welche Gruppe von Schlüssel-/Wertepaare wir in unserem Objekt zugreifen wollen. Wir tun das, indem wir ein KConfigGroup-Objekt erstellen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig config;&lt;br /&gt;
KConfigGroup generalGroup( &amp;amp;config, &amp;quot;General&amp;quot; );&lt;br /&gt;
KConfigGroup colorsGroup = config.group( &amp;quot;Colors&amp;quot; ); // ...oder so ähnlich...&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Man kann{{class|KConfigGroup}} {{class|KConfig}}- oder {{class|KSharedConfig}}-Objekte übergeben.&lt;br /&gt;
&lt;br /&gt;
Konfigurationsgruppen können ebenfalls verschachtelt werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfigGroup subGroup1( &amp;amp;generalGroup, &amp;quot;LessGeneral&amp;quot; );&lt;br /&gt;
KConfigGroup subGroup2 = colorsGroup.group( &amp;quot;Dialogs&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Lesen von Einträgen ==&lt;br /&gt;
&lt;br /&gt;
Wenn man erst einmal ein {{class|KConfigGroup}}-Objekt erstellt hat, ist das Lesen von Einträgen ziemlich einfach:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
QString accountName = generalGroup.readEntry( &amp;quot;Account&amp;quot;,&lt;br /&gt;
                                              QString() );&lt;br /&gt;
QColor color = colorsGroup.readEntry( &amp;quot;background&amp;quot;,&lt;br /&gt;
                                      Qt::white );&lt;br /&gt;
QStringList list = generalGroup.readEntry( &amp;quot;List&amp;quot;,&lt;br /&gt;
                                           QStringList() );&lt;br /&gt;
QString path = generalGroup.readPathEntry( &amp;quot;SaveTo&amp;quot;,&lt;br /&gt;
                                           defaultPath );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wie man hier oben sehen kann, kann man Lesevorgänge von verschiedenen {{class|KConfigGroup}}-Objekten, die auf dem selben {{class|KConfig}}-Objekt erstellt wurden, problemlos mischen. Die Lese-Methoden nehmen den Schlüssel, der Gross- und Kleinschreibung unterscheidet, als erstes Argument und den Standardwert als zweites Argument. Dieses Argument bestimmt auch welche Art von Daten, also z.B. eine Farbe in Zeile 3, erwartet wird und auch die Art von Objekt, die zurückgegeben werden soll.Das zurückgegebene Objekt wird in eine {{qt|QVariant}} gepackt um diese Hexerei zu ermöglichen. &lt;br /&gt;
&lt;br /&gt;
Es gibt eine Anzahl von speziellen Methoden, zum Beispiel &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt;, das einen Datei-Systempfad zurückgibt. Es ist entscheidend, dass man &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; benutzt, wenn man nach einem Pfad fragt, das es Funktionen wie Erreichbarkeits-Profile ermöglicht richtig zu funktionieren.&lt;br /&gt;
&lt;br /&gt;
Wenn kein solcher Schlüssel im Konfigurationsobjekt existiert, dann wird stattdessen der Standardwert zurückgegeben. Falls es eine lokalisierte (d.h. in eine andere Sprache übersetzte) Version für den Schlüssel gibt, die der eingestellten Sprache entspricht, dann wird diese zurückgegeben.&lt;br /&gt;
&lt;br /&gt;
== Schreiben neuer Einträge ==&lt;br /&gt;
&lt;br /&gt;
Neue Werte zu definieren ist ähnlich einfach:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
generalGroup.writeEntry( &amp;quot;Account&amp;quot;, accountName );&lt;br /&gt;
generalGroup.writePathEntry( &amp;quot;SaveTo&amp;quot;, savePath );&lt;br /&gt;
colorGroup.writeEntry( &amp;quot;background&amp;quot;, color );&lt;br /&gt;
generalGroup.config()-&amp;gt;sync();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beachten sie die Benutzung von &amp;lt;tt&amp;gt;writePathEntry&amp;lt;/tt&amp;gt; und wie die Art von Objekt, das wir benutzen, wie zum Beispiel {{qt|QColor}} auf Zeile 3, bestimmt, wie die Daten angeordnet werden. Zusätzlich, wenn wir mit den Einträgen fertig sind, muss &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; auf das Konfigurationsobjekt ausgeführt werden, um es auf die Festplatte zu speichern. Man kann auch einfach warten, bis das Objekt zerstört wird, was falls nötig automatisch einen &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; auslöst.&lt;br /&gt;
&lt;br /&gt;
== KDesktopFile: Ein besonderer Fall ==&lt;br /&gt;
&lt;br /&gt;
Wann ist eine Konfigurationsdatei keine Konfigurationsdatei? Wenn es eine [http://freedesktop.org/wiki/Standards_2fdesktop_2dentry_2dspec Desktop-Datei] ist. Diese Dateien, die im Grunde genommen Konfigurationsdateien sind, werden benutzt um Einträge für Anwendungsmenüs, Dateitypen, Plugins und verschiedene Services.&lt;br /&gt;
&lt;br /&gt;
Wenn auf eine .desktop Datei zugegriffen wird, sollte man stattdessen die  {{class|KDesktopFile}}-Klasse verwenden, die, während eine {{class|KConfig}}-Klasse über alle oben genannten Ressourcen verfügt, über eine Anzahl von Methoden verfügt, um das Zugreifen auf Standard-Attribute dieser Dateien konsistent und zuverlässig zu machen.&lt;br /&gt;
&lt;br /&gt;
== Kiosk: Abriegelung und Benutzer-/Gruppenprofile ==&lt;br /&gt;
&lt;br /&gt;
KConfig stellt eine Reihe von leistungsstarken Abriegelungs- und Konfigurations-Definitionen bereit, insgesamt als &amp;quot;Kiosk&amp;quot; bekannt, worauf viele System-Administratoren und -Integratoren basieren. Während ein Grossteil dieses Systems der Anwendung transparent bereitgestellt wird, ist es möglich dass man den Schreib/Lese-Status eines Konfigurationsobjekts prüfen will.&lt;br /&gt;
&lt;br /&gt;
Einträge in Konfigurationsobjekten die mithilfe von Kiosk abgeriegelt sind, werden &amp;quot;unveränderlich&amp;quot; genannt. Eine Anwendung kann nach der Unveränderlichkeit von ganzen Konfigurationsobjekten, Gruppen oder Schlüsseln, wie in diesem Beispiel gezeigt, fragen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::config();&lt;br /&gt;
&lt;br /&gt;
if ( config-&amp;gt;isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;Konfigurationsobjekt ist unveränderlich&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
KConfigGroup group(config, &amp;quot;General&amp;quot;);&lt;br /&gt;
if ( group.isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;Die Gruppe 'General' ist unveränderlich&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if ( group.entryIsImmutable(&amp;quot;URL&amp;quot;) ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;Der URL Eintrag in der Gruppe 'General' ist unveränderlich&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das kann in gewissen Situationen, wo eine Aktion ausgeführt werden soll, falls ein Objekt unveränderlich ist.&lt;br /&gt;
&lt;br /&gt;
== KConfig XT ==&lt;br /&gt;
&lt;br /&gt;
Es gibt einen Weg, gewisse Anwendungsfälle von KConfig einfacher, schneller und zuverlässiger zu  machen: KConfig XT. Im Bestimmten kann KConfig XT bei Hauptanwendungs- oder Plug-In-Konfigurationsobjekten und bei Konfigurationsdialogen und anderen Benutzeroberflächen mit diesen Werten sehr hilfreich sein. Es dokumentiert gleichzeitig auch alle verfügbaren Konfigurations-Optionen, was alle System-Administratoren und -Integratoren, die KDE benutzen so viel glücklicher macht.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[../Using_KConfig_XT_(de)|Die nächste Anleitung handelt über KConfig XT und wie es zu benutzen.]]&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials/KConfig_(de)</id>
		<title>Development/Tutorials/KConfig (de)</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials/KConfig_(de)"/>
				<updated>2008-02-23T10:57:35Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: /* Grundlegender Aufbau */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:I18n/Language Navigation Bar|Development/Tutorials/KConfig}}&lt;br /&gt;
&lt;br /&gt;
{{TutorialBrowser (de)|&lt;br /&gt;
&lt;br /&gt;
series=KConfig|&lt;br /&gt;
&lt;br /&gt;
name=Einführung in KConfig|&lt;br /&gt;
&lt;br /&gt;
pre=Keine|&lt;br /&gt;
&lt;br /&gt;
next=[[../Using_KConfig_XT (de)|Benutzen von KConfig XT]]|&lt;br /&gt;
&lt;br /&gt;
reading=Keine&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{improve (de)}}&lt;br /&gt;
&lt;br /&gt;
== Zusammenfassung ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dieser Artikel beschäftigt sich mir dem KDE Einstellungdaten-System, angefangen mit einer Übersicht über den grundlegenden Aufbau aus der Sicht eines Entwicklers. Es wirft ausserdem einen Blick auf jede der Klassen, die für die Entwicklung von Anwendungen relevant sind und fährt dann mit kiosk (Benutzer- und Gruppenprofile) Integration fort.&lt;br /&gt;
&lt;br /&gt;
== Grundlegender Aufbau ==&lt;br /&gt;
&lt;br /&gt;
KConfig ist ausgelegt um das Konzept vom eigentlichen Speichern und Auffinden von Konfigurationsdaten hinter eine Programmierschnittstelle zu abstrahieren die es ermöglicht, auf einfache Weise Informationen abzurufen und zu setzen. Wo oder in welcher Form Daten gespeichert werden ist für eine Anwendung die KConfig benutzt irrelevant.&lt;br /&gt;
&lt;br /&gt;
Das behält alle KDE Anwendungen konsistent in ihrer Art, Konfigurationen handzuhaben und nimmt einem Anwendungs-Entwickler die Arbeit so ein System von Grund auf neu zu schreiben, was ein sehr fehleranfälliger Prozess sein kann.&lt;br /&gt;
&lt;br /&gt;
Jedes KConfig Objekt verkörpert ein einziges Konfigurationsobjekt. Jedes Konfigurationsobjekt ist durch seinen einzigartigen Namen gekennzeichnet und kann von mehreren lokalen oder externen Daten oder Services gelesen werden. Jede Anwendung hat standardmässig ein zugehöriges Konfigurationsobjekt und es gibt auch ein globales Konfigurationsobjekt.&lt;br /&gt;
&lt;br /&gt;
Diese Konfigurationsobjekte sind nach einer zweistufigen Hierarchie getrennt: Gruppen und Schlüssel. Ein Konfigurationsobjekt kann eine beliebige Anzahl an Gruppen haben und jede Gruppe kann einen oder mehrere Schlüssel mit zugehörigen Werten haben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die gespeicherten Werte können aus beliebig vielen verschiedenen Datentypen bestehen. Sie werden gespeichert und abgerufen als das Objekt selbst. Zum Beispiel wird ein {{qt|QObject}}-Objekt direkt einem Konfigurationsobjekt übergeben, wenn es einen Farbwert speichert und wenn ein Farbwert abgerufen wird, wird ein {{qt|QObject}}-Objekt zurückgegeben.&lt;br /&gt;
&lt;br /&gt;
Anwendungen selbst müssen sich deshalb nicht um das Gliedern und Entgliedern von Objekten kümmern.&lt;br /&gt;
&lt;br /&gt;
== Die KConfig Klasse ==&lt;br /&gt;
&lt;br /&gt;
Das {{class|KConfig}}-Objekt wird benutzt um ein bestehendes Konfigurationsobjekt anzusteuern. Es gibt eine Reihe von Möglichkeiten ein Konfigurationsobjekt zu erstellen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
// ein einfaches, altes lesen/schreiben Konfigurationsobjekt&lt;br /&gt;
KConfig config(&amp;quot;myapprc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// eine bestimmte Datei im Dateisystem&lt;br /&gt;
// currently must be an INI style file&lt;br /&gt;
KConfig fullPath(&amp;quot;/etc/kderc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// nicht mit globalen Werten verflochten&lt;br /&gt;
KConfig globalFree( &amp;quot;localsrc&amp;quot;, KConfig::NoGlobals );&lt;br /&gt;
&lt;br /&gt;
// nicht mit globalen Werten orde der $KDEDIRS Hierarchie verflochten&lt;br /&gt;
KConfig simpleConfig( &amp;quot;simplerc&amp;quot;, KConfig::SimpleConfig );&lt;br /&gt;
&lt;br /&gt;
// Komponenten-spezifische Konfiguration, in diesem Fall ein Plugin&lt;br /&gt;
KConfig pluginConfig( componentData(), &amp;quot;pluginrc&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
// Ausserhalb der normalen Konfigurations-Ressource&lt;br /&gt;
KConfig dataResource( &amp;quot;data&amp;quot;, &amp;quot;myapp/somefile&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{note (de)|wie soll &amp;quot;merged&amp;quot; in den folgenden Fällen übersetzt werden? &amp;lt;br&amp;gt; &amp;lt;tt&amp;gt;&amp;quot;verschmolzen&amp;quot; oder &amp;quot;verflochten&amp;quot;&amp;lt;/tt&amp;gt; &amp;lt;br&amp;gt; der Anwendung selber transparent&amp;quot; tönt auch nicht sehr gut}}&lt;br /&gt;
&lt;br /&gt;
Das Kconfig Objekt, das wir auf Zeile 2 erstellen ist ein gewöhnliches Konfigurationsobjekt. Wir können Werte aus ihm lesen, neue Einträge schreiben und nach verschiedenen Eigenschaften des Objekts fragen. Dieses Objekt wird aus der Konfigurations-Ressource geladen, wie es durch {{class|KStandardDirs}} bestimmt wird, das heisst, dass jede Instanz des &amp;lt;tt&amp;gt;myapprc&amp;lt;/tt&amp;gt;-Objekts in jedem der Ordner in der Konfigurations-Ressourcen-Hierarchie verschmolzen werden um die Werte zu erzeugen, die in diesem Objekt gesehen werden. So werden Systemweite und &lt;br /&gt;
pro-Benutzer/Gruppen Profile erstellt und unterstützt. Das alles geschieht der Anwendung selber transparent.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{tip| Für mehr Informationen, wie das Verschmelzen funktioniert, siehe diesen Artikel über die [[KDE System Administration/KDE_Filesystem_Hierarchy|KDE Dateisystem Hierarchie]].}}&lt;br /&gt;
&lt;br /&gt;
{{note (de)|Ist das so gemeint mit &amp;quot;expects an INI style file&amp;quot;&amp;lt;br&amp;gt; &amp;lt;tt&amp;gt; On line 6 we open a specific local file, this case /etc/kderc. This performs no merging of values and expects an INI style file.&amp;lt;/tt&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Auf Zeile 6 öffnen wir eine bestimmte Lokale Datei, in diesem Fall {{path|/etc/kderc}}. Das führt kein verschmelzen von Werten aus und erwartet eine Datei im INI Format.&lt;br /&gt;
&lt;br /&gt;
Zeile 9 erzeugt ein Konfigurationsobjekt, dass nicht mit dem globalen &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt;-Konfigurationsobjekt verflochten ist,  während das Konfigurationsobjekt auf Zeile 12 zusätzlich mit keinem der Dateien in der &amp;lt;tt&amp;gt;$KDEDIRS&amp;lt;/tt&amp;gt;-Hierarchie verflochten ist. Das kann die Leistung spürbar verbessern, falls man einfach nur Werte aus einer einfachen Konfuguration liest und globale Werte keine Rolle spielen.&lt;br /&gt;
&lt;br /&gt;
Zeile 15 erzeugt ein Konfigurationsobjekt unter Benutzung des {{class|KComponentData}}-Objekts das zu einem Plugin oder einer anderen Komponente gehört. Das Plugin kann verschiedene Ordner aufweisen, die in seinen {{class|KStandardDirs}} definiert sind und das ist eine Möglichkeit sich zu versichern, dass {{class|KConfig}} das respektiert.&lt;br /&gt;
&lt;br /&gt;
Und schliesslich auf Zeile 18 erzeugen wir ein Konfigurationsobjekt, das nicht in der &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt;-Ressource sondern in der &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt;-Ressource existiert. Man kann kann auf diese Weise jede Ressource verwenden, von denen {{class|KStandardDirs}} Kenntnis hat, auch solche die während der Laufzeit hinzugefügt werden.&lt;br /&gt;
&lt;br /&gt;
=== Spezielle Konfigurationsobjekte ===&lt;br /&gt;
&lt;br /&gt;
Jede Anwendung hat sein eigenes Konfigurationsobjekt das den Namen benutzt, der von {{class|KAboutData}} bereitgestellt wird mit angehängtem &amp;quot;rc&amp;quot;. Also hätte eine Anwendung mit dem Namen &amp;quot;myapp&amp;quot; das Standard-Konfigurationsobjekt &amp;quot;myapprc&amp;quot;. Dieses Konfigurationsobjekt kann auf diese Weise aufgerufen werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KComponentData&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
#include &amp;lt;KGlobal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    // beachten sie, dass dies eigentlich ein KSharedConfig ist&lt;br /&gt;
    // mehr über diese Klasse siehe weiter unten&lt;br /&gt;
    KConfig* config = KGlobal::config();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Auf das Standard-Konfigurationsobjekt für die Anwendung wird zugegriffen, wenn kein Name definiert wurde, als das {{class|KConfig}}-Objekt erzeugt wurde. Also könnten wir stattdessen auch das tun:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    KConfig config;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zusätzlich könnte jede Komponente sein eigenes Konfigurationsobjekt haben. Auf dieses wird normalerweise durch die &amp;lt;tt&amp;gt;componentData()&amp;lt;/tt&amp;gt; des Plugins zugegriffen, anstatt durch die &amp;lt;tt&amp;gt;{{class|KGlobal}}::mainComponent()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Und schliesslich gibt es noch ein globales Konfigurationsobjekt, &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt;, das von jeder Anwendung verwendet wird. Es enthält Informationen wie die Standard-Tatenkombinationen für verschiedene Aktionen. Es wird in das Konfigurationsobjekt &amp;quot;gemischt&amp;quot; wenn der &amp;lt;tt&amp;gt;KConfig::IncludeGlobals&amp;lt;/tt&amp;gt; Bitschalter dem {{class|KConfig}} Konstruktor übergeben wird, was standardmässig der Fall ist.&lt;br /&gt;
&lt;br /&gt;
=== Allgemein nützliche Methoden ===&lt;br /&gt;
&lt;br /&gt;
Um den momentanen Zustand des Konfigurationsobjektes zu speichern, rufen wir die &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt;-Methode auf. Diese Methode wird also aufgerufen, wenn ein Objekt zerstört wird. Falls keine Änderungen gemacht wurden, oder die Ressource weist sich als nicht beschreibbar aus (Wenn der Benutzer zum Beispiel nicht genug Rechte hat, um die Datei zu bearbeiten), dann wird keine Beschäftigung der Festplatte hervorgerufen. &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; verschmilzt Änderungen die gleichzeitig von anderen Prozessen ausgeführt werden - lokale Änderungen haben aber trotzdem Vorrang.&lt;br /&gt;
&lt;br /&gt;
Wenn wir sicher gehen wollen, dass wir die aktuellsten Werte von der Festplatte haben, dann rufen wir &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt; auf, welches &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; aufruft und dann die Daten von der Festplatte aktualisiert.&lt;br /&gt;
&lt;br /&gt;
Falls wir verhindern müssen, dass das Konfigurationsobjekt bereits gemachte Änderungen nicht auf die Festplatte speichert, müssen wir &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt; aufrufen. Ein besonderer Anwendungsfall ist es, die Konfiguration zum Festplatten-Zustand zurückzusetzen indem man &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt; gefolgt von &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt; aufruft.&lt;br /&gt;
&lt;br /&gt;
Alle Gruppen in einem Konfigurationsobjekt aufzurufen ist so einfach wie hier in diesem Code-Abschnitt &amp;lt;tt&amp;gt;groupList()&amp;lt;/tt&amp;gt; aufzurufen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::mainComponent().config();&lt;br /&gt;
&lt;br /&gt;
foreach ( const QString&amp;amp; group, config.groupList() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;next group:&amp;quot; &amp;lt;&amp;lt; group;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== KSharedConfig ==&lt;br /&gt;
&lt;br /&gt;
Die {{class|KSharedConfig}} Klasse ist eine Referenz-gezählte Version von {{class|KConfig}}. Darum stellt es eine Möglichkeit bereit, das selbe Konfigurationsobjekt von unterschiedlichen Orten zu referenzieren ohne zusätzlich die Objekte trennen zu müssen oder sich um die Synchronisation des Schreibvorgangs zu kümmern, selbst wenn das Konfigurationsobjekt von verschiedenen Code-Pfaden aktualisiert wird.&lt;br /&gt;
&lt;br /&gt;
Auf ein {{class|KSharedConfig}}-Objekt zuzugreifen ist so einfach wie das hier:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KSharedConfigPtr config = KSharedConfig::openConfig();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;openConfig()&amp;lt;/tt&amp;gt; nimmt die selben Parameter wie {{class|KConfig}}'s Konstruktoren, was es einem ermöglicht zu definieren, welche Konfigurationsdatei zu öffnen und Markierungen das Verschmelzen von nicht-&amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt;-Ressourcen zu kontrollieren.  &lt;br /&gt;
&lt;br /&gt;
Es wird grundsätzlich empfohlen {{class|KSharedConfig}} anstatt {{class|KConfig}} selbst zu benutzen, und auch das Objekt, das von {{class|KComponentData}} zurückgegeben wird ist in der Tat ein {{class|KSharedConfig}}-Objekt.&lt;br /&gt;
&lt;br /&gt;
== KConfigGroup ==&lt;br /&gt;
&lt;br /&gt;
Nun da wir ein Konfigurationsobjekt haben, ist der nächste Schritt es tatsächlich zu nutzen. Das erste, das wir tun müssen, ist zu bestimmen, auf welche Gruppe von Schlüssel-/Wertepaare wir in unserem Objekt zugreifen wollen. Wir tun das, indem wir ein KConfigGroup-Objekt erstellen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig config;&lt;br /&gt;
KConfigGroup generalGroup( &amp;amp;config, &amp;quot;General&amp;quot; );&lt;br /&gt;
KConfigGroup colorsGroup = config.group( &amp;quot;Colors&amp;quot; ); // ...oder so ähnlich...&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Man kann{{class|KConfigGroup}} {{class|KConfig}}- oder {{class|KSharedConfig}}-Objekte übergeben.&lt;br /&gt;
&lt;br /&gt;
Konfigurationsgruppen können ebenfalls verschachtelt werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfigGroup subGroup1( &amp;amp;generalGroup, &amp;quot;LessGeneral&amp;quot; );&lt;br /&gt;
KConfigGroup subGroup2 = colorsGroup.group( &amp;quot;Dialogs&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Lesen von Einträgen ==&lt;br /&gt;
&lt;br /&gt;
Wenn man erst einmal ein {{class|KConfigGroup}}-Objekt erstellt hat, ist das Lesen von Einträgen ziemlich einfach:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
QString accountName = generalGroup.readEntry( &amp;quot;Account&amp;quot;,&lt;br /&gt;
                                              QString() );&lt;br /&gt;
QColor color = colorsGroup.readEntry( &amp;quot;background&amp;quot;,&lt;br /&gt;
                                      Qt::white );&lt;br /&gt;
QStringList list = generalGroup.readEntry( &amp;quot;List&amp;quot;,&lt;br /&gt;
                                           QStringList() );&lt;br /&gt;
QString path = generalGroup.readPathEntry( &amp;quot;SaveTo&amp;quot;,&lt;br /&gt;
                                           defaultPath );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wie man hier oben sehen kann, kann man Lesevorgänge von verschiedenen {{class|KConfigGroup}}-Objekten, die auf dem selben {{class|KConfig}}-Objekt erstellt wurden, problemlos mischen. Die Lese-Methoden nehmen den Schlüssel, der Gross- und Kleinschreibung unterscheidet, als erstes Argument und den Standardwert als zweites Argument. Dieses Argument bestimmt auch welche Art von Daten, also z.B. eine Farbe in Zeile 3, erwartet wird und auch die Art von Objekt, die zurückgegeben werden soll.Das zurückgegebene Objekt wird in eine {{qt|QVariant}} gepackt um diese Hexerei zu ermöglichen. &lt;br /&gt;
&lt;br /&gt;
Es gibt eine Anzahl von speziellen Methoden, zum Beispiel &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt;, das einen Datei-Systempfad zurückgibt. Es ist entscheidend, dass man &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; benutzt, wenn man nach einem Pfad fragt, das es Funktionen wie Erreichbarkeits-Profile ermöglicht richtig zu funktionieren.&lt;br /&gt;
&lt;br /&gt;
Wenn kein solcher Schlüssel im Konfigurationsobjekt existiert, dann wird stattdessen der Standardwert zurückgegeben. Falls es eine lokalisierte (d.h. in eine andere Sprache übersetzte) Version für den Schlüssel gibt, die der eingestellten Sprache entspricht, dann wird diese zurückgegeben.&lt;br /&gt;
&lt;br /&gt;
== Schreiben neuer Einträge ==&lt;br /&gt;
&lt;br /&gt;
Neue Werte zu definieren ist ähnlich einfach:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
generalGroup.writeEntry( &amp;quot;Account&amp;quot;, accountName );&lt;br /&gt;
generalGroup.writePathEntry( &amp;quot;SaveTo&amp;quot;, savePath );&lt;br /&gt;
colorGroup.writeEntry( &amp;quot;background&amp;quot;, color );&lt;br /&gt;
generalGroup.config()-&amp;gt;sync();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beachten sie die Benutzung von &amp;lt;tt&amp;gt;writePathEntry&amp;lt;/tt&amp;gt; und wie die Art von Objekt, das wir benutzen, wie zum Beispiel {{qt|QColor}} auf Zeile 3, bestimmt, wie die Daten angeordnet werden. Zusätzlich, wenn wir mit den Einträgen fertig sind, muss &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; auf das Konfigurationsobjekt ausgeführt werden, um es auf die Festplatte zu speichern. Man kann auch einfach warten, bis das Objekt zerstört wird, was falls nötig automatisch einen &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; auslöst.&lt;br /&gt;
&lt;br /&gt;
== KDesktopFile: Ein besonderer Fall ==&lt;br /&gt;
&lt;br /&gt;
Wann ist eine Konfigurationsdatei keine Konfigurationsdatei? Wenn es eine [http://freedesktop.org/wiki/Standards_2fdesktop_2dentry_2dspec Desktop-Datei] ist. Diese Dateien, die im Grunde genommen Konfigurationsdateien sind, werden benutzt um Einträge für Anwendungsmenüs, Dateitypen, Plugins und verschiedene Services.&lt;br /&gt;
&lt;br /&gt;
Wenn auf eine .desktop Datei zugegriffen wird, sollte man stattdessen die  {{class|KDesktopFile}}-Klasse verwenden, die, während eine {{class|KConfig}}-Klasse über alle oben genannten Ressourcen verfügt, über eine Anzahl von Methoden verfügt, um das Zugreifen auf Standard-Attribute dieser Dateien konsistent und zuverlässig zu machen.&lt;br /&gt;
&lt;br /&gt;
== Kiosk: Abriegelung und Benutzer-/Gruppenprofile ==&lt;br /&gt;
&lt;br /&gt;
KConfig stellt eine Reihe von leistungsstarken Abriegelungs- und Konfigurations-Definitionen bereit, insgesamt als &amp;quot;Kiosk&amp;quot; bekannt, worauf viele System-Administratoren und -Integratoren basieren. Während ein Grossteil dieses Systems der Anwendung transparent bereitgestellt wird, ist es möglich dass man den Schreib/Lese-Status eines Konfigurationsobjekts prüfen will.&lt;br /&gt;
&lt;br /&gt;
Einträge in Konfigurationsobjekten die mithilfe von Kiosk abgeriegelt sind, werden &amp;quot;unveränderlich&amp;quot; genannt. Eine Anwendung kann nach der Unveränderlichkeit von ganzen Konfigurationsobjekten, Gruppen oder Schlüsseln, wie in diesem Beispiel gezeigt, fragen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::config();&lt;br /&gt;
&lt;br /&gt;
if ( config-&amp;gt;isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;Konfigurationsobjekt ist unveränderlich&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
KConfigGroup group(config, &amp;quot;General&amp;quot;);&lt;br /&gt;
if ( group.isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;Die Gruppe 'General' ist unveränderlich&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if ( group.entryIsImmutable(&amp;quot;URL&amp;quot;) ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;Der URL Eintrag in der Gruppe 'General' ist unveränderlich&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das kann in gewissen Situationen, wo eine Aktion ausgeführt werden soll, falls ein Objekt unveränderlich ist.&lt;br /&gt;
&lt;br /&gt;
== KConfig XT ==&lt;br /&gt;
&lt;br /&gt;
Es gibt einen Weg, gewisse Anwendungsfälle von KConfig einfacher, schneller und zuverlässiger zu  machen: KConfig XT. Im Bestimmten kann KConfig XT bei Hauptanwendungs- oder Plug-In-Konfigurationsobjekten und bei Konfigurationsdialogen und anderen Benutzeroberflächen mit diesen Werten sehr hilfreich sein. Es dokumentiert gleichzeitig auch alle verfügbaren Konfigurations-Optionen, was alle System-Administratoren und -Integratoren, die KDE benutzen so viel glücklicher macht.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[../Using_KConfig_XT_(de)|Die nächste Anleitung handelt über KConfig XT und wie es zu benutzen.]]&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials/KConfig_(de)</id>
		<title>Development/Tutorials/KConfig (de)</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials/KConfig_(de)"/>
				<updated>2008-02-07T13:39:50Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:I18n/Language Navigation Bar|Development/Tutorials/KConfig}}&lt;br /&gt;
&lt;br /&gt;
{{TutorialBrowser (de)|&lt;br /&gt;
&lt;br /&gt;
series=KConfig|&lt;br /&gt;
&lt;br /&gt;
name=Einführung in KConfig|&lt;br /&gt;
&lt;br /&gt;
pre=Keine|&lt;br /&gt;
&lt;br /&gt;
next=[[../Using_KConfig_XT (de)|Benutzen von KConfig XT]]|&lt;br /&gt;
&lt;br /&gt;
reading=Keine&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{improve (de)}}&lt;br /&gt;
&lt;br /&gt;
== Zusammenfassung ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dieser Artikel beschäftigt sich mir dem KDE Einstellungdaten-System, angefangen mit einer Übersicht über den grundlegenden Aufbau aus der Sicht eines Entwicklers. Es wirft ausserdem einen Blick auf jede der Klassen, die für die Entwicklung von Anwendungen relevant sind und fährt dann mit kiosk (Benutzer- und Gruppenprofile) Integration fort.&lt;br /&gt;
&lt;br /&gt;
== Grundlegender Aufbau ==&lt;br /&gt;
&lt;br /&gt;
KConfig ist ausgelegt um das Konzept vom eigentlichen Speichern und Auffinden von Konfigurationsdaten hinter eine Programmierschnittstelle zu abstrahieren die es ermöglicht, auf einfache Weise Informationen abzurufen und zu setzen. Wo oder in welcher Form Daten gespeichert werden ist für eine Anwendung die KConfig benutzt irrelevant.&lt;br /&gt;
&lt;br /&gt;
Das behält alle KDE Anwendungen konsistent in ihrer Art, Konfigurationen handzuhaben und nimmt einem Anwendungs-Entwickler die Arbeit so ein System von Grund auf neu zu schreiben, was ein sehr fehleranfälliger Prozess sein kann.&lt;br /&gt;
&lt;br /&gt;
Jedes KConfig Objekt verkörpert ein einziges Konfigurationsobjekt. Jedes Konfigurationsobjekt ist durch seinen einzigartigen Namen gekennzeichnet und kann von mehreren lokalen oder externen Daten oder Services gelesen werden. Jede Anwendung hat standardmässig ein zugehöriges Konfigurationsobjekt und es gibt auch ein globales Konfigurationsobjekt.&lt;br /&gt;
&lt;br /&gt;
Diese Konfigurationsobjekte sind nach einer zweistufigen Hierarchie getrennt: Gruppen und Schlüssel. Ein Konfigurationsobjekt kann eine beliebige Anzahl an Gruppen haben und jede Gruppe kann einen oder mehrere Schlüssel mit zugehörigen Werten haben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die gespeicherten Werte können aus beliebig vielen verschiedenen Datentypen bestehen. Sie werden gespeichert und abgerufen als das Objekt selbst. Zum Beispiel wird ein {{qt|QObject}}-Objekt direkt einem Konfigurationsobjekt übergeben, wenn es einen Farbwert speichert und wenn ein Farbwert abgerufen wird, wird ein {{qt|QObject}}-Objekt zurückgegeben.&lt;br /&gt;
&lt;br /&gt;
{{note (de)| deserialization  entgliedern? &amp;lt;br&amp;gt; &amp;lt;tt&amp;gt; &amp;quot;do not have to perform serialization and deserialization of objects themselves&amp;quot; &amp;lt;/tt&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Anwendungen selbst müssen darum normalerweise Objekte nicht selber gliedern und entgliedern.&lt;br /&gt;
&lt;br /&gt;
== Die KConfig Klasse ==&lt;br /&gt;
&lt;br /&gt;
Das {{class|KConfig}}-Objekt wird benutzt um ein bestehendes Konfigurationsobjekt anzusteuern. Es gibt eine Reihe von Möglichkeiten ein Konfigurationsobjekt zu erstellen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
// ein einfaches, altes lesen/schreiben Konfigurationsobjekt&lt;br /&gt;
KConfig config(&amp;quot;myapprc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// eine bestimmte Datei im Dateisystem&lt;br /&gt;
// currently must be an INI style file&lt;br /&gt;
KConfig fullPath(&amp;quot;/etc/kderc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// nicht mit globalen Werten verflochten&lt;br /&gt;
KConfig globalFree( &amp;quot;localsrc&amp;quot;, KConfig::NoGlobals );&lt;br /&gt;
&lt;br /&gt;
// nicht mit globalen Werten orde der $KDEDIRS Hierarchie verflochten&lt;br /&gt;
KConfig simpleConfig( &amp;quot;simplerc&amp;quot;, KConfig::SimpleConfig );&lt;br /&gt;
&lt;br /&gt;
// Komponenten-spezifische Konfiguration, in diesem Fall ein Plugin&lt;br /&gt;
KConfig pluginConfig( componentData(), &amp;quot;pluginrc&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
// Ausserhalb der normalen Konfigurations-Ressource&lt;br /&gt;
KConfig dataResource( &amp;quot;data&amp;quot;, &amp;quot;myapp/somefile&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{note (de)|wie soll &amp;quot;merged&amp;quot; in den folgenden Fällen übersetzt werden? &amp;lt;br&amp;gt; &amp;lt;tt&amp;gt;&amp;quot;verschmolzen&amp;quot; oder &amp;quot;verflochten&amp;quot;&amp;lt;/tt&amp;gt; &amp;lt;br&amp;gt; der Anwendung selber transparent&amp;quot; tönt auch nicht sehr gut}}&lt;br /&gt;
&lt;br /&gt;
Das Kconfig Objekt, das wir auf Zeile 2 erstellen ist ein gewöhnliches Konfigurationsobjekt. Wir können Werte aus ihm lesen, neue Einträge schreiben und nach verschiedenen Eigenschaften des Objekts fragen. Dieses Objekt wird aus der Konfigurations-Ressource geladen, wie es durch {{class|KStandardDirs}} bestimmt wird, das heisst, dass jede Instanz des &amp;lt;tt&amp;gt;myapprc&amp;lt;/tt&amp;gt;-Objekts in jedem der Ordner in der Konfigurations-Ressourcen-Hierarchie verschmolzen werden um die Werte zu erzeugen, die in diesem Objekt gesehen werden. So werden Systemweite und &lt;br /&gt;
pro-Benutzer/Gruppen Profile erstellt und unterstützt. Das alles geschieht der Anwendung selber transparent.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{tip| Für mehr Informationen, wie das Verschmelzen funktioniert, siehe diesen Artikel über die [[KDE System Administration/KDE_Filesystem_Hierarchy|KDE Dateisystem Hierarchie]].}}&lt;br /&gt;
&lt;br /&gt;
{{note (de)|Ist das so gemeint mit &amp;quot;expects an INI style file&amp;quot;&amp;lt;br&amp;gt; &amp;lt;tt&amp;gt; On line 6 we open a specific local file, this case /etc/kderc. This performs no merging of values and expects an INI style file.&amp;lt;/tt&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Auf Zeile 6 öffnen wir eine bestimmte Lokale Datei, in diesem Fall {{path|/etc/kderc}}. Das führt kein verschmelzen von Werten aus und erwartet eine Datei im INI Format.&lt;br /&gt;
&lt;br /&gt;
Zeile 9 erzeugt ein Konfigurationsobjekt, dass nicht mit dem globalen &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt;-Konfigurationsobjekt verflochten ist,  während das Konfigurationsobjekt auf Zeile 12 zusätzlich mit keinem der Dateien in der &amp;lt;tt&amp;gt;$KDEDIRS&amp;lt;/tt&amp;gt;-Hierarchie verflochten ist. Das kann die Leistung spürbar verbessern, falls man einfach nur Werte aus einer einfachen Konfuguration liest und globale Werte keine Rolle spielen.&lt;br /&gt;
&lt;br /&gt;
Zeile 15 erzeugt ein Konfigurationsobjekt unter Benutzung des {{class|KComponentData}}-Objekts das zu einem Plugin oder einer anderen Komponente gehört. Das Plugin kann verschiedene Ordner aufweisen, die in seinen {{class|KStandardDirs}} definiert sind und das ist eine Möglichkeit sich zu versichern, dass {{class|KConfig}} das respektiert.&lt;br /&gt;
&lt;br /&gt;
Und schliesslich auf Zeile 18 erzeugen wir ein Konfigurationsobjekt, das nicht in der &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt;-Ressource sondern in der &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt;-Ressource existiert. Man kann kann auf diese Weise jede Ressource verwenden, von denen {{class|KStandardDirs}} Kenntnis hat, auch solche die während der Laufzeit hinzugefügt werden.&lt;br /&gt;
&lt;br /&gt;
=== Spezielle Konfigurationsobjekte ===&lt;br /&gt;
&lt;br /&gt;
Jede Anwendung hat sein eigenes Konfigurationsobjekt das den Namen benutzt, der von {{class|KAboutData}} bereitgestellt wird mit angehängtem &amp;quot;rc&amp;quot;. Also hätte eine Anwendung mit dem Namen &amp;quot;myapp&amp;quot; das Standard-Konfigurationsobjekt &amp;quot;myapprc&amp;quot;. Dieses Konfigurationsobjekt kann auf diese Weise aufgerufen werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KComponentData&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
#include &amp;lt;KGlobal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    // beachten sie, dass dies eigentlich ein KSharedConfig ist&lt;br /&gt;
    // mehr über diese Klasse siehe weiter unten&lt;br /&gt;
    KConfig* config = KGlobal::config();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Auf das Standard-Konfigurationsobjekt für die Anwendung wird zugegriffen, wenn kein Name definiert wurde, als das {{class|KConfig}}-Objekt erzeugt wurde. Also könnten wir stattdessen auch das tun:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    KConfig config;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zusätzlich könnte jede Komponente sein eigenes Konfigurationsobjekt haben. Auf dieses wird normalerweise durch die &amp;lt;tt&amp;gt;componentData()&amp;lt;/tt&amp;gt; des Plugins zugegriffen, anstatt durch die &amp;lt;tt&amp;gt;{{class|KGlobal}}::mainComponent()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Und schliesslich gibt es noch ein globales Konfigurationsobjekt, &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt;, das von jeder Anwendung verwendet wird. Es enthält Informationen wie die Standard-Tatenkombinationen für verschiedene Aktionen. Es wird in das Konfigurationsobjekt &amp;quot;gemischt&amp;quot; wenn der &amp;lt;tt&amp;gt;KConfig::IncludeGlobals&amp;lt;/tt&amp;gt; Bitschalter dem {{class|KConfig}} Konstruktor übergeben wird, was standardmässig der Fall ist.&lt;br /&gt;
&lt;br /&gt;
=== Allgemein nützliche Methoden ===&lt;br /&gt;
&lt;br /&gt;
Um den momentanen Zustand des Konfigurationsobjektes zu speichern, rufen wir die &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt;-Methode auf. Diese Methode wird also aufgerufen, wenn ein Objekt zerstört wird. Falls keine Änderungen gemacht wurden, oder die Ressource weist sich als nicht beschreibbar aus (Wenn der Benutzer zum Beispiel nicht genug Rechte hat, um die Datei zu bearbeiten), dann wird keine Beschäftigung der Festplatte hervorgerufen. &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; verschmilzt Änderungen die gleichzeitig von anderen Prozessen ausgeführt werden - lokale Änderungen haben aber trotzdem Vorrang.&lt;br /&gt;
&lt;br /&gt;
Wenn wir sicher gehen wollen, dass wir die aktuellsten Werte von der Festplatte haben, dann rufen wir &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt; auf, welches &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; aufruft und dann die Daten von der Festplatte aktualisiert.&lt;br /&gt;
&lt;br /&gt;
Falls wir verhindern müssen, dass das Konfigurationsobjekt bereits gemachte Änderungen nicht auf die Festplatte speichert, müssen wir &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt; aufrufen. Ein besonderer Anwendungsfall ist es, die Konfiguration zum Festplatten-Zustand zurückzusetzen indem man &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt; gefolgt von &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt; aufruft.&lt;br /&gt;
&lt;br /&gt;
Alle Gruppen in einem Konfigurationsobjekt aufzurufen ist so einfach wie hier in diesem Code-Abschnitt &amp;lt;tt&amp;gt;groupList()&amp;lt;/tt&amp;gt; aufzurufen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::mainComponent().config();&lt;br /&gt;
&lt;br /&gt;
foreach ( const QString&amp;amp; group, config.groupList() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;next group:&amp;quot; &amp;lt;&amp;lt; group;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== KSharedConfig ==&lt;br /&gt;
&lt;br /&gt;
Die {{class|KSharedConfig}} Klasse ist eine Referenz-gezählte Version von {{class|KConfig}}. Darum stellt es eine Möglichkeit bereit, das selbe Konfigurationsobjekt von unterschiedlichen Orten zu referenzieren ohne zusätzlich die Objekte trennen zu müssen oder sich um die Synchronisation des Schreibvorgangs zu kümmern, selbst wenn das Konfigurationsobjekt von verschiedenen Code-Pfaden aktualisiert wird.&lt;br /&gt;
&lt;br /&gt;
Auf ein {{class|KSharedConfig}}-Objekt zuzugreifen ist so einfach wie das hier:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KSharedConfigPtr config = KSharedConfig::openConfig();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;openConfig()&amp;lt;/tt&amp;gt; nimmt die selben Parameter wie {{class|KConfig}}'s Konstruktoren, was es einem ermöglicht zu definieren, welche Konfigurationsdatei zu öffnen und Markierungen das Verschmelzen von nicht-&amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt;-Ressourcen zu kontrollieren.  &lt;br /&gt;
&lt;br /&gt;
Es wird grundsätzlich empfohlen {{class|KSharedConfig}} anstatt {{class|KConfig}} selbst zu benutzen, und auch das Objekt, das von {{class|KComponentData}} zurückgegeben wird ist in der Tat ein {{class|KSharedConfig}}-Objekt.&lt;br /&gt;
&lt;br /&gt;
== KConfigGroup ==&lt;br /&gt;
&lt;br /&gt;
Nun da wir ein Konfigurationsobjekt haben, ist der nächste Schritt es tatsächlich zu nutzen. Das erste, das wir tun müssen, ist zu bestimmen, auf welche Gruppe von Schlüssel-/Wertepaare wir in unserem Objekt zugreifen wollen. Wir tun das, indem wir ein KConfigGroup-Objekt erstellen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig config;&lt;br /&gt;
KConfigGroup generalGroup( &amp;amp;config, &amp;quot;General&amp;quot; );&lt;br /&gt;
KConfigGroup colorsGroup = config.group( &amp;quot;Colors&amp;quot; ); // ...oder so ähnlich...&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Man kann{{class|KConfigGroup}} {{class|KConfig}}- oder {{class|KSharedConfig}}-Objekte übergeben.&lt;br /&gt;
&lt;br /&gt;
Konfigurationsgruppen können ebenfalls verschachtelt werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfigGroup subGroup1( &amp;amp;generalGroup, &amp;quot;LessGeneral&amp;quot; );&lt;br /&gt;
KConfigGroup subGroup2 = colorsGroup.group( &amp;quot;Dialogs&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Lesen von Einträgen ==&lt;br /&gt;
&lt;br /&gt;
Wenn man erst einmal ein {{class|KConfigGroup}}-Objekt erstellt hat, ist das Lesen von Einträgen ziemlich einfach:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
QString accountName = generalGroup.readEntry( &amp;quot;Account&amp;quot;,&lt;br /&gt;
                                              QString() );&lt;br /&gt;
QColor color = colorsGroup.readEntry( &amp;quot;background&amp;quot;,&lt;br /&gt;
                                      Qt::white );&lt;br /&gt;
QStringList list = generalGroup.readEntry( &amp;quot;List&amp;quot;,&lt;br /&gt;
                                           QStringList() );&lt;br /&gt;
QString path = generalGroup.readPathEntry( &amp;quot;SaveTo&amp;quot;,&lt;br /&gt;
                                           defaultPath );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wie man hier oben sehen kann, kann man Lesevorgänge von verschiedenen {{class|KConfigGroup}}-Objekten, die auf dem selben {{class|KConfig}}-Objekt erstellt wurden, problemlos mischen. Die Lese-Methoden nehmen den Schlüssel, der Gross- und Kleinschreibung unterscheidet, als erstes Argument und den Standardwert als zweites Argument. Dieses Argument bestimmt auch welche Art von Daten, also z.B. eine Farbe in Zeile 3, erwartet wird und auch die Art von Objekt, die zurückgegeben werden soll.Das zurückgegebene Objekt wird in eine {{qt|QVariant}} gepackt um diese Hexerei zu ermöglichen. &lt;br /&gt;
&lt;br /&gt;
Es gibt eine Anzahl von speziellen Methoden, zum Beispiel &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt;, das einen Datei-Systempfad zurückgibt. Es ist entscheidend, dass man &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; benutzt, wenn man nach einem Pfad fragt, das es Funktionen wie Erreichbarkeits-Profile ermöglicht richtig zu funktionieren.&lt;br /&gt;
&lt;br /&gt;
Wenn kein solcher Schlüssel im Konfigurationsobjekt existiert, dann wird stattdessen der Standardwert zurückgegeben. Falls es eine lokalisierte (d.h. in eine andere Sprache übersetzte) Version für den Schlüssel gibt, die der eingestellten Sprache entspricht, dann wird diese zurückgegeben.&lt;br /&gt;
&lt;br /&gt;
== Schreiben neuer Einträge ==&lt;br /&gt;
&lt;br /&gt;
Neue Werte zu definieren ist ähnlich einfach:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
generalGroup.writeEntry( &amp;quot;Account&amp;quot;, accountName );&lt;br /&gt;
generalGroup.writePathEntry( &amp;quot;SaveTo&amp;quot;, savePath );&lt;br /&gt;
colorGroup.writeEntry( &amp;quot;background&amp;quot;, color );&lt;br /&gt;
generalGroup.config()-&amp;gt;sync();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beachten sie die Benutzung von &amp;lt;tt&amp;gt;writePathEntry&amp;lt;/tt&amp;gt; und wie die Art von Objekt, das wir benutzen, wie zum Beispiel {{qt|QColor}} auf Zeile 3, bestimmt, wie die Daten angeordnet werden. Zusätzlich, wenn wir mit den Einträgen fertig sind, muss &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; auf das Konfigurationsobjekt ausgeführt werden, um es auf die Festplatte zu speichern. Man kann auch einfach warten, bis das Objekt zerstört wird, was falls nötig automatisch einen &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; auslöst.&lt;br /&gt;
&lt;br /&gt;
== KDesktopFile: Ein besonderer Fall ==&lt;br /&gt;
&lt;br /&gt;
Wann ist eine Konfigurationsdatei keine Konfigurationsdatei? Wenn es eine [http://freedesktop.org/wiki/Standards_2fdesktop_2dentry_2dspec Desktop-Datei] ist. Diese Dateien, die im Grunde genommen Konfigurationsdateien sind, werden benutzt um Einträge für Anwendungsmenüs, Dateitypen, Plugins und verschiedene Services.&lt;br /&gt;
&lt;br /&gt;
Wenn auf eine .desktop Datei zugegriffen wird, sollte man stattdessen die  {{class|KDesktopFile}}-Klasse verwenden, die, während eine {{class|KConfig}}-Klasse über alle oben genannten Ressourcen verfügt, über eine Anzahl von Methoden verfügt, um das Zugreifen auf Standard-Attribute dieser Dateien konsistent und zuverlässig zu machen.&lt;br /&gt;
&lt;br /&gt;
== Kiosk: Abriegelung und Benutzer-/Gruppenprofile ==&lt;br /&gt;
&lt;br /&gt;
KConfig stellt eine Reihe von leistungsstarken Abriegelungs- und Konfigurations-Definitionen bereit, insgesamt als &amp;quot;Kiosk&amp;quot; bekannt, worauf viele System-Administratoren und -Integratoren basieren. Während ein Grossteil dieses Systems der Anwendung transparent bereitgestellt wird, ist es möglich dass man den Schreib/Lese-Status eines Konfigurationsobjekts prüfen will.&lt;br /&gt;
&lt;br /&gt;
Einträge in Konfigurationsobjekten die mithilfe von Kiosk abgeriegelt sind, werden &amp;quot;unveränderlich&amp;quot; genannt. Eine Anwendung kann nach der Unveränderlichkeit von ganzen Konfigurationsobjekten, Gruppen oder Schlüsseln, wie in diesem Beispiel gezeigt, fragen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::config();&lt;br /&gt;
&lt;br /&gt;
if ( config-&amp;gt;isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;Konfigurationsobjekt ist unveränderlich&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
KConfigGroup group(config, &amp;quot;General&amp;quot;);&lt;br /&gt;
if ( group.isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;Die Gruppe 'General' ist unveränderlich&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if ( group.entryIsImmutable(&amp;quot;URL&amp;quot;) ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;Der URL Eintrag in der Gruppe 'General' ist unveränderlich&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das kann in gewissen Situationen, wo eine Aktion ausgeführt werden soll, falls ein Objekt unveränderlich ist.&lt;br /&gt;
&lt;br /&gt;
== KConfig XT ==&lt;br /&gt;
&lt;br /&gt;
Es gibt einen Weg, gewisse Anwendungsfälle von KConfig einfacher, schneller und zuverlässiger zu  machen: KConfig XT. Im Bestimmten kann KConfig XT bei Hauptanwendungs- oder Plug-In-Konfigurationsobjekten und bei Konfigurationsdialogen und anderen Benutzeroberflächen mit diesen Werten sehr hilfreich sein. Es dokumentiert gleichzeitig auch alle verfügbaren Konfigurations-Optionen, was alle System-Administratoren und -Integratoren, die KDE benutzen so viel glücklicher macht.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[../Using_KConfig_XT_(de)|Die nächste Anleitung handelt über KConfig XT und wie es zu benutzen.]]&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials/KConfig_(de)</id>
		<title>Development/Tutorials/KConfig (de)</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials/KConfig_(de)"/>
				<updated>2008-02-07T13:38:35Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: /* KConfig XT */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:I18n/Language Navigation Bar|Development/Tutorials/KConfig}}&lt;br /&gt;
&lt;br /&gt;
{{TutorialBrowser (de)|&lt;br /&gt;
&lt;br /&gt;
series=KConfig|&lt;br /&gt;
&lt;br /&gt;
name=Einführung in KConfig|&lt;br /&gt;
&lt;br /&gt;
pre=Keine|&lt;br /&gt;
&lt;br /&gt;
next=[[../Using_KConfig_XT|Benutzen von KConfig XT]]|&lt;br /&gt;
&lt;br /&gt;
reading=Keine&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{improve (de)}}&lt;br /&gt;
&lt;br /&gt;
== Zusammenfassung ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dieser Artikel beschäftigt sich mir dem KDE Einstellungdaten-System, angefangen mit einer Übersicht über den grundlegenden Aufbau aus der Sicht eines Entwicklers. Es wirft ausserdem einen Blick auf jede der Klassen, die für die Entwicklung von Anwendungen relevant sind und fährt dann mit kiosk (Benutzer- und Gruppenprofile) Integration fort.&lt;br /&gt;
&lt;br /&gt;
== Grundlegender Aufbau ==&lt;br /&gt;
&lt;br /&gt;
KConfig ist ausgelegt um das Konzept vom eigentlichen Speichern und Auffinden von Konfigurationsdaten hinter eine Programmierschnittstelle zu abstrahieren die es ermöglicht, auf einfache Weise Informationen abzurufen und zu setzen. Wo oder in welcher Form Daten gespeichert werden ist für eine Anwendung die KConfig benutzt irrelevant.&lt;br /&gt;
&lt;br /&gt;
Das behält alle KDE Anwendungen konsistent in ihrer Art, Konfigurationen handzuhaben und nimmt einem Anwendungs-Entwickler die Arbeit so ein System von Grund auf neu zu schreiben, was ein sehr fehleranfälliger Prozess sein kann.&lt;br /&gt;
&lt;br /&gt;
Jedes KConfig Objekt verkörpert ein einziges Konfigurationsobjekt. Jedes Konfigurationsobjekt ist durch seinen einzigartigen Namen gekennzeichnet und kann von mehreren lokalen oder externen Daten oder Services gelesen werden. Jede Anwendung hat standardmässig ein zugehöriges Konfigurationsobjekt und es gibt auch ein globales Konfigurationsobjekt.&lt;br /&gt;
&lt;br /&gt;
Diese Konfigurationsobjekte sind nach einer zweistufigen Hierarchie getrennt: Gruppen und Schlüssel. Ein Konfigurationsobjekt kann eine beliebige Anzahl an Gruppen haben und jede Gruppe kann einen oder mehrere Schlüssel mit zugehörigen Werten haben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die gespeicherten Werte können aus beliebig vielen verschiedenen Datentypen bestehen. Sie werden gespeichert und abgerufen als das Objekt selbst. Zum Beispiel wird ein {{qt|QObject}}-Objekt direkt einem Konfigurationsobjekt übergeben, wenn es einen Farbwert speichert und wenn ein Farbwert abgerufen wird, wird ein {{qt|QObject}}-Objekt zurückgegeben.&lt;br /&gt;
&lt;br /&gt;
{{note (de)| deserialization  entgliedern? &amp;lt;br&amp;gt; &amp;lt;tt&amp;gt; &amp;quot;do not have to perform serialization and deserialization of objects themselves&amp;quot; &amp;lt;/tt&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Anwendungen selbst müssen darum normalerweise Objekte nicht selber gliedern und entgliedern.&lt;br /&gt;
&lt;br /&gt;
== Die KConfig Klasse ==&lt;br /&gt;
&lt;br /&gt;
Das {{class|KConfig}}-Objekt wird benutzt um ein bestehendes Konfigurationsobjekt anzusteuern. Es gibt eine Reihe von Möglichkeiten ein Konfigurationsobjekt zu erstellen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
// ein einfaches, altes lesen/schreiben Konfigurationsobjekt&lt;br /&gt;
KConfig config(&amp;quot;myapprc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// eine bestimmte Datei im Dateisystem&lt;br /&gt;
// currently must be an INI style file&lt;br /&gt;
KConfig fullPath(&amp;quot;/etc/kderc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// nicht mit globalen Werten verflochten&lt;br /&gt;
KConfig globalFree( &amp;quot;localsrc&amp;quot;, KConfig::NoGlobals );&lt;br /&gt;
&lt;br /&gt;
// nicht mit globalen Werten orde der $KDEDIRS Hierarchie verflochten&lt;br /&gt;
KConfig simpleConfig( &amp;quot;simplerc&amp;quot;, KConfig::SimpleConfig );&lt;br /&gt;
&lt;br /&gt;
// Komponenten-spezifische Konfiguration, in diesem Fall ein Plugin&lt;br /&gt;
KConfig pluginConfig( componentData(), &amp;quot;pluginrc&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
// Ausserhalb der normalen Konfigurations-Ressource&lt;br /&gt;
KConfig dataResource( &amp;quot;data&amp;quot;, &amp;quot;myapp/somefile&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{note (de)|wie soll &amp;quot;merged&amp;quot; in den folgenden Fällen übersetzt werden? &amp;lt;br&amp;gt; &amp;lt;tt&amp;gt;&amp;quot;verschmolzen&amp;quot; oder &amp;quot;verflochten&amp;quot;&amp;lt;/tt&amp;gt; &amp;lt;br&amp;gt; der Anwendung selber transparent&amp;quot; tönt auch nicht sehr gut}}&lt;br /&gt;
&lt;br /&gt;
Das Kconfig Objekt, das wir auf Zeile 2 erstellen ist ein gewöhnliches Konfigurationsobjekt. Wir können Werte aus ihm lesen, neue Einträge schreiben und nach verschiedenen Eigenschaften des Objekts fragen. Dieses Objekt wird aus der Konfigurations-Ressource geladen, wie es durch {{class|KStandardDirs}} bestimmt wird, das heisst, dass jede Instanz des &amp;lt;tt&amp;gt;myapprc&amp;lt;/tt&amp;gt;-Objekts in jedem der Ordner in der Konfigurations-Ressourcen-Hierarchie verschmolzen werden um die Werte zu erzeugen, die in diesem Objekt gesehen werden. So werden Systemweite und &lt;br /&gt;
pro-Benutzer/Gruppen Profile erstellt und unterstützt. Das alles geschieht der Anwendung selber transparent.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{tip| Für mehr Informationen, wie das Verschmelzen funktioniert, siehe diesen Artikel über die [[KDE System Administration/KDE_Filesystem_Hierarchy|KDE Dateisystem Hierarchie]].}}&lt;br /&gt;
&lt;br /&gt;
{{note (de)|Ist das so gemeint mit &amp;quot;expects an INI style file&amp;quot;&amp;lt;br&amp;gt; &amp;lt;tt&amp;gt; On line 6 we open a specific local file, this case /etc/kderc. This performs no merging of values and expects an INI style file.&amp;lt;/tt&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Auf Zeile 6 öffnen wir eine bestimmte Lokale Datei, in diesem Fall {{path|/etc/kderc}}. Das führt kein verschmelzen von Werten aus und erwartet eine Datei im INI Format.&lt;br /&gt;
&lt;br /&gt;
Zeile 9 erzeugt ein Konfigurationsobjekt, dass nicht mit dem globalen &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt;-Konfigurationsobjekt verflochten ist,  während das Konfigurationsobjekt auf Zeile 12 zusätzlich mit keinem der Dateien in der &amp;lt;tt&amp;gt;$KDEDIRS&amp;lt;/tt&amp;gt;-Hierarchie verflochten ist. Das kann die Leistung spürbar verbessern, falls man einfach nur Werte aus einer einfachen Konfuguration liest und globale Werte keine Rolle spielen.&lt;br /&gt;
&lt;br /&gt;
Zeile 15 erzeugt ein Konfigurationsobjekt unter Benutzung des {{class|KComponentData}}-Objekts das zu einem Plugin oder einer anderen Komponente gehört. Das Plugin kann verschiedene Ordner aufweisen, die in seinen {{class|KStandardDirs}} definiert sind und das ist eine Möglichkeit sich zu versichern, dass {{class|KConfig}} das respektiert.&lt;br /&gt;
&lt;br /&gt;
Und schliesslich auf Zeile 18 erzeugen wir ein Konfigurationsobjekt, das nicht in der &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt;-Ressource sondern in der &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt;-Ressource existiert. Man kann kann auf diese Weise jede Ressource verwenden, von denen {{class|KStandardDirs}} Kenntnis hat, auch solche die während der Laufzeit hinzugefügt werden.&lt;br /&gt;
&lt;br /&gt;
=== Spezielle Konfigurationsobjekte ===&lt;br /&gt;
&lt;br /&gt;
Jede Anwendung hat sein eigenes Konfigurationsobjekt das den Namen benutzt, der von {{class|KAboutData}} bereitgestellt wird mit angehängtem &amp;quot;rc&amp;quot;. Also hätte eine Anwendung mit dem Namen &amp;quot;myapp&amp;quot; das Standard-Konfigurationsobjekt &amp;quot;myapprc&amp;quot;. Dieses Konfigurationsobjekt kann auf diese Weise aufgerufen werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KComponentData&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
#include &amp;lt;KGlobal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    // beachten sie, dass dies eigentlich ein KSharedConfig ist&lt;br /&gt;
    // mehr über diese Klasse siehe weiter unten&lt;br /&gt;
    KConfig* config = KGlobal::config();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Auf das Standard-Konfigurationsobjekt für die Anwendung wird zugegriffen, wenn kein Name definiert wurde, als das {{class|KConfig}}-Objekt erzeugt wurde. Also könnten wir stattdessen auch das tun:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    KConfig config;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zusätzlich könnte jede Komponente sein eigenes Konfigurationsobjekt haben. Auf dieses wird normalerweise durch die &amp;lt;tt&amp;gt;componentData()&amp;lt;/tt&amp;gt; des Plugins zugegriffen, anstatt durch die &amp;lt;tt&amp;gt;{{class|KGlobal}}::mainComponent()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Und schliesslich gibt es noch ein globales Konfigurationsobjekt, &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt;, das von jeder Anwendung verwendet wird. Es enthält Informationen wie die Standard-Tatenkombinationen für verschiedene Aktionen. Es wird in das Konfigurationsobjekt &amp;quot;gemischt&amp;quot; wenn der &amp;lt;tt&amp;gt;KConfig::IncludeGlobals&amp;lt;/tt&amp;gt; Bitschalter dem {{class|KConfig}} Konstruktor übergeben wird, was standardmässig der Fall ist.&lt;br /&gt;
&lt;br /&gt;
=== Allgemein nützliche Methoden ===&lt;br /&gt;
&lt;br /&gt;
Um den momentanen Zustand des Konfigurationsobjektes zu speichern, rufen wir die &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt;-Methode auf. Diese Methode wird also aufgerufen, wenn ein Objekt zerstört wird. Falls keine Änderungen gemacht wurden, oder die Ressource weist sich als nicht beschreibbar aus (Wenn der Benutzer zum Beispiel nicht genug Rechte hat, um die Datei zu bearbeiten), dann wird keine Beschäftigung der Festplatte hervorgerufen. &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; verschmilzt Änderungen die gleichzeitig von anderen Prozessen ausgeführt werden - lokale Änderungen haben aber trotzdem Vorrang.&lt;br /&gt;
&lt;br /&gt;
Wenn wir sicher gehen wollen, dass wir die aktuellsten Werte von der Festplatte haben, dann rufen wir &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt; auf, welches &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; aufruft und dann die Daten von der Festplatte aktualisiert.&lt;br /&gt;
&lt;br /&gt;
Falls wir verhindern müssen, dass das Konfigurationsobjekt bereits gemachte Änderungen nicht auf die Festplatte speichert, müssen wir &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt; aufrufen. Ein besonderer Anwendungsfall ist es, die Konfiguration zum Festplatten-Zustand zurückzusetzen indem man &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt; gefolgt von &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt; aufruft.&lt;br /&gt;
&lt;br /&gt;
Alle Gruppen in einem Konfigurationsobjekt aufzurufen ist so einfach wie hier in diesem Code-Abschnitt &amp;lt;tt&amp;gt;groupList()&amp;lt;/tt&amp;gt; aufzurufen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::mainComponent().config();&lt;br /&gt;
&lt;br /&gt;
foreach ( const QString&amp;amp; group, config.groupList() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;next group:&amp;quot; &amp;lt;&amp;lt; group;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== KSharedConfig ==&lt;br /&gt;
&lt;br /&gt;
Die {{class|KSharedConfig}} Klasse ist eine Referenz-gezählte Version von {{class|KConfig}}. Darum stellt es eine Möglichkeit bereit, das selbe Konfigurationsobjekt von unterschiedlichen Orten zu referenzieren ohne zusätzlich die Objekte trennen zu müssen oder sich um die Synchronisation des Schreibvorgangs zu kümmern, selbst wenn das Konfigurationsobjekt von verschiedenen Code-Pfaden aktualisiert wird.&lt;br /&gt;
&lt;br /&gt;
Auf ein {{class|KSharedConfig}}-Objekt zuzugreifen ist so einfach wie das hier:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KSharedConfigPtr config = KSharedConfig::openConfig();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;openConfig()&amp;lt;/tt&amp;gt; nimmt die selben Parameter wie {{class|KConfig}}'s Konstruktoren, was es einem ermöglicht zu definieren, welche Konfigurationsdatei zu öffnen und Markierungen das Verschmelzen von nicht-&amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt;-Ressourcen zu kontrollieren.  &lt;br /&gt;
&lt;br /&gt;
Es wird grundsätzlich empfohlen {{class|KSharedConfig}} anstatt {{class|KConfig}} selbst zu benutzen, und auch das Objekt, das von {{class|KComponentData}} zurückgegeben wird ist in der Tat ein {{class|KSharedConfig}}-Objekt.&lt;br /&gt;
&lt;br /&gt;
== KConfigGroup ==&lt;br /&gt;
&lt;br /&gt;
Nun da wir ein Konfigurationsobjekt haben, ist der nächste Schritt es tatsächlich zu nutzen. Das erste, das wir tun müssen, ist zu bestimmen, auf welche Gruppe von Schlüssel-/Wertepaare wir in unserem Objekt zugreifen wollen. Wir tun das, indem wir ein KConfigGroup-Objekt erstellen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig config;&lt;br /&gt;
KConfigGroup generalGroup( &amp;amp;config, &amp;quot;General&amp;quot; );&lt;br /&gt;
KConfigGroup colorsGroup = config.group( &amp;quot;Colors&amp;quot; ); // ...oder so ähnlich...&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Man kann{{class|KConfigGroup}} {{class|KConfig}}- oder {{class|KSharedConfig}}-Objekte übergeben.&lt;br /&gt;
&lt;br /&gt;
Konfigurationsgruppen können ebenfalls verschachtelt werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfigGroup subGroup1( &amp;amp;generalGroup, &amp;quot;LessGeneral&amp;quot; );&lt;br /&gt;
KConfigGroup subGroup2 = colorsGroup.group( &amp;quot;Dialogs&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Lesen von Einträgen ==&lt;br /&gt;
&lt;br /&gt;
Wenn man erst einmal ein {{class|KConfigGroup}}-Objekt erstellt hat, ist das Lesen von Einträgen ziemlich einfach:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
QString accountName = generalGroup.readEntry( &amp;quot;Account&amp;quot;,&lt;br /&gt;
                                              QString() );&lt;br /&gt;
QColor color = colorsGroup.readEntry( &amp;quot;background&amp;quot;,&lt;br /&gt;
                                      Qt::white );&lt;br /&gt;
QStringList list = generalGroup.readEntry( &amp;quot;List&amp;quot;,&lt;br /&gt;
                                           QStringList() );&lt;br /&gt;
QString path = generalGroup.readPathEntry( &amp;quot;SaveTo&amp;quot;,&lt;br /&gt;
                                           defaultPath );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wie man hier oben sehen kann, kann man Lesevorgänge von verschiedenen {{class|KConfigGroup}}-Objekten, die auf dem selben {{class|KConfig}}-Objekt erstellt wurden, problemlos mischen. Die Lese-Methoden nehmen den Schlüssel, der Gross- und Kleinschreibung unterscheidet, als erstes Argument und den Standardwert als zweites Argument. Dieses Argument bestimmt auch welche Art von Daten, also z.B. eine Farbe in Zeile 3, erwartet wird und auch die Art von Objekt, die zurückgegeben werden soll.Das zurückgegebene Objekt wird in eine {{qt|QVariant}} gepackt um diese Hexerei zu ermöglichen. &lt;br /&gt;
&lt;br /&gt;
Es gibt eine Anzahl von speziellen Methoden, zum Beispiel &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt;, das einen Datei-Systempfad zurückgibt. Es ist entscheidend, dass man &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; benutzt, wenn man nach einem Pfad fragt, das es Funktionen wie Erreichbarkeits-Profile ermöglicht richtig zu funktionieren.&lt;br /&gt;
&lt;br /&gt;
Wenn kein solcher Schlüssel im Konfigurationsobjekt existiert, dann wird stattdessen der Standardwert zurückgegeben. Falls es eine lokalisierte (d.h. in eine andere Sprache übersetzte) Version für den Schlüssel gibt, die der eingestellten Sprache entspricht, dann wird diese zurückgegeben.&lt;br /&gt;
&lt;br /&gt;
== Schreiben neuer Einträge ==&lt;br /&gt;
&lt;br /&gt;
Neue Werte zu definieren ist ähnlich einfach:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
generalGroup.writeEntry( &amp;quot;Account&amp;quot;, accountName );&lt;br /&gt;
generalGroup.writePathEntry( &amp;quot;SaveTo&amp;quot;, savePath );&lt;br /&gt;
colorGroup.writeEntry( &amp;quot;background&amp;quot;, color );&lt;br /&gt;
generalGroup.config()-&amp;gt;sync();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beachten sie die Benutzung von &amp;lt;tt&amp;gt;writePathEntry&amp;lt;/tt&amp;gt; und wie die Art von Objekt, das wir benutzen, wie zum Beispiel {{qt|QColor}} auf Zeile 3, bestimmt, wie die Daten angeordnet werden. Zusätzlich, wenn wir mit den Einträgen fertig sind, muss &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; auf das Konfigurationsobjekt ausgeführt werden, um es auf die Festplatte zu speichern. Man kann auch einfach warten, bis das Objekt zerstört wird, was falls nötig automatisch einen &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; auslöst.&lt;br /&gt;
&lt;br /&gt;
== KDesktopFile: Ein besonderer Fall ==&lt;br /&gt;
&lt;br /&gt;
Wann ist eine Konfigurationsdatei keine Konfigurationsdatei? Wenn es eine [http://freedesktop.org/wiki/Standards_2fdesktop_2dentry_2dspec Desktop-Datei] ist. Diese Dateien, die im Grunde genommen Konfigurationsdateien sind, werden benutzt um Einträge für Anwendungsmenüs, Dateitypen, Plugins und verschiedene Services.&lt;br /&gt;
&lt;br /&gt;
Wenn auf eine .desktop Datei zugegriffen wird, sollte man stattdessen die  {{class|KDesktopFile}}-Klasse verwenden, die, während eine {{class|KConfig}}-Klasse über alle oben genannten Ressourcen verfügt, über eine Anzahl von Methoden verfügt, um das Zugreifen auf Standard-Attribute dieser Dateien konsistent und zuverlässig zu machen.&lt;br /&gt;
&lt;br /&gt;
== Kiosk: Abriegelung und Benutzer-/Gruppenprofile ==&lt;br /&gt;
&lt;br /&gt;
KConfig stellt eine Reihe von leistungsstarken Abriegelungs- und Konfigurations-Definitionen bereit, insgesamt als &amp;quot;Kiosk&amp;quot; bekannt, worauf viele System-Administratoren und -Integratoren basieren. Während ein Grossteil dieses Systems der Anwendung transparent bereitgestellt wird, ist es möglich dass man den Schreib/Lese-Status eines Konfigurationsobjekts prüfen will.&lt;br /&gt;
&lt;br /&gt;
Einträge in Konfigurationsobjekten die mithilfe von Kiosk abgeriegelt sind, werden &amp;quot;unveränderlich&amp;quot; genannt. Eine Anwendung kann nach der Unveränderlichkeit von ganzen Konfigurationsobjekten, Gruppen oder Schlüsseln, wie in diesem Beispiel gezeigt, fragen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::config();&lt;br /&gt;
&lt;br /&gt;
if ( config-&amp;gt;isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;Konfigurationsobjekt ist unveränderlich&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
KConfigGroup group(config, &amp;quot;General&amp;quot;);&lt;br /&gt;
if ( group.isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;Die Gruppe 'General' ist unveränderlich&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if ( group.entryIsImmutable(&amp;quot;URL&amp;quot;) ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;Der URL Eintrag in der Gruppe 'General' ist unveränderlich&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das kann in gewissen Situationen, wo eine Aktion ausgeführt werden soll, falls ein Objekt unveränderlich ist.&lt;br /&gt;
&lt;br /&gt;
== KConfig XT ==&lt;br /&gt;
&lt;br /&gt;
Es gibt einen Weg, gewisse Anwendungsfälle von KConfig einfacher, schneller und zuverlässiger zu  machen: KConfig XT. Im Bestimmten kann KConfig XT bei Hauptanwendungs- oder Plug-In-Konfigurationsobjekten und bei Konfigurationsdialogen und anderen Benutzeroberflächen mit diesen Werten sehr hilfreich sein. Es dokumentiert gleichzeitig auch alle verfügbaren Konfigurations-Optionen, was alle System-Administratoren und -Integratoren, die KDE benutzen so viel glücklicher macht.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[../Using_KConfig_XT_de|Die nächste Anleitung handelt über KConfig XT und wie es zu benutzen.]]&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials/KConfig_(de)</id>
		<title>Development/Tutorials/KConfig (de)</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials/KConfig_(de)"/>
				<updated>2008-02-07T13:02:20Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: /* Kiosk: Lockdown and User/Group Profiles */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:I18n/Language Navigation Bar|Development/Tutorials/KConfig}}&lt;br /&gt;
&lt;br /&gt;
{{TutorialBrowser (de)|&lt;br /&gt;
&lt;br /&gt;
series=KConfig|&lt;br /&gt;
&lt;br /&gt;
name=Einführung in KConfig|&lt;br /&gt;
&lt;br /&gt;
pre=Keine|&lt;br /&gt;
&lt;br /&gt;
next=[[../Using_KConfig_XT|Benutzen von KConfig XT]]|&lt;br /&gt;
&lt;br /&gt;
reading=Keine&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{improve (de)}}&lt;br /&gt;
&lt;br /&gt;
== Zusammenfassung ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dieser Artikel beschäftigt sich mir dem KDE Einstellungdaten-System, angefangen mit einer Übersicht über den grundlegenden Aufbau aus der Sicht eines Entwicklers. Es wirft ausserdem einen Blick auf jede der Klassen, die für die Entwicklung von Anwendungen relevant sind und fährt dann mit kiosk (Benutzer- und Gruppenprofile) Integration fort.&lt;br /&gt;
&lt;br /&gt;
== Grundlegender Aufbau ==&lt;br /&gt;
&lt;br /&gt;
KConfig ist ausgelegt um das Konzept vom eigentlichen Speichern und Auffinden von Konfigurationsdaten hinter eine Programmierschnittstelle zu abstrahieren die es ermöglicht, auf einfache Weise Informationen abzurufen und zu setzen. Wo oder in welcher Form Daten gespeichert werden ist für eine Anwendung die KConfig benutzt irrelevant.&lt;br /&gt;
&lt;br /&gt;
Das behält alle KDE Anwendungen konsistent in ihrer Art, Konfigurationen handzuhaben und nimmt einem Anwendungs-Entwickler die Arbeit so ein System von Grund auf neu zu schreiben, was ein sehr fehleranfälliger Prozess sein kann.&lt;br /&gt;
&lt;br /&gt;
Jedes KConfig Objekt verkörpert ein einziges Konfigurationsobjekt. Jedes Konfigurationsobjekt ist durch seinen einzigartigen Namen gekennzeichnet und kann von mehreren lokalen oder externen Daten oder Services gelesen werden. Jede Anwendung hat standardmässig ein zugehöriges Konfigurationsobjekt und es gibt auch ein globales Konfigurationsobjekt.&lt;br /&gt;
&lt;br /&gt;
Diese Konfigurationsobjekte sind nach einer zweistufigen Hierarchie getrennt: Gruppen und Schlüssel. Ein Konfigurationsobjekt kann eine beliebige Anzahl an Gruppen haben und jede Gruppe kann einen oder mehrere Schlüssel mit zugehörigen Werten haben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die gespeicherten Werte können aus beliebig vielen verschiedenen Datentypen bestehen. Sie werden gespeichert und abgerufen als das Objekt selbst. Zum Beispiel wird ein {{qt|QObject}}-Objekt direkt einem Konfigurationsobjekt übergeben, wenn es einen Farbwert speichert und wenn ein Farbwert abgerufen wird, wird ein {{qt|QObject}}-Objekt zurückgegeben.&lt;br /&gt;
&lt;br /&gt;
{{note (de)| deserialization  entgliedern? &amp;lt;br&amp;gt; &amp;lt;tt&amp;gt; &amp;quot;do not have to perform serialization and deserialization of objects themselves&amp;quot; &amp;lt;/tt&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Anwendungen selbst müssen darum normalerweise Objekte nicht selber gliedern und entgliedern.&lt;br /&gt;
&lt;br /&gt;
== Die KConfig Klasse ==&lt;br /&gt;
&lt;br /&gt;
Das {{class|KConfig}}-Objekt wird benutzt um ein bestehendes Konfigurationsobjekt anzusteuern. Es gibt eine Reihe von Möglichkeiten ein Konfigurationsobjekt zu erstellen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
// ein einfaches, altes lesen/schreiben Konfigurationsobjekt&lt;br /&gt;
KConfig config(&amp;quot;myapprc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// eine bestimmte Datei im Dateisystem&lt;br /&gt;
// currently must be an INI style file&lt;br /&gt;
KConfig fullPath(&amp;quot;/etc/kderc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// nicht mit globalen Werten verflochten&lt;br /&gt;
KConfig globalFree( &amp;quot;localsrc&amp;quot;, KConfig::NoGlobals );&lt;br /&gt;
&lt;br /&gt;
// nicht mit globalen Werten orde der $KDEDIRS Hierarchie verflochten&lt;br /&gt;
KConfig simpleConfig( &amp;quot;simplerc&amp;quot;, KConfig::SimpleConfig );&lt;br /&gt;
&lt;br /&gt;
// Komponenten-spezifische Konfiguration, in diesem Fall ein Plugin&lt;br /&gt;
KConfig pluginConfig( componentData(), &amp;quot;pluginrc&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
// Ausserhalb der normalen Konfigurations-Ressource&lt;br /&gt;
KConfig dataResource( &amp;quot;data&amp;quot;, &amp;quot;myapp/somefile&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{note (de)|wie soll &amp;quot;merged&amp;quot; in den folgenden Fällen übersetzt werden? &amp;lt;br&amp;gt; &amp;lt;tt&amp;gt;&amp;quot;verschmolzen&amp;quot; oder &amp;quot;verflochten&amp;quot;&amp;lt;/tt&amp;gt; &amp;lt;br&amp;gt; der Anwendung selber transparent&amp;quot; tönt auch nicht sehr gut}}&lt;br /&gt;
&lt;br /&gt;
Das Kconfig Objekt, das wir auf Zeile 2 erstellen ist ein gewöhnliches Konfigurationsobjekt. Wir können Werte aus ihm lesen, neue Einträge schreiben und nach verschiedenen Eigenschaften des Objekts fragen. Dieses Objekt wird aus der Konfigurations-Ressource geladen, wie es durch {{class|KStandardDirs}} bestimmt wird, das heisst, dass jede Instanz des &amp;lt;tt&amp;gt;myapprc&amp;lt;/tt&amp;gt;-Objekts in jedem der Ordner in der Konfigurations-Ressourcen-Hierarchie verschmolzen werden um die Werte zu erzeugen, die in diesem Objekt gesehen werden. So werden Systemweite und &lt;br /&gt;
pro-Benutzer/Gruppen Profile erstellt und unterstützt. Das alles geschieht der Anwendung selber transparent.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{tip| Für mehr Informationen, wie das Verschmelzen funktioniert, siehe diesen Artikel über die [[KDE System Administration/KDE_Filesystem_Hierarchy|KDE Dateisystem Hierarchie]].}}&lt;br /&gt;
&lt;br /&gt;
{{note (de)|Ist das so gemeint mit &amp;quot;expects an INI style file&amp;quot;&amp;lt;br&amp;gt; &amp;lt;tt&amp;gt; On line 6 we open a specific local file, this case /etc/kderc. This performs no merging of values and expects an INI style file.&amp;lt;/tt&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Auf Zeile 6 öffnen wir eine bestimmte Lokale Datei, in diesem Fall {{path|/etc/kderc}}. Das führt kein verschmelzen von Werten aus und erwartet eine Datei im INI Format.&lt;br /&gt;
&lt;br /&gt;
Zeile 9 erzeugt ein Konfigurationsobjekt, dass nicht mit dem globalen &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt;-Konfigurationsobjekt verflochten ist,  während das Konfigurationsobjekt auf Zeile 12 zusätzlich mit keinem der Dateien in der &amp;lt;tt&amp;gt;$KDEDIRS&amp;lt;/tt&amp;gt;-Hierarchie verflochten ist. Das kann die Leistung spürbar verbessern, falls man einfach nur Werte aus einer einfachen Konfuguration liest und globale Werte keine Rolle spielen.&lt;br /&gt;
&lt;br /&gt;
Zeile 15 erzeugt ein Konfigurationsobjekt unter Benutzung des {{class|KComponentData}}-Objekts das zu einem Plugin oder einer anderen Komponente gehört. Das Plugin kann verschiedene Ordner aufweisen, die in seinen {{class|KStandardDirs}} definiert sind und das ist eine Möglichkeit sich zu versichern, dass {{class|KConfig}} das respektiert.&lt;br /&gt;
&lt;br /&gt;
Und schliesslich auf Zeile 18 erzeugen wir ein Konfigurationsobjekt, das nicht in der &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt;-Ressource sondern in der &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt;-Ressource existiert. Man kann kann auf diese Weise jede Ressource verwenden, von denen {{class|KStandardDirs}} Kenntnis hat, auch solche die während der Laufzeit hinzugefügt werden.&lt;br /&gt;
&lt;br /&gt;
=== Spezielle Konfigurationsobjekte ===&lt;br /&gt;
&lt;br /&gt;
Jede Anwendung hat sein eigenes Konfigurationsobjekt das den Namen benutzt, der von {{class|KAboutData}} bereitgestellt wird mit angehängtem &amp;quot;rc&amp;quot;. Also hätte eine Anwendung mit dem Namen &amp;quot;myapp&amp;quot; das Standard-Konfigurationsobjekt &amp;quot;myapprc&amp;quot;. Dieses Konfigurationsobjekt kann auf diese Weise aufgerufen werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KComponentData&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
#include &amp;lt;KGlobal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    // beachten sie, dass dies eigentlich ein KSharedConfig ist&lt;br /&gt;
    // mehr über diese Klasse siehe weiter unten&lt;br /&gt;
    KConfig* config = KGlobal::config();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Auf das Standard-Konfigurationsobjekt für die Anwendung wird zugegriffen, wenn kein Name definiert wurde, als das {{class|KConfig}}-Objekt erzeugt wurde. Also könnten wir stattdessen auch das tun:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    KConfig config;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zusätzlich könnte jede Komponente sein eigenes Konfigurationsobjekt haben. Auf dieses wird normalerweise durch die &amp;lt;tt&amp;gt;componentData()&amp;lt;/tt&amp;gt; des Plugins zugegriffen, anstatt durch die &amp;lt;tt&amp;gt;{{class|KGlobal}}::mainComponent()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Und schliesslich gibt es noch ein globales Konfigurationsobjekt, &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt;, das von jeder Anwendung verwendet wird. Es enthält Informationen wie die Standard-Tatenkombinationen für verschiedene Aktionen. Es wird in das Konfigurationsobjekt &amp;quot;gemischt&amp;quot; wenn der &amp;lt;tt&amp;gt;KConfig::IncludeGlobals&amp;lt;/tt&amp;gt; Bitschalter dem {{class|KConfig}} Konstruktor übergeben wird, was standardmässig der Fall ist.&lt;br /&gt;
&lt;br /&gt;
=== Allgemein nützliche Methoden ===&lt;br /&gt;
&lt;br /&gt;
Um den momentanen Zustand des Konfigurationsobjektes zu speichern, rufen wir die &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt;-Methode auf. Diese Methode wird also aufgerufen, wenn ein Objekt zerstört wird. Falls keine Änderungen gemacht wurden, oder die Ressource weist sich als nicht beschreibbar aus (Wenn der Benutzer zum Beispiel nicht genug Rechte hat, um die Datei zu bearbeiten), dann wird keine Beschäftigung der Festplatte hervorgerufen. &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; verschmilzt Änderungen die gleichzeitig von anderen Prozessen ausgeführt werden - lokale Änderungen haben aber trotzdem Vorrang.&lt;br /&gt;
&lt;br /&gt;
Wenn wir sicher gehen wollen, dass wir die aktuellsten Werte von der Festplatte haben, dann rufen wir &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt; auf, welches &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; aufruft und dann die Daten von der Festplatte aktualisiert.&lt;br /&gt;
&lt;br /&gt;
Falls wir verhindern müssen, dass das Konfigurationsobjekt bereits gemachte Änderungen nicht auf die Festplatte speichert, müssen wir &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt; aufrufen. Ein besonderer Anwendungsfall ist es, die Konfiguration zum Festplatten-Zustand zurückzusetzen indem man &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt; gefolgt von &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt; aufruft.&lt;br /&gt;
&lt;br /&gt;
Alle Gruppen in einem Konfigurationsobjekt aufzurufen ist so einfach wie hier in diesem Code-Abschnitt &amp;lt;tt&amp;gt;groupList()&amp;lt;/tt&amp;gt; aufzurufen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::mainComponent().config();&lt;br /&gt;
&lt;br /&gt;
foreach ( const QString&amp;amp; group, config.groupList() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;next group:&amp;quot; &amp;lt;&amp;lt; group;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== KSharedConfig ==&lt;br /&gt;
&lt;br /&gt;
Die {{class|KSharedConfig}} Klasse ist eine Referenz-gezählte Version von {{class|KConfig}}. Darum stellt es eine Möglichkeit bereit, das selbe Konfigurationsobjekt von unterschiedlichen Orten zu referenzieren ohne zusätzlich die Objekte trennen zu müssen oder sich um die Synchronisation des Schreibvorgangs zu kümmern, selbst wenn das Konfigurationsobjekt von verschiedenen Code-Pfaden aktualisiert wird.&lt;br /&gt;
&lt;br /&gt;
Auf ein {{class|KSharedConfig}}-Objekt zuzugreifen ist so einfach wie das hier:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KSharedConfigPtr config = KSharedConfig::openConfig();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;openConfig()&amp;lt;/tt&amp;gt; nimmt die selben Parameter wie {{class|KConfig}}'s Konstruktoren, was es einem ermöglicht zu definieren, welche Konfigurationsdatei zu öffnen und Markierungen das Verschmelzen von nicht-&amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt;-Ressourcen zu kontrollieren.  &lt;br /&gt;
&lt;br /&gt;
Es wird grundsätzlich empfohlen {{class|KSharedConfig}} anstatt {{class|KConfig}} selbst zu benutzen, und auch das Objekt, das von {{class|KComponentData}} zurückgegeben wird ist in der Tat ein {{class|KSharedConfig}}-Objekt.&lt;br /&gt;
&lt;br /&gt;
== KConfigGroup ==&lt;br /&gt;
&lt;br /&gt;
Nun da wir ein Konfigurationsobjekt haben, ist der nächste Schritt es tatsächlich zu nutzen. Das erste, das wir tun müssen, ist zu bestimmen, auf welche Gruppe von Schlüssel-/Wertepaare wir in unserem Objekt zugreifen wollen. Wir tun das, indem wir ein KConfigGroup-Objekt erstellen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig config;&lt;br /&gt;
KConfigGroup generalGroup( &amp;amp;config, &amp;quot;General&amp;quot; );&lt;br /&gt;
KConfigGroup colorsGroup = config.group( &amp;quot;Colors&amp;quot; ); // ...oder so ähnlich...&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Man kann{{class|KConfigGroup}} {{class|KConfig}}- oder {{class|KSharedConfig}}-Objekte übergeben.&lt;br /&gt;
&lt;br /&gt;
Konfigurationsgruppen können ebenfalls verschachtelt werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfigGroup subGroup1( &amp;amp;generalGroup, &amp;quot;LessGeneral&amp;quot; );&lt;br /&gt;
KConfigGroup subGroup2 = colorsGroup.group( &amp;quot;Dialogs&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Lesen von Einträgen ==&lt;br /&gt;
&lt;br /&gt;
Wenn man erst einmal ein {{class|KConfigGroup}}-Objekt erstellt hat, ist das Lesen von Einträgen ziemlich einfach:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
QString accountName = generalGroup.readEntry( &amp;quot;Account&amp;quot;,&lt;br /&gt;
                                              QString() );&lt;br /&gt;
QColor color = colorsGroup.readEntry( &amp;quot;background&amp;quot;,&lt;br /&gt;
                                      Qt::white );&lt;br /&gt;
QStringList list = generalGroup.readEntry( &amp;quot;List&amp;quot;,&lt;br /&gt;
                                           QStringList() );&lt;br /&gt;
QString path = generalGroup.readPathEntry( &amp;quot;SaveTo&amp;quot;,&lt;br /&gt;
                                           defaultPath );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wie man hier oben sehen kann, kann man Lesevorgänge von verschiedenen {{class|KConfigGroup}}-Objekten, die auf dem selben {{class|KConfig}}-Objekt erstellt wurden, problemlos mischen. Die Lese-Methoden nehmen den Schlüssel, der Gross- und Kleinschreibung unterscheidet, als erstes Argument und den Standardwert als zweites Argument. Dieses Argument bestimmt auch welche Art von Daten, also z.B. eine Farbe in Zeile 3, erwartet wird und auch die Art von Objekt, die zurückgegeben werden soll.Das zurückgegebene Objekt wird in eine {{qt|QVariant}} gepackt um diese Hexerei zu ermöglichen. &lt;br /&gt;
&lt;br /&gt;
Es gibt eine Anzahl von speziellen Methoden, zum Beispiel &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt;, das einen Datei-Systempfad zurückgibt. Es ist entscheidend, dass man &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; benutzt, wenn man nach einem Pfad fragt, das es Funktionen wie Erreichbarkeits-Profile ermöglicht richtig zu funktionieren.&lt;br /&gt;
&lt;br /&gt;
Wenn kein solcher Schlüssel im Konfigurationsobjekt existiert, dann wird stattdessen der Standardwert zurückgegeben. Falls es eine lokalisierte (d.h. in eine andere Sprache übersetzte) Version für den Schlüssel gibt, die der eingestellten Sprache entspricht, dann wird diese zurückgegeben.&lt;br /&gt;
&lt;br /&gt;
== Schreiben neuer Einträge ==&lt;br /&gt;
&lt;br /&gt;
Neue Werte zu definieren ist ähnlich einfach:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
generalGroup.writeEntry( &amp;quot;Account&amp;quot;, accountName );&lt;br /&gt;
generalGroup.writePathEntry( &amp;quot;SaveTo&amp;quot;, savePath );&lt;br /&gt;
colorGroup.writeEntry( &amp;quot;background&amp;quot;, color );&lt;br /&gt;
generalGroup.config()-&amp;gt;sync();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beachten sie die Benutzung von &amp;lt;tt&amp;gt;writePathEntry&amp;lt;/tt&amp;gt; und wie die Art von Objekt, das wir benutzen, wie zum Beispiel {{qt|QColor}} auf Zeile 3, bestimmt, wie die Daten angeordnet werden. Zusätzlich, wenn wir mit den Einträgen fertig sind, muss &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; auf das Konfigurationsobjekt ausgeführt werden, um es auf die Festplatte zu speichern. Man kann auch einfach warten, bis das Objekt zerstört wird, was falls nötig automatisch einen &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; auslöst.&lt;br /&gt;
&lt;br /&gt;
== KDesktopFile: Ein besonderer Fall ==&lt;br /&gt;
&lt;br /&gt;
Wann ist eine Konfigurationsdatei keine Konfigurationsdatei? Wenn es eine [http://freedesktop.org/wiki/Standards_2fdesktop_2dentry_2dspec Desktop-Datei] ist. Diese Dateien, die im Grunde genommen Konfigurationsdateien sind, werden benutzt um Einträge für Anwendungsmenüs, Dateitypen, Plugins und verschiedene Services.&lt;br /&gt;
&lt;br /&gt;
Wenn auf eine .desktop Datei zugegriffen wird, sollte man stattdessen die  {{class|KDesktopFile}}-Klasse verwenden, die, während eine {{class|KConfig}}-Klasse über alle oben genannten Ressourcen verfügt, über eine Anzahl von Methoden verfügt, um das Zugreifen auf Standard-Attribute dieser Dateien konsistent und zuverlässig zu machen.&lt;br /&gt;
&lt;br /&gt;
== Kiosk: Abriegelung und Benutzer-/Gruppenprofile ==&lt;br /&gt;
&lt;br /&gt;
KConfig stellt eine Reihe von leistungsstarken Abriegelungs- und Konfigurations-Definitionen bereit, insgesamt als &amp;quot;Kiosk&amp;quot; bekannt, worauf viele System-Administratoren und -Integratoren basieren. Während ein Grossteil dieses Systems der Anwendung transparent bereitgestellt wird, ist es möglich dass man den Schreib/Lese-Status eines Konfigurationsobjekts prüfen will.&lt;br /&gt;
&lt;br /&gt;
Einträge in Konfigurationsobjekten die mithilfe von Kiosk abgeriegelt sind, werden &amp;quot;unveränderlich&amp;quot; genannt. Eine Anwendung kann nach der Unveränderlichkeit von ganzen Konfigurationsobjekten, Gruppen oder Schlüsseln, wie in diesem Beispiel gezeigt, fragen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::config();&lt;br /&gt;
&lt;br /&gt;
if ( config-&amp;gt;isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;Konfigurationsobjekt ist unveränderlich&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
KConfigGroup group(config, &amp;quot;General&amp;quot;);&lt;br /&gt;
if ( group.isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;Die Gruppe 'General' ist unveränderlich&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if ( group.entryIsImmutable(&amp;quot;URL&amp;quot;) ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;Der URL Eintrag in der Gruppe 'General' ist unveränderlich&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das kann in gewissen Situationen, wo eine Aktion ausgeführt werden soll, falls ein Objekt unveränderlich ist.&lt;br /&gt;
&lt;br /&gt;
== KConfig XT ==&lt;br /&gt;
&lt;br /&gt;
There is a way to make certain use cases of KConfig easier, faster and more reliable: KConfig XT. In particular, for main application or plugin configuration objects and when syncing configuration dialogs and other interfaces with these values, KConfig XT can help immensely. It also  simultaneously documents the configuration options available, which makes every sys admin and system integrator that uses KDE that much more happy.&lt;br /&gt;
&lt;br /&gt;
[[../Using_KConfig_XT|The next tutorial in the KConfig series covers what KConfig XT is and how to use it.]]&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials/Saving_and_loading_(de)</id>
		<title>Development/Tutorials/Saving and loading (de)</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials/Saving_and_loading_(de)"/>
				<updated>2008-01-21T21:19:39Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:I18n/Language Navigation Bar|Development/Tutorials/Saving_and_loading}}&lt;br /&gt;
&lt;br /&gt;
{{TutorialBrowser (de)|&lt;br /&gt;
&lt;br /&gt;
series=Anleitung für Anfänger|&lt;br /&gt;
&lt;br /&gt;
name=Laden und Speichern von Dateien|&lt;br /&gt;
&lt;br /&gt;
pre=[[Development/Tutorials/Using_KActions (de)|Anleitung 3 - KActions benutzen]]|&lt;br /&gt;
&lt;br /&gt;
next=[[Development/Tutorials/KCmdLineArgs (de)|Anleitung 5 - KCmdLineArgs benutzen]]| &lt;br /&gt;
&lt;br /&gt;
reading=KIO::{{class|NetAccess}} {{qt|QFile}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Zusammenfassung==&lt;br /&gt;
&lt;br /&gt;
In diesem Kapitel werden sie lernen, wie man grundsätzliche Datei-Aktionen wie Laden und  Speichern mithilfe der KIO Bibliothek einbindet.&lt;br /&gt;
&lt;br /&gt;
KDE stellt eine Anzahl von Klassen bereit um das Arbeiten mit Dateien für die Entwickler deutlich zu vereinfachen. Die KIO Bibliothek ermöglicht es Dateien auf einfache Weise über Netzwerk-transparente Protokolle anzusteuern und stellt auch Standard Dateidialoge bereit.&lt;br /&gt;
&lt;br /&gt;
[[image:introtokdetutorial4.png|frame|center]]&lt;br /&gt;
&lt;br /&gt;
== Der Code ==&lt;br /&gt;
&lt;br /&gt;
===main.cpp===&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KApplication&amp;gt;&lt;br /&gt;
#include &amp;lt;KAboutData&amp;gt;&lt;br /&gt;
#include &amp;lt;KCmdLineArgs&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
#include &amp;quot;mainwindow.h&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
int main (int argc, char *argv[])&lt;br /&gt;
{&lt;br /&gt;
  KAboutData aboutData( &amp;quot;tutorial4&amp;quot;, &amp;quot;tutorial4&amp;quot;,&lt;br /&gt;
      ki18n(&amp;quot;Tutorial 4&amp;quot;), &amp;quot;1.0&amp;quot;,&lt;br /&gt;
      ki18n(&amp;quot;A simple text area which can load and save.&amp;quot;),&lt;br /&gt;
      KAboutData::License_GPL,&lt;br /&gt;
      ki18n(&amp;quot;Copyright (c) 2007 Developer&amp;quot;) );&lt;br /&gt;
  KCmdLineArgs::init( argc, argv, &amp;amp;aboutData );&lt;br /&gt;
  KApplication app;&lt;br /&gt;
 &lt;br /&gt;
  MainWindow* window = new MainWindow();&lt;br /&gt;
  window-&amp;gt;show();&lt;br /&gt;
  return app.exec();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;tt&amp;gt;main.cpp&amp;lt;/tt&amp;gt; hat sich seit der dritten Anleitung nicht verändert, ausser das jeder Bezug zu 'tutorial 3' zu 'tutorial 4' geändert wurde.&lt;br /&gt;
&lt;br /&gt;
===mainwindow.h===&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#ifndef MAINWINDOW_H&lt;br /&gt;
#define MAINWINDOW_H&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;KXmlGuiWindow&amp;gt;&lt;br /&gt;
#include &amp;lt;KTextEdit&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class MainWindow : public KXmlGuiWindow&lt;br /&gt;
{&lt;br /&gt;
  Q_OBJECT //neu seit Anleitung 3&lt;br /&gt;
  &lt;br /&gt;
  public:&lt;br /&gt;
    MainWindow(QWidget *parent=0);&lt;br /&gt;
  &lt;br /&gt;
  private:&lt;br /&gt;
    KTextEdit* textArea;&lt;br /&gt;
    void setupActions();&lt;br /&gt;
    QString fileName; //neu&lt;br /&gt;
&lt;br /&gt;
  private slots: //neu&lt;br /&gt;
    void newFile(); //neu&lt;br /&gt;
    void openFile(); //neu&lt;br /&gt;
    void saveFile(); //neu&lt;br /&gt;
    void saveFileAs(); //neu&lt;br /&gt;
    void saveFileAs(const QString &amp;amp;outputFileName); //neu&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Da wir unserem Programm die Fähigkeit geben wollen, Dateien zu laden und zu speichern müssen wir Funktionen hinzufügen, die diese Arbeit erledigen werden. Da die Funktionen durch Qt's [http://doc.trolltech.com/latest/signalsandslots.html signal/slot]-Mechanismus aufgerufen werden, müssen wir definieren, dass diese Funktionen Slots sind, wie wir dies auf Zeile 19 machen. Da wir Slots in diesem Header-File benutzen, müssen wir auch das [http://doc.trolltech.com/latest/qobject.html#Q_OBJECT &amp;lt;tt&amp;gt;Q_OBJECT&amp;lt;/tt&amp;gt;] Makro hinzufügen.&lt;br /&gt;
&lt;br /&gt;
Wir werden auch den Dateinamen der momentan geöffneten Datei verfügbar haben wollen, also definieren wir einen &amp;lt;tt&amp;gt;{{qt|QString}} fileName&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===mainwindow.cpp===&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;quot;mainwindow.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;KApplication&amp;gt;&lt;br /&gt;
#include &amp;lt;KAction&amp;gt;&lt;br /&gt;
#include &amp;lt;KLocale&amp;gt;&lt;br /&gt;
#include &amp;lt;KActionCollection&amp;gt;&lt;br /&gt;
#include &amp;lt;KStandardAction&amp;gt;&lt;br /&gt;
#include &amp;lt;KFileDialog&amp;gt; //neu&lt;br /&gt;
#include &amp;lt;KMessageBox&amp;gt; //neu&lt;br /&gt;
#include &amp;lt;KIO/NetAccess&amp;gt; //neu&lt;br /&gt;
#include &amp;lt;KSaveFile&amp;gt; //neu&lt;br /&gt;
#include &amp;lt;QTextStream&amp;gt; //neu&lt;br /&gt;
 &lt;br /&gt;
MainWindow::MainWindow(QWidget *parent)&lt;br /&gt;
    : KXmlGuiWindow(parent),&lt;br /&gt;
      fileName(QString()) //neu&lt;br /&gt;
{&lt;br /&gt;
  textArea = new KTextEdit;&lt;br /&gt;
  setCentralWidget(textArea);&lt;br /&gt;
 &lt;br /&gt;
  setupActions();&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
void MainWindow::setupActions()&lt;br /&gt;
{&lt;br /&gt;
  KAction* clearAction = new KAction(this);&lt;br /&gt;
  clearAction-&amp;gt;setText(i18n(&amp;quot;Clear&amp;quot;));&lt;br /&gt;
  clearAction-&amp;gt;setIcon(KIcon(&amp;quot;document-new&amp;quot;));&lt;br /&gt;
  clearAction-&amp;gt;setShortcut(Qt::CTRL + Qt::Key_W);&lt;br /&gt;
  actionCollection()-&amp;gt;addAction(&amp;quot;clear&amp;quot;, clearAction);&lt;br /&gt;
  connect(clearAction, SIGNAL(triggered(bool)),&lt;br /&gt;
          textArea, SLOT(clear()));&lt;br /&gt;
 &lt;br /&gt;
  KStandardAction::quit(kapp, SLOT(quit()),&lt;br /&gt;
                        actionCollection());&lt;br /&gt;
 &lt;br /&gt;
  KStandardAction::open(this, SLOT(openFile()),&lt;br /&gt;
                        actionCollection()); //neu&lt;br /&gt;
 &lt;br /&gt;
  KStandardAction::save(this, SLOT(saveFile()),&lt;br /&gt;
                        actionCollection()); //neu&lt;br /&gt;
 &lt;br /&gt;
  KStandardAction::saveAs(this, SLOT(saveFileAs()),&lt;br /&gt;
                        actionCollection()); //neu&lt;br /&gt;
 &lt;br /&gt;
  KStandardAction::openNew(this, SLOT(newFile()),&lt;br /&gt;
                        actionCollection()); //neu&lt;br /&gt;
 &lt;br /&gt;
  setupGUI();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Neu ab hier&lt;br /&gt;
&lt;br /&gt;
void MainWindow::newFile()&lt;br /&gt;
{&lt;br /&gt;
  fileName.clear();&lt;br /&gt;
  textArea-&amp;gt;clear();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void MainWindow::saveFileAs(const QString &amp;amp;outputFileName)&lt;br /&gt;
{&lt;br /&gt;
  KSaveFile file(outputFileName);&lt;br /&gt;
  file.open();&lt;br /&gt;
  &lt;br /&gt;
  QByteArray outputByteArray;&lt;br /&gt;
  outputByteArray.append(textArea-&amp;gt;toPlainText());&lt;br /&gt;
  file.write(outputByteArray);&lt;br /&gt;
  file.finalize();&lt;br /&gt;
  file.close();&lt;br /&gt;
  &lt;br /&gt;
  fileName = outputFileName;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void MainWindow::saveFileAs()&lt;br /&gt;
{&lt;br /&gt;
  saveFileAs(KFileDialog::getSaveFileName());&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void MainWindow::saveFile()&lt;br /&gt;
{&lt;br /&gt;
  if(!fileName.isEmpty())&lt;br /&gt;
  {&lt;br /&gt;
    saveFileAs(fileName);&lt;br /&gt;
  }&lt;br /&gt;
  else&lt;br /&gt;
  {&lt;br /&gt;
    saveFileAs();&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void MainWindow::openFile()&lt;br /&gt;
{&lt;br /&gt;
  QString fileNameFromDialog = KFileDialog::getOpenFileName();&lt;br /&gt;
&lt;br /&gt;
  QString tmpFile;&lt;br /&gt;
  if(KIO::NetAccess::download(fileNameFromDialog, tmpFile, &lt;br /&gt;
         this))&lt;br /&gt;
  {&lt;br /&gt;
    QFile file(tmpFile);&lt;br /&gt;
    file.open(QIODevice::ReadOnly);&lt;br /&gt;
    textArea-&amp;gt;setPlainText(QTextStream(&amp;amp;file).readAll());&lt;br /&gt;
    fileName = fileNameFromDialog;&lt;br /&gt;
&lt;br /&gt;
    KIO::NetAccess::removeTempFile(tmpFile);&lt;br /&gt;
  }&lt;br /&gt;
  else&lt;br /&gt;
  {&lt;br /&gt;
    KMessageBox::error(this, &lt;br /&gt;
        KIO::NetAccess::lastErrorString());&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===tutorial4ui.rc===&lt;br /&gt;
&amp;lt;code xml n&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE kpartgui SYSTEM &amp;quot;kpartgui.dtd&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;gui name=&amp;quot;tutorial4&amp;quot; version=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;ToolBar name=&amp;quot;mainToolBar&amp;quot; &amp;gt;&lt;br /&gt;
    &amp;lt;text&amp;gt;Main Toolbar&amp;lt;/text&amp;gt;&lt;br /&gt;
    &amp;lt;Action name=&amp;quot;clear&amp;quot; /&amp;gt;&lt;br /&gt;
  &amp;lt;/ToolBar&amp;gt;&lt;br /&gt;
  &amp;lt;MenuBar&amp;gt;&lt;br /&gt;
    &amp;lt;Menu name=&amp;quot;file&amp;quot; &amp;gt;&lt;br /&gt;
      &amp;lt;Action name=&amp;quot;clear&amp;quot; /&amp;gt;&lt;br /&gt;
    &amp;lt;/Menu&amp;gt;&lt;br /&gt;
  &amp;lt;/MenuBar&amp;gt;&lt;br /&gt;
&amp;lt;/gui&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Dies ist identisch mit &amp;lt;tt&amp;gt;tutorial3ui.rc&amp;lt;/tt&amp;gt; aus Anleitung 3 ausser dass &amp;lt;tt&amp;gt;name&amp;lt;/tt&amp;gt; zu 'tutorial4' geändert wurde. Wir müssen keine Informationen über irgendeine der &amp;lt;tt&amp;gt;KStandardActions&amp;lt;/tt&amp;gt; hinzuzufügen da die Platzierung dieser Aktionen automatisch durch KDE erfolgt.&lt;br /&gt;
&lt;br /&gt;
==Erklärung==&lt;br /&gt;
&lt;br /&gt;
Nun kommen wir zum Code, der das Laden und Speichern erledigen wird. Das wird alles in &amp;lt;tt&amp;gt;mainwindow.cpp&amp;lt;/tt&amp;gt; passieren.&lt;br /&gt;
&lt;br /&gt;
Als erstes fügen wir&lt;br /&gt;
&amp;lt;code cppqt&amp;gt;&lt;br /&gt;
fileName(QString())&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
der &amp;lt;tt&amp;gt;MainWindow&amp;lt;/tt&amp;gt; Konstruktor-Liste auf Zeile 16 hinzu. Das stellt sicher, dass &amp;lt;tt&amp;gt;fileName&amp;lt;/tt&amp;gt; von Anfang an leer ist.&lt;br /&gt;
&lt;br /&gt;
===Hinzufügen der Aktionen===&lt;br /&gt;
&lt;br /&gt;
Als nächstes werden wir das äusserliche Interface für den Benutzer bereitstellen, so dass er der Anwendung mitteilen kann zu laden und zu speichern. Wie mit der &amp;lt;tt&amp;gt;quit&amp;lt;/tt&amp;gt; Aktion in Anleitung 3 werden wir &amp;lt;tt&amp;gt;KStandardActions&amp;lt;/tt&amp;gt; verwenden. Auf Zeilen 37 bis 47 werden wir die Aktionen auf die selbe Weise hinzufügen wie für die &amp;lt;tt&amp;gt;quit&amp;lt;/tt&amp;gt; Aktion. Für jedes einzelne werden wir es mit dem richtigen Slot verbinden den wir in der Header Datei definiert haben.&lt;br /&gt;
&lt;br /&gt;
===Erstellen eines neuen Dokuments===&lt;br /&gt;
&lt;br /&gt;
Die erste Funktion die wir erstellen ist &amp;lt;tt&amp;gt;newFile()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt&amp;gt;&lt;br /&gt;
void MainWindow::newFile()&lt;br /&gt;
{&lt;br /&gt;
  fileName.clear();&lt;br /&gt;
  textArea-&amp;gt;clear();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;tt&amp;gt;fileName.clear()&amp;lt;/tt&amp;gt; setzt den &amp;lt;tt&amp;gt;fileName&amp;lt;/tt&amp;gt; QString auf leer um zu zeigen, dass dieses Dokument noch keine Präsenz auf der Festplatte hat. &amp;lt;tt&amp;gt;textArea-&amp;gt;clear()&amp;lt;/tt&amp;gt; leert dann das zentrale Textfeld unter Verwendung der gleichen Funktion mit der wir die &amp;lt;tt&amp;gt;clear&amp;lt;/tt&amp;gt; &amp;lt;tt&amp;gt;KAction&amp;lt;/tt&amp;gt; in Anleitung 3 verbunden haben.&lt;br /&gt;
&lt;br /&gt;
===Speichern einer Datei===&lt;br /&gt;
&lt;br /&gt;
====saveFileAs(QString)====&lt;br /&gt;
&lt;br /&gt;
Jetzt kommen wir zum ersten Datei-Handhabungs-Code. Wir werden eine Funktion einführen, die die Inhalte des Textfeldes in den Dateinamen, der als Parameter gegeben ist, speichert. KDE stellt die {{class|KSaveFile}} Klasse bereit, mit der man sicher Dateien speichern kann. Sie ist von Qt's {{qt|QFile}} abgeleitet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der Prototyp für unsere Funktion ist&lt;br /&gt;
&amp;lt;code cppqt&amp;gt;&lt;br /&gt;
void MainWindow::saveFileAs(const QString &amp;amp;outputFileName)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Wir erstellen dann unser &amp;lt;tt&amp;gt;KSaveFile&amp;lt;/tt&amp;gt; Objekt und öffnen es mit&lt;br /&gt;
&amp;lt;code cppqt&amp;gt;&lt;br /&gt;
KSaveFile file(outputFileName);&lt;br /&gt;
file.open();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nun da wir unsere Datei zum beschreiben haben, müssen wir den Text im Textfeld so formatieren, dass er in eine Datei geschrieben werden kann. Dazu erstellen wir ein {{qt|QByteArray}} und füllen es mit der einfachen Text Version von was auch immer im Textfeld ist:&lt;br /&gt;
&amp;lt;code cppqt&amp;gt;&lt;br /&gt;
QByteArray outputByteArray;&lt;br /&gt;
outputByteArray.append(textArea-&amp;gt;toPlainText());&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Jetzt haben wir unser &amp;lt;tt&amp;gt;QByteArray&amp;lt;/tt&amp;gt;, das wir dazu verwenden mit &amp;lt;tt&amp;gt;KSaveFile::write()&amp;lt;/tt&amp;gt; in die Datei zu schreiben. Wenn wir ein normales &amp;lt;tt&amp;gt;QFile&amp;lt;/tt&amp;gt; benutzen würden, würde dies die Änderungen sofort ausführen. Falls aber während dem Schreiben ein Fehler passieren würde, würde die Datei beschädigt werden. Darum speichert &amp;lt;tt&amp;gt;KSaveFile&amp;lt;/tt&amp;gt; zuerst in eine temporäre Datei und dann, wenn man &amp;lt;tt&amp;gt;KSaveFile::finalize()&amp;lt;/tt&amp;gt; aufruft, werden die Änderungen in die eigentliche Datei geschrieben.&lt;br /&gt;
&amp;lt;code cppqt&amp;gt;&lt;br /&gt;
file.write(outputByteArray);&lt;br /&gt;
file.finalize();&lt;br /&gt;
file.close();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Schliesslich setzen wir &amp;lt;tt&amp;gt;MainWindows&amp;lt;/tt&amp;gt;'s &amp;lt;tt&amp;gt;fileName&amp;lt;/tt&amp;gt; Element dazu auf den Dateinamen zu zeigen, in den wir gerade geschrieben haben.&lt;br /&gt;
&amp;lt;code cppqt&amp;gt;&lt;br /&gt;
fileName = outputFileName;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====saveFileAs()====&lt;br /&gt;
&lt;br /&gt;
Dies ist die Funktion mit der der &amp;lt;tt&amp;gt;saveAs&amp;lt;/tt&amp;gt; Slot verbunden ist. Sie ruft einfach eine normale &amp;lt;tt&amp;gt;saveFileAs(QString)&amp;lt;/tt&amp;gt; Funktion auf und übergibt den Dateinamen der von &amp;lt;tt&amp;gt;{{class|KFileDialog}}::[http://api.kde.org/4.0-api/kdelibs-apidocs/kio/html/classKFileDialog.html#8891356c249c5911e1ab15cc2739a89b getSaveFileName()]&amp;lt;/tt&amp;gt; zurückgegeben wird.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt&amp;gt;&lt;br /&gt;
void MainWindow::saveFileAs()&lt;br /&gt;
{&lt;br /&gt;
  saveFileAs(KFileDialog::getSaveFileName());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dies ist unser erster eigentlicher Gebrauch der KIO Bibliothek. {{class|KFileDialog}} Stellt eine Anzahl statischer Funktionen bereit um den gemeinsamen Dateidialog, der von allen KDE Anwendungen genutzt wird, anzuzeigen.&lt;br /&gt;
&amp;lt;tt&amp;gt;KFileDialog::getSaveFileName()&amp;lt;/tt&amp;gt; aufzurufen wird einen Dialog anzeigen wo der Benutzer den Namen der Datei eingeben kann in die er speichern will oder einen neuen Namen angeben. Diese Funktion gibt den vollständigen Dateinamen zurück, den wir dann &amp;lt;tt&amp;gt;saveFileAs(QString)&amp;lt;/tt&amp;gt; übergeben.&lt;br /&gt;
&lt;br /&gt;
====saveFile()====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt&amp;gt;&lt;br /&gt;
void MainWindow::saveFile()&lt;br /&gt;
{&lt;br /&gt;
  if(!fileName.isEmpty())&lt;br /&gt;
  {&lt;br /&gt;
    saveFileAs(fileName);&lt;br /&gt;
  }&lt;br /&gt;
  else&lt;br /&gt;
  {&lt;br /&gt;
    saveFileAs();&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt nichts neues oder aufregendes an dieser Funktion, nur die Logik zu entscheiden den Speicher-Dialog zu zeigen, oder nicht. Wenn &amp;lt;tt&amp;gt;fileName&amp;lt;/tt&amp;gt; nicht leer ist, dann wird die Datei zu &amp;lt;tt&amp;gt;fileName&amp;lt;/tt&amp;gt; gespeichert. Andernfalls wird der Dialog angezeigt damit der Benutzer einen Dateinamen bestimmen kann.&lt;br /&gt;
&lt;br /&gt;
===Laden einer Datei===&lt;br /&gt;
&lt;br /&gt;
Endlich werden wir in der Lage sein eine Datei zu öffnen. Der ganze Code hierfür ist in &amp;lt;tt&amp;gt;MainWindow::openFile()&amp;lt;/tt&amp;gt; enthalten.&lt;br /&gt;
&lt;br /&gt;
Als erstes müssen wir den Benutzer nach dem Namen der Datei fragen, die er öffnen möchte. Dazu benutzen wir eine weitere &amp;lt;tt&amp;gt;KFileDialog&amp;lt;/tt&amp;gt; Funktion diesmal &amp;lt;tt&amp;gt;getOpenFileName()&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt&amp;gt;&lt;br /&gt;
QString fileNameFromDialog = KFileDialog::getOpenFileName();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dann nutzen wir die KIO Bibliothek um unsere Datei aufzurufen. Das ermöglicht es uns die Datei mit QFile zu öffnen, selbst wenn sie sich auf einem externen Speicherort befindet, wie auf einer FTP-Seite. Wir machen den folgenden Aufruf an die  {{class|NetAccess}} &amp;lt;tt&amp;gt;download()&amp;lt;/tt&amp;gt; Funktion:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt&amp;gt;&lt;br /&gt;
KIO::NetAccess::download(fileNameFromDialog, tmpFile, this)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese Funktion speichert die Datei temporär auf der Festplatte. Das erste Argument ist der Name der Datei, die man öffnen möchte. Das zweite ist ein QString der, nachdem der Download abgeschlossen ist den Speicherort der temporären Datei enthalten wird. Es ist mit diesem &amp;lt;tt&amp;gt;tmpFile&amp;lt;/tt&amp;gt;, mit dem wir von nun an arbeiten werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Funktion gibt &amp;lt;tt&amp;gt;true&amp;lt;/tt&amp;gt; oder &amp;lt;tt&amp;gt;false&amp;lt;/tt&amp;gt; zurück, je nachdem ob die Übertragung erfolgreich war oder nicht. Falls sie fehlgeschlagen ist, wird eine Fehlermeldung angezeigt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt&amp;gt;&lt;br /&gt;
KMessageBox::error(this, KIO::NetAccess::lastErrorString());&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ansonsten fahren wir fort, die Datei zu öffnen.&lt;br /&gt;
&lt;br /&gt;
Wir erstellen ein QFile indem wir die temporäre Datei die durch &amp;lt;tt&amp;gt;NetAccess::download()&amp;lt;/tt&amp;gt; erzeugt wurde ihrem Konstruktor übergeben und dann in schreibgeschütztem Modus öffnen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt&amp;gt;&lt;br /&gt;
QFile file(tmpFile);&lt;br /&gt;
file.open(QIODevice::ReadOnly);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Um den Inhalt der Datei anzuzeigen, müssen wir Gebrauch von einem {{class|QTextStream}} machen. Wir erstellen einen, indem wir den Inhalt unserer Datei seinem Konstruktor übergeben und dann QFile's &amp;lt;tt&amp;gt;readAll()&amp;lt;/tt&amp;gt; Funktion aufrufen um den Text von der Datei zu erhalten. Dieser wird dann zu der &amp;lt;tt&amp;gt;setPlainText()&amp;lt;/tt&amp;gt; Funktion unseres Textfelds übergeben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt&amp;gt;&lt;br /&gt;
textArea-&amp;gt;setPlainText(QTextStream(&amp;amp;file).readAll());&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wir speichern dann den Pfad der Datei, die wir gerade geöffnet haben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt&amp;gt;&lt;br /&gt;
fileName = fileNameFromDialog;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Und schliesslich entfernen wir die temporäre Datei, die durch &amp;lt;tt&amp;gt;NetAccess::download()&amp;lt;/tt&amp;gt; erstellt wurde:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt&amp;gt;&lt;br /&gt;
KIO::NetAccess::removeTempFile(tmpFile);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Erzeugen, Installieren und Ausführen==&lt;br /&gt;
&lt;br /&gt;
===CMakeLists.txt===&lt;br /&gt;
&amp;lt;code ini n&amp;gt;&lt;br /&gt;
project(tutorial4)&lt;br /&gt;
 &lt;br /&gt;
find_package(KDE4 REQUIRED)&lt;br /&gt;
include_directories(${KDE4_INCLUDES})&lt;br /&gt;
 &lt;br /&gt;
set(tutorial4_SRCS &lt;br /&gt;
  main.cpp&lt;br /&gt;
  mainwindow.cpp&lt;br /&gt;
)&lt;br /&gt;
 &lt;br /&gt;
kde4_add_executable(tutorial4 ${tutorial4_SRCS})&lt;br /&gt;
 &lt;br /&gt;
target_link_libraries(tutorial4 ${KDE4_KDEUI_LIBS} &lt;br /&gt;
                                ${KDE4_KIO_LIBS})&lt;br /&gt;
 &lt;br /&gt;
install(TARGETS tutorial4 DESTINATION ${BIN_INSTALL_DIR})&lt;br /&gt;
install(FILES tutorial4ui.rc &lt;br /&gt;
        DESTINATION ${DATA_INSTALL_DIR}/tutorial4)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Da wir nun die KIO Bibliothek verwenden, müssen wir CMake mitteilen es einzubinden. Wir machen das indem wir &amp;lt;tt&amp;gt;${KDE4_KIO_LIBS}&amp;lt;/tt&amp;gt; der &amp;lt;tt&amp;gt;target_link_libraries()&amp;lt;/tt&amp;gt; Funktion übergeben.&lt;br /&gt;
&lt;br /&gt;
Mit dieser Datei kann die Anleitung auf die selbe Weise erzeugt und ausgeführt werden wie in Anleitung 3. Für weitere Informationen, siehe [[Development/Tutorials/Using KActions (de)|Anleitung 3]].&lt;br /&gt;
&lt;br /&gt;
 mkdir build &amp;amp;&amp;amp; cd build&lt;br /&gt;
 cmake .. -DCMAKE_INSTALL_PREFIX=$HOME&lt;br /&gt;
 make install&lt;br /&gt;
 $HOME/bin/tutorial4&lt;br /&gt;
&lt;br /&gt;
==Weiter geht's==&lt;br /&gt;
Jetzt können sie mit dem Kapitel [[Development/Tutorials/KCmdLineArgs (de)|KCmdLineArgs]] forfahren.&lt;br /&gt;
&lt;br /&gt;
[[Category:C++]]&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials_(de)</id>
		<title>Development/Tutorials (de)</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials_(de)"/>
				<updated>2008-01-21T21:18:17Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: /* Konfigurationen mit KConfig verwalten */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:I18n/Language Navigation Bar|Development/Tutorials}}&lt;br /&gt;
&lt;br /&gt;
Tutorials sind der schnellste Weg um herauszufinden, was man mit KDE anstellen kann und wie man das macht. Es folgt eine Liste der verfügbaren Tutorials '''für KDE4'''. Tutorials und Anleitungen zu KDE3 und KDE2 finden Sie am Ende dieser Seite.&lt;br /&gt;
&lt;br /&gt;
== Einführung in die KDE4 Programmierung ==&lt;br /&gt;
Sind Sie an der Entwicklung von Programmen für KDE 4 interesiert? Wenn ja sind Sie hier genau richtig. Diese Artikelserie richtet sich an alle, die noch nie mit KDE programmiert haben.&lt;br /&gt;
;[[Development/Tutorials/First program (de)|Hallo Welt!]]&lt;br /&gt;
:''Einführung in die Grundlagen der KDE Programmierung''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Using KXmlGuiWindow (de)|Erstellen eines Hauptfensters]]&lt;br /&gt;
:''Dieser Artikel erklärt, wie der wichtigste Teil eines grafischen Programmes erstellt wird: das Hauptfenster.''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Using KActions (de)|Die Verwendung von KActions]]&lt;br /&gt;
:''In diesem Artikel erfahren Sie, wie Aktionen und Werkzeugleisten (Toolbars) im Menü hinzugefügt werden können.''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Saving and loading (de)|Laden und Speichern von Dateien]]&lt;br /&gt;
:''Dieser Artikel führt die KIO Bibliothek ein und erklärt wie man Dateien laden und speichern kann.''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/KCmdLineArgs (de)|Befehlszeilen Argumente (todo)]]&lt;br /&gt;
:''In diesem Artikel werden Sie lernen Ihrer Anwendung zu ermöglichen, Dateien über die Befehlszeile oder sogar unter Dolphin mit 'Öffnen mit' zu laden''&lt;br /&gt;
&lt;br /&gt;
== Grundlagen ==&lt;br /&gt;
;[[Development/Tutorials/KDE4 Porting Guide (de)|Ihre Applikation nach KDE 4 portieren]]&lt;br /&gt;
:''Anleitungen Qt3/KDE3 Applikationen nach Qt4/KDE4 zu portieren''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/CMake (de)|Einführung in CMake]]&lt;br /&gt;
:''Wie man CMake in KDE 4 benutzt''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Common Programming Mistakes (de)|Häufige Programmierfehler]]&lt;br /&gt;
:''Einige häufige Fehler die man während der Entwicklung von Qt und KDE Applikationen machen kann und wie man sie vermeidet.''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Using Qt Designer (de)|Den Qt Designer benutzen um Benutzerschnittstellen zu erzeugen]]&lt;br /&gt;
:''Wie man UI Dateien mit dem Designer erzeugt und wie man diese in einem KDE Programm integriert.''&lt;br /&gt;
&lt;br /&gt;
== Testen und Fehler beheben ==&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Debugging (de)|Debugging Ihrer Applikation]]&lt;br /&gt;
:''Tips, Tools und Techniken zum Debuggen von KDE Applikationen''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Unittests|Schreiben von Unit-Tests für Qt4 und KDE4 mit QTestLib]] ([http://developer.kde.org/documentation/tutorials/writingunittests/writingunittests.html Original link])&lt;br /&gt;
:''Tutorial von [mailto:bradh@frogmouth.net Brad Hards] das beschreibt, wie man Unit-Tests mit dem QTestLib Framework erstellt. Das Tutorial wird anhand eines Beispiels beschrieben und befindet sich zur Zeit noch in Entwicklung.''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Code_Checking|Halbautomatische Werge zur Erkennung von Programmierfehlern]]&lt;br /&gt;
:''Techniken um Fehler in KDE Code aufzuspüren''&lt;br /&gt;
&lt;br /&gt;
== Konfigurationen mit KConfig verwalten ==&lt;br /&gt;
;[[Development/Tutorials/KConfig (de)|Einführung in KConfig]]&lt;br /&gt;
:''Eine Übersicht über die zu KConfig gehörenden Klassen und wie Sie diese in Ihre Anwendung einbinden können''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Using KConfig XT|Benutzung von KConfig XT]]&lt;br /&gt;
:''Tutorial über das effiziente Benutzen des KConfig XT Frameworks.''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Updating KConfig Files|Update von KConfig Dateien]]&lt;br /&gt;
:''Tutorial das beschreibt, wie man ein Update-Skript erstellt, dass Veränderungen am Format der Konfiguration Ihrer Anwendung mit den bereits vorgenommenen Einstellungen des Anwenders abgleicht.''&lt;br /&gt;
&lt;br /&gt;
== Dienste: Applikationen und Plugins ==&lt;br /&gt;
;[[Development/Tutorials/Services/Introduction (de)|Einführung in das Dienst-Framework]]&lt;br /&gt;
:''Eine Einführung über das Dienst-Framework in KDE und was es dem Applikationsentwickler zur Verfügung stellen kann. Beschäftigt sich mit dem system configuration cache (SyCoCa), den benötigten Dateien und wie indizierte Informationen benutzt werden.&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Services/Traders (de)|Dienste über Trader Queries finden]]&lt;br /&gt;
:''Wie man mit der Trader Query Syntax Dienste wie Plugins oder Mimetypes findet, die im SyCoCa zwischengespeichert wurden. ''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Services/Plugins|Erstellen und Laden von Plugins mit KService]]&lt;br /&gt;
:''Zeigt, wie man eigene Plugintypen definiert, installiere Plugins findet (einschließlich denen von anderen Herstellern) und wie man diese einfach und portabel läd, indem man KService benutzt.''&lt;br /&gt;
&lt;br /&gt;
== Lokalisierung ==&lt;br /&gt;
;[[Development/Tutorials/Localization/Unicode (de)|Einführung in Unicode]]&lt;br /&gt;
:''Eine Einführung was Unicode ist und wie KDE Applikationen damit umgehen.''&lt;br /&gt;
&lt;br /&gt;
; [[Development/Tutorials/Localization/i18n (de)|Beim Schreiben der Applikation an die Lokalisierung denken]]&lt;br /&gt;
:''Diese Anleitung beschäftigt sich damit, was Lokalisation ist, warum sie wichtig ist und wie man sicherstellt, dass die eigene Applikation bereit ist, lokalisiert zu werden. Jeder Applikationsentwickler sollte das lesen.''&lt;br /&gt;
&lt;br /&gt;
; [[Development/Tutorials/Localization/i18n Mistakes (de)|Häufige Fehler vermeiden]]&lt;br /&gt;
:''Es gibt einige häufige Fehler, die es verhindern, dass eine Applikation angemesssen übersetzt werden kann. Diese Anleitung zeigt diese Fehler auf und zeigt, wie man sie vermeidet.''&lt;br /&gt;
&lt;br /&gt;
; [[Development/Tutorials/Localization/Building KDE's l10n Module|Erstellen von KDE's Lokalisierungs Modul]]&lt;br /&gt;
:''Das Erstellen und Installieren der Sprachunterstützung mit KDE's Lokalisierungs-Modul (l10n) ist ratsam für alle, die an Anwendungen im KDE Haupt-Repository arbeiten. Hierdurch erreichen Sie, das Sie Ihre Anwendung in anderen Sprachen testen und somit auftauchende Probleme erkennen können. Dieses Tutorial bringt Ihnen genau das bei.''&lt;br /&gt;
&lt;br /&gt;
; [[Development/Tutorials/Localization/i18n Build Systems|Einbeziehen von i18n in das Build System]]&lt;br /&gt;
:''Sobald Ihre Anwendung bereit dazu ist lokalisiert zu werden, ist es der nächste Schritt sicherzustellen, dass die Übersetzungsdateien automatisch erstellt und aktuell gehalten werden. Dieses Tutorial behandelt die nötigen Änderungen an den CMakeFile.txt Dateien sowie den Prozess um den resultierenden Nachrichten-Katalog mit Ihrer Applikation zu verteilen.''&lt;br /&gt;
&lt;br /&gt;
; [[Development/Tutorials/Localization/i18n Challenges|i18n - Herausforderungen and Lösungen]]&lt;br /&gt;
:''Dieses Tutorial behandelt die Aufgaben und Fallstricke, die bei der Lokalisierung auftreten wie das Übersetzen von Handbüchern und anderen Daten die ausserhalb des Quellcodes auftreten, das Behandeln von nicht mehr gültigen .po-Dateien, das Umgehen mit Freezes, programmieren in anderen Sprachen als Englisch und Erstellung unabhängiger Releases oder das Verschieben von Anwendungen zwischen KDE Modulen.''&lt;br /&gt;
&lt;br /&gt;
; [[Development/Tutorials/Localization/i18n_Semantics|Semantisches Markup für Nachrichten]]&lt;br /&gt;
:''Um eine konsistente und semantisch korrekte Darstellung von Nachrichten in Anwendungen sicherzustellen, können semantische Kommentare zu den Nachrichten, die übersetzt werden sollen, mit dem KUIT System hinzugefügt werden. Dieses Tutorial beschreibt die Funktionsweise dieses Systems.''&lt;br /&gt;
&lt;br /&gt;
; [[Development/Tutorials/Localization/i18n Krazy|Automatisierte i18n Codeüberprüfung]]&lt;br /&gt;
:''Der Krazy Code-Checker durchsucht KDE's Code und meldet häufige i18n Fehler.''&lt;br /&gt;
&lt;br /&gt;
; [[Development/Tutorials/Localization/Language Change (de)|Mit Sprachänderungen umgehen]]&lt;br /&gt;
:''Wie man seiner Applikation beibringt beim nächsten Start oder zur Laufzeit eine andere Sprache zu benutzen.''&lt;br /&gt;
&lt;br /&gt;
== Dokumentation ==&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/API_Documentation|API Dokumentation]]&lt;br /&gt;
:''Dieses Tutorial erklärt, wie Sie Ihre APIs korrekt dokumentieren.''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Man_Pages|Man Seiten]]&lt;br /&gt;
:''Das Schreiben und Erstellen von Referenz-Handbüchern.''&lt;br /&gt;
&lt;br /&gt;
== Anwendungsautomatisierung und Skripting ==&lt;br /&gt;
&lt;br /&gt;
=== D-Bus ===&lt;br /&gt;
; [[Development/Tutorials/D-Bus/Introduction|Einführung in D-Bus]]&lt;br /&gt;
:''Eine unkomplizierte Einführung in die Kernkonzepte von D-Bus aus der Sicht eines Anwendungs-Programmierers. Dieses Tutorial behandet was D-Bus ist, und wie Sie es in Ihren Anwendungen einsetzen können.''&lt;br /&gt;
&lt;br /&gt;
; [[Development/Tutorials/D-Bus/Accessing Interfaces|Zugriff auf D-Bus Schnittstellen]]&lt;br /&gt;
:''Eine Schrittweise Anleitung zum Aufruf von D-Bus-Methoden und zur Verbindung mit D-Bus-Signalen unter Verwendung von QtDBus.''&lt;br /&gt;
&lt;br /&gt;
; [[Development/Tutorials/D-Bus/Intermediate_D-Bus|D-Bus für Fortgeschrittene]]&lt;br /&gt;
:''Tips zur Verwendung von QtDBus wenn sie mit problematischen Realwelt-Schnittstellen konfrontiert werden.''&lt;br /&gt;
&lt;br /&gt;
; [[Development/Tutorials/D-Bus/Creating Interfaces|Erstellen von D-Bus Schnittstellen]]&lt;br /&gt;
:''Lernen Sie, wie sie Funktionalität Ihrer Applikationen bereit stellen, indem Sie eigene D-Bus Schnittstellen erstellen und benutzen. Beschreibt das Erstellen von XML-Beschreibungen, die Bereitstellung von Schnittstellen zur Laufzeit und das Aufsetzen des Build-Systems mit CMake.''&lt;br /&gt;
&lt;br /&gt;
; [[Development/Tutorials/D-Bus/Autostart Services|D-Bus Autostart Dienste]]&lt;br /&gt;
:''Machen Sie mit diesem Tutorial aus Ihrer Anwendung einen D-Bus-Autostart-Dienst. Dieses Feature, dass auch als &amp;quot;D-Bus Dienst Aktivierung&amp;quot; bekannt ist, ermöglicht es, dass D-Bus Aufrufe zu Ihrer Applikation selbst dann funktionieren, wenn sie gerade nicht läuft indem sie den D-Bus-Daemon Ihre Applikation starten lassen, wenn deren Funktionen benötigt werden.''&lt;br /&gt;
&lt;br /&gt;
; [[Development/Tutorials/Porting_to_D-Bus|Portieren von DCOP nach D-Bus]]&lt;br /&gt;
: ''Portieren Sie mit Hilfe dieser Anleitung Ihre Anwendungen von DCOP nach D-Bus.''&lt;br /&gt;
&lt;br /&gt;
=== Konqueror ===&lt;br /&gt;
; [[Development/Tutorials/Creating Konqueror Service Menus|Erstellung von Konqueror Dienstmenus]]&lt;br /&gt;
:''Dieses Tutorial zeigt Ihnen wie Sie MIME-Typ-spezifische Aktionen in Konquerors Kontextmenu bereitstellen.''&lt;br /&gt;
&lt;br /&gt;
=== Kross ===&lt;br /&gt;
; [[Development/Tutorials/Kross/Introduction|Einführung in Kross]]&lt;br /&gt;
:''Eine Einführung in das Kross Scripting Framework.''&lt;br /&gt;
&lt;br /&gt;
; [[Development/Tutorials/Kross/Hello_World|Hallo Welt]]&lt;br /&gt;
:''Eine erste Anwendung mit funktionierendem Kross Code.''&lt;br /&gt;
&lt;br /&gt;
; [[Development/Tutorials/Kross/Connecting_Signals_and_slots_in_Kross|Verbinden von Signalen und Slots in Kross]]&lt;br /&gt;
:''Einfache Demonstration, wie man Signale von Objekten mit Slots von Skripten verbindet.''&lt;br /&gt;
&lt;br /&gt;
; [[Development/Tutorials/Kross/Scripts-as-Plugins|Skripte als Plugins mit Kross]]&lt;br /&gt;
:''Dieses Tutorial bietet eine schrittweise Einführung, wie Sie Skripte als Plugins in eine KDE Anwendung integrieren.''&lt;br /&gt;
&lt;br /&gt;
=== KOffice ===&lt;br /&gt;
; [[Development/Tutorials/KOffice Overview|KOffice Übersicht]]&lt;br /&gt;
:''Dieses Dokument zeigt eine Übersicht über die verschiedenen KOffice Plugin Typen sowie ihren jeweiligen Nutzen und Stärken.'' Wenn KOffice Plugins neu für Sie sind, ist dieses Tutorial für Sie geeignet.&lt;br /&gt;
&lt;br /&gt;
; [[Development/Tutorials/Write a Flake Plugin|Erstellen von KOffice Flake Plugins]]&lt;br /&gt;
:''Dieses Tutorial zeigt Ihnen wie Sie ein Plugin für KOffice Anwendungen erstellen das Ihnen mit Hilfe von Flake erlaubt, Inhalte in ODF-Dokumente einzubetten.''&lt;br /&gt;
&lt;br /&gt;
; [[Development/Tutorials/KWord Scripting|KWord Scripting]]&lt;br /&gt;
:''Dieses Tutorial zeigt, wie man KWord mit Skriptsprachen wie Python, Ruby oder JavaScript über Kross anspricht.''&lt;br /&gt;
&lt;br /&gt;
; [[Development/Tutorials/KSpread Scripting|KSpread Scripting]]&lt;br /&gt;
:''Dieses Tutorial zeigt, wie man KSpread mit Skriptsprachen wie Python, Ruby oder JavaScript über Kross anspricht.''&lt;br /&gt;
&lt;br /&gt;
; [[Development/Tutorials/Krita Scripting|Krita Scripting]]&lt;br /&gt;
:''Dieses Tutorial zeigt, wie man Krita mit Skriptsprachen wie Python, Ruby oder JavaScript über Kross anspricht.''&lt;br /&gt;
&lt;br /&gt;
=== SuperKaramba ===&lt;br /&gt;
; [[Development/Tutorials/SuperKaramba|SuperKaramba Tutorial]]&lt;br /&gt;
:''Dieses Tutorial bietet einen Einblick in SuperKaramba, Themen-Dateien und das Skripten mit Python, Ruby und JavaScript.&lt;br /&gt;
&lt;br /&gt;
== Suche und Meta-Daten ==&lt;br /&gt;
&lt;br /&gt;
=== Strigi ===&lt;br /&gt;
&lt;br /&gt;
; [[Development/Tutorials/Writing file analyzers|Schreiben von Datei-Analysierern]]&lt;br /&gt;
:''Datei-Analysierer extrahieren Daten aus Dateien um Sie in Datei-Dialogen und Datei-Managern anzeigen können. Die Daten die auf diesem Weg erhalten werden, werden auch für die Suche nach Dateien verwendet. KDE4 erlaubt die Benutzung von mehreren Analysierern pro Dateityp. Dieses Tutorial beschreibt, wie Sie neue Analysierer schreiben können.''&lt;br /&gt;
&lt;br /&gt;
=== Nepomuk ===&lt;br /&gt;
&lt;br /&gt;
; [[Development/Tutorials/Metadata/KMetaData first steps|Erste Schritte mit Nepomuk]]&lt;br /&gt;
:''Nepomuk ist die KDE-Bibliothek die einfachen Zugriff auf Metadaten im [http://nepomuk-kde.semanticdesktop.org Nepomuk-KDE] System erlaubt. Lernen Sie, wie Ihre Applikation mit Hilfe von Nepomuk Metadaten bereitstellen und verwenden kann.''&lt;br /&gt;
&lt;br /&gt;
== Ansprechen von Hardware (Solid) ==&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Solid_Tutorials|Einführung in Solid]]&lt;br /&gt;
:''Eine Einführung in die Benutzung der Solid Hardware-Erkennung und -Verwendung in KDE Applikationen.''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Solid_Network_Tutorial|Zugriff auf Netzwerk-Informationen]]&lt;br /&gt;
:''Wie man Solid benutzt um Informationen über das Netzwerk herauszufinden''&lt;br /&gt;
&lt;br /&gt;
== Multimedia (Phonon) ==&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Phonon/Introduction|Phonon]]&lt;br /&gt;
:''Erste Schritte mit der Multimedia API''&lt;br /&gt;
&lt;br /&gt;
:''Erstellung und Benutzung von Phonon und seinem GStreamer Backend unter Linux mit Qt 4.3.x''&lt;br /&gt;
::''Dieser Artikel gibt Ihnen eine kurze Anleitung wie Sie Phonon und sein GStreamer Backend unter GNU/Linux mit lediglich Qt 4.3.x beziehen, kompilieren und benutzen können. Gegen Ende beschreibt der Artikel zusätzlich, wie ein Entwickler Phonon benutzen kann um einfache Audio- und Video-Spieler zu erstellen. Sie können den Artikel [http://www.vcreatelogic.com/oss/docs/CompilingPhononOnLinux.pdf hier] lesen.&lt;br /&gt;
Sie können die editierbare OpenDocumentText Datei von [http://www.prashanthudupa.com/phonon/CompilingPhononOnLinux.odt hier]. herunterladen''&lt;br /&gt;
&lt;br /&gt;
== Plasma ==&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Plasma/GettingStarted|Erste Schritte mit Plasmoids]]&lt;br /&gt;
:''Erstellung Ihres ersten Plasma-Widgets oder Plasmoids in C++ mit einem SVG Hintergrund, einem Icon und etwas Text''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Plasma/DataEngines|Schreiben einer DataEngine]]&lt;br /&gt;
:''DataEngines bieten eine standardisierte Schnittstelle zur Darstellung von Daten aus verschiedenen Datenquellen. Lernen Sie was eine DataEngine ist und wie Sie selbst ein schreiben können.''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Plasma/UsingDataEngines|Benutzung von DataEngines in Plasmoids]]&lt;br /&gt;
:''Mit einer DataEngine ist es möglich, Daten auf einfache und standardisierte Art und Weise zu empfangen und darzustellen. Dieses Tutorial behandelt das Thema, wie man DataEngines zu diesem Zweck in Plasma einsetzt.''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Plasma/AbstractRunner|Erstellen von Runners]]&lt;br /&gt;
:''Runners sind Plugins die Aktions-basierte Suchfunkionalität im Plasma Ausführen-Dialog erlauben. Diese Plugins können von jeder Applikation verwendet werden, die libplasma einbindet.''&lt;br /&gt;
&lt;br /&gt;
== Kate / Kwrite ==&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Kate/KTextEditor Plugins|Erste Schritte mit KTextEditor Plugins]]&lt;br /&gt;
:''Erstellung Ihres ersten KTextEditor Plugins''&lt;br /&gt;
&lt;br /&gt;
== Drucken ==&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Printing Hello World|Hallo Welt]]&lt;br /&gt;
:''Einführung in das KDE Drucksystem''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Printing Print Dialog|Druckdialog]]&lt;br /&gt;
:''Benutzung des KDE Druckdialogs''&lt;br /&gt;
&lt;br /&gt;
== Neue Dinge herunterladen ==&lt;br /&gt;
; [[Development/Tutorials/Introduction to Get Hot New Stuff|Einführung in &amp;quot;Neue Dinge herunterladen&amp;quot;]]&lt;br /&gt;
:''Eine Einführung in das Entwickler-freundliche Netzwerk-Update-System das KDE Applikationen erlaubt, neue Anwendungsdaten zur Laufzeit auf benutzerfreundliche Weise herunterzuladen.''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/KNewStuffSecure|Sicherheit mit KNewStuff]] ([http://developer.kde.org/documentation/tutorials/knewstuffsecure/index.html Original Link])&lt;br /&gt;
:''Tutorial das zeigt, wie man Ressourcen auf sichere Weise teilt (KDE 3.4 und später).''  Geschrieben von Andr&amp;amp;#225;s Mantia &amp;amp;lt;amantia@kde.org&amp;amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Schnelle Anwendungsentwicklung ==&lt;br /&gt;
&lt;br /&gt;
=== Python ===&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Python introduction to signals and slots|101 Einführung in Signale und Slots]]&lt;br /&gt;
:''Eine einfache Einführung in Qt's Signal- und Slot-Architektur.''&lt;br /&gt;
&lt;br /&gt;
=== Ruby ===&lt;br /&gt;
&lt;br /&gt;
;[http://developer.kde.org/language-bindings/ruby/kde3tutorial/index.html KDE Ruby Korundum Tutorial]&lt;br /&gt;
:''Eine Ruby-Version von Antonio Larossa Jim&amp;amp;eacute;nezs KDE Tutorial von Richard Dale. Sehen Sie sich for Qt Tutorials und andere Informationen auch die  [http://developer.kde.org/language-bindings/ruby/index.html Ruby Developers Corner] an.''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Qt4_Ruby_Tutorial|Qt4 Ruby Tutorial]]&lt;br /&gt;
:''Trolltechs sagenhaftes Einstiegstutorial in Qt, übersetzt für Ruby.''&lt;br /&gt;
&lt;br /&gt;
=== Shell ===&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Shell_Scripting_with_KDE_Dialogs|Shell Scripting mit KDE Dialogen]] ([http://developer.kde.org/documentation/tutorials/kdialog/t1.html Original Link])&lt;br /&gt;
:''Tutorial von [mailto:bradh@frogmouth.net Brad Hards] das beschreibt, wie man KDE Dialoge mit Hilfe von kdialog in Shell-Skripten verwendet. Das Tutorial wird anhand eines Beispiels durchgeführt.''&lt;br /&gt;
&lt;br /&gt;
== Andere Tutorials ==&lt;br /&gt;
&lt;br /&gt;
=== Benutzung der KDE Games Bibliothek ===&lt;br /&gt;
;[[Development/Tutorials/Games/KStandardGameAction| KStandardGameAction]]&lt;br /&gt;
:''Benutzung von libkdegames um Ihr Spiel dem kdegames Standard anzupassen''&lt;br /&gt;
;[[Development/Tutorials/Games/Highscores| Highscores]]&lt;br /&gt;
:''Implementierung einer einfachen Highscore-Tabelle in Ihrem Spiel''&lt;br /&gt;
;[[Development/Tutorials/Games/Theme Selector| Themen-Auswahl]]&lt;br /&gt;
:'' Benutzung des libkdegames Themen-Auswahl-Dialogs''&lt;br /&gt;
&lt;br /&gt;
=== 2D Plotting (KPlotWidget) ===&lt;br /&gt;
;[[Development/Tutorials/KPlotWidget|Benutzen des KDE Daten-Plotting Widgets]]&lt;br /&gt;
:''Dieses Tutorial führt KPlotWidget ein, welches zum plotten zweidimensionaler Daten verwendet werden kann. Es enthält Informationen zu einfachen Benutzung des Widgets (inklusive Hinzufügen und Änderung von Datensätzen sowie Anpassung der Koordinatenachsen und deren Beschriftung) sowie erweiterten Anwendungsfällen (inklusive Erweiterung des Widgets durch Vererbung).''&lt;br /&gt;
&lt;br /&gt;
=== Rechtschreib- und Grammatikprüfung (Sonnet) ===&lt;br /&gt;
;[[Development/Tutorials/Sonnet/SonnetTutorial|Rechtschreib- oder Grammatikprüfung in KDE Applikationen einbinden]]&lt;br /&gt;
:''Diess Tutorial führt in Sonnet ein und wie man es benutzt um Sprachkorrekturen in der eigenen KDE Anwendung zu verwenden. Sonnets Hilffunktionen sollen in einem weiteren Tutorial beschrieben werden.''&lt;br /&gt;
&lt;br /&gt;
=== Pixmap cache (KPixmapCache) ===&lt;br /&gt;
;[[Development/Tutorials/KPixmapCache|Benutzung des KDE Pixmap Caches]]&lt;br /&gt;
:''Dieses Tutorial demonstriert die Benutzung von KPixmapCache zum Zwischenspeichern von beispielsweise Pixmaps die aus SVGs oder Daten erstellt wurden.''&lt;br /&gt;
&lt;br /&gt;
== Material für KDE2 und KDE3 ==&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/KDE3|KDE3 Tutorials]]&lt;br /&gt;
:''Diese Tutorials behandeln Themen im Bezug auf KDE3.''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/KDE2|KDE2 Tutorials]]&lt;br /&gt;
:''Diese Tutorials behandeln Themen im Bezug auf KDE2.''&lt;br /&gt;
&lt;br /&gt;
[[Category:KDE4]]&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials/KConfig_(de)</id>
		<title>Development/Tutorials/KConfig (de)</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials/KConfig_(de)"/>
				<updated>2008-01-04T21:02:58Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: /* KDesktopFile: Ein besonderer Fall */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:I18n/Language Navigation Bar|Development/Tutorials/KConfig}}&lt;br /&gt;
&lt;br /&gt;
{{TutorialBrowser (de)|&lt;br /&gt;
&lt;br /&gt;
series=KConfig|&lt;br /&gt;
&lt;br /&gt;
name=Einführung in KConfig|&lt;br /&gt;
&lt;br /&gt;
pre=Keine|&lt;br /&gt;
&lt;br /&gt;
next=[[../Using_KConfig_XT (de)|Benutzen von KConfig XT]]|&lt;br /&gt;
&lt;br /&gt;
reading=Keine&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{improve (de)}}&lt;br /&gt;
&lt;br /&gt;
== Zusammenfassung ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dieser Artikel beschäftigt sich mir dem KDE Einstellungdaten-System, angefangen mit einer Übersicht über den grundlegenden Aufbau aus der Sicht eines Entwicklers. Es wirft ausserdem einen Blick auf jede der Klassen, die für die Entwicklung von Anwendungen relevant sind und fährt dann mit kiosk (Benutzer- und Gruppenprofile) Integration fort.&lt;br /&gt;
&lt;br /&gt;
== Grundlegender Aufbau ==&lt;br /&gt;
&lt;br /&gt;
KConfig ist ausgelegt um das Konzept vom eigentlichen Speichern und Auffinden von Konfigurationsdaten hinter eine Programmierschnittstelle zu abstrahieren die es ermöglicht, auf einfache Weise Informationen abzurufen und zu setzen. Wo oder in welcher Form Daten gespeichert werden ist für eine Anwendung die KConfig benutzt irrelevant.&lt;br /&gt;
&lt;br /&gt;
Das behält alle KDE Anwendungen konsistent in ihrer Art, Konfigurationen handzuhaben und nimmt einem Anwendungs-Entwickler die Arbeit so ein System von Grund auf neu zu schreiben, was ein sehr fehleranfälliger Prozess sein kann.&lt;br /&gt;
&lt;br /&gt;
Jedes KConfig Objekt verkörpert ein einziges Konfigurationsobjekt. Jedes Konfigurationsobjekt ist durch seinen einzigartigen Namen gekennzeichnet und kann von mehreren lokalen oder externen Daten oder Services gelesen werden. Jede Anwendung hat standardmässig ein zugehöriges Konfigurationsobjekt und es gibt auch ein globales Konfigurationsobjekt.&lt;br /&gt;
&lt;br /&gt;
Diese Konfigurationsobjekte sind nach einer zweistufigen Hierarchie getrennt: Gruppen und Schlüssel. Ein Konfigurationsobjekt kann eine beliebige Anzahl an Gruppen haben und jede Gruppe kann einen oder mehrere Schlüssel mit zugehörigen Werten haben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die gespeicherten Werte können aus beliebig vielen verschiedenen Datentypen bestehen. Sie werden gespeichert und abgerufen als das Objekt selbst. Zum Beispiel wird ein {{qt|QObject}}-Objekt direkt einem Konfigurationsobjekt übergeben, wenn es einen Farbwert speichert und wenn ein Farbwert abgerufen wird, wird ein {{qt|QObject}}-Objekt zurückgegeben.&lt;br /&gt;
&lt;br /&gt;
{{note (de)| deserialization  entgliedern? &amp;lt;br&amp;gt; &amp;lt;tt&amp;gt; &amp;quot;do not have to perform serialization and deserialization of objects themselves&amp;quot; &amp;lt;/tt&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Anwendungen selbst müssen darum normalerweise Objekte nicht selber gliedern und entgliedern.&lt;br /&gt;
&lt;br /&gt;
Applications themselves therefore generally do not have to perform serialization and deserialization of objects themselves.&lt;br /&gt;
&lt;br /&gt;
== Die KConfig Klasse ==&lt;br /&gt;
&lt;br /&gt;
Das {{class|KConfig}}-Objekt wird benutzt um ein bestehendes Konfigurationsobjekt anzusteuern. Es gibt eine Reihe von Möglichkeiten ein Konfigurationsobjekt zu erstellen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
// ein einfaches, altes lesen/schreiben Konfigurationsobjekt&lt;br /&gt;
KConfig config(&amp;quot;myapprc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// eine bestimmte Datei im Dateisystem&lt;br /&gt;
// currently must be an INI style file&lt;br /&gt;
KConfig fullPath(&amp;quot;/etc/kderc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// nicht mit globalen Werten verflochten&lt;br /&gt;
KConfig globalFree( &amp;quot;localsrc&amp;quot;, KConfig::NoGlobals );&lt;br /&gt;
&lt;br /&gt;
// nicht mit globalen Werten orde der $KDEDIRS Hierarchie verflochten&lt;br /&gt;
KConfig simpleConfig( &amp;quot;simplerc&amp;quot;, KConfig::SimpleConfig );&lt;br /&gt;
&lt;br /&gt;
// Komponenten-spezifische Konfiguration, in diesem Fall ein Plugin&lt;br /&gt;
KConfig pluginConfig( componentData(), &amp;quot;pluginrc&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
// Ausserhalb der normalen Konfigurations-Ressource&lt;br /&gt;
KConfig dataResource( &amp;quot;data&amp;quot;, &amp;quot;myapp/somefile&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{note (de)|wie soll &amp;quot;merged&amp;quot; in den folgenden Fällen übersetzt werden? &amp;lt;br&amp;gt; &amp;lt;tt&amp;gt;&amp;quot;verschmolzen&amp;quot; oder &amp;quot;verflochten&amp;quot;&amp;lt;/tt&amp;gt; &amp;lt;br&amp;gt; der Anwendung selber transparent&amp;quot; tönt auch nicht sehr gut}}&lt;br /&gt;
&lt;br /&gt;
Das Kconfig Objekt, das wir auf Zeile 2 erstellen ist ein gewöhnliches Konfigurationsobjekt. Wir können Werte aus ihm lesen, neue Einträge schreiben und nach verschiedenen Eigenschaften des Objekts fragen. Dieses Objekt wird aus der Konfigurations-Ressource geladen, wie es durch {{class|KStandardDirs}} bestimmt wird, das heisst, dass jede Instanz des &amp;lt;tt&amp;gt;myapprc&amp;lt;/tt&amp;gt;-Objekts in jedem der Ordner in der Konfigurations-Ressourcen-Hierarchie verschmolzen werden um die Werte zu erzeugen, die in diesem Objekt gesehen werden. So werden Systemweite und &lt;br /&gt;
pro-Benutzer/Gruppen Profile erstellt und unterstützt. Das alles geschieht der Anwendung selber transparent.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{tip| Für mehr Informationen, wie das Verschmelzen funktioniert, siehe diesen Artikel über die [[KDE System Administration/KDE_Filesystem_Hierarchy|KDE Dateisystem Hierarchie]].}}&lt;br /&gt;
&lt;br /&gt;
{{note (de)|Ist das so gemeint mit &amp;quot;expects an INI style file&amp;quot;&amp;lt;br&amp;gt; &amp;lt;tt&amp;gt; On line 6 we open a specific local file, this case /etc/kderc. This performs no merging of values and expects an INI style file.&amp;lt;/tt&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Auf Zeile 6 öffnen wir eine bestimmte Lokale Datei, in diesem Fall {{path|/etc/kderc}}. Das führt kein verschmelzen von Werten aus und erwartet eine Datei im INI Format.&lt;br /&gt;
&lt;br /&gt;
Zeile 9 erzeugt ein Konfigurationsobjekt, dass nicht mit dem globalen &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt;-Konfigurationsobjekt verflochten ist,  während das Konfigurationsobjekt auf Zeile 12 zusätzlich mit keinem der Dateien in der &amp;lt;tt&amp;gt;$KDEDIRS&amp;lt;/tt&amp;gt;-Hierarchie verflochten ist. Das kann die Leistung spürbar verbessern, falls man einfach nur Werte aus einer einfachen Konfuguration liest und globale Werte keine Rolle spielen.&lt;br /&gt;
&lt;br /&gt;
Zeile 15 erzeugt ein Konfigurationsobjekt unter Benutzung des {{class|KComponentData}}-Objekts das zu einem Plugin oder einer anderen Komponente gehört. Das Plugin kann verschiedene Ordner aufweisen, die in seinen {{class|KStandardDirs}} definiert sind und das ist eine Möglichkeit sich zu versichern, dass {{class|KConfig}} das respektiert.&lt;br /&gt;
&lt;br /&gt;
Und schliesslich auf Zeile 18 erzeugen wir ein Konfigurationsobjekt, das nicht in der &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt;-Ressource sondern in der &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt;-Ressource existiert. Man kann kann auf diese Weise jede Ressource verwenden, von denen {{class|KStandardDirs}} Kenntnis hat, auch solche die während der Laufzeit hinzugefügt werden.&lt;br /&gt;
&lt;br /&gt;
=== Spezielle Konfigurationsobjekte ===&lt;br /&gt;
&lt;br /&gt;
Jede Anwendung hat sein eigenes Konfigurationsobjekt das den Namen benutzt, der von {{class|KAboutData}} bereitgestellt wird mit angehängtem &amp;quot;rc&amp;quot;. Also hätte eine Anwendung mit dem Namen &amp;quot;myapp&amp;quot; das Standard-Konfigurationsobjekt &amp;quot;myapprc&amp;quot;. Dieses Konfigurationsobjekt kann auf diese Weise aufgerufen werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KComponentData&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
#include &amp;lt;KGlobal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    // beachten sie, dass dies eigentlich ein KSharedConfig ist&lt;br /&gt;
    // mehr über diese Klasse siehe weiter unten&lt;br /&gt;
    KConfig* config = KGlobal::config();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Auf das Standard-Konfigurationsobjekt für die Anwendung wird zugegriffen, wenn kein Name definiert wurde, als das {{class|KConfig}}-Objekt erzeugt wurde. Also könnten wir stattdessen auch das tun:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    KConfig config;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zusätzlich könnte jede Komponente sein eigenes Konfigurationsobjekt haben. Auf dieses wird normalerweise durch die &amp;lt;tt&amp;gt;componentData()&amp;lt;/tt&amp;gt; des Plugins zugegriffen, anstatt durch die &amp;lt;tt&amp;gt;{{class|KGlobal}}::mainComponent()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Und schliesslich gibt es noch ein globales Konfigurationsobjekt, &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt;, das von jeder Anwendung verwendet wird. Es enthält Informationen wie die Standard-Tatenkombinationen für verschiedene Aktionen. Es wird in das Konfigurationsobjekt &amp;quot;gemischt&amp;quot; wenn der &amp;lt;tt&amp;gt;KConfig::IncludeGlobals&amp;lt;/tt&amp;gt; Bitschalter dem {{class|KConfig}} Konstruktor übergeben wird, was standardmässig der Fall ist.&lt;br /&gt;
&lt;br /&gt;
=== Allgemein nützliche Methoden ===&lt;br /&gt;
&lt;br /&gt;
Um den momentanen Zustand des Konfigurationsobjektes zu speichern, rufen wir die &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt;-Methode auf. Diese Methode wird also aufgerufen, wenn ein Objekt zerstört wird. Falls keine Änderungen gemacht wurden, oder die Ressource weist sich als nicht beschreibbar aus (Wenn der Benutzer zum Beispiel nicht genug Rechte hat, um die Datei zu bearbeiten), dann wird keine Beschäftigung der Festplatte hervorgerufen. &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; verschmilzt Änderungen die gleichzeitig von anderen Prozessen ausgeführt werden - lokale Änderungen haben aber trotzdem Vorrang.&lt;br /&gt;
&lt;br /&gt;
Wenn wir sicher gehen wollen, dass wir die aktuellsten Werte von der Festplatte haben, dann rufen wir &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt; auf, welches &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; aufruft und dann die Daten von der Festplatte aktualisiert.&lt;br /&gt;
&lt;br /&gt;
Falls wir verhindern müssen, dass das Konfigurationsobjekt bereits gemachte Änderungen nicht auf die Festplatte speichert, müssen wir &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt; aufrufen. Ein besonderer Anwendungsfall ist es, die Konfiguration zum Festplatten-Zustand zurückzusetzen indem man &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt; gefolgt von &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt; aufruft.&lt;br /&gt;
&lt;br /&gt;
Alle Gruppen in einem Konfigurationsobjekt aufzurufen ist so einfach wie hier in diesem Code-Abschnitt &amp;lt;tt&amp;gt;groupList()&amp;lt;/tt&amp;gt; aufzurufen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::mainComponent().config();&lt;br /&gt;
&lt;br /&gt;
foreach ( const QString&amp;amp; group, config.groupList() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;next group:&amp;quot; &amp;lt;&amp;lt; group;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== KSharedConfig ==&lt;br /&gt;
&lt;br /&gt;
Die {{class|KSharedConfig}} Klasse ist eine Referenz-gezählte Version von {{class|KConfig}}. Darum stellt es eine Möglichkeit bereit, das selbe Konfigurationsobjekt von unterschiedlichen Orten zu referenzieren ohne zusätzlich die Objekte trennen zu müssen oder sich um die Synchronisation des Schreibvorgangs zu kümmern, selbst wenn das Konfigurationsobjekt von verschiedenen Code-Pfaden aktualisiert wird.&lt;br /&gt;
&lt;br /&gt;
Auf ein {{class|KSharedConfig}}-Objekt zuzugreifen ist so einfach wie das hier:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KSharedConfigPtr config = KSharedConfig::openConfig();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;openConfig()&amp;lt;/tt&amp;gt; nimmt die selben Parameter wie {{class|KConfig}}'s Konstruktoren, was es einem ermöglicht zu definieren, welche Konfigurationsdatei zu öffnen und Markierungen das Verschmelzen von nicht-&amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt;-Ressourcen zu kontrollieren.  &lt;br /&gt;
&lt;br /&gt;
Es wird grundsätzlich empfohlen {{class|KSharedConfig}} anstatt {{class|KConfig}} selbst zu benutzen, und auch das Objekt, das von {{class|KComponentData}} zurückgegeben wird ist in der Tat ein {{class|KSharedConfig}}-Objekt.&lt;br /&gt;
&lt;br /&gt;
== KConfigGroup ==&lt;br /&gt;
&lt;br /&gt;
Nun da wir ein Konfigurationsobjekt haben, ist der nächste Schritt es tatsächlich zu nutzen. Das erste, das wir tun müssen, ist zu bestimmen, auf welche Gruppe von Schlüssel-/Wertepaare wir in unserem Objekt zugreifen wollen. Wir tun das, indem wir ein KConfigGroup-Objekt erstellen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig config;&lt;br /&gt;
KConfigGroup generalGroup( &amp;amp;config, &amp;quot;General&amp;quot; );&lt;br /&gt;
KConfigGroup colorsGroup = config.group( &amp;quot;Colors&amp;quot; ); // ...oder so ähnlich...&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Man kann{{class|KConfigGroup}} {{class|KConfig}}- oder {{class|KSharedConfig}}-Objekte übergeben.&lt;br /&gt;
&lt;br /&gt;
Konfigurationsgruppen können ebenfalls verschachtelt werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfigGroup subGroup1( &amp;amp;generalGroup, &amp;quot;LessGeneral&amp;quot; );&lt;br /&gt;
KConfigGroup subGroup2 = colorsGroup.group( &amp;quot;Dialogs&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Lesen von Einträgen ==&lt;br /&gt;
&lt;br /&gt;
Wenn man erst einmal ein {{class|KConfigGroup}}-Objekt erstellt hat, ist das Lesen von Einträgen ziemlich einfach:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
QString accountName = generalGroup.readEntry( &amp;quot;Account&amp;quot;,&lt;br /&gt;
                                              QString() );&lt;br /&gt;
QColor color = colorsGroup.readEntry( &amp;quot;background&amp;quot;,&lt;br /&gt;
                                      Qt::white );&lt;br /&gt;
QStringList list = generalGroup.readEntry( &amp;quot;List&amp;quot;,&lt;br /&gt;
                                           QStringList() );&lt;br /&gt;
QString path = generalGroup.readPathEntry( &amp;quot;SaveTo&amp;quot;,&lt;br /&gt;
                                           defaultPath );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wie man hier oben sehen kann, kann man Lesevorgänge von verschiedenen {{class|KConfigGroup}}-Objekten, die auf dem selben {{class|KConfig}}-Objekt erstellt wurden, problemlos mischen. Die Lese-Methoden nehmen den Schlüssel, der Gross- und Kleinschreibung unterscheidet, als erstes Argument und den Standardwert als zweites Argument. Dieses Argument bestimmt auch welche Art von Daten, also z.B. eine Farbe in Zeile 3, erwartet wird und auch die Art von Objekt, die zurückgegeben werden soll.Das zurückgegebene Objekt wird in eine {{qt|QVariant}} gepackt um diese Hexerei zu ermöglichen. &lt;br /&gt;
&lt;br /&gt;
Es gibt eine Anzahl von speziellen Methoden, zum Beispiel &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt;, das einen Datei-Systempfad zurückgibt. Es ist entscheidend, dass man &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; benutzt, wenn man nach einem Pfad fragt, das es Funktionen wie Erreichbarkeits-Profile ermöglicht richtig zu funktionieren.&lt;br /&gt;
&lt;br /&gt;
Wenn kein solcher Schlüssel im Konfigurationsobjekt existiert, dann wird stattdessen der Standardwert zurückgegeben. Falls es eine lokalisierte (d.h. in eine andere Sprache übersetzte) Version für den Schlüssel gibt, die der eingestellten Sprache entspricht, dann wird diese zurückgegeben.&lt;br /&gt;
&lt;br /&gt;
== Schreiben neuer Einträge ==&lt;br /&gt;
&lt;br /&gt;
Neue Werte zu definieren ist ähnlich einfach:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
generalGroup.writeEntry( &amp;quot;Account&amp;quot;, accountName );&lt;br /&gt;
generalGroup.writePathEntry( &amp;quot;SaveTo&amp;quot;, savePath );&lt;br /&gt;
colorGroup.writeEntry( &amp;quot;background&amp;quot;, color );&lt;br /&gt;
generalGroup.config()-&amp;gt;sync();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beachten sie die Benutzung von &amp;lt;tt&amp;gt;writePathEntry&amp;lt;/tt&amp;gt; und wie die Art von Objekt, das wir benutzen, wie zum Beispiel {{qt|QColor}} auf Zeile 3, bestimmt, wie die Daten angeordnet werden. Zusätzlich, wenn wir mit den Einträgen fertig sind, muss &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; auf das Konfigurationsobjekt ausgeführt werden, um es auf die Festplatte zu speichern. Man kann auch einfach warten, bis das Objekt zerstört wird, was falls nötig automatisch einen &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; auslöst.&lt;br /&gt;
&lt;br /&gt;
== KDesktopFile: Ein besonderer Fall ==&lt;br /&gt;
&lt;br /&gt;
Wann ist eine Konfigurationsdatei keine Konfigurationsdatei? Wenn es eine [http://freedesktop.org/wiki/Standards_2fdesktop_2dentry_2dspec Desktop-Datei] ist. Diese Dateien, die im Grunde genommen Konfigurationsdateien sind, werden benutzt um Einträge für Anwendungsmenüs, Dateitypen, Plugins und verschiedene Services.&lt;br /&gt;
&lt;br /&gt;
Wenn auf eine .desktop Datei zugegriffen wird, sollte man stattdessen die  {{class|KDesktopFile}}-Klasse verwenden, die, während eine {{class|KConfig}}-Klasse über alle oben genannten Ressourcen verfügt, über eine Anzahl von Methoden verfügt, um das Zugreifen auf Standard-Attribute dieser Dateien konsistent und zuverlässig zu machen.&lt;br /&gt;
&lt;br /&gt;
== Kiosk: Lockdown and User/Group Profiles ==&lt;br /&gt;
&lt;br /&gt;
KConfig provides a powerful set of lockdown and configuration definition capabilities, collectively known as &amp;quot;Kiosk&amp;quot;, that many system administrators and system integrators rely on. While most of this framework is provided transparently to the application, there is occassion when an application will want to check on the read/write status of a configuration object.&lt;br /&gt;
&lt;br /&gt;
Entries in configuration objects that are locked down using the kiosk facilities are said to be ''immutable''. An application can check for immutability of entire configuration objects, groups or keys as shown in this example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::config();&lt;br /&gt;
&lt;br /&gt;
if ( config-&amp;gt;isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;configuration object is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
KConfigGroup group(config, &amp;quot;General&amp;quot;);&lt;br /&gt;
if ( group.isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;group General is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if ( group.entryIsImmutable(&amp;quot;URL&amp;quot;) ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;URL entry in group General is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This can be useful in particular situations where an action should be taken when an item is immutable. For instance, the KDE panels will not offer configuration options to the user or allow them to otherwise change the order of applets and icons when the panel's configuration object is marked as immutable.&lt;br /&gt;
&lt;br /&gt;
== KConfig XT ==&lt;br /&gt;
&lt;br /&gt;
There is a way to make certain use cases of KConfig easier, faster and more reliable: KConfig XT. In particular, for main application or plugin configuration objects and when syncing configuration dialogs and other interfaces with these values, KConfig XT can help immensely. It also  simultaneously documents the configuration options available, which makes every sys admin and system integrator that uses KDE that much more happy.&lt;br /&gt;
&lt;br /&gt;
[[../Using_KConfig_XT|The next tutorial in the KConfig series covers what KConfig XT is and how to use it.]]&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials/KConfig_(de)</id>
		<title>Development/Tutorials/KConfig (de)</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials/KConfig_(de)"/>
				<updated>2008-01-03T20:40:11Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: /* Writing Entries */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:I18n/Language Navigation Bar|Development/Tutorials/KConfig}}&lt;br /&gt;
&lt;br /&gt;
{{TutorialBrowser (de)|&lt;br /&gt;
&lt;br /&gt;
series=KConfig|&lt;br /&gt;
&lt;br /&gt;
name=Einführung in KConfig|&lt;br /&gt;
&lt;br /&gt;
pre=Keine|&lt;br /&gt;
&lt;br /&gt;
next=[[../Using_KConfig_XT (de)|Benutzen von KConfig XT]]|&lt;br /&gt;
&lt;br /&gt;
reading=Keine&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{improve (de)}}&lt;br /&gt;
&lt;br /&gt;
== Zusammenfassung ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dieser Artikel beschäftigt sich mir dem KDE Einstellungdaten-System, angefangen mit einer Übersicht über den grundlegenden Aufbau aus der Sicht eines Entwicklers. Es wirft ausserdem einen Blick auf jede der Klassen, die für die Entwicklung von Anwendungen relevant sind und fährt dann mit kiosk (Benutzer- und Gruppenprofile) Integration fort.&lt;br /&gt;
&lt;br /&gt;
== Grundlegender Aufbau ==&lt;br /&gt;
&lt;br /&gt;
KConfig ist ausgelegt um das Konzept vom eigentlichen Speichern und Auffinden von Konfigurationsdaten hinter eine Programmierschnittstelle zu abstrahieren die es ermöglicht, auf einfache Weise Informationen abzurufen und zu setzen. Wo oder in welcher Form Daten gespeichert werden ist für eine Anwendung die KConfig benutzt irrelevant.&lt;br /&gt;
&lt;br /&gt;
Das behält alle KDE Anwendungen konsistent in ihrer Art, Konfigurationen handzuhaben und nimmt einem Anwendungs-Entwickler die Arbeit so ein System von Grund auf neu zu schreiben, was ein sehr fehleranfälliger Prozess sein kann.&lt;br /&gt;
&lt;br /&gt;
Jedes KConfig Objekt verkörpert ein einziges Konfigurationsobjekt. Jedes Konfigurationsobjekt ist durch seinen einzigartigen Namen gekennzeichnet und kann von mehreren lokalen oder externen Daten oder Services gelesen werden. Jede Anwendung hat standardmässig ein zugehöriges Konfigurationsobjekt und es gibt auch ein globales Konfigurationsobjekt.&lt;br /&gt;
&lt;br /&gt;
Diese Konfigurationsobjekte sind nach einer zweistufigen Hierarchie getrennt: Gruppen und Schlüssel. Ein Konfigurationsobjekt kann eine beliebige Anzahl an Gruppen haben und jede Gruppe kann einen oder mehrere Schlüssel mit zugehörigen Werten haben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die gespeicherten Werte können aus beliebig vielen verschiedenen Datentypen bestehen. Sie werden gespeichert und abgerufen als das Objekt selbst. Zum Beispiel wird ein {{qt|QObject}}-Objekt direkt einem Konfigurationsobjekt übergeben, wenn es einen Farbwert speichert und wenn ein Farbwert abgerufen wird, wird ein {{qt|QObject}}-Objekt zurückgegeben.&lt;br /&gt;
&lt;br /&gt;
{{note (de)| deserialization  entgliedern? &amp;lt;br&amp;gt; &amp;lt;tt&amp;gt; &amp;quot;do not have to perform serialization and deserialization of objects themselves&amp;quot; &amp;lt;/tt&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Anwendungen selbst müssen darum normalerweise Objekte nicht selber gliedern und entgliedern.&lt;br /&gt;
&lt;br /&gt;
Applications themselves therefore generally do not have to perform serialization and deserialization of objects themselves.&lt;br /&gt;
&lt;br /&gt;
== Die KConfig Klasse ==&lt;br /&gt;
&lt;br /&gt;
Das {{class|KConfig}}-Objekt wird benutzt um ein bestehendes Konfigurationsobjekt anzusteuern. Es gibt eine Reihe von Möglichkeiten ein Konfigurationsobjekt zu erstellen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
// ein einfaches, altes lesen/schreiben Konfigurationsobjekt&lt;br /&gt;
KConfig config(&amp;quot;myapprc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// eine bestimmte Datei im Dateisystem&lt;br /&gt;
// currently must be an INI style file&lt;br /&gt;
KConfig fullPath(&amp;quot;/etc/kderc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// nicht mit globalen Werten verflochten&lt;br /&gt;
KConfig globalFree( &amp;quot;localsrc&amp;quot;, KConfig::NoGlobals );&lt;br /&gt;
&lt;br /&gt;
// nicht mit globalen Werten orde der $KDEDIRS Hierarchie verflochten&lt;br /&gt;
KConfig simpleConfig( &amp;quot;simplerc&amp;quot;, KConfig::SimpleConfig );&lt;br /&gt;
&lt;br /&gt;
// Komponenten-spezifische Konfiguration, in diesem Fall ein Plugin&lt;br /&gt;
KConfig pluginConfig( componentData(), &amp;quot;pluginrc&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
// Ausserhalb der normalen Konfigurations-Ressource&lt;br /&gt;
KConfig dataResource( &amp;quot;data&amp;quot;, &amp;quot;myapp/somefile&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{note (de)|wie soll &amp;quot;merged&amp;quot; in den folgenden Fällen übersetzt werden? &amp;lt;br&amp;gt; &amp;lt;tt&amp;gt;&amp;quot;verschmolzen&amp;quot; oder &amp;quot;verflochten&amp;quot;&amp;lt;/tt&amp;gt; &amp;lt;br&amp;gt; der Anwendung selber transparent&amp;quot; tönt auch nicht sehr gut}}&lt;br /&gt;
&lt;br /&gt;
Das Kconfig Objekt, das wir auf Zeile 2 erstellen ist ein gewöhnliches Konfigurationsobjekt. Wir können Werte aus ihm lesen, neue Einträge schreiben und nach verschiedenen Eigenschaften des Objekts fragen. Dieses Objekt wird aus der Konfigurations-Ressource geladen, wie es durch {{class|KStandardDirs}} bestimmt wird, das heisst, dass jede Instanz des &amp;lt;tt&amp;gt;myapprc&amp;lt;/tt&amp;gt;-Objekts in jedem der Ordner in der Konfigurations-Ressourcen-Hierarchie verschmolzen werden um die Werte zu erzeugen, die in diesem Objekt gesehen werden. So werden Systemweite und &lt;br /&gt;
pro-Benutzer/Gruppen Profile erstellt und unterstützt. Das alles geschieht der Anwendung selber transparent.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{tip| Für mehr Informationen, wie das Verschmelzen funktioniert, siehe diesen Artikel über die [[KDE System Administration/KDE_Filesystem_Hierarchy|KDE Dateisystem Hierarchie]].}}&lt;br /&gt;
&lt;br /&gt;
{{note (de)|Ist das so gemeint mit &amp;quot;expects an INI style file&amp;quot;&amp;lt;br&amp;gt; &amp;lt;tt&amp;gt; On line 6 we open a specific local file, this case /etc/kderc. This performs no merging of values and expects an INI style file.&amp;lt;/tt&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Auf Zeile 6 öffnen wir eine bestimmte Lokale Datei, in diesem Fall {{path|/etc/kderc}}. Das führt kein verschmelzen von Werten aus und erwartet eine Datei im INI Format.&lt;br /&gt;
&lt;br /&gt;
Zeile 9 erzeugt ein Konfigurationsobjekt, dass nicht mit dem globalen &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt;-Konfigurationsobjekt verflochten ist,  während das Konfigurationsobjekt auf Zeile 12 zusätzlich mit keinem der Dateien in der &amp;lt;tt&amp;gt;$KDEDIRS&amp;lt;/tt&amp;gt;-Hierarchie verflochten ist. Das kann die Leistung spürbar verbessern, falls man einfach nur Werte aus einer einfachen Konfuguration liest und globale Werte keine Rolle spielen.&lt;br /&gt;
&lt;br /&gt;
Zeile 15 erzeugt ein Konfigurationsobjekt unter Benutzung des {{class|KComponentData}}-Objekts das zu einem Plugin oder einer anderen Komponente gehört. Das Plugin kann verschiedene Ordner aufweisen, die in seinen {{class|KStandardDirs}} definiert sind und das ist eine Möglichkeit sich zu versichern, dass {{class|KConfig}} das respektiert.&lt;br /&gt;
&lt;br /&gt;
Und schliesslich auf Zeile 18 erzeugen wir ein Konfigurationsobjekt, das nicht in der &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt;-Ressource sondern in der &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt;-Ressource existiert. Man kann kann auf diese Weise jede Ressource verwenden, von denen {{class|KStandardDirs}} Kenntnis hat, auch solche die während der Laufzeit hinzugefügt werden.&lt;br /&gt;
&lt;br /&gt;
=== Spezielle Konfigurationsobjekte ===&lt;br /&gt;
&lt;br /&gt;
Jede Anwendung hat sein eigenes Konfigurationsobjekt das den Namen benutzt, der von {{class|KAboutData}} bereitgestellt wird mit angehängtem &amp;quot;rc&amp;quot;. Also hätte eine Anwendung mit dem Namen &amp;quot;myapp&amp;quot; das Standard-Konfigurationsobjekt &amp;quot;myapprc&amp;quot;. Dieses Konfigurationsobjekt kann auf diese Weise aufgerufen werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KComponentData&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
#include &amp;lt;KGlobal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    // beachten sie, dass dies eigentlich ein KSharedConfig ist&lt;br /&gt;
    // mehr über diese Klasse siehe weiter unten&lt;br /&gt;
    KConfig* config = KGlobal::config();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Auf das Standard-Konfigurationsobjekt für die Anwendung wird zugegriffen, wenn kein Name definiert wurde, als das {{class|KConfig}}-Objekt erzeugt wurde. Also könnten wir stattdessen auch das tun:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    KConfig config;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zusätzlich könnte jede Komponente sein eigenes Konfigurationsobjekt haben. Auf dieses wird normalerweise durch die &amp;lt;tt&amp;gt;componentData()&amp;lt;/tt&amp;gt; des Plugins zugegriffen, anstatt durch die &amp;lt;tt&amp;gt;{{class|KGlobal}}::mainComponent()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Und schliesslich gibt es noch ein globales Konfigurationsobjekt, &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt;, das von jeder Anwendung verwendet wird. Es enthält Informationen wie die Standard-Tatenkombinationen für verschiedene Aktionen. Es wird in das Konfigurationsobjekt &amp;quot;gemischt&amp;quot; wenn der &amp;lt;tt&amp;gt;KConfig::IncludeGlobals&amp;lt;/tt&amp;gt; Bitschalter dem {{class|KConfig}} Konstruktor übergeben wird, was standardmässig der Fall ist.&lt;br /&gt;
&lt;br /&gt;
=== Allgemein nützliche Methoden ===&lt;br /&gt;
&lt;br /&gt;
Um den momentanen Zustand des Konfigurationsobjektes zu speichern, rufen wir die &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt;-Methode auf. Diese Methode wird also aufgerufen, wenn ein Objekt zerstört wird. Falls keine Änderungen gemacht wurden, oder die Ressource weist sich als nicht beschreibbar aus (Wenn der Benutzer zum Beispiel nicht genug Rechte hat, um die Datei zu bearbeiten), dann wird keine Beschäftigung der Festplatte hervorgerufen. &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; verschmilzt Änderungen die gleichzeitig von anderen Prozessen ausgeführt werden - lokale Änderungen haben aber trotzdem Vorrang.&lt;br /&gt;
&lt;br /&gt;
Wenn wir sicher gehen wollen, dass wir die aktuellsten Werte von der Festplatte haben, dann rufen wir &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt; auf, welches &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; aufruft und dann die Daten von der Festplatte aktualisiert.&lt;br /&gt;
&lt;br /&gt;
Falls wir verhindern müssen, dass das Konfigurationsobjekt bereits gemachte Änderungen nicht auf die Festplatte speichert, müssen wir &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt; aufrufen. Ein besonderer Anwendungsfall ist es, die Konfiguration zum Festplatten-Zustand zurückzusetzen indem man &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt; gefolgt von &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt; aufruft.&lt;br /&gt;
&lt;br /&gt;
Alle Gruppen in einem Konfigurationsobjekt aufzurufen ist so einfach wie hier in diesem Code-Abschnitt &amp;lt;tt&amp;gt;groupList()&amp;lt;/tt&amp;gt; aufzurufen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::mainComponent().config();&lt;br /&gt;
&lt;br /&gt;
foreach ( const QString&amp;amp; group, config.groupList() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;next group:&amp;quot; &amp;lt;&amp;lt; group;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== KSharedConfig ==&lt;br /&gt;
&lt;br /&gt;
Die {{class|KSharedConfig}} Klasse ist eine Referenz-gezählte Version von {{class|KConfig}}. Darum stellt es eine Möglichkeit bereit, das selbe Konfigurationsobjekt von unterschiedlichen Orten zu referenzieren ohne zusätzlich die Objekte trennen zu müssen oder sich um die Synchronisation des Schreibvorgangs zu kümmern, selbst wenn das Konfigurationsobjekt von verschiedenen Code-Pfaden aktualisiert wird.&lt;br /&gt;
&lt;br /&gt;
Auf ein {{class|KSharedConfig}}-Objekt zuzugreifen ist so einfach wie das hier:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KSharedConfigPtr config = KSharedConfig::openConfig();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;openConfig()&amp;lt;/tt&amp;gt; nimmt die selben Parameter wie {{class|KConfig}}'s Konstruktoren, was es einem ermöglicht zu definieren, welche Konfigurationsdatei zu öffnen und Markierungen das Verschmelzen von nicht-&amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt;-Ressourcen zu kontrollieren.  &lt;br /&gt;
&lt;br /&gt;
Es wird grundsätzlich empfohlen {{class|KSharedConfig}} anstatt {{class|KConfig}} selbst zu benutzen, und auch das Objekt, das von {{class|KComponentData}} zurückgegeben wird ist in der Tat ein {{class|KSharedConfig}}-Objekt.&lt;br /&gt;
&lt;br /&gt;
== KConfigGroup ==&lt;br /&gt;
&lt;br /&gt;
Nun da wir ein Konfigurationsobjekt haben, ist der nächste Schritt es tatsächlich zu nutzen. Das erste, das wir tun müssen, ist zu bestimmen, auf welche Gruppe von Schlüssel-/Wertepaare wir in unserem Objekt zugreifen wollen. Wir tun das, indem wir ein KConfigGroup-Objekt erstellen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig config;&lt;br /&gt;
KConfigGroup generalGroup( &amp;amp;config, &amp;quot;General&amp;quot; );&lt;br /&gt;
KConfigGroup colorsGroup = config.group( &amp;quot;Colors&amp;quot; ); // ...oder so ähnlich...&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Man kann{{class|KConfigGroup}} {{class|KConfig}}- oder {{class|KSharedConfig}}-Objekte übergeben.&lt;br /&gt;
&lt;br /&gt;
Konfigurationsgruppen können ebenfalls verschachtelt werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfigGroup subGroup1( &amp;amp;generalGroup, &amp;quot;LessGeneral&amp;quot; );&lt;br /&gt;
KConfigGroup subGroup2 = colorsGroup.group( &amp;quot;Dialogs&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Lesen von Einträgen ==&lt;br /&gt;
&lt;br /&gt;
{{note (de)| Der Rest muss noch übersetzt werden}}&lt;br /&gt;
&lt;br /&gt;
Wenn man erst einmal ein {{class|KConfigGroup}}-Objekt erstellt hat, ist das Lesen von Einträgen ziemlich einfach:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
QString accountName = generalGroup.readEntry( &amp;quot;Account&amp;quot;,&lt;br /&gt;
                                              QString() );&lt;br /&gt;
QColor color = colorsGroup.readEntry( &amp;quot;background&amp;quot;,&lt;br /&gt;
                                      Qt::white );&lt;br /&gt;
QStringList list = generalGroup.readEntry( &amp;quot;List&amp;quot;,&lt;br /&gt;
                                           QStringList() );&lt;br /&gt;
QString path = generalGroup.readPathEntry( &amp;quot;SaveTo&amp;quot;,&lt;br /&gt;
                                           defaultPath );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wie man hier oben sehen kann, kann man Lesevorgänge von verschiedenen {{class|KConfigGroup}}-Objekten, die auf dem selben {{class|KConfig}}-Objekt erstellt wurden, problemlos mischen. Die Lese-Methoden nehmen den Schlüssel, der Gross- und Kleinschreibung unterscheidet, als erstes Argument und den Standardwert als zweites Argument. Dieses Argument bestimmt auch welche Art von Daten, also z.B. eine Farbe in Zeile 3, erwartet wird und auch die Art von Objekt, die zurückgegeben werden soll.Das zurückgegebene Objekt wird in eine {{qt|QVariant}} gepackt um diese Hexerei zu ermöglichen. &lt;br /&gt;
&lt;br /&gt;
Es gibt eine Anzahl von speziellen Methoden, zum Beispiel &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt;, das einen Datei-Systempfad zurückgibt. Es ist entscheidend, dass man &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; benutzt, wenn man nach einem Pfad fragt, das es Funktionen wie Erreichbarkeits-Profile ermöglicht richtig zu funktionieren.&lt;br /&gt;
&lt;br /&gt;
Wenn kein solcher Schlüssel im Konfigurationsobjekt existiert, dann wird stattdessen der Standardwert zurückgegeben. Falls es eine lokalisierte (d.h. in eine andere Sprache übersetzte) Version für den Schlüssel gibt, die der eingestellten Sprache entspricht, dann wird diese zurückgegeben.&lt;br /&gt;
&lt;br /&gt;
== Schreiben neuer Einträge ==&lt;br /&gt;
&lt;br /&gt;
Neue Werte zu definieren ist ähnlich einfach:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
generalGroup.writeEntry( &amp;quot;Account&amp;quot;, accountName );&lt;br /&gt;
generalGroup.writePathEntry( &amp;quot;SaveTo&amp;quot;, savePath );&lt;br /&gt;
colorGroup.writeEntry( &amp;quot;background&amp;quot;, color );&lt;br /&gt;
generalGroup.config()-&amp;gt;sync();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beachten sie die Benutzung von &amp;lt;tt&amp;gt;writePathEntry&amp;lt;/tt&amp;gt; und wie die Art von Objekt, das wir benutzen, wie zum Beispiel {{qt|QColor}} auf Zeile 3, bestimmt, wie die Daten angeordnet werden. Zusätzlich, wenn wir mit den Einträgen fertig sind, muss &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; auf das Konfigurationsobjekt ausgeführt werden, um es auf die Festplatte zu speichern. Man kann auch einfach warten, bis das Objekt zerstört wird, was falls nötig automatisch einen &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; auslöst.&lt;br /&gt;
&lt;br /&gt;
== KDesktopFile: A Special Case ==&lt;br /&gt;
&lt;br /&gt;
When is a configuration file not a configuration file? When it is a [http://freedesktop.org/wiki/Standards_2fdesktop_2dentry_2dspec desktop file]. These files, which are essentially configuration files at their heart, are used  to describe entries for application menus, mimetypes, plugins and various services.&lt;br /&gt;
&lt;br /&gt;
When accessing a .desktop file, one should instead use the {{class|KDesktopFile}} class which, while a {{class|KConfig}} class offering all the capabilities described above, offers a set of methods designed to make accessing standard attributes of these files consistent and reliable.&lt;br /&gt;
&lt;br /&gt;
== Kiosk: Lockdown and User/Group Profiles ==&lt;br /&gt;
&lt;br /&gt;
KConfig provides a powerful set of lockdown and configuration definition capabilities, collectively known as &amp;quot;Kiosk&amp;quot;, that many system administrators and system integrators rely on. While most of this framework is provided transparently to the application, there is occassion when an application will want to check on the read/write status of a configuration object.&lt;br /&gt;
&lt;br /&gt;
Entries in configuration objects that are locked down using the kiosk facilities are said to be ''immutable''. An application can check for immutability of entire configuration objects, groups or keys as shown in this example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::config();&lt;br /&gt;
&lt;br /&gt;
if ( config-&amp;gt;isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;configuration object is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
KConfigGroup group(config, &amp;quot;General&amp;quot;);&lt;br /&gt;
if ( group.isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;group General is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if ( group.entryIsImmutable(&amp;quot;URL&amp;quot;) ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;URL entry in group General is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This can be useful in particular situations where an action should be taken when an item is immutable. For instance, the KDE panels will not offer configuration options to the user or allow them to otherwise change the order of applets and icons when the panel's configuration object is marked as immutable.&lt;br /&gt;
&lt;br /&gt;
== KConfig XT ==&lt;br /&gt;
&lt;br /&gt;
There is a way to make certain use cases of KConfig easier, faster and more reliable: KConfig XT. In particular, for main application or plugin configuration objects and when syncing configuration dialogs and other interfaces with these values, KConfig XT can help immensely. It also  simultaneously documents the configuration options available, which makes every sys admin and system integrator that uses KDE that much more happy.&lt;br /&gt;
&lt;br /&gt;
[[../Using_KConfig_XT|The next tutorial in the KConfig series covers what KConfig XT is and how to use it.]]&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials/KConfig_(de)</id>
		<title>Development/Tutorials/KConfig (de)</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials/KConfig_(de)"/>
				<updated>2008-01-03T14:03:22Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: /* Lesen von Einträgen */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:I18n/Language Navigation Bar|Development/Tutorials/KConfig}}&lt;br /&gt;
&lt;br /&gt;
{{TutorialBrowser (de)|&lt;br /&gt;
&lt;br /&gt;
series=KConfig|&lt;br /&gt;
&lt;br /&gt;
name=Einführung in KConfig|&lt;br /&gt;
&lt;br /&gt;
pre=Keine|&lt;br /&gt;
&lt;br /&gt;
next=[[../Using_KConfig_XT (de)|Benutzen von KConfig XT]]|&lt;br /&gt;
&lt;br /&gt;
reading=Keine&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{improve (de)}}&lt;br /&gt;
&lt;br /&gt;
== Zusammenfassung ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dieser Artikel beschäftigt sich mir dem KDE Einstellungdaten-System, angefangen mit einer Übersicht über den grundlegenden Aufbau aus der Sicht eines Entwicklers. Es wirft ausserdem einen Blick auf jede der Klassen, die für die Entwicklung von Anwendungen relevant sind und fährt dann mit kiosk (Benutzer- und Gruppenprofile) Integration fort.&lt;br /&gt;
&lt;br /&gt;
== Grundlegender Aufbau ==&lt;br /&gt;
&lt;br /&gt;
KConfig ist ausgelegt um das Konzept vom eigentlichen Speichern und Auffinden von Konfigurationsdaten hinter eine Programmierschnittstelle zu abstrahieren die es ermöglicht, auf einfache Weise Informationen abzurufen und zu setzen. Wo oder in welcher Form Daten gespeichert werden ist für eine Anwendung die KConfig benutzt irrelevant.&lt;br /&gt;
&lt;br /&gt;
Das behält alle KDE Anwendungen konsistent in ihrer Art, Konfigurationen handzuhaben und nimmt einem Anwendungs-Entwickler die Arbeit so ein System von Grund auf neu zu schreiben, was ein sehr fehleranfälliger Prozess sein kann.&lt;br /&gt;
&lt;br /&gt;
Jedes KConfig Objekt verkörpert ein einziges Konfigurationsobjekt. Jedes Konfigurationsobjekt ist durch seinen einzigartigen Namen gekennzeichnet und kann von mehreren lokalen oder externen Daten oder Services gelesen werden. Jede Anwendung hat standardmässig ein zugehöriges Konfigurationsobjekt und es gibt auch ein globales Konfigurationsobjekt.&lt;br /&gt;
&lt;br /&gt;
Diese Konfigurationsobjekte sind nach einer zweistufigen Hierarchie getrennt: Gruppen und Schlüssel. Ein Konfigurationsobjekt kann eine beliebige Anzahl an Gruppen haben und jede Gruppe kann einen oder mehrere Schlüssel mit zugehörigen Werten haben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die gespeicherten Werte können aus beliebig vielen verschiedenen Datentypen bestehen. Sie werden gespeichert und abgerufen als das Objekt selbst. Zum Beispiel wird ein {{qt|QObject}}-Objekt direkt einem Konfigurationsobjekt übergeben, wenn es einen Farbwert speichert und wenn ein Farbwert abgerufen wird, wird ein {{qt|QObject}}-Objekt zurückgegeben.&lt;br /&gt;
&lt;br /&gt;
{{note (de)| deserialization  entgliedern? &amp;lt;br&amp;gt; &amp;lt;tt&amp;gt; &amp;quot;do not have to perform serialization and deserialization of objects themselves&amp;quot; &amp;lt;/tt&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Anwendungen selbst müssen darum normalerweise Objekte nicht selber gliedern und entgliedern.&lt;br /&gt;
&lt;br /&gt;
Applications themselves therefore generally do not have to perform serialization and deserialization of objects themselves.&lt;br /&gt;
&lt;br /&gt;
== Die KConfig Klasse ==&lt;br /&gt;
&lt;br /&gt;
Das {{class|KConfig}}-Objekt wird benutzt um ein bestehendes Konfigurationsobjekt anzusteuern. Es gibt eine Reihe von Möglichkeiten ein Konfigurationsobjekt zu erstellen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
// ein einfaches, altes lesen/schreiben Konfigurationsobjekt&lt;br /&gt;
KConfig config(&amp;quot;myapprc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// eine bestimmte Datei im Dateisystem&lt;br /&gt;
// currently must be an INI style file&lt;br /&gt;
KConfig fullPath(&amp;quot;/etc/kderc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// nicht mit globalen Werten verflochten&lt;br /&gt;
KConfig globalFree( &amp;quot;localsrc&amp;quot;, KConfig::NoGlobals );&lt;br /&gt;
&lt;br /&gt;
// nicht mit globalen Werten orde der $KDEDIRS Hierarchie verflochten&lt;br /&gt;
KConfig simpleConfig( &amp;quot;simplerc&amp;quot;, KConfig::SimpleConfig );&lt;br /&gt;
&lt;br /&gt;
// Komponenten-spezifische Konfiguration, in diesem Fall ein Plugin&lt;br /&gt;
KConfig pluginConfig( componentData(), &amp;quot;pluginrc&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
// Ausserhalb der normalen Konfigurations-Ressource&lt;br /&gt;
KConfig dataResource( &amp;quot;data&amp;quot;, &amp;quot;myapp/somefile&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{note (de)|wie soll &amp;quot;merged&amp;quot; in den folgenden Fällen übersetzt werden? &amp;lt;br&amp;gt; &amp;lt;tt&amp;gt;&amp;quot;verschmolzen&amp;quot; oder &amp;quot;verflochten&amp;quot;&amp;lt;/tt&amp;gt; &amp;lt;br&amp;gt; der Anwendung selber transparent&amp;quot; tönt auch nicht sehr gut}}&lt;br /&gt;
&lt;br /&gt;
Das Kconfig Objekt, das wir auf Zeile 2 erstellen ist ein gewöhnliches Konfigurationsobjekt. Wir können Werte aus ihm lesen, neue Einträge schreiben und nach verschiedenen Eigenschaften des Objekts fragen. Dieses Objekt wird aus der Konfigurations-Ressource geladen, wie es durch {{class|KStandardDirs}} bestimmt wird, das heisst, dass jede Instanz des &amp;lt;tt&amp;gt;myapprc&amp;lt;/tt&amp;gt;-Objekts in jedem der Ordner in der Konfigurations-Ressourcen-Hierarchie verschmolzen werden um die Werte zu erzeugen, die in diesem Objekt gesehen werden. So werden Systemweite und &lt;br /&gt;
pro-Benutzer/Gruppen Profile erstellt und unterstützt. Das alles geschieht der Anwendung selber transparent.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{tip| Für mehr Informationen, wie das Verschmelzen funktioniert, siehe diesen Artikel über die [[KDE System Administration/KDE_Filesystem_Hierarchy|KDE Dateisystem Hierarchie]].}}&lt;br /&gt;
&lt;br /&gt;
{{note (de)|Ist das so gemeint mit &amp;quot;expects an INI style file&amp;quot;&amp;lt;br&amp;gt; &amp;lt;tt&amp;gt; On line 6 we open a specific local file, this case /etc/kderc. This performs no merging of values and expects an INI style file.&amp;lt;/tt&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Auf Zeile 6 öffnen wir eine bestimmte Lokale Datei, in diesem Fall {{path|/etc/kderc}}. Das führt kein verschmelzen von Werten aus und erwartet eine Datei im INI Format.&lt;br /&gt;
&lt;br /&gt;
Zeile 9 erzeugt ein Konfigurationsobjekt, dass nicht mit dem globalen &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt;-Konfigurationsobjekt verflochten ist,  während das Konfigurationsobjekt auf Zeile 12 zusätzlich mit keinem der Dateien in der &amp;lt;tt&amp;gt;$KDEDIRS&amp;lt;/tt&amp;gt;-Hierarchie verflochten ist. Das kann die Leistung spürbar verbessern, falls man einfach nur Werte aus einer einfachen Konfuguration liest und globale Werte keine Rolle spielen.&lt;br /&gt;
&lt;br /&gt;
Zeile 15 erzeugt ein Konfigurationsobjekt unter Benutzung des {{class|KComponentData}}-Objekts das zu einem Plugin oder einer anderen Komponente gehört. Das Plugin kann verschiedene Ordner aufweisen, die in seinen {{class|KStandardDirs}} definiert sind und das ist eine Möglichkeit sich zu versichern, dass {{class|KConfig}} das respektiert.&lt;br /&gt;
&lt;br /&gt;
Und schliesslich auf Zeile 18 erzeugen wir ein Konfigurationsobjekt, das nicht in der &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt;-Ressource sondern in der &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt;-Ressource existiert. Man kann kann auf diese Weise jede Ressource verwenden, von denen {{class|KStandardDirs}} Kenntnis hat, auch solche die während der Laufzeit hinzugefügt werden.&lt;br /&gt;
&lt;br /&gt;
=== Spezielle Konfigurationsobjekte ===&lt;br /&gt;
&lt;br /&gt;
Jede Anwendung hat sein eigenes Konfigurationsobjekt das den Namen benutzt, der von {{class|KAboutData}} bereitgestellt wird mit angehängtem &amp;quot;rc&amp;quot;. Also hätte eine Anwendung mit dem Namen &amp;quot;myapp&amp;quot; das Standard-Konfigurationsobjekt &amp;quot;myapprc&amp;quot;. Dieses Konfigurationsobjekt kann auf diese Weise aufgerufen werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KComponentData&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
#include &amp;lt;KGlobal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    // beachten sie, dass dies eigentlich ein KSharedConfig ist&lt;br /&gt;
    // mehr über diese Klasse siehe weiter unten&lt;br /&gt;
    KConfig* config = KGlobal::config();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Auf das Standard-Konfigurationsobjekt für die Anwendung wird zugegriffen, wenn kein Name definiert wurde, als das {{class|KConfig}}-Objekt erzeugt wurde. Also könnten wir stattdessen auch das tun:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    KConfig config;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zusätzlich könnte jede Komponente sein eigenes Konfigurationsobjekt haben. Auf dieses wird normalerweise durch die &amp;lt;tt&amp;gt;componentData()&amp;lt;/tt&amp;gt; des Plugins zugegriffen, anstatt durch die &amp;lt;tt&amp;gt;{{class|KGlobal}}::mainComponent()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Und schliesslich gibt es noch ein globales Konfigurationsobjekt, &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt;, das von jeder Anwendung verwendet wird. Es enthält Informationen wie die Standard-Tatenkombinationen für verschiedene Aktionen. Es wird in das Konfigurationsobjekt &amp;quot;gemischt&amp;quot; wenn der &amp;lt;tt&amp;gt;KConfig::IncludeGlobals&amp;lt;/tt&amp;gt; Bitschalter dem {{class|KConfig}} Konstruktor übergeben wird, was standardmässig der Fall ist.&lt;br /&gt;
&lt;br /&gt;
=== Allgemein nützliche Methoden ===&lt;br /&gt;
&lt;br /&gt;
Um den momentanen Zustand des Konfigurationsobjektes zu speichern, rufen wir die &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt;-Methode auf. Diese Methode wird also aufgerufen, wenn ein Objekt zerstört wird. Falls keine Änderungen gemacht wurden, oder die Ressource weist sich als nicht beschreibbar aus (Wenn der Benutzer zum Beispiel nicht genug Rechte hat, um die Datei zu bearbeiten), dann wird keine Beschäftigung der Festplatte hervorgerufen. &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; verschmilzt Änderungen die gleichzeitig von anderen Prozessen ausgeführt werden - lokale Änderungen haben aber trotzdem Vorrang.&lt;br /&gt;
&lt;br /&gt;
Wenn wir sicher gehen wollen, dass wir die aktuellsten Werte von der Festplatte haben, dann rufen wir &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt; auf, welches &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; aufruft und dann die Daten von der Festplatte aktualisiert.&lt;br /&gt;
&lt;br /&gt;
Falls wir verhindern müssen, dass das Konfigurationsobjekt bereits gemachte Änderungen nicht auf die Festplatte speichert, müssen wir &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt; aufrufen. Ein besonderer Anwendungsfall ist es, die Konfiguration zum Festplatten-Zustand zurückzusetzen indem man &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt; gefolgt von &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt; aufruft.&lt;br /&gt;
&lt;br /&gt;
Alle Gruppen in einem Konfigurationsobjekt aufzurufen ist so einfach wie hier in diesem Code-Abschnitt &amp;lt;tt&amp;gt;groupList()&amp;lt;/tt&amp;gt; aufzurufen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::mainComponent().config();&lt;br /&gt;
&lt;br /&gt;
foreach ( const QString&amp;amp; group, config.groupList() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;next group:&amp;quot; &amp;lt;&amp;lt; group;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== KSharedConfig ==&lt;br /&gt;
&lt;br /&gt;
Die {{class|KSharedConfig}} Klasse ist eine Referenz-gezählte Version von {{class|KConfig}}. Darum stellt es eine Möglichkeit bereit, das selbe Konfigurationsobjekt von unterschiedlichen Orten zu referenzieren ohne zusätzlich die Objekte trennen zu müssen oder sich um die Synchronisation des Schreibvorgangs zu kümmern, selbst wenn das Konfigurationsobjekt von verschiedenen Code-Pfaden aktualisiert wird.&lt;br /&gt;
&lt;br /&gt;
Auf ein {{class|KSharedConfig}}-Objekt zuzugreifen ist so einfach wie das hier:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KSharedConfigPtr config = KSharedConfig::openConfig();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;openConfig()&amp;lt;/tt&amp;gt; nimmt die selben Parameter wie {{class|KConfig}}'s Konstruktoren, was es einem ermöglicht zu definieren, welche Konfigurationsdatei zu öffnen und Markierungen das Verschmelzen von nicht-&amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt;-Ressourcen zu kontrollieren.  &lt;br /&gt;
&lt;br /&gt;
Es wird grundsätzlich empfohlen {{class|KSharedConfig}} anstatt {{class|KConfig}} selbst zu benutzen, und auch das Objekt, das von {{class|KComponentData}} zurückgegeben wird ist in der Tat ein {{class|KSharedConfig}}-Objekt.&lt;br /&gt;
&lt;br /&gt;
== KConfigGroup ==&lt;br /&gt;
&lt;br /&gt;
Nun da wir ein Konfigurationsobjekt haben, ist der nächste Schritt es tatsächlich zu nutzen. Das erste, das wir tun müssen, ist zu bestimmen, auf welche Gruppe von Schlüssel-/Wertepaare wir in unserem Objekt zugreifen wollen. Wir tun das, indem wir ein KConfigGroup-Objekt erstellen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig config;&lt;br /&gt;
KConfigGroup generalGroup( &amp;amp;config, &amp;quot;General&amp;quot; );&lt;br /&gt;
KConfigGroup colorsGroup = config.group( &amp;quot;Colors&amp;quot; ); // ...oder so ähnlich...&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Man kann{{class|KConfigGroup}} {{class|KConfig}}- oder {{class|KSharedConfig}}-Objekte übergeben.&lt;br /&gt;
&lt;br /&gt;
Konfigurationsgruppen können ebenfalls verschachtelt werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfigGroup subGroup1( &amp;amp;generalGroup, &amp;quot;LessGeneral&amp;quot; );&lt;br /&gt;
KConfigGroup subGroup2 = colorsGroup.group( &amp;quot;Dialogs&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Lesen von Einträgen ==&lt;br /&gt;
&lt;br /&gt;
{{note (de)| Der Rest muss noch übersetzt werden}}&lt;br /&gt;
&lt;br /&gt;
Wenn man erst einmal ein {{class|KConfigGroup}}-Objekt erstellt hat, ist das Lesen von Einträgen ziemlich einfach:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
QString accountName = generalGroup.readEntry( &amp;quot;Account&amp;quot;,&lt;br /&gt;
                                              QString() );&lt;br /&gt;
QColor color = colorsGroup.readEntry( &amp;quot;background&amp;quot;,&lt;br /&gt;
                                      Qt::white );&lt;br /&gt;
QStringList list = generalGroup.readEntry( &amp;quot;List&amp;quot;,&lt;br /&gt;
                                           QStringList() );&lt;br /&gt;
QString path = generalGroup.readPathEntry( &amp;quot;SaveTo&amp;quot;,&lt;br /&gt;
                                           defaultPath );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wie man hier oben sehen kann, kann man Lesevorgänge von verschiedenen {{class|KConfigGroup}}-Objekten, die auf dem selben {{class|KConfig}}-Objekt erstellt wurden, problemlos mischen. Die Lese-Methoden nehmen den Schlüssel, der Gross- und Kleinschreibung unterscheidet, als erstes Argument und den Standardwert als zweites Argument. Dieses Argument bestimmt auch welche Art von Daten, also z.B. eine Farbe in Zeile 3, erwartet wird und auch die Art von Objekt, die zurückgegeben werden soll.Das zurückgegebene Objekt wird in eine {{qt|QVariant}} gepackt um diese Hexerei zu ermöglichen. &lt;br /&gt;
&lt;br /&gt;
Es gibt eine Anzahl von speziellen Methoden, zum Beispiel &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt;, das einen Datei-Systempfad zurückgibt. Es ist entscheidend, dass man &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; benutzt, wenn man nach einem Pfad fragt, das es Funktionen wie Erreichbarkeits-Profile ermöglicht richtig zu funktionieren.&lt;br /&gt;
&lt;br /&gt;
Wenn kein solcher Schlüssel im Konfigurationsobjekt existiert, dann wird stattdessen der Standardwert zurückgegeben. Falls es eine lokalisierte (d.h. in eine andere Sprache übersetzte) Version für den Schlüssel gibt, die der eingestellten Sprache entspricht, dann wird diese zurückgegeben.&lt;br /&gt;
&lt;br /&gt;
== Writing Entries ==&lt;br /&gt;
&lt;br /&gt;
Setting new values is similarly straightforward:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
generalGroup.writeEntry( &amp;quot;Account&amp;quot;, accountName );&lt;br /&gt;
generalGroup.writePathEntry( &amp;quot;SaveTo&amp;quot;, savePath );&lt;br /&gt;
colorGroup.writeEntry( &amp;quot;background&amp;quot;, color );&lt;br /&gt;
generalGroup.config()-&amp;gt;sync();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note the use of &amp;lt;tt&amp;gt;writePathEntry&amp;lt;/tt&amp;gt; and how the type of object we use, such as {{qt|QColor}} on line 3, dictates how the data is serialized. Additionally, once we are done writing entries, &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; must be called on the config object for it to be saved to disk. We can also simply wait for the object to be destroyed, which triggers an automatic &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; if necessary.&lt;br /&gt;
&lt;br /&gt;
== KDesktopFile: A Special Case ==&lt;br /&gt;
&lt;br /&gt;
When is a configuration file not a configuration file? When it is a [http://freedesktop.org/wiki/Standards_2fdesktop_2dentry_2dspec desktop file]. These files, which are essentially configuration files at their heart, are used  to describe entries for application menus, mimetypes, plugins and various services.&lt;br /&gt;
&lt;br /&gt;
When accessing a .desktop file, one should instead use the {{class|KDesktopFile}} class which, while a {{class|KConfig}} class offering all the capabilities described above, offers a set of methods designed to make accessing standard attributes of these files consistent and reliable.&lt;br /&gt;
&lt;br /&gt;
== Kiosk: Lockdown and User/Group Profiles ==&lt;br /&gt;
&lt;br /&gt;
KConfig provides a powerful set of lockdown and configuration definition capabilities, collectively known as &amp;quot;Kiosk&amp;quot;, that many system administrators and system integrators rely on. While most of this framework is provided transparently to the application, there is occassion when an application will want to check on the read/write status of a configuration object.&lt;br /&gt;
&lt;br /&gt;
Entries in configuration objects that are locked down using the kiosk facilities are said to be ''immutable''. An application can check for immutability of entire configuration objects, groups or keys as shown in this example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::config();&lt;br /&gt;
&lt;br /&gt;
if ( config-&amp;gt;isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;configuration object is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
KConfigGroup group(config, &amp;quot;General&amp;quot;);&lt;br /&gt;
if ( group.isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;group General is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if ( group.entryIsImmutable(&amp;quot;URL&amp;quot;) ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;URL entry in group General is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This can be useful in particular situations where an action should be taken when an item is immutable. For instance, the KDE panels will not offer configuration options to the user or allow them to otherwise change the order of applets and icons when the panel's configuration object is marked as immutable.&lt;br /&gt;
&lt;br /&gt;
== KConfig XT ==&lt;br /&gt;
&lt;br /&gt;
There is a way to make certain use cases of KConfig easier, faster and more reliable: KConfig XT. In particular, for main application or plugin configuration objects and when syncing configuration dialogs and other interfaces with these values, KConfig XT can help immensely. It also  simultaneously documents the configuration options available, which makes every sys admin and system integrator that uses KDE that much more happy.&lt;br /&gt;
&lt;br /&gt;
[[../Using_KConfig_XT|The next tutorial in the KConfig series covers what KConfig XT is and how to use it.]]&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials/KConfig_(de)</id>
		<title>Development/Tutorials/KConfig (de)</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials/KConfig_(de)"/>
				<updated>2008-01-02T17:01:35Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: /* Reading Entries */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:I18n/Language Navigation Bar|Development/Tutorials/KConfig}}&lt;br /&gt;
&lt;br /&gt;
{{TutorialBrowser (de)|&lt;br /&gt;
&lt;br /&gt;
series=KConfig|&lt;br /&gt;
&lt;br /&gt;
name=Einführung in KConfig|&lt;br /&gt;
&lt;br /&gt;
pre=Keine|&lt;br /&gt;
&lt;br /&gt;
next=[[../Using_KConfig_XT (de)|Benutzen von KConfig XT]]|&lt;br /&gt;
&lt;br /&gt;
reading=Keine&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{improve (de)}}&lt;br /&gt;
&lt;br /&gt;
== Zusammenfassung ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dieser Artikel beschäftigt sich mir dem KDE Einstellungdaten-System, angefangen mit einer Übersicht über den grundlegenden Aufbau aus der Sicht eines Entwicklers. Es wirft ausserdem einen Blick auf jede der Klassen, die für die Entwicklung von Anwendungen relevant sind und fährt dann mit kiosk (Benutzer- und Gruppenprofile) Integration fort.&lt;br /&gt;
&lt;br /&gt;
== Grundlegender Aufbau ==&lt;br /&gt;
&lt;br /&gt;
KConfig ist ausgelegt um das Konzept vom eigentlichen Speichern und Auffinden von Konfigurationsdaten hinter eine Programmierschnittstelle zu abstrahieren die es ermöglicht, auf einfache Weise Informationen abzurufen und zu setzen. Wo oder in welcher Form Daten gespeichert werden ist für eine Anwendung die KConfig benutzt irrelevant.&lt;br /&gt;
&lt;br /&gt;
Das behält alle KDE Anwendungen konsistent in ihrer Art, Konfigurationen handzuhaben und nimmt einem Anwendungs-Entwickler die Arbeit so ein System von Grund auf neu zu schreiben, was ein sehr fehleranfälliger Prozess sein kann.&lt;br /&gt;
&lt;br /&gt;
Jedes KConfig Objekt verkörpert ein einziges Konfigurationsobjekt. Jedes Konfigurationsobjekt ist durch seinen einzigartigen Namen gekennzeichnet und kann von mehreren lokalen oder externen Daten oder Services gelesen werden. Jede Anwendung hat standardmässig ein zugehöriges Konfigurationsobjekt und es gibt auch ein globales Konfigurationsobjekt.&lt;br /&gt;
&lt;br /&gt;
Diese Konfigurationsobjekte sind nach einer zweistufigen Hierarchie getrennt: Gruppen und Schlüssel. Ein Konfigurationsobjekt kann eine beliebige Anzahl an Gruppen haben und jede Gruppe kann einen oder mehrere Schlüssel mit zugehörigen Werten haben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die gespeicherten Werte können aus beliebig vielen verschiedenen Datentypen bestehen. Sie werden gespeichert und abgerufen als das Objekt selbst. Zum Beispiel wird ein {{qt|QObject}}-Objekt direkt einem Konfigurationsobjekt übergeben, wenn es einen Farbwert speichert und wenn ein Farbwert abgerufen wird, wird ein {{qt|QObject}}-Objekt zurückgegeben.&lt;br /&gt;
&lt;br /&gt;
{{note (de)| deserialization  entgliedern? &amp;lt;br&amp;gt; &amp;lt;tt&amp;gt; &amp;quot;do not have to perform serialization and deserialization of objects themselves&amp;quot; &amp;lt;/tt&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Anwendungen selbst müssen darum normalerweise Objekte nicht selber gliedern und entgliedern.&lt;br /&gt;
&lt;br /&gt;
Applications themselves therefore generally do not have to perform serialization and deserialization of objects themselves.&lt;br /&gt;
&lt;br /&gt;
== Die KConfig Klasse ==&lt;br /&gt;
&lt;br /&gt;
Das {{class|KConfig}}-Objekt wird benutzt um ein bestehendes Konfigurationsobjekt anzusteuern. Es gibt eine Reihe von Möglichkeiten ein Konfigurationsobjekt zu erstellen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
// ein einfaches, altes lesen/schreiben Konfigurationsobjekt&lt;br /&gt;
KConfig config(&amp;quot;myapprc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// eine bestimmte Datei im Dateisystem&lt;br /&gt;
// currently must be an INI style file&lt;br /&gt;
KConfig fullPath(&amp;quot;/etc/kderc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// nicht mit globalen Werten verflochten&lt;br /&gt;
KConfig globalFree( &amp;quot;localsrc&amp;quot;, KConfig::NoGlobals );&lt;br /&gt;
&lt;br /&gt;
// nicht mit globalen Werten orde der $KDEDIRS Hierarchie verflochten&lt;br /&gt;
KConfig simpleConfig( &amp;quot;simplerc&amp;quot;, KConfig::SimpleConfig );&lt;br /&gt;
&lt;br /&gt;
// Komponenten-spezifische Konfiguration, in diesem Fall ein Plugin&lt;br /&gt;
KConfig pluginConfig( componentData(), &amp;quot;pluginrc&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
// Ausserhalb der normalen Konfigurations-Ressource&lt;br /&gt;
KConfig dataResource( &amp;quot;data&amp;quot;, &amp;quot;myapp/somefile&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{note (de)|wie soll &amp;quot;merged&amp;quot; in den folgenden Fällen übersetzt werden? &amp;lt;br&amp;gt; &amp;lt;tt&amp;gt;&amp;quot;verschmolzen&amp;quot; oder &amp;quot;verflochten&amp;quot;&amp;lt;/tt&amp;gt; &amp;lt;br&amp;gt; der Anwendung selber transparent&amp;quot; tönt auch nicht sehr gut}}&lt;br /&gt;
&lt;br /&gt;
Das Kconfig Objekt, das wir auf Zeile 2 erstellen ist ein gewöhnliches Konfigurationsobjekt. Wir können Werte aus ihm lesen, neue Einträge schreiben und nach verschiedenen Eigenschaften des Objekts fragen. Dieses Objekt wird aus der Konfigurations-Ressource geladen, wie es durch {{class|KStandardDirs}} bestimmt wird, das heisst, dass jede Instanz des &amp;lt;tt&amp;gt;myapprc&amp;lt;/tt&amp;gt;-Objekts in jedem der Ordner in der Konfigurations-Ressourcen-Hierarchie verschmolzen werden um die Werte zu erzeugen, die in diesem Objekt gesehen werden. So werden Systemweite und &lt;br /&gt;
pro-Benutzer/Gruppen Profile erstellt und unterstützt. Das alles geschieht der Anwendung selber transparent.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{tip| Für mehr Informationen, wie das Verschmelzen funktioniert, siehe diesen Artikel über die [[KDE System Administration/KDE_Filesystem_Hierarchy|KDE Dateisystem Hierarchie]].}}&lt;br /&gt;
&lt;br /&gt;
{{note (de)|Ist das so gemeint mit &amp;quot;expects an INI style file&amp;quot;&amp;lt;br&amp;gt; &amp;lt;tt&amp;gt; On line 6 we open a specific local file, this case /etc/kderc. This performs no merging of values and expects an INI style file.&amp;lt;/tt&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Auf Zeile 6 öffnen wir eine bestimmte Lokale Datei, in diesem Fall {{path|/etc/kderc}}. Das führt kein verschmelzen von Werten aus und erwartet eine Datei im INI Format.&lt;br /&gt;
&lt;br /&gt;
Zeile 9 erzeugt ein Konfigurationsobjekt, dass nicht mit dem globalen &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt;-Konfigurationsobjekt verflochten ist,  während das Konfigurationsobjekt auf Zeile 12 zusätzlich mit keinem der Dateien in der &amp;lt;tt&amp;gt;$KDEDIRS&amp;lt;/tt&amp;gt;-Hierarchie verflochten ist. Das kann die Leistung spürbar verbessern, falls man einfach nur Werte aus einer einfachen Konfuguration liest und globale Werte keine Rolle spielen.&lt;br /&gt;
&lt;br /&gt;
Zeile 15 erzeugt ein Konfigurationsobjekt unter Benutzung des {{class|KComponentData}}-Objekts das zu einem Plugin oder einer anderen Komponente gehört. Das Plugin kann verschiedene Ordner aufweisen, die in seinen {{class|KStandardDirs}} definiert sind und das ist eine Möglichkeit sich zu versichern, dass {{class|KConfig}} das respektiert.&lt;br /&gt;
&lt;br /&gt;
Und schliesslich auf Zeile 18 erzeugen wir ein Konfigurationsobjekt, das nicht in der &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt;-Ressource sondern in der &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt;-Ressource existiert. Man kann kann auf diese Weise jede Ressource verwenden, von denen {{class|KStandardDirs}} Kenntnis hat, auch solche die während der Laufzeit hinzugefügt werden.&lt;br /&gt;
&lt;br /&gt;
=== Spezielle Konfigurationsobjekte ===&lt;br /&gt;
&lt;br /&gt;
Jede Anwendung hat sein eigenes Konfigurationsobjekt das den Namen benutzt, der von {{class|KAboutData}} bereitgestellt wird mit angehängtem &amp;quot;rc&amp;quot;. Also hätte eine Anwendung mit dem Namen &amp;quot;myapp&amp;quot; das Standard-Konfigurationsobjekt &amp;quot;myapprc&amp;quot;. Dieses Konfigurationsobjekt kann auf diese Weise aufgerufen werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KComponentData&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
#include &amp;lt;KGlobal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    // beachten sie, dass dies eigentlich ein KSharedConfig ist&lt;br /&gt;
    // mehr über diese Klasse siehe weiter unten&lt;br /&gt;
    KConfig* config = KGlobal::config();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Auf das Standard-Konfigurationsobjekt für die Anwendung wird zugegriffen, wenn kein Name definiert wurde, als das {{class|KConfig}}-Objekt erzeugt wurde. Also könnten wir stattdessen auch das tun:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    KConfig config;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zusätzlich könnte jede Komponente sein eigenes Konfigurationsobjekt haben. Auf dieses wird normalerweise durch die &amp;lt;tt&amp;gt;componentData()&amp;lt;/tt&amp;gt; des Plugins zugegriffen, anstatt durch die &amp;lt;tt&amp;gt;{{class|KGlobal}}::mainComponent()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Und schliesslich gibt es noch ein globales Konfigurationsobjekt, &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt;, das von jeder Anwendung verwendet wird. Es enthält Informationen wie die Standard-Tatenkombinationen für verschiedene Aktionen. Es wird in das Konfigurationsobjekt &amp;quot;gemischt&amp;quot; wenn der &amp;lt;tt&amp;gt;KConfig::IncludeGlobals&amp;lt;/tt&amp;gt; Bitschalter dem {{class|KConfig}} Konstruktor übergeben wird, was standardmässig der Fall ist.&lt;br /&gt;
&lt;br /&gt;
=== Allgemein nützliche Methoden ===&lt;br /&gt;
&lt;br /&gt;
Um den momentanen Zustand des Konfigurationsobjektes zu speichern, rufen wir die &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt;-Methode auf. Diese Methode wird also aufgerufen, wenn ein Objekt zerstört wird. Falls keine Änderungen gemacht wurden, oder die Ressource weist sich als nicht beschreibbar aus (Wenn der Benutzer zum Beispiel nicht genug Rechte hat, um die Datei zu bearbeiten), dann wird keine Beschäftigung der Festplatte hervorgerufen. &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; verschmilzt Änderungen die gleichzeitig von anderen Prozessen ausgeführt werden - lokale Änderungen haben aber trotzdem Vorrang.&lt;br /&gt;
&lt;br /&gt;
Wenn wir sicher gehen wollen, dass wir die aktuellsten Werte von der Festplatte haben, dann rufen wir &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt; auf, welches &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; aufruft und dann die Daten von der Festplatte aktualisiert.&lt;br /&gt;
&lt;br /&gt;
Falls wir verhindern müssen, dass das Konfigurationsobjekt bereits gemachte Änderungen nicht auf die Festplatte speichert, müssen wir &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt; aufrufen. Ein besonderer Anwendungsfall ist es, die Konfiguration zum Festplatten-Zustand zurückzusetzen indem man &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt; gefolgt von &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt; aufruft.&lt;br /&gt;
&lt;br /&gt;
Alle Gruppen in einem Konfigurationsobjekt aufzurufen ist so einfach wie hier in diesem Code-Abschnitt &amp;lt;tt&amp;gt;groupList()&amp;lt;/tt&amp;gt; aufzurufen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::mainComponent().config();&lt;br /&gt;
&lt;br /&gt;
foreach ( const QString&amp;amp; group, config.groupList() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;next group:&amp;quot; &amp;lt;&amp;lt; group;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== KSharedConfig ==&lt;br /&gt;
&lt;br /&gt;
Die {{class|KSharedConfig}} Klasse ist eine Referenz-gezählte Version von {{class|KConfig}}. Darum stellt es eine Möglichkeit bereit, das selbe Konfigurationsobjekt von unterschiedlichen Orten zu referenzieren ohne zusätzlich die Objekte trennen zu müssen oder sich um die Synchronisation des Schreibvorgangs zu kümmern, selbst wenn das Konfigurationsobjekt von verschiedenen Code-Pfaden aktualisiert wird.&lt;br /&gt;
&lt;br /&gt;
Auf ein {{class|KSharedConfig}}-Objekt zuzugreifen ist so einfach wie das hier:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KSharedConfigPtr config = KSharedConfig::openConfig();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;openConfig()&amp;lt;/tt&amp;gt; nimmt die selben Parameter wie {{class|KConfig}}'s Konstruktoren, was es einem ermöglicht zu definieren, welche Konfigurationsdatei zu öffnen und Markierungen das Verschmelzen von nicht-&amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt;-Ressourcen zu kontrollieren.  &lt;br /&gt;
&lt;br /&gt;
Es wird grundsätzlich empfohlen {{class|KSharedConfig}} anstatt {{class|KConfig}} selbst zu benutzen, und auch das Objekt, das von {{class|KComponentData}} zurückgegeben wird ist in der Tat ein {{class|KSharedConfig}}-Objekt.&lt;br /&gt;
&lt;br /&gt;
== KConfigGroup ==&lt;br /&gt;
&lt;br /&gt;
Nun da wir ein Konfigurationsobjekt haben, ist der nächste Schritt es tatsächlich zu nutzen. Das erste, das wir tun müssen, ist zu bestimmen, auf welche Gruppe von Schlüssel-/Wertepaare wir in unserem Objekt zugreifen wollen. Wir tun das, indem wir ein KConfigGroup-Objekt erstellen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig config;&lt;br /&gt;
KConfigGroup generalGroup( &amp;amp;config, &amp;quot;General&amp;quot; );&lt;br /&gt;
KConfigGroup colorsGroup = config.group( &amp;quot;Colors&amp;quot; ); // ...oder so ähnlich...&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Man kann{{class|KConfigGroup}} {{class|KConfig}}- oder {{class|KSharedConfig}}-Objekte übergeben.&lt;br /&gt;
&lt;br /&gt;
Konfigurationsgruppen können ebenfalls verschachtelt werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfigGroup subGroup1( &amp;amp;generalGroup, &amp;quot;LessGeneral&amp;quot; );&lt;br /&gt;
KConfigGroup subGroup2 = colorsGroup.group( &amp;quot;Dialogs&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Lesen von Einträgen ==&lt;br /&gt;
&lt;br /&gt;
{{note (de)| Der Rest muss noch übersetzt werden}}&lt;br /&gt;
&lt;br /&gt;
With a {{class|KConfigGroup}} object in hand reading entries is now quite straight forward:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
QString accountName = generalGroup.readEntry( &amp;quot;Account&amp;quot;,&lt;br /&gt;
                                              QString() );&lt;br /&gt;
QColor color = colorsGroup.readEntry( &amp;quot;background&amp;quot;,&lt;br /&gt;
                                      Qt::white );&lt;br /&gt;
QStringList list = generalGroup.readEntry( &amp;quot;List&amp;quot;,&lt;br /&gt;
                                           QStringList() );&lt;br /&gt;
QString path = generalGroup.readPathEntry( &amp;quot;SaveTo&amp;quot;,&lt;br /&gt;
                                           defaultPath );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As can be seen from the above, you can mix reads from different {{class|KConfigGroup}} objects created on the same {{class|KConfig}} object. The read methods take the key, which is case sensitive, as the first argument and the default value as the second argument. This argument controls what kind of data, e.g. a color in line 3 above, is to be expected as well as the type of object returned. The returned object is wrapped in a {{qt|QVariant}} to make this magic happen.&lt;br /&gt;
&lt;br /&gt;
There are a couple of special read methods, including &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; which returns a file system path. It is vital that one uses &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; if it is a path as this enables such features as roaming profiles to work properly.&lt;br /&gt;
&lt;br /&gt;
If no such key currently exists in the configuration object, the default value is returned instead. If there is a localized (e.g. translated into another language) entry for the key that matches the current locale, that is returned.&lt;br /&gt;
&lt;br /&gt;
== Writing Entries ==&lt;br /&gt;
&lt;br /&gt;
Setting new values is similarly straightforward:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
generalGroup.writeEntry( &amp;quot;Account&amp;quot;, accountName );&lt;br /&gt;
generalGroup.writePathEntry( &amp;quot;SaveTo&amp;quot;, savePath );&lt;br /&gt;
colorGroup.writeEntry( &amp;quot;background&amp;quot;, color );&lt;br /&gt;
generalGroup.config()-&amp;gt;sync();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note the use of &amp;lt;tt&amp;gt;writePathEntry&amp;lt;/tt&amp;gt; and how the type of object we use, such as {{qt|QColor}} on line 3, dictates how the data is serialized. Additionally, once we are done writing entries, &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; must be called on the config object for it to be saved to disk. We can also simply wait for the object to be destroyed, which triggers an automatic &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; if necessary.&lt;br /&gt;
&lt;br /&gt;
== KDesktopFile: A Special Case ==&lt;br /&gt;
&lt;br /&gt;
When is a configuration file not a configuration file? When it is a [http://freedesktop.org/wiki/Standards_2fdesktop_2dentry_2dspec desktop file]. These files, which are essentially configuration files at their heart, are used  to describe entries for application menus, mimetypes, plugins and various services.&lt;br /&gt;
&lt;br /&gt;
When accessing a .desktop file, one should instead use the {{class|KDesktopFile}} class which, while a {{class|KConfig}} class offering all the capabilities described above, offers a set of methods designed to make accessing standard attributes of these files consistent and reliable.&lt;br /&gt;
&lt;br /&gt;
== Kiosk: Lockdown and User/Group Profiles ==&lt;br /&gt;
&lt;br /&gt;
KConfig provides a powerful set of lockdown and configuration definition capabilities, collectively known as &amp;quot;Kiosk&amp;quot;, that many system administrators and system integrators rely on. While most of this framework is provided transparently to the application, there is occassion when an application will want to check on the read/write status of a configuration object.&lt;br /&gt;
&lt;br /&gt;
Entries in configuration objects that are locked down using the kiosk facilities are said to be ''immutable''. An application can check for immutability of entire configuration objects, groups or keys as shown in this example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::config();&lt;br /&gt;
&lt;br /&gt;
if ( config-&amp;gt;isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;configuration object is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
KConfigGroup group(config, &amp;quot;General&amp;quot;);&lt;br /&gt;
if ( group.isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;group General is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if ( group.entryIsImmutable(&amp;quot;URL&amp;quot;) ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;URL entry in group General is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This can be useful in particular situations where an action should be taken when an item is immutable. For instance, the KDE panels will not offer configuration options to the user or allow them to otherwise change the order of applets and icons when the panel's configuration object is marked as immutable.&lt;br /&gt;
&lt;br /&gt;
== KConfig XT ==&lt;br /&gt;
&lt;br /&gt;
There is a way to make certain use cases of KConfig easier, faster and more reliable: KConfig XT. In particular, for main application or plugin configuration objects and when syncing configuration dialogs and other interfaces with these values, KConfig XT can help immensely. It also  simultaneously documents the configuration options available, which makes every sys admin and system integrator that uses KDE that much more happy.&lt;br /&gt;
&lt;br /&gt;
[[../Using_KConfig_XT|The next tutorial in the KConfig series covers what KConfig XT is and how to use it.]]&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials/KConfig_(de)</id>
		<title>Development/Tutorials/KConfig (de)</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials/KConfig_(de)"/>
				<updated>2008-01-02T17:01:19Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: /* Reading Entries */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:I18n/Language Navigation Bar|Development/Tutorials/KConfig}}&lt;br /&gt;
&lt;br /&gt;
{{TutorialBrowser (de)|&lt;br /&gt;
&lt;br /&gt;
series=KConfig|&lt;br /&gt;
&lt;br /&gt;
name=Einführung in KConfig|&lt;br /&gt;
&lt;br /&gt;
pre=Keine|&lt;br /&gt;
&lt;br /&gt;
next=[[../Using_KConfig_XT (de)|Benutzen von KConfig XT]]|&lt;br /&gt;
&lt;br /&gt;
reading=Keine&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{improve (de)}}&lt;br /&gt;
&lt;br /&gt;
== Zusammenfassung ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dieser Artikel beschäftigt sich mir dem KDE Einstellungdaten-System, angefangen mit einer Übersicht über den grundlegenden Aufbau aus der Sicht eines Entwicklers. Es wirft ausserdem einen Blick auf jede der Klassen, die für die Entwicklung von Anwendungen relevant sind und fährt dann mit kiosk (Benutzer- und Gruppenprofile) Integration fort.&lt;br /&gt;
&lt;br /&gt;
== Grundlegender Aufbau ==&lt;br /&gt;
&lt;br /&gt;
KConfig ist ausgelegt um das Konzept vom eigentlichen Speichern und Auffinden von Konfigurationsdaten hinter eine Programmierschnittstelle zu abstrahieren die es ermöglicht, auf einfache Weise Informationen abzurufen und zu setzen. Wo oder in welcher Form Daten gespeichert werden ist für eine Anwendung die KConfig benutzt irrelevant.&lt;br /&gt;
&lt;br /&gt;
Das behält alle KDE Anwendungen konsistent in ihrer Art, Konfigurationen handzuhaben und nimmt einem Anwendungs-Entwickler die Arbeit so ein System von Grund auf neu zu schreiben, was ein sehr fehleranfälliger Prozess sein kann.&lt;br /&gt;
&lt;br /&gt;
Jedes KConfig Objekt verkörpert ein einziges Konfigurationsobjekt. Jedes Konfigurationsobjekt ist durch seinen einzigartigen Namen gekennzeichnet und kann von mehreren lokalen oder externen Daten oder Services gelesen werden. Jede Anwendung hat standardmässig ein zugehöriges Konfigurationsobjekt und es gibt auch ein globales Konfigurationsobjekt.&lt;br /&gt;
&lt;br /&gt;
Diese Konfigurationsobjekte sind nach einer zweistufigen Hierarchie getrennt: Gruppen und Schlüssel. Ein Konfigurationsobjekt kann eine beliebige Anzahl an Gruppen haben und jede Gruppe kann einen oder mehrere Schlüssel mit zugehörigen Werten haben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die gespeicherten Werte können aus beliebig vielen verschiedenen Datentypen bestehen. Sie werden gespeichert und abgerufen als das Objekt selbst. Zum Beispiel wird ein {{qt|QObject}}-Objekt direkt einem Konfigurationsobjekt übergeben, wenn es einen Farbwert speichert und wenn ein Farbwert abgerufen wird, wird ein {{qt|QObject}}-Objekt zurückgegeben.&lt;br /&gt;
&lt;br /&gt;
{{note (de)| deserialization  entgliedern? &amp;lt;br&amp;gt; &amp;lt;tt&amp;gt; &amp;quot;do not have to perform serialization and deserialization of objects themselves&amp;quot; &amp;lt;/tt&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Anwendungen selbst müssen darum normalerweise Objekte nicht selber gliedern und entgliedern.&lt;br /&gt;
&lt;br /&gt;
Applications themselves therefore generally do not have to perform serialization and deserialization of objects themselves.&lt;br /&gt;
&lt;br /&gt;
== Die KConfig Klasse ==&lt;br /&gt;
&lt;br /&gt;
Das {{class|KConfig}}-Objekt wird benutzt um ein bestehendes Konfigurationsobjekt anzusteuern. Es gibt eine Reihe von Möglichkeiten ein Konfigurationsobjekt zu erstellen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
// ein einfaches, altes lesen/schreiben Konfigurationsobjekt&lt;br /&gt;
KConfig config(&amp;quot;myapprc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// eine bestimmte Datei im Dateisystem&lt;br /&gt;
// currently must be an INI style file&lt;br /&gt;
KConfig fullPath(&amp;quot;/etc/kderc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// nicht mit globalen Werten verflochten&lt;br /&gt;
KConfig globalFree( &amp;quot;localsrc&amp;quot;, KConfig::NoGlobals );&lt;br /&gt;
&lt;br /&gt;
// nicht mit globalen Werten orde der $KDEDIRS Hierarchie verflochten&lt;br /&gt;
KConfig simpleConfig( &amp;quot;simplerc&amp;quot;, KConfig::SimpleConfig );&lt;br /&gt;
&lt;br /&gt;
// Komponenten-spezifische Konfiguration, in diesem Fall ein Plugin&lt;br /&gt;
KConfig pluginConfig( componentData(), &amp;quot;pluginrc&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
// Ausserhalb der normalen Konfigurations-Ressource&lt;br /&gt;
KConfig dataResource( &amp;quot;data&amp;quot;, &amp;quot;myapp/somefile&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{note (de)|wie soll &amp;quot;merged&amp;quot; in den folgenden Fällen übersetzt werden? &amp;lt;br&amp;gt; &amp;lt;tt&amp;gt;&amp;quot;verschmolzen&amp;quot; oder &amp;quot;verflochten&amp;quot;&amp;lt;/tt&amp;gt; &amp;lt;br&amp;gt; der Anwendung selber transparent&amp;quot; tönt auch nicht sehr gut}}&lt;br /&gt;
&lt;br /&gt;
Das Kconfig Objekt, das wir auf Zeile 2 erstellen ist ein gewöhnliches Konfigurationsobjekt. Wir können Werte aus ihm lesen, neue Einträge schreiben und nach verschiedenen Eigenschaften des Objekts fragen. Dieses Objekt wird aus der Konfigurations-Ressource geladen, wie es durch {{class|KStandardDirs}} bestimmt wird, das heisst, dass jede Instanz des &amp;lt;tt&amp;gt;myapprc&amp;lt;/tt&amp;gt;-Objekts in jedem der Ordner in der Konfigurations-Ressourcen-Hierarchie verschmolzen werden um die Werte zu erzeugen, die in diesem Objekt gesehen werden. So werden Systemweite und &lt;br /&gt;
pro-Benutzer/Gruppen Profile erstellt und unterstützt. Das alles geschieht der Anwendung selber transparent.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{tip| Für mehr Informationen, wie das Verschmelzen funktioniert, siehe diesen Artikel über die [[KDE System Administration/KDE_Filesystem_Hierarchy|KDE Dateisystem Hierarchie]].}}&lt;br /&gt;
&lt;br /&gt;
{{note (de)|Ist das so gemeint mit &amp;quot;expects an INI style file&amp;quot;&amp;lt;br&amp;gt; &amp;lt;tt&amp;gt; On line 6 we open a specific local file, this case /etc/kderc. This performs no merging of values and expects an INI style file.&amp;lt;/tt&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Auf Zeile 6 öffnen wir eine bestimmte Lokale Datei, in diesem Fall {{path|/etc/kderc}}. Das führt kein verschmelzen von Werten aus und erwartet eine Datei im INI Format.&lt;br /&gt;
&lt;br /&gt;
Zeile 9 erzeugt ein Konfigurationsobjekt, dass nicht mit dem globalen &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt;-Konfigurationsobjekt verflochten ist,  während das Konfigurationsobjekt auf Zeile 12 zusätzlich mit keinem der Dateien in der &amp;lt;tt&amp;gt;$KDEDIRS&amp;lt;/tt&amp;gt;-Hierarchie verflochten ist. Das kann die Leistung spürbar verbessern, falls man einfach nur Werte aus einer einfachen Konfuguration liest und globale Werte keine Rolle spielen.&lt;br /&gt;
&lt;br /&gt;
Zeile 15 erzeugt ein Konfigurationsobjekt unter Benutzung des {{class|KComponentData}}-Objekts das zu einem Plugin oder einer anderen Komponente gehört. Das Plugin kann verschiedene Ordner aufweisen, die in seinen {{class|KStandardDirs}} definiert sind und das ist eine Möglichkeit sich zu versichern, dass {{class|KConfig}} das respektiert.&lt;br /&gt;
&lt;br /&gt;
Und schliesslich auf Zeile 18 erzeugen wir ein Konfigurationsobjekt, das nicht in der &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt;-Ressource sondern in der &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt;-Ressource existiert. Man kann kann auf diese Weise jede Ressource verwenden, von denen {{class|KStandardDirs}} Kenntnis hat, auch solche die während der Laufzeit hinzugefügt werden.&lt;br /&gt;
&lt;br /&gt;
=== Spezielle Konfigurationsobjekte ===&lt;br /&gt;
&lt;br /&gt;
Jede Anwendung hat sein eigenes Konfigurationsobjekt das den Namen benutzt, der von {{class|KAboutData}} bereitgestellt wird mit angehängtem &amp;quot;rc&amp;quot;. Also hätte eine Anwendung mit dem Namen &amp;quot;myapp&amp;quot; das Standard-Konfigurationsobjekt &amp;quot;myapprc&amp;quot;. Dieses Konfigurationsobjekt kann auf diese Weise aufgerufen werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KComponentData&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
#include &amp;lt;KGlobal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    // beachten sie, dass dies eigentlich ein KSharedConfig ist&lt;br /&gt;
    // mehr über diese Klasse siehe weiter unten&lt;br /&gt;
    KConfig* config = KGlobal::config();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Auf das Standard-Konfigurationsobjekt für die Anwendung wird zugegriffen, wenn kein Name definiert wurde, als das {{class|KConfig}}-Objekt erzeugt wurde. Also könnten wir stattdessen auch das tun:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    KConfig config;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zusätzlich könnte jede Komponente sein eigenes Konfigurationsobjekt haben. Auf dieses wird normalerweise durch die &amp;lt;tt&amp;gt;componentData()&amp;lt;/tt&amp;gt; des Plugins zugegriffen, anstatt durch die &amp;lt;tt&amp;gt;{{class|KGlobal}}::mainComponent()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Und schliesslich gibt es noch ein globales Konfigurationsobjekt, &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt;, das von jeder Anwendung verwendet wird. Es enthält Informationen wie die Standard-Tatenkombinationen für verschiedene Aktionen. Es wird in das Konfigurationsobjekt &amp;quot;gemischt&amp;quot; wenn der &amp;lt;tt&amp;gt;KConfig::IncludeGlobals&amp;lt;/tt&amp;gt; Bitschalter dem {{class|KConfig}} Konstruktor übergeben wird, was standardmässig der Fall ist.&lt;br /&gt;
&lt;br /&gt;
=== Allgemein nützliche Methoden ===&lt;br /&gt;
&lt;br /&gt;
Um den momentanen Zustand des Konfigurationsobjektes zu speichern, rufen wir die &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt;-Methode auf. Diese Methode wird also aufgerufen, wenn ein Objekt zerstört wird. Falls keine Änderungen gemacht wurden, oder die Ressource weist sich als nicht beschreibbar aus (Wenn der Benutzer zum Beispiel nicht genug Rechte hat, um die Datei zu bearbeiten), dann wird keine Beschäftigung der Festplatte hervorgerufen. &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; verschmilzt Änderungen die gleichzeitig von anderen Prozessen ausgeführt werden - lokale Änderungen haben aber trotzdem Vorrang.&lt;br /&gt;
&lt;br /&gt;
Wenn wir sicher gehen wollen, dass wir die aktuellsten Werte von der Festplatte haben, dann rufen wir &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt; auf, welches &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; aufruft und dann die Daten von der Festplatte aktualisiert.&lt;br /&gt;
&lt;br /&gt;
Falls wir verhindern müssen, dass das Konfigurationsobjekt bereits gemachte Änderungen nicht auf die Festplatte speichert, müssen wir &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt; aufrufen. Ein besonderer Anwendungsfall ist es, die Konfiguration zum Festplatten-Zustand zurückzusetzen indem man &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt; gefolgt von &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt; aufruft.&lt;br /&gt;
&lt;br /&gt;
Alle Gruppen in einem Konfigurationsobjekt aufzurufen ist so einfach wie hier in diesem Code-Abschnitt &amp;lt;tt&amp;gt;groupList()&amp;lt;/tt&amp;gt; aufzurufen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::mainComponent().config();&lt;br /&gt;
&lt;br /&gt;
foreach ( const QString&amp;amp; group, config.groupList() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;next group:&amp;quot; &amp;lt;&amp;lt; group;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== KSharedConfig ==&lt;br /&gt;
&lt;br /&gt;
Die {{class|KSharedConfig}} Klasse ist eine Referenz-gezählte Version von {{class|KConfig}}. Darum stellt es eine Möglichkeit bereit, das selbe Konfigurationsobjekt von unterschiedlichen Orten zu referenzieren ohne zusätzlich die Objekte trennen zu müssen oder sich um die Synchronisation des Schreibvorgangs zu kümmern, selbst wenn das Konfigurationsobjekt von verschiedenen Code-Pfaden aktualisiert wird.&lt;br /&gt;
&lt;br /&gt;
Auf ein {{class|KSharedConfig}}-Objekt zuzugreifen ist so einfach wie das hier:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KSharedConfigPtr config = KSharedConfig::openConfig();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;openConfig()&amp;lt;/tt&amp;gt; nimmt die selben Parameter wie {{class|KConfig}}'s Konstruktoren, was es einem ermöglicht zu definieren, welche Konfigurationsdatei zu öffnen und Markierungen das Verschmelzen von nicht-&amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt;-Ressourcen zu kontrollieren.  &lt;br /&gt;
&lt;br /&gt;
Es wird grundsätzlich empfohlen {{class|KSharedConfig}} anstatt {{class|KConfig}} selbst zu benutzen, und auch das Objekt, das von {{class|KComponentData}} zurückgegeben wird ist in der Tat ein {{class|KSharedConfig}}-Objekt.&lt;br /&gt;
&lt;br /&gt;
== KConfigGroup ==&lt;br /&gt;
&lt;br /&gt;
Nun da wir ein Konfigurationsobjekt haben, ist der nächste Schritt es tatsächlich zu nutzen. Das erste, das wir tun müssen, ist zu bestimmen, auf welche Gruppe von Schlüssel-/Wertepaare wir in unserem Objekt zugreifen wollen. Wir tun das, indem wir ein KConfigGroup-Objekt erstellen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig config;&lt;br /&gt;
KConfigGroup generalGroup( &amp;amp;config, &amp;quot;General&amp;quot; );&lt;br /&gt;
KConfigGroup colorsGroup = config.group( &amp;quot;Colors&amp;quot; ); // ...oder so ähnlich...&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Man kann{{class|KConfigGroup}} {{class|KConfig}}- oder {{class|KSharedConfig}}-Objekte übergeben.&lt;br /&gt;
&lt;br /&gt;
Konfigurationsgruppen können ebenfalls verschachtelt werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfigGroup subGroup1( &amp;amp;generalGroup, &amp;quot;LessGeneral&amp;quot; );&lt;br /&gt;
KConfigGroup subGroup2 = colorsGroup.group( &amp;quot;Dialogs&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Reading Entries ==&lt;br /&gt;
&lt;br /&gt;
{{note (de)| Der Rest muss noch übersetzt werden}}&lt;br /&gt;
&lt;br /&gt;
With a {{class|KConfigGroup}} object in hand reading entries is now quite straight forward:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
QString accountName = generalGroup.readEntry( &amp;quot;Account&amp;quot;,&lt;br /&gt;
                                              QString() );&lt;br /&gt;
QColor color = colorsGroup.readEntry( &amp;quot;background&amp;quot;,&lt;br /&gt;
                                      Qt::white );&lt;br /&gt;
QStringList list = generalGroup.readEntry( &amp;quot;List&amp;quot;,&lt;br /&gt;
                                           QStringList() );&lt;br /&gt;
QString path = generalGroup.readPathEntry( &amp;quot;SaveTo&amp;quot;,&lt;br /&gt;
                                           defaultPath );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As can be seen from the above, you can mix reads from different {{class|KConfigGroup}} objects created on the same {{class|KConfig}} object. The read methods take the key, which is case sensitive, as the first argument and the default value as the second argument. This argument controls what kind of data, e.g. a color in line 3 above, is to be expected as well as the type of object returned. The returned object is wrapped in a {{qt|QVariant}} to make this magic happen.&lt;br /&gt;
&lt;br /&gt;
There are a couple of special read methods, including &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; which returns a file system path. It is vital that one uses &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; if it is a path as this enables such features as roaming profiles to work properly.&lt;br /&gt;
&lt;br /&gt;
If no such key currently exists in the configuration object, the default value is returned instead. If there is a localized (e.g. translated into another language) entry for the key that matches the current locale, that is returned.&lt;br /&gt;
&lt;br /&gt;
== Writing Entries ==&lt;br /&gt;
&lt;br /&gt;
Setting new values is similarly straightforward:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
generalGroup.writeEntry( &amp;quot;Account&amp;quot;, accountName );&lt;br /&gt;
generalGroup.writePathEntry( &amp;quot;SaveTo&amp;quot;, savePath );&lt;br /&gt;
colorGroup.writeEntry( &amp;quot;background&amp;quot;, color );&lt;br /&gt;
generalGroup.config()-&amp;gt;sync();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note the use of &amp;lt;tt&amp;gt;writePathEntry&amp;lt;/tt&amp;gt; and how the type of object we use, such as {{qt|QColor}} on line 3, dictates how the data is serialized. Additionally, once we are done writing entries, &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; must be called on the config object for it to be saved to disk. We can also simply wait for the object to be destroyed, which triggers an automatic &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; if necessary.&lt;br /&gt;
&lt;br /&gt;
== KDesktopFile: A Special Case ==&lt;br /&gt;
&lt;br /&gt;
When is a configuration file not a configuration file? When it is a [http://freedesktop.org/wiki/Standards_2fdesktop_2dentry_2dspec desktop file]. These files, which are essentially configuration files at their heart, are used  to describe entries for application menus, mimetypes, plugins and various services.&lt;br /&gt;
&lt;br /&gt;
When accessing a .desktop file, one should instead use the {{class|KDesktopFile}} class which, while a {{class|KConfig}} class offering all the capabilities described above, offers a set of methods designed to make accessing standard attributes of these files consistent and reliable.&lt;br /&gt;
&lt;br /&gt;
== Kiosk: Lockdown and User/Group Profiles ==&lt;br /&gt;
&lt;br /&gt;
KConfig provides a powerful set of lockdown and configuration definition capabilities, collectively known as &amp;quot;Kiosk&amp;quot;, that many system administrators and system integrators rely on. While most of this framework is provided transparently to the application, there is occassion when an application will want to check on the read/write status of a configuration object.&lt;br /&gt;
&lt;br /&gt;
Entries in configuration objects that are locked down using the kiosk facilities are said to be ''immutable''. An application can check for immutability of entire configuration objects, groups or keys as shown in this example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::config();&lt;br /&gt;
&lt;br /&gt;
if ( config-&amp;gt;isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;configuration object is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
KConfigGroup group(config, &amp;quot;General&amp;quot;);&lt;br /&gt;
if ( group.isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;group General is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if ( group.entryIsImmutable(&amp;quot;URL&amp;quot;) ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;URL entry in group General is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This can be useful in particular situations where an action should be taken when an item is immutable. For instance, the KDE panels will not offer configuration options to the user or allow them to otherwise change the order of applets and icons when the panel's configuration object is marked as immutable.&lt;br /&gt;
&lt;br /&gt;
== KConfig XT ==&lt;br /&gt;
&lt;br /&gt;
There is a way to make certain use cases of KConfig easier, faster and more reliable: KConfig XT. In particular, for main application or plugin configuration objects and when syncing configuration dialogs and other interfaces with these values, KConfig XT can help immensely. It also  simultaneously documents the configuration options available, which makes every sys admin and system integrator that uses KDE that much more happy.&lt;br /&gt;
&lt;br /&gt;
[[../Using_KConfig_XT|The next tutorial in the KConfig series covers what KConfig XT is and how to use it.]]&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials/KConfig_(de)</id>
		<title>Development/Tutorials/KConfig (de)</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials/KConfig_(de)"/>
				<updated>2008-01-02T17:00:04Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: /* KConfigGroup */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:I18n/Language Navigation Bar|Development/Tutorials/KConfig}}&lt;br /&gt;
&lt;br /&gt;
{{TutorialBrowser (de)|&lt;br /&gt;
&lt;br /&gt;
series=KConfig|&lt;br /&gt;
&lt;br /&gt;
name=Einführung in KConfig|&lt;br /&gt;
&lt;br /&gt;
pre=Keine|&lt;br /&gt;
&lt;br /&gt;
next=[[../Using_KConfig_XT (de)|Benutzen von KConfig XT]]|&lt;br /&gt;
&lt;br /&gt;
reading=Keine&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{improve (de)}}&lt;br /&gt;
&lt;br /&gt;
== Zusammenfassung ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dieser Artikel beschäftigt sich mir dem KDE Einstellungdaten-System, angefangen mit einer Übersicht über den grundlegenden Aufbau aus der Sicht eines Entwicklers. Es wirft ausserdem einen Blick auf jede der Klassen, die für die Entwicklung von Anwendungen relevant sind und fährt dann mit kiosk (Benutzer- und Gruppenprofile) Integration fort.&lt;br /&gt;
&lt;br /&gt;
== Grundlegender Aufbau ==&lt;br /&gt;
&lt;br /&gt;
KConfig ist ausgelegt um das Konzept vom eigentlichen Speichern und Auffinden von Konfigurationsdaten hinter eine Programmierschnittstelle zu abstrahieren die es ermöglicht, auf einfache Weise Informationen abzurufen und zu setzen. Wo oder in welcher Form Daten gespeichert werden ist für eine Anwendung die KConfig benutzt irrelevant.&lt;br /&gt;
&lt;br /&gt;
Das behält alle KDE Anwendungen konsistent in ihrer Art, Konfigurationen handzuhaben und nimmt einem Anwendungs-Entwickler die Arbeit so ein System von Grund auf neu zu schreiben, was ein sehr fehleranfälliger Prozess sein kann.&lt;br /&gt;
&lt;br /&gt;
Jedes KConfig Objekt verkörpert ein einziges Konfigurationsobjekt. Jedes Konfigurationsobjekt ist durch seinen einzigartigen Namen gekennzeichnet und kann von mehreren lokalen oder externen Daten oder Services gelesen werden. Jede Anwendung hat standardmässig ein zugehöriges Konfigurationsobjekt und es gibt auch ein globales Konfigurationsobjekt.&lt;br /&gt;
&lt;br /&gt;
Diese Konfigurationsobjekte sind nach einer zweistufigen Hierarchie getrennt: Gruppen und Schlüssel. Ein Konfigurationsobjekt kann eine beliebige Anzahl an Gruppen haben und jede Gruppe kann einen oder mehrere Schlüssel mit zugehörigen Werten haben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die gespeicherten Werte können aus beliebig vielen verschiedenen Datentypen bestehen. Sie werden gespeichert und abgerufen als das Objekt selbst. Zum Beispiel wird ein {{qt|QObject}}-Objekt direkt einem Konfigurationsobjekt übergeben, wenn es einen Farbwert speichert und wenn ein Farbwert abgerufen wird, wird ein {{qt|QObject}}-Objekt zurückgegeben.&lt;br /&gt;
&lt;br /&gt;
{{note (de)| deserialization  entgliedern? &amp;lt;br&amp;gt; &amp;lt;tt&amp;gt; &amp;quot;do not have to perform serialization and deserialization of objects themselves&amp;quot; &amp;lt;/tt&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Anwendungen selbst müssen darum normalerweise Objekte nicht selber gliedern und entgliedern.&lt;br /&gt;
&lt;br /&gt;
Applications themselves therefore generally do not have to perform serialization and deserialization of objects themselves.&lt;br /&gt;
&lt;br /&gt;
== Die KConfig Klasse ==&lt;br /&gt;
&lt;br /&gt;
Das {{class|KConfig}}-Objekt wird benutzt um ein bestehendes Konfigurationsobjekt anzusteuern. Es gibt eine Reihe von Möglichkeiten ein Konfigurationsobjekt zu erstellen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
// ein einfaches, altes lesen/schreiben Konfigurationsobjekt&lt;br /&gt;
KConfig config(&amp;quot;myapprc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// eine bestimmte Datei im Dateisystem&lt;br /&gt;
// currently must be an INI style file&lt;br /&gt;
KConfig fullPath(&amp;quot;/etc/kderc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// nicht mit globalen Werten verflochten&lt;br /&gt;
KConfig globalFree( &amp;quot;localsrc&amp;quot;, KConfig::NoGlobals );&lt;br /&gt;
&lt;br /&gt;
// nicht mit globalen Werten orde der $KDEDIRS Hierarchie verflochten&lt;br /&gt;
KConfig simpleConfig( &amp;quot;simplerc&amp;quot;, KConfig::SimpleConfig );&lt;br /&gt;
&lt;br /&gt;
// Komponenten-spezifische Konfiguration, in diesem Fall ein Plugin&lt;br /&gt;
KConfig pluginConfig( componentData(), &amp;quot;pluginrc&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
// Ausserhalb der normalen Konfigurations-Ressource&lt;br /&gt;
KConfig dataResource( &amp;quot;data&amp;quot;, &amp;quot;myapp/somefile&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{note (de)|wie soll &amp;quot;merged&amp;quot; in den folgenden Fällen übersetzt werden? &amp;lt;br&amp;gt; &amp;lt;tt&amp;gt;&amp;quot;verschmolzen&amp;quot; oder &amp;quot;verflochten&amp;quot;&amp;lt;/tt&amp;gt; &amp;lt;br&amp;gt; der Anwendung selber transparent&amp;quot; tönt auch nicht sehr gut}}&lt;br /&gt;
&lt;br /&gt;
Das Kconfig Objekt, das wir auf Zeile 2 erstellen ist ein gewöhnliches Konfigurationsobjekt. Wir können Werte aus ihm lesen, neue Einträge schreiben und nach verschiedenen Eigenschaften des Objekts fragen. Dieses Objekt wird aus der Konfigurations-Ressource geladen, wie es durch {{class|KStandardDirs}} bestimmt wird, das heisst, dass jede Instanz des &amp;lt;tt&amp;gt;myapprc&amp;lt;/tt&amp;gt;-Objekts in jedem der Ordner in der Konfigurations-Ressourcen-Hierarchie verschmolzen werden um die Werte zu erzeugen, die in diesem Objekt gesehen werden. So werden Systemweite und &lt;br /&gt;
pro-Benutzer/Gruppen Profile erstellt und unterstützt. Das alles geschieht der Anwendung selber transparent.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{tip| Für mehr Informationen, wie das Verschmelzen funktioniert, siehe diesen Artikel über die [[KDE System Administration/KDE_Filesystem_Hierarchy|KDE Dateisystem Hierarchie]].}}&lt;br /&gt;
&lt;br /&gt;
{{note (de)|Ist das so gemeint mit &amp;quot;expects an INI style file&amp;quot;&amp;lt;br&amp;gt; &amp;lt;tt&amp;gt; On line 6 we open a specific local file, this case /etc/kderc. This performs no merging of values and expects an INI style file.&amp;lt;/tt&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Auf Zeile 6 öffnen wir eine bestimmte Lokale Datei, in diesem Fall {{path|/etc/kderc}}. Das führt kein verschmelzen von Werten aus und erwartet eine Datei im INI Format.&lt;br /&gt;
&lt;br /&gt;
Zeile 9 erzeugt ein Konfigurationsobjekt, dass nicht mit dem globalen &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt;-Konfigurationsobjekt verflochten ist,  während das Konfigurationsobjekt auf Zeile 12 zusätzlich mit keinem der Dateien in der &amp;lt;tt&amp;gt;$KDEDIRS&amp;lt;/tt&amp;gt;-Hierarchie verflochten ist. Das kann die Leistung spürbar verbessern, falls man einfach nur Werte aus einer einfachen Konfuguration liest und globale Werte keine Rolle spielen.&lt;br /&gt;
&lt;br /&gt;
Zeile 15 erzeugt ein Konfigurationsobjekt unter Benutzung des {{class|KComponentData}}-Objekts das zu einem Plugin oder einer anderen Komponente gehört. Das Plugin kann verschiedene Ordner aufweisen, die in seinen {{class|KStandardDirs}} definiert sind und das ist eine Möglichkeit sich zu versichern, dass {{class|KConfig}} das respektiert.&lt;br /&gt;
&lt;br /&gt;
Und schliesslich auf Zeile 18 erzeugen wir ein Konfigurationsobjekt, das nicht in der &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt;-Ressource sondern in der &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt;-Ressource existiert. Man kann kann auf diese Weise jede Ressource verwenden, von denen {{class|KStandardDirs}} Kenntnis hat, auch solche die während der Laufzeit hinzugefügt werden.&lt;br /&gt;
&lt;br /&gt;
=== Spezielle Konfigurationsobjekte ===&lt;br /&gt;
&lt;br /&gt;
Jede Anwendung hat sein eigenes Konfigurationsobjekt das den Namen benutzt, der von {{class|KAboutData}} bereitgestellt wird mit angehängtem &amp;quot;rc&amp;quot;. Also hätte eine Anwendung mit dem Namen &amp;quot;myapp&amp;quot; das Standard-Konfigurationsobjekt &amp;quot;myapprc&amp;quot;. Dieses Konfigurationsobjekt kann auf diese Weise aufgerufen werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KComponentData&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
#include &amp;lt;KGlobal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    // beachten sie, dass dies eigentlich ein KSharedConfig ist&lt;br /&gt;
    // mehr über diese Klasse siehe weiter unten&lt;br /&gt;
    KConfig* config = KGlobal::config();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Auf das Standard-Konfigurationsobjekt für die Anwendung wird zugegriffen, wenn kein Name definiert wurde, als das {{class|KConfig}}-Objekt erzeugt wurde. Also könnten wir stattdessen auch das tun:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    KConfig config;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zusätzlich könnte jede Komponente sein eigenes Konfigurationsobjekt haben. Auf dieses wird normalerweise durch die &amp;lt;tt&amp;gt;componentData()&amp;lt;/tt&amp;gt; des Plugins zugegriffen, anstatt durch die &amp;lt;tt&amp;gt;{{class|KGlobal}}::mainComponent()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Und schliesslich gibt es noch ein globales Konfigurationsobjekt, &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt;, das von jeder Anwendung verwendet wird. Es enthält Informationen wie die Standard-Tatenkombinationen für verschiedene Aktionen. Es wird in das Konfigurationsobjekt &amp;quot;gemischt&amp;quot; wenn der &amp;lt;tt&amp;gt;KConfig::IncludeGlobals&amp;lt;/tt&amp;gt; Bitschalter dem {{class|KConfig}} Konstruktor übergeben wird, was standardmässig der Fall ist.&lt;br /&gt;
&lt;br /&gt;
=== Allgemein nützliche Methoden ===&lt;br /&gt;
&lt;br /&gt;
Um den momentanen Zustand des Konfigurationsobjektes zu speichern, rufen wir die &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt;-Methode auf. Diese Methode wird also aufgerufen, wenn ein Objekt zerstört wird. Falls keine Änderungen gemacht wurden, oder die Ressource weist sich als nicht beschreibbar aus (Wenn der Benutzer zum Beispiel nicht genug Rechte hat, um die Datei zu bearbeiten), dann wird keine Beschäftigung der Festplatte hervorgerufen. &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; verschmilzt Änderungen die gleichzeitig von anderen Prozessen ausgeführt werden - lokale Änderungen haben aber trotzdem Vorrang.&lt;br /&gt;
&lt;br /&gt;
Wenn wir sicher gehen wollen, dass wir die aktuellsten Werte von der Festplatte haben, dann rufen wir &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt; auf, welches &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; aufruft und dann die Daten von der Festplatte aktualisiert.&lt;br /&gt;
&lt;br /&gt;
Falls wir verhindern müssen, dass das Konfigurationsobjekt bereits gemachte Änderungen nicht auf die Festplatte speichert, müssen wir &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt; aufrufen. Ein besonderer Anwendungsfall ist es, die Konfiguration zum Festplatten-Zustand zurückzusetzen indem man &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt; gefolgt von &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt; aufruft.&lt;br /&gt;
&lt;br /&gt;
Alle Gruppen in einem Konfigurationsobjekt aufzurufen ist so einfach wie hier in diesem Code-Abschnitt &amp;lt;tt&amp;gt;groupList()&amp;lt;/tt&amp;gt; aufzurufen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::mainComponent().config();&lt;br /&gt;
&lt;br /&gt;
foreach ( const QString&amp;amp; group, config.groupList() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;next group:&amp;quot; &amp;lt;&amp;lt; group;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== KSharedConfig ==&lt;br /&gt;
&lt;br /&gt;
Die {{class|KSharedConfig}} Klasse ist eine Referenz-gezählte Version von {{class|KConfig}}. Darum stellt es eine Möglichkeit bereit, das selbe Konfigurationsobjekt von unterschiedlichen Orten zu referenzieren ohne zusätzlich die Objekte trennen zu müssen oder sich um die Synchronisation des Schreibvorgangs zu kümmern, selbst wenn das Konfigurationsobjekt von verschiedenen Code-Pfaden aktualisiert wird.&lt;br /&gt;
&lt;br /&gt;
Auf ein {{class|KSharedConfig}}-Objekt zuzugreifen ist so einfach wie das hier:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KSharedConfigPtr config = KSharedConfig::openConfig();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;openConfig()&amp;lt;/tt&amp;gt; nimmt die selben Parameter wie {{class|KConfig}}'s Konstruktoren, was es einem ermöglicht zu definieren, welche Konfigurationsdatei zu öffnen und Markierungen das Verschmelzen von nicht-&amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt;-Ressourcen zu kontrollieren.  &lt;br /&gt;
&lt;br /&gt;
Es wird grundsätzlich empfohlen {{class|KSharedConfig}} anstatt {{class|KConfig}} selbst zu benutzen, und auch das Objekt, das von {{class|KComponentData}} zurückgegeben wird ist in der Tat ein {{class|KSharedConfig}}-Objekt.&lt;br /&gt;
&lt;br /&gt;
== KConfigGroup ==&lt;br /&gt;
&lt;br /&gt;
Nun da wir ein Konfigurationsobjekt haben, ist der nächste Schritt es tatsächlich zu nutzen. Das erste, das wir tun müssen, ist zu bestimmen, auf welche Gruppe von Schlüssel-/Wertepaare wir in unserem Objekt zugreifen wollen. Wir tun das, indem wir ein KConfigGroup-Objekt erstellen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig config;&lt;br /&gt;
KConfigGroup generalGroup( &amp;amp;config, &amp;quot;General&amp;quot; );&lt;br /&gt;
KConfigGroup colorsGroup = config.group( &amp;quot;Colors&amp;quot; ); // ...oder so ähnlich...&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Man kann{{class|KConfigGroup}} {{class|KConfig}}- oder {{class|KSharedConfig}}-Objekte übergeben.&lt;br /&gt;
&lt;br /&gt;
Konfigurationsgruppen können ebenfalls verschachtelt werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfigGroup subGroup1( &amp;amp;generalGroup, &amp;quot;LessGeneral&amp;quot; );&lt;br /&gt;
KConfigGroup subGroup2 = colorsGroup.group( &amp;quot;Dialogs&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Reading Entries ==&lt;br /&gt;
&lt;br /&gt;
With a {{class|KConfigGroup}} object in hand reading entries is now quite straight forward:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
QString accountName = generalGroup.readEntry( &amp;quot;Account&amp;quot;,&lt;br /&gt;
                                              QString() );&lt;br /&gt;
QColor color = colorsGroup.readEntry( &amp;quot;background&amp;quot;,&lt;br /&gt;
                                      Qt::white );&lt;br /&gt;
QStringList list = generalGroup.readEntry( &amp;quot;List&amp;quot;,&lt;br /&gt;
                                           QStringList() );&lt;br /&gt;
QString path = generalGroup.readPathEntry( &amp;quot;SaveTo&amp;quot;,&lt;br /&gt;
                                           defaultPath );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As can be seen from the above, you can mix reads from different {{class|KConfigGroup}} objects created on the same {{class|KConfig}} object. The read methods take the key, which is case sensitive, as the first argument and the default value as the second argument. This argument controls what kind of data, e.g. a color in line 3 above, is to be expected as well as the type of object returned. The returned object is wrapped in a {{qt|QVariant}} to make this magic happen.&lt;br /&gt;
&lt;br /&gt;
There are a couple of special read methods, including &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; which returns a file system path. It is vital that one uses &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; if it is a path as this enables such features as roaming profiles to work properly.&lt;br /&gt;
&lt;br /&gt;
If no such key currently exists in the configuration object, the default value is returned instead. If there is a localized (e.g. translated into another language) entry for the key that matches the current locale, that is returned.&lt;br /&gt;
&lt;br /&gt;
== Writing Entries ==&lt;br /&gt;
&lt;br /&gt;
Setting new values is similarly straightforward:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
generalGroup.writeEntry( &amp;quot;Account&amp;quot;, accountName );&lt;br /&gt;
generalGroup.writePathEntry( &amp;quot;SaveTo&amp;quot;, savePath );&lt;br /&gt;
colorGroup.writeEntry( &amp;quot;background&amp;quot;, color );&lt;br /&gt;
generalGroup.config()-&amp;gt;sync();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note the use of &amp;lt;tt&amp;gt;writePathEntry&amp;lt;/tt&amp;gt; and how the type of object we use, such as {{qt|QColor}} on line 3, dictates how the data is serialized. Additionally, once we are done writing entries, &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; must be called on the config object for it to be saved to disk. We can also simply wait for the object to be destroyed, which triggers an automatic &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; if necessary.&lt;br /&gt;
&lt;br /&gt;
== KDesktopFile: A Special Case ==&lt;br /&gt;
&lt;br /&gt;
When is a configuration file not a configuration file? When it is a [http://freedesktop.org/wiki/Standards_2fdesktop_2dentry_2dspec desktop file]. These files, which are essentially configuration files at their heart, are used  to describe entries for application menus, mimetypes, plugins and various services.&lt;br /&gt;
&lt;br /&gt;
When accessing a .desktop file, one should instead use the {{class|KDesktopFile}} class which, while a {{class|KConfig}} class offering all the capabilities described above, offers a set of methods designed to make accessing standard attributes of these files consistent and reliable.&lt;br /&gt;
&lt;br /&gt;
== Kiosk: Lockdown and User/Group Profiles ==&lt;br /&gt;
&lt;br /&gt;
KConfig provides a powerful set of lockdown and configuration definition capabilities, collectively known as &amp;quot;Kiosk&amp;quot;, that many system administrators and system integrators rely on. While most of this framework is provided transparently to the application, there is occassion when an application will want to check on the read/write status of a configuration object.&lt;br /&gt;
&lt;br /&gt;
Entries in configuration objects that are locked down using the kiosk facilities are said to be ''immutable''. An application can check for immutability of entire configuration objects, groups or keys as shown in this example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::config();&lt;br /&gt;
&lt;br /&gt;
if ( config-&amp;gt;isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;configuration object is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
KConfigGroup group(config, &amp;quot;General&amp;quot;);&lt;br /&gt;
if ( group.isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;group General is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if ( group.entryIsImmutable(&amp;quot;URL&amp;quot;) ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;URL entry in group General is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This can be useful in particular situations where an action should be taken when an item is immutable. For instance, the KDE panels will not offer configuration options to the user or allow them to otherwise change the order of applets and icons when the panel's configuration object is marked as immutable.&lt;br /&gt;
&lt;br /&gt;
== KConfig XT ==&lt;br /&gt;
&lt;br /&gt;
There is a way to make certain use cases of KConfig easier, faster and more reliable: KConfig XT. In particular, for main application or plugin configuration objects and when syncing configuration dialogs and other interfaces with these values, KConfig XT can help immensely. It also  simultaneously documents the configuration options available, which makes every sys admin and system integrator that uses KDE that much more happy.&lt;br /&gt;
&lt;br /&gt;
[[../Using_KConfig_XT|The next tutorial in the KConfig series covers what KConfig XT is and how to use it.]]&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials/KConfig_(de)</id>
		<title>Development/Tutorials/KConfig (de)</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials/KConfig_(de)"/>
				<updated>2008-01-02T16:53:54Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: /* KSharedConfig */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:I18n/Language Navigation Bar|Development/Tutorials/KConfig}}&lt;br /&gt;
&lt;br /&gt;
{{TutorialBrowser (de)|&lt;br /&gt;
&lt;br /&gt;
series=KConfig|&lt;br /&gt;
&lt;br /&gt;
name=Einführung in KConfig|&lt;br /&gt;
&lt;br /&gt;
pre=Keine|&lt;br /&gt;
&lt;br /&gt;
next=[[../Using_KConfig_XT (de)|Benutzen von KConfig XT]]|&lt;br /&gt;
&lt;br /&gt;
reading=Keine&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{improve (de)}}&lt;br /&gt;
&lt;br /&gt;
== Zusammenfassung ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dieser Artikel beschäftigt sich mir dem KDE Einstellungdaten-System, angefangen mit einer Übersicht über den grundlegenden Aufbau aus der Sicht eines Entwicklers. Es wirft ausserdem einen Blick auf jede der Klassen, die für die Entwicklung von Anwendungen relevant sind und fährt dann mit kiosk (Benutzer- und Gruppenprofile) Integration fort.&lt;br /&gt;
&lt;br /&gt;
== Grundlegender Aufbau ==&lt;br /&gt;
&lt;br /&gt;
KConfig ist ausgelegt um das Konzept vom eigentlichen Speichern und Auffinden von Konfigurationsdaten hinter eine Programmierschnittstelle zu abstrahieren die es ermöglicht, auf einfache Weise Informationen abzurufen und zu setzen. Wo oder in welcher Form Daten gespeichert werden ist für eine Anwendung die KConfig benutzt irrelevant.&lt;br /&gt;
&lt;br /&gt;
Das behält alle KDE Anwendungen konsistent in ihrer Art, Konfigurationen handzuhaben und nimmt einem Anwendungs-Entwickler die Arbeit so ein System von Grund auf neu zu schreiben, was ein sehr fehleranfälliger Prozess sein kann.&lt;br /&gt;
&lt;br /&gt;
Jedes KConfig Objekt verkörpert ein einziges Konfigurationsobjekt. Jedes Konfigurationsobjekt ist durch seinen einzigartigen Namen gekennzeichnet und kann von mehreren lokalen oder externen Daten oder Services gelesen werden. Jede Anwendung hat standardmässig ein zugehöriges Konfigurationsobjekt und es gibt auch ein globales Konfigurationsobjekt.&lt;br /&gt;
&lt;br /&gt;
Diese Konfigurationsobjekte sind nach einer zweistufigen Hierarchie getrennt: Gruppen und Schlüssel. Ein Konfigurationsobjekt kann eine beliebige Anzahl an Gruppen haben und jede Gruppe kann einen oder mehrere Schlüssel mit zugehörigen Werten haben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die gespeicherten Werte können aus beliebig vielen verschiedenen Datentypen bestehen. Sie werden gespeichert und abgerufen als das Objekt selbst. Zum Beispiel wird ein {{qt|QObject}}-Objekt direkt einem Konfigurationsobjekt übergeben, wenn es einen Farbwert speichert und wenn ein Farbwert abgerufen wird, wird ein {{qt|QObject}}-Objekt zurückgegeben.&lt;br /&gt;
&lt;br /&gt;
{{note (de)| deserialization  entgliedern? &amp;lt;br&amp;gt; &amp;lt;tt&amp;gt; &amp;quot;do not have to perform serialization and deserialization of objects themselves&amp;quot; &amp;lt;/tt&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Anwendungen selbst müssen darum normalerweise Objekte nicht selber gliedern und entgliedern.&lt;br /&gt;
&lt;br /&gt;
Applications themselves therefore generally do not have to perform serialization and deserialization of objects themselves.&lt;br /&gt;
&lt;br /&gt;
== Die KConfig Klasse ==&lt;br /&gt;
&lt;br /&gt;
Das {{class|KConfig}}-Objekt wird benutzt um ein bestehendes Konfigurationsobjekt anzusteuern. Es gibt eine Reihe von Möglichkeiten ein Konfigurationsobjekt zu erstellen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
// ein einfaches, altes lesen/schreiben Konfigurationsobjekt&lt;br /&gt;
KConfig config(&amp;quot;myapprc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// eine bestimmte Datei im Dateisystem&lt;br /&gt;
// currently must be an INI style file&lt;br /&gt;
KConfig fullPath(&amp;quot;/etc/kderc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// nicht mit globalen Werten verflochten&lt;br /&gt;
KConfig globalFree( &amp;quot;localsrc&amp;quot;, KConfig::NoGlobals );&lt;br /&gt;
&lt;br /&gt;
// nicht mit globalen Werten orde der $KDEDIRS Hierarchie verflochten&lt;br /&gt;
KConfig simpleConfig( &amp;quot;simplerc&amp;quot;, KConfig::SimpleConfig );&lt;br /&gt;
&lt;br /&gt;
// Komponenten-spezifische Konfiguration, in diesem Fall ein Plugin&lt;br /&gt;
KConfig pluginConfig( componentData(), &amp;quot;pluginrc&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
// Ausserhalb der normalen Konfigurations-Ressource&lt;br /&gt;
KConfig dataResource( &amp;quot;data&amp;quot;, &amp;quot;myapp/somefile&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{note (de)|wie soll &amp;quot;merged&amp;quot; in den folgenden Fällen übersetzt werden? &amp;lt;br&amp;gt; &amp;lt;tt&amp;gt;&amp;quot;verschmolzen&amp;quot; oder &amp;quot;verflochten&amp;quot;&amp;lt;/tt&amp;gt; &amp;lt;br&amp;gt; der Anwendung selber transparent&amp;quot; tönt auch nicht sehr gut}}&lt;br /&gt;
&lt;br /&gt;
Das Kconfig Objekt, das wir auf Zeile 2 erstellen ist ein gewöhnliches Konfigurationsobjekt. Wir können Werte aus ihm lesen, neue Einträge schreiben und nach verschiedenen Eigenschaften des Objekts fragen. Dieses Objekt wird aus der Konfigurations-Ressource geladen, wie es durch {{class|KStandardDirs}} bestimmt wird, das heisst, dass jede Instanz des &amp;lt;tt&amp;gt;myapprc&amp;lt;/tt&amp;gt;-Objekts in jedem der Ordner in der Konfigurations-Ressourcen-Hierarchie verschmolzen werden um die Werte zu erzeugen, die in diesem Objekt gesehen werden. So werden Systemweite und &lt;br /&gt;
pro-Benutzer/Gruppen Profile erstellt und unterstützt. Das alles geschieht der Anwendung selber transparent.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{tip| Für mehr Informationen, wie das Verschmelzen funktioniert, siehe diesen Artikel über die [[KDE System Administration/KDE_Filesystem_Hierarchy|KDE Dateisystem Hierarchie]].}}&lt;br /&gt;
&lt;br /&gt;
{{note (de)|Ist das so gemeint mit &amp;quot;expects an INI style file&amp;quot;&amp;lt;br&amp;gt; &amp;lt;tt&amp;gt; On line 6 we open a specific local file, this case /etc/kderc. This performs no merging of values and expects an INI style file.&amp;lt;/tt&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Auf Zeile 6 öffnen wir eine bestimmte Lokale Datei, in diesem Fall {{path|/etc/kderc}}. Das führt kein verschmelzen von Werten aus und erwartet eine Datei im INI Format.&lt;br /&gt;
&lt;br /&gt;
Zeile 9 erzeugt ein Konfigurationsobjekt, dass nicht mit dem globalen &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt;-Konfigurationsobjekt verflochten ist,  während das Konfigurationsobjekt auf Zeile 12 zusätzlich mit keinem der Dateien in der &amp;lt;tt&amp;gt;$KDEDIRS&amp;lt;/tt&amp;gt;-Hierarchie verflochten ist. Das kann die Leistung spürbar verbessern, falls man einfach nur Werte aus einer einfachen Konfuguration liest und globale Werte keine Rolle spielen.&lt;br /&gt;
&lt;br /&gt;
Zeile 15 erzeugt ein Konfigurationsobjekt unter Benutzung des {{class|KComponentData}}-Objekts das zu einem Plugin oder einer anderen Komponente gehört. Das Plugin kann verschiedene Ordner aufweisen, die in seinen {{class|KStandardDirs}} definiert sind und das ist eine Möglichkeit sich zu versichern, dass {{class|KConfig}} das respektiert.&lt;br /&gt;
&lt;br /&gt;
Und schliesslich auf Zeile 18 erzeugen wir ein Konfigurationsobjekt, das nicht in der &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt;-Ressource sondern in der &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt;-Ressource existiert. Man kann kann auf diese Weise jede Ressource verwenden, von denen {{class|KStandardDirs}} Kenntnis hat, auch solche die während der Laufzeit hinzugefügt werden.&lt;br /&gt;
&lt;br /&gt;
=== Spezielle Konfigurationsobjekte ===&lt;br /&gt;
&lt;br /&gt;
Jede Anwendung hat sein eigenes Konfigurationsobjekt das den Namen benutzt, der von {{class|KAboutData}} bereitgestellt wird mit angehängtem &amp;quot;rc&amp;quot;. Also hätte eine Anwendung mit dem Namen &amp;quot;myapp&amp;quot; das Standard-Konfigurationsobjekt &amp;quot;myapprc&amp;quot;. Dieses Konfigurationsobjekt kann auf diese Weise aufgerufen werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KComponentData&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
#include &amp;lt;KGlobal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    // beachten sie, dass dies eigentlich ein KSharedConfig ist&lt;br /&gt;
    // mehr über diese Klasse siehe weiter unten&lt;br /&gt;
    KConfig* config = KGlobal::config();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Auf das Standard-Konfigurationsobjekt für die Anwendung wird zugegriffen, wenn kein Name definiert wurde, als das {{class|KConfig}}-Objekt erzeugt wurde. Also könnten wir stattdessen auch das tun:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    KConfig config;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zusätzlich könnte jede Komponente sein eigenes Konfigurationsobjekt haben. Auf dieses wird normalerweise durch die &amp;lt;tt&amp;gt;componentData()&amp;lt;/tt&amp;gt; des Plugins zugegriffen, anstatt durch die &amp;lt;tt&amp;gt;{{class|KGlobal}}::mainComponent()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Und schliesslich gibt es noch ein globales Konfigurationsobjekt, &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt;, das von jeder Anwendung verwendet wird. Es enthält Informationen wie die Standard-Tatenkombinationen für verschiedene Aktionen. Es wird in das Konfigurationsobjekt &amp;quot;gemischt&amp;quot; wenn der &amp;lt;tt&amp;gt;KConfig::IncludeGlobals&amp;lt;/tt&amp;gt; Bitschalter dem {{class|KConfig}} Konstruktor übergeben wird, was standardmässig der Fall ist.&lt;br /&gt;
&lt;br /&gt;
=== Allgemein nützliche Methoden ===&lt;br /&gt;
&lt;br /&gt;
Um den momentanen Zustand des Konfigurationsobjektes zu speichern, rufen wir die &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt;-Methode auf. Diese Methode wird also aufgerufen, wenn ein Objekt zerstört wird. Falls keine Änderungen gemacht wurden, oder die Ressource weist sich als nicht beschreibbar aus (Wenn der Benutzer zum Beispiel nicht genug Rechte hat, um die Datei zu bearbeiten), dann wird keine Beschäftigung der Festplatte hervorgerufen. &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; verschmilzt Änderungen die gleichzeitig von anderen Prozessen ausgeführt werden - lokale Änderungen haben aber trotzdem Vorrang.&lt;br /&gt;
&lt;br /&gt;
Wenn wir sicher gehen wollen, dass wir die aktuellsten Werte von der Festplatte haben, dann rufen wir &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt; auf, welches &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; aufruft und dann die Daten von der Festplatte aktualisiert.&lt;br /&gt;
&lt;br /&gt;
Falls wir verhindern müssen, dass das Konfigurationsobjekt bereits gemachte Änderungen nicht auf die Festplatte speichert, müssen wir &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt; aufrufen. Ein besonderer Anwendungsfall ist es, die Konfiguration zum Festplatten-Zustand zurückzusetzen indem man &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt; gefolgt von &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt; aufruft.&lt;br /&gt;
&lt;br /&gt;
Alle Gruppen in einem Konfigurationsobjekt aufzurufen ist so einfach wie hier in diesem Code-Abschnitt &amp;lt;tt&amp;gt;groupList()&amp;lt;/tt&amp;gt; aufzurufen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::mainComponent().config();&lt;br /&gt;
&lt;br /&gt;
foreach ( const QString&amp;amp; group, config.groupList() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;next group:&amp;quot; &amp;lt;&amp;lt; group;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== KSharedConfig ==&lt;br /&gt;
&lt;br /&gt;
Die {{class|KSharedConfig}} Klasse ist eine Referenz-gezählte Version von {{class|KConfig}}. Darum stellt es eine Möglichkeit bereit, das selbe Konfigurationsobjekt von unterschiedlichen Orten zu referenzieren ohne zusätzlich die Objekte trennen zu müssen oder sich um die Synchronisation des Schreibvorgangs zu kümmern, selbst wenn das Konfigurationsobjekt von verschiedenen Code-Pfaden aktualisiert wird.&lt;br /&gt;
&lt;br /&gt;
Auf ein {{class|KSharedConfig}}-Objekt zuzugreifen ist so einfach wie das hier:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KSharedConfigPtr config = KSharedConfig::openConfig();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;openConfig()&amp;lt;/tt&amp;gt; nimmt die selben Parameter wie {{class|KConfig}}'s Konstruktoren, was es einem ermöglicht zu definieren, welche Konfigurationsdatei zu öffnen und Markierungen das Verschmelzen von nicht-&amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt;-Ressourcen zu kontrollieren.  &lt;br /&gt;
&lt;br /&gt;
Es wird grundsätzlich empfohlen {{class|KSharedConfig}} anstatt {{class|KConfig}} selbst zu benutzen, und auch das Objekt, das von {{class|KComponentData}} zurückgegeben wird ist in der Tat ein {{class|KSharedConfig}}-Objekt.&lt;br /&gt;
&lt;br /&gt;
== KConfigGroup ==&lt;br /&gt;
&lt;br /&gt;
Now that we have a configuration object, the next step is to actually use it. The first thing we must do is to define which group of key/value pairs we wish to access in the object. We do this by creating a KConfigGroup object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig config;&lt;br /&gt;
KConfigGroup generalGroup( &amp;amp;config, &amp;quot;General&amp;quot; );&lt;br /&gt;
KConfigGroup colorsGroup = config.group( &amp;quot;Colors&amp;quot; ); // ... or a bit differently ...&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can pass {{class|KConfig}} or {{class|KSharedConfig}} objects to {{class|KConfigGroup}}.&lt;br /&gt;
&lt;br /&gt;
Config groups can be nested as well:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfigGroup subGroup1( &amp;amp;generalGroup, &amp;quot;LessGeneral&amp;quot; );&lt;br /&gt;
KConfigGroup subGroup2 = colorsGroup.group( &amp;quot;Dialogs&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Reading Entries ==&lt;br /&gt;
&lt;br /&gt;
With a {{class|KConfigGroup}} object in hand reading entries is now quite straight forward:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
QString accountName = generalGroup.readEntry( &amp;quot;Account&amp;quot;,&lt;br /&gt;
                                              QString() );&lt;br /&gt;
QColor color = colorsGroup.readEntry( &amp;quot;background&amp;quot;,&lt;br /&gt;
                                      Qt::white );&lt;br /&gt;
QStringList list = generalGroup.readEntry( &amp;quot;List&amp;quot;,&lt;br /&gt;
                                           QStringList() );&lt;br /&gt;
QString path = generalGroup.readPathEntry( &amp;quot;SaveTo&amp;quot;,&lt;br /&gt;
                                           defaultPath );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As can be seen from the above, you can mix reads from different {{class|KConfigGroup}} objects created on the same {{class|KConfig}} object. The read methods take the key, which is case sensitive, as the first argument and the default value as the second argument. This argument controls what kind of data, e.g. a color in line 3 above, is to be expected as well as the type of object returned. The returned object is wrapped in a {{qt|QVariant}} to make this magic happen.&lt;br /&gt;
&lt;br /&gt;
There are a couple of special read methods, including &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; which returns a file system path. It is vital that one uses &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; if it is a path as this enables such features as roaming profiles to work properly.&lt;br /&gt;
&lt;br /&gt;
If no such key currently exists in the configuration object, the default value is returned instead. If there is a localized (e.g. translated into another language) entry for the key that matches the current locale, that is returned.&lt;br /&gt;
&lt;br /&gt;
== Writing Entries ==&lt;br /&gt;
&lt;br /&gt;
Setting new values is similarly straightforward:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
generalGroup.writeEntry( &amp;quot;Account&amp;quot;, accountName );&lt;br /&gt;
generalGroup.writePathEntry( &amp;quot;SaveTo&amp;quot;, savePath );&lt;br /&gt;
colorGroup.writeEntry( &amp;quot;background&amp;quot;, color );&lt;br /&gt;
generalGroup.config()-&amp;gt;sync();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note the use of &amp;lt;tt&amp;gt;writePathEntry&amp;lt;/tt&amp;gt; and how the type of object we use, such as {{qt|QColor}} on line 3, dictates how the data is serialized. Additionally, once we are done writing entries, &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; must be called on the config object for it to be saved to disk. We can also simply wait for the object to be destroyed, which triggers an automatic &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; if necessary.&lt;br /&gt;
&lt;br /&gt;
== KDesktopFile: A Special Case ==&lt;br /&gt;
&lt;br /&gt;
When is a configuration file not a configuration file? When it is a [http://freedesktop.org/wiki/Standards_2fdesktop_2dentry_2dspec desktop file]. These files, which are essentially configuration files at their heart, are used  to describe entries for application menus, mimetypes, plugins and various services.&lt;br /&gt;
&lt;br /&gt;
When accessing a .desktop file, one should instead use the {{class|KDesktopFile}} class which, while a {{class|KConfig}} class offering all the capabilities described above, offers a set of methods designed to make accessing standard attributes of these files consistent and reliable.&lt;br /&gt;
&lt;br /&gt;
== Kiosk: Lockdown and User/Group Profiles ==&lt;br /&gt;
&lt;br /&gt;
KConfig provides a powerful set of lockdown and configuration definition capabilities, collectively known as &amp;quot;Kiosk&amp;quot;, that many system administrators and system integrators rely on. While most of this framework is provided transparently to the application, there is occassion when an application will want to check on the read/write status of a configuration object.&lt;br /&gt;
&lt;br /&gt;
Entries in configuration objects that are locked down using the kiosk facilities are said to be ''immutable''. An application can check for immutability of entire configuration objects, groups or keys as shown in this example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::config();&lt;br /&gt;
&lt;br /&gt;
if ( config-&amp;gt;isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;configuration object is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
KConfigGroup group(config, &amp;quot;General&amp;quot;);&lt;br /&gt;
if ( group.isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;group General is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if ( group.entryIsImmutable(&amp;quot;URL&amp;quot;) ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;URL entry in group General is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This can be useful in particular situations where an action should be taken when an item is immutable. For instance, the KDE panels will not offer configuration options to the user or allow them to otherwise change the order of applets and icons when the panel's configuration object is marked as immutable.&lt;br /&gt;
&lt;br /&gt;
== KConfig XT ==&lt;br /&gt;
&lt;br /&gt;
There is a way to make certain use cases of KConfig easier, faster and more reliable: KConfig XT. In particular, for main application or plugin configuration objects and when syncing configuration dialogs and other interfaces with these values, KConfig XT can help immensely. It also  simultaneously documents the configuration options available, which makes every sys admin and system integrator that uses KDE that much more happy.&lt;br /&gt;
&lt;br /&gt;
[[../Using_KConfig_XT|The next tutorial in the KConfig series covers what KConfig XT is and how to use it.]]&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials/KConfig_(de)</id>
		<title>Development/Tutorials/KConfig (de)</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials/KConfig_(de)"/>
				<updated>2008-01-02T16:34:54Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: /* Allgemein nützliche Methoden */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:I18n/Language Navigation Bar|Development/Tutorials/KConfig}}&lt;br /&gt;
&lt;br /&gt;
{{TutorialBrowser (de)|&lt;br /&gt;
&lt;br /&gt;
series=KConfig|&lt;br /&gt;
&lt;br /&gt;
name=Einführung in KConfig|&lt;br /&gt;
&lt;br /&gt;
pre=Keine|&lt;br /&gt;
&lt;br /&gt;
next=[[../Using_KConfig_XT (de)|Benutzen von KConfig XT]]|&lt;br /&gt;
&lt;br /&gt;
reading=Keine&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{improve (de)}}&lt;br /&gt;
&lt;br /&gt;
== Zusammenfassung ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dieser Artikel beschäftigt sich mir dem KDE Einstellungdaten-System, angefangen mit einer Übersicht über den grundlegenden Aufbau aus der Sicht eines Entwicklers. Es wirft ausserdem einen Blick auf jede der Klassen, die für die Entwicklung von Anwendungen relevant sind und fährt dann mit kiosk (Benutzer- und Gruppenprofile) Integration fort.&lt;br /&gt;
&lt;br /&gt;
== Grundlegender Aufbau ==&lt;br /&gt;
&lt;br /&gt;
KConfig ist ausgelegt um das Konzept vom eigentlichen Speichern und Auffinden von Konfigurationsdaten hinter eine Programmierschnittstelle zu abstrahieren die es ermöglicht, auf einfache Weise Informationen abzurufen und zu setzen. Wo oder in welcher Form Daten gespeichert werden ist für eine Anwendung die KConfig benutzt irrelevant.&lt;br /&gt;
&lt;br /&gt;
Das behält alle KDE Anwendungen konsistent in ihrer Art, Konfigurationen handzuhaben und nimmt einem Anwendungs-Entwickler die Arbeit so ein System von Grund auf neu zu schreiben, was ein sehr fehleranfälliger Prozess sein kann.&lt;br /&gt;
&lt;br /&gt;
Jedes KConfig Objekt verkörpert ein einziges Konfigurationsobjekt. Jedes Konfigurationsobjekt ist durch seinen einzigartigen Namen gekennzeichnet und kann von mehreren lokalen oder externen Daten oder Services gelesen werden. Jede Anwendung hat standardmässig ein zugehöriges Konfigurationsobjekt und es gibt auch ein globales Konfigurationsobjekt.&lt;br /&gt;
&lt;br /&gt;
Diese Konfigurationsobjekte sind nach einer zweistufigen Hierarchie getrennt: Gruppen und Schlüssel. Ein Konfigurationsobjekt kann eine beliebige Anzahl an Gruppen haben und jede Gruppe kann einen oder mehrere Schlüssel mit zugehörigen Werten haben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die gespeicherten Werte können aus beliebig vielen verschiedenen Datentypen bestehen. Sie werden gespeichert und abgerufen als das Objekt selbst. Zum Beispiel wird ein {{qt|QObject}}-Objekt direkt einem Konfigurationsobjekt übergeben, wenn es einen Farbwert speichert und wenn ein Farbwert abgerufen wird, wird ein {{qt|QObject}}-Objekt zurückgegeben.&lt;br /&gt;
&lt;br /&gt;
{{note (de)| deserialization  entgliedern? &amp;lt;br&amp;gt; &amp;lt;tt&amp;gt; &amp;quot;do not have to perform serialization and deserialization of objects themselves&amp;quot; &amp;lt;/tt&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Anwendungen selbst müssen darum normalerweise Objekte nicht selber gliedern und entgliedern.&lt;br /&gt;
&lt;br /&gt;
Applications themselves therefore generally do not have to perform serialization and deserialization of objects themselves.&lt;br /&gt;
&lt;br /&gt;
== Die KConfig Klasse ==&lt;br /&gt;
&lt;br /&gt;
Das {{class|KConfig}}-Objekt wird benutzt um ein bestehendes Konfigurationsobjekt anzusteuern. Es gibt eine Reihe von Möglichkeiten ein Konfigurationsobjekt zu erstellen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
// ein einfaches, altes lesen/schreiben Konfigurationsobjekt&lt;br /&gt;
KConfig config(&amp;quot;myapprc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// eine bestimmte Datei im Dateisystem&lt;br /&gt;
// currently must be an INI style file&lt;br /&gt;
KConfig fullPath(&amp;quot;/etc/kderc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// nicht mit globalen Werten verflochten&lt;br /&gt;
KConfig globalFree( &amp;quot;localsrc&amp;quot;, KConfig::NoGlobals );&lt;br /&gt;
&lt;br /&gt;
// nicht mit globalen Werten orde der $KDEDIRS Hierarchie verflochten&lt;br /&gt;
KConfig simpleConfig( &amp;quot;simplerc&amp;quot;, KConfig::SimpleConfig );&lt;br /&gt;
&lt;br /&gt;
// Komponenten-spezifische Konfiguration, in diesem Fall ein Plugin&lt;br /&gt;
KConfig pluginConfig( componentData(), &amp;quot;pluginrc&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
// Ausserhalb der normalen Konfigurations-Ressource&lt;br /&gt;
KConfig dataResource( &amp;quot;data&amp;quot;, &amp;quot;myapp/somefile&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{note (de)|wie soll &amp;quot;merged&amp;quot; in den folgenden Fällen übersetzt werden? &amp;lt;br&amp;gt; &amp;lt;tt&amp;gt;&amp;quot;verschmolzen&amp;quot; oder &amp;quot;verflochten&amp;quot;&amp;lt;/tt&amp;gt; &amp;lt;br&amp;gt; der Anwendung selber transparent&amp;quot; tönt auch nicht sehr gut}}&lt;br /&gt;
&lt;br /&gt;
Das Kconfig Objekt, das wir auf Zeile 2 erstellen ist ein gewöhnliches Konfigurationsobjekt. Wir können Werte aus ihm lesen, neue Einträge schreiben und nach verschiedenen Eigenschaften des Objekts fragen. Dieses Objekt wird aus der Konfigurations-Ressource geladen, wie es durch {{class|KStandardDirs}} bestimmt wird, das heisst, dass jede Instanz des &amp;lt;tt&amp;gt;myapprc&amp;lt;/tt&amp;gt;-Objekts in jedem der Ordner in der Konfigurations-Ressourcen-Hierarchie verschmolzen werden um die Werte zu erzeugen, die in diesem Objekt gesehen werden. So werden Systemweite und &lt;br /&gt;
pro-Benutzer/Gruppen Profile erstellt und unterstützt. Das alles geschieht der Anwendung selber transparent.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{tip| Für mehr Informationen, wie das Verschmelzen funktioniert, siehe diesen Artikel über die [[KDE System Administration/KDE_Filesystem_Hierarchy|KDE Dateisystem Hierarchie]].}}&lt;br /&gt;
&lt;br /&gt;
{{note (de)|Ist das so gemeint mit &amp;quot;expects an INI style file&amp;quot;&amp;lt;br&amp;gt; &amp;lt;tt&amp;gt; On line 6 we open a specific local file, this case /etc/kderc. This performs no merging of values and expects an INI style file.&amp;lt;/tt&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Auf Zeile 6 öffnen wir eine bestimmte Lokale Datei, in diesem Fall {{path|/etc/kderc}}. Das führt kein verschmelzen von Werten aus und erwartet eine Datei im INI Format.&lt;br /&gt;
&lt;br /&gt;
Zeile 9 erzeugt ein Konfigurationsobjekt, dass nicht mit dem globalen &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt;-Konfigurationsobjekt verflochten ist,  während das Konfigurationsobjekt auf Zeile 12 zusätzlich mit keinem der Dateien in der &amp;lt;tt&amp;gt;$KDEDIRS&amp;lt;/tt&amp;gt;-Hierarchie verflochten ist. Das kann die Leistung spürbar verbessern, falls man einfach nur Werte aus einer einfachen Konfuguration liest und globale Werte keine Rolle spielen.&lt;br /&gt;
&lt;br /&gt;
Zeile 15 erzeugt ein Konfigurationsobjekt unter Benutzung des {{class|KComponentData}}-Objekts das zu einem Plugin oder einer anderen Komponente gehört. Das Plugin kann verschiedene Ordner aufweisen, die in seinen {{class|KStandardDirs}} definiert sind und das ist eine Möglichkeit sich zu versichern, dass {{class|KConfig}} das respektiert.&lt;br /&gt;
&lt;br /&gt;
Und schliesslich auf Zeile 18 erzeugen wir ein Konfigurationsobjekt, das nicht in der &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt;-Ressource sondern in der &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt;-Ressource existiert. Man kann kann auf diese Weise jede Ressource verwenden, von denen {{class|KStandardDirs}} Kenntnis hat, auch solche die während der Laufzeit hinzugefügt werden.&lt;br /&gt;
&lt;br /&gt;
=== Spezielle Konfigurationsobjekte ===&lt;br /&gt;
&lt;br /&gt;
Jede Anwendung hat sein eigenes Konfigurationsobjekt das den Namen benutzt, der von {{class|KAboutData}} bereitgestellt wird mit angehängtem &amp;quot;rc&amp;quot;. Also hätte eine Anwendung mit dem Namen &amp;quot;myapp&amp;quot; das Standard-Konfigurationsobjekt &amp;quot;myapprc&amp;quot;. Dieses Konfigurationsobjekt kann auf diese Weise aufgerufen werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KComponentData&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
#include &amp;lt;KGlobal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    // beachten sie, dass dies eigentlich ein KSharedConfig ist&lt;br /&gt;
    // mehr über diese Klasse siehe weiter unten&lt;br /&gt;
    KConfig* config = KGlobal::config();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Auf das Standard-Konfigurationsobjekt für die Anwendung wird zugegriffen, wenn kein Name definiert wurde, als das {{class|KConfig}}-Objekt erzeugt wurde. Also könnten wir stattdessen auch das tun:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    KConfig config;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zusätzlich könnte jede Komponente sein eigenes Konfigurationsobjekt haben. Auf dieses wird normalerweise durch die &amp;lt;tt&amp;gt;componentData()&amp;lt;/tt&amp;gt; des Plugins zugegriffen, anstatt durch die &amp;lt;tt&amp;gt;{{class|KGlobal}}::mainComponent()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Und schliesslich gibt es noch ein globales Konfigurationsobjekt, &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt;, das von jeder Anwendung verwendet wird. Es enthält Informationen wie die Standard-Tatenkombinationen für verschiedene Aktionen. Es wird in das Konfigurationsobjekt &amp;quot;gemischt&amp;quot; wenn der &amp;lt;tt&amp;gt;KConfig::IncludeGlobals&amp;lt;/tt&amp;gt; Bitschalter dem {{class|KConfig}} Konstruktor übergeben wird, was standardmässig der Fall ist.&lt;br /&gt;
&lt;br /&gt;
=== Allgemein nützliche Methoden ===&lt;br /&gt;
&lt;br /&gt;
Um den momentanen Zustand des Konfigurationsobjektes zu speichern, rufen wir die &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt;-Methode auf. Diese Methode wird also aufgerufen, wenn ein Objekt zerstört wird. Falls keine Änderungen gemacht wurden, oder die Ressource weist sich als nicht beschreibbar aus (Wenn der Benutzer zum Beispiel nicht genug Rechte hat, um die Datei zu bearbeiten), dann wird keine Beschäftigung der Festplatte hervorgerufen. &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; verschmilzt Änderungen die gleichzeitig von anderen Prozessen ausgeführt werden - lokale Änderungen haben aber trotzdem Vorrang.&lt;br /&gt;
&lt;br /&gt;
Wenn wir sicher gehen wollen, dass wir die aktuellsten Werte von der Festplatte haben, dann rufen wir &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt; auf, welches &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; aufruft und dann die Daten von der Festplatte aktualisiert.&lt;br /&gt;
&lt;br /&gt;
Falls wir verhindern müssen, dass das Konfigurationsobjekt bereits gemachte Änderungen nicht auf die Festplatte speichert, müssen wir &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt; aufrufen. Ein besonderer Anwendungsfall ist es, die Konfiguration zum Festplatten-Zustand zurückzusetzen indem man &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt; gefolgt von &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt; aufruft.&lt;br /&gt;
&lt;br /&gt;
Alle Gruppen in einem Konfigurationsobjekt aufzurufen ist so einfach wie hier in diesem Code-Abschnitt &amp;lt;tt&amp;gt;groupList()&amp;lt;/tt&amp;gt; aufzurufen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::mainComponent().config();&lt;br /&gt;
&lt;br /&gt;
foreach ( const QString&amp;amp; group, config.groupList() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;next group:&amp;quot; &amp;lt;&amp;lt; group;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== KSharedConfig ==&lt;br /&gt;
&lt;br /&gt;
The {{class|KSharedConfig}} class is a reference counted version of {{class|KConfig}}. It thus provides a way to reference the same configuration object from multiple places in your application without the extra overhead of separate objects or concerns about syncronizing writes to disk even if the configuration object is updated from multiple code paths. &lt;br /&gt;
&lt;br /&gt;
Accessing a {{class|KSharedConfig}} object is as easy as this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KSharedConfigPtr config = KSharedConfig::openConfig();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;openConfig()&amp;lt;/tt&amp;gt; take the same parameters as {{class|KConfig}}'s constructors do, allowing one to define which configuration file to open, flags to control merging and non-&amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; resources.&lt;br /&gt;
&lt;br /&gt;
{{class|KSharedConfig}} is generally recommended over using {{class|KConfig}} itself, and the object returned from {{class|KComponentData}} is indeed a {{class|KSharedConfig}} object.&lt;br /&gt;
&lt;br /&gt;
== KConfigGroup ==&lt;br /&gt;
&lt;br /&gt;
Now that we have a configuration object, the next step is to actually use it. The first thing we must do is to define which group of key/value pairs we wish to access in the object. We do this by creating a KConfigGroup object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig config;&lt;br /&gt;
KConfigGroup generalGroup( &amp;amp;config, &amp;quot;General&amp;quot; );&lt;br /&gt;
KConfigGroup colorsGroup = config.group( &amp;quot;Colors&amp;quot; ); // ... or a bit differently ...&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can pass {{class|KConfig}} or {{class|KSharedConfig}} objects to {{class|KConfigGroup}}.&lt;br /&gt;
&lt;br /&gt;
Config groups can be nested as well:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfigGroup subGroup1( &amp;amp;generalGroup, &amp;quot;LessGeneral&amp;quot; );&lt;br /&gt;
KConfigGroup subGroup2 = colorsGroup.group( &amp;quot;Dialogs&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Reading Entries ==&lt;br /&gt;
&lt;br /&gt;
With a {{class|KConfigGroup}} object in hand reading entries is now quite straight forward:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
QString accountName = generalGroup.readEntry( &amp;quot;Account&amp;quot;,&lt;br /&gt;
                                              QString() );&lt;br /&gt;
QColor color = colorsGroup.readEntry( &amp;quot;background&amp;quot;,&lt;br /&gt;
                                      Qt::white );&lt;br /&gt;
QStringList list = generalGroup.readEntry( &amp;quot;List&amp;quot;,&lt;br /&gt;
                                           QStringList() );&lt;br /&gt;
QString path = generalGroup.readPathEntry( &amp;quot;SaveTo&amp;quot;,&lt;br /&gt;
                                           defaultPath );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As can be seen from the above, you can mix reads from different {{class|KConfigGroup}} objects created on the same {{class|KConfig}} object. The read methods take the key, which is case sensitive, as the first argument and the default value as the second argument. This argument controls what kind of data, e.g. a color in line 3 above, is to be expected as well as the type of object returned. The returned object is wrapped in a {{qt|QVariant}} to make this magic happen.&lt;br /&gt;
&lt;br /&gt;
There are a couple of special read methods, including &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; which returns a file system path. It is vital that one uses &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; if it is a path as this enables such features as roaming profiles to work properly.&lt;br /&gt;
&lt;br /&gt;
If no such key currently exists in the configuration object, the default value is returned instead. If there is a localized (e.g. translated into another language) entry for the key that matches the current locale, that is returned.&lt;br /&gt;
&lt;br /&gt;
== Writing Entries ==&lt;br /&gt;
&lt;br /&gt;
Setting new values is similarly straightforward:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
generalGroup.writeEntry( &amp;quot;Account&amp;quot;, accountName );&lt;br /&gt;
generalGroup.writePathEntry( &amp;quot;SaveTo&amp;quot;, savePath );&lt;br /&gt;
colorGroup.writeEntry( &amp;quot;background&amp;quot;, color );&lt;br /&gt;
generalGroup.config()-&amp;gt;sync();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note the use of &amp;lt;tt&amp;gt;writePathEntry&amp;lt;/tt&amp;gt; and how the type of object we use, such as {{qt|QColor}} on line 3, dictates how the data is serialized. Additionally, once we are done writing entries, &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; must be called on the config object for it to be saved to disk. We can also simply wait for the object to be destroyed, which triggers an automatic &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; if necessary.&lt;br /&gt;
&lt;br /&gt;
== KDesktopFile: A Special Case ==&lt;br /&gt;
&lt;br /&gt;
When is a configuration file not a configuration file? When it is a [http://freedesktop.org/wiki/Standards_2fdesktop_2dentry_2dspec desktop file]. These files, which are essentially configuration files at their heart, are used  to describe entries for application menus, mimetypes, plugins and various services.&lt;br /&gt;
&lt;br /&gt;
When accessing a .desktop file, one should instead use the {{class|KDesktopFile}} class which, while a {{class|KConfig}} class offering all the capabilities described above, offers a set of methods designed to make accessing standard attributes of these files consistent and reliable.&lt;br /&gt;
&lt;br /&gt;
== Kiosk: Lockdown and User/Group Profiles ==&lt;br /&gt;
&lt;br /&gt;
KConfig provides a powerful set of lockdown and configuration definition capabilities, collectively known as &amp;quot;Kiosk&amp;quot;, that many system administrators and system integrators rely on. While most of this framework is provided transparently to the application, there is occassion when an application will want to check on the read/write status of a configuration object.&lt;br /&gt;
&lt;br /&gt;
Entries in configuration objects that are locked down using the kiosk facilities are said to be ''immutable''. An application can check for immutability of entire configuration objects, groups or keys as shown in this example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::config();&lt;br /&gt;
&lt;br /&gt;
if ( config-&amp;gt;isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;configuration object is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
KConfigGroup group(config, &amp;quot;General&amp;quot;);&lt;br /&gt;
if ( group.isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;group General is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if ( group.entryIsImmutable(&amp;quot;URL&amp;quot;) ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;URL entry in group General is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This can be useful in particular situations where an action should be taken when an item is immutable. For instance, the KDE panels will not offer configuration options to the user or allow them to otherwise change the order of applets and icons when the panel's configuration object is marked as immutable.&lt;br /&gt;
&lt;br /&gt;
== KConfig XT ==&lt;br /&gt;
&lt;br /&gt;
There is a way to make certain use cases of KConfig easier, faster and more reliable: KConfig XT. In particular, for main application or plugin configuration objects and when syncing configuration dialogs and other interfaces with these values, KConfig XT can help immensely. It also  simultaneously documents the configuration options available, which makes every sys admin and system integrator that uses KDE that much more happy.&lt;br /&gt;
&lt;br /&gt;
[[../Using_KConfig_XT|The next tutorial in the KConfig series covers what KConfig XT is and how to use it.]]&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials/KConfig_(de)</id>
		<title>Development/Tutorials/KConfig (de)</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials/KConfig_(de)"/>
				<updated>2008-01-02T16:34:09Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: /* Spezielle Konfigurationsobjekte */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:I18n/Language Navigation Bar|Development/Tutorials/KConfig}}&lt;br /&gt;
&lt;br /&gt;
{{TutorialBrowser (de)|&lt;br /&gt;
&lt;br /&gt;
series=KConfig|&lt;br /&gt;
&lt;br /&gt;
name=Einführung in KConfig|&lt;br /&gt;
&lt;br /&gt;
pre=Keine|&lt;br /&gt;
&lt;br /&gt;
next=[[../Using_KConfig_XT (de)|Benutzen von KConfig XT]]|&lt;br /&gt;
&lt;br /&gt;
reading=Keine&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{improve (de)}}&lt;br /&gt;
&lt;br /&gt;
== Zusammenfassung ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dieser Artikel beschäftigt sich mir dem KDE Einstellungdaten-System, angefangen mit einer Übersicht über den grundlegenden Aufbau aus der Sicht eines Entwicklers. Es wirft ausserdem einen Blick auf jede der Klassen, die für die Entwicklung von Anwendungen relevant sind und fährt dann mit kiosk (Benutzer- und Gruppenprofile) Integration fort.&lt;br /&gt;
&lt;br /&gt;
== Grundlegender Aufbau ==&lt;br /&gt;
&lt;br /&gt;
KConfig ist ausgelegt um das Konzept vom eigentlichen Speichern und Auffinden von Konfigurationsdaten hinter eine Programmierschnittstelle zu abstrahieren die es ermöglicht, auf einfache Weise Informationen abzurufen und zu setzen. Wo oder in welcher Form Daten gespeichert werden ist für eine Anwendung die KConfig benutzt irrelevant.&lt;br /&gt;
&lt;br /&gt;
Das behält alle KDE Anwendungen konsistent in ihrer Art, Konfigurationen handzuhaben und nimmt einem Anwendungs-Entwickler die Arbeit so ein System von Grund auf neu zu schreiben, was ein sehr fehleranfälliger Prozess sein kann.&lt;br /&gt;
&lt;br /&gt;
Jedes KConfig Objekt verkörpert ein einziges Konfigurationsobjekt. Jedes Konfigurationsobjekt ist durch seinen einzigartigen Namen gekennzeichnet und kann von mehreren lokalen oder externen Daten oder Services gelesen werden. Jede Anwendung hat standardmässig ein zugehöriges Konfigurationsobjekt und es gibt auch ein globales Konfigurationsobjekt.&lt;br /&gt;
&lt;br /&gt;
Diese Konfigurationsobjekte sind nach einer zweistufigen Hierarchie getrennt: Gruppen und Schlüssel. Ein Konfigurationsobjekt kann eine beliebige Anzahl an Gruppen haben und jede Gruppe kann einen oder mehrere Schlüssel mit zugehörigen Werten haben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die gespeicherten Werte können aus beliebig vielen verschiedenen Datentypen bestehen. Sie werden gespeichert und abgerufen als das Objekt selbst. Zum Beispiel wird ein {{qt|QObject}}-Objekt direkt einem Konfigurationsobjekt übergeben, wenn es einen Farbwert speichert und wenn ein Farbwert abgerufen wird, wird ein {{qt|QObject}}-Objekt zurückgegeben.&lt;br /&gt;
&lt;br /&gt;
{{note (de)| deserialization  entgliedern? &amp;lt;br&amp;gt; &amp;lt;tt&amp;gt; &amp;quot;do not have to perform serialization and deserialization of objects themselves&amp;quot; &amp;lt;/tt&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Anwendungen selbst müssen darum normalerweise Objekte nicht selber gliedern und entgliedern.&lt;br /&gt;
&lt;br /&gt;
Applications themselves therefore generally do not have to perform serialization and deserialization of objects themselves.&lt;br /&gt;
&lt;br /&gt;
== Die KConfig Klasse ==&lt;br /&gt;
&lt;br /&gt;
Das {{class|KConfig}}-Objekt wird benutzt um ein bestehendes Konfigurationsobjekt anzusteuern. Es gibt eine Reihe von Möglichkeiten ein Konfigurationsobjekt zu erstellen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
// ein einfaches, altes lesen/schreiben Konfigurationsobjekt&lt;br /&gt;
KConfig config(&amp;quot;myapprc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// eine bestimmte Datei im Dateisystem&lt;br /&gt;
// currently must be an INI style file&lt;br /&gt;
KConfig fullPath(&amp;quot;/etc/kderc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// nicht mit globalen Werten verflochten&lt;br /&gt;
KConfig globalFree( &amp;quot;localsrc&amp;quot;, KConfig::NoGlobals );&lt;br /&gt;
&lt;br /&gt;
// nicht mit globalen Werten orde der $KDEDIRS Hierarchie verflochten&lt;br /&gt;
KConfig simpleConfig( &amp;quot;simplerc&amp;quot;, KConfig::SimpleConfig );&lt;br /&gt;
&lt;br /&gt;
// Komponenten-spezifische Konfiguration, in diesem Fall ein Plugin&lt;br /&gt;
KConfig pluginConfig( componentData(), &amp;quot;pluginrc&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
// Ausserhalb der normalen Konfigurations-Ressource&lt;br /&gt;
KConfig dataResource( &amp;quot;data&amp;quot;, &amp;quot;myapp/somefile&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{note (de)|wie soll &amp;quot;merged&amp;quot; in den folgenden Fällen übersetzt werden? &amp;lt;br&amp;gt; &amp;lt;tt&amp;gt;&amp;quot;verschmolzen&amp;quot; oder &amp;quot;verflochten&amp;quot;&amp;lt;/tt&amp;gt; &amp;lt;br&amp;gt; der Anwendung selber transparent&amp;quot; tönt auch nicht sehr gut}}&lt;br /&gt;
&lt;br /&gt;
Das Kconfig Objekt, das wir auf Zeile 2 erstellen ist ein gewöhnliches Konfigurationsobjekt. Wir können Werte aus ihm lesen, neue Einträge schreiben und nach verschiedenen Eigenschaften des Objekts fragen. Dieses Objekt wird aus der Konfigurations-Ressource geladen, wie es durch {{class|KStandardDirs}} bestimmt wird, das heisst, dass jede Instanz des &amp;lt;tt&amp;gt;myapprc&amp;lt;/tt&amp;gt;-Objekts in jedem der Ordner in der Konfigurations-Ressourcen-Hierarchie verschmolzen werden um die Werte zu erzeugen, die in diesem Objekt gesehen werden. So werden Systemweite und &lt;br /&gt;
pro-Benutzer/Gruppen Profile erstellt und unterstützt. Das alles geschieht der Anwendung selber transparent.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{tip| Für mehr Informationen, wie das Verschmelzen funktioniert, siehe diesen Artikel über die [[KDE System Administration/KDE_Filesystem_Hierarchy|KDE Dateisystem Hierarchie]].}}&lt;br /&gt;
&lt;br /&gt;
{{note (de)|Ist das so gemeint mit &amp;quot;expects an INI style file&amp;quot;&amp;lt;br&amp;gt; &amp;lt;tt&amp;gt; On line 6 we open a specific local file, this case /etc/kderc. This performs no merging of values and expects an INI style file.&amp;lt;/tt&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Auf Zeile 6 öffnen wir eine bestimmte Lokale Datei, in diesem Fall {{path|/etc/kderc}}. Das führt kein verschmelzen von Werten aus und erwartet eine Datei im INI Format.&lt;br /&gt;
&lt;br /&gt;
Zeile 9 erzeugt ein Konfigurationsobjekt, dass nicht mit dem globalen &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt;-Konfigurationsobjekt verflochten ist,  während das Konfigurationsobjekt auf Zeile 12 zusätzlich mit keinem der Dateien in der &amp;lt;tt&amp;gt;$KDEDIRS&amp;lt;/tt&amp;gt;-Hierarchie verflochten ist. Das kann die Leistung spürbar verbessern, falls man einfach nur Werte aus einer einfachen Konfuguration liest und globale Werte keine Rolle spielen.&lt;br /&gt;
&lt;br /&gt;
Zeile 15 erzeugt ein Konfigurationsobjekt unter Benutzung des {{class|KComponentData}}-Objekts das zu einem Plugin oder einer anderen Komponente gehört. Das Plugin kann verschiedene Ordner aufweisen, die in seinen {{class|KStandardDirs}} definiert sind und das ist eine Möglichkeit sich zu versichern, dass {{class|KConfig}} das respektiert.&lt;br /&gt;
&lt;br /&gt;
Und schliesslich auf Zeile 18 erzeugen wir ein Konfigurationsobjekt, das nicht in der &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt;-Ressource sondern in der &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt;-Ressource existiert. Man kann kann auf diese Weise jede Ressource verwenden, von denen {{class|KStandardDirs}} Kenntnis hat, auch solche die während der Laufzeit hinzugefügt werden.&lt;br /&gt;
&lt;br /&gt;
=== Spezielle Konfigurationsobjekte ===&lt;br /&gt;
&lt;br /&gt;
Jede Anwendung hat sein eigenes Konfigurationsobjekt das den Namen benutzt, der von {{class|KAboutData}} bereitgestellt wird mit angehängtem &amp;quot;rc&amp;quot;. Also hätte eine Anwendung mit dem Namen &amp;quot;myapp&amp;quot; das Standard-Konfigurationsobjekt &amp;quot;myapprc&amp;quot;. Dieses Konfigurationsobjekt kann auf diese Weise aufgerufen werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KComponentData&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
#include &amp;lt;KGlobal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    // beachten sie, dass dies eigentlich ein KSharedConfig ist&lt;br /&gt;
    // mehr über diese Klasse siehe weiter unten&lt;br /&gt;
    KConfig* config = KGlobal::config();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Auf das Standard-Konfigurationsobjekt für die Anwendung wird zugegriffen, wenn kein Name definiert wurde, als das {{class|KConfig}}-Objekt erzeugt wurde. Also könnten wir stattdessen auch das tun:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    KConfig config;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zusätzlich könnte jede Komponente sein eigenes Konfigurationsobjekt haben. Auf dieses wird normalerweise durch die &amp;lt;tt&amp;gt;componentData()&amp;lt;/tt&amp;gt; des Plugins zugegriffen, anstatt durch die &amp;lt;tt&amp;gt;{{class|KGlobal}}::mainComponent()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Und schliesslich gibt es noch ein globales Konfigurationsobjekt, &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt;, das von jeder Anwendung verwendet wird. Es enthält Informationen wie die Standard-Tatenkombinationen für verschiedene Aktionen. Es wird in das Konfigurationsobjekt &amp;quot;gemischt&amp;quot; wenn der &amp;lt;tt&amp;gt;KConfig::IncludeGlobals&amp;lt;/tt&amp;gt; Bitschalter dem {{class|KConfig}} Konstruktor übergeben wird, was standardmässig der Fall ist.&lt;br /&gt;
&lt;br /&gt;
=== Allgemein nützliche Methoden ===&lt;br /&gt;
&lt;br /&gt;
Um den momentanen Zustand des Konfigurationsobjektes zu speichern, rufen wir die &amp;lt;tt&amp;gt;sync()&amp;lt;/tt-Methode auf. Diese Methode wird also aufgerufen, wenn ein Objekt zerstört wird. Falls keine Änderungen gemacht wurden, oder die Ressource weist sich als nicht beschreibbar aus (Wenn der Benutzer zum Beispiel nicht genug Rechte hat, um die Datei zu bearbeiten), dann wird keine Beschäftigung der Festplatte hervorgerufen. &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; verschmilzt Änderungen die gleichzeitig von anderen Prozessen ausgeführt werden - lokale Änderungen haben aber trotzdem Vorrang.&lt;br /&gt;
&lt;br /&gt;
Wenn wir sicher gehen wollen, dass wir die aktuellsten Werte von der Festplatte haben, dann rufen wir &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt; auf, welches &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; aufruft und dann die Daten von der Festplatte aktualisiert.&lt;br /&gt;
&lt;br /&gt;
Falls wir verhindern müssen, dass das Konfigurationsobjekt bereits gemachte Änderungen nicht auf die Festplatte speichert, müssen wir &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt; aufrufen. Ein besonderer Anwendungsfall ist es, die Konfiguration zum Festplatten-Zustand zurückzusetzen indem man &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt; gefolgt von &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt; aufruft.&lt;br /&gt;
&lt;br /&gt;
Alle Gruppen in einem Konfigurationsobjekt aufzurufen ist so einfach wie hier in diesem Code-Abschnitt &amp;lt;tt&amp;gt;groupList()&amp;lt;/tt&amp;gt; aufzurufen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::mainComponent().config();&lt;br /&gt;
&lt;br /&gt;
foreach ( const QString&amp;amp; group, config.groupList() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;next group:&amp;quot; &amp;lt;&amp;lt; group;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== KSharedConfig ==&lt;br /&gt;
&lt;br /&gt;
The {{class|KSharedConfig}} class is a reference counted version of {{class|KConfig}}. It thus provides a way to reference the same configuration object from multiple places in your application without the extra overhead of separate objects or concerns about syncronizing writes to disk even if the configuration object is updated from multiple code paths. &lt;br /&gt;
&lt;br /&gt;
Accessing a {{class|KSharedConfig}} object is as easy as this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KSharedConfigPtr config = KSharedConfig::openConfig();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;openConfig()&amp;lt;/tt&amp;gt; take the same parameters as {{class|KConfig}}'s constructors do, allowing one to define which configuration file to open, flags to control merging and non-&amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; resources.&lt;br /&gt;
&lt;br /&gt;
{{class|KSharedConfig}} is generally recommended over using {{class|KConfig}} itself, and the object returned from {{class|KComponentData}} is indeed a {{class|KSharedConfig}} object.&lt;br /&gt;
&lt;br /&gt;
== KConfigGroup ==&lt;br /&gt;
&lt;br /&gt;
Now that we have a configuration object, the next step is to actually use it. The first thing we must do is to define which group of key/value pairs we wish to access in the object. We do this by creating a KConfigGroup object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig config;&lt;br /&gt;
KConfigGroup generalGroup( &amp;amp;config, &amp;quot;General&amp;quot; );&lt;br /&gt;
KConfigGroup colorsGroup = config.group( &amp;quot;Colors&amp;quot; ); // ... or a bit differently ...&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can pass {{class|KConfig}} or {{class|KSharedConfig}} objects to {{class|KConfigGroup}}.&lt;br /&gt;
&lt;br /&gt;
Config groups can be nested as well:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfigGroup subGroup1( &amp;amp;generalGroup, &amp;quot;LessGeneral&amp;quot; );&lt;br /&gt;
KConfigGroup subGroup2 = colorsGroup.group( &amp;quot;Dialogs&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Reading Entries ==&lt;br /&gt;
&lt;br /&gt;
With a {{class|KConfigGroup}} object in hand reading entries is now quite straight forward:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
QString accountName = generalGroup.readEntry( &amp;quot;Account&amp;quot;,&lt;br /&gt;
                                              QString() );&lt;br /&gt;
QColor color = colorsGroup.readEntry( &amp;quot;background&amp;quot;,&lt;br /&gt;
                                      Qt::white );&lt;br /&gt;
QStringList list = generalGroup.readEntry( &amp;quot;List&amp;quot;,&lt;br /&gt;
                                           QStringList() );&lt;br /&gt;
QString path = generalGroup.readPathEntry( &amp;quot;SaveTo&amp;quot;,&lt;br /&gt;
                                           defaultPath );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As can be seen from the above, you can mix reads from different {{class|KConfigGroup}} objects created on the same {{class|KConfig}} object. The read methods take the key, which is case sensitive, as the first argument and the default value as the second argument. This argument controls what kind of data, e.g. a color in line 3 above, is to be expected as well as the type of object returned. The returned object is wrapped in a {{qt|QVariant}} to make this magic happen.&lt;br /&gt;
&lt;br /&gt;
There are a couple of special read methods, including &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; which returns a file system path. It is vital that one uses &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; if it is a path as this enables such features as roaming profiles to work properly.&lt;br /&gt;
&lt;br /&gt;
If no such key currently exists in the configuration object, the default value is returned instead. If there is a localized (e.g. translated into another language) entry for the key that matches the current locale, that is returned.&lt;br /&gt;
&lt;br /&gt;
== Writing Entries ==&lt;br /&gt;
&lt;br /&gt;
Setting new values is similarly straightforward:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
generalGroup.writeEntry( &amp;quot;Account&amp;quot;, accountName );&lt;br /&gt;
generalGroup.writePathEntry( &amp;quot;SaveTo&amp;quot;, savePath );&lt;br /&gt;
colorGroup.writeEntry( &amp;quot;background&amp;quot;, color );&lt;br /&gt;
generalGroup.config()-&amp;gt;sync();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note the use of &amp;lt;tt&amp;gt;writePathEntry&amp;lt;/tt&amp;gt; and how the type of object we use, such as {{qt|QColor}} on line 3, dictates how the data is serialized. Additionally, once we are done writing entries, &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; must be called on the config object for it to be saved to disk. We can also simply wait for the object to be destroyed, which triggers an automatic &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; if necessary.&lt;br /&gt;
&lt;br /&gt;
== KDesktopFile: A Special Case ==&lt;br /&gt;
&lt;br /&gt;
When is a configuration file not a configuration file? When it is a [http://freedesktop.org/wiki/Standards_2fdesktop_2dentry_2dspec desktop file]. These files, which are essentially configuration files at their heart, are used  to describe entries for application menus, mimetypes, plugins and various services.&lt;br /&gt;
&lt;br /&gt;
When accessing a .desktop file, one should instead use the {{class|KDesktopFile}} class which, while a {{class|KConfig}} class offering all the capabilities described above, offers a set of methods designed to make accessing standard attributes of these files consistent and reliable.&lt;br /&gt;
&lt;br /&gt;
== Kiosk: Lockdown and User/Group Profiles ==&lt;br /&gt;
&lt;br /&gt;
KConfig provides a powerful set of lockdown and configuration definition capabilities, collectively known as &amp;quot;Kiosk&amp;quot;, that many system administrators and system integrators rely on. While most of this framework is provided transparently to the application, there is occassion when an application will want to check on the read/write status of a configuration object.&lt;br /&gt;
&lt;br /&gt;
Entries in configuration objects that are locked down using the kiosk facilities are said to be ''immutable''. An application can check for immutability of entire configuration objects, groups or keys as shown in this example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::config();&lt;br /&gt;
&lt;br /&gt;
if ( config-&amp;gt;isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;configuration object is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
KConfigGroup group(config, &amp;quot;General&amp;quot;);&lt;br /&gt;
if ( group.isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;group General is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if ( group.entryIsImmutable(&amp;quot;URL&amp;quot;) ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;URL entry in group General is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This can be useful in particular situations where an action should be taken when an item is immutable. For instance, the KDE panels will not offer configuration options to the user or allow them to otherwise change the order of applets and icons when the panel's configuration object is marked as immutable.&lt;br /&gt;
&lt;br /&gt;
== KConfig XT ==&lt;br /&gt;
&lt;br /&gt;
There is a way to make certain use cases of KConfig easier, faster and more reliable: KConfig XT. In particular, for main application or plugin configuration objects and when syncing configuration dialogs and other interfaces with these values, KConfig XT can help immensely. It also  simultaneously documents the configuration options available, which makes every sys admin and system integrator that uses KDE that much more happy.&lt;br /&gt;
&lt;br /&gt;
[[../Using_KConfig_XT|The next tutorial in the KConfig series covers what KConfig XT is and how to use it.]]&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials/KConfig_(de)</id>
		<title>Development/Tutorials/KConfig (de)</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials/KConfig_(de)"/>
				<updated>2008-01-02T16:33:44Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: /* Die KConfig Klasse */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:I18n/Language Navigation Bar|Development/Tutorials/KConfig}}&lt;br /&gt;
&lt;br /&gt;
{{TutorialBrowser (de)|&lt;br /&gt;
&lt;br /&gt;
series=KConfig|&lt;br /&gt;
&lt;br /&gt;
name=Einführung in KConfig|&lt;br /&gt;
&lt;br /&gt;
pre=Keine|&lt;br /&gt;
&lt;br /&gt;
next=[[../Using_KConfig_XT (de)|Benutzen von KConfig XT]]|&lt;br /&gt;
&lt;br /&gt;
reading=Keine&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{improve (de)}}&lt;br /&gt;
&lt;br /&gt;
== Zusammenfassung ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dieser Artikel beschäftigt sich mir dem KDE Einstellungdaten-System, angefangen mit einer Übersicht über den grundlegenden Aufbau aus der Sicht eines Entwicklers. Es wirft ausserdem einen Blick auf jede der Klassen, die für die Entwicklung von Anwendungen relevant sind und fährt dann mit kiosk (Benutzer- und Gruppenprofile) Integration fort.&lt;br /&gt;
&lt;br /&gt;
== Grundlegender Aufbau ==&lt;br /&gt;
&lt;br /&gt;
KConfig ist ausgelegt um das Konzept vom eigentlichen Speichern und Auffinden von Konfigurationsdaten hinter eine Programmierschnittstelle zu abstrahieren die es ermöglicht, auf einfache Weise Informationen abzurufen und zu setzen. Wo oder in welcher Form Daten gespeichert werden ist für eine Anwendung die KConfig benutzt irrelevant.&lt;br /&gt;
&lt;br /&gt;
Das behält alle KDE Anwendungen konsistent in ihrer Art, Konfigurationen handzuhaben und nimmt einem Anwendungs-Entwickler die Arbeit so ein System von Grund auf neu zu schreiben, was ein sehr fehleranfälliger Prozess sein kann.&lt;br /&gt;
&lt;br /&gt;
Jedes KConfig Objekt verkörpert ein einziges Konfigurationsobjekt. Jedes Konfigurationsobjekt ist durch seinen einzigartigen Namen gekennzeichnet und kann von mehreren lokalen oder externen Daten oder Services gelesen werden. Jede Anwendung hat standardmässig ein zugehöriges Konfigurationsobjekt und es gibt auch ein globales Konfigurationsobjekt.&lt;br /&gt;
&lt;br /&gt;
Diese Konfigurationsobjekte sind nach einer zweistufigen Hierarchie getrennt: Gruppen und Schlüssel. Ein Konfigurationsobjekt kann eine beliebige Anzahl an Gruppen haben und jede Gruppe kann einen oder mehrere Schlüssel mit zugehörigen Werten haben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die gespeicherten Werte können aus beliebig vielen verschiedenen Datentypen bestehen. Sie werden gespeichert und abgerufen als das Objekt selbst. Zum Beispiel wird ein {{qt|QObject}}-Objekt direkt einem Konfigurationsobjekt übergeben, wenn es einen Farbwert speichert und wenn ein Farbwert abgerufen wird, wird ein {{qt|QObject}}-Objekt zurückgegeben.&lt;br /&gt;
&lt;br /&gt;
{{note (de)| deserialization  entgliedern? &amp;lt;br&amp;gt; &amp;lt;tt&amp;gt; &amp;quot;do not have to perform serialization and deserialization of objects themselves&amp;quot; &amp;lt;/tt&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Anwendungen selbst müssen darum normalerweise Objekte nicht selber gliedern und entgliedern.&lt;br /&gt;
&lt;br /&gt;
Applications themselves therefore generally do not have to perform serialization and deserialization of objects themselves.&lt;br /&gt;
&lt;br /&gt;
== Die KConfig Klasse ==&lt;br /&gt;
&lt;br /&gt;
Das {{class|KConfig}}-Objekt wird benutzt um ein bestehendes Konfigurationsobjekt anzusteuern. Es gibt eine Reihe von Möglichkeiten ein Konfigurationsobjekt zu erstellen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
// ein einfaches, altes lesen/schreiben Konfigurationsobjekt&lt;br /&gt;
KConfig config(&amp;quot;myapprc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// eine bestimmte Datei im Dateisystem&lt;br /&gt;
// currently must be an INI style file&lt;br /&gt;
KConfig fullPath(&amp;quot;/etc/kderc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// nicht mit globalen Werten verflochten&lt;br /&gt;
KConfig globalFree( &amp;quot;localsrc&amp;quot;, KConfig::NoGlobals );&lt;br /&gt;
&lt;br /&gt;
// nicht mit globalen Werten orde der $KDEDIRS Hierarchie verflochten&lt;br /&gt;
KConfig simpleConfig( &amp;quot;simplerc&amp;quot;, KConfig::SimpleConfig );&lt;br /&gt;
&lt;br /&gt;
// Komponenten-spezifische Konfiguration, in diesem Fall ein Plugin&lt;br /&gt;
KConfig pluginConfig( componentData(), &amp;quot;pluginrc&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
// Ausserhalb der normalen Konfigurations-Ressource&lt;br /&gt;
KConfig dataResource( &amp;quot;data&amp;quot;, &amp;quot;myapp/somefile&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{note (de)|wie soll &amp;quot;merged&amp;quot; in den folgenden Fällen übersetzt werden? &amp;lt;br&amp;gt; &amp;lt;tt&amp;gt;&amp;quot;verschmolzen&amp;quot; oder &amp;quot;verflochten&amp;quot;&amp;lt;/tt&amp;gt; &amp;lt;br&amp;gt; der Anwendung selber transparent&amp;quot; tönt auch nicht sehr gut}}&lt;br /&gt;
&lt;br /&gt;
Das Kconfig Objekt, das wir auf Zeile 2 erstellen ist ein gewöhnliches Konfigurationsobjekt. Wir können Werte aus ihm lesen, neue Einträge schreiben und nach verschiedenen Eigenschaften des Objekts fragen. Dieses Objekt wird aus der Konfigurations-Ressource geladen, wie es durch {{class|KStandardDirs}} bestimmt wird, das heisst, dass jede Instanz des &amp;lt;tt&amp;gt;myapprc&amp;lt;/tt&amp;gt;-Objekts in jedem der Ordner in der Konfigurations-Ressourcen-Hierarchie verschmolzen werden um die Werte zu erzeugen, die in diesem Objekt gesehen werden. So werden Systemweite und &lt;br /&gt;
pro-Benutzer/Gruppen Profile erstellt und unterstützt. Das alles geschieht der Anwendung selber transparent.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{tip| Für mehr Informationen, wie das Verschmelzen funktioniert, siehe diesen Artikel über die [[KDE System Administration/KDE_Filesystem_Hierarchy|KDE Dateisystem Hierarchie]].}}&lt;br /&gt;
&lt;br /&gt;
{{note (de)|Ist das so gemeint mit &amp;quot;expects an INI style file&amp;quot;&amp;lt;br&amp;gt; &amp;lt;tt&amp;gt; On line 6 we open a specific local file, this case /etc/kderc. This performs no merging of values and expects an INI style file.&amp;lt;/tt&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Auf Zeile 6 öffnen wir eine bestimmte Lokale Datei, in diesem Fall {{path|/etc/kderc}}. Das führt kein verschmelzen von Werten aus und erwartet eine Datei im INI Format.&lt;br /&gt;
&lt;br /&gt;
Zeile 9 erzeugt ein Konfigurationsobjekt, dass nicht mit dem globalen &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt;-Konfigurationsobjekt verflochten ist,  während das Konfigurationsobjekt auf Zeile 12 zusätzlich mit keinem der Dateien in der &amp;lt;tt&amp;gt;$KDEDIRS&amp;lt;/tt&amp;gt;-Hierarchie verflochten ist. Das kann die Leistung spürbar verbessern, falls man einfach nur Werte aus einer einfachen Konfuguration liest und globale Werte keine Rolle spielen.&lt;br /&gt;
&lt;br /&gt;
Zeile 15 erzeugt ein Konfigurationsobjekt unter Benutzung des {{class|KComponentData}}-Objekts das zu einem Plugin oder einer anderen Komponente gehört. Das Plugin kann verschiedene Ordner aufweisen, die in seinen {{class|KStandardDirs}} definiert sind und das ist eine Möglichkeit sich zu versichern, dass {{class|KConfig}} das respektiert.&lt;br /&gt;
&lt;br /&gt;
Und schliesslich auf Zeile 18 erzeugen wir ein Konfigurationsobjekt, das nicht in der &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt;-Ressource sondern in der &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt;-Ressource existiert. Man kann kann auf diese Weise jede Ressource verwenden, von denen {{class|KStandardDirs}} Kenntnis hat, auch solche die während der Laufzeit hinzugefügt werden.&lt;br /&gt;
&lt;br /&gt;
=== Spezielle Konfigurationsobjekte ===&lt;br /&gt;
&lt;br /&gt;
Jede Anwendung hat sein eigenes Konfigurationsobjekt das den Namen benutzt, der von {{class|KAboutData}} bereitgestellt wird mit angehängtem &amp;quot;rc&amp;quot;. Also hätte eine Anwendung mit dem Namen &amp;quot;myapp&amp;quot; das Standard-Konfigurationsobjekt &amp;quot;myapprc&amp;quot;. Dieses Konfigurationsobjekt kann auf diese Weise aufgerufen werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KComponentData&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
#include &amp;lt;KGlobal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    // beachten sie, dass dies eigentlich ein KSharedConfig ist&lt;br /&gt;
    // mehr über diese Klasse siehe weiter unten&lt;br /&gt;
    KConfig* config = KGlobal::config();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Auf das Standard-Konfigurationsobjekt für die Anwendung wird zugegriffen, wenn kein Name definiert wurde, als das {{class|KConfig}}-Objekt erzeugt wurde. Also könnten wir stattdessen auch das tun:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    KConfig config;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zusätzlich könnte jede Komponente sein eigenes Konfigurationsobjekt haben. Auf dieses wird normalerweise durch die &amp;lt;tt&amp;gt;componentData()&amp;lt;/tt&amp;gt; des Plugins zugegriffen, anstatt durch die &amp;lt;tt&amp;gt;{{class|KGlobal}}::mainComponent()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Und schliesslich gibt es noch ein globales Konfigurationsobjekt, &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt;, das von jeder Anwendung verwendet wird. Es enthält Informationen wie die Standard-Tatenkombinationen für verschiedene Aktionen. Es wird in das Konfigurationsobjekt &amp;quot;gemischt&amp;quot; wenn der &amp;lt;tt&amp;gt;KConfig::IncludeGlobals&amp;lt;/tt&amp;gt; Bitschalter dem {{class|KConfig}} Konstruktor übergeben wird, was standardmässig der Fall ist.&lt;br /&gt;
&lt;br /&gt;
{{note (de)|Der Rest muss noch übersetzt werden}}&lt;br /&gt;
&lt;br /&gt;
=== Allgemein nützliche Methoden ===&lt;br /&gt;
&lt;br /&gt;
Um den momentanen Zustand des Konfigurationsobjektes zu speichern, rufen wir die &amp;lt;tt&amp;gt;sync()&amp;lt;/tt-Methode auf. Diese Methode wird also aufgerufen, wenn ein Objekt zerstört wird. Falls keine Änderungen gemacht wurden, oder die Ressource weist sich als nicht beschreibbar aus (Wenn der Benutzer zum Beispiel nicht genug Rechte hat, um die Datei zu bearbeiten), dann wird keine Beschäftigung der Festplatte hervorgerufen. &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; verschmilzt Änderungen die gleichzeitig von anderen Prozessen ausgeführt werden - lokale Änderungen haben aber trotzdem Vorrang.&lt;br /&gt;
&lt;br /&gt;
Wenn wir sicher gehen wollen, dass wir die aktuellsten Werte von der Festplatte haben, dann rufen wir &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt; auf, welches &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; aufruft und dann die Daten von der Festplatte aktualisiert.&lt;br /&gt;
&lt;br /&gt;
Falls wir verhindern müssen, dass das Konfigurationsobjekt bereits gemachte Änderungen nicht auf die Festplatte speichert, müssen wir &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt; aufrufen. Ein besonderer Anwendungsfall ist es, die Konfiguration zum Festplatten-Zustand zurückzusetzen indem man &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt; gefolgt von &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt; aufruft.&lt;br /&gt;
&lt;br /&gt;
Alle Gruppen in einem Konfigurationsobjekt aufzurufen ist so einfach wie hier in diesem Code-Abschnitt &amp;lt;tt&amp;gt;groupList()&amp;lt;/tt&amp;gt; aufzurufen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::mainComponent().config();&lt;br /&gt;
&lt;br /&gt;
foreach ( const QString&amp;amp; group, config.groupList() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;next group:&amp;quot; &amp;lt;&amp;lt; group;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== KSharedConfig ==&lt;br /&gt;
&lt;br /&gt;
The {{class|KSharedConfig}} class is a reference counted version of {{class|KConfig}}. It thus provides a way to reference the same configuration object from multiple places in your application without the extra overhead of separate objects or concerns about syncronizing writes to disk even if the configuration object is updated from multiple code paths. &lt;br /&gt;
&lt;br /&gt;
Accessing a {{class|KSharedConfig}} object is as easy as this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KSharedConfigPtr config = KSharedConfig::openConfig();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;openConfig()&amp;lt;/tt&amp;gt; take the same parameters as {{class|KConfig}}'s constructors do, allowing one to define which configuration file to open, flags to control merging and non-&amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; resources.&lt;br /&gt;
&lt;br /&gt;
{{class|KSharedConfig}} is generally recommended over using {{class|KConfig}} itself, and the object returned from {{class|KComponentData}} is indeed a {{class|KSharedConfig}} object.&lt;br /&gt;
&lt;br /&gt;
== KConfigGroup ==&lt;br /&gt;
&lt;br /&gt;
Now that we have a configuration object, the next step is to actually use it. The first thing we must do is to define which group of key/value pairs we wish to access in the object. We do this by creating a KConfigGroup object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig config;&lt;br /&gt;
KConfigGroup generalGroup( &amp;amp;config, &amp;quot;General&amp;quot; );&lt;br /&gt;
KConfigGroup colorsGroup = config.group( &amp;quot;Colors&amp;quot; ); // ... or a bit differently ...&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can pass {{class|KConfig}} or {{class|KSharedConfig}} objects to {{class|KConfigGroup}}.&lt;br /&gt;
&lt;br /&gt;
Config groups can be nested as well:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfigGroup subGroup1( &amp;amp;generalGroup, &amp;quot;LessGeneral&amp;quot; );&lt;br /&gt;
KConfigGroup subGroup2 = colorsGroup.group( &amp;quot;Dialogs&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Reading Entries ==&lt;br /&gt;
&lt;br /&gt;
With a {{class|KConfigGroup}} object in hand reading entries is now quite straight forward:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
QString accountName = generalGroup.readEntry( &amp;quot;Account&amp;quot;,&lt;br /&gt;
                                              QString() );&lt;br /&gt;
QColor color = colorsGroup.readEntry( &amp;quot;background&amp;quot;,&lt;br /&gt;
                                      Qt::white );&lt;br /&gt;
QStringList list = generalGroup.readEntry( &amp;quot;List&amp;quot;,&lt;br /&gt;
                                           QStringList() );&lt;br /&gt;
QString path = generalGroup.readPathEntry( &amp;quot;SaveTo&amp;quot;,&lt;br /&gt;
                                           defaultPath );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As can be seen from the above, you can mix reads from different {{class|KConfigGroup}} objects created on the same {{class|KConfig}} object. The read methods take the key, which is case sensitive, as the first argument and the default value as the second argument. This argument controls what kind of data, e.g. a color in line 3 above, is to be expected as well as the type of object returned. The returned object is wrapped in a {{qt|QVariant}} to make this magic happen.&lt;br /&gt;
&lt;br /&gt;
There are a couple of special read methods, including &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; which returns a file system path. It is vital that one uses &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; if it is a path as this enables such features as roaming profiles to work properly.&lt;br /&gt;
&lt;br /&gt;
If no such key currently exists in the configuration object, the default value is returned instead. If there is a localized (e.g. translated into another language) entry for the key that matches the current locale, that is returned.&lt;br /&gt;
&lt;br /&gt;
== Writing Entries ==&lt;br /&gt;
&lt;br /&gt;
Setting new values is similarly straightforward:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
generalGroup.writeEntry( &amp;quot;Account&amp;quot;, accountName );&lt;br /&gt;
generalGroup.writePathEntry( &amp;quot;SaveTo&amp;quot;, savePath );&lt;br /&gt;
colorGroup.writeEntry( &amp;quot;background&amp;quot;, color );&lt;br /&gt;
generalGroup.config()-&amp;gt;sync();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note the use of &amp;lt;tt&amp;gt;writePathEntry&amp;lt;/tt&amp;gt; and how the type of object we use, such as {{qt|QColor}} on line 3, dictates how the data is serialized. Additionally, once we are done writing entries, &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; must be called on the config object for it to be saved to disk. We can also simply wait for the object to be destroyed, which triggers an automatic &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; if necessary.&lt;br /&gt;
&lt;br /&gt;
== KDesktopFile: A Special Case ==&lt;br /&gt;
&lt;br /&gt;
When is a configuration file not a configuration file? When it is a [http://freedesktop.org/wiki/Standards_2fdesktop_2dentry_2dspec desktop file]. These files, which are essentially configuration files at their heart, are used  to describe entries for application menus, mimetypes, plugins and various services.&lt;br /&gt;
&lt;br /&gt;
When accessing a .desktop file, one should instead use the {{class|KDesktopFile}} class which, while a {{class|KConfig}} class offering all the capabilities described above, offers a set of methods designed to make accessing standard attributes of these files consistent and reliable.&lt;br /&gt;
&lt;br /&gt;
== Kiosk: Lockdown and User/Group Profiles ==&lt;br /&gt;
&lt;br /&gt;
KConfig provides a powerful set of lockdown and configuration definition capabilities, collectively known as &amp;quot;Kiosk&amp;quot;, that many system administrators and system integrators rely on. While most of this framework is provided transparently to the application, there is occassion when an application will want to check on the read/write status of a configuration object.&lt;br /&gt;
&lt;br /&gt;
Entries in configuration objects that are locked down using the kiosk facilities are said to be ''immutable''. An application can check for immutability of entire configuration objects, groups or keys as shown in this example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::config();&lt;br /&gt;
&lt;br /&gt;
if ( config-&amp;gt;isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;configuration object is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
KConfigGroup group(config, &amp;quot;General&amp;quot;);&lt;br /&gt;
if ( group.isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;group General is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if ( group.entryIsImmutable(&amp;quot;URL&amp;quot;) ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;URL entry in group General is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This can be useful in particular situations where an action should be taken when an item is immutable. For instance, the KDE panels will not offer configuration options to the user or allow them to otherwise change the order of applets and icons when the panel's configuration object is marked as immutable.&lt;br /&gt;
&lt;br /&gt;
== KConfig XT ==&lt;br /&gt;
&lt;br /&gt;
There is a way to make certain use cases of KConfig easier, faster and more reliable: KConfig XT. In particular, for main application or plugin configuration objects and when syncing configuration dialogs and other interfaces with these values, KConfig XT can help immensely. It also  simultaneously documents the configuration options available, which makes every sys admin and system integrator that uses KDE that much more happy.&lt;br /&gt;
&lt;br /&gt;
[[../Using_KConfig_XT|The next tutorial in the KConfig series covers what KConfig XT is and how to use it.]]&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials/KConfig_(de)</id>
		<title>Development/Tutorials/KConfig (de)</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials/KConfig_(de)"/>
				<updated>2008-01-02T13:07:57Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: /* Die KConfig Klasse */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:I18n/Language Navigation Bar|Development/Tutorials/KConfig}}&lt;br /&gt;
&lt;br /&gt;
{{TutorialBrowser (de)|&lt;br /&gt;
&lt;br /&gt;
series=KConfig|&lt;br /&gt;
&lt;br /&gt;
name=Einführung in KConfig|&lt;br /&gt;
&lt;br /&gt;
pre=Keine|&lt;br /&gt;
&lt;br /&gt;
next=[[../Using_KConfig_XT (de)|Benutzen von KConfig XT]]|&lt;br /&gt;
&lt;br /&gt;
reading=Keine&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{improve (de)}}&lt;br /&gt;
&lt;br /&gt;
== Zusammenfassung ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dieser Artikel beschäftigt sich mir dem KDE Einstellungdaten-System, angefangen mit einer Übersicht über den grundlegenden Aufbau aus der Sicht eines Entwicklers. Es wirft ausserdem einen Blick auf jede der Klassen, die für die Entwicklung von Anwendungen relevant sind und fährt dann mit kiosk (Benutzer- und Gruppenprofile) Integration fort.&lt;br /&gt;
&lt;br /&gt;
== Grundlegender Aufbau ==&lt;br /&gt;
&lt;br /&gt;
KConfig ist ausgelegt um das Konzept vom eigentlichen Speichern und Auffinden von Konfigurationsdaten hinter eine Programmierschnittstelle zu abstrahieren die es ermöglicht, auf einfache Weise Informationen abzurufen und zu setzen. Wo oder in welcher Form Daten gespeichert werden ist für eine Anwendung die KConfig benutzt irrelevant.&lt;br /&gt;
&lt;br /&gt;
Das behält alle KDE Anwendungen konsistent in ihrer Art, Konfigurationen handzuhaben und nimmt einem Anwendungs-Entwickler die Arbeit so ein System von Grund auf neu zu schreiben, was ein sehr fehleranfälliger Prozess sein kann.&lt;br /&gt;
&lt;br /&gt;
Jedes KConfig Objekt verkörpert ein einziges Konfigurationsobjekt. Jedes Konfigurationsobjekt ist durch seinen einzigartigen Namen gekennzeichnet und kann von mehreren lokalen oder externen Daten oder Services gelesen werden. Jede Anwendung hat standardmässig ein zugehöriges Konfigurationsobjekt und es gibt auch ein globales Konfigurationsobjekt.&lt;br /&gt;
&lt;br /&gt;
Diese Konfigurationsobjekte sind nach einer zweistufigen Hierarchie getrennt: Gruppen und Schlüssel. Ein Konfigurationsobjekt kann eine beliebige Anzahl an Gruppen haben und jede Gruppe kann einen oder mehrere Schlüssel mit zugehörigen Werten haben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die gespeicherten Werte können aus beliebig vielen verschiedenen Datentypen bestehen. Sie werden gespeichert und abgerufen als das Objekt selbst. Zum Beispiel wird ein {{qt|QObject}}-Objekt direkt einem Konfigurationsobjekt übergeben, wenn es einen Farbwert speichert und wenn ein Farbwert abgerufen wird, wird ein {{qt|QObject}}-Objekt zurückgegeben.&lt;br /&gt;
&lt;br /&gt;
{{note (de)| deserialization  entgliedern? &amp;lt;br&amp;gt; &amp;lt;tt&amp;gt; &amp;quot;do not have to perform serialization and deserialization of objects themselves&amp;quot; &amp;lt;/tt&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Anwendungen selbst müssen darum normalerweise Objekte nicht selber gliedern und entgliedern.&lt;br /&gt;
&lt;br /&gt;
Applications themselves therefore generally do not have to perform serialization and deserialization of objects themselves.&lt;br /&gt;
&lt;br /&gt;
== Die KConfig Klasse ==&lt;br /&gt;
&lt;br /&gt;
Das {{class|KConfig}}-Objekt wird benutzt um ein bestehendes Konfigurationsobjekt anzusteuern. Es gibt eine Reihe von Möglichkeiten ein Konfigurationsobjekt zu erstellen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
// ein einfaches, altes lesen/schreiben Konfigurationsobjekt&lt;br /&gt;
KConfig config(&amp;quot;myapprc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// eine bestimmte Datei im Dateisystem&lt;br /&gt;
// currently must be an INI style file&lt;br /&gt;
KConfig fullPath(&amp;quot;/etc/kderc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// nicht mit globalen Werten verflochten&lt;br /&gt;
KConfig globalFree( &amp;quot;localsrc&amp;quot;, KConfig::NoGlobals );&lt;br /&gt;
&lt;br /&gt;
// nicht mit globalen Werten orde der $KDEDIRS Hierarchie verflochten&lt;br /&gt;
KConfig simpleConfig( &amp;quot;simplerc&amp;quot;, KConfig::SimpleConfig );&lt;br /&gt;
&lt;br /&gt;
// Komponenten-spezifische Konfiguration, in diesem Fall ein Plugin&lt;br /&gt;
KConfig pluginConfig( componentData(), &amp;quot;pluginrc&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
// Ausserhalb der normalen Konfigurations-Ressource&lt;br /&gt;
KConfig dataResource( &amp;quot;data&amp;quot;, &amp;quot;myapp/somefile&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{note (de)|wie soll &amp;quot;merged&amp;quot; in den folgenden Fällen übersetzt werden? &amp;lt;br&amp;gt; &amp;lt;tt&amp;gt;&amp;quot;verschmolzen&amp;quot; oder &amp;quot;verflochten&amp;quot;&amp;lt;/tt&amp;gt; &amp;lt;br&amp;gt; der Anwendung selber transparent&amp;quot; tönt auch nicht sehr gut}}&lt;br /&gt;
&lt;br /&gt;
Das Kconfig Objekt, das wir auf Zeile 2 erstellen ist ein gewöhnliches Konfigurationsobjekt. Wir können Werte aus ihm lesen, neue Einträge schreiben und nach verschiedenen Eigenschaften des Objekts fragen. Dieses Objekt wird aus der Konfigurations-Ressource geladen, wie es durch {{class|KStandardDirs}} bestimmt wird, das heisst, dass jede Instanz des &amp;lt;tt&amp;gt;myapprc&amp;lt;/tt&amp;gt;-Objekts in jedem der Ordner in der Konfigurations-Ressourcen-Hierarchie verschmolzen werden um die Werte zu erzeugen, die in diesem Objekt gesehen werden. So werden Systemweite und &lt;br /&gt;
pro-Benutzer/Gruppen Profile erstellt und unterstützt. Das alles geschieht der Anwendung selber transparent.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{tip| Für mehr Informationen, wie das Verschmelzen funktioniert, siehe diesen Artikel über die [[KDE System Administration/KDE_Filesystem_Hierarchy|KDE Dateisystem Hierarchie]].}}&lt;br /&gt;
&lt;br /&gt;
{{note (de)|Ist das so gemeint mit &amp;quot;expects an INI style file&amp;quot;&amp;lt;br&amp;gt; &amp;lt;tt&amp;gt; On line 6 we open a specific local file, this case /etc/kderc. This performs no merging of values and expects an INI style file.&amp;lt;/tt&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Auf Zeile 6 öffnen wir eine bestimmte Lokale Datei, in diesem Fall {{path|/etc/kderc}}. Das führt kein verschmelzen von Werten aus und erwartet eine Datei im INI Format.&lt;br /&gt;
&lt;br /&gt;
Zeile 9 erzeugt ein Konfigurationsobjekt, dass nicht mit dem globalen &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt;-Konfigurationsobjekt verflochten ist,  während das Konfigurationsobjekt auf Zeile 12 zusätzlich mit keinem der Dateien in der &amp;lt;tt&amp;gt;$KDEDIRS&amp;lt;/tt&amp;gt;-Hierarchie verflochten ist. Das kann die Leistung spürbar verbessern, falls man einfach nur Werte aus einer einfachen Konfuguration liest und globale Werte keine Rolle spielen.&lt;br /&gt;
&lt;br /&gt;
Zeile 15 erzeugt ein Konfigurationsobjekt unter Benutzung des {{class|KComponentData}}-Objekts das zu einem Plugin oder einer anderen Komponente gehört. Das Plugin kann verschiedene Ordner aufweisen, die in seinen {{class|KStandardDirs}} definiert sind und das ist eine Möglichkeit sich zu versichern, dass {{class|KConfig}} das respektiert.&lt;br /&gt;
&lt;br /&gt;
Und schliesslich auf Zeile 18 erzeugen wir ein Konfigurationsobjekt, das nicht in der &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt;-Ressource sondern in der &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt;-Ressource existiert. Man kann kann auf diese Weise jede Ressource verwenden, von denen {{class|KStandardDirs}} Kenntnis hat, auch solche die während der Laufzeit hinzugefügt werden.&lt;br /&gt;
&lt;br /&gt;
=== Spezielle Konfigurationsobjekte ===&lt;br /&gt;
&lt;br /&gt;
Jede Anwendung hat sein eigenes Konfigurationsobjekt das den Namen benutzt, der von {{class|KAboutData}} bereitgestellt wird mit angehängtem &amp;quot;rc&amp;quot;. Also hätte eine Anwendung mit dem Namen &amp;quot;myapp&amp;quot; das Standard-Konfigurationsobjekt &amp;quot;myapprc&amp;quot;. Dieses Konfigurationsobjekt kann auf diese Weise aufgerufen werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KComponentData&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
#include &amp;lt;KGlobal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    // beachten sie, dass dies eigentlich ein KSharedConfig ist&lt;br /&gt;
    // mehr über diese Klasse siehe weiter unten&lt;br /&gt;
    KConfig* config = KGlobal::config();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Auf das Standard-Konfigurationsobjekt für die Anwendung wird zugegriffen, wenn kein Name definiert wurde, als das {{class|KConfig}}-Objekt erzeugt wurde. Also könnten wir stattdessen auch das tun:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    KConfig config;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zusätzlich könnte jede Komponente sein eigenes Konfigurationsobjekt haben. Auf dieses wird normalerweise durch die &amp;lt;tt&amp;gt;componentData()&amp;lt;/tt&amp;gt; des Plugins zugegriffen, anstatt durch die &amp;lt;tt&amp;gt;{{class|KGlobal}}::mainComponent()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Und schliesslich gibt es noch ein globales Konfigurationsobjekt, &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt;, das von jeder Anwendung verwendet wird. Es enthält Informationen wie die Standard-Tatenkombinationen für verschiedene Aktionen. Es wird in das Konfigurationsobjekt &amp;quot;gemischt&amp;quot; wenn der &amp;lt;tt&amp;gt;KConfig::IncludeGlobals&amp;lt;/tt&amp;gt; Bitschalter dem {{class|KConfig}} Konstruktor übergeben wird, was standardmässig der Fall ist.&lt;br /&gt;
&lt;br /&gt;
{{note (de)|Der Rest muss noch übersetzt werden}}&lt;br /&gt;
&lt;br /&gt;
=== Commonly Useful Methods ===&lt;br /&gt;
&lt;br /&gt;
To save the current state of the configuration object we call the &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; method. This method is also called when the object is destroyed. If no changes have been made or the resource reports itself as non-writable (such as in the case of the user not having write permissions to the file) then no disk activity occurs. &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; merges changes performed concurrently by other processes - local changes have priority, though.&lt;br /&gt;
&lt;br /&gt;
If we want to make sure that we have the latest values from disk we can call &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt; which calls &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; and then reloads the data from disk.&lt;br /&gt;
&lt;br /&gt;
If we need to prevent the config object from saving already made modifications to disk we need to call &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt;. A particular use case for this is rolling back the configuration to the on-disk state by calling &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt; followed by &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Listing all groups in a configuration object is as simple as calling &amp;lt;tt&amp;gt;groupList()&amp;lt;/tt&amp;gt; as in this code snippet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::mainComponent().config();&lt;br /&gt;
&lt;br /&gt;
foreach ( const QString&amp;amp; group, config.groupList() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;next group:&amp;quot; &amp;lt;&amp;lt; group;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== KSharedConfig ==&lt;br /&gt;
&lt;br /&gt;
The {{class|KSharedConfig}} class is a reference counted version of {{class|KConfig}}. It thus provides a way to reference the same configuration object from multiple places in your application without the extra overhead of separate objects or concerns about syncronizing writes to disk even if the configuration object is updated from multiple code paths. &lt;br /&gt;
&lt;br /&gt;
Accessing a {{class|KSharedConfig}} object is as easy as this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KSharedConfigPtr config = KSharedConfig::openConfig();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;openConfig()&amp;lt;/tt&amp;gt; take the same parameters as {{class|KConfig}}'s constructors do, allowing one to define which configuration file to open, flags to control merging and non-&amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; resources.&lt;br /&gt;
&lt;br /&gt;
{{class|KSharedConfig}} is generally recommended over using {{class|KConfig}} itself, and the object returned from {{class|KComponentData}} is indeed a {{class|KSharedConfig}} object.&lt;br /&gt;
&lt;br /&gt;
== KConfigGroup ==&lt;br /&gt;
&lt;br /&gt;
Now that we have a configuration object, the next step is to actually use it. The first thing we must do is to define which group of key/value pairs we wish to access in the object. We do this by creating a KConfigGroup object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig config;&lt;br /&gt;
KConfigGroup generalGroup( &amp;amp;config, &amp;quot;General&amp;quot; );&lt;br /&gt;
KConfigGroup colorsGroup = config.group( &amp;quot;Colors&amp;quot; ); // ... or a bit differently ...&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can pass {{class|KConfig}} or {{class|KSharedConfig}} objects to {{class|KConfigGroup}}.&lt;br /&gt;
&lt;br /&gt;
Config groups can be nested as well:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfigGroup subGroup1( &amp;amp;generalGroup, &amp;quot;LessGeneral&amp;quot; );&lt;br /&gt;
KConfigGroup subGroup2 = colorsGroup.group( &amp;quot;Dialogs&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Reading Entries ==&lt;br /&gt;
&lt;br /&gt;
With a {{class|KConfigGroup}} object in hand reading entries is now quite straight forward:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
QString accountName = generalGroup.readEntry( &amp;quot;Account&amp;quot;,&lt;br /&gt;
                                              QString() );&lt;br /&gt;
QColor color = colorsGroup.readEntry( &amp;quot;background&amp;quot;,&lt;br /&gt;
                                      Qt::white );&lt;br /&gt;
QStringList list = generalGroup.readEntry( &amp;quot;List&amp;quot;,&lt;br /&gt;
                                           QStringList() );&lt;br /&gt;
QString path = generalGroup.readPathEntry( &amp;quot;SaveTo&amp;quot;,&lt;br /&gt;
                                           defaultPath );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As can be seen from the above, you can mix reads from different {{class|KConfigGroup}} objects created on the same {{class|KConfig}} object. The read methods take the key, which is case sensitive, as the first argument and the default value as the second argument. This argument controls what kind of data, e.g. a color in line 3 above, is to be expected as well as the type of object returned. The returned object is wrapped in a {{qt|QVariant}} to make this magic happen.&lt;br /&gt;
&lt;br /&gt;
There are a couple of special read methods, including &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; which returns a file system path. It is vital that one uses &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; if it is a path as this enables such features as roaming profiles to work properly.&lt;br /&gt;
&lt;br /&gt;
If no such key currently exists in the configuration object, the default value is returned instead. If there is a localized (e.g. translated into another language) entry for the key that matches the current locale, that is returned.&lt;br /&gt;
&lt;br /&gt;
== Writing Entries ==&lt;br /&gt;
&lt;br /&gt;
Setting new values is similarly straightforward:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
generalGroup.writeEntry( &amp;quot;Account&amp;quot;, accountName );&lt;br /&gt;
generalGroup.writePathEntry( &amp;quot;SaveTo&amp;quot;, savePath );&lt;br /&gt;
colorGroup.writeEntry( &amp;quot;background&amp;quot;, color );&lt;br /&gt;
generalGroup.config()-&amp;gt;sync();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note the use of &amp;lt;tt&amp;gt;writePathEntry&amp;lt;/tt&amp;gt; and how the type of object we use, such as {{qt|QColor}} on line 3, dictates how the data is serialized. Additionally, once we are done writing entries, &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; must be called on the config object for it to be saved to disk. We can also simply wait for the object to be destroyed, which triggers an automatic &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; if necessary.&lt;br /&gt;
&lt;br /&gt;
== KDesktopFile: A Special Case ==&lt;br /&gt;
&lt;br /&gt;
When is a configuration file not a configuration file? When it is a [http://freedesktop.org/wiki/Standards_2fdesktop_2dentry_2dspec desktop file]. These files, which are essentially configuration files at their heart, are used  to describe entries for application menus, mimetypes, plugins and various services.&lt;br /&gt;
&lt;br /&gt;
When accessing a .desktop file, one should instead use the {{class|KDesktopFile}} class which, while a {{class|KConfig}} class offering all the capabilities described above, offers a set of methods designed to make accessing standard attributes of these files consistent and reliable.&lt;br /&gt;
&lt;br /&gt;
== Kiosk: Lockdown and User/Group Profiles ==&lt;br /&gt;
&lt;br /&gt;
KConfig provides a powerful set of lockdown and configuration definition capabilities, collectively known as &amp;quot;Kiosk&amp;quot;, that many system administrators and system integrators rely on. While most of this framework is provided transparently to the application, there is occassion when an application will want to check on the read/write status of a configuration object.&lt;br /&gt;
&lt;br /&gt;
Entries in configuration objects that are locked down using the kiosk facilities are said to be ''immutable''. An application can check for immutability of entire configuration objects, groups or keys as shown in this example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::config();&lt;br /&gt;
&lt;br /&gt;
if ( config-&amp;gt;isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;configuration object is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
KConfigGroup group(config, &amp;quot;General&amp;quot;);&lt;br /&gt;
if ( group.isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;group General is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if ( group.entryIsImmutable(&amp;quot;URL&amp;quot;) ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;URL entry in group General is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This can be useful in particular situations where an action should be taken when an item is immutable. For instance, the KDE panels will not offer configuration options to the user or allow them to otherwise change the order of applets and icons when the panel's configuration object is marked as immutable.&lt;br /&gt;
&lt;br /&gt;
== KConfig XT ==&lt;br /&gt;
&lt;br /&gt;
There is a way to make certain use cases of KConfig easier, faster and more reliable: KConfig XT. In particular, for main application or plugin configuration objects and when syncing configuration dialogs and other interfaces with these values, KConfig XT can help immensely. It also  simultaneously documents the configuration options available, which makes every sys admin and system integrator that uses KDE that much more happy.&lt;br /&gt;
&lt;br /&gt;
[[../Using_KConfig_XT|The next tutorial in the KConfig series covers what KConfig XT is and how to use it.]]&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials/KConfig_(de)</id>
		<title>Development/Tutorials/KConfig (de)</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials/KConfig_(de)"/>
				<updated>2008-01-02T12:30:14Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: /* Die KConfig Klasse */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:I18n/Language Navigation Bar|Development/Tutorials/KConfig}}&lt;br /&gt;
&lt;br /&gt;
{{TutorialBrowser (de)|&lt;br /&gt;
&lt;br /&gt;
series=KConfig|&lt;br /&gt;
&lt;br /&gt;
name=Einführung in KConfig|&lt;br /&gt;
&lt;br /&gt;
pre=Keine|&lt;br /&gt;
&lt;br /&gt;
next=[[../Using_KConfig_XT (de)|Benutzen von KConfig XT]]|&lt;br /&gt;
&lt;br /&gt;
reading=Keine&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{improve (de)}}&lt;br /&gt;
&lt;br /&gt;
== Zusammenfassung ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dieser Artikel beschäftigt sich mir dem KDE Einstellungdaten-System, angefangen mit einer Übersicht über den grundlegenden Aufbau aus der Sicht eines Entwicklers. Es wirft ausserdem einen Blick auf jede der Klassen, die für die Entwicklung von Anwendungen relevant sind und fährt dann mit kiosk (Benutzer- und Gruppenprofile) Integration fort.&lt;br /&gt;
&lt;br /&gt;
== Grundlegender Aufbau ==&lt;br /&gt;
&lt;br /&gt;
KConfig ist ausgelegt um das Konzept vom eigentlichen Speichern und Auffinden von Konfigurationsdaten hinter eine Programmierschnittstelle zu abstrahieren die es ermöglicht, auf einfache Weise Informationen abzurufen und zu setzen. Wo oder in welcher Form Daten gespeichert werden ist für eine Anwendung die KConfig benutzt irrelevant.&lt;br /&gt;
&lt;br /&gt;
Das behält alle KDE Anwendungen konsistent in ihrer Art, Konfigurationen handzuhaben und nimmt einem Anwendungs-Entwickler die Arbeit so ein System von Grund auf neu zu schreiben, was ein sehr fehleranfälliger Prozess sein kann.&lt;br /&gt;
&lt;br /&gt;
Jedes KConfig Objekt verkörpert ein einziges Konfigurationsobjekt. Jedes Konfigurationsobjekt ist durch seinen einzigartigen Namen gekennzeichnet und kann von mehreren lokalen oder externen Daten oder Services gelesen werden. Jede Anwendung hat standardmässig ein zugehöriges Konfigurationsobjekt und es gibt auch ein globales Konfigurationsobjekt.&lt;br /&gt;
&lt;br /&gt;
Diese Konfigurationsobjekte sind nach einer zweistufigen Hierarchie getrennt: Gruppen und Schlüssel. Ein Konfigurationsobjekt kann eine beliebige Anzahl an Gruppen haben und jede Gruppe kann einen oder mehrere Schlüssel mit zugehörigen Werten haben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die gespeicherten Werte können aus beliebig vielen verschiedenen Datentypen bestehen. Sie werden gespeichert und abgerufen als das Objekt selbst. Zum Beispiel wird ein {{qt|QObject}}-Objekt direkt einem Konfigurationsobjekt übergeben, wenn es einen Farbwert speichert und wenn ein Farbwert abgerufen wird, wird ein {{qt|QObject}}-Objekt zurückgegeben.&lt;br /&gt;
&lt;br /&gt;
{{note (de)| deserialization  entgliedern? &amp;lt;br&amp;gt; &amp;lt;tt&amp;gt; &amp;quot;do not have to perform serialization and deserialization of objects themselves&amp;quot; &amp;lt;/tt&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Anwendungen selbst müssen darum normalerweise Objekte nicht selber gliedern und entgliedern.&lt;br /&gt;
&lt;br /&gt;
Applications themselves therefore generally do not have to perform serialization and deserialization of objects themselves.&lt;br /&gt;
&lt;br /&gt;
== Die KConfig Klasse ==&lt;br /&gt;
&lt;br /&gt;
Das {{class|KConfig}}-Objekt wird benutzt um ein bestehendes Konfigurationsobjekt anzusteuern. Es gibt eine Reihe von Möglichkeiten ein Konfigurationsobjekt zu erstellen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
// ein einfaches, altes lesen/schreiben Konfigurationsobjekt&lt;br /&gt;
KConfig config(&amp;quot;myapprc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// eine bestimmte Datei im Dateisystem&lt;br /&gt;
// currently must be an INI style file&lt;br /&gt;
KConfig fullPath(&amp;quot;/etc/kderc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// nicht mit globalen Werten verflochten&lt;br /&gt;
KConfig globalFree( &amp;quot;localsrc&amp;quot;, KConfig::NoGlobals );&lt;br /&gt;
&lt;br /&gt;
// nicht mit globalen Werten orde der $KDEDIRS Hierarchie verflochten&lt;br /&gt;
KConfig simpleConfig( &amp;quot;simplerc&amp;quot;, KConfig::SimpleConfig );&lt;br /&gt;
&lt;br /&gt;
// Komponenten-spezifische Konfiguration, in diesem Fall ein Plugin&lt;br /&gt;
KConfig pluginConfig( componentData(), &amp;quot;pluginrc&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
// Ausserhalb der normalen Konfigurations-Ressource&lt;br /&gt;
KConfig dataResource( &amp;quot;data&amp;quot;, &amp;quot;myapp/somefile&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{note (de)|wie soll &amp;quot;merged&amp;quot; in den folgenden Fällen übersetzt werden? &amp;lt;br&amp;gt; &amp;lt;tt&amp;gt;&amp;quot;verschmolzen&amp;quot; oder &amp;quot;verflochten&amp;quot;&amp;lt;/tt&amp;gt; &amp;lt;br&amp;gt; der Anwendung selber transparent&amp;quot; tönt auch nicht sehr gut}}&lt;br /&gt;
&lt;br /&gt;
Das Kconfig Objekt, das wir auf Zeile 2 erstellen ist ein gewöhnliches Konfigurationsobjekt. Wir können Werte aus ihm lesen, neue Einträge schreiben und nach verschiedenen Eigenschaften des Objekts fragen. Dieses Objekt wird aus der Konfigurations-Ressource geladen, wie es durch {{class|KStandardDirs}} bestimmt wird, das heisst, dass jede Instanz des &amp;lt;tt&amp;gt;myapprc&amp;lt;/tt&amp;gt;-Objekts in jedem der Ordner in der Konfigurations-Ressourcen-Hierarchie verschmolzen werden um die Werte zu erzeugen, die in diesem Objekt gesehen werden. So werden Systemweite und &lt;br /&gt;
pro-Benutzer/Gruppen Profile erstellt und unterstützt. Das alles geschieht der Anwendung selber transparent.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{tip| Für mehr Informationen, wie das Verschmelzen funktioniert, siehe diesen Artikel über die [[KDE System Administration/KDE_Filesystem_Hierarchy|KDE Dateisystem Hierarchie]].}}&lt;br /&gt;
&lt;br /&gt;
{{note (de)|Ist das so gemeint mit &amp;quot;expects an INI style file&amp;quot;&amp;lt;br&amp;gt; &amp;lt;tt&amp;gt; On line 6 we open a specific local file, this case /etc/kderc. This performs no merging of values and expects an INI style file.&amp;lt;/tt&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Auf Zeile 6 öffnen wir eine bestimmte Lokale Datei, in diesem Fall {{path|/etc/kderc}}. Das führt kein verschmelzen von Werten aus und erwartet eine Datei im INI Format.&lt;br /&gt;
&lt;br /&gt;
Zeile 9 erzeugt ein Konfigurationsobjekt, dass nicht mit dem globalen &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt;-Konfigurationsobjekt verflochten ist,  während das Konfigurationsobjekt auf Zeile 12 zusätzlich mit keinem der Dateien in der &amp;lt;tt&amp;gt;$KDEDIRS&amp;lt;/tt&amp;gt;-Hierarchie verflochten ist. Das kann die Leistung spürbar verbessern, falls man einfach nur Werte aus einer einfachen Konfuguration liest und globale Werte keine Rolle spielen.&lt;br /&gt;
&lt;br /&gt;
Zeile 15 erzeugt ein Konfigurationsobjekt unter Benutzung des {{class|KComponentData}}-Objekts das zu einem Plugin oder einer anderen Komponente gehört. Das Plugin kann verschiedene Ordner haben, die in seinen {{class|KStandardDirs}} definiert sind und das ist eine Möglichkeit sich zu versichern, dass {{class|KConfig}} das respektiert.&lt;br /&gt;
&lt;br /&gt;
Und schliesslich auf Zeile 18 erzeugen wir ein Konfigurationsobjekt, das nicht in der &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt;-Ressource sondern in der &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt;-Ressource existiert. Man kann kann auf diese Weise jede Ressource verwenden, von denen {{class|KStandardDirs}} weiss, auch solche die während der Laufzeit hinzugefügt werden.&lt;br /&gt;
&lt;br /&gt;
{{note (de)|Der Rest muss noch übersetzt werden}}&lt;br /&gt;
&lt;br /&gt;
=== Special Configuration Objects ===&lt;br /&gt;
&lt;br /&gt;
Each application has its own configuration object that uses the name provided to {{class|KAboutData}} appended with &amp;quot;rc&amp;quot; as its name. So an app named &amp;quot;myapp&amp;quot; would have the default configuration object of &amp;quot;myapprc&amp;quot;. This configuration file can be retrieved in this way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KComponentData&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
#include &amp;lt;KGlobal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    // note that this is actually a KSharedConfig&lt;br /&gt;
    // more on that class in a bit!&lt;br /&gt;
    KConfig* config = KGlobal::config();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The default configuration object for the application is accessed when no name is specified when creating a {{class|KConfig}} object. So we could also do this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    KConfig config;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additionally, each component may have its own configuration object. This is generally accessed via the plugin's &amp;lt;tt&amp;gt;componentData()&amp;lt;/tt&amp;gt; rather than &amp;lt;tt&amp;gt;{{class|KGlobal}}::mainComponent()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Finally there is a global configuration object, &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt;, that is shared by every application. It holds such information as the default application shortcuts for various actions. It is &amp;quot;blended&amp;quot; into the configuration object if the &amp;lt;tt&amp;gt;KConfig::IncludeGlobals&amp;lt;/tt&amp;gt; flag is passed to the {{class|KConfig}} constructor, which is the default.&lt;br /&gt;
&lt;br /&gt;
=== Commonly Useful Methods ===&lt;br /&gt;
&lt;br /&gt;
To save the current state of the configuration object we call the &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; method. This method is also called when the object is destroyed. If no changes have been made or the resource reports itself as non-writable (such as in the case of the user not having write permissions to the file) then no disk activity occurs. &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; merges changes performed concurrently by other processes - local changes have priority, though.&lt;br /&gt;
&lt;br /&gt;
If we want to make sure that we have the latest values from disk we can call &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt; which calls &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; and then reloads the data from disk.&lt;br /&gt;
&lt;br /&gt;
If we need to prevent the config object from saving already made modifications to disk we need to call &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt;. A particular use case for this is rolling back the configuration to the on-disk state by calling &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt; followed by &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Listing all groups in a configuration object is as simple as calling &amp;lt;tt&amp;gt;groupList()&amp;lt;/tt&amp;gt; as in this code snippet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::mainComponent().config();&lt;br /&gt;
&lt;br /&gt;
foreach ( const QString&amp;amp; group, config.groupList() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;next group:&amp;quot; &amp;lt;&amp;lt; group;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== KSharedConfig ==&lt;br /&gt;
&lt;br /&gt;
The {{class|KSharedConfig}} class is a reference counted version of {{class|KConfig}}. It thus provides a way to reference the same configuration object from multiple places in your application without the extra overhead of separate objects or concerns about syncronizing writes to disk even if the configuration object is updated from multiple code paths. &lt;br /&gt;
&lt;br /&gt;
Accessing a {{class|KSharedConfig}} object is as easy as this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KSharedConfigPtr config = KSharedConfig::openConfig();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;openConfig()&amp;lt;/tt&amp;gt; take the same parameters as {{class|KConfig}}'s constructors do, allowing one to define which configuration file to open, flags to control merging and non-&amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; resources.&lt;br /&gt;
&lt;br /&gt;
{{class|KSharedConfig}} is generally recommended over using {{class|KConfig}} itself, and the object returned from {{class|KComponentData}} is indeed a {{class|KSharedConfig}} object.&lt;br /&gt;
&lt;br /&gt;
== KConfigGroup ==&lt;br /&gt;
&lt;br /&gt;
Now that we have a configuration object, the next step is to actually use it. The first thing we must do is to define which group of key/value pairs we wish to access in the object. We do this by creating a KConfigGroup object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig config;&lt;br /&gt;
KConfigGroup generalGroup( &amp;amp;config, &amp;quot;General&amp;quot; );&lt;br /&gt;
KConfigGroup colorsGroup = config.group( &amp;quot;Colors&amp;quot; ); // ... or a bit differently ...&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can pass {{class|KConfig}} or {{class|KSharedConfig}} objects to {{class|KConfigGroup}}.&lt;br /&gt;
&lt;br /&gt;
Config groups can be nested as well:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfigGroup subGroup1( &amp;amp;generalGroup, &amp;quot;LessGeneral&amp;quot; );&lt;br /&gt;
KConfigGroup subGroup2 = colorsGroup.group( &amp;quot;Dialogs&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Reading Entries ==&lt;br /&gt;
&lt;br /&gt;
With a {{class|KConfigGroup}} object in hand reading entries is now quite straight forward:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
QString accountName = generalGroup.readEntry( &amp;quot;Account&amp;quot;,&lt;br /&gt;
                                              QString() );&lt;br /&gt;
QColor color = colorsGroup.readEntry( &amp;quot;background&amp;quot;,&lt;br /&gt;
                                      Qt::white );&lt;br /&gt;
QStringList list = generalGroup.readEntry( &amp;quot;List&amp;quot;,&lt;br /&gt;
                                           QStringList() );&lt;br /&gt;
QString path = generalGroup.readPathEntry( &amp;quot;SaveTo&amp;quot;,&lt;br /&gt;
                                           defaultPath );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As can be seen from the above, you can mix reads from different {{class|KConfigGroup}} objects created on the same {{class|KConfig}} object. The read methods take the key, which is case sensitive, as the first argument and the default value as the second argument. This argument controls what kind of data, e.g. a color in line 3 above, is to be expected as well as the type of object returned. The returned object is wrapped in a {{qt|QVariant}} to make this magic happen.&lt;br /&gt;
&lt;br /&gt;
There are a couple of special read methods, including &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; which returns a file system path. It is vital that one uses &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; if it is a path as this enables such features as roaming profiles to work properly.&lt;br /&gt;
&lt;br /&gt;
If no such key currently exists in the configuration object, the default value is returned instead. If there is a localized (e.g. translated into another language) entry for the key that matches the current locale, that is returned.&lt;br /&gt;
&lt;br /&gt;
== Writing Entries ==&lt;br /&gt;
&lt;br /&gt;
Setting new values is similarly straightforward:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
generalGroup.writeEntry( &amp;quot;Account&amp;quot;, accountName );&lt;br /&gt;
generalGroup.writePathEntry( &amp;quot;SaveTo&amp;quot;, savePath );&lt;br /&gt;
colorGroup.writeEntry( &amp;quot;background&amp;quot;, color );&lt;br /&gt;
generalGroup.config()-&amp;gt;sync();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note the use of &amp;lt;tt&amp;gt;writePathEntry&amp;lt;/tt&amp;gt; and how the type of object we use, such as {{qt|QColor}} on line 3, dictates how the data is serialized. Additionally, once we are done writing entries, &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; must be called on the config object for it to be saved to disk. We can also simply wait for the object to be destroyed, which triggers an automatic &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; if necessary.&lt;br /&gt;
&lt;br /&gt;
== KDesktopFile: A Special Case ==&lt;br /&gt;
&lt;br /&gt;
When is a configuration file not a configuration file? When it is a [http://freedesktop.org/wiki/Standards_2fdesktop_2dentry_2dspec desktop file]. These files, which are essentially configuration files at their heart, are used  to describe entries for application menus, mimetypes, plugins and various services.&lt;br /&gt;
&lt;br /&gt;
When accessing a .desktop file, one should instead use the {{class|KDesktopFile}} class which, while a {{class|KConfig}} class offering all the capabilities described above, offers a set of methods designed to make accessing standard attributes of these files consistent and reliable.&lt;br /&gt;
&lt;br /&gt;
== Kiosk: Lockdown and User/Group Profiles ==&lt;br /&gt;
&lt;br /&gt;
KConfig provides a powerful set of lockdown and configuration definition capabilities, collectively known as &amp;quot;Kiosk&amp;quot;, that many system administrators and system integrators rely on. While most of this framework is provided transparently to the application, there is occassion when an application will want to check on the read/write status of a configuration object.&lt;br /&gt;
&lt;br /&gt;
Entries in configuration objects that are locked down using the kiosk facilities are said to be ''immutable''. An application can check for immutability of entire configuration objects, groups or keys as shown in this example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::config();&lt;br /&gt;
&lt;br /&gt;
if ( config-&amp;gt;isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;configuration object is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
KConfigGroup group(config, &amp;quot;General&amp;quot;);&lt;br /&gt;
if ( group.isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;group General is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if ( group.entryIsImmutable(&amp;quot;URL&amp;quot;) ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;URL entry in group General is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This can be useful in particular situations where an action should be taken when an item is immutable. For instance, the KDE panels will not offer configuration options to the user or allow them to otherwise change the order of applets and icons when the panel's configuration object is marked as immutable.&lt;br /&gt;
&lt;br /&gt;
== KConfig XT ==&lt;br /&gt;
&lt;br /&gt;
There is a way to make certain use cases of KConfig easier, faster and more reliable: KConfig XT. In particular, for main application or plugin configuration objects and when syncing configuration dialogs and other interfaces with these values, KConfig XT can help immensely. It also  simultaneously documents the configuration options available, which makes every sys admin and system integrator that uses KDE that much more happy.&lt;br /&gt;
&lt;br /&gt;
[[../Using_KConfig_XT|The next tutorial in the KConfig series covers what KConfig XT is and how to use it.]]&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials/KConfig_(de)</id>
		<title>Development/Tutorials/KConfig (de)</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials/KConfig_(de)"/>
				<updated>2008-01-01T23:46:21Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: /* Die KConfig Klasse */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:I18n/Language Navigation Bar|Development/Tutorials/KConfig}}&lt;br /&gt;
&lt;br /&gt;
{{TutorialBrowser (de)|&lt;br /&gt;
&lt;br /&gt;
series=KConfig|&lt;br /&gt;
&lt;br /&gt;
name=Einführung in KConfig|&lt;br /&gt;
&lt;br /&gt;
pre=Keine|&lt;br /&gt;
&lt;br /&gt;
next=[[../Using_KConfig_XT (de)|Benutzen von KConfig XT]]|&lt;br /&gt;
&lt;br /&gt;
reading=Keine&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{improve (de)}}&lt;br /&gt;
&lt;br /&gt;
== Zusammenfassung ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dieser Artikel beschäftigt sich mir dem KDE Einstellungdaten-System, angefangen mit einer Übersicht über den grundlegenden Aufbau aus der Sicht eines Entwicklers. Es wirft ausserdem einen Blick auf jede der Klassen, die für die Entwicklung von Anwendungen relevant sind und fährt dann mit kiosk (Benutzer- und Gruppenprofile) Integration fort.&lt;br /&gt;
&lt;br /&gt;
== Grundlegender Aufbau ==&lt;br /&gt;
&lt;br /&gt;
KConfig ist ausgelegt um das Konzept vom eigentlichen Speichern und Auffinden von Konfigurationsdaten hinter eine Programmierschnittstelle zu abstrahieren die es ermöglicht, auf einfache Weise Informationen abzurufen und zu setzen. Wo oder in welcher Form Daten gespeichert werden ist für eine Anwendung die KConfig benutzt irrelevant.&lt;br /&gt;
&lt;br /&gt;
Das behält alle KDE Anwendungen konsistent in ihrer Art, Konfigurationen handzuhaben und nimmt einem Anwendungs-Entwickler die Arbeit so ein System von Grund auf neu zu schreiben, was ein sehr fehleranfälliger Prozess sein kann.&lt;br /&gt;
&lt;br /&gt;
Jedes KConfig Objekt verkörpert ein einziges Konfigurationsobjekt. Jedes Konfigurationsobjekt ist durch seinen einzigartigen Namen gekennzeichnet und kann von mehreren lokalen oder externen Daten oder Services gelesen werden. Jede Anwendung hat standardmässig ein zugehöriges Konfigurationsobjekt und es gibt auch ein globales Konfigurationsobjekt.&lt;br /&gt;
&lt;br /&gt;
Diese Konfigurationsobjekte sind nach einer zweistufigen Hierarchie getrennt: Gruppen und Schlüssel. Ein Konfigurationsobjekt kann eine beliebige Anzahl an Gruppen haben und jede Gruppe kann einen oder mehrere Schlüssel mit zugehörigen Werten haben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die gespeicherten Werte können aus beliebig vielen verschiedenen Datentypen bestehen. Sie werden gespeichert und abgerufen als das Objekt selbst. Zum Beispiel wird ein {{qt|QObject}}-Objekt direkt einem Konfigurationsobjekt übergeben, wenn es einen Farbwert speichert und wenn ein Farbwert abgerufen wird, wird ein {{qt|QObject}}-Objekt zurückgegeben.&lt;br /&gt;
&lt;br /&gt;
{{note (de)| deserialization  entgliedern? &amp;lt;br&amp;gt; &amp;lt;tt&amp;gt; &amp;quot;do not have to perform serialization and deserialization of objects themselves&amp;quot; &amp;lt;/tt&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Anwendungen selbst müssen darum normalerweise Objekte nicht selber gliedern und entgliedern.&lt;br /&gt;
&lt;br /&gt;
Applications themselves therefore generally do not have to perform serialization and deserialization of objects themselves.&lt;br /&gt;
&lt;br /&gt;
== Die KConfig Klasse ==&lt;br /&gt;
&lt;br /&gt;
Das {{class|KConfig}}-Objekt wird benutzt um ein bestehendes Konfigurationsobjekt anzusteuern. Es gibt eine Reihe von Möglichkeiten ein Konfigurationsobjekt zu erstellen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
// ein einfaches, altes lesen/schreiben Konfigurationsobjekt&lt;br /&gt;
KConfig config(&amp;quot;myapprc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// eine bestimmte Datei im Dateisystem&lt;br /&gt;
// currently must be an INI style file&lt;br /&gt;
KConfig fullPath(&amp;quot;/etc/kderc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// nicht mit globalen Werten verflochten&lt;br /&gt;
KConfig globalFree( &amp;quot;localsrc&amp;quot;, KConfig::NoGlobals );&lt;br /&gt;
&lt;br /&gt;
// nicht mit globalen Werten orde der $KDEDIRS Hierarchie verflochten&lt;br /&gt;
KConfig simpleConfig( &amp;quot;simplerc&amp;quot;, KConfig::SimpleConfig );&lt;br /&gt;
&lt;br /&gt;
// Komponenten-spezifische Konfiguration, in diesem Fall ein Plugin&lt;br /&gt;
KConfig pluginConfig( componentData(), &amp;quot;pluginrc&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
// Ausserhalb der normalen Konfigurations-Ressource&lt;br /&gt;
KConfig dataResource( &amp;quot;data&amp;quot;, &amp;quot;myapp/somefile&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{note (de)|&amp;quot;der Anwendung selber transparent&amp;quot; tönt nicht sehr gut}}&lt;br /&gt;
&lt;br /&gt;
Das Kconfig Objekt, das wir auf Zeile 2 erstellen ist ein gewöhnliches Konfigurationsobjekt. Wir können Werte aus ihm lesen, neue Einträge schreiben und nach verschiedenen Eigenschaften des Objekts fragen. Dieses Objekt wird aus der Konfigurations-Ressource geladen, wie es durch {{class|KStandardDirs}} bestimmt wird, das heisst, dass jede Instanz des &amp;lt;tt&amp;gt;myapprc&amp;lt;/tt&amp;gt;-Objekts in jedem der Ordner in der Konfigurations-Ressourcen-Hierarchie verschmolzen werden um die Werte zu erzeugen, die in diesem Objekt gesehen werden. So werden Systemweite und &lt;br /&gt;
pro-Benutzer/Gruppen Profile erstellt und unterstützt. Das alles geschieht der Anwendung selber transparent.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{tip| Für mehr Informationen, wie das Verschmelzen funktioniert, siehe diesen Artikel über die [[KDE System Administration/KDE_Filesystem_Hierarchy|KDE Dateisystem Hierarchie]].}}&lt;br /&gt;
&lt;br /&gt;
{{note (de)|Ist das so gemeint mit &amp;quot;expects an INI style file&amp;quot;&amp;lt;br&amp;gt; &amp;lt;tt&amp;gt; On line 6 we open a specific local file, this case /etc/kderc. This performs no merging of values and expects an INI style file.&amp;lt;/tt&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Auf Zeile 6 öffnen wir eine bestimmte Lokale Datei, in diesem Fall {{path|/etc/kderc}}. Das führt kein verschmelzen von Werten aus und erwartet eine Datei im INI Format.&lt;br /&gt;
&lt;br /&gt;
{{note (de)|Der Rest muss noch übersetzt werden}}&lt;br /&gt;
&lt;br /&gt;
Line 9 sees the creation of a configuration object that is not merged with the global &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt; configuration object, while the configuration file on line 12 is additionally not merged with any files in the &amp;lt;tt&amp;gt;$KDEDIRS&amp;lt;/tt&amp;gt; hierarchy. This can noticeably improve performance in the case where one is simply reading values out of a simple configuration for which global values are not meaningful.&lt;br /&gt;
&lt;br /&gt;
Line 15 creates a configuration object using the {{class|KComponentData}} object that belongs to a plugin or other component. The plugin may have a different set of directories defined in its {{class|KStandardDirs}} and this is a way of ensuring that {{class|KConfig}} respects this.&lt;br /&gt;
&lt;br /&gt;
Finally on line 18 we see the creation of a configuration object that does not exist in the &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; resource but rather in the application &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; resource. You may use any resource that {{class|KStandardDirs}} is aware of, including ones that are added at runtime.&lt;br /&gt;
&lt;br /&gt;
=== Special Configuration Objects ===&lt;br /&gt;
&lt;br /&gt;
Each application has its own configuration object that uses the name provided to {{class|KAboutData}} appended with &amp;quot;rc&amp;quot; as its name. So an app named &amp;quot;myapp&amp;quot; would have the default configuration object of &amp;quot;myapprc&amp;quot;. This configuration file can be retrieved in this way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KComponentData&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
#include &amp;lt;KGlobal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    // note that this is actually a KSharedConfig&lt;br /&gt;
    // more on that class in a bit!&lt;br /&gt;
    KConfig* config = KGlobal::config();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The default configuration object for the application is accessed when no name is specified when creating a {{class|KConfig}} object. So we could also do this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    KConfig config;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additionally, each component may have its own configuration object. This is generally accessed via the plugin's &amp;lt;tt&amp;gt;componentData()&amp;lt;/tt&amp;gt; rather than &amp;lt;tt&amp;gt;{{class|KGlobal}}::mainComponent()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Finally there is a global configuration object, &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt;, that is shared by every application. It holds such information as the default application shortcuts for various actions. It is &amp;quot;blended&amp;quot; into the configuration object if the &amp;lt;tt&amp;gt;KConfig::IncludeGlobals&amp;lt;/tt&amp;gt; flag is passed to the {{class|KConfig}} constructor, which is the default.&lt;br /&gt;
&lt;br /&gt;
=== Commonly Useful Methods ===&lt;br /&gt;
&lt;br /&gt;
To save the current state of the configuration object we call the &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; method. This method is also called when the object is destroyed. If no changes have been made or the resource reports itself as non-writable (such as in the case of the user not having write permissions to the file) then no disk activity occurs. &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; merges changes performed concurrently by other processes - local changes have priority, though.&lt;br /&gt;
&lt;br /&gt;
If we want to make sure that we have the latest values from disk we can call &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt; which calls &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; and then reloads the data from disk.&lt;br /&gt;
&lt;br /&gt;
If we need to prevent the config object from saving already made modifications to disk we need to call &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt;. A particular use case for this is rolling back the configuration to the on-disk state by calling &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt; followed by &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Listing all groups in a configuration object is as simple as calling &amp;lt;tt&amp;gt;groupList()&amp;lt;/tt&amp;gt; as in this code snippet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::mainComponent().config();&lt;br /&gt;
&lt;br /&gt;
foreach ( const QString&amp;amp; group, config.groupList() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;next group:&amp;quot; &amp;lt;&amp;lt; group;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== KSharedConfig ==&lt;br /&gt;
&lt;br /&gt;
The {{class|KSharedConfig}} class is a reference counted version of {{class|KConfig}}. It thus provides a way to reference the same configuration object from multiple places in your application without the extra overhead of separate objects or concerns about syncronizing writes to disk even if the configuration object is updated from multiple code paths. &lt;br /&gt;
&lt;br /&gt;
Accessing a {{class|KSharedConfig}} object is as easy as this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KSharedConfigPtr config = KSharedConfig::openConfig();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;openConfig()&amp;lt;/tt&amp;gt; take the same parameters as {{class|KConfig}}'s constructors do, allowing one to define which configuration file to open, flags to control merging and non-&amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; resources.&lt;br /&gt;
&lt;br /&gt;
{{class|KSharedConfig}} is generally recommended over using {{class|KConfig}} itself, and the object returned from {{class|KComponentData}} is indeed a {{class|KSharedConfig}} object.&lt;br /&gt;
&lt;br /&gt;
== KConfigGroup ==&lt;br /&gt;
&lt;br /&gt;
Now that we have a configuration object, the next step is to actually use it. The first thing we must do is to define which group of key/value pairs we wish to access in the object. We do this by creating a KConfigGroup object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig config;&lt;br /&gt;
KConfigGroup generalGroup( &amp;amp;config, &amp;quot;General&amp;quot; );&lt;br /&gt;
KConfigGroup colorsGroup = config.group( &amp;quot;Colors&amp;quot; ); // ... or a bit differently ...&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can pass {{class|KConfig}} or {{class|KSharedConfig}} objects to {{class|KConfigGroup}}.&lt;br /&gt;
&lt;br /&gt;
Config groups can be nested as well:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfigGroup subGroup1( &amp;amp;generalGroup, &amp;quot;LessGeneral&amp;quot; );&lt;br /&gt;
KConfigGroup subGroup2 = colorsGroup.group( &amp;quot;Dialogs&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Reading Entries ==&lt;br /&gt;
&lt;br /&gt;
With a {{class|KConfigGroup}} object in hand reading entries is now quite straight forward:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
QString accountName = generalGroup.readEntry( &amp;quot;Account&amp;quot;,&lt;br /&gt;
                                              QString() );&lt;br /&gt;
QColor color = colorsGroup.readEntry( &amp;quot;background&amp;quot;,&lt;br /&gt;
                                      Qt::white );&lt;br /&gt;
QStringList list = generalGroup.readEntry( &amp;quot;List&amp;quot;,&lt;br /&gt;
                                           QStringList() );&lt;br /&gt;
QString path = generalGroup.readPathEntry( &amp;quot;SaveTo&amp;quot;,&lt;br /&gt;
                                           defaultPath );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As can be seen from the above, you can mix reads from different {{class|KConfigGroup}} objects created on the same {{class|KConfig}} object. The read methods take the key, which is case sensitive, as the first argument and the default value as the second argument. This argument controls what kind of data, e.g. a color in line 3 above, is to be expected as well as the type of object returned. The returned object is wrapped in a {{qt|QVariant}} to make this magic happen.&lt;br /&gt;
&lt;br /&gt;
There are a couple of special read methods, including &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; which returns a file system path. It is vital that one uses &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; if it is a path as this enables such features as roaming profiles to work properly.&lt;br /&gt;
&lt;br /&gt;
If no such key currently exists in the configuration object, the default value is returned instead. If there is a localized (e.g. translated into another language) entry for the key that matches the current locale, that is returned.&lt;br /&gt;
&lt;br /&gt;
== Writing Entries ==&lt;br /&gt;
&lt;br /&gt;
Setting new values is similarly straightforward:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
generalGroup.writeEntry( &amp;quot;Account&amp;quot;, accountName );&lt;br /&gt;
generalGroup.writePathEntry( &amp;quot;SaveTo&amp;quot;, savePath );&lt;br /&gt;
colorGroup.writeEntry( &amp;quot;background&amp;quot;, color );&lt;br /&gt;
generalGroup.config()-&amp;gt;sync();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note the use of &amp;lt;tt&amp;gt;writePathEntry&amp;lt;/tt&amp;gt; and how the type of object we use, such as {{qt|QColor}} on line 3, dictates how the data is serialized. Additionally, once we are done writing entries, &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; must be called on the config object for it to be saved to disk. We can also simply wait for the object to be destroyed, which triggers an automatic &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; if necessary.&lt;br /&gt;
&lt;br /&gt;
== KDesktopFile: A Special Case ==&lt;br /&gt;
&lt;br /&gt;
When is a configuration file not a configuration file? When it is a [http://freedesktop.org/wiki/Standards_2fdesktop_2dentry_2dspec desktop file]. These files, which are essentially configuration files at their heart, are used  to describe entries for application menus, mimetypes, plugins and various services.&lt;br /&gt;
&lt;br /&gt;
When accessing a .desktop file, one should instead use the {{class|KDesktopFile}} class which, while a {{class|KConfig}} class offering all the capabilities described above, offers a set of methods designed to make accessing standard attributes of these files consistent and reliable.&lt;br /&gt;
&lt;br /&gt;
== Kiosk: Lockdown and User/Group Profiles ==&lt;br /&gt;
&lt;br /&gt;
KConfig provides a powerful set of lockdown and configuration definition capabilities, collectively known as &amp;quot;Kiosk&amp;quot;, that many system administrators and system integrators rely on. While most of this framework is provided transparently to the application, there is occassion when an application will want to check on the read/write status of a configuration object.&lt;br /&gt;
&lt;br /&gt;
Entries in configuration objects that are locked down using the kiosk facilities are said to be ''immutable''. An application can check for immutability of entire configuration objects, groups or keys as shown in this example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::config();&lt;br /&gt;
&lt;br /&gt;
if ( config-&amp;gt;isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;configuration object is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
KConfigGroup group(config, &amp;quot;General&amp;quot;);&lt;br /&gt;
if ( group.isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;group General is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if ( group.entryIsImmutable(&amp;quot;URL&amp;quot;) ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;URL entry in group General is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This can be useful in particular situations where an action should be taken when an item is immutable. For instance, the KDE panels will not offer configuration options to the user or allow them to otherwise change the order of applets and icons when the panel's configuration object is marked as immutable.&lt;br /&gt;
&lt;br /&gt;
== KConfig XT ==&lt;br /&gt;
&lt;br /&gt;
There is a way to make certain use cases of KConfig easier, faster and more reliable: KConfig XT. In particular, for main application or plugin configuration objects and when syncing configuration dialogs and other interfaces with these values, KConfig XT can help immensely. It also  simultaneously documents the configuration options available, which makes every sys admin and system integrator that uses KDE that much more happy.&lt;br /&gt;
&lt;br /&gt;
[[../Using_KConfig_XT|The next tutorial in the KConfig series covers what KConfig XT is and how to use it.]]&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials/KConfig_(de)</id>
		<title>Development/Tutorials/KConfig (de)</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials/KConfig_(de)"/>
				<updated>2008-01-01T23:45:47Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: /* Grundlegender Aufbau */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:I18n/Language Navigation Bar|Development/Tutorials/KConfig}}&lt;br /&gt;
&lt;br /&gt;
{{TutorialBrowser (de)|&lt;br /&gt;
&lt;br /&gt;
series=KConfig|&lt;br /&gt;
&lt;br /&gt;
name=Einführung in KConfig|&lt;br /&gt;
&lt;br /&gt;
pre=Keine|&lt;br /&gt;
&lt;br /&gt;
next=[[../Using_KConfig_XT (de)|Benutzen von KConfig XT]]|&lt;br /&gt;
&lt;br /&gt;
reading=Keine&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{improve (de)}}&lt;br /&gt;
&lt;br /&gt;
== Zusammenfassung ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dieser Artikel beschäftigt sich mir dem KDE Einstellungdaten-System, angefangen mit einer Übersicht über den grundlegenden Aufbau aus der Sicht eines Entwicklers. Es wirft ausserdem einen Blick auf jede der Klassen, die für die Entwicklung von Anwendungen relevant sind und fährt dann mit kiosk (Benutzer- und Gruppenprofile) Integration fort.&lt;br /&gt;
&lt;br /&gt;
== Grundlegender Aufbau ==&lt;br /&gt;
&lt;br /&gt;
KConfig ist ausgelegt um das Konzept vom eigentlichen Speichern und Auffinden von Konfigurationsdaten hinter eine Programmierschnittstelle zu abstrahieren die es ermöglicht, auf einfache Weise Informationen abzurufen und zu setzen. Wo oder in welcher Form Daten gespeichert werden ist für eine Anwendung die KConfig benutzt irrelevant.&lt;br /&gt;
&lt;br /&gt;
Das behält alle KDE Anwendungen konsistent in ihrer Art, Konfigurationen handzuhaben und nimmt einem Anwendungs-Entwickler die Arbeit so ein System von Grund auf neu zu schreiben, was ein sehr fehleranfälliger Prozess sein kann.&lt;br /&gt;
&lt;br /&gt;
Jedes KConfig Objekt verkörpert ein einziges Konfigurationsobjekt. Jedes Konfigurationsobjekt ist durch seinen einzigartigen Namen gekennzeichnet und kann von mehreren lokalen oder externen Daten oder Services gelesen werden. Jede Anwendung hat standardmässig ein zugehöriges Konfigurationsobjekt und es gibt auch ein globales Konfigurationsobjekt.&lt;br /&gt;
&lt;br /&gt;
Diese Konfigurationsobjekte sind nach einer zweistufigen Hierarchie getrennt: Gruppen und Schlüssel. Ein Konfigurationsobjekt kann eine beliebige Anzahl an Gruppen haben und jede Gruppe kann einen oder mehrere Schlüssel mit zugehörigen Werten haben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die gespeicherten Werte können aus beliebig vielen verschiedenen Datentypen bestehen. Sie werden gespeichert und abgerufen als das Objekt selbst. Zum Beispiel wird ein {{qt|QObject}}-Objekt direkt einem Konfigurationsobjekt übergeben, wenn es einen Farbwert speichert und wenn ein Farbwert abgerufen wird, wird ein {{qt|QObject}}-Objekt zurückgegeben.&lt;br /&gt;
&lt;br /&gt;
{{note (de)| deserialization  entgliedern? &amp;lt;br&amp;gt; &amp;lt;tt&amp;gt; &amp;quot;do not have to perform serialization and deserialization of objects themselves&amp;quot; &amp;lt;/tt&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Anwendungen selbst müssen darum normalerweise Objekte nicht selber gliedern und entgliedern.&lt;br /&gt;
&lt;br /&gt;
Applications themselves therefore generally do not have to perform serialization and deserialization of objects themselves.&lt;br /&gt;
&lt;br /&gt;
== Die KConfig Klasse ==&lt;br /&gt;
&lt;br /&gt;
Das {{class|KConfig}}-Objekt wird benutzt um ein bestehendes Konfigurationsobjekt anzusteuern. Es gibt eine Reihe von Möglichkeiten ein Konfigurationsobjekt zu erstellen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
// ein einfaches, altes lesen/schreiben Konfigurationsobjekt&lt;br /&gt;
KConfig config(&amp;quot;myapprc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// eine bestimmte Datei im Dateisystem&lt;br /&gt;
// currently must be an INI style file&lt;br /&gt;
KConfig fullPath(&amp;quot;/etc/kderc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// nicht mit globalen Werten verflochten&lt;br /&gt;
KConfig globalFree( &amp;quot;localsrc&amp;quot;, KConfig::NoGlobals );&lt;br /&gt;
&lt;br /&gt;
// nicht mit globalen Werten orde der $KDEDIRS Hierarchie verflochten&lt;br /&gt;
KConfig simpleConfig( &amp;quot;simplerc&amp;quot;, KConfig::SimpleConfig );&lt;br /&gt;
&lt;br /&gt;
// Komponenten-spezifische Konfiguration, in diesem Fall ein Plugin&lt;br /&gt;
KConfig pluginConfig( componentData(), &amp;quot;pluginrc&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
// Ausserhalb der normalen Konfigurations-Ressource&lt;br /&gt;
KConfig dataResource( &amp;quot;data&amp;quot;, &amp;quot;myapp/somefile&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{note (de)|&amp;quot;der Anwendung selber transparent&amp;quot; tönt nicht sehr gut}}&lt;br /&gt;
&lt;br /&gt;
Das Kconfig Objekt, das wir auf Zeile 2 erstellen ist ein gewöhnliches Konfigurationsobjekt. Wir können Werte aus ihm lesen, neue Einträge schreiben und nach verschiedenen Eigenschaften des Objekts fragen. Dieses Objekt wird aus der Konfigurations-Ressource geladen, wie es durch {{class|KStandardDirs}} bestimmt wird, das heisst, dass jede Instanz des &amp;lt;tt&amp;gt;myapprc&amp;lt;/tt&amp;gt;-Objekts in jedem der Ordner in der Konfigurations-Ressourcen-Hierarchie verschmolzen werden um die Werte zu erzeugen, die in diesem Objekt gesehen werden. So werden Systemweite und &lt;br /&gt;
pro-Benutzer/Gruppen Profile erstellt und unterstützt. Das alles geschieht der Anwendung selber transparent.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{tip| Für mehr Informationen, wie das Verschmelzen funktioniert, siehe diesen Artikel über die [[KDE System Administration/KDE_Filesystem_Hierarchy|KDE Dateisystem Hierarchie]].}}&lt;br /&gt;
&lt;br /&gt;
{{note (de)|Ist das so gemeint mit &amp;quot;expects an INI style file&amp;quot;&amp;lt;br&amp;gt; &amp;lt;tt&amp;gt; On line 6 we open a specific local file, this case /etc/kderc. This performs no merging of values and expects an INI style file.&amp;lt;/tt&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Auf Zeile 6 öffnen wir eine bestimmte Lokale Datei, in diesem Fall {{path|/etc/kderc}. Das führt kein verschmelzen von Werten aus und erwartet eine Datei im INI Format.&lt;br /&gt;
&lt;br /&gt;
{{note (de)|Der Rest muss noch übersetzt werden}}&lt;br /&gt;
&lt;br /&gt;
Line 9 sees the creation of a configuration object that is not merged with the global &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt; configuration object, while the configuration file on line 12 is additionally not merged with any files in the &amp;lt;tt&amp;gt;$KDEDIRS&amp;lt;/tt&amp;gt; hierarchy. This can noticeably improve performance in the case where one is simply reading values out of a simple configuration for which global values are not meaningful.&lt;br /&gt;
&lt;br /&gt;
Line 15 creates a configuration object using the {{class|KComponentData}} object that belongs to a plugin or other component. The plugin may have a different set of directories defined in its {{class|KStandardDirs}} and this is a way of ensuring that {{class|KConfig}} respects this.&lt;br /&gt;
&lt;br /&gt;
Finally on line 18 we see the creation of a configuration object that does not exist in the &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; resource but rather in the application &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; resource. You may use any resource that {{class|KStandardDirs}} is aware of, including ones that are added at runtime.&lt;br /&gt;
&lt;br /&gt;
=== Special Configuration Objects ===&lt;br /&gt;
&lt;br /&gt;
Each application has its own configuration object that uses the name provided to {{class|KAboutData}} appended with &amp;quot;rc&amp;quot; as its name. So an app named &amp;quot;myapp&amp;quot; would have the default configuration object of &amp;quot;myapprc&amp;quot;. This configuration file can be retrieved in this way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KComponentData&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
#include &amp;lt;KGlobal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    // note that this is actually a KSharedConfig&lt;br /&gt;
    // more on that class in a bit!&lt;br /&gt;
    KConfig* config = KGlobal::config();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The default configuration object for the application is accessed when no name is specified when creating a {{class|KConfig}} object. So we could also do this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    KConfig config;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additionally, each component may have its own configuration object. This is generally accessed via the plugin's &amp;lt;tt&amp;gt;componentData()&amp;lt;/tt&amp;gt; rather than &amp;lt;tt&amp;gt;{{class|KGlobal}}::mainComponent()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Finally there is a global configuration object, &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt;, that is shared by every application. It holds such information as the default application shortcuts for various actions. It is &amp;quot;blended&amp;quot; into the configuration object if the &amp;lt;tt&amp;gt;KConfig::IncludeGlobals&amp;lt;/tt&amp;gt; flag is passed to the {{class|KConfig}} constructor, which is the default.&lt;br /&gt;
&lt;br /&gt;
=== Commonly Useful Methods ===&lt;br /&gt;
&lt;br /&gt;
To save the current state of the configuration object we call the &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; method. This method is also called when the object is destroyed. If no changes have been made or the resource reports itself as non-writable (such as in the case of the user not having write permissions to the file) then no disk activity occurs. &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; merges changes performed concurrently by other processes - local changes have priority, though.&lt;br /&gt;
&lt;br /&gt;
If we want to make sure that we have the latest values from disk we can call &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt; which calls &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; and then reloads the data from disk.&lt;br /&gt;
&lt;br /&gt;
If we need to prevent the config object from saving already made modifications to disk we need to call &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt;. A particular use case for this is rolling back the configuration to the on-disk state by calling &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt; followed by &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Listing all groups in a configuration object is as simple as calling &amp;lt;tt&amp;gt;groupList()&amp;lt;/tt&amp;gt; as in this code snippet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::mainComponent().config();&lt;br /&gt;
&lt;br /&gt;
foreach ( const QString&amp;amp; group, config.groupList() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;next group:&amp;quot; &amp;lt;&amp;lt; group;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== KSharedConfig ==&lt;br /&gt;
&lt;br /&gt;
The {{class|KSharedConfig}} class is a reference counted version of {{class|KConfig}}. It thus provides a way to reference the same configuration object from multiple places in your application without the extra overhead of separate objects or concerns about syncronizing writes to disk even if the configuration object is updated from multiple code paths. &lt;br /&gt;
&lt;br /&gt;
Accessing a {{class|KSharedConfig}} object is as easy as this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KSharedConfigPtr config = KSharedConfig::openConfig();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;openConfig()&amp;lt;/tt&amp;gt; take the same parameters as {{class|KConfig}}'s constructors do, allowing one to define which configuration file to open, flags to control merging and non-&amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; resources.&lt;br /&gt;
&lt;br /&gt;
{{class|KSharedConfig}} is generally recommended over using {{class|KConfig}} itself, and the object returned from {{class|KComponentData}} is indeed a {{class|KSharedConfig}} object.&lt;br /&gt;
&lt;br /&gt;
== KConfigGroup ==&lt;br /&gt;
&lt;br /&gt;
Now that we have a configuration object, the next step is to actually use it. The first thing we must do is to define which group of key/value pairs we wish to access in the object. We do this by creating a KConfigGroup object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig config;&lt;br /&gt;
KConfigGroup generalGroup( &amp;amp;config, &amp;quot;General&amp;quot; );&lt;br /&gt;
KConfigGroup colorsGroup = config.group( &amp;quot;Colors&amp;quot; ); // ... or a bit differently ...&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can pass {{class|KConfig}} or {{class|KSharedConfig}} objects to {{class|KConfigGroup}}.&lt;br /&gt;
&lt;br /&gt;
Config groups can be nested as well:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfigGroup subGroup1( &amp;amp;generalGroup, &amp;quot;LessGeneral&amp;quot; );&lt;br /&gt;
KConfigGroup subGroup2 = colorsGroup.group( &amp;quot;Dialogs&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Reading Entries ==&lt;br /&gt;
&lt;br /&gt;
With a {{class|KConfigGroup}} object in hand reading entries is now quite straight forward:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
QString accountName = generalGroup.readEntry( &amp;quot;Account&amp;quot;,&lt;br /&gt;
                                              QString() );&lt;br /&gt;
QColor color = colorsGroup.readEntry( &amp;quot;background&amp;quot;,&lt;br /&gt;
                                      Qt::white );&lt;br /&gt;
QStringList list = generalGroup.readEntry( &amp;quot;List&amp;quot;,&lt;br /&gt;
                                           QStringList() );&lt;br /&gt;
QString path = generalGroup.readPathEntry( &amp;quot;SaveTo&amp;quot;,&lt;br /&gt;
                                           defaultPath );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As can be seen from the above, you can mix reads from different {{class|KConfigGroup}} objects created on the same {{class|KConfig}} object. The read methods take the key, which is case sensitive, as the first argument and the default value as the second argument. This argument controls what kind of data, e.g. a color in line 3 above, is to be expected as well as the type of object returned. The returned object is wrapped in a {{qt|QVariant}} to make this magic happen.&lt;br /&gt;
&lt;br /&gt;
There are a couple of special read methods, including &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; which returns a file system path. It is vital that one uses &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; if it is a path as this enables such features as roaming profiles to work properly.&lt;br /&gt;
&lt;br /&gt;
If no such key currently exists in the configuration object, the default value is returned instead. If there is a localized (e.g. translated into another language) entry for the key that matches the current locale, that is returned.&lt;br /&gt;
&lt;br /&gt;
== Writing Entries ==&lt;br /&gt;
&lt;br /&gt;
Setting new values is similarly straightforward:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
generalGroup.writeEntry( &amp;quot;Account&amp;quot;, accountName );&lt;br /&gt;
generalGroup.writePathEntry( &amp;quot;SaveTo&amp;quot;, savePath );&lt;br /&gt;
colorGroup.writeEntry( &amp;quot;background&amp;quot;, color );&lt;br /&gt;
generalGroup.config()-&amp;gt;sync();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note the use of &amp;lt;tt&amp;gt;writePathEntry&amp;lt;/tt&amp;gt; and how the type of object we use, such as {{qt|QColor}} on line 3, dictates how the data is serialized. Additionally, once we are done writing entries, &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; must be called on the config object for it to be saved to disk. We can also simply wait for the object to be destroyed, which triggers an automatic &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; if necessary.&lt;br /&gt;
&lt;br /&gt;
== KDesktopFile: A Special Case ==&lt;br /&gt;
&lt;br /&gt;
When is a configuration file not a configuration file? When it is a [http://freedesktop.org/wiki/Standards_2fdesktop_2dentry_2dspec desktop file]. These files, which are essentially configuration files at their heart, are used  to describe entries for application menus, mimetypes, plugins and various services.&lt;br /&gt;
&lt;br /&gt;
When accessing a .desktop file, one should instead use the {{class|KDesktopFile}} class which, while a {{class|KConfig}} class offering all the capabilities described above, offers a set of methods designed to make accessing standard attributes of these files consistent and reliable.&lt;br /&gt;
&lt;br /&gt;
== Kiosk: Lockdown and User/Group Profiles ==&lt;br /&gt;
&lt;br /&gt;
KConfig provides a powerful set of lockdown and configuration definition capabilities, collectively known as &amp;quot;Kiosk&amp;quot;, that many system administrators and system integrators rely on. While most of this framework is provided transparently to the application, there is occassion when an application will want to check on the read/write status of a configuration object.&lt;br /&gt;
&lt;br /&gt;
Entries in configuration objects that are locked down using the kiosk facilities are said to be ''immutable''. An application can check for immutability of entire configuration objects, groups or keys as shown in this example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::config();&lt;br /&gt;
&lt;br /&gt;
if ( config-&amp;gt;isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;configuration object is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
KConfigGroup group(config, &amp;quot;General&amp;quot;);&lt;br /&gt;
if ( group.isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;group General is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if ( group.entryIsImmutable(&amp;quot;URL&amp;quot;) ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;URL entry in group General is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This can be useful in particular situations where an action should be taken when an item is immutable. For instance, the KDE panels will not offer configuration options to the user or allow them to otherwise change the order of applets and icons when the panel's configuration object is marked as immutable.&lt;br /&gt;
&lt;br /&gt;
== KConfig XT ==&lt;br /&gt;
&lt;br /&gt;
There is a way to make certain use cases of KConfig easier, faster and more reliable: KConfig XT. In particular, for main application or plugin configuration objects and when syncing configuration dialogs and other interfaces with these values, KConfig XT can help immensely. It also  simultaneously documents the configuration options available, which makes every sys admin and system integrator that uses KDE that much more happy.&lt;br /&gt;
&lt;br /&gt;
[[../Using_KConfig_XT|The next tutorial in the KConfig series covers what KConfig XT is and how to use it.]]&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials/KConfig_(de)</id>
		<title>Development/Tutorials/KConfig (de)</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials/KConfig_(de)"/>
				<updated>2008-01-01T23:44:20Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: /* Grundlegender Aufbau */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:I18n/Language Navigation Bar|Development/Tutorials/KConfig}}&lt;br /&gt;
&lt;br /&gt;
{{TutorialBrowser (de)|&lt;br /&gt;
&lt;br /&gt;
series=KConfig|&lt;br /&gt;
&lt;br /&gt;
name=Einführung in KConfig|&lt;br /&gt;
&lt;br /&gt;
pre=Keine|&lt;br /&gt;
&lt;br /&gt;
next=[[../Using_KConfig_XT (de)|Benutzen von KConfig XT]]|&lt;br /&gt;
&lt;br /&gt;
reading=Keine&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{improve (de)}}&lt;br /&gt;
&lt;br /&gt;
== Zusammenfassung ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dieser Artikel beschäftigt sich mir dem KDE Einstellungdaten-System, angefangen mit einer Übersicht über den grundlegenden Aufbau aus der Sicht eines Entwicklers. Es wirft ausserdem einen Blick auf jede der Klassen, die für die Entwicklung von Anwendungen relevant sind und fährt dann mit kiosk (Benutzer- und Gruppenprofile) Integration fort.&lt;br /&gt;
&lt;br /&gt;
== Grundlegender Aufbau ==&lt;br /&gt;
&lt;br /&gt;
KConfig ist ausgelegt um das Konzept vom eigentlichen Speichern und Auffinden von Konfigurationsdaten hinter eine Programmierschnittstelle zu abstrahieren die es ermöglicht, auf einfache Weise Informationen abzurufen und zu setzen. Wo oder in welcher Form Daten gespeichert werden ist für eine Anwendung die KConfig benutzt irrelevant.&lt;br /&gt;
&lt;br /&gt;
Das behält alle KDE Anwendungen konsistent in ihrer Art, Konfigurationen handzuhaben und nimmt einem Anwendungs-Entwickler die Arbeit so ein System von Grund auf neu zu schreiben, was ein sehr fehleranfälliger Prozess sein kann.&lt;br /&gt;
&lt;br /&gt;
Jedes KConfig Objekt verkörpert ein einziges Konfigurationsobjekt. Jedes Konfigurationsobjekt ist durch seinen einzigartigen Namen gekennzeichnet und kann von mehreren lokalen oder externen Daten oder Services gelesen werden. Jede Anwendung hat standardmässig ein zugehöriges Konfigurationsobjekt und es gibt auch ein globales Konfigurationsobjekt.&lt;br /&gt;
&lt;br /&gt;
Diese Konfigurationsobjekte sind nach einer zweistufigen Hierarchie getrennt: Gruppen und Schlüssel. Ein Konfigurationsobjekt kann eine beliebige Anzahl an Gruppen haben und jede Gruppe kann einen oder mehrere Schlüssel mit zugehörigen Werten haben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die gespeicherten Werte können aus beliebig vielen verschiedenen Datentypen bestehen. Sie werden gespeichert und abgerufen als das Objekt selbst. Zum Beispiel wird ein {{qt|QObject}}-Objekt direkt einem Konfigurationsobjekt übergeben, wenn es einen Farbwert speichert und wenn ein Farbwert abgerufen wird, wird ein {{qt|QObject}}-Objekt zurückgegeben.&lt;br /&gt;
&lt;br /&gt;
{{note (de)| deserialization? &amp;lt;tt&amp;gt;  do not have to perform serialization and deserialization of objects themselves &amp;lt;/tt&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Anwendungen selbst müssen darum normalerweise Objekte nicht selber gliedern und entgliedern.&lt;br /&gt;
&lt;br /&gt;
Applications themselves therefore generally do not have to perform serialization and deserialization of objects themselves.&lt;br /&gt;
&lt;br /&gt;
== Die KConfig Klasse ==&lt;br /&gt;
&lt;br /&gt;
Das {{class|KConfig}}-Objekt wird benutzt um ein bestehendes Konfigurationsobjekt anzusteuern. Es gibt eine Reihe von Möglichkeiten ein Konfigurationsobjekt zu erstellen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
// ein einfaches, altes lesen/schreiben Konfigurationsobjekt&lt;br /&gt;
KConfig config(&amp;quot;myapprc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// eine bestimmte Datei im Dateisystem&lt;br /&gt;
// currently must be an INI style file&lt;br /&gt;
KConfig fullPath(&amp;quot;/etc/kderc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// nicht mit globalen Werten verflochten&lt;br /&gt;
KConfig globalFree( &amp;quot;localsrc&amp;quot;, KConfig::NoGlobals );&lt;br /&gt;
&lt;br /&gt;
// nicht mit globalen Werten orde der $KDEDIRS Hierarchie verflochten&lt;br /&gt;
KConfig simpleConfig( &amp;quot;simplerc&amp;quot;, KConfig::SimpleConfig );&lt;br /&gt;
&lt;br /&gt;
// Komponenten-spezifische Konfiguration, in diesem Fall ein Plugin&lt;br /&gt;
KConfig pluginConfig( componentData(), &amp;quot;pluginrc&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
// Ausserhalb der normalen Konfigurations-Ressource&lt;br /&gt;
KConfig dataResource( &amp;quot;data&amp;quot;, &amp;quot;myapp/somefile&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{note (de)|&amp;quot;der Anwendung selber transparent&amp;quot; tönt nicht sehr gut}}&lt;br /&gt;
&lt;br /&gt;
Das Kconfig Objekt, das wir auf Zeile 2 erstellen ist ein gewöhnliches Konfigurationsobjekt. Wir können Werte aus ihm lesen, neue Einträge schreiben und nach verschiedenen Eigenschaften des Objekts fragen. Dieses Objekt wird aus der Konfigurations-Ressource geladen, wie es durch {{class|KStandardDirs}} bestimmt wird, das heisst, dass jede Instanz des &amp;lt;tt&amp;gt;myapprc&amp;lt;/tt&amp;gt;-Objekts in jedem der Ordner in der Konfigurations-Ressourcen-Hierarchie verschmolzen werden um die Werte zu erzeugen, die in diesem Objekt gesehen werden. So werden Systemweite und &lt;br /&gt;
pro-Benutzer/Gruppen Profile erstellt und unterstützt. Das alles geschieht der Anwendung selber transparent.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{tip| Für mehr Informationen, wie das Verschmelzen funktioniert, siehe diesen Artikel über die [[KDE System Administration/KDE_Filesystem_Hierarchy|KDE Dateisystem Hierarchie]].}}&lt;br /&gt;
&lt;br /&gt;
{{note (de)|Ist das so gemeint mit &amp;quot;expects an INI style file&amp;quot;&amp;lt;br&amp;gt; &amp;lt;tt&amp;gt; On line 6 we open a specific local file, this case /etc/kderc. This performs no merging of values and expects an INI style file.&amp;lt;/tt&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Auf Zeile 6 öffnen wir eine bestimmte Lokale Datei, in diesem Fall {{path|/etc/kderc}. Das führt kein verschmelzen von Werten aus und erwartet eine Datei im INI Format.&lt;br /&gt;
&lt;br /&gt;
{{note (de)|Der Rest muss noch übersetzt werden}}&lt;br /&gt;
&lt;br /&gt;
Line 9 sees the creation of a configuration object that is not merged with the global &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt; configuration object, while the configuration file on line 12 is additionally not merged with any files in the &amp;lt;tt&amp;gt;$KDEDIRS&amp;lt;/tt&amp;gt; hierarchy. This can noticeably improve performance in the case where one is simply reading values out of a simple configuration for which global values are not meaningful.&lt;br /&gt;
&lt;br /&gt;
Line 15 creates a configuration object using the {{class|KComponentData}} object that belongs to a plugin or other component. The plugin may have a different set of directories defined in its {{class|KStandardDirs}} and this is a way of ensuring that {{class|KConfig}} respects this.&lt;br /&gt;
&lt;br /&gt;
Finally on line 18 we see the creation of a configuration object that does not exist in the &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; resource but rather in the application &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; resource. You may use any resource that {{class|KStandardDirs}} is aware of, including ones that are added at runtime.&lt;br /&gt;
&lt;br /&gt;
=== Special Configuration Objects ===&lt;br /&gt;
&lt;br /&gt;
Each application has its own configuration object that uses the name provided to {{class|KAboutData}} appended with &amp;quot;rc&amp;quot; as its name. So an app named &amp;quot;myapp&amp;quot; would have the default configuration object of &amp;quot;myapprc&amp;quot;. This configuration file can be retrieved in this way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KComponentData&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
#include &amp;lt;KGlobal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    // note that this is actually a KSharedConfig&lt;br /&gt;
    // more on that class in a bit!&lt;br /&gt;
    KConfig* config = KGlobal::config();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The default configuration object for the application is accessed when no name is specified when creating a {{class|KConfig}} object. So we could also do this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    KConfig config;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additionally, each component may have its own configuration object. This is generally accessed via the plugin's &amp;lt;tt&amp;gt;componentData()&amp;lt;/tt&amp;gt; rather than &amp;lt;tt&amp;gt;{{class|KGlobal}}::mainComponent()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Finally there is a global configuration object, &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt;, that is shared by every application. It holds such information as the default application shortcuts for various actions. It is &amp;quot;blended&amp;quot; into the configuration object if the &amp;lt;tt&amp;gt;KConfig::IncludeGlobals&amp;lt;/tt&amp;gt; flag is passed to the {{class|KConfig}} constructor, which is the default.&lt;br /&gt;
&lt;br /&gt;
=== Commonly Useful Methods ===&lt;br /&gt;
&lt;br /&gt;
To save the current state of the configuration object we call the &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; method. This method is also called when the object is destroyed. If no changes have been made or the resource reports itself as non-writable (such as in the case of the user not having write permissions to the file) then no disk activity occurs. &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; merges changes performed concurrently by other processes - local changes have priority, though.&lt;br /&gt;
&lt;br /&gt;
If we want to make sure that we have the latest values from disk we can call &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt; which calls &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; and then reloads the data from disk.&lt;br /&gt;
&lt;br /&gt;
If we need to prevent the config object from saving already made modifications to disk we need to call &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt;. A particular use case for this is rolling back the configuration to the on-disk state by calling &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt; followed by &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Listing all groups in a configuration object is as simple as calling &amp;lt;tt&amp;gt;groupList()&amp;lt;/tt&amp;gt; as in this code snippet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::mainComponent().config();&lt;br /&gt;
&lt;br /&gt;
foreach ( const QString&amp;amp; group, config.groupList() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;next group:&amp;quot; &amp;lt;&amp;lt; group;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== KSharedConfig ==&lt;br /&gt;
&lt;br /&gt;
The {{class|KSharedConfig}} class is a reference counted version of {{class|KConfig}}. It thus provides a way to reference the same configuration object from multiple places in your application without the extra overhead of separate objects or concerns about syncronizing writes to disk even if the configuration object is updated from multiple code paths. &lt;br /&gt;
&lt;br /&gt;
Accessing a {{class|KSharedConfig}} object is as easy as this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KSharedConfigPtr config = KSharedConfig::openConfig();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;openConfig()&amp;lt;/tt&amp;gt; take the same parameters as {{class|KConfig}}'s constructors do, allowing one to define which configuration file to open, flags to control merging and non-&amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; resources.&lt;br /&gt;
&lt;br /&gt;
{{class|KSharedConfig}} is generally recommended over using {{class|KConfig}} itself, and the object returned from {{class|KComponentData}} is indeed a {{class|KSharedConfig}} object.&lt;br /&gt;
&lt;br /&gt;
== KConfigGroup ==&lt;br /&gt;
&lt;br /&gt;
Now that we have a configuration object, the next step is to actually use it. The first thing we must do is to define which group of key/value pairs we wish to access in the object. We do this by creating a KConfigGroup object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig config;&lt;br /&gt;
KConfigGroup generalGroup( &amp;amp;config, &amp;quot;General&amp;quot; );&lt;br /&gt;
KConfigGroup colorsGroup = config.group( &amp;quot;Colors&amp;quot; ); // ... or a bit differently ...&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can pass {{class|KConfig}} or {{class|KSharedConfig}} objects to {{class|KConfigGroup}}.&lt;br /&gt;
&lt;br /&gt;
Config groups can be nested as well:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfigGroup subGroup1( &amp;amp;generalGroup, &amp;quot;LessGeneral&amp;quot; );&lt;br /&gt;
KConfigGroup subGroup2 = colorsGroup.group( &amp;quot;Dialogs&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Reading Entries ==&lt;br /&gt;
&lt;br /&gt;
With a {{class|KConfigGroup}} object in hand reading entries is now quite straight forward:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
QString accountName = generalGroup.readEntry( &amp;quot;Account&amp;quot;,&lt;br /&gt;
                                              QString() );&lt;br /&gt;
QColor color = colorsGroup.readEntry( &amp;quot;background&amp;quot;,&lt;br /&gt;
                                      Qt::white );&lt;br /&gt;
QStringList list = generalGroup.readEntry( &amp;quot;List&amp;quot;,&lt;br /&gt;
                                           QStringList() );&lt;br /&gt;
QString path = generalGroup.readPathEntry( &amp;quot;SaveTo&amp;quot;,&lt;br /&gt;
                                           defaultPath );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As can be seen from the above, you can mix reads from different {{class|KConfigGroup}} objects created on the same {{class|KConfig}} object. The read methods take the key, which is case sensitive, as the first argument and the default value as the second argument. This argument controls what kind of data, e.g. a color in line 3 above, is to be expected as well as the type of object returned. The returned object is wrapped in a {{qt|QVariant}} to make this magic happen.&lt;br /&gt;
&lt;br /&gt;
There are a couple of special read methods, including &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; which returns a file system path. It is vital that one uses &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; if it is a path as this enables such features as roaming profiles to work properly.&lt;br /&gt;
&lt;br /&gt;
If no such key currently exists in the configuration object, the default value is returned instead. If there is a localized (e.g. translated into another language) entry for the key that matches the current locale, that is returned.&lt;br /&gt;
&lt;br /&gt;
== Writing Entries ==&lt;br /&gt;
&lt;br /&gt;
Setting new values is similarly straightforward:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
generalGroup.writeEntry( &amp;quot;Account&amp;quot;, accountName );&lt;br /&gt;
generalGroup.writePathEntry( &amp;quot;SaveTo&amp;quot;, savePath );&lt;br /&gt;
colorGroup.writeEntry( &amp;quot;background&amp;quot;, color );&lt;br /&gt;
generalGroup.config()-&amp;gt;sync();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note the use of &amp;lt;tt&amp;gt;writePathEntry&amp;lt;/tt&amp;gt; and how the type of object we use, such as {{qt|QColor}} on line 3, dictates how the data is serialized. Additionally, once we are done writing entries, &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; must be called on the config object for it to be saved to disk. We can also simply wait for the object to be destroyed, which triggers an automatic &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; if necessary.&lt;br /&gt;
&lt;br /&gt;
== KDesktopFile: A Special Case ==&lt;br /&gt;
&lt;br /&gt;
When is a configuration file not a configuration file? When it is a [http://freedesktop.org/wiki/Standards_2fdesktop_2dentry_2dspec desktop file]. These files, which are essentially configuration files at their heart, are used  to describe entries for application menus, mimetypes, plugins and various services.&lt;br /&gt;
&lt;br /&gt;
When accessing a .desktop file, one should instead use the {{class|KDesktopFile}} class which, while a {{class|KConfig}} class offering all the capabilities described above, offers a set of methods designed to make accessing standard attributes of these files consistent and reliable.&lt;br /&gt;
&lt;br /&gt;
== Kiosk: Lockdown and User/Group Profiles ==&lt;br /&gt;
&lt;br /&gt;
KConfig provides a powerful set of lockdown and configuration definition capabilities, collectively known as &amp;quot;Kiosk&amp;quot;, that many system administrators and system integrators rely on. While most of this framework is provided transparently to the application, there is occassion when an application will want to check on the read/write status of a configuration object.&lt;br /&gt;
&lt;br /&gt;
Entries in configuration objects that are locked down using the kiosk facilities are said to be ''immutable''. An application can check for immutability of entire configuration objects, groups or keys as shown in this example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::config();&lt;br /&gt;
&lt;br /&gt;
if ( config-&amp;gt;isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;configuration object is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
KConfigGroup group(config, &amp;quot;General&amp;quot;);&lt;br /&gt;
if ( group.isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;group General is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if ( group.entryIsImmutable(&amp;quot;URL&amp;quot;) ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;URL entry in group General is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This can be useful in particular situations where an action should be taken when an item is immutable. For instance, the KDE panels will not offer configuration options to the user or allow them to otherwise change the order of applets and icons when the panel's configuration object is marked as immutable.&lt;br /&gt;
&lt;br /&gt;
== KConfig XT ==&lt;br /&gt;
&lt;br /&gt;
There is a way to make certain use cases of KConfig easier, faster and more reliable: KConfig XT. In particular, for main application or plugin configuration objects and when syncing configuration dialogs and other interfaces with these values, KConfig XT can help immensely. It also  simultaneously documents the configuration options available, which makes every sys admin and system integrator that uses KDE that much more happy.&lt;br /&gt;
&lt;br /&gt;
[[../Using_KConfig_XT|The next tutorial in the KConfig series covers what KConfig XT is and how to use it.]]&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials/KConfig_(de)</id>
		<title>Development/Tutorials/KConfig (de)</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials/KConfig_(de)"/>
				<updated>2008-01-01T23:43:23Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:I18n/Language Navigation Bar|Development/Tutorials/KConfig}}&lt;br /&gt;
&lt;br /&gt;
{{TutorialBrowser (de)|&lt;br /&gt;
&lt;br /&gt;
series=KConfig|&lt;br /&gt;
&lt;br /&gt;
name=Einführung in KConfig|&lt;br /&gt;
&lt;br /&gt;
pre=Keine|&lt;br /&gt;
&lt;br /&gt;
next=[[../Using_KConfig_XT (de)|Benutzen von KConfig XT]]|&lt;br /&gt;
&lt;br /&gt;
reading=Keine&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{improve (de)}}&lt;br /&gt;
&lt;br /&gt;
== Zusammenfassung ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dieser Artikel beschäftigt sich mir dem KDE Einstellungdaten-System, angefangen mit einer Übersicht über den grundlegenden Aufbau aus der Sicht eines Entwicklers. Es wirft ausserdem einen Blick auf jede der Klassen, die für die Entwicklung von Anwendungen relevant sind und fährt dann mit kiosk (Benutzer- und Gruppenprofile) Integration fort.&lt;br /&gt;
&lt;br /&gt;
== Grundlegender Aufbau ==&lt;br /&gt;
&lt;br /&gt;
KConfig ist ausgelegt um das Konzept vom eigentlichen Speichern und Auffinden von Konfigurationsdaten hinter eine Programmierschnittstelle zu abstrahieren die es ermöglicht, auf einfache Weise Informationen abzurufen und zu setzen. Wo oder in welcher Form Daten gespeichert werden ist für eine Anwendung die KConfig benutzt irrelevant.&lt;br /&gt;
&lt;br /&gt;
Das behält alle KDE Anwendungen konsistent in ihrer Art, Konfigurationen handzuhaben und nimmt einem Anwendungs-Entwickler die Arbeit so ein System von Grund auf neu zu schreiben, was ein sehr fehleranfälliger Prozess sein kann.&lt;br /&gt;
&lt;br /&gt;
Jedes KConfig Objekt verkörpert ein einziges Konfigurationsobjekt. Jedes Konfigurationsobjekt ist durch seinen einzigartigen Namen gekennzeichnet und kann von mehreren lokalen oder externen Daten oder Services gelesen werden. Jede Anwendung hat standardmässig ein zugehöriges Konfigurationsobjekt und es gibt auch ein globales Konfigurationsobjekt.&lt;br /&gt;
&lt;br /&gt;
Diese Konfigurationsobjekte sind nach einer zweistufigen Hierarchie getrennt: Gruppen und Schlüssel. Ein Konfigurationsobjekt kann eine beliebige Anzahl an Gruppen haben und jede Gruppe kann einen oder mehrere Schlüssel mit zugehörigen Werten haben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die gespeicherten Werte können aus beliebig vielen verschiedenen Datentypen bestehen. Sie werden gespeichert und abgerufen als das Objekt selbst. Zum Beispiel wird ein {{qt|QObject}}-Objekt direkt einem Konfigurationsobjekt übergeben, wenn es einen Farbwert speichert und wenn ein Farbwert abgerufen wird, wird ein {{qt|QObject}}-Objekt zurückgegeben.&lt;br /&gt;
&lt;br /&gt;
TODO: (deserialization?)&lt;br /&gt;
&lt;br /&gt;
Anwendungen selbst müssen darum normalerweise Objekte nicht selber gliedern und entgliedern.&lt;br /&gt;
&lt;br /&gt;
Applications themselves therefore generally do not have to perform serialization and deserialization of objects themselves.&lt;br /&gt;
&lt;br /&gt;
== Die KConfig Klasse ==&lt;br /&gt;
&lt;br /&gt;
Das {{class|KConfig}}-Objekt wird benutzt um ein bestehendes Konfigurationsobjekt anzusteuern. Es gibt eine Reihe von Möglichkeiten ein Konfigurationsobjekt zu erstellen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
// ein einfaches, altes lesen/schreiben Konfigurationsobjekt&lt;br /&gt;
KConfig config(&amp;quot;myapprc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// eine bestimmte Datei im Dateisystem&lt;br /&gt;
// currently must be an INI style file&lt;br /&gt;
KConfig fullPath(&amp;quot;/etc/kderc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// nicht mit globalen Werten verflochten&lt;br /&gt;
KConfig globalFree( &amp;quot;localsrc&amp;quot;, KConfig::NoGlobals );&lt;br /&gt;
&lt;br /&gt;
// nicht mit globalen Werten orde der $KDEDIRS Hierarchie verflochten&lt;br /&gt;
KConfig simpleConfig( &amp;quot;simplerc&amp;quot;, KConfig::SimpleConfig );&lt;br /&gt;
&lt;br /&gt;
// Komponenten-spezifische Konfiguration, in diesem Fall ein Plugin&lt;br /&gt;
KConfig pluginConfig( componentData(), &amp;quot;pluginrc&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
// Ausserhalb der normalen Konfigurations-Ressource&lt;br /&gt;
KConfig dataResource( &amp;quot;data&amp;quot;, &amp;quot;myapp/somefile&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{note (de)|&amp;quot;der Anwendung selber transparent&amp;quot; tönt nicht sehr gut}}&lt;br /&gt;
&lt;br /&gt;
Das Kconfig Objekt, das wir auf Zeile 2 erstellen ist ein gewöhnliches Konfigurationsobjekt. Wir können Werte aus ihm lesen, neue Einträge schreiben und nach verschiedenen Eigenschaften des Objekts fragen. Dieses Objekt wird aus der Konfigurations-Ressource geladen, wie es durch {{class|KStandardDirs}} bestimmt wird, das heisst, dass jede Instanz des &amp;lt;tt&amp;gt;myapprc&amp;lt;/tt&amp;gt;-Objekts in jedem der Ordner in der Konfigurations-Ressourcen-Hierarchie verschmolzen werden um die Werte zu erzeugen, die in diesem Objekt gesehen werden. So werden Systemweite und &lt;br /&gt;
pro-Benutzer/Gruppen Profile erstellt und unterstützt. Das alles geschieht der Anwendung selber transparent.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{tip| Für mehr Informationen, wie das Verschmelzen funktioniert, siehe diesen Artikel über die [[KDE System Administration/KDE_Filesystem_Hierarchy|KDE Dateisystem Hierarchie]].}}&lt;br /&gt;
&lt;br /&gt;
{{note (de)|Ist das so gemeint mit &amp;quot;expects an INI style file&amp;quot;&amp;lt;br&amp;gt; &amp;lt;tt&amp;gt; On line 6 we open a specific local file, this case /etc/kderc. This performs no merging of values and expects an INI style file.&amp;lt;/tt&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Auf Zeile 6 öffnen wir eine bestimmte Lokale Datei, in diesem Fall {{path|/etc/kderc}. Das führt kein verschmelzen von Werten aus und erwartet eine Datei im INI Format.&lt;br /&gt;
&lt;br /&gt;
{{note (de)|Der Rest muss noch übersetzt werden}}&lt;br /&gt;
&lt;br /&gt;
Line 9 sees the creation of a configuration object that is not merged with the global &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt; configuration object, while the configuration file on line 12 is additionally not merged with any files in the &amp;lt;tt&amp;gt;$KDEDIRS&amp;lt;/tt&amp;gt; hierarchy. This can noticeably improve performance in the case where one is simply reading values out of a simple configuration for which global values are not meaningful.&lt;br /&gt;
&lt;br /&gt;
Line 15 creates a configuration object using the {{class|KComponentData}} object that belongs to a plugin or other component. The plugin may have a different set of directories defined in its {{class|KStandardDirs}} and this is a way of ensuring that {{class|KConfig}} respects this.&lt;br /&gt;
&lt;br /&gt;
Finally on line 18 we see the creation of a configuration object that does not exist in the &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; resource but rather in the application &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; resource. You may use any resource that {{class|KStandardDirs}} is aware of, including ones that are added at runtime.&lt;br /&gt;
&lt;br /&gt;
=== Special Configuration Objects ===&lt;br /&gt;
&lt;br /&gt;
Each application has its own configuration object that uses the name provided to {{class|KAboutData}} appended with &amp;quot;rc&amp;quot; as its name. So an app named &amp;quot;myapp&amp;quot; would have the default configuration object of &amp;quot;myapprc&amp;quot;. This configuration file can be retrieved in this way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KComponentData&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
#include &amp;lt;KGlobal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    // note that this is actually a KSharedConfig&lt;br /&gt;
    // more on that class in a bit!&lt;br /&gt;
    KConfig* config = KGlobal::config();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The default configuration object for the application is accessed when no name is specified when creating a {{class|KConfig}} object. So we could also do this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    KConfig config;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additionally, each component may have its own configuration object. This is generally accessed via the plugin's &amp;lt;tt&amp;gt;componentData()&amp;lt;/tt&amp;gt; rather than &amp;lt;tt&amp;gt;{{class|KGlobal}}::mainComponent()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Finally there is a global configuration object, &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt;, that is shared by every application. It holds such information as the default application shortcuts for various actions. It is &amp;quot;blended&amp;quot; into the configuration object if the &amp;lt;tt&amp;gt;KConfig::IncludeGlobals&amp;lt;/tt&amp;gt; flag is passed to the {{class|KConfig}} constructor, which is the default.&lt;br /&gt;
&lt;br /&gt;
=== Commonly Useful Methods ===&lt;br /&gt;
&lt;br /&gt;
To save the current state of the configuration object we call the &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; method. This method is also called when the object is destroyed. If no changes have been made or the resource reports itself as non-writable (such as in the case of the user not having write permissions to the file) then no disk activity occurs. &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; merges changes performed concurrently by other processes - local changes have priority, though.&lt;br /&gt;
&lt;br /&gt;
If we want to make sure that we have the latest values from disk we can call &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt; which calls &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; and then reloads the data from disk.&lt;br /&gt;
&lt;br /&gt;
If we need to prevent the config object from saving already made modifications to disk we need to call &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt;. A particular use case for this is rolling back the configuration to the on-disk state by calling &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt; followed by &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Listing all groups in a configuration object is as simple as calling &amp;lt;tt&amp;gt;groupList()&amp;lt;/tt&amp;gt; as in this code snippet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::mainComponent().config();&lt;br /&gt;
&lt;br /&gt;
foreach ( const QString&amp;amp; group, config.groupList() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;next group:&amp;quot; &amp;lt;&amp;lt; group;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== KSharedConfig ==&lt;br /&gt;
&lt;br /&gt;
The {{class|KSharedConfig}} class is a reference counted version of {{class|KConfig}}. It thus provides a way to reference the same configuration object from multiple places in your application without the extra overhead of separate objects or concerns about syncronizing writes to disk even if the configuration object is updated from multiple code paths. &lt;br /&gt;
&lt;br /&gt;
Accessing a {{class|KSharedConfig}} object is as easy as this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KSharedConfigPtr config = KSharedConfig::openConfig();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;openConfig()&amp;lt;/tt&amp;gt; take the same parameters as {{class|KConfig}}'s constructors do, allowing one to define which configuration file to open, flags to control merging and non-&amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; resources.&lt;br /&gt;
&lt;br /&gt;
{{class|KSharedConfig}} is generally recommended over using {{class|KConfig}} itself, and the object returned from {{class|KComponentData}} is indeed a {{class|KSharedConfig}} object.&lt;br /&gt;
&lt;br /&gt;
== KConfigGroup ==&lt;br /&gt;
&lt;br /&gt;
Now that we have a configuration object, the next step is to actually use it. The first thing we must do is to define which group of key/value pairs we wish to access in the object. We do this by creating a KConfigGroup object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig config;&lt;br /&gt;
KConfigGroup generalGroup( &amp;amp;config, &amp;quot;General&amp;quot; );&lt;br /&gt;
KConfigGroup colorsGroup = config.group( &amp;quot;Colors&amp;quot; ); // ... or a bit differently ...&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can pass {{class|KConfig}} or {{class|KSharedConfig}} objects to {{class|KConfigGroup}}.&lt;br /&gt;
&lt;br /&gt;
Config groups can be nested as well:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfigGroup subGroup1( &amp;amp;generalGroup, &amp;quot;LessGeneral&amp;quot; );&lt;br /&gt;
KConfigGroup subGroup2 = colorsGroup.group( &amp;quot;Dialogs&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Reading Entries ==&lt;br /&gt;
&lt;br /&gt;
With a {{class|KConfigGroup}} object in hand reading entries is now quite straight forward:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
QString accountName = generalGroup.readEntry( &amp;quot;Account&amp;quot;,&lt;br /&gt;
                                              QString() );&lt;br /&gt;
QColor color = colorsGroup.readEntry( &amp;quot;background&amp;quot;,&lt;br /&gt;
                                      Qt::white );&lt;br /&gt;
QStringList list = generalGroup.readEntry( &amp;quot;List&amp;quot;,&lt;br /&gt;
                                           QStringList() );&lt;br /&gt;
QString path = generalGroup.readPathEntry( &amp;quot;SaveTo&amp;quot;,&lt;br /&gt;
                                           defaultPath );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As can be seen from the above, you can mix reads from different {{class|KConfigGroup}} objects created on the same {{class|KConfig}} object. The read methods take the key, which is case sensitive, as the first argument and the default value as the second argument. This argument controls what kind of data, e.g. a color in line 3 above, is to be expected as well as the type of object returned. The returned object is wrapped in a {{qt|QVariant}} to make this magic happen.&lt;br /&gt;
&lt;br /&gt;
There are a couple of special read methods, including &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; which returns a file system path. It is vital that one uses &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; if it is a path as this enables such features as roaming profiles to work properly.&lt;br /&gt;
&lt;br /&gt;
If no such key currently exists in the configuration object, the default value is returned instead. If there is a localized (e.g. translated into another language) entry for the key that matches the current locale, that is returned.&lt;br /&gt;
&lt;br /&gt;
== Writing Entries ==&lt;br /&gt;
&lt;br /&gt;
Setting new values is similarly straightforward:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
generalGroup.writeEntry( &amp;quot;Account&amp;quot;, accountName );&lt;br /&gt;
generalGroup.writePathEntry( &amp;quot;SaveTo&amp;quot;, savePath );&lt;br /&gt;
colorGroup.writeEntry( &amp;quot;background&amp;quot;, color );&lt;br /&gt;
generalGroup.config()-&amp;gt;sync();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note the use of &amp;lt;tt&amp;gt;writePathEntry&amp;lt;/tt&amp;gt; and how the type of object we use, such as {{qt|QColor}} on line 3, dictates how the data is serialized. Additionally, once we are done writing entries, &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; must be called on the config object for it to be saved to disk. We can also simply wait for the object to be destroyed, which triggers an automatic &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; if necessary.&lt;br /&gt;
&lt;br /&gt;
== KDesktopFile: A Special Case ==&lt;br /&gt;
&lt;br /&gt;
When is a configuration file not a configuration file? When it is a [http://freedesktop.org/wiki/Standards_2fdesktop_2dentry_2dspec desktop file]. These files, which are essentially configuration files at their heart, are used  to describe entries for application menus, mimetypes, plugins and various services.&lt;br /&gt;
&lt;br /&gt;
When accessing a .desktop file, one should instead use the {{class|KDesktopFile}} class which, while a {{class|KConfig}} class offering all the capabilities described above, offers a set of methods designed to make accessing standard attributes of these files consistent and reliable.&lt;br /&gt;
&lt;br /&gt;
== Kiosk: Lockdown and User/Group Profiles ==&lt;br /&gt;
&lt;br /&gt;
KConfig provides a powerful set of lockdown and configuration definition capabilities, collectively known as &amp;quot;Kiosk&amp;quot;, that many system administrators and system integrators rely on. While most of this framework is provided transparently to the application, there is occassion when an application will want to check on the read/write status of a configuration object.&lt;br /&gt;
&lt;br /&gt;
Entries in configuration objects that are locked down using the kiosk facilities are said to be ''immutable''. An application can check for immutability of entire configuration objects, groups or keys as shown in this example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::config();&lt;br /&gt;
&lt;br /&gt;
if ( config-&amp;gt;isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;configuration object is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
KConfigGroup group(config, &amp;quot;General&amp;quot;);&lt;br /&gt;
if ( group.isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;group General is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if ( group.entryIsImmutable(&amp;quot;URL&amp;quot;) ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;URL entry in group General is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This can be useful in particular situations where an action should be taken when an item is immutable. For instance, the KDE panels will not offer configuration options to the user or allow them to otherwise change the order of applets and icons when the panel's configuration object is marked as immutable.&lt;br /&gt;
&lt;br /&gt;
== KConfig XT ==&lt;br /&gt;
&lt;br /&gt;
There is a way to make certain use cases of KConfig easier, faster and more reliable: KConfig XT. In particular, for main application or plugin configuration objects and when syncing configuration dialogs and other interfaces with these values, KConfig XT can help immensely. It also  simultaneously documents the configuration options available, which makes every sys admin and system integrator that uses KDE that much more happy.&lt;br /&gt;
&lt;br /&gt;
[[../Using_KConfig_XT|The next tutorial in the KConfig series covers what KConfig XT is and how to use it.]]&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials/KConfig_(de)</id>
		<title>Development/Tutorials/KConfig (de)</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials/KConfig_(de)"/>
				<updated>2008-01-01T23:41:15Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: /* Die KConfig Klasse */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:I18n/Language Navigation Bar|Development/Tutorials/KConfig}}&lt;br /&gt;
&lt;br /&gt;
{{TutorialBrowser (de)|&lt;br /&gt;
&lt;br /&gt;
series=KConfig|&lt;br /&gt;
&lt;br /&gt;
name=Einführung in KConfig|&lt;br /&gt;
&lt;br /&gt;
pre=Keine|&lt;br /&gt;
&lt;br /&gt;
next=[[../Using_KConfig_XT (de)|Benutzen von KConfig XT]]|&lt;br /&gt;
&lt;br /&gt;
reading=Keine&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Zusammenfassung ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dieser Artikel beschäftigt sich mir dem KDE Einstellungdaten-System, angefangen mit einer Übersicht über den grundlegenden Aufbau aus der Sicht eines Entwicklers. Es wirft ausserdem einen Blick auf jede der Klassen, die für die Entwicklung von Anwendungen relevant sind und fährt dann mit kiosk (Benutzer- und Gruppenprofile) Integration fort.&lt;br /&gt;
&lt;br /&gt;
== Grundlegender Aufbau ==&lt;br /&gt;
&lt;br /&gt;
KConfig ist ausgelegt um das Konzept vom eigentlichen Speichern und Auffinden von Konfigurationsdaten hinter eine Programmierschnittstelle zu abstrahieren die es ermöglicht, auf einfache Weise Informationen abzurufen und zu setzen. Wo oder in welcher Form Daten gespeichert werden ist für eine Anwendung die KConfig benutzt irrelevant.&lt;br /&gt;
&lt;br /&gt;
Das behält alle KDE Anwendungen konsistent in ihrer Art, Konfigurationen handzuhaben und nimmt einem Anwendungs-Entwickler die Arbeit so ein System von Grund auf neu zu schreiben, was ein sehr fehleranfälliger Prozess sein kann.&lt;br /&gt;
&lt;br /&gt;
Jedes KConfig Objekt verkörpert ein einziges Konfigurationsobjekt. Jedes Konfigurationsobjekt ist durch seinen einzigartigen Namen gekennzeichnet und kann von mehreren lokalen oder externen Daten oder Services gelesen werden. Jede Anwendung hat standardmässig ein zugehöriges Konfigurationsobjekt und es gibt auch ein globales Konfigurationsobjekt.&lt;br /&gt;
&lt;br /&gt;
Diese Konfigurationsobjekte sind nach einer zweistufigen Hierarchie getrennt: Gruppen und Schlüssel. Ein Konfigurationsobjekt kann eine beliebige Anzahl an Gruppen haben und jede Gruppe kann einen oder mehrere Schlüssel mit zugehörigen Werten haben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die gespeicherten Werte können aus beliebig vielen verschiedenen Datentypen bestehen. Sie werden gespeichert und abgerufen als das Objekt selbst. Zum Beispiel wird ein {{qt|QObject}}-Objekt direkt einem Konfigurationsobjekt übergeben, wenn es einen Farbwert speichert und wenn ein Farbwert abgerufen wird, wird ein {{qt|QObject}}-Objekt zurückgegeben.&lt;br /&gt;
&lt;br /&gt;
TODO: (deserialization?)&lt;br /&gt;
&lt;br /&gt;
Anwendungen selbst müssen darum normalerweise Objekte nicht selber gliedern und entgliedern.&lt;br /&gt;
&lt;br /&gt;
Applications themselves therefore generally do not have to perform serialization and deserialization of objects themselves.&lt;br /&gt;
&lt;br /&gt;
== Die KConfig Klasse ==&lt;br /&gt;
&lt;br /&gt;
Das {{class|KConfig}}-Objekt wird benutzt um ein bestehendes Konfigurationsobjekt anzusteuern. Es gibt eine Reihe von Möglichkeiten ein Konfigurationsobjekt zu erstellen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
// ein einfaches, altes lesen/schreiben Konfigurationsobjekt&lt;br /&gt;
KConfig config(&amp;quot;myapprc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// eine bestimmte Datei im Dateisystem&lt;br /&gt;
// currently must be an INI style file&lt;br /&gt;
KConfig fullPath(&amp;quot;/etc/kderc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// nicht mit globalen Werten verflochten&lt;br /&gt;
KConfig globalFree( &amp;quot;localsrc&amp;quot;, KConfig::NoGlobals );&lt;br /&gt;
&lt;br /&gt;
// nicht mit globalen Werten orde der $KDEDIRS Hierarchie verflochten&lt;br /&gt;
KConfig simpleConfig( &amp;quot;simplerc&amp;quot;, KConfig::SimpleConfig );&lt;br /&gt;
&lt;br /&gt;
// Komponenten-spezifische Konfiguration, in diesem Fall ein Plugin&lt;br /&gt;
KConfig pluginConfig( componentData(), &amp;quot;pluginrc&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
// Ausserhalb der normalen Konfigurations-Ressource&lt;br /&gt;
KConfig dataResource( &amp;quot;data&amp;quot;, &amp;quot;myapp/somefile&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{note (de)|&amp;quot;der Anwendung selber transparent&amp;quot; tönt nicht sehr gut}}&lt;br /&gt;
&lt;br /&gt;
Das Kconfig Objekt, das wir auf Zeile 2 erstellen ist ein gewöhnliches Konfigurationsobjekt. Wir können Werte aus ihm lesen, neue Einträge schreiben und nach verschiedenen Eigenschaften des Objekts fragen. Dieses Objekt wird aus der Konfigurations-Ressource geladen, wie es durch {{class|KStandardDirs}} bestimmt wird, das heisst, dass jede Instanz des &amp;lt;tt&amp;gt;myapprc&amp;lt;/tt&amp;gt;-Objekts in jedem der Ordner in der Konfigurations-Ressourcen-Hierarchie verschmolzen werden um die Werte zu erzeugen, die in diesem Objekt gesehen werden. So werden Systemweite und &lt;br /&gt;
pro-Benutzer/Gruppen Profile erstellt und unterstützt. Das alles geschieht der Anwendung selber transparent.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{tip| Für mehr Informationen, wie das Verschmelzen funktioniert, siehe diesen Artikel über die [[KDE System Administration/KDE_Filesystem_Hierarchy|KDE Dateisystem Hierarchie]].}}&lt;br /&gt;
&lt;br /&gt;
{{note (de)|Ist das so gemeint mit &amp;quot;expects an INI style file&amp;quot;&amp;lt;br&amp;gt; &amp;lt;tt&amp;gt; On line 6 we open a specific local file, this case /etc/kderc. This performs no merging of values and expects an INI style file.&amp;lt;/tt&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Auf Zeile 6 öffnen wir eine bestimmte Lokale Datei, in diesem Fall {{path|/etc/kderc}. Das führt kein verschmelzen von Werten aus und erwartet eine Datei im INI Format.&lt;br /&gt;
&lt;br /&gt;
{{note (de)|Der Rest muss noch übersetzt werden}}&lt;br /&gt;
&lt;br /&gt;
Line 9 sees the creation of a configuration object that is not merged with the global &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt; configuration object, while the configuration file on line 12 is additionally not merged with any files in the &amp;lt;tt&amp;gt;$KDEDIRS&amp;lt;/tt&amp;gt; hierarchy. This can noticeably improve performance in the case where one is simply reading values out of a simple configuration for which global values are not meaningful.&lt;br /&gt;
&lt;br /&gt;
Line 15 creates a configuration object using the {{class|KComponentData}} object that belongs to a plugin or other component. The plugin may have a different set of directories defined in its {{class|KStandardDirs}} and this is a way of ensuring that {{class|KConfig}} respects this.&lt;br /&gt;
&lt;br /&gt;
Finally on line 18 we see the creation of a configuration object that does not exist in the &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; resource but rather in the application &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; resource. You may use any resource that {{class|KStandardDirs}} is aware of, including ones that are added at runtime.&lt;br /&gt;
&lt;br /&gt;
=== Special Configuration Objects ===&lt;br /&gt;
&lt;br /&gt;
Each application has its own configuration object that uses the name provided to {{class|KAboutData}} appended with &amp;quot;rc&amp;quot; as its name. So an app named &amp;quot;myapp&amp;quot; would have the default configuration object of &amp;quot;myapprc&amp;quot;. This configuration file can be retrieved in this way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KComponentData&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
#include &amp;lt;KGlobal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    // note that this is actually a KSharedConfig&lt;br /&gt;
    // more on that class in a bit!&lt;br /&gt;
    KConfig* config = KGlobal::config();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The default configuration object for the application is accessed when no name is specified when creating a {{class|KConfig}} object. So we could also do this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    KConfig config;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additionally, each component may have its own configuration object. This is generally accessed via the plugin's &amp;lt;tt&amp;gt;componentData()&amp;lt;/tt&amp;gt; rather than &amp;lt;tt&amp;gt;{{class|KGlobal}}::mainComponent()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Finally there is a global configuration object, &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt;, that is shared by every application. It holds such information as the default application shortcuts for various actions. It is &amp;quot;blended&amp;quot; into the configuration object if the &amp;lt;tt&amp;gt;KConfig::IncludeGlobals&amp;lt;/tt&amp;gt; flag is passed to the {{class|KConfig}} constructor, which is the default.&lt;br /&gt;
&lt;br /&gt;
=== Commonly Useful Methods ===&lt;br /&gt;
&lt;br /&gt;
To save the current state of the configuration object we call the &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; method. This method is also called when the object is destroyed. If no changes have been made or the resource reports itself as non-writable (such as in the case of the user not having write permissions to the file) then no disk activity occurs. &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; merges changes performed concurrently by other processes - local changes have priority, though.&lt;br /&gt;
&lt;br /&gt;
If we want to make sure that we have the latest values from disk we can call &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt; which calls &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; and then reloads the data from disk.&lt;br /&gt;
&lt;br /&gt;
If we need to prevent the config object from saving already made modifications to disk we need to call &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt;. A particular use case for this is rolling back the configuration to the on-disk state by calling &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt; followed by &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Listing all groups in a configuration object is as simple as calling &amp;lt;tt&amp;gt;groupList()&amp;lt;/tt&amp;gt; as in this code snippet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::mainComponent().config();&lt;br /&gt;
&lt;br /&gt;
foreach ( const QString&amp;amp; group, config.groupList() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;next group:&amp;quot; &amp;lt;&amp;lt; group;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== KSharedConfig ==&lt;br /&gt;
&lt;br /&gt;
The {{class|KSharedConfig}} class is a reference counted version of {{class|KConfig}}. It thus provides a way to reference the same configuration object from multiple places in your application without the extra overhead of separate objects or concerns about syncronizing writes to disk even if the configuration object is updated from multiple code paths. &lt;br /&gt;
&lt;br /&gt;
Accessing a {{class|KSharedConfig}} object is as easy as this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KSharedConfigPtr config = KSharedConfig::openConfig();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;openConfig()&amp;lt;/tt&amp;gt; take the same parameters as {{class|KConfig}}'s constructors do, allowing one to define which configuration file to open, flags to control merging and non-&amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; resources.&lt;br /&gt;
&lt;br /&gt;
{{class|KSharedConfig}} is generally recommended over using {{class|KConfig}} itself, and the object returned from {{class|KComponentData}} is indeed a {{class|KSharedConfig}} object.&lt;br /&gt;
&lt;br /&gt;
== KConfigGroup ==&lt;br /&gt;
&lt;br /&gt;
Now that we have a configuration object, the next step is to actually use it. The first thing we must do is to define which group of key/value pairs we wish to access in the object. We do this by creating a KConfigGroup object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig config;&lt;br /&gt;
KConfigGroup generalGroup( &amp;amp;config, &amp;quot;General&amp;quot; );&lt;br /&gt;
KConfigGroup colorsGroup = config.group( &amp;quot;Colors&amp;quot; ); // ... or a bit differently ...&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can pass {{class|KConfig}} or {{class|KSharedConfig}} objects to {{class|KConfigGroup}}.&lt;br /&gt;
&lt;br /&gt;
Config groups can be nested as well:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfigGroup subGroup1( &amp;amp;generalGroup, &amp;quot;LessGeneral&amp;quot; );&lt;br /&gt;
KConfigGroup subGroup2 = colorsGroup.group( &amp;quot;Dialogs&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Reading Entries ==&lt;br /&gt;
&lt;br /&gt;
With a {{class|KConfigGroup}} object in hand reading entries is now quite straight forward:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
QString accountName = generalGroup.readEntry( &amp;quot;Account&amp;quot;,&lt;br /&gt;
                                              QString() );&lt;br /&gt;
QColor color = colorsGroup.readEntry( &amp;quot;background&amp;quot;,&lt;br /&gt;
                                      Qt::white );&lt;br /&gt;
QStringList list = generalGroup.readEntry( &amp;quot;List&amp;quot;,&lt;br /&gt;
                                           QStringList() );&lt;br /&gt;
QString path = generalGroup.readPathEntry( &amp;quot;SaveTo&amp;quot;,&lt;br /&gt;
                                           defaultPath );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As can be seen from the above, you can mix reads from different {{class|KConfigGroup}} objects created on the same {{class|KConfig}} object. The read methods take the key, which is case sensitive, as the first argument and the default value as the second argument. This argument controls what kind of data, e.g. a color in line 3 above, is to be expected as well as the type of object returned. The returned object is wrapped in a {{qt|QVariant}} to make this magic happen.&lt;br /&gt;
&lt;br /&gt;
There are a couple of special read methods, including &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; which returns a file system path. It is vital that one uses &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; if it is a path as this enables such features as roaming profiles to work properly.&lt;br /&gt;
&lt;br /&gt;
If no such key currently exists in the configuration object, the default value is returned instead. If there is a localized (e.g. translated into another language) entry for the key that matches the current locale, that is returned.&lt;br /&gt;
&lt;br /&gt;
== Writing Entries ==&lt;br /&gt;
&lt;br /&gt;
Setting new values is similarly straightforward:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
generalGroup.writeEntry( &amp;quot;Account&amp;quot;, accountName );&lt;br /&gt;
generalGroup.writePathEntry( &amp;quot;SaveTo&amp;quot;, savePath );&lt;br /&gt;
colorGroup.writeEntry( &amp;quot;background&amp;quot;, color );&lt;br /&gt;
generalGroup.config()-&amp;gt;sync();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note the use of &amp;lt;tt&amp;gt;writePathEntry&amp;lt;/tt&amp;gt; and how the type of object we use, such as {{qt|QColor}} on line 3, dictates how the data is serialized. Additionally, once we are done writing entries, &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; must be called on the config object for it to be saved to disk. We can also simply wait for the object to be destroyed, which triggers an automatic &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; if necessary.&lt;br /&gt;
&lt;br /&gt;
== KDesktopFile: A Special Case ==&lt;br /&gt;
&lt;br /&gt;
When is a configuration file not a configuration file? When it is a [http://freedesktop.org/wiki/Standards_2fdesktop_2dentry_2dspec desktop file]. These files, which are essentially configuration files at their heart, are used  to describe entries for application menus, mimetypes, plugins and various services.&lt;br /&gt;
&lt;br /&gt;
When accessing a .desktop file, one should instead use the {{class|KDesktopFile}} class which, while a {{class|KConfig}} class offering all the capabilities described above, offers a set of methods designed to make accessing standard attributes of these files consistent and reliable.&lt;br /&gt;
&lt;br /&gt;
== Kiosk: Lockdown and User/Group Profiles ==&lt;br /&gt;
&lt;br /&gt;
KConfig provides a powerful set of lockdown and configuration definition capabilities, collectively known as &amp;quot;Kiosk&amp;quot;, that many system administrators and system integrators rely on. While most of this framework is provided transparently to the application, there is occassion when an application will want to check on the read/write status of a configuration object.&lt;br /&gt;
&lt;br /&gt;
Entries in configuration objects that are locked down using the kiosk facilities are said to be ''immutable''. An application can check for immutability of entire configuration objects, groups or keys as shown in this example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::config();&lt;br /&gt;
&lt;br /&gt;
if ( config-&amp;gt;isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;configuration object is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
KConfigGroup group(config, &amp;quot;General&amp;quot;);&lt;br /&gt;
if ( group.isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;group General is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if ( group.entryIsImmutable(&amp;quot;URL&amp;quot;) ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;URL entry in group General is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This can be useful in particular situations where an action should be taken when an item is immutable. For instance, the KDE panels will not offer configuration options to the user or allow them to otherwise change the order of applets and icons when the panel's configuration object is marked as immutable.&lt;br /&gt;
&lt;br /&gt;
== KConfig XT ==&lt;br /&gt;
&lt;br /&gt;
There is a way to make certain use cases of KConfig easier, faster and more reliable: KConfig XT. In particular, for main application or plugin configuration objects and when syncing configuration dialogs and other interfaces with these values, KConfig XT can help immensely. It also  simultaneously documents the configuration options available, which makes every sys admin and system integrator that uses KDE that much more happy.&lt;br /&gt;
&lt;br /&gt;
[[../Using_KConfig_XT|The next tutorial in the KConfig series covers what KConfig XT is and how to use it.]]&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials/KConfig_(de)</id>
		<title>Development/Tutorials/KConfig (de)</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials/KConfig_(de)"/>
				<updated>2008-01-01T16:31:40Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: /* The KConfig Class */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:I18n/Language Navigation Bar|Development/Tutorials/KConfig}}&lt;br /&gt;
&lt;br /&gt;
{{TutorialBrowser (de)|&lt;br /&gt;
&lt;br /&gt;
series=KConfig|&lt;br /&gt;
&lt;br /&gt;
name=Einführung in KConfig|&lt;br /&gt;
&lt;br /&gt;
pre=Keine|&lt;br /&gt;
&lt;br /&gt;
next=[[../Using_KConfig_XT (de)|Benutzen von KConfig XT]]|&lt;br /&gt;
&lt;br /&gt;
reading=Keine&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Zusammenfassung ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dieser Artikel beschäftigt sich mir dem KDE Einstellungdaten-System, angefangen mit einer Übersicht über den grundlegenden Aufbau aus der Sicht eines Entwicklers. Es wirft ausserdem einen Blick auf jede der Klassen, die für die Entwicklung von Anwendungen relevant sind und fährt dann mit kiosk (Benutzer- und Gruppenprofile) Integration fort.&lt;br /&gt;
&lt;br /&gt;
== Grundlegender Aufbau ==&lt;br /&gt;
&lt;br /&gt;
KConfig ist ausgelegt um das Konzept vom eigentlichen Speichern und Auffinden von Konfigurationsdaten hinter eine Programmierschnittstelle zu abstrahieren die es ermöglicht, auf einfache Weise Informationen abzurufen und zu setzen. Wo oder in welcher Form Daten gespeichert werden ist für eine Anwendung die KConfig benutzt irrelevant.&lt;br /&gt;
&lt;br /&gt;
Das behält alle KDE Anwendungen konsistent in ihrer Art, Konfigurationen handzuhaben und nimmt einem Anwendungs-Entwickler die Arbeit so ein System von Grund auf neu zu schreiben, was ein sehr fehleranfälliger Prozess sein kann.&lt;br /&gt;
&lt;br /&gt;
Jedes KConfig Objekt verkörpert ein einziges Konfigurationsobjekt. Jedes Konfigurationsobjekt ist durch seinen einzigartigen Namen gekennzeichnet und kann von mehreren lokalen oder externen Daten oder Services gelesen werden. Jede Anwendung hat standardmässig ein zugehöriges Konfigurationsobjekt und es gibt auch ein globales Konfigurationsobjekt.&lt;br /&gt;
&lt;br /&gt;
Diese Konfigurationsobjekte sind nach einer zweistufigen Hierarchie getrennt: Gruppen und Schlüssel. Ein Konfigurationsobjekt kann eine beliebige Anzahl an Gruppen haben und jede Gruppe kann einen oder mehrere Schlüssel mit zugehörigen Werten haben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die gespeicherten Werte können aus beliebig vielen verschiedenen Datentypen bestehen. Sie werden gespeichert und abgerufen als das Objekt selbst. Zum Beispiel wird ein {{qt|QObject}}-Objekt direkt einem Konfigurationsobjekt übergeben, wenn es einen Farbwert speichert und wenn ein Farbwert abgerufen wird, wird ein {{qt|QObject}}-Objekt zurückgegeben.&lt;br /&gt;
&lt;br /&gt;
TODO: (deserialization?)&lt;br /&gt;
&lt;br /&gt;
Anwendungen selbst müssen darum normalerweise Objekte nicht selber gliedern und entgliedern.&lt;br /&gt;
&lt;br /&gt;
Applications themselves therefore generally do not have to perform serialization and deserialization of objects themselves.&lt;br /&gt;
&lt;br /&gt;
== Die KConfig Klasse ==&lt;br /&gt;
&lt;br /&gt;
Das {{class|KConfig}}-Objekt wird benutzt um ein bestehendes Konfigurationsobjekt anzusteuern. Es gibt eine Reihe von Möglichkeiten ein Konfigurationsobjekt zu erstellen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
// ein einfaches, altes lesen/schreiben Konfigurationsobjekt&lt;br /&gt;
KConfig config(&amp;quot;myapprc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// eine bestimmte Datei im Dateisystem&lt;br /&gt;
// currently must be an INI style file&lt;br /&gt;
KConfig fullPath(&amp;quot;/etc/kderc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// nicht mit globalen Werten verflochten&lt;br /&gt;
KConfig globalFree( &amp;quot;localsrc&amp;quot;, KConfig::NoGlobals );&lt;br /&gt;
&lt;br /&gt;
// nicht mit globalen Werten orde der $KDEDIRS Hierarchie verflochten&lt;br /&gt;
KConfig simpleConfig( &amp;quot;simplerc&amp;quot;, KConfig::SimpleConfig );&lt;br /&gt;
&lt;br /&gt;
// Komponenten-spezifische Konfiguration, in diesem Fall ein Plugin&lt;br /&gt;
KConfig pluginConfig( componentData(), &amp;quot;pluginrc&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
// Ausserhalb der normalen Konfigurations-Ressource&lt;br /&gt;
KConfig dataResource( &amp;quot;data&amp;quot;, &amp;quot;myapp/somefile&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TODO: (will be merged - &amp;quot;verschmolzen werden&amp;quot;, &amp;quot;der Anwendung selber transparent&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
Das Kconfig Objekt, das wir auf Zeile 2 erstellen ist ein gewöhnliches Konfigurationsobjekt. Wir können Werte aus ihm lesen, neue Einträge schreiben und nach verschiedenen Eigenschaften des Objekts fragen. Dieses Objekt wird aus der Konfigurations-Ressource geladen, wie es durch {{class|KStandardDirs}} bestimmt wird, das heisst, dass jede Instanz des &amp;lt;tt&amp;gt;myapprc&amp;lt;/tt&amp;gt;-Objekts in jedem der Ordner in der Konfigurations-Ressourcen-Hierarchie verschmolzen werden um die Werte zu erzeugen, die in diesem Objekt gesehen werden. So werden Systemweite und &lt;br /&gt;
pro-Benutzer/Gruppen Profile erstellt und unterstützt. Das alles geschieht der Anwendung selber transparent.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{tip| Für mehr Informationen, wie das Verschmelzen funktioniert, siehe diesen Artikel über das [[KDE System Administration/KDE_Filesystem_Hierarchy|KDE Dateisystem Hierarchie]].}}&lt;br /&gt;
&lt;br /&gt;
TODO:Rest übersetzen&lt;br /&gt;
&lt;br /&gt;
On line 6 we open a specific local file, this case {{path|/etc/kderc}}. This performs no merging of values and expects an INI style file.&lt;br /&gt;
&lt;br /&gt;
Line 9 sees the creation of a configuration object that is not merged with the global &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt; configuration object, while the configuration file on line 12 is additionally not merged with any files in the &amp;lt;tt&amp;gt;$KDEDIRS&amp;lt;/tt&amp;gt; hierarchy. This can noticeably improve performance in the case where one is simply reading values out of a simple configuration for which global values are not meaningful.&lt;br /&gt;
&lt;br /&gt;
Line 15 creates a configuration object using the {{class|KComponentData}} object that belongs to a plugin or other component. The plugin may have a different set of directories defined in its {{class|KStandardDirs}} and this is a way of ensuring that {{class|KConfig}} respects this.&lt;br /&gt;
&lt;br /&gt;
Finally on line 18 we see the creation of a configuration object that does not exist in the &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; resource but rather in the application &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; resource. You may use any resource that {{class|KStandardDirs}} is aware of, including ones that are added at runtime.&lt;br /&gt;
&lt;br /&gt;
=== Special Configuration Objects ===&lt;br /&gt;
&lt;br /&gt;
Each application has its own configuration object that uses the name provided to {{class|KAboutData}} appended with &amp;quot;rc&amp;quot; as its name. So an app named &amp;quot;myapp&amp;quot; would have the default configuration object of &amp;quot;myapprc&amp;quot;. This configuration file can be retrieved in this way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KComponentData&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
#include &amp;lt;KGlobal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    // note that this is actually a KSharedConfig&lt;br /&gt;
    // more on that class in a bit!&lt;br /&gt;
    KConfig* config = KGlobal::config();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The default configuration object for the application is accessed when no name is specified when creating a {{class|KConfig}} object. So we could also do this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    KConfig config;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additionally, each component may have its own configuration object. This is generally accessed via the plugin's &amp;lt;tt&amp;gt;componentData()&amp;lt;/tt&amp;gt; rather than &amp;lt;tt&amp;gt;{{class|KGlobal}}::mainComponent()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Finally there is a global configuration object, &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt;, that is shared by every application. It holds such information as the default application shortcuts for various actions. It is &amp;quot;blended&amp;quot; into the configuration object if the &amp;lt;tt&amp;gt;KConfig::IncludeGlobals&amp;lt;/tt&amp;gt; flag is passed to the {{class|KConfig}} constructor, which is the default.&lt;br /&gt;
&lt;br /&gt;
=== Commonly Useful Methods ===&lt;br /&gt;
&lt;br /&gt;
To save the current state of the configuration object we call the &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; method. This method is also called when the object is destroyed. If no changes have been made or the resource reports itself as non-writable (such as in the case of the user not having write permissions to the file) then no disk activity occurs. &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; merges changes performed concurrently by other processes - local changes have priority, though.&lt;br /&gt;
&lt;br /&gt;
If we want to make sure that we have the latest values from disk we can call &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt; which calls &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; and then reloads the data from disk.&lt;br /&gt;
&lt;br /&gt;
If we need to prevent the config object from saving already made modifications to disk we need to call &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt;. A particular use case for this is rolling back the configuration to the on-disk state by calling &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt; followed by &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Listing all groups in a configuration object is as simple as calling &amp;lt;tt&amp;gt;groupList()&amp;lt;/tt&amp;gt; as in this code snippet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::mainComponent().config();&lt;br /&gt;
&lt;br /&gt;
foreach ( const QString&amp;amp; group, config.groupList() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;next group:&amp;quot; &amp;lt;&amp;lt; group;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== KSharedConfig ==&lt;br /&gt;
&lt;br /&gt;
The {{class|KSharedConfig}} class is a reference counted version of {{class|KConfig}}. It thus provides a way to reference the same configuration object from multiple places in your application without the extra overhead of separate objects or concerns about syncronizing writes to disk even if the configuration object is updated from multiple code paths. &lt;br /&gt;
&lt;br /&gt;
Accessing a {{class|KSharedConfig}} object is as easy as this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KSharedConfigPtr config = KSharedConfig::openConfig();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;openConfig()&amp;lt;/tt&amp;gt; take the same parameters as {{class|KConfig}}'s constructors do, allowing one to define which configuration file to open, flags to control merging and non-&amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; resources.&lt;br /&gt;
&lt;br /&gt;
{{class|KSharedConfig}} is generally recommended over using {{class|KConfig}} itself, and the object returned from {{class|KComponentData}} is indeed a {{class|KSharedConfig}} object.&lt;br /&gt;
&lt;br /&gt;
== KConfigGroup ==&lt;br /&gt;
&lt;br /&gt;
Now that we have a configuration object, the next step is to actually use it. The first thing we must do is to define which group of key/value pairs we wish to access in the object. We do this by creating a KConfigGroup object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig config;&lt;br /&gt;
KConfigGroup generalGroup( &amp;amp;config, &amp;quot;General&amp;quot; );&lt;br /&gt;
KConfigGroup colorsGroup = config.group( &amp;quot;Colors&amp;quot; ); // ... or a bit differently ...&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can pass {{class|KConfig}} or {{class|KSharedConfig}} objects to {{class|KConfigGroup}}.&lt;br /&gt;
&lt;br /&gt;
Config groups can be nested as well:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfigGroup subGroup1( &amp;amp;generalGroup, &amp;quot;LessGeneral&amp;quot; );&lt;br /&gt;
KConfigGroup subGroup2 = colorsGroup.group( &amp;quot;Dialogs&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Reading Entries ==&lt;br /&gt;
&lt;br /&gt;
With a {{class|KConfigGroup}} object in hand reading entries is now quite straight forward:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
QString accountName = generalGroup.readEntry( &amp;quot;Account&amp;quot;,&lt;br /&gt;
                                              QString() );&lt;br /&gt;
QColor color = colorsGroup.readEntry( &amp;quot;background&amp;quot;,&lt;br /&gt;
                                      Qt::white );&lt;br /&gt;
QStringList list = generalGroup.readEntry( &amp;quot;List&amp;quot;,&lt;br /&gt;
                                           QStringList() );&lt;br /&gt;
QString path = generalGroup.readPathEntry( &amp;quot;SaveTo&amp;quot;,&lt;br /&gt;
                                           defaultPath );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As can be seen from the above, you can mix reads from different {{class|KConfigGroup}} objects created on the same {{class|KConfig}} object. The read methods take the key, which is case sensitive, as the first argument and the default value as the second argument. This argument controls what kind of data, e.g. a color in line 3 above, is to be expected as well as the type of object returned. The returned object is wrapped in a {{qt|QVariant}} to make this magic happen.&lt;br /&gt;
&lt;br /&gt;
There are a couple of special read methods, including &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; which returns a file system path. It is vital that one uses &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; if it is a path as this enables such features as roaming profiles to work properly.&lt;br /&gt;
&lt;br /&gt;
If no such key currently exists in the configuration object, the default value is returned instead. If there is a localized (e.g. translated into another language) entry for the key that matches the current locale, that is returned.&lt;br /&gt;
&lt;br /&gt;
== Writing Entries ==&lt;br /&gt;
&lt;br /&gt;
Setting new values is similarly straightforward:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
generalGroup.writeEntry( &amp;quot;Account&amp;quot;, accountName );&lt;br /&gt;
generalGroup.writePathEntry( &amp;quot;SaveTo&amp;quot;, savePath );&lt;br /&gt;
colorGroup.writeEntry( &amp;quot;background&amp;quot;, color );&lt;br /&gt;
generalGroup.config()-&amp;gt;sync();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note the use of &amp;lt;tt&amp;gt;writePathEntry&amp;lt;/tt&amp;gt; and how the type of object we use, such as {{qt|QColor}} on line 3, dictates how the data is serialized. Additionally, once we are done writing entries, &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; must be called on the config object for it to be saved to disk. We can also simply wait for the object to be destroyed, which triggers an automatic &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; if necessary.&lt;br /&gt;
&lt;br /&gt;
== KDesktopFile: A Special Case ==&lt;br /&gt;
&lt;br /&gt;
When is a configuration file not a configuration file? When it is a [http://freedesktop.org/wiki/Standards_2fdesktop_2dentry_2dspec desktop file]. These files, which are essentially configuration files at their heart, are used  to describe entries for application menus, mimetypes, plugins and various services.&lt;br /&gt;
&lt;br /&gt;
When accessing a .desktop file, one should instead use the {{class|KDesktopFile}} class which, while a {{class|KConfig}} class offering all the capabilities described above, offers a set of methods designed to make accessing standard attributes of these files consistent and reliable.&lt;br /&gt;
&lt;br /&gt;
== Kiosk: Lockdown and User/Group Profiles ==&lt;br /&gt;
&lt;br /&gt;
KConfig provides a powerful set of lockdown and configuration definition capabilities, collectively known as &amp;quot;Kiosk&amp;quot;, that many system administrators and system integrators rely on. While most of this framework is provided transparently to the application, there is occassion when an application will want to check on the read/write status of a configuration object.&lt;br /&gt;
&lt;br /&gt;
Entries in configuration objects that are locked down using the kiosk facilities are said to be ''immutable''. An application can check for immutability of entire configuration objects, groups or keys as shown in this example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::config();&lt;br /&gt;
&lt;br /&gt;
if ( config-&amp;gt;isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;configuration object is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
KConfigGroup group(config, &amp;quot;General&amp;quot;);&lt;br /&gt;
if ( group.isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;group General is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if ( group.entryIsImmutable(&amp;quot;URL&amp;quot;) ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;URL entry in group General is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This can be useful in particular situations where an action should be taken when an item is immutable. For instance, the KDE panels will not offer configuration options to the user or allow them to otherwise change the order of applets and icons when the panel's configuration object is marked as immutable.&lt;br /&gt;
&lt;br /&gt;
== KConfig XT ==&lt;br /&gt;
&lt;br /&gt;
There is a way to make certain use cases of KConfig easier, faster and more reliable: KConfig XT. In particular, for main application or plugin configuration objects and when syncing configuration dialogs and other interfaces with these values, KConfig XT can help immensely. It also  simultaneously documents the configuration options available, which makes every sys admin and system integrator that uses KDE that much more happy.&lt;br /&gt;
&lt;br /&gt;
[[../Using_KConfig_XT|The next tutorial in the KConfig series covers what KConfig XT is and how to use it.]]&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials/KConfig_(de)</id>
		<title>Development/Tutorials/KConfig (de)</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials/KConfig_(de)"/>
				<updated>2008-01-01T15:28:56Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: /* Zusammenfassung */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:I18n/Language Navigation Bar|Development/Tutorials/KConfig}}&lt;br /&gt;
&lt;br /&gt;
{{TutorialBrowser (de)|&lt;br /&gt;
&lt;br /&gt;
series=KConfig|&lt;br /&gt;
&lt;br /&gt;
name=Einführung in KConfig|&lt;br /&gt;
&lt;br /&gt;
pre=Keine|&lt;br /&gt;
&lt;br /&gt;
next=[[../Using_KConfig_XT (de)|Benutzen von KConfig XT]]|&lt;br /&gt;
&lt;br /&gt;
reading=Keine&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Zusammenfassung ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dieser Artikel beschäftigt sich mir dem KDE Einstellungdaten-System, angefangen mit einer Übersicht über den grundlegenden Aufbau aus der Sicht eines Entwicklers. Es wirft ausserdem einen Blick auf jede der Klassen, die für die Entwicklung von Anwendungen relevant sind und fährt dann mit kiosk (Benutzer- und Gruppenprofile) Integration fort.&lt;br /&gt;
&lt;br /&gt;
== Grundlegender Aufbau ==&lt;br /&gt;
&lt;br /&gt;
KConfig ist ausgelegt um das Konzept vom eigentlichen Speichern und Auffinden von Konfigurationsdaten hinter eine Programmierschnittstelle zu abstrahieren die es ermöglicht, auf einfache Weise Informationen abzurufen und zu setzen. Wo oder in welcher Form Daten gespeichert werden ist für eine Anwendung die KConfig benutzt irrelevant.&lt;br /&gt;
&lt;br /&gt;
Das behält alle KDE Anwendungen konsistent in ihrer Art, Konfigurationen handzuhaben und nimmt einem Anwendungs-Entwickler die Arbeit so ein System von Grund auf neu zu schreiben, was ein sehr fehleranfälliger Prozess sein kann.&lt;br /&gt;
&lt;br /&gt;
Jedes KConfig Objekt verkörpert ein einziges Konfigurationsobjekt. Jedes Konfigurationsobjekt ist durch seinen einzigartigen Namen gekennzeichnet und kann von mehreren lokalen oder externen Daten oder Services gelesen werden. Jede Anwendung hat standardmässig ein zugehöriges Konfigurationsobjekt und es gibt auch ein globales Konfigurationsobjekt.&lt;br /&gt;
&lt;br /&gt;
Diese Konfigurationsobjekte sind nach einer zweistufigen Hierarchie getrennt: Gruppen und Schlüssel. Ein Konfigurationsobjekt kann eine beliebige Anzahl an Gruppen haben und jede Gruppe kann einen oder mehrere Schlüssel mit zugehörigen Werten haben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die gespeicherten Werte können aus beliebig vielen verschiedenen Datentypen bestehen. Sie werden gespeichert und abgerufen als das Objekt selbst. Zum Beispiel wird ein {{qt|QObject}}-Objekt direkt einem Konfigurationsobjekt übergeben, wenn es einen Farbwert speichert und wenn ein Farbwert abgerufen wird, wird ein {{qt|QObject}}-Objekt zurückgegeben.&lt;br /&gt;
&lt;br /&gt;
TODO: (deserialization?)&lt;br /&gt;
&lt;br /&gt;
Anwendungen selbst müssen darum normalerweise Objekte nicht selber gliedern und entgliedern.&lt;br /&gt;
&lt;br /&gt;
Applications themselves therefore generally do not have to perform serialization and deserialization of objects themselves.&lt;br /&gt;
&lt;br /&gt;
== The KConfig Class ==&lt;br /&gt;
&lt;br /&gt;
The {{class|KConfig}} object is used to access a given configuration object. There are a number of ways to create a config object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
// a plain old read/write config object&lt;br /&gt;
KConfig config(&amp;quot;myapprc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// a specific file in the filesystem&lt;br /&gt;
// currently must be an INI style file&lt;br /&gt;
KConfig fullPath(&amp;quot;/etc/kderc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// not merged with global values&lt;br /&gt;
KConfig globalFree( &amp;quot;localsrc&amp;quot;, KConfig::NoGlobals );&lt;br /&gt;
&lt;br /&gt;
// not merged with globals or the $KDEDIRS hierarchy&lt;br /&gt;
KConfig simpleConfig( &amp;quot;simplerc&amp;quot;, KConfig::SimpleConfig );&lt;br /&gt;
&lt;br /&gt;
// config specific to a component, in this case a plugin&lt;br /&gt;
KConfig pluginConfig( componentData(), &amp;quot;pluginrc&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
// outside the standard config resource&lt;br /&gt;
KConfig dataResource( &amp;quot;data&amp;quot;, &amp;quot;myapp/somefile&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The KConfig object create on line 2 is a regular config object. We can read values from it, write new entries and ask for various properties of the object.  This object will be loaded from the config resource as determined by {{class|KStandardDirs}}, meaning that every instance of the &amp;lt;tt&amp;gt;myapprc&amp;lt;/tt&amp;gt; object in each of the directories in the config resource hierarchy will be merged to create the values seen in this object. This is how system wide and per-user/group profiles are generated and supported and it all happens transparently to the application itself.&lt;br /&gt;
&lt;br /&gt;
{{tip|For more information on how the merging works, see the [[KDE System Administration/KDE_Filesystem_Hierarchy|KDE Filesystem Hierarchy]] article.}}&lt;br /&gt;
&lt;br /&gt;
On line 6 we open a specific local file, this case {{path|/etc/kderc}}. This performs no merging of values and expects an INI style file.&lt;br /&gt;
&lt;br /&gt;
Line 9 sees the creation of a configuration object that is not merged with the global &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt; configuration object, while the configuration file on line 12 is additionally not merged with any files in the &amp;lt;tt&amp;gt;$KDEDIRS&amp;lt;/tt&amp;gt; hierarchy. This can noticeably improve performance in the case where one is simply reading values out of a simple configuration for which global values are not meaningful.&lt;br /&gt;
&lt;br /&gt;
Line 15 creates a configuration object using the {{class|KComponentData}} object that belongs to a plugin or other component. The plugin may have a different set of directories defined in its {{class|KStandardDirs}} and this is a way of ensuring that {{class|KConfig}} respects this.&lt;br /&gt;
&lt;br /&gt;
Finally on line 18 we see the creation of a configuration object that does not exist in the &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; resource but rather in the application &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; resource. You may use any resource that {{class|KStandardDirs}} is aware of, including ones that are added at runtime.&lt;br /&gt;
&lt;br /&gt;
=== Special Configuration Objects ===&lt;br /&gt;
&lt;br /&gt;
Each application has its own configuration object that uses the name provided to {{class|KAboutData}} appended with &amp;quot;rc&amp;quot; as its name. So an app named &amp;quot;myapp&amp;quot; would have the default configuration object of &amp;quot;myapprc&amp;quot;. This configuration file can be retrieved in this way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KComponentData&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
#include &amp;lt;KGlobal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    // note that this is actually a KSharedConfig&lt;br /&gt;
    // more on that class in a bit!&lt;br /&gt;
    KConfig* config = KGlobal::config();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The default configuration object for the application is accessed when no name is specified when creating a {{class|KConfig}} object. So we could also do this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    KConfig config;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additionally, each component may have its own configuration object. This is generally accessed via the plugin's &amp;lt;tt&amp;gt;componentData()&amp;lt;/tt&amp;gt; rather than &amp;lt;tt&amp;gt;{{class|KGlobal}}::mainComponent()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Finally there is a global configuration object, &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt;, that is shared by every application. It holds such information as the default application shortcuts for various actions. It is &amp;quot;blended&amp;quot; into the configuration object if the &amp;lt;tt&amp;gt;KConfig::IncludeGlobals&amp;lt;/tt&amp;gt; flag is passed to the {{class|KConfig}} constructor, which is the default.&lt;br /&gt;
&lt;br /&gt;
=== Commonly Useful Methods ===&lt;br /&gt;
&lt;br /&gt;
To save the current state of the configuration object we call the &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; method. This method is also called when the object is destroyed. If no changes have been made or the resource reports itself as non-writable (such as in the case of the user not having write permissions to the file) then no disk activity occurs. &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; merges changes performed concurrently by other processes - local changes have priority, though.&lt;br /&gt;
&lt;br /&gt;
If we want to make sure that we have the latest values from disk we can call &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt; which calls &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; and then reloads the data from disk.&lt;br /&gt;
&lt;br /&gt;
If we need to prevent the config object from saving already made modifications to disk we need to call &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt;. A particular use case for this is rolling back the configuration to the on-disk state by calling &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt; followed by &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Listing all groups in a configuration object is as simple as calling &amp;lt;tt&amp;gt;groupList()&amp;lt;/tt&amp;gt; as in this code snippet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::mainComponent().config();&lt;br /&gt;
&lt;br /&gt;
foreach ( const QString&amp;amp; group, config.groupList() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;next group:&amp;quot; &amp;lt;&amp;lt; group;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== KSharedConfig ==&lt;br /&gt;
&lt;br /&gt;
The {{class|KSharedConfig}} class is a reference counted version of {{class|KConfig}}. It thus provides a way to reference the same configuration object from multiple places in your application without the extra overhead of separate objects or concerns about syncronizing writes to disk even if the configuration object is updated from multiple code paths. &lt;br /&gt;
&lt;br /&gt;
Accessing a {{class|KSharedConfig}} object is as easy as this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KSharedConfigPtr config = KSharedConfig::openConfig();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;openConfig()&amp;lt;/tt&amp;gt; take the same parameters as {{class|KConfig}}'s constructors do, allowing one to define which configuration file to open, flags to control merging and non-&amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; resources.&lt;br /&gt;
&lt;br /&gt;
{{class|KSharedConfig}} is generally recommended over using {{class|KConfig}} itself, and the object returned from {{class|KComponentData}} is indeed a {{class|KSharedConfig}} object.&lt;br /&gt;
&lt;br /&gt;
== KConfigGroup ==&lt;br /&gt;
&lt;br /&gt;
Now that we have a configuration object, the next step is to actually use it. The first thing we must do is to define which group of key/value pairs we wish to access in the object. We do this by creating a KConfigGroup object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig config;&lt;br /&gt;
KConfigGroup generalGroup( &amp;amp;config, &amp;quot;General&amp;quot; );&lt;br /&gt;
KConfigGroup colorsGroup = config.group( &amp;quot;Colors&amp;quot; ); // ... or a bit differently ...&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can pass {{class|KConfig}} or {{class|KSharedConfig}} objects to {{class|KConfigGroup}}.&lt;br /&gt;
&lt;br /&gt;
Config groups can be nested as well:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfigGroup subGroup1( &amp;amp;generalGroup, &amp;quot;LessGeneral&amp;quot; );&lt;br /&gt;
KConfigGroup subGroup2 = colorsGroup.group( &amp;quot;Dialogs&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Reading Entries ==&lt;br /&gt;
&lt;br /&gt;
With a {{class|KConfigGroup}} object in hand reading entries is now quite straight forward:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
QString accountName = generalGroup.readEntry( &amp;quot;Account&amp;quot;,&lt;br /&gt;
                                              QString() );&lt;br /&gt;
QColor color = colorsGroup.readEntry( &amp;quot;background&amp;quot;,&lt;br /&gt;
                                      Qt::white );&lt;br /&gt;
QStringList list = generalGroup.readEntry( &amp;quot;List&amp;quot;,&lt;br /&gt;
                                           QStringList() );&lt;br /&gt;
QString path = generalGroup.readPathEntry( &amp;quot;SaveTo&amp;quot;,&lt;br /&gt;
                                           defaultPath );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As can be seen from the above, you can mix reads from different {{class|KConfigGroup}} objects created on the same {{class|KConfig}} object. The read methods take the key, which is case sensitive, as the first argument and the default value as the second argument. This argument controls what kind of data, e.g. a color in line 3 above, is to be expected as well as the type of object returned. The returned object is wrapped in a {{qt|QVariant}} to make this magic happen.&lt;br /&gt;
&lt;br /&gt;
There are a couple of special read methods, including &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; which returns a file system path. It is vital that one uses &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; if it is a path as this enables such features as roaming profiles to work properly.&lt;br /&gt;
&lt;br /&gt;
If no such key currently exists in the configuration object, the default value is returned instead. If there is a localized (e.g. translated into another language) entry for the key that matches the current locale, that is returned.&lt;br /&gt;
&lt;br /&gt;
== Writing Entries ==&lt;br /&gt;
&lt;br /&gt;
Setting new values is similarly straightforward:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
generalGroup.writeEntry( &amp;quot;Account&amp;quot;, accountName );&lt;br /&gt;
generalGroup.writePathEntry( &amp;quot;SaveTo&amp;quot;, savePath );&lt;br /&gt;
colorGroup.writeEntry( &amp;quot;background&amp;quot;, color );&lt;br /&gt;
generalGroup.config()-&amp;gt;sync();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note the use of &amp;lt;tt&amp;gt;writePathEntry&amp;lt;/tt&amp;gt; and how the type of object we use, such as {{qt|QColor}} on line 3, dictates how the data is serialized. Additionally, once we are done writing entries, &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; must be called on the config object for it to be saved to disk. We can also simply wait for the object to be destroyed, which triggers an automatic &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; if necessary.&lt;br /&gt;
&lt;br /&gt;
== KDesktopFile: A Special Case ==&lt;br /&gt;
&lt;br /&gt;
When is a configuration file not a configuration file? When it is a [http://freedesktop.org/wiki/Standards_2fdesktop_2dentry_2dspec desktop file]. These files, which are essentially configuration files at their heart, are used  to describe entries for application menus, mimetypes, plugins and various services.&lt;br /&gt;
&lt;br /&gt;
When accessing a .desktop file, one should instead use the {{class|KDesktopFile}} class which, while a {{class|KConfig}} class offering all the capabilities described above, offers a set of methods designed to make accessing standard attributes of these files consistent and reliable.&lt;br /&gt;
&lt;br /&gt;
== Kiosk: Lockdown and User/Group Profiles ==&lt;br /&gt;
&lt;br /&gt;
KConfig provides a powerful set of lockdown and configuration definition capabilities, collectively known as &amp;quot;Kiosk&amp;quot;, that many system administrators and system integrators rely on. While most of this framework is provided transparently to the application, there is occassion when an application will want to check on the read/write status of a configuration object.&lt;br /&gt;
&lt;br /&gt;
Entries in configuration objects that are locked down using the kiosk facilities are said to be ''immutable''. An application can check for immutability of entire configuration objects, groups or keys as shown in this example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::config();&lt;br /&gt;
&lt;br /&gt;
if ( config-&amp;gt;isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;configuration object is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
KConfigGroup group(config, &amp;quot;General&amp;quot;);&lt;br /&gt;
if ( group.isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;group General is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if ( group.entryIsImmutable(&amp;quot;URL&amp;quot;) ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;URL entry in group General is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This can be useful in particular situations where an action should be taken when an item is immutable. For instance, the KDE panels will not offer configuration options to the user or allow them to otherwise change the order of applets and icons when the panel's configuration object is marked as immutable.&lt;br /&gt;
&lt;br /&gt;
== KConfig XT ==&lt;br /&gt;
&lt;br /&gt;
There is a way to make certain use cases of KConfig easier, faster and more reliable: KConfig XT. In particular, for main application or plugin configuration objects and when syncing configuration dialogs and other interfaces with these values, KConfig XT can help immensely. It also  simultaneously documents the configuration options available, which makes every sys admin and system integrator that uses KDE that much more happy.&lt;br /&gt;
&lt;br /&gt;
[[../Using_KConfig_XT|The next tutorial in the KConfig series covers what KConfig XT is and how to use it.]]&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials/KConfig_(de)</id>
		<title>Development/Tutorials/KConfig (de)</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials/KConfig_(de)"/>
				<updated>2008-01-01T15:28:33Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: /* Zusammenfassung */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:I18n/Language Navigation Bar|Development/Tutorials/KConfig}}&lt;br /&gt;
&lt;br /&gt;
{{TutorialBrowser (de)|&lt;br /&gt;
&lt;br /&gt;
series=KConfig|&lt;br /&gt;
&lt;br /&gt;
name=Einführung in KConfig|&lt;br /&gt;
&lt;br /&gt;
pre=Keine|&lt;br /&gt;
&lt;br /&gt;
next=[[../Using_KConfig_XT (de)|Benutzen von KConfig XT]]|&lt;br /&gt;
&lt;br /&gt;
reading=Keine&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Zusammenfassung ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dieser Artikel beschäftigt sich mir dem KDE Einstellungdaten-System, angefangen mit einer Übersicht über den grundlegenden Aufbau aus der Sicht eines Entwicklers. Es wirft ausserdem einen Blick auf jede der Klassen, die für die Entwicklung von Anwendungen relevant sind und fährt dann mit kiosk (Benutzer und Gruppen Profile) Integration fort.&lt;br /&gt;
&lt;br /&gt;
== Grundlegender Aufbau ==&lt;br /&gt;
&lt;br /&gt;
KConfig ist ausgelegt um das Konzept vom eigentlichen Speichern und Auffinden von Konfigurationsdaten hinter eine Programmierschnittstelle zu abstrahieren die es ermöglicht, auf einfache Weise Informationen abzurufen und zu setzen. Wo oder in welcher Form Daten gespeichert werden ist für eine Anwendung die KConfig benutzt irrelevant.&lt;br /&gt;
&lt;br /&gt;
Das behält alle KDE Anwendungen konsistent in ihrer Art, Konfigurationen handzuhaben und nimmt einem Anwendungs-Entwickler die Arbeit so ein System von Grund auf neu zu schreiben, was ein sehr fehleranfälliger Prozess sein kann.&lt;br /&gt;
&lt;br /&gt;
Jedes KConfig Objekt verkörpert ein einziges Konfigurationsobjekt. Jedes Konfigurationsobjekt ist durch seinen einzigartigen Namen gekennzeichnet und kann von mehreren lokalen oder externen Daten oder Services gelesen werden. Jede Anwendung hat standardmässig ein zugehöriges Konfigurationsobjekt und es gibt auch ein globales Konfigurationsobjekt.&lt;br /&gt;
&lt;br /&gt;
Diese Konfigurationsobjekte sind nach einer zweistufigen Hierarchie getrennt: Gruppen und Schlüssel. Ein Konfigurationsobjekt kann eine beliebige Anzahl an Gruppen haben und jede Gruppe kann einen oder mehrere Schlüssel mit zugehörigen Werten haben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die gespeicherten Werte können aus beliebig vielen verschiedenen Datentypen bestehen. Sie werden gespeichert und abgerufen als das Objekt selbst. Zum Beispiel wird ein {{qt|QObject}}-Objekt direkt einem Konfigurationsobjekt übergeben, wenn es einen Farbwert speichert und wenn ein Farbwert abgerufen wird, wird ein {{qt|QObject}}-Objekt zurückgegeben.&lt;br /&gt;
&lt;br /&gt;
TODO: (deserialization?)&lt;br /&gt;
&lt;br /&gt;
Anwendungen selbst müssen darum normalerweise Objekte nicht selber gliedern und entgliedern.&lt;br /&gt;
&lt;br /&gt;
Applications themselves therefore generally do not have to perform serialization and deserialization of objects themselves.&lt;br /&gt;
&lt;br /&gt;
== The KConfig Class ==&lt;br /&gt;
&lt;br /&gt;
The {{class|KConfig}} object is used to access a given configuration object. There are a number of ways to create a config object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
// a plain old read/write config object&lt;br /&gt;
KConfig config(&amp;quot;myapprc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// a specific file in the filesystem&lt;br /&gt;
// currently must be an INI style file&lt;br /&gt;
KConfig fullPath(&amp;quot;/etc/kderc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// not merged with global values&lt;br /&gt;
KConfig globalFree( &amp;quot;localsrc&amp;quot;, KConfig::NoGlobals );&lt;br /&gt;
&lt;br /&gt;
// not merged with globals or the $KDEDIRS hierarchy&lt;br /&gt;
KConfig simpleConfig( &amp;quot;simplerc&amp;quot;, KConfig::SimpleConfig );&lt;br /&gt;
&lt;br /&gt;
// config specific to a component, in this case a plugin&lt;br /&gt;
KConfig pluginConfig( componentData(), &amp;quot;pluginrc&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
// outside the standard config resource&lt;br /&gt;
KConfig dataResource( &amp;quot;data&amp;quot;, &amp;quot;myapp/somefile&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The KConfig object create on line 2 is a regular config object. We can read values from it, write new entries and ask for various properties of the object.  This object will be loaded from the config resource as determined by {{class|KStandardDirs}}, meaning that every instance of the &amp;lt;tt&amp;gt;myapprc&amp;lt;/tt&amp;gt; object in each of the directories in the config resource hierarchy will be merged to create the values seen in this object. This is how system wide and per-user/group profiles are generated and supported and it all happens transparently to the application itself.&lt;br /&gt;
&lt;br /&gt;
{{tip|For more information on how the merging works, see the [[KDE System Administration/KDE_Filesystem_Hierarchy|KDE Filesystem Hierarchy]] article.}}&lt;br /&gt;
&lt;br /&gt;
On line 6 we open a specific local file, this case {{path|/etc/kderc}}. This performs no merging of values and expects an INI style file.&lt;br /&gt;
&lt;br /&gt;
Line 9 sees the creation of a configuration object that is not merged with the global &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt; configuration object, while the configuration file on line 12 is additionally not merged with any files in the &amp;lt;tt&amp;gt;$KDEDIRS&amp;lt;/tt&amp;gt; hierarchy. This can noticeably improve performance in the case where one is simply reading values out of a simple configuration for which global values are not meaningful.&lt;br /&gt;
&lt;br /&gt;
Line 15 creates a configuration object using the {{class|KComponentData}} object that belongs to a plugin or other component. The plugin may have a different set of directories defined in its {{class|KStandardDirs}} and this is a way of ensuring that {{class|KConfig}} respects this.&lt;br /&gt;
&lt;br /&gt;
Finally on line 18 we see the creation of a configuration object that does not exist in the &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; resource but rather in the application &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; resource. You may use any resource that {{class|KStandardDirs}} is aware of, including ones that are added at runtime.&lt;br /&gt;
&lt;br /&gt;
=== Special Configuration Objects ===&lt;br /&gt;
&lt;br /&gt;
Each application has its own configuration object that uses the name provided to {{class|KAboutData}} appended with &amp;quot;rc&amp;quot; as its name. So an app named &amp;quot;myapp&amp;quot; would have the default configuration object of &amp;quot;myapprc&amp;quot;. This configuration file can be retrieved in this way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KComponentData&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
#include &amp;lt;KGlobal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    // note that this is actually a KSharedConfig&lt;br /&gt;
    // more on that class in a bit!&lt;br /&gt;
    KConfig* config = KGlobal::config();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The default configuration object for the application is accessed when no name is specified when creating a {{class|KConfig}} object. So we could also do this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    KConfig config;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additionally, each component may have its own configuration object. This is generally accessed via the plugin's &amp;lt;tt&amp;gt;componentData()&amp;lt;/tt&amp;gt; rather than &amp;lt;tt&amp;gt;{{class|KGlobal}}::mainComponent()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Finally there is a global configuration object, &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt;, that is shared by every application. It holds such information as the default application shortcuts for various actions. It is &amp;quot;blended&amp;quot; into the configuration object if the &amp;lt;tt&amp;gt;KConfig::IncludeGlobals&amp;lt;/tt&amp;gt; flag is passed to the {{class|KConfig}} constructor, which is the default.&lt;br /&gt;
&lt;br /&gt;
=== Commonly Useful Methods ===&lt;br /&gt;
&lt;br /&gt;
To save the current state of the configuration object we call the &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; method. This method is also called when the object is destroyed. If no changes have been made or the resource reports itself as non-writable (such as in the case of the user not having write permissions to the file) then no disk activity occurs. &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; merges changes performed concurrently by other processes - local changes have priority, though.&lt;br /&gt;
&lt;br /&gt;
If we want to make sure that we have the latest values from disk we can call &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt; which calls &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; and then reloads the data from disk.&lt;br /&gt;
&lt;br /&gt;
If we need to prevent the config object from saving already made modifications to disk we need to call &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt;. A particular use case for this is rolling back the configuration to the on-disk state by calling &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt; followed by &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Listing all groups in a configuration object is as simple as calling &amp;lt;tt&amp;gt;groupList()&amp;lt;/tt&amp;gt; as in this code snippet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::mainComponent().config();&lt;br /&gt;
&lt;br /&gt;
foreach ( const QString&amp;amp; group, config.groupList() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;next group:&amp;quot; &amp;lt;&amp;lt; group;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== KSharedConfig ==&lt;br /&gt;
&lt;br /&gt;
The {{class|KSharedConfig}} class is a reference counted version of {{class|KConfig}}. It thus provides a way to reference the same configuration object from multiple places in your application without the extra overhead of separate objects or concerns about syncronizing writes to disk even if the configuration object is updated from multiple code paths. &lt;br /&gt;
&lt;br /&gt;
Accessing a {{class|KSharedConfig}} object is as easy as this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KSharedConfigPtr config = KSharedConfig::openConfig();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;openConfig()&amp;lt;/tt&amp;gt; take the same parameters as {{class|KConfig}}'s constructors do, allowing one to define which configuration file to open, flags to control merging and non-&amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; resources.&lt;br /&gt;
&lt;br /&gt;
{{class|KSharedConfig}} is generally recommended over using {{class|KConfig}} itself, and the object returned from {{class|KComponentData}} is indeed a {{class|KSharedConfig}} object.&lt;br /&gt;
&lt;br /&gt;
== KConfigGroup ==&lt;br /&gt;
&lt;br /&gt;
Now that we have a configuration object, the next step is to actually use it. The first thing we must do is to define which group of key/value pairs we wish to access in the object. We do this by creating a KConfigGroup object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig config;&lt;br /&gt;
KConfigGroup generalGroup( &amp;amp;config, &amp;quot;General&amp;quot; );&lt;br /&gt;
KConfigGroup colorsGroup = config.group( &amp;quot;Colors&amp;quot; ); // ... or a bit differently ...&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can pass {{class|KConfig}} or {{class|KSharedConfig}} objects to {{class|KConfigGroup}}.&lt;br /&gt;
&lt;br /&gt;
Config groups can be nested as well:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfigGroup subGroup1( &amp;amp;generalGroup, &amp;quot;LessGeneral&amp;quot; );&lt;br /&gt;
KConfigGroup subGroup2 = colorsGroup.group( &amp;quot;Dialogs&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Reading Entries ==&lt;br /&gt;
&lt;br /&gt;
With a {{class|KConfigGroup}} object in hand reading entries is now quite straight forward:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
QString accountName = generalGroup.readEntry( &amp;quot;Account&amp;quot;,&lt;br /&gt;
                                              QString() );&lt;br /&gt;
QColor color = colorsGroup.readEntry( &amp;quot;background&amp;quot;,&lt;br /&gt;
                                      Qt::white );&lt;br /&gt;
QStringList list = generalGroup.readEntry( &amp;quot;List&amp;quot;,&lt;br /&gt;
                                           QStringList() );&lt;br /&gt;
QString path = generalGroup.readPathEntry( &amp;quot;SaveTo&amp;quot;,&lt;br /&gt;
                                           defaultPath );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As can be seen from the above, you can mix reads from different {{class|KConfigGroup}} objects created on the same {{class|KConfig}} object. The read methods take the key, which is case sensitive, as the first argument and the default value as the second argument. This argument controls what kind of data, e.g. a color in line 3 above, is to be expected as well as the type of object returned. The returned object is wrapped in a {{qt|QVariant}} to make this magic happen.&lt;br /&gt;
&lt;br /&gt;
There are a couple of special read methods, including &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; which returns a file system path. It is vital that one uses &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; if it is a path as this enables such features as roaming profiles to work properly.&lt;br /&gt;
&lt;br /&gt;
If no such key currently exists in the configuration object, the default value is returned instead. If there is a localized (e.g. translated into another language) entry for the key that matches the current locale, that is returned.&lt;br /&gt;
&lt;br /&gt;
== Writing Entries ==&lt;br /&gt;
&lt;br /&gt;
Setting new values is similarly straightforward:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
generalGroup.writeEntry( &amp;quot;Account&amp;quot;, accountName );&lt;br /&gt;
generalGroup.writePathEntry( &amp;quot;SaveTo&amp;quot;, savePath );&lt;br /&gt;
colorGroup.writeEntry( &amp;quot;background&amp;quot;, color );&lt;br /&gt;
generalGroup.config()-&amp;gt;sync();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note the use of &amp;lt;tt&amp;gt;writePathEntry&amp;lt;/tt&amp;gt; and how the type of object we use, such as {{qt|QColor}} on line 3, dictates how the data is serialized. Additionally, once we are done writing entries, &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; must be called on the config object for it to be saved to disk. We can also simply wait for the object to be destroyed, which triggers an automatic &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; if necessary.&lt;br /&gt;
&lt;br /&gt;
== KDesktopFile: A Special Case ==&lt;br /&gt;
&lt;br /&gt;
When is a configuration file not a configuration file? When it is a [http://freedesktop.org/wiki/Standards_2fdesktop_2dentry_2dspec desktop file]. These files, which are essentially configuration files at their heart, are used  to describe entries for application menus, mimetypes, plugins and various services.&lt;br /&gt;
&lt;br /&gt;
When accessing a .desktop file, one should instead use the {{class|KDesktopFile}} class which, while a {{class|KConfig}} class offering all the capabilities described above, offers a set of methods designed to make accessing standard attributes of these files consistent and reliable.&lt;br /&gt;
&lt;br /&gt;
== Kiosk: Lockdown and User/Group Profiles ==&lt;br /&gt;
&lt;br /&gt;
KConfig provides a powerful set of lockdown and configuration definition capabilities, collectively known as &amp;quot;Kiosk&amp;quot;, that many system administrators and system integrators rely on. While most of this framework is provided transparently to the application, there is occassion when an application will want to check on the read/write status of a configuration object.&lt;br /&gt;
&lt;br /&gt;
Entries in configuration objects that are locked down using the kiosk facilities are said to be ''immutable''. An application can check for immutability of entire configuration objects, groups or keys as shown in this example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::config();&lt;br /&gt;
&lt;br /&gt;
if ( config-&amp;gt;isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;configuration object is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
KConfigGroup group(config, &amp;quot;General&amp;quot;);&lt;br /&gt;
if ( group.isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;group General is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if ( group.entryIsImmutable(&amp;quot;URL&amp;quot;) ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;URL entry in group General is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This can be useful in particular situations where an action should be taken when an item is immutable. For instance, the KDE panels will not offer configuration options to the user or allow them to otherwise change the order of applets and icons when the panel's configuration object is marked as immutable.&lt;br /&gt;
&lt;br /&gt;
== KConfig XT ==&lt;br /&gt;
&lt;br /&gt;
There is a way to make certain use cases of KConfig easier, faster and more reliable: KConfig XT. In particular, for main application or plugin configuration objects and when syncing configuration dialogs and other interfaces with these values, KConfig XT can help immensely. It also  simultaneously documents the configuration options available, which makes every sys admin and system integrator that uses KDE that much more happy.&lt;br /&gt;
&lt;br /&gt;
[[../Using_KConfig_XT|The next tutorial in the KConfig series covers what KConfig XT is and how to use it.]]&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials/KConfig_(de)</id>
		<title>Development/Tutorials/KConfig (de)</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials/KConfig_(de)"/>
				<updated>2008-01-01T15:27:57Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: /* Grundlegender Aufbau */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:I18n/Language Navigation Bar|Development/Tutorials/KConfig}}&lt;br /&gt;
&lt;br /&gt;
{{TutorialBrowser (de)|&lt;br /&gt;
&lt;br /&gt;
series=KConfig|&lt;br /&gt;
&lt;br /&gt;
name=Einführung in KConfig|&lt;br /&gt;
&lt;br /&gt;
pre=Keine|&lt;br /&gt;
&lt;br /&gt;
next=[[../Using_KConfig_XT (de)|Benutzen von KConfig XT]]|&lt;br /&gt;
&lt;br /&gt;
reading=Keine&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Zusammenfassung ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dieser Artikel beschäftigt sich mir dem KDE Einstellungdaten-System, angefangen mit einer Übersicht über die Grundlagen des Aufbaus aus der Sicht eines Entwicklers. Es wirft ausserdem einen Blick auf jede der Klassen, die für die Entwicklung von Anwendungen relevant sind und fährt dann mit kiosk (Benutzer und Gruppen Profile) Integration fort.&lt;br /&gt;
&lt;br /&gt;
== Grundlegender Aufbau ==&lt;br /&gt;
&lt;br /&gt;
KConfig ist ausgelegt um das Konzept vom eigentlichen Speichern und Auffinden von Konfigurationsdaten hinter eine Programmierschnittstelle zu abstrahieren die es ermöglicht, auf einfache Weise Informationen abzurufen und zu setzen. Wo oder in welcher Form Daten gespeichert werden ist für eine Anwendung die KConfig benutzt irrelevant.&lt;br /&gt;
&lt;br /&gt;
Das behält alle KDE Anwendungen konsistent in ihrer Art, Konfigurationen handzuhaben und nimmt einem Anwendungs-Entwickler die Arbeit so ein System von Grund auf neu zu schreiben, was ein sehr fehleranfälliger Prozess sein kann.&lt;br /&gt;
&lt;br /&gt;
Jedes KConfig Objekt verkörpert ein einziges Konfigurationsobjekt. Jedes Konfigurationsobjekt ist durch seinen einzigartigen Namen gekennzeichnet und kann von mehreren lokalen oder externen Daten oder Services gelesen werden. Jede Anwendung hat standardmässig ein zugehöriges Konfigurationsobjekt und es gibt auch ein globales Konfigurationsobjekt.&lt;br /&gt;
&lt;br /&gt;
Diese Konfigurationsobjekte sind nach einer zweistufigen Hierarchie getrennt: Gruppen und Schlüssel. Ein Konfigurationsobjekt kann eine beliebige Anzahl an Gruppen haben und jede Gruppe kann einen oder mehrere Schlüssel mit zugehörigen Werten haben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die gespeicherten Werte können aus beliebig vielen verschiedenen Datentypen bestehen. Sie werden gespeichert und abgerufen als das Objekt selbst. Zum Beispiel wird ein {{qt|QObject}}-Objekt direkt einem Konfigurationsobjekt übergeben, wenn es einen Farbwert speichert und wenn ein Farbwert abgerufen wird, wird ein {{qt|QObject}}-Objekt zurückgegeben.&lt;br /&gt;
&lt;br /&gt;
TODO: (deserialization?)&lt;br /&gt;
&lt;br /&gt;
Anwendungen selbst müssen darum normalerweise Objekte nicht selber gliedern und entgliedern.&lt;br /&gt;
&lt;br /&gt;
Applications themselves therefore generally do not have to perform serialization and deserialization of objects themselves.&lt;br /&gt;
&lt;br /&gt;
== The KConfig Class ==&lt;br /&gt;
&lt;br /&gt;
The {{class|KConfig}} object is used to access a given configuration object. There are a number of ways to create a config object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
// a plain old read/write config object&lt;br /&gt;
KConfig config(&amp;quot;myapprc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// a specific file in the filesystem&lt;br /&gt;
// currently must be an INI style file&lt;br /&gt;
KConfig fullPath(&amp;quot;/etc/kderc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// not merged with global values&lt;br /&gt;
KConfig globalFree( &amp;quot;localsrc&amp;quot;, KConfig::NoGlobals );&lt;br /&gt;
&lt;br /&gt;
// not merged with globals or the $KDEDIRS hierarchy&lt;br /&gt;
KConfig simpleConfig( &amp;quot;simplerc&amp;quot;, KConfig::SimpleConfig );&lt;br /&gt;
&lt;br /&gt;
// config specific to a component, in this case a plugin&lt;br /&gt;
KConfig pluginConfig( componentData(), &amp;quot;pluginrc&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
// outside the standard config resource&lt;br /&gt;
KConfig dataResource( &amp;quot;data&amp;quot;, &amp;quot;myapp/somefile&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The KConfig object create on line 2 is a regular config object. We can read values from it, write new entries and ask for various properties of the object.  This object will be loaded from the config resource as determined by {{class|KStandardDirs}}, meaning that every instance of the &amp;lt;tt&amp;gt;myapprc&amp;lt;/tt&amp;gt; object in each of the directories in the config resource hierarchy will be merged to create the values seen in this object. This is how system wide and per-user/group profiles are generated and supported and it all happens transparently to the application itself.&lt;br /&gt;
&lt;br /&gt;
{{tip|For more information on how the merging works, see the [[KDE System Administration/KDE_Filesystem_Hierarchy|KDE Filesystem Hierarchy]] article.}}&lt;br /&gt;
&lt;br /&gt;
On line 6 we open a specific local file, this case {{path|/etc/kderc}}. This performs no merging of values and expects an INI style file.&lt;br /&gt;
&lt;br /&gt;
Line 9 sees the creation of a configuration object that is not merged with the global &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt; configuration object, while the configuration file on line 12 is additionally not merged with any files in the &amp;lt;tt&amp;gt;$KDEDIRS&amp;lt;/tt&amp;gt; hierarchy. This can noticeably improve performance in the case where one is simply reading values out of a simple configuration for which global values are not meaningful.&lt;br /&gt;
&lt;br /&gt;
Line 15 creates a configuration object using the {{class|KComponentData}} object that belongs to a plugin or other component. The plugin may have a different set of directories defined in its {{class|KStandardDirs}} and this is a way of ensuring that {{class|KConfig}} respects this.&lt;br /&gt;
&lt;br /&gt;
Finally on line 18 we see the creation of a configuration object that does not exist in the &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; resource but rather in the application &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; resource. You may use any resource that {{class|KStandardDirs}} is aware of, including ones that are added at runtime.&lt;br /&gt;
&lt;br /&gt;
=== Special Configuration Objects ===&lt;br /&gt;
&lt;br /&gt;
Each application has its own configuration object that uses the name provided to {{class|KAboutData}} appended with &amp;quot;rc&amp;quot; as its name. So an app named &amp;quot;myapp&amp;quot; would have the default configuration object of &amp;quot;myapprc&amp;quot;. This configuration file can be retrieved in this way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KComponentData&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
#include &amp;lt;KGlobal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    // note that this is actually a KSharedConfig&lt;br /&gt;
    // more on that class in a bit!&lt;br /&gt;
    KConfig* config = KGlobal::config();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The default configuration object for the application is accessed when no name is specified when creating a {{class|KConfig}} object. So we could also do this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    KConfig config;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additionally, each component may have its own configuration object. This is generally accessed via the plugin's &amp;lt;tt&amp;gt;componentData()&amp;lt;/tt&amp;gt; rather than &amp;lt;tt&amp;gt;{{class|KGlobal}}::mainComponent()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Finally there is a global configuration object, &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt;, that is shared by every application. It holds such information as the default application shortcuts for various actions. It is &amp;quot;blended&amp;quot; into the configuration object if the &amp;lt;tt&amp;gt;KConfig::IncludeGlobals&amp;lt;/tt&amp;gt; flag is passed to the {{class|KConfig}} constructor, which is the default.&lt;br /&gt;
&lt;br /&gt;
=== Commonly Useful Methods ===&lt;br /&gt;
&lt;br /&gt;
To save the current state of the configuration object we call the &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; method. This method is also called when the object is destroyed. If no changes have been made or the resource reports itself as non-writable (such as in the case of the user not having write permissions to the file) then no disk activity occurs. &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; merges changes performed concurrently by other processes - local changes have priority, though.&lt;br /&gt;
&lt;br /&gt;
If we want to make sure that we have the latest values from disk we can call &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt; which calls &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; and then reloads the data from disk.&lt;br /&gt;
&lt;br /&gt;
If we need to prevent the config object from saving already made modifications to disk we need to call &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt;. A particular use case for this is rolling back the configuration to the on-disk state by calling &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt; followed by &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Listing all groups in a configuration object is as simple as calling &amp;lt;tt&amp;gt;groupList()&amp;lt;/tt&amp;gt; as in this code snippet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::mainComponent().config();&lt;br /&gt;
&lt;br /&gt;
foreach ( const QString&amp;amp; group, config.groupList() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;next group:&amp;quot; &amp;lt;&amp;lt; group;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== KSharedConfig ==&lt;br /&gt;
&lt;br /&gt;
The {{class|KSharedConfig}} class is a reference counted version of {{class|KConfig}}. It thus provides a way to reference the same configuration object from multiple places in your application without the extra overhead of separate objects or concerns about syncronizing writes to disk even if the configuration object is updated from multiple code paths. &lt;br /&gt;
&lt;br /&gt;
Accessing a {{class|KSharedConfig}} object is as easy as this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KSharedConfigPtr config = KSharedConfig::openConfig();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;openConfig()&amp;lt;/tt&amp;gt; take the same parameters as {{class|KConfig}}'s constructors do, allowing one to define which configuration file to open, flags to control merging and non-&amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; resources.&lt;br /&gt;
&lt;br /&gt;
{{class|KSharedConfig}} is generally recommended over using {{class|KConfig}} itself, and the object returned from {{class|KComponentData}} is indeed a {{class|KSharedConfig}} object.&lt;br /&gt;
&lt;br /&gt;
== KConfigGroup ==&lt;br /&gt;
&lt;br /&gt;
Now that we have a configuration object, the next step is to actually use it. The first thing we must do is to define which group of key/value pairs we wish to access in the object. We do this by creating a KConfigGroup object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig config;&lt;br /&gt;
KConfigGroup generalGroup( &amp;amp;config, &amp;quot;General&amp;quot; );&lt;br /&gt;
KConfigGroup colorsGroup = config.group( &amp;quot;Colors&amp;quot; ); // ... or a bit differently ...&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can pass {{class|KConfig}} or {{class|KSharedConfig}} objects to {{class|KConfigGroup}}.&lt;br /&gt;
&lt;br /&gt;
Config groups can be nested as well:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfigGroup subGroup1( &amp;amp;generalGroup, &amp;quot;LessGeneral&amp;quot; );&lt;br /&gt;
KConfigGroup subGroup2 = colorsGroup.group( &amp;quot;Dialogs&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Reading Entries ==&lt;br /&gt;
&lt;br /&gt;
With a {{class|KConfigGroup}} object in hand reading entries is now quite straight forward:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
QString accountName = generalGroup.readEntry( &amp;quot;Account&amp;quot;,&lt;br /&gt;
                                              QString() );&lt;br /&gt;
QColor color = colorsGroup.readEntry( &amp;quot;background&amp;quot;,&lt;br /&gt;
                                      Qt::white );&lt;br /&gt;
QStringList list = generalGroup.readEntry( &amp;quot;List&amp;quot;,&lt;br /&gt;
                                           QStringList() );&lt;br /&gt;
QString path = generalGroup.readPathEntry( &amp;quot;SaveTo&amp;quot;,&lt;br /&gt;
                                           defaultPath );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As can be seen from the above, you can mix reads from different {{class|KConfigGroup}} objects created on the same {{class|KConfig}} object. The read methods take the key, which is case sensitive, as the first argument and the default value as the second argument. This argument controls what kind of data, e.g. a color in line 3 above, is to be expected as well as the type of object returned. The returned object is wrapped in a {{qt|QVariant}} to make this magic happen.&lt;br /&gt;
&lt;br /&gt;
There are a couple of special read methods, including &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; which returns a file system path. It is vital that one uses &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; if it is a path as this enables such features as roaming profiles to work properly.&lt;br /&gt;
&lt;br /&gt;
If no such key currently exists in the configuration object, the default value is returned instead. If there is a localized (e.g. translated into another language) entry for the key that matches the current locale, that is returned.&lt;br /&gt;
&lt;br /&gt;
== Writing Entries ==&lt;br /&gt;
&lt;br /&gt;
Setting new values is similarly straightforward:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
generalGroup.writeEntry( &amp;quot;Account&amp;quot;, accountName );&lt;br /&gt;
generalGroup.writePathEntry( &amp;quot;SaveTo&amp;quot;, savePath );&lt;br /&gt;
colorGroup.writeEntry( &amp;quot;background&amp;quot;, color );&lt;br /&gt;
generalGroup.config()-&amp;gt;sync();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note the use of &amp;lt;tt&amp;gt;writePathEntry&amp;lt;/tt&amp;gt; and how the type of object we use, such as {{qt|QColor}} on line 3, dictates how the data is serialized. Additionally, once we are done writing entries, &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; must be called on the config object for it to be saved to disk. We can also simply wait for the object to be destroyed, which triggers an automatic &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; if necessary.&lt;br /&gt;
&lt;br /&gt;
== KDesktopFile: A Special Case ==&lt;br /&gt;
&lt;br /&gt;
When is a configuration file not a configuration file? When it is a [http://freedesktop.org/wiki/Standards_2fdesktop_2dentry_2dspec desktop file]. These files, which are essentially configuration files at their heart, are used  to describe entries for application menus, mimetypes, plugins and various services.&lt;br /&gt;
&lt;br /&gt;
When accessing a .desktop file, one should instead use the {{class|KDesktopFile}} class which, while a {{class|KConfig}} class offering all the capabilities described above, offers a set of methods designed to make accessing standard attributes of these files consistent and reliable.&lt;br /&gt;
&lt;br /&gt;
== Kiosk: Lockdown and User/Group Profiles ==&lt;br /&gt;
&lt;br /&gt;
KConfig provides a powerful set of lockdown and configuration definition capabilities, collectively known as &amp;quot;Kiosk&amp;quot;, that many system administrators and system integrators rely on. While most of this framework is provided transparently to the application, there is occassion when an application will want to check on the read/write status of a configuration object.&lt;br /&gt;
&lt;br /&gt;
Entries in configuration objects that are locked down using the kiosk facilities are said to be ''immutable''. An application can check for immutability of entire configuration objects, groups or keys as shown in this example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::config();&lt;br /&gt;
&lt;br /&gt;
if ( config-&amp;gt;isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;configuration object is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
KConfigGroup group(config, &amp;quot;General&amp;quot;);&lt;br /&gt;
if ( group.isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;group General is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if ( group.entryIsImmutable(&amp;quot;URL&amp;quot;) ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;URL entry in group General is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This can be useful in particular situations where an action should be taken when an item is immutable. For instance, the KDE panels will not offer configuration options to the user or allow them to otherwise change the order of applets and icons when the panel's configuration object is marked as immutable.&lt;br /&gt;
&lt;br /&gt;
== KConfig XT ==&lt;br /&gt;
&lt;br /&gt;
There is a way to make certain use cases of KConfig easier, faster and more reliable: KConfig XT. In particular, for main application or plugin configuration objects and when syncing configuration dialogs and other interfaces with these values, KConfig XT can help immensely. It also  simultaneously documents the configuration options available, which makes every sys admin and system integrator that uses KDE that much more happy.&lt;br /&gt;
&lt;br /&gt;
[[../Using_KConfig_XT|The next tutorial in the KConfig series covers what KConfig XT is and how to use it.]]&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials/KConfig_(de)</id>
		<title>Development/Tutorials/KConfig (de)</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials/KConfig_(de)"/>
				<updated>2008-01-01T14:49:24Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: /* Grundlagen des Aufbaus */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:I18n/Language Navigation Bar|Development/Tutorials/KConfig}}&lt;br /&gt;
&lt;br /&gt;
{{TutorialBrowser (de)|&lt;br /&gt;
&lt;br /&gt;
series=KConfig|&lt;br /&gt;
&lt;br /&gt;
name=Einführung in KConfig|&lt;br /&gt;
&lt;br /&gt;
pre=Keine|&lt;br /&gt;
&lt;br /&gt;
next=[[../Using_KConfig_XT (de)|Benutzen von KConfig XT]]|&lt;br /&gt;
&lt;br /&gt;
reading=Keine&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Zusammenfassung ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dieser Artikel beschäftigt sich mir dem KDE Einstellungdaten-System, angefangen mit einer Übersicht über die Grundlagen des Aufbaus aus der Sicht eines Entwicklers. Es wirft ausserdem einen Blick auf jede der Klassen, die für die Entwicklung von Anwendungen relevant sind und fährt dann mit kiosk (Benutzer und Gruppen Profile) Integration fort.&lt;br /&gt;
&lt;br /&gt;
== Grundlegender Aufbau ==&lt;br /&gt;
&lt;br /&gt;
KConfig ist ausgelegt um das Konzept vom eigentlichen Speichern und Auffinden von Konfigurationsdaten hinter eine Programmierschnittstelle zu abstrahieren die es ermöglicht, auf einfache Weise Informationen abzurufen und zu setzen. Wo oder in welcher Form Daten gespeichert werden ist für eine Anwendung die KConfig benutzt irrelevant.&lt;br /&gt;
&lt;br /&gt;
Das behält alle KDE Anwendungen konsistent in ihrer Art, Konfigurationen handzuhaben und nimmt einem Anwendungs-Entwickler die Arbeit so ein System von Grund auf neu zu schreiben, was ein sehr fehleranfälliger Prozess sein kann.&lt;br /&gt;
&lt;br /&gt;
Jedes KConfig Objekt verkörpert ein einziges Konfigurationsobjekt. Jedes Konfigurationsobjekt ist durch seinen einzigartigen Namen gekennzeichnet und kann von mehreren lokalen oder externen Daten oder Services gelesen werden. Jede Anwendung hat standardmässig ein zugehöriges Konfigurationsobjekt und es gibt auch ein globales Konfigurationsobjekt.&lt;br /&gt;
&lt;br /&gt;
TODO:&lt;br /&gt;
&lt;br /&gt;
These configuration objects are broken down into a two level hierarchy: groups and keys. A configuration object can have any number of groups and each group can have one or more keys with associated values.&lt;br /&gt;
&lt;br /&gt;
Values stored may be of any number of data types. They are stored and retreived as the objects themselves. For example, a {{qt|QObject}} object is passed to a config object directly when storing a color value and when retreived a {{qt|QObject}} object is returned. Applications themselves therefore generally do not have to perform serialization and deserialization of objects themselves.&lt;br /&gt;
&lt;br /&gt;
== The KConfig Class ==&lt;br /&gt;
&lt;br /&gt;
The {{class|KConfig}} object is used to access a given configuration object. There are a number of ways to create a config object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
// a plain old read/write config object&lt;br /&gt;
KConfig config(&amp;quot;myapprc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// a specific file in the filesystem&lt;br /&gt;
// currently must be an INI style file&lt;br /&gt;
KConfig fullPath(&amp;quot;/etc/kderc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// not merged with global values&lt;br /&gt;
KConfig globalFree( &amp;quot;localsrc&amp;quot;, KConfig::NoGlobals );&lt;br /&gt;
&lt;br /&gt;
// not merged with globals or the $KDEDIRS hierarchy&lt;br /&gt;
KConfig simpleConfig( &amp;quot;simplerc&amp;quot;, KConfig::SimpleConfig );&lt;br /&gt;
&lt;br /&gt;
// config specific to a component, in this case a plugin&lt;br /&gt;
KConfig pluginConfig( componentData(), &amp;quot;pluginrc&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
// outside the standard config resource&lt;br /&gt;
KConfig dataResource( &amp;quot;data&amp;quot;, &amp;quot;myapp/somefile&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The KConfig object create on line 2 is a regular config object. We can read values from it, write new entries and ask for various properties of the object.  This object will be loaded from the config resource as determined by {{class|KStandardDirs}}, meaning that every instance of the &amp;lt;tt&amp;gt;myapprc&amp;lt;/tt&amp;gt; object in each of the directories in the config resource hierarchy will be merged to create the values seen in this object. This is how system wide and per-user/group profiles are generated and supported and it all happens transparently to the application itself.&lt;br /&gt;
&lt;br /&gt;
{{tip|For more information on how the merging works, see the [[KDE System Administration/KDE_Filesystem_Hierarchy|KDE Filesystem Hierarchy]] article.}}&lt;br /&gt;
&lt;br /&gt;
On line 6 we open a specific local file, this case {{path|/etc/kderc}}. This performs no merging of values and expects an INI style file.&lt;br /&gt;
&lt;br /&gt;
Line 9 sees the creation of a configuration object that is not merged with the global &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt; configuration object, while the configuration file on line 12 is additionally not merged with any files in the &amp;lt;tt&amp;gt;$KDEDIRS&amp;lt;/tt&amp;gt; hierarchy. This can noticeably improve performance in the case where one is simply reading values out of a simple configuration for which global values are not meaningful.&lt;br /&gt;
&lt;br /&gt;
Line 15 creates a configuration object using the {{class|KComponentData}} object that belongs to a plugin or other component. The plugin may have a different set of directories defined in its {{class|KStandardDirs}} and this is a way of ensuring that {{class|KConfig}} respects this.&lt;br /&gt;
&lt;br /&gt;
Finally on line 18 we see the creation of a configuration object that does not exist in the &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; resource but rather in the application &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; resource. You may use any resource that {{class|KStandardDirs}} is aware of, including ones that are added at runtime.&lt;br /&gt;
&lt;br /&gt;
=== Special Configuration Objects ===&lt;br /&gt;
&lt;br /&gt;
Each application has its own configuration object that uses the name provided to {{class|KAboutData}} appended with &amp;quot;rc&amp;quot; as its name. So an app named &amp;quot;myapp&amp;quot; would have the default configuration object of &amp;quot;myapprc&amp;quot;. This configuration file can be retrieved in this way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KComponentData&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
#include &amp;lt;KGlobal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    // note that this is actually a KSharedConfig&lt;br /&gt;
    // more on that class in a bit!&lt;br /&gt;
    KConfig* config = KGlobal::config();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The default configuration object for the application is accessed when no name is specified when creating a {{class|KConfig}} object. So we could also do this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    KConfig config;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additionally, each component may have its own configuration object. This is generally accessed via the plugin's &amp;lt;tt&amp;gt;componentData()&amp;lt;/tt&amp;gt; rather than &amp;lt;tt&amp;gt;{{class|KGlobal}}::mainComponent()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Finally there is a global configuration object, &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt;, that is shared by every application. It holds such information as the default application shortcuts for various actions. It is &amp;quot;blended&amp;quot; into the configuration object if the &amp;lt;tt&amp;gt;KConfig::IncludeGlobals&amp;lt;/tt&amp;gt; flag is passed to the {{class|KConfig}} constructor, which is the default.&lt;br /&gt;
&lt;br /&gt;
=== Commonly Useful Methods ===&lt;br /&gt;
&lt;br /&gt;
To save the current state of the configuration object we call the &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; method. This method is also called when the object is destroyed. If no changes have been made or the resource reports itself as non-writable (such as in the case of the user not having write permissions to the file) then no disk activity occurs. &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; merges changes performed concurrently by other processes - local changes have priority, though.&lt;br /&gt;
&lt;br /&gt;
If we want to make sure that we have the latest values from disk we can call &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt; which calls &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; and then reloads the data from disk.&lt;br /&gt;
&lt;br /&gt;
If we need to prevent the config object from saving already made modifications to disk we need to call &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt;. A particular use case for this is rolling back the configuration to the on-disk state by calling &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt; followed by &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Listing all groups in a configuration object is as simple as calling &amp;lt;tt&amp;gt;groupList()&amp;lt;/tt&amp;gt; as in this code snippet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::mainComponent().config();&lt;br /&gt;
&lt;br /&gt;
foreach ( const QString&amp;amp; group, config.groupList() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;next group:&amp;quot; &amp;lt;&amp;lt; group;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== KSharedConfig ==&lt;br /&gt;
&lt;br /&gt;
The {{class|KSharedConfig}} class is a reference counted version of {{class|KConfig}}. It thus provides a way to reference the same configuration object from multiple places in your application without the extra overhead of separate objects or concerns about syncronizing writes to disk even if the configuration object is updated from multiple code paths. &lt;br /&gt;
&lt;br /&gt;
Accessing a {{class|KSharedConfig}} object is as easy as this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KSharedConfigPtr config = KSharedConfig::openConfig();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;openConfig()&amp;lt;/tt&amp;gt; take the same parameters as {{class|KConfig}}'s constructors do, allowing one to define which configuration file to open, flags to control merging and non-&amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; resources.&lt;br /&gt;
&lt;br /&gt;
{{class|KSharedConfig}} is generally recommended over using {{class|KConfig}} itself, and the object returned from {{class|KComponentData}} is indeed a {{class|KSharedConfig}} object.&lt;br /&gt;
&lt;br /&gt;
== KConfigGroup ==&lt;br /&gt;
&lt;br /&gt;
Now that we have a configuration object, the next step is to actually use it. The first thing we must do is to define which group of key/value pairs we wish to access in the object. We do this by creating a KConfigGroup object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig config;&lt;br /&gt;
KConfigGroup generalGroup( &amp;amp;config, &amp;quot;General&amp;quot; );&lt;br /&gt;
KConfigGroup colorsGroup = config.group( &amp;quot;Colors&amp;quot; ); // ... or a bit differently ...&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can pass {{class|KConfig}} or {{class|KSharedConfig}} objects to {{class|KConfigGroup}}.&lt;br /&gt;
&lt;br /&gt;
Config groups can be nested as well:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfigGroup subGroup1( &amp;amp;generalGroup, &amp;quot;LessGeneral&amp;quot; );&lt;br /&gt;
KConfigGroup subGroup2 = colorsGroup.group( &amp;quot;Dialogs&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Reading Entries ==&lt;br /&gt;
&lt;br /&gt;
With a {{class|KConfigGroup}} object in hand reading entries is now quite straight forward:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
QString accountName = generalGroup.readEntry( &amp;quot;Account&amp;quot;,&lt;br /&gt;
                                              QString() );&lt;br /&gt;
QColor color = colorsGroup.readEntry( &amp;quot;background&amp;quot;,&lt;br /&gt;
                                      Qt::white );&lt;br /&gt;
QStringList list = generalGroup.readEntry( &amp;quot;List&amp;quot;,&lt;br /&gt;
                                           QStringList() );&lt;br /&gt;
QString path = generalGroup.readPathEntry( &amp;quot;SaveTo&amp;quot;,&lt;br /&gt;
                                           defaultPath );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As can be seen from the above, you can mix reads from different {{class|KConfigGroup}} objects created on the same {{class|KConfig}} object. The read methods take the key, which is case sensitive, as the first argument and the default value as the second argument. This argument controls what kind of data, e.g. a color in line 3 above, is to be expected as well as the type of object returned. The returned object is wrapped in a {{qt|QVariant}} to make this magic happen.&lt;br /&gt;
&lt;br /&gt;
There are a couple of special read methods, including &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; which returns a file system path. It is vital that one uses &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; if it is a path as this enables such features as roaming profiles to work properly.&lt;br /&gt;
&lt;br /&gt;
If no such key currently exists in the configuration object, the default value is returned instead. If there is a localized (e.g. translated into another language) entry for the key that matches the current locale, that is returned.&lt;br /&gt;
&lt;br /&gt;
== Writing Entries ==&lt;br /&gt;
&lt;br /&gt;
Setting new values is similarly straightforward:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
generalGroup.writeEntry( &amp;quot;Account&amp;quot;, accountName );&lt;br /&gt;
generalGroup.writePathEntry( &amp;quot;SaveTo&amp;quot;, savePath );&lt;br /&gt;
colorGroup.writeEntry( &amp;quot;background&amp;quot;, color );&lt;br /&gt;
generalGroup.config()-&amp;gt;sync();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note the use of &amp;lt;tt&amp;gt;writePathEntry&amp;lt;/tt&amp;gt; and how the type of object we use, such as {{qt|QColor}} on line 3, dictates how the data is serialized. Additionally, once we are done writing entries, &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; must be called on the config object for it to be saved to disk. We can also simply wait for the object to be destroyed, which triggers an automatic &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; if necessary.&lt;br /&gt;
&lt;br /&gt;
== KDesktopFile: A Special Case ==&lt;br /&gt;
&lt;br /&gt;
When is a configuration file not a configuration file? When it is a [http://freedesktop.org/wiki/Standards_2fdesktop_2dentry_2dspec desktop file]. These files, which are essentially configuration files at their heart, are used  to describe entries for application menus, mimetypes, plugins and various services.&lt;br /&gt;
&lt;br /&gt;
When accessing a .desktop file, one should instead use the {{class|KDesktopFile}} class which, while a {{class|KConfig}} class offering all the capabilities described above, offers a set of methods designed to make accessing standard attributes of these files consistent and reliable.&lt;br /&gt;
&lt;br /&gt;
== Kiosk: Lockdown and User/Group Profiles ==&lt;br /&gt;
&lt;br /&gt;
KConfig provides a powerful set of lockdown and configuration definition capabilities, collectively known as &amp;quot;Kiosk&amp;quot;, that many system administrators and system integrators rely on. While most of this framework is provided transparently to the application, there is occassion when an application will want to check on the read/write status of a configuration object.&lt;br /&gt;
&lt;br /&gt;
Entries in configuration objects that are locked down using the kiosk facilities are said to be ''immutable''. An application can check for immutability of entire configuration objects, groups or keys as shown in this example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::config();&lt;br /&gt;
&lt;br /&gt;
if ( config-&amp;gt;isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;configuration object is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
KConfigGroup group(config, &amp;quot;General&amp;quot;);&lt;br /&gt;
if ( group.isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;group General is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if ( group.entryIsImmutable(&amp;quot;URL&amp;quot;) ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;URL entry in group General is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This can be useful in particular situations where an action should be taken when an item is immutable. For instance, the KDE panels will not offer configuration options to the user or allow them to otherwise change the order of applets and icons when the panel's configuration object is marked as immutable.&lt;br /&gt;
&lt;br /&gt;
== KConfig XT ==&lt;br /&gt;
&lt;br /&gt;
There is a way to make certain use cases of KConfig easier, faster and more reliable: KConfig XT. In particular, for main application or plugin configuration objects and when syncing configuration dialogs and other interfaces with these values, KConfig XT can help immensely. It also  simultaneously documents the configuration options available, which makes every sys admin and system integrator that uses KDE that much more happy.&lt;br /&gt;
&lt;br /&gt;
[[../Using_KConfig_XT|The next tutorial in the KConfig series covers what KConfig XT is and how to use it.]]&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials/KConfig_(de)</id>
		<title>Development/Tutorials/KConfig (de)</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials/KConfig_(de)"/>
				<updated>2008-01-01T12:45:04Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:I18n/Language Navigation Bar|Development/Tutorials/KConfig}}&lt;br /&gt;
&lt;br /&gt;
{{TutorialBrowser (de)|&lt;br /&gt;
&lt;br /&gt;
series=KConfig|&lt;br /&gt;
&lt;br /&gt;
name=Einführung in KConfig|&lt;br /&gt;
&lt;br /&gt;
pre=Keine|&lt;br /&gt;
&lt;br /&gt;
next=[[../Using_KConfig_XT (de)|Benutzen von KConfig XT]]|&lt;br /&gt;
&lt;br /&gt;
reading=Keine&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Zusammenfassung ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dieser Artikel beschäftigt sich mir dem KDE Einstellungdaten-System, angefangen mit einer Übersicht über die Grundlagen des Aufbaus aus der Sicht eines Entwicklers. Es wirft ausserdem einen Blick auf jede der Klassen, die für die Entwicklung von Anwendungen relevant sind und fährt dann mit kiosk (Benutzer und Gruppen Profile) Integration fort.&lt;br /&gt;
&lt;br /&gt;
== Grundlagen des Aufbaus ==&lt;br /&gt;
&lt;br /&gt;
KConfig ist ausgelegt um das Konzept vom eigentlichen Speichern und Auffinden von Konfigurationsdaten hinter eine Programmierschnittstelle zu abstrahieren die es ermöglicht, auf einfache Weise Informationen abzurufen und zu setzen. Wo oder in welcher Form Daten gespeichert werden ist für eine Anwendung die KConfig benutzt irrelevant.&lt;br /&gt;
&lt;br /&gt;
TODO:&lt;br /&gt;
&lt;br /&gt;
This keeps all KDE applications consistent in their handling of configurations while alleviating each and every application author to build such a system on their own from scratch, which can be a highly error prone exercise.&lt;br /&gt;
&lt;br /&gt;
A KConfig object represents a single configuration object. Each configuration object is referenced by its unique name and may be actually read from multiple local or remote files or services. Each application has a default configuration object associated with it and there is also a global configuration object.&lt;br /&gt;
&lt;br /&gt;
These configuration objects are broken down into a two level hierarchy: groups and keys. A configuration object can have any number of groups and each group can have one or more keys with associated values.&lt;br /&gt;
&lt;br /&gt;
Values stored may be of any number of data types. They are stored and retreived as the objects themselves. For example, a {{qt|QObject}} object is passed to a config object directly when storing a color value and when retreived a {{qt|QObject}} object is returned. Applications themselves therefore generally do not have to perform serialization and deserialization of objects themselves.&lt;br /&gt;
&lt;br /&gt;
== The KConfig Class ==&lt;br /&gt;
&lt;br /&gt;
The {{class|KConfig}} object is used to access a given configuration object. There are a number of ways to create a config object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
// a plain old read/write config object&lt;br /&gt;
KConfig config(&amp;quot;myapprc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// a specific file in the filesystem&lt;br /&gt;
// currently must be an INI style file&lt;br /&gt;
KConfig fullPath(&amp;quot;/etc/kderc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// not merged with global values&lt;br /&gt;
KConfig globalFree( &amp;quot;localsrc&amp;quot;, KConfig::NoGlobals );&lt;br /&gt;
&lt;br /&gt;
// not merged with globals or the $KDEDIRS hierarchy&lt;br /&gt;
KConfig simpleConfig( &amp;quot;simplerc&amp;quot;, KConfig::SimpleConfig );&lt;br /&gt;
&lt;br /&gt;
// config specific to a component, in this case a plugin&lt;br /&gt;
KConfig pluginConfig( componentData(), &amp;quot;pluginrc&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
// outside the standard config resource&lt;br /&gt;
KConfig dataResource( &amp;quot;data&amp;quot;, &amp;quot;myapp/somefile&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The KConfig object create on line 2 is a regular config object. We can read values from it, write new entries and ask for various properties of the object.  This object will be loaded from the config resource as determined by {{class|KStandardDirs}}, meaning that every instance of the &amp;lt;tt&amp;gt;myapprc&amp;lt;/tt&amp;gt; object in each of the directories in the config resource hierarchy will be merged to create the values seen in this object. This is how system wide and per-user/group profiles are generated and supported and it all happens transparently to the application itself.&lt;br /&gt;
&lt;br /&gt;
{{tip|For more information on how the merging works, see the [[KDE System Administration/KDE_Filesystem_Hierarchy|KDE Filesystem Hierarchy]] article.}}&lt;br /&gt;
&lt;br /&gt;
On line 6 we open a specific local file, this case {{path|/etc/kderc}}. This performs no merging of values and expects an INI style file.&lt;br /&gt;
&lt;br /&gt;
Line 9 sees the creation of a configuration object that is not merged with the global &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt; configuration object, while the configuration file on line 12 is additionally not merged with any files in the &amp;lt;tt&amp;gt;$KDEDIRS&amp;lt;/tt&amp;gt; hierarchy. This can noticeably improve performance in the case where one is simply reading values out of a simple configuration for which global values are not meaningful.&lt;br /&gt;
&lt;br /&gt;
Line 15 creates a configuration object using the {{class|KComponentData}} object that belongs to a plugin or other component. The plugin may have a different set of directories defined in its {{class|KStandardDirs}} and this is a way of ensuring that {{class|KConfig}} respects this.&lt;br /&gt;
&lt;br /&gt;
Finally on line 18 we see the creation of a configuration object that does not exist in the &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; resource but rather in the application &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; resource. You may use any resource that {{class|KStandardDirs}} is aware of, including ones that are added at runtime.&lt;br /&gt;
&lt;br /&gt;
=== Special Configuration Objects ===&lt;br /&gt;
&lt;br /&gt;
Each application has its own configuration object that uses the name provided to {{class|KAboutData}} appended with &amp;quot;rc&amp;quot; as its name. So an app named &amp;quot;myapp&amp;quot; would have the default configuration object of &amp;quot;myapprc&amp;quot;. This configuration file can be retrieved in this way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KComponentData&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
#include &amp;lt;KGlobal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    // note that this is actually a KSharedConfig&lt;br /&gt;
    // more on that class in a bit!&lt;br /&gt;
    KConfig* config = KGlobal::config();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The default configuration object for the application is accessed when no name is specified when creating a {{class|KConfig}} object. So we could also do this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    KConfig config;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additionally, each component may have its own configuration object. This is generally accessed via the plugin's &amp;lt;tt&amp;gt;componentData()&amp;lt;/tt&amp;gt; rather than &amp;lt;tt&amp;gt;{{class|KGlobal}}::mainComponent()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Finally there is a global configuration object, &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt;, that is shared by every application. It holds such information as the default application shortcuts for various actions. It is &amp;quot;blended&amp;quot; into the configuration object if the &amp;lt;tt&amp;gt;KConfig::IncludeGlobals&amp;lt;/tt&amp;gt; flag is passed to the {{class|KConfig}} constructor, which is the default.&lt;br /&gt;
&lt;br /&gt;
=== Commonly Useful Methods ===&lt;br /&gt;
&lt;br /&gt;
To save the current state of the configuration object we call the &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; method. This method is also called when the object is destroyed. If no changes have been made or the resource reports itself as non-writable (such as in the case of the user not having write permissions to the file) then no disk activity occurs. &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; merges changes performed concurrently by other processes - local changes have priority, though.&lt;br /&gt;
&lt;br /&gt;
If we want to make sure that we have the latest values from disk we can call &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt; which calls &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; and then reloads the data from disk.&lt;br /&gt;
&lt;br /&gt;
If we need to prevent the config object from saving already made modifications to disk we need to call &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt;. A particular use case for this is rolling back the configuration to the on-disk state by calling &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt; followed by &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Listing all groups in a configuration object is as simple as calling &amp;lt;tt&amp;gt;groupList()&amp;lt;/tt&amp;gt; as in this code snippet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::mainComponent().config();&lt;br /&gt;
&lt;br /&gt;
foreach ( const QString&amp;amp; group, config.groupList() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;next group:&amp;quot; &amp;lt;&amp;lt; group;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== KSharedConfig ==&lt;br /&gt;
&lt;br /&gt;
The {{class|KSharedConfig}} class is a reference counted version of {{class|KConfig}}. It thus provides a way to reference the same configuration object from multiple places in your application without the extra overhead of separate objects or concerns about syncronizing writes to disk even if the configuration object is updated from multiple code paths. &lt;br /&gt;
&lt;br /&gt;
Accessing a {{class|KSharedConfig}} object is as easy as this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KSharedConfigPtr config = KSharedConfig::openConfig();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;openConfig()&amp;lt;/tt&amp;gt; take the same parameters as {{class|KConfig}}'s constructors do, allowing one to define which configuration file to open, flags to control merging and non-&amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; resources.&lt;br /&gt;
&lt;br /&gt;
{{class|KSharedConfig}} is generally recommended over using {{class|KConfig}} itself, and the object returned from {{class|KComponentData}} is indeed a {{class|KSharedConfig}} object.&lt;br /&gt;
&lt;br /&gt;
== KConfigGroup ==&lt;br /&gt;
&lt;br /&gt;
Now that we have a configuration object, the next step is to actually use it. The first thing we must do is to define which group of key/value pairs we wish to access in the object. We do this by creating a KConfigGroup object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig config;&lt;br /&gt;
KConfigGroup generalGroup( &amp;amp;config, &amp;quot;General&amp;quot; );&lt;br /&gt;
KConfigGroup colorsGroup = config.group( &amp;quot;Colors&amp;quot; ); // ... or a bit differently ...&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can pass {{class|KConfig}} or {{class|KSharedConfig}} objects to {{class|KConfigGroup}}.&lt;br /&gt;
&lt;br /&gt;
Config groups can be nested as well:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfigGroup subGroup1( &amp;amp;generalGroup, &amp;quot;LessGeneral&amp;quot; );&lt;br /&gt;
KConfigGroup subGroup2 = colorsGroup.group( &amp;quot;Dialogs&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Reading Entries ==&lt;br /&gt;
&lt;br /&gt;
With a {{class|KConfigGroup}} object in hand reading entries is now quite straight forward:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
QString accountName = generalGroup.readEntry( &amp;quot;Account&amp;quot;,&lt;br /&gt;
                                              QString() );&lt;br /&gt;
QColor color = colorsGroup.readEntry( &amp;quot;background&amp;quot;,&lt;br /&gt;
                                      Qt::white );&lt;br /&gt;
QStringList list = generalGroup.readEntry( &amp;quot;List&amp;quot;,&lt;br /&gt;
                                           QStringList() );&lt;br /&gt;
QString path = generalGroup.readPathEntry( &amp;quot;SaveTo&amp;quot;,&lt;br /&gt;
                                           defaultPath );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As can be seen from the above, you can mix reads from different {{class|KConfigGroup}} objects created on the same {{class|KConfig}} object. The read methods take the key, which is case sensitive, as the first argument and the default value as the second argument. This argument controls what kind of data, e.g. a color in line 3 above, is to be expected as well as the type of object returned. The returned object is wrapped in a {{qt|QVariant}} to make this magic happen.&lt;br /&gt;
&lt;br /&gt;
There are a couple of special read methods, including &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; which returns a file system path. It is vital that one uses &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; if it is a path as this enables such features as roaming profiles to work properly.&lt;br /&gt;
&lt;br /&gt;
If no such key currently exists in the configuration object, the default value is returned instead. If there is a localized (e.g. translated into another language) entry for the key that matches the current locale, that is returned.&lt;br /&gt;
&lt;br /&gt;
== Writing Entries ==&lt;br /&gt;
&lt;br /&gt;
Setting new values is similarly straightforward:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
generalGroup.writeEntry( &amp;quot;Account&amp;quot;, accountName );&lt;br /&gt;
generalGroup.writePathEntry( &amp;quot;SaveTo&amp;quot;, savePath );&lt;br /&gt;
colorGroup.writeEntry( &amp;quot;background&amp;quot;, color );&lt;br /&gt;
generalGroup.config()-&amp;gt;sync();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note the use of &amp;lt;tt&amp;gt;writePathEntry&amp;lt;/tt&amp;gt; and how the type of object we use, such as {{qt|QColor}} on line 3, dictates how the data is serialized. Additionally, once we are done writing entries, &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; must be called on the config object for it to be saved to disk. We can also simply wait for the object to be destroyed, which triggers an automatic &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; if necessary.&lt;br /&gt;
&lt;br /&gt;
== KDesktopFile: A Special Case ==&lt;br /&gt;
&lt;br /&gt;
When is a configuration file not a configuration file? When it is a [http://freedesktop.org/wiki/Standards_2fdesktop_2dentry_2dspec desktop file]. These files, which are essentially configuration files at their heart, are used  to describe entries for application menus, mimetypes, plugins and various services.&lt;br /&gt;
&lt;br /&gt;
When accessing a .desktop file, one should instead use the {{class|KDesktopFile}} class which, while a {{class|KConfig}} class offering all the capabilities described above, offers a set of methods designed to make accessing standard attributes of these files consistent and reliable.&lt;br /&gt;
&lt;br /&gt;
== Kiosk: Lockdown and User/Group Profiles ==&lt;br /&gt;
&lt;br /&gt;
KConfig provides a powerful set of lockdown and configuration definition capabilities, collectively known as &amp;quot;Kiosk&amp;quot;, that many system administrators and system integrators rely on. While most of this framework is provided transparently to the application, there is occassion when an application will want to check on the read/write status of a configuration object.&lt;br /&gt;
&lt;br /&gt;
Entries in configuration objects that are locked down using the kiosk facilities are said to be ''immutable''. An application can check for immutability of entire configuration objects, groups or keys as shown in this example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::config();&lt;br /&gt;
&lt;br /&gt;
if ( config-&amp;gt;isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;configuration object is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
KConfigGroup group(config, &amp;quot;General&amp;quot;);&lt;br /&gt;
if ( group.isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;group General is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if ( group.entryIsImmutable(&amp;quot;URL&amp;quot;) ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;URL entry in group General is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This can be useful in particular situations where an action should be taken when an item is immutable. For instance, the KDE panels will not offer configuration options to the user or allow them to otherwise change the order of applets and icons when the panel's configuration object is marked as immutable.&lt;br /&gt;
&lt;br /&gt;
== KConfig XT ==&lt;br /&gt;
&lt;br /&gt;
There is a way to make certain use cases of KConfig easier, faster and more reliable: KConfig XT. In particular, for main application or plugin configuration objects and when syncing configuration dialogs and other interfaces with these values, KConfig XT can help immensely. It also  simultaneously documents the configuration options available, which makes every sys admin and system integrator that uses KDE that much more happy.&lt;br /&gt;
&lt;br /&gt;
[[../Using_KConfig_XT|The next tutorial in the KConfig series covers what KConfig XT is and how to use it.]]&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials/KConfig_(de)</id>
		<title>Development/Tutorials/KConfig (de)</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials/KConfig_(de)"/>
				<updated>2008-01-01T12:44:47Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:I18n/Language Navigation Bar|Development/Tutorials/KConfig}}&lt;br /&gt;
&lt;br /&gt;
{{TutorialBrowser (de)|&lt;br /&gt;
&lt;br /&gt;
series=KConfig|&lt;br /&gt;
&lt;br /&gt;
name=Einführung in KConfig|&lt;br /&gt;
&lt;br /&gt;
pre=Keine&lt;br /&gt;
&lt;br /&gt;
next=[[../Using_KConfig_XT (de)|Benutzen von KConfig XT]]|&lt;br /&gt;
&lt;br /&gt;
reading=Keine&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Zusammenfassung ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dieser Artikel beschäftigt sich mir dem KDE Einstellungdaten-System, angefangen mit einer Übersicht über die Grundlagen des Aufbaus aus der Sicht eines Entwicklers. Es wirft ausserdem einen Blick auf jede der Klassen, die für die Entwicklung von Anwendungen relevant sind und fährt dann mit kiosk (Benutzer und Gruppen Profile) Integration fort.&lt;br /&gt;
&lt;br /&gt;
== Grundlagen des Aufbaus ==&lt;br /&gt;
&lt;br /&gt;
KConfig ist ausgelegt um das Konzept vom eigentlichen Speichern und Auffinden von Konfigurationsdaten hinter eine Programmierschnittstelle zu abstrahieren die es ermöglicht, auf einfache Weise Informationen abzurufen und zu setzen. Wo oder in welcher Form Daten gespeichert werden ist für eine Anwendung die KConfig benutzt irrelevant.&lt;br /&gt;
&lt;br /&gt;
TODO:&lt;br /&gt;
&lt;br /&gt;
This keeps all KDE applications consistent in their handling of configurations while alleviating each and every application author to build such a system on their own from scratch, which can be a highly error prone exercise.&lt;br /&gt;
&lt;br /&gt;
A KConfig object represents a single configuration object. Each configuration object is referenced by its unique name and may be actually read from multiple local or remote files or services. Each application has a default configuration object associated with it and there is also a global configuration object.&lt;br /&gt;
&lt;br /&gt;
These configuration objects are broken down into a two level hierarchy: groups and keys. A configuration object can have any number of groups and each group can have one or more keys with associated values.&lt;br /&gt;
&lt;br /&gt;
Values stored may be of any number of data types. They are stored and retreived as the objects themselves. For example, a {{qt|QObject}} object is passed to a config object directly when storing a color value and when retreived a {{qt|QObject}} object is returned. Applications themselves therefore generally do not have to perform serialization and deserialization of objects themselves.&lt;br /&gt;
&lt;br /&gt;
== The KConfig Class ==&lt;br /&gt;
&lt;br /&gt;
The {{class|KConfig}} object is used to access a given configuration object. There are a number of ways to create a config object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
// a plain old read/write config object&lt;br /&gt;
KConfig config(&amp;quot;myapprc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// a specific file in the filesystem&lt;br /&gt;
// currently must be an INI style file&lt;br /&gt;
KConfig fullPath(&amp;quot;/etc/kderc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// not merged with global values&lt;br /&gt;
KConfig globalFree( &amp;quot;localsrc&amp;quot;, KConfig::NoGlobals );&lt;br /&gt;
&lt;br /&gt;
// not merged with globals or the $KDEDIRS hierarchy&lt;br /&gt;
KConfig simpleConfig( &amp;quot;simplerc&amp;quot;, KConfig::SimpleConfig );&lt;br /&gt;
&lt;br /&gt;
// config specific to a component, in this case a plugin&lt;br /&gt;
KConfig pluginConfig( componentData(), &amp;quot;pluginrc&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
// outside the standard config resource&lt;br /&gt;
KConfig dataResource( &amp;quot;data&amp;quot;, &amp;quot;myapp/somefile&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The KConfig object create on line 2 is a regular config object. We can read values from it, write new entries and ask for various properties of the object.  This object will be loaded from the config resource as determined by {{class|KStandardDirs}}, meaning that every instance of the &amp;lt;tt&amp;gt;myapprc&amp;lt;/tt&amp;gt; object in each of the directories in the config resource hierarchy will be merged to create the values seen in this object. This is how system wide and per-user/group profiles are generated and supported and it all happens transparently to the application itself.&lt;br /&gt;
&lt;br /&gt;
{{tip|For more information on how the merging works, see the [[KDE System Administration/KDE_Filesystem_Hierarchy|KDE Filesystem Hierarchy]] article.}}&lt;br /&gt;
&lt;br /&gt;
On line 6 we open a specific local file, this case {{path|/etc/kderc}}. This performs no merging of values and expects an INI style file.&lt;br /&gt;
&lt;br /&gt;
Line 9 sees the creation of a configuration object that is not merged with the global &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt; configuration object, while the configuration file on line 12 is additionally not merged with any files in the &amp;lt;tt&amp;gt;$KDEDIRS&amp;lt;/tt&amp;gt; hierarchy. This can noticeably improve performance in the case where one is simply reading values out of a simple configuration for which global values are not meaningful.&lt;br /&gt;
&lt;br /&gt;
Line 15 creates a configuration object using the {{class|KComponentData}} object that belongs to a plugin or other component. The plugin may have a different set of directories defined in its {{class|KStandardDirs}} and this is a way of ensuring that {{class|KConfig}} respects this.&lt;br /&gt;
&lt;br /&gt;
Finally on line 18 we see the creation of a configuration object that does not exist in the &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; resource but rather in the application &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; resource. You may use any resource that {{class|KStandardDirs}} is aware of, including ones that are added at runtime.&lt;br /&gt;
&lt;br /&gt;
=== Special Configuration Objects ===&lt;br /&gt;
&lt;br /&gt;
Each application has its own configuration object that uses the name provided to {{class|KAboutData}} appended with &amp;quot;rc&amp;quot; as its name. So an app named &amp;quot;myapp&amp;quot; would have the default configuration object of &amp;quot;myapprc&amp;quot;. This configuration file can be retrieved in this way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KComponentData&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
#include &amp;lt;KGlobal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    // note that this is actually a KSharedConfig&lt;br /&gt;
    // more on that class in a bit!&lt;br /&gt;
    KConfig* config = KGlobal::config();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The default configuration object for the application is accessed when no name is specified when creating a {{class|KConfig}} object. So we could also do this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    KConfig config;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additionally, each component may have its own configuration object. This is generally accessed via the plugin's &amp;lt;tt&amp;gt;componentData()&amp;lt;/tt&amp;gt; rather than &amp;lt;tt&amp;gt;{{class|KGlobal}}::mainComponent()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Finally there is a global configuration object, &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt;, that is shared by every application. It holds such information as the default application shortcuts for various actions. It is &amp;quot;blended&amp;quot; into the configuration object if the &amp;lt;tt&amp;gt;KConfig::IncludeGlobals&amp;lt;/tt&amp;gt; flag is passed to the {{class|KConfig}} constructor, which is the default.&lt;br /&gt;
&lt;br /&gt;
=== Commonly Useful Methods ===&lt;br /&gt;
&lt;br /&gt;
To save the current state of the configuration object we call the &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; method. This method is also called when the object is destroyed. If no changes have been made or the resource reports itself as non-writable (such as in the case of the user not having write permissions to the file) then no disk activity occurs. &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; merges changes performed concurrently by other processes - local changes have priority, though.&lt;br /&gt;
&lt;br /&gt;
If we want to make sure that we have the latest values from disk we can call &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt; which calls &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; and then reloads the data from disk.&lt;br /&gt;
&lt;br /&gt;
If we need to prevent the config object from saving already made modifications to disk we need to call &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt;. A particular use case for this is rolling back the configuration to the on-disk state by calling &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt; followed by &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Listing all groups in a configuration object is as simple as calling &amp;lt;tt&amp;gt;groupList()&amp;lt;/tt&amp;gt; as in this code snippet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::mainComponent().config();&lt;br /&gt;
&lt;br /&gt;
foreach ( const QString&amp;amp; group, config.groupList() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;next group:&amp;quot; &amp;lt;&amp;lt; group;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== KSharedConfig ==&lt;br /&gt;
&lt;br /&gt;
The {{class|KSharedConfig}} class is a reference counted version of {{class|KConfig}}. It thus provides a way to reference the same configuration object from multiple places in your application without the extra overhead of separate objects or concerns about syncronizing writes to disk even if the configuration object is updated from multiple code paths. &lt;br /&gt;
&lt;br /&gt;
Accessing a {{class|KSharedConfig}} object is as easy as this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KSharedConfigPtr config = KSharedConfig::openConfig();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;openConfig()&amp;lt;/tt&amp;gt; take the same parameters as {{class|KConfig}}'s constructors do, allowing one to define which configuration file to open, flags to control merging and non-&amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; resources.&lt;br /&gt;
&lt;br /&gt;
{{class|KSharedConfig}} is generally recommended over using {{class|KConfig}} itself, and the object returned from {{class|KComponentData}} is indeed a {{class|KSharedConfig}} object.&lt;br /&gt;
&lt;br /&gt;
== KConfigGroup ==&lt;br /&gt;
&lt;br /&gt;
Now that we have a configuration object, the next step is to actually use it. The first thing we must do is to define which group of key/value pairs we wish to access in the object. We do this by creating a KConfigGroup object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig config;&lt;br /&gt;
KConfigGroup generalGroup( &amp;amp;config, &amp;quot;General&amp;quot; );&lt;br /&gt;
KConfigGroup colorsGroup = config.group( &amp;quot;Colors&amp;quot; ); // ... or a bit differently ...&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can pass {{class|KConfig}} or {{class|KSharedConfig}} objects to {{class|KConfigGroup}}.&lt;br /&gt;
&lt;br /&gt;
Config groups can be nested as well:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfigGroup subGroup1( &amp;amp;generalGroup, &amp;quot;LessGeneral&amp;quot; );&lt;br /&gt;
KConfigGroup subGroup2 = colorsGroup.group( &amp;quot;Dialogs&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Reading Entries ==&lt;br /&gt;
&lt;br /&gt;
With a {{class|KConfigGroup}} object in hand reading entries is now quite straight forward:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
QString accountName = generalGroup.readEntry( &amp;quot;Account&amp;quot;,&lt;br /&gt;
                                              QString() );&lt;br /&gt;
QColor color = colorsGroup.readEntry( &amp;quot;background&amp;quot;,&lt;br /&gt;
                                      Qt::white );&lt;br /&gt;
QStringList list = generalGroup.readEntry( &amp;quot;List&amp;quot;,&lt;br /&gt;
                                           QStringList() );&lt;br /&gt;
QString path = generalGroup.readPathEntry( &amp;quot;SaveTo&amp;quot;,&lt;br /&gt;
                                           defaultPath );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As can be seen from the above, you can mix reads from different {{class|KConfigGroup}} objects created on the same {{class|KConfig}} object. The read methods take the key, which is case sensitive, as the first argument and the default value as the second argument. This argument controls what kind of data, e.g. a color in line 3 above, is to be expected as well as the type of object returned. The returned object is wrapped in a {{qt|QVariant}} to make this magic happen.&lt;br /&gt;
&lt;br /&gt;
There are a couple of special read methods, including &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; which returns a file system path. It is vital that one uses &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; if it is a path as this enables such features as roaming profiles to work properly.&lt;br /&gt;
&lt;br /&gt;
If no such key currently exists in the configuration object, the default value is returned instead. If there is a localized (e.g. translated into another language) entry for the key that matches the current locale, that is returned.&lt;br /&gt;
&lt;br /&gt;
== Writing Entries ==&lt;br /&gt;
&lt;br /&gt;
Setting new values is similarly straightforward:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
generalGroup.writeEntry( &amp;quot;Account&amp;quot;, accountName );&lt;br /&gt;
generalGroup.writePathEntry( &amp;quot;SaveTo&amp;quot;, savePath );&lt;br /&gt;
colorGroup.writeEntry( &amp;quot;background&amp;quot;, color );&lt;br /&gt;
generalGroup.config()-&amp;gt;sync();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note the use of &amp;lt;tt&amp;gt;writePathEntry&amp;lt;/tt&amp;gt; and how the type of object we use, such as {{qt|QColor}} on line 3, dictates how the data is serialized. Additionally, once we are done writing entries, &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; must be called on the config object for it to be saved to disk. We can also simply wait for the object to be destroyed, which triggers an automatic &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; if necessary.&lt;br /&gt;
&lt;br /&gt;
== KDesktopFile: A Special Case ==&lt;br /&gt;
&lt;br /&gt;
When is a configuration file not a configuration file? When it is a [http://freedesktop.org/wiki/Standards_2fdesktop_2dentry_2dspec desktop file]. These files, which are essentially configuration files at their heart, are used  to describe entries for application menus, mimetypes, plugins and various services.&lt;br /&gt;
&lt;br /&gt;
When accessing a .desktop file, one should instead use the {{class|KDesktopFile}} class which, while a {{class|KConfig}} class offering all the capabilities described above, offers a set of methods designed to make accessing standard attributes of these files consistent and reliable.&lt;br /&gt;
&lt;br /&gt;
== Kiosk: Lockdown and User/Group Profiles ==&lt;br /&gt;
&lt;br /&gt;
KConfig provides a powerful set of lockdown and configuration definition capabilities, collectively known as &amp;quot;Kiosk&amp;quot;, that many system administrators and system integrators rely on. While most of this framework is provided transparently to the application, there is occassion when an application will want to check on the read/write status of a configuration object.&lt;br /&gt;
&lt;br /&gt;
Entries in configuration objects that are locked down using the kiosk facilities are said to be ''immutable''. An application can check for immutability of entire configuration objects, groups or keys as shown in this example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::config();&lt;br /&gt;
&lt;br /&gt;
if ( config-&amp;gt;isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;configuration object is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
KConfigGroup group(config, &amp;quot;General&amp;quot;);&lt;br /&gt;
if ( group.isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;group General is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if ( group.entryIsImmutable(&amp;quot;URL&amp;quot;) ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;URL entry in group General is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This can be useful in particular situations where an action should be taken when an item is immutable. For instance, the KDE panels will not offer configuration options to the user or allow them to otherwise change the order of applets and icons when the panel's configuration object is marked as immutable.&lt;br /&gt;
&lt;br /&gt;
== KConfig XT ==&lt;br /&gt;
&lt;br /&gt;
There is a way to make certain use cases of KConfig easier, faster and more reliable: KConfig XT. In particular, for main application or plugin configuration objects and when syncing configuration dialogs and other interfaces with these values, KConfig XT can help immensely. It also  simultaneously documents the configuration options available, which makes every sys admin and system integrator that uses KDE that much more happy.&lt;br /&gt;
&lt;br /&gt;
[[../Using_KConfig_XT|The next tutorial in the KConfig series covers what KConfig XT is and how to use it.]]&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials/KConfig_(de)</id>
		<title>Development/Tutorials/KConfig (de)</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials/KConfig_(de)"/>
				<updated>2008-01-01T12:44:05Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: New page: {{Template:I18n/Language Navigation Bar|Development/Tutorials/KConfig}}  {{TutorialBrowser (de)|  series=KConfig|  name=Einführung in KConfig|  next=[[../Using_KConfig_XT (de)|Benutzen vo...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:I18n/Language Navigation Bar|Development/Tutorials/KConfig}}&lt;br /&gt;
&lt;br /&gt;
{{TutorialBrowser (de)|&lt;br /&gt;
&lt;br /&gt;
series=KConfig|&lt;br /&gt;
&lt;br /&gt;
name=Einführung in KConfig|&lt;br /&gt;
&lt;br /&gt;
next=[[../Using_KConfig_XT (de)|Benutzen von KConfig XT]]|&lt;br /&gt;
&lt;br /&gt;
reading=Keine&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Zusammenfassung ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dieser Artikel beschäftigt sich mir dem KDE Einstellungdaten-System, angefangen mit einer Übersicht über die Grundlagen des Aufbaus aus der Sicht eines Entwicklers. Es wirft ausserdem einen Blick auf jede der Klassen, die für die Entwicklung von Anwendungen relevant sind und fährt dann mit kiosk (Benutzer und Gruppen Profile) Integration fort.&lt;br /&gt;
&lt;br /&gt;
== Grundlagen des Aufbaus ==&lt;br /&gt;
&lt;br /&gt;
KConfig ist ausgelegt um das Konzept vom eigentlichen Speichern und Auffinden von Konfigurationsdaten hinter eine Programmierschnittstelle zu abstrahieren die es ermöglicht, auf einfache Weise Informationen abzurufen und zu setzen. Wo oder in welcher Form Daten gespeichert werden ist für eine Anwendung die KConfig benutzt irrelevant.&lt;br /&gt;
&lt;br /&gt;
TODO:&lt;br /&gt;
&lt;br /&gt;
This keeps all KDE applications consistent in their handling of configurations while alleviating each and every application author to build such a system on their own from scratch, which can be a highly error prone exercise.&lt;br /&gt;
&lt;br /&gt;
A KConfig object represents a single configuration object. Each configuration object is referenced by its unique name and may be actually read from multiple local or remote files or services. Each application has a default configuration object associated with it and there is also a global configuration object.&lt;br /&gt;
&lt;br /&gt;
These configuration objects are broken down into a two level hierarchy: groups and keys. A configuration object can have any number of groups and each group can have one or more keys with associated values.&lt;br /&gt;
&lt;br /&gt;
Values stored may be of any number of data types. They are stored and retreived as the objects themselves. For example, a {{qt|QObject}} object is passed to a config object directly when storing a color value and when retreived a {{qt|QObject}} object is returned. Applications themselves therefore generally do not have to perform serialization and deserialization of objects themselves.&lt;br /&gt;
&lt;br /&gt;
== The KConfig Class ==&lt;br /&gt;
&lt;br /&gt;
The {{class|KConfig}} object is used to access a given configuration object. There are a number of ways to create a config object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
// a plain old read/write config object&lt;br /&gt;
KConfig config(&amp;quot;myapprc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// a specific file in the filesystem&lt;br /&gt;
// currently must be an INI style file&lt;br /&gt;
KConfig fullPath(&amp;quot;/etc/kderc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// not merged with global values&lt;br /&gt;
KConfig globalFree( &amp;quot;localsrc&amp;quot;, KConfig::NoGlobals );&lt;br /&gt;
&lt;br /&gt;
// not merged with globals or the $KDEDIRS hierarchy&lt;br /&gt;
KConfig simpleConfig( &amp;quot;simplerc&amp;quot;, KConfig::SimpleConfig );&lt;br /&gt;
&lt;br /&gt;
// config specific to a component, in this case a plugin&lt;br /&gt;
KConfig pluginConfig( componentData(), &amp;quot;pluginrc&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
// outside the standard config resource&lt;br /&gt;
KConfig dataResource( &amp;quot;data&amp;quot;, &amp;quot;myapp/somefile&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The KConfig object create on line 2 is a regular config object. We can read values from it, write new entries and ask for various properties of the object.  This object will be loaded from the config resource as determined by {{class|KStandardDirs}}, meaning that every instance of the &amp;lt;tt&amp;gt;myapprc&amp;lt;/tt&amp;gt; object in each of the directories in the config resource hierarchy will be merged to create the values seen in this object. This is how system wide and per-user/group profiles are generated and supported and it all happens transparently to the application itself.&lt;br /&gt;
&lt;br /&gt;
{{tip|For more information on how the merging works, see the [[KDE System Administration/KDE_Filesystem_Hierarchy|KDE Filesystem Hierarchy]] article.}}&lt;br /&gt;
&lt;br /&gt;
On line 6 we open a specific local file, this case {{path|/etc/kderc}}. This performs no merging of values and expects an INI style file.&lt;br /&gt;
&lt;br /&gt;
Line 9 sees the creation of a configuration object that is not merged with the global &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt; configuration object, while the configuration file on line 12 is additionally not merged with any files in the &amp;lt;tt&amp;gt;$KDEDIRS&amp;lt;/tt&amp;gt; hierarchy. This can noticeably improve performance in the case where one is simply reading values out of a simple configuration for which global values are not meaningful.&lt;br /&gt;
&lt;br /&gt;
Line 15 creates a configuration object using the {{class|KComponentData}} object that belongs to a plugin or other component. The plugin may have a different set of directories defined in its {{class|KStandardDirs}} and this is a way of ensuring that {{class|KConfig}} respects this.&lt;br /&gt;
&lt;br /&gt;
Finally on line 18 we see the creation of a configuration object that does not exist in the &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; resource but rather in the application &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; resource. You may use any resource that {{class|KStandardDirs}} is aware of, including ones that are added at runtime.&lt;br /&gt;
&lt;br /&gt;
=== Special Configuration Objects ===&lt;br /&gt;
&lt;br /&gt;
Each application has its own configuration object that uses the name provided to {{class|KAboutData}} appended with &amp;quot;rc&amp;quot; as its name. So an app named &amp;quot;myapp&amp;quot; would have the default configuration object of &amp;quot;myapprc&amp;quot;. This configuration file can be retrieved in this way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KComponentData&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
#include &amp;lt;KGlobal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    // note that this is actually a KSharedConfig&lt;br /&gt;
    // more on that class in a bit!&lt;br /&gt;
    KConfig* config = KGlobal::config();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The default configuration object for the application is accessed when no name is specified when creating a {{class|KConfig}} object. So we could also do this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    KConfig config;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additionally, each component may have its own configuration object. This is generally accessed via the plugin's &amp;lt;tt&amp;gt;componentData()&amp;lt;/tt&amp;gt; rather than &amp;lt;tt&amp;gt;{{class|KGlobal}}::mainComponent()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Finally there is a global configuration object, &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt;, that is shared by every application. It holds such information as the default application shortcuts for various actions. It is &amp;quot;blended&amp;quot; into the configuration object if the &amp;lt;tt&amp;gt;KConfig::IncludeGlobals&amp;lt;/tt&amp;gt; flag is passed to the {{class|KConfig}} constructor, which is the default.&lt;br /&gt;
&lt;br /&gt;
=== Commonly Useful Methods ===&lt;br /&gt;
&lt;br /&gt;
To save the current state of the configuration object we call the &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; method. This method is also called when the object is destroyed. If no changes have been made or the resource reports itself as non-writable (such as in the case of the user not having write permissions to the file) then no disk activity occurs. &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; merges changes performed concurrently by other processes - local changes have priority, though.&lt;br /&gt;
&lt;br /&gt;
If we want to make sure that we have the latest values from disk we can call &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt; which calls &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; and then reloads the data from disk.&lt;br /&gt;
&lt;br /&gt;
If we need to prevent the config object from saving already made modifications to disk we need to call &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt;. A particular use case for this is rolling back the configuration to the on-disk state by calling &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt; followed by &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Listing all groups in a configuration object is as simple as calling &amp;lt;tt&amp;gt;groupList()&amp;lt;/tt&amp;gt; as in this code snippet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::mainComponent().config();&lt;br /&gt;
&lt;br /&gt;
foreach ( const QString&amp;amp; group, config.groupList() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;next group:&amp;quot; &amp;lt;&amp;lt; group;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== KSharedConfig ==&lt;br /&gt;
&lt;br /&gt;
The {{class|KSharedConfig}} class is a reference counted version of {{class|KConfig}}. It thus provides a way to reference the same configuration object from multiple places in your application without the extra overhead of separate objects or concerns about syncronizing writes to disk even if the configuration object is updated from multiple code paths. &lt;br /&gt;
&lt;br /&gt;
Accessing a {{class|KSharedConfig}} object is as easy as this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KSharedConfigPtr config = KSharedConfig::openConfig();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;openConfig()&amp;lt;/tt&amp;gt; take the same parameters as {{class|KConfig}}'s constructors do, allowing one to define which configuration file to open, flags to control merging and non-&amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; resources.&lt;br /&gt;
&lt;br /&gt;
{{class|KSharedConfig}} is generally recommended over using {{class|KConfig}} itself, and the object returned from {{class|KComponentData}} is indeed a {{class|KSharedConfig}} object.&lt;br /&gt;
&lt;br /&gt;
== KConfigGroup ==&lt;br /&gt;
&lt;br /&gt;
Now that we have a configuration object, the next step is to actually use it. The first thing we must do is to define which group of key/value pairs we wish to access in the object. We do this by creating a KConfigGroup object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig config;&lt;br /&gt;
KConfigGroup generalGroup( &amp;amp;config, &amp;quot;General&amp;quot; );&lt;br /&gt;
KConfigGroup colorsGroup = config.group( &amp;quot;Colors&amp;quot; ); // ... or a bit differently ...&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can pass {{class|KConfig}} or {{class|KSharedConfig}} objects to {{class|KConfigGroup}}.&lt;br /&gt;
&lt;br /&gt;
Config groups can be nested as well:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfigGroup subGroup1( &amp;amp;generalGroup, &amp;quot;LessGeneral&amp;quot; );&lt;br /&gt;
KConfigGroup subGroup2 = colorsGroup.group( &amp;quot;Dialogs&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Reading Entries ==&lt;br /&gt;
&lt;br /&gt;
With a {{class|KConfigGroup}} object in hand reading entries is now quite straight forward:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
QString accountName = generalGroup.readEntry( &amp;quot;Account&amp;quot;,&lt;br /&gt;
                                              QString() );&lt;br /&gt;
QColor color = colorsGroup.readEntry( &amp;quot;background&amp;quot;,&lt;br /&gt;
                                      Qt::white );&lt;br /&gt;
QStringList list = generalGroup.readEntry( &amp;quot;List&amp;quot;,&lt;br /&gt;
                                           QStringList() );&lt;br /&gt;
QString path = generalGroup.readPathEntry( &amp;quot;SaveTo&amp;quot;,&lt;br /&gt;
                                           defaultPath );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As can be seen from the above, you can mix reads from different {{class|KConfigGroup}} objects created on the same {{class|KConfig}} object. The read methods take the key, which is case sensitive, as the first argument and the default value as the second argument. This argument controls what kind of data, e.g. a color in line 3 above, is to be expected as well as the type of object returned. The returned object is wrapped in a {{qt|QVariant}} to make this magic happen.&lt;br /&gt;
&lt;br /&gt;
There are a couple of special read methods, including &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; which returns a file system path. It is vital that one uses &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; if it is a path as this enables such features as roaming profiles to work properly.&lt;br /&gt;
&lt;br /&gt;
If no such key currently exists in the configuration object, the default value is returned instead. If there is a localized (e.g. translated into another language) entry for the key that matches the current locale, that is returned.&lt;br /&gt;
&lt;br /&gt;
== Writing Entries ==&lt;br /&gt;
&lt;br /&gt;
Setting new values is similarly straightforward:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
generalGroup.writeEntry( &amp;quot;Account&amp;quot;, accountName );&lt;br /&gt;
generalGroup.writePathEntry( &amp;quot;SaveTo&amp;quot;, savePath );&lt;br /&gt;
colorGroup.writeEntry( &amp;quot;background&amp;quot;, color );&lt;br /&gt;
generalGroup.config()-&amp;gt;sync();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note the use of &amp;lt;tt&amp;gt;writePathEntry&amp;lt;/tt&amp;gt; and how the type of object we use, such as {{qt|QColor}} on line 3, dictates how the data is serialized. Additionally, once we are done writing entries, &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; must be called on the config object for it to be saved to disk. We can also simply wait for the object to be destroyed, which triggers an automatic &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; if necessary.&lt;br /&gt;
&lt;br /&gt;
== KDesktopFile: A Special Case ==&lt;br /&gt;
&lt;br /&gt;
When is a configuration file not a configuration file? When it is a [http://freedesktop.org/wiki/Standards_2fdesktop_2dentry_2dspec desktop file]. These files, which are essentially configuration files at their heart, are used  to describe entries for application menus, mimetypes, plugins and various services.&lt;br /&gt;
&lt;br /&gt;
When accessing a .desktop file, one should instead use the {{class|KDesktopFile}} class which, while a {{class|KConfig}} class offering all the capabilities described above, offers a set of methods designed to make accessing standard attributes of these files consistent and reliable.&lt;br /&gt;
&lt;br /&gt;
== Kiosk: Lockdown and User/Group Profiles ==&lt;br /&gt;
&lt;br /&gt;
KConfig provides a powerful set of lockdown and configuration definition capabilities, collectively known as &amp;quot;Kiosk&amp;quot;, that many system administrators and system integrators rely on. While most of this framework is provided transparently to the application, there is occassion when an application will want to check on the read/write status of a configuration object.&lt;br /&gt;
&lt;br /&gt;
Entries in configuration objects that are locked down using the kiosk facilities are said to be ''immutable''. An application can check for immutability of entire configuration objects, groups or keys as shown in this example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::config();&lt;br /&gt;
&lt;br /&gt;
if ( config-&amp;gt;isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;configuration object is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
KConfigGroup group(config, &amp;quot;General&amp;quot;);&lt;br /&gt;
if ( group.isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;group General is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if ( group.entryIsImmutable(&amp;quot;URL&amp;quot;) ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;URL entry in group General is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This can be useful in particular situations where an action should be taken when an item is immutable. For instance, the KDE panels will not offer configuration options to the user or allow them to otherwise change the order of applets and icons when the panel's configuration object is marked as immutable.&lt;br /&gt;
&lt;br /&gt;
== KConfig XT ==&lt;br /&gt;
&lt;br /&gt;
There is a way to make certain use cases of KConfig easier, faster and more reliable: KConfig XT. In particular, for main application or plugin configuration objects and when syncing configuration dialogs and other interfaces with these values, KConfig XT can help immensely. It also  simultaneously documents the configuration options available, which makes every sys admin and system integrator that uses KDE that much more happy.&lt;br /&gt;
&lt;br /&gt;
[[../Using_KConfig_XT|The next tutorial in the KConfig series covers what KConfig XT is and how to use it.]]&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials/KCmdLineArgs_(de)</id>
		<title>Development/Tutorials/KCmdLineArgs (de)</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials/KCmdLineArgs_(de)"/>
				<updated>2008-01-01T11:44:14Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:I18n/Language Navigation Bar|Development/Tutorials/KCmdLineArgs}}&lt;br /&gt;
&lt;br /&gt;
{{TutorialBrowser (de)|&lt;br /&gt;
&lt;br /&gt;
series=Anleitung für Anfänger|&lt;br /&gt;
&lt;br /&gt;
name=Befehlszeilen Argumente (Under construction)|&lt;br /&gt;
&lt;br /&gt;
pre=[[Development/Tutorials/Saving and loading (de)|Anleitung 4 - Laden und Speichern von Dateien]]|&lt;br /&gt;
&lt;br /&gt;
next=[[Development/Tutorials/###|Tutorial 6 - ###]])| &lt;br /&gt;
&lt;br /&gt;
reading={{class|KCmdLineArgs}} {{class|KCmdLineOptions}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Zusammenfassung==&lt;br /&gt;
&lt;br /&gt;
In diesem Kapitel werden sie lernen ihrer Anwendung zu ermöglichen, Dateien über die Befehlszeile zu öffnen oder sogar mit 'Öffnen mit' von Dolphin aus zu verwenden.&lt;br /&gt;
&lt;br /&gt;
[[image:introtokdetutorial5.png|frame|center]]&lt;br /&gt;
&lt;br /&gt;
== The Code ==&lt;br /&gt;
&lt;br /&gt;
===main.cpp===&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KApplication&amp;gt;&lt;br /&gt;
#include &amp;lt;KAboutData&amp;gt;&lt;br /&gt;
#include &amp;lt;KCmdLineArgs&amp;gt;&lt;br /&gt;
#include &amp;lt;KUrl&amp;gt; //new&lt;br /&gt;
 &lt;br /&gt;
#include &amp;quot;mainwindow.h&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
int main (int argc, char *argv[])&lt;br /&gt;
{&lt;br /&gt;
  KAboutData aboutData( &amp;quot;tutorial5&amp;quot;, &amp;quot;tutorial5&amp;quot;,&lt;br /&gt;
      ki18n(&amp;quot;Tutorial 5&amp;quot;), &amp;quot;1.0&amp;quot;,&lt;br /&gt;
      ki18n(&amp;quot;A simple text area which can load and save.&amp;quot;),&lt;br /&gt;
      KAboutData::License_GPL,&lt;br /&gt;
      ki18n(&amp;quot;Copyright (c) 2007 Developer&amp;quot;) );&lt;br /&gt;
  KCmdLineArgs::init( argc, argv, &amp;amp;aboutData );&lt;br /&gt;
&lt;br /&gt;
  KCmdLineOptions options; //new&lt;br /&gt;
  options.add(&amp;quot;+[file]&amp;quot;, ki18n(&amp;quot;Document to open&amp;quot;)); //new&lt;br /&gt;
  KCmdLineArgs::addCmdLineOptions(options); //new&lt;br /&gt;
&lt;br /&gt;
  KApplication app;&lt;br /&gt;
 &lt;br /&gt;
  MainWindow* window = new MainWindow();&lt;br /&gt;
  window-&amp;gt;show();&lt;br /&gt;
&lt;br /&gt;
  KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); //new&lt;br /&gt;
  if(args-&amp;gt;count()) //new&lt;br /&gt;
  {&lt;br /&gt;
    window-&amp;gt;openFile(args-&amp;gt;url(0).url()); //new&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return app.exec();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===mainwindow.h===&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#ifndef MAINWINDOW_H&lt;br /&gt;
#define MAINWINDOW_H&lt;br /&gt;
 &lt;br /&gt;
#include &amp;lt;KXmlGuiWindow&amp;gt;&lt;br /&gt;
#include &amp;lt;KTextEdit&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
class MainWindow : public KXmlGuiWindow&lt;br /&gt;
{&lt;br /&gt;
  Q_OBJECT&lt;br /&gt;
  &lt;br /&gt;
  public:&lt;br /&gt;
    MainWindow(QWidget *parent=0);&lt;br /&gt;
    void openFile(const QString &amp;amp;inputFileName); //new&lt;br /&gt;
  &lt;br /&gt;
  private:&lt;br /&gt;
    KTextEdit* textArea;&lt;br /&gt;
    void setupActions();&lt;br /&gt;
    QString fileName;&lt;br /&gt;
 &lt;br /&gt;
  private slots:&lt;br /&gt;
    void newFile();&lt;br /&gt;
    void openFile();&lt;br /&gt;
    void saveFile();&lt;br /&gt;
    void saveFileAs();&lt;br /&gt;
    void saveFileAs(const QString &amp;amp;outputFileName);&lt;br /&gt;
};&lt;br /&gt;
 &lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===mainwindow.cpp===&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;quot;mainwindow.h&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
#include &amp;lt;KApplication&amp;gt;&lt;br /&gt;
#include &amp;lt;KAction&amp;gt;&lt;br /&gt;
#include &amp;lt;KLocale&amp;gt;&lt;br /&gt;
#include &amp;lt;KActionCollection&amp;gt;&lt;br /&gt;
#include &amp;lt;KStandardAction&amp;gt;&lt;br /&gt;
#include &amp;lt;KFileDialog&amp;gt;&lt;br /&gt;
#include &amp;lt;KMessageBox&amp;gt;&lt;br /&gt;
#include &amp;lt;KIO/NetAccess&amp;gt;&lt;br /&gt;
#include &amp;lt;KSaveFile&amp;gt;&lt;br /&gt;
#include &amp;lt;QTextStream&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
MainWindow::MainWindow(QWidget *parent)&lt;br /&gt;
    : KXmlGuiWindow(parent),&lt;br /&gt;
      fileName(QString())&lt;br /&gt;
{&lt;br /&gt;
  textArea = new KTextEdit;&lt;br /&gt;
  setCentralWidget(textArea);&lt;br /&gt;
 &lt;br /&gt;
  setupActions();&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
void MainWindow::setupActions()&lt;br /&gt;
{&lt;br /&gt;
  KAction* clearAction = new KAction(this);&lt;br /&gt;
  clearAction-&amp;gt;setText(i18n(&amp;quot;Clear&amp;quot;));&lt;br /&gt;
  clearAction-&amp;gt;setIcon(KIcon(&amp;quot;document-new&amp;quot;));&lt;br /&gt;
  clearAction-&amp;gt;setShortcut(Qt::CTRL + Qt::Key_W);&lt;br /&gt;
  actionCollection()-&amp;gt;addAction(&amp;quot;clear&amp;quot;, clearAction);&lt;br /&gt;
  connect(clearAction, SIGNAL(triggered(bool)),&lt;br /&gt;
          textArea, SLOT(clear()));&lt;br /&gt;
 &lt;br /&gt;
  KStandardAction::quit(kapp, SLOT(quit()),&lt;br /&gt;
                        actionCollection());&lt;br /&gt;
 &lt;br /&gt;
  KStandardAction::open(this, SLOT(openFile()),&lt;br /&gt;
                        actionCollection());&lt;br /&gt;
 &lt;br /&gt;
  KStandardAction::save(this, SLOT(saveFile()),&lt;br /&gt;
                        actionCollection());&lt;br /&gt;
 &lt;br /&gt;
  KStandardAction::saveAs(this, SLOT(saveFileAs()),&lt;br /&gt;
                        actionCollection());&lt;br /&gt;
 &lt;br /&gt;
  KStandardAction::openNew(this, SLOT(newFile()),&lt;br /&gt;
                        actionCollection());&lt;br /&gt;
 &lt;br /&gt;
  setupGUI();&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
void MainWindow::newFile()&lt;br /&gt;
{&lt;br /&gt;
  fileName.clear();&lt;br /&gt;
  textArea-&amp;gt;clear();&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
void MainWindow::saveFileAs(const QString &amp;amp;outputFileName)&lt;br /&gt;
{&lt;br /&gt;
  KSaveFile file(outputFileName);&lt;br /&gt;
  file.open();&lt;br /&gt;
  &lt;br /&gt;
  QByteArray outputByteArray;&lt;br /&gt;
  outputByteArray.append(textArea-&amp;gt;toPlainText());&lt;br /&gt;
  file.write(outputByteArray);&lt;br /&gt;
  file.finalize();&lt;br /&gt;
  file.close();&lt;br /&gt;
  &lt;br /&gt;
  fileName = outputFileName;&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
void MainWindow::saveFileAs()&lt;br /&gt;
{&lt;br /&gt;
  saveFileAs(KFileDialog::getSaveFileName());&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
void MainWindow::saveFile()&lt;br /&gt;
{&lt;br /&gt;
  if(!fileName.isEmpty())&lt;br /&gt;
  {&lt;br /&gt;
    saveFileAs(fileName);&lt;br /&gt;
  }&lt;br /&gt;
  else&lt;br /&gt;
  {&lt;br /&gt;
    saveFileAs();&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
void MainWindow::openFile() //changed&lt;br /&gt;
{&lt;br /&gt;
  openFile(KFileDialog::getOpenFileName());&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void MainWindow::openFile(const QString &amp;amp;inputFileName) //new&lt;br /&gt;
{&lt;br /&gt;
  QString tmpFile;&lt;br /&gt;
  if(KIO::NetAccess::download(inputFileName, tmpFile, &lt;br /&gt;
         this))&lt;br /&gt;
  {&lt;br /&gt;
    QFile file(tmpFile);&lt;br /&gt;
    file.open(QIODevice::ReadOnly);&lt;br /&gt;
    textArea-&amp;gt;setPlainText(QTextStream(&amp;amp;file).readAll());&lt;br /&gt;
    fileName = inputFileName;&lt;br /&gt;
 &lt;br /&gt;
    KIO::NetAccess::removeTempFile(tmpFile);&lt;br /&gt;
  }&lt;br /&gt;
  else&lt;br /&gt;
  {&lt;br /&gt;
    KMessageBox::error(this, &lt;br /&gt;
        KIO::NetAccess::lastErrorString());&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===tutorial4ui.rc===&lt;br /&gt;
&amp;lt;code xml n&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE kpartgui SYSTEM &amp;quot;kpartgui.dtd&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;gui name=&amp;quot;tutorial5&amp;quot; version=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;ToolBar name=&amp;quot;mainToolBar&amp;quot; &amp;gt;&lt;br /&gt;
    &amp;lt;text&amp;gt;Main Toolbar&amp;lt;/text&amp;gt;&lt;br /&gt;
    &amp;lt;Action name=&amp;quot;clear&amp;quot; /&amp;gt;&lt;br /&gt;
  &amp;lt;/ToolBar&amp;gt;&lt;br /&gt;
  &amp;lt;MenuBar&amp;gt;&lt;br /&gt;
    &amp;lt;Menu name=&amp;quot;file&amp;quot; &amp;gt;&lt;br /&gt;
      &amp;lt;Action name=&amp;quot;clear&amp;quot; /&amp;gt;&lt;br /&gt;
    &amp;lt;/Menu&amp;gt;&lt;br /&gt;
  &amp;lt;/MenuBar&amp;gt;&lt;br /&gt;
&amp;lt;/gui&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Dies ist identisch mit &amp;lt;tt&amp;gt;tutorial'X'ui.rc&amp;lt;/tt&amp;gt; aus den letzten beiden Anleitungen ausser dass &amp;lt;tt&amp;gt;name&amp;lt;/tt&amp;gt; zu 'tutorial5' geändert wurde.&lt;br /&gt;
&lt;br /&gt;
==Erklärung==&lt;br /&gt;
&lt;br /&gt;
===mainwindow.h===&lt;br /&gt;
&lt;br /&gt;
Hier haben wir nichts weiteres gemacht als eine neue &amp;lt;tt&amp;gt;openFile&amp;lt;/tt&amp;gt; Funktion hinzuzufügen, die einen &amp;lt;tt&amp;gt;QString&amp;lt;/tt&amp;gt; annimmt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt&amp;gt;&lt;br /&gt;
void openFile(const QString &amp;amp;inputFileName);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===mainwindow.cpp===&lt;br /&gt;
&lt;br /&gt;
Hier gibt es keinen neuen Code, nur Umordnen. Alles aus &amp;lt;tt&amp;gt;void openFile()&amp;lt;/tt&amp;gt; wurde in &amp;lt;tt&amp;gt;void openFile(const QString &amp;amp;inputFileName)&amp;lt;/tt&amp;gt; verschoben, ausser der Aufruf an &amp;lt;tt&amp;gt;KFileDialog::getOpenFileName()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Auf diese Weise können wir &amp;lt;tt&amp;gt;openFile()&amp;lt;/tt&amp;gt; aufrufen, wenn wir einen Dialog anzeigen möchten, oder wir können &amp;lt;tt&amp;gt;openFile(QString)&amp;lt;/tt&amp;gt; aufrufen, falls wir den Namen der Datei bereits kennen.&lt;br /&gt;
&lt;br /&gt;
===main.cpp===&lt;br /&gt;
&lt;br /&gt;
Hier passiert die ganze {{class|KCmdLineArgs}} Hexerei.&lt;br /&gt;
&lt;br /&gt;
==Erzeugen, Installieren und Ausführen==&lt;br /&gt;
&lt;br /&gt;
===CMakeLists.txt===&lt;br /&gt;
&amp;lt;code ini n&amp;gt;&lt;br /&gt;
project(tutorial5)&lt;br /&gt;
 &lt;br /&gt;
find_package(KDE4 REQUIRED)&lt;br /&gt;
include_directories( ${KDE4_INCLUDES} )&lt;br /&gt;
 &lt;br /&gt;
set(tutorial5_SRCS &lt;br /&gt;
  main.cpp&lt;br /&gt;
  mainwindow.cpp&lt;br /&gt;
)&lt;br /&gt;
 &lt;br /&gt;
kde4_add_executable(tutorial5 ${tutorial5_SRCS})&lt;br /&gt;
 &lt;br /&gt;
target_link_libraries(tutorial5 ${KDE4_KDEUI_LIBS}&lt;br /&gt;
                                ${KDE4_KIO_LIBS})&lt;br /&gt;
 &lt;br /&gt;
install(TARGETS tutorial5 DESTINATION ${BIN_INSTALL_DIR})&lt;br /&gt;
install( FILES tutorial5ui.rc &lt;br /&gt;
         DESTINATION  ${DATA_INSTALL_DIR}/tutorial5 )&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mit dieser Datei kann die Anleitung auf die gleiche Weise erstellt und ausgeführt werden wie Anleitung 3 und 4. Für mehr Informationen siehe [[Development/Tutorials/Using KActions (de)|Anleitung 3]].&lt;br /&gt;
&lt;br /&gt;
 mkdir build &amp;amp;&amp;amp; cd build&lt;br /&gt;
 cmake .. -DCMAKE_INSTALL_PREFIX=$HOME&lt;br /&gt;
 make install&lt;br /&gt;
 $HOME/bin/tutorial5&lt;br /&gt;
&lt;br /&gt;
==Weiter Geht's==&lt;br /&gt;
Now you can move on to the ### (TODO [[User:milliams]]) tutorial.&lt;br /&gt;
&lt;br /&gt;
[[Category:C++]]&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials_(de)</id>
		<title>Development/Tutorials (de)</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials_(de)"/>
				<updated>2008-01-01T11:41:03Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:I18n/Language Navigation Bar|Development/Tutorials}}&lt;br /&gt;
&lt;br /&gt;
{{improve (de)|Bitte hilf, die englische Seite vollständig ins Deutsche zu übersetzen.}}&lt;br /&gt;
&lt;br /&gt;
== Einführung in die KDE 4 Programmierung ==&lt;br /&gt;
Sind Sie an der Entwicklung von Programmen für KDE 4 interesiert? Wenn ja sind Sie hier genau richtig. Diese Artikelserie richtet sich an alle, die noch nie mit KDE programmiert haben.&lt;br /&gt;
;[[Development/Tutorials/First program (de)|Hallo Welt!]]&lt;br /&gt;
:''Einführung in die Grundlagen der KDE Programmierung''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Using KXmlGuiWindow (de)|Erstellen eines Hauptfensters]]&lt;br /&gt;
:''Dieser Artikel erklärt, wie der wichtigste Teil eines grafischen Programmes erstellt wird: das Hauptfenster.''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Using KActions (de)|Die Verwendung von KActions]]&lt;br /&gt;
:''In diesem Artikel erfahren Sie, wie Aktionen und Werkzeugleisten (Toolbars) im Menü hinzugefügt werden können.''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Saving and loading (de)|Laden und Speichern von Dateien]]&lt;br /&gt;
:''Dieser Artikel führt die KIO Bibliothek ein und erklärt wie man Dateien laden und speichern kann.''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/KCmdLineArgs (de)|Befehlszeilen Argumente (todo)]]&lt;br /&gt;
:''In diesem Artikel werden sie lernen ihrer Anwendung zu ermöglichen, Dateien über die Befehlszeile zu öffnen oder sogar mit 'Öffnen mit' von Dolphin aus zu verwenden.''&lt;br /&gt;
&lt;br /&gt;
== Grundlagen ==&lt;br /&gt;
;[[Development/Tutorials/KDE4 Porting Guide (de)|Ihre Applikation nach KDE 4 portieren]]&lt;br /&gt;
:''Anleitungen Qt3/KDE3 Applikationen nach Qt4/KDE4 zu portieren''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/CMake (de)|Einführung in CMake]]&lt;br /&gt;
:''Wie man CMake in KDE 4 benutzt''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Common Programming Mistakes (de)|Häufige Programmierfehler]]&lt;br /&gt;
:''Einige häufige Fehler die man während der Entwicklung von Qt und KDE Applikationen machen kann und wie man sie vermeidet.''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Using Qt Designer (de)|Den Qt Designer benutzen um Benutzerschnittstellen zu erzeugen]]&lt;br /&gt;
:''Wie man UI Dateien mit dem Designer erzeugt und wie man diese in einem KDE Programm integriert.''&lt;br /&gt;
&lt;br /&gt;
== Dienste: Applicationen and Plugins ==&lt;br /&gt;
;[[Development/Tutorials/Services/Introduction (de)|Einführung in das Dienst-Framework]]&lt;br /&gt;
:''Eine Einführung über das Dienst-Framework in KDE und was es dem Applikationsentwickler zur Verfügung stellen kann. Beschäftigt sich mit dem system configuration cache (SyCoCa), den benötigten Dateien und wie indizierte Informationen benutzt werden.&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Services/Traders (de)|Dienste über Trader Queries finden]]&lt;br /&gt;
:''Wie man mit der Trader Query Syntax Dienste wie Plugins oder Mimetypes findet, die im SyCoCa zwischengespeichert wurden. ''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Services/Plugins (de)|Erstellen und Laden von Plugins mit KService]]&lt;br /&gt;
:''Zeigt, wie man eigene Plugintypen definiert, installiere Plugins findet (einschließlich denen von anderen Herstellern) und wie man diese einfach und portabel läd, indem man KService benutzt.''&lt;br /&gt;
&lt;br /&gt;
== Lokalisation ==&lt;br /&gt;
;[[Development/Tutorials/Localization/Unicode (de)|Einführung in Unicode]]&lt;br /&gt;
:''Eine Einführung was Unicode ist und wie KDE Applikationen damit umgehen.''&lt;br /&gt;
&lt;br /&gt;
; [[Development/Tutorials/Localization/i18n (de)|Beim Schreiben der Applikation an die Lokalisation denken]]&lt;br /&gt;
:''Diese Anleitung beschäftigt sich damit, was Lokalisation ist, warum sie wichtig ist und wie man sicherstellt, dass die eigene Applikation bereit ist, lokalisiert zu werden. Jeder Applikationsentwickler sollte das lesen.''&lt;br /&gt;
&lt;br /&gt;
; [[Development/Tutorials/Localization/i18n Mistakes (de)|Häufige Fehler vermeiden]]&lt;br /&gt;
:''Es gibt einige häufige Fehler, die es verhindern, dass eine Applikation angemesssen übersetzt werden kann. Diese Anleitung zeigt diese Fehler auf und zeigt, wie man sie vermeidet.''&lt;br /&gt;
&lt;br /&gt;
; [[Development/Tutorials/Localization/Language Change (de)|Mit Sprachänderungen umgehen]]&lt;br /&gt;
:''Wie man seiner Applikation beibringt beim nächsten Start oder zur Laufzeit eine andere Sprache zu benutzen.''&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials/Using_KActions_(de)</id>
		<title>Development/Tutorials/Using KActions (de)</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials/Using_KActions_(de)"/>
				<updated>2008-01-01T11:36:45Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:I18n/Language Navigation Bar|Development/Tutorials/Using_KActions}}&lt;br /&gt;
&lt;br /&gt;
{{TutorialBrowser (de)|&lt;br /&gt;
&lt;br /&gt;
series=Anleitungen für Anfänger|&lt;br /&gt;
&lt;br /&gt;
name=KActions benutzen|&lt;br /&gt;
&lt;br /&gt;
pre=[[Development/Tutorials/Using_KXmlGuiWindow (de)|Anleitung 2 - KXmlGuiWindow]]|&lt;br /&gt;
&lt;br /&gt;
next=[[Development/Tutorials/Saving_and_loading (de)|Anleitung 4 - Laden und Speichern von Dateien]]| &lt;br /&gt;
&lt;br /&gt;
reading=Keine&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Zusammenfassung==&lt;br /&gt;
In diesem Kapitel wird das Konzept der Aktionen eingeführt. Aktionen sind ein vereinheitlichter Weg, dem Benutzer eine Interaktion mit Ihrem Programm zu ermöglichen&lt;br /&gt;
&lt;br /&gt;
Soll zum Beispiel durch das Klicken eines Buttons, einem Eintrag im Dateimenü oder einem Tastaturshortcut das Textfeld geleert werden, wird dies alles durch eine {{class|KAction}} bewerkstelligt.&lt;br /&gt;
&lt;br /&gt;
[[image:introtokdetutorial3.png|frame|center]]&lt;br /&gt;
&lt;br /&gt;
==KAction==&lt;br /&gt;
Eine {{class|KAction}} ist ein Objekt, welches alle Informationen über das Icon und Shortcuts enthält, welche mit einer bestimmten Aktion assoziiert sind. Diese Aktion läßt sich mit einem [http://doc.trolltech.com/latest/signalsandslots.html slot] verbinden, welcher dann bestimmte Arbeiten ausführt, die bei dieser Aktion vorgesehen sind. &lt;br /&gt;
&lt;br /&gt;
===Eine eigene Aktion erzeugen===&lt;br /&gt;
Um eine Aktion zu erzeugen, muss &amp;lt;tt&amp;gt;#include &amp;lt;KAction&amp;gt;&amp;lt;/tt&amp;gt; in die  &amp;lt;tt&amp;gt;.cpp&amp;lt;/tt&amp;gt; Datei eingefügt werden.  &lt;br /&gt;
&lt;br /&gt;
=====Das Objekt erzeugen=====&lt;br /&gt;
Wir werden hier eine Aktion erzeugen, welche die Applikation aus Kapitel 2 dahingehend erweitert, dass durch sie das Textfeld geleert wird. Die KAction wird in einer Reihe einzelner Schritte zusammengestellt. Zunächst wird das Objekt selber erzeugt:&lt;br /&gt;
&amp;lt;code cppqt&amp;gt;KAction* clearAction = new KAction(this);&amp;lt;/code&amp;gt;&lt;br /&gt;
Das erzeugt ein KAction-Objekt welches &amp;lt;tt&amp;gt;clearAction&amp;lt;/tt&amp;gt; heißt.&lt;br /&gt;
&lt;br /&gt;
=====Text=====&lt;br /&gt;
Bei dem jetzt erzeugten KAction Objekt können jetzt die Eigenschaften gesetzt werden. Zunächst setzen wir einen Text der im Menü und unter seinem Icon in der Werkzeugleiste angezeigt wird:&lt;br /&gt;
&amp;lt;code cppqt&amp;gt;clearAction-&amp;gt;setText(i18n(&amp;quot;Clear&amp;quot;));&amp;lt;/code&amp;gt;&lt;br /&gt;
Wie man sieht, muss dieser Text durch die &amp;lt;tt&amp;gt;i18n()&amp;lt;/tt&amp;gt; Funktion geleitet werden, wenn man das Benutzerinterface später übersetzen möchte. &lt;br /&gt;
&lt;br /&gt;
=====Icon=====&lt;br /&gt;
Soll in der Werkzeugleiste die Aktion angezeigt werden, muss man ein Icon verknüpfen, welches die Aktion bildlich beschreibt. Um das zu bewekstelligen, benutzen wir die &amp;lt;tt&amp;gt;setIcon()&amp;lt;/tt&amp;gt; Funktion:&lt;br /&gt;
&amp;lt;code cppqt&amp;gt;clearAction-&amp;gt;setIcon(KIcon(&amp;quot;document-new&amp;quot;));&amp;lt;/code&amp;gt;&lt;br /&gt;
Hier wird das Standardicon &amp;lt;tt&amp;gt;document-new&amp;lt;/tt&amp;gt; von KDE benutzt.&lt;br /&gt;
&lt;br /&gt;
=====Shortcut=====&lt;br /&gt;
Wir können auch einen Tastaturshortcut definieren, welcher die Aktion ausführt.. Das wird ganz einfach durch &amp;lt;code cppqt&amp;gt;clearAction-&amp;gt;setShortcut(Qt::CTRL+Qt::Key_W);&amp;lt;/code&amp;gt; bewekstelligt. In diesem Fall wird Ctrl+W mit der Aktion verknüpft.&lt;br /&gt;
&lt;br /&gt;
=====Zur Sammlung hinzufügen=====&lt;br /&gt;
Damit das XmlGui Framework auf unsere Aktion zugreifen kann, muss diese in die ''action collection'' (Sammlung der Aktionen) der Applikation eingefügt werden. Auf diese wird über die &amp;lt;tt&amp;gt;actionCollection()&amp;lt;/tt&amp;gt; Funktion zugegriffen: &lt;br /&gt;
&amp;lt;code cppqt&amp;gt;&lt;br /&gt;
actionCollection()-&amp;gt;addAction(&amp;quot;clear&amp;quot;, clearAction);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Dieser Code fügt die &amp;lt;tt&amp;gt;clearAction&amp;lt;/tt&amp;gt; KAction in die Sammlung ein und gibt ihr den Namen ''clear''. Dieser Name wird vom XmlGui Framework benutzt.&lt;br /&gt;
&lt;br /&gt;
=====Die Aktion verbinden=====&lt;br /&gt;
Jetzt ist unsere Aktion vollständig aufgesetzt und sie muss nun noch verknüpft werden, damit sie etwas sinnvolles macht. Wir werden unsere Aktion mit dem &amp;lt;tt&amp;gt;clear()&amp;lt;/tt&amp;gt; Slot, der zu einem KTextArea Objekt gehört, verknüpfen:&lt;br /&gt;
&amp;lt;code cppqt&amp;gt;&lt;br /&gt;
connect( clearAction, SIGNAL( triggered(bool) ), &lt;br /&gt;
         textArea, SLOT( clear() ) );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Das gleiche würden wir in Qt mit einer {{qt|QAction}} machen&lt;br /&gt;
&lt;br /&gt;
===KStandardAction===&lt;br /&gt;
&lt;br /&gt;
Manche Aktionen, wie zum Beispiel 'beenden', 'speichern' und 'laden', benötigt fast jede KDE Applikation. Daher gibt es zur Vereinfachung vorgefertigte KActions, auf welche über {{class|KStandardAction}} zugegriffen wird. &lt;br /&gt;
&lt;br /&gt;
Diese sind sehr einfach zu benutzen. Sobald man &amp;lt;tt&amp;gt;#include &amp;lt;KStandardAction&amp;gt;&amp;lt;/tt&amp;gt; im Quellcode eingefügt hat, muss man nur noch festlegen, welche Funktion bei Auslösung aufgerufen werden soll und zu welcher &amp;lt;tt&amp;gt;KActionCollection&amp;lt;/tt&amp;gt; die Aktion hinzugefügt werden soll. Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt&amp;gt;KStandardAction::quit(kapp, SLOT(quit()), actionCollection());&amp;lt;/code&amp;gt;&lt;br /&gt;
Dieser Code erzeugt ein KAction Objekt mit dem entsprechenden Icon, Text und Shortcut und fügt dieses sogar zum Datei-Menü hinzu.&lt;br /&gt;
&lt;br /&gt;
==Der Code==&lt;br /&gt;
===mainwindow.h===&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#ifndef MAINWINDOW_H&lt;br /&gt;
#define MAINWINDOW_H&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;KXmlGuiWindow&amp;gt;&lt;br /&gt;
#include &amp;lt;KTextEdit&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class MainWindow : public KXmlGuiWindow&lt;br /&gt;
{&lt;br /&gt;
  public:&lt;br /&gt;
    MainWindow(QWidget *parent=0);&lt;br /&gt;
	&lt;br /&gt;
  private:&lt;br /&gt;
    KTextEdit* textArea;&lt;br /&gt;
    void setupActions();&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===mainwindow.cpp===&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;quot;mainwindow.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;KApplication&amp;gt;&lt;br /&gt;
#include &amp;lt;KAction&amp;gt;&lt;br /&gt;
#include &amp;lt;KLocale&amp;gt;&lt;br /&gt;
#include &amp;lt;KActionCollection&amp;gt;&lt;br /&gt;
#include &amp;lt;KStandardAction&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MainWindow::MainWindow(QWidget *parent)&lt;br /&gt;
    : KXmlGuiWindow(parent)&lt;br /&gt;
{&lt;br /&gt;
  textArea = new KTextEdit;&lt;br /&gt;
  setCentralWidget(textArea);&lt;br /&gt;
&lt;br /&gt;
  setupActions();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void MainWindow::setupActions()&lt;br /&gt;
{&lt;br /&gt;
  KAction* clearAction = new KAction(this);&lt;br /&gt;
  clearAction-&amp;gt;setText(i18n(&amp;quot;Clear&amp;quot;));&lt;br /&gt;
  clearAction-&amp;gt;setIcon(KIcon(&amp;quot;document-new&amp;quot;));&lt;br /&gt;
  clearAction-&amp;gt;setShortcut(Qt::CTRL+Qt::Key_W);&lt;br /&gt;
  actionCollection()-&amp;gt;addAction(&amp;quot;clear&amp;quot;, clearAction);&lt;br /&gt;
  connect(clearAction, SIGNAL(triggered(bool)),&lt;br /&gt;
          textArea, SLOT(clear()));&lt;br /&gt;
&lt;br /&gt;
  KStandardAction::quit(kapp, SLOT(quit()),&lt;br /&gt;
                        actionCollection());&lt;br /&gt;
&lt;br /&gt;
  setupGUI();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===main.cpp===&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KApplication&amp;gt;&lt;br /&gt;
#include &amp;lt;KAboutData&amp;gt;&lt;br /&gt;
#include &amp;lt;KCmdLineArgs&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;mainwindow.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
int main (int argc, char *argv[])&lt;br /&gt;
{&lt;br /&gt;
  KAboutData aboutData( &amp;quot;tutorial3&amp;quot;, &amp;quot;tutorial3&amp;quot;,&lt;br /&gt;
      ki18n(&amp;quot;Tutorial 3&amp;quot;), &amp;quot;1.0&amp;quot;,&lt;br /&gt;
      ki18n(&amp;quot;A simple text area using KAction etc.&amp;quot;),&lt;br /&gt;
      KAboutData::License_GPL,&lt;br /&gt;
      ki18n(&amp;quot;Copyright (c) 2007 Developer&amp;quot;) );&lt;br /&gt;
  KCmdLineArgs::init( argc, argv, &amp;amp;aboutData );&lt;br /&gt;
  KApplication app;&lt;br /&gt;
 &lt;br /&gt;
  MainWindow* window = new MainWindow();&lt;br /&gt;
  window-&amp;gt;show();&lt;br /&gt;
  return app.exec();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Die Aktionen mit den Menüs und Werkzeugleisten verknüpfen==&lt;br /&gt;
Zur Zeit haben wir nur unsere neue &amp;quot;Clear&amp;quot; Aktion erzeugt. Zum jetzigen Zeitpunkt würde diese weder in den Menüs noch in den Werkzeugleisten erscheinen. Um der Applikation mitzuteilen wo die Aktion eingefügt werden soll (und dem Benutzer zu ermöglichen, diese dann beliebig umherzuschieben) wird die KDE-Technik namens XmlGui genutzt. &lt;br /&gt;
&lt;br /&gt;
===XmlGui===&lt;br /&gt;
{{note (de)|In einer späteren Version von KDE4 könnte XmlGui durch ein neues Framework namens liveui ersetzt werden. Doch zum jetzigen Zeitpunkt ist XmlGui die einzige und korrekte Art, das UI aufzusetzen.}}&lt;br /&gt;
&lt;br /&gt;
Ruft man &amp;lt;tt&amp;gt;setupGUI()&amp;lt;/tt&amp;gt; in der {{class|KXmlGuiWindow}} Klasse auf, wird das XmlGui System aufgerufen, welche eine XML Datei einliest, welche das entsprechende interface beschreibt und die Buttons und Menüeinträge entsprechend erzeugt. Diese Datei wird im nächsten Schritt für unsere Applikation erzeugt.&lt;br /&gt;
&lt;br /&gt;
Natürlich muss das XmlGui System wissen, welche Beschreibungs-Datei zu der jeweiligen Applikation gehört. Es muss also dem Namen und den Pfad dieser Datei kennen. Standardmäßig soll die Datei &amp;lt;tt&amp;gt;appnameui.rc&amp;lt;/tt&amp;gt; genannt werden(&amp;lt;tt&amp;gt;appname&amp;lt;/tt&amp;gt; ist dabei der Name, der in {{class|KAboutData}}) gesetzt wurde). In unserem Beispiel wird die Datei also &amp;lt;tt&amp;gt;tutorial3ui.rc&amp;lt;/tt&amp;gt; heißen. Wo die Datei zu finden ist, wird von CMake erledigt.&lt;br /&gt;
&lt;br /&gt;
===Die ''appname''ui.rc Datei schreiben===&lt;br /&gt;
&lt;br /&gt;
Da die Beschreibung unseres UI mit XML definiert wird, muss der Inhalt der Beschreibung strengen Regeln folgen. Wir werden hier nicht alle Regeln auflisten. Darüber wird es eine gesonderte und detailierte Seite geben (die aber noch nicht fertig ist).&lt;br /&gt;
&lt;br /&gt;
===tutorial3ui.rc===&lt;br /&gt;
&amp;lt;code xml n&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE kpartgui SYSTEM &amp;quot;kpartgui.dtd&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;gui name=&amp;quot;tutorial3&amp;quot; version=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;ToolBar name=&amp;quot;mainToolBar&amp;quot; &amp;gt;&lt;br /&gt;
    &amp;lt;text&amp;gt;Main Toolbar&amp;lt;/text&amp;gt;&lt;br /&gt;
    &amp;lt;Action name=&amp;quot;clear&amp;quot; /&amp;gt;&lt;br /&gt;
    &amp;lt;ActionList name=&amp;quot;dynamicActionlist&amp;quot; /&amp;gt;&lt;br /&gt;
  &amp;lt;/ToolBar&amp;gt;&lt;br /&gt;
  &amp;lt;MenuBar&amp;gt;&lt;br /&gt;
    &amp;lt;Menu name=&amp;quot;file&amp;quot; &amp;gt;&lt;br /&gt;
      &amp;lt;text&amp;gt;&amp;amp;amp;File&amp;lt;/text&amp;gt;&lt;br /&gt;
      &amp;lt;Action name=&amp;quot;clear&amp;quot; /&amp;gt;&lt;br /&gt;
    &amp;lt;/Menu&amp;gt;&lt;br /&gt;
  &amp;lt;/MenuBar&amp;gt;&lt;br /&gt;
&amp;lt;/gui&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das &amp;lt;tt&amp;gt;&amp;lt;Toolbar&amp;gt;&amp;lt;/tt&amp;gt; Tag beschreibt die Werkzeugleiste (der Balken mit Icons am oberen Rand des Fensters). Wir geben dieser hier den eindeutigen Namen ''mainToolBar'', setzen den Namen, der für den Benutzer sichtbar ist, auf  ''Main Toolbar'', indem wir das &amp;lt;tt&amp;gt;&amp;lt;text&amp;gt;&amp;lt;/tt&amp;gt; Tag anwenden und fügen letztlich unsere Clear-Aktion in die Werkzeugleiste ein, indem wir das &amp;lt;tt&amp;gt;&amp;lt;Action&amp;gt;&amp;lt;/tt&amp;gt; Tag benutzen. Der Parameter &amp;quot;name&amp;quot; dieses Tags ist die gleiche Zeichenkette, die der &amp;lt;tt&amp;gt;addAction()&amp;lt;/tt&amp;gt; Funktion im C++ Code übergeben wurde. &lt;br /&gt;
&lt;br /&gt;
Neben der Werkzeugleiste können wir die Aktion auch in das Hauptmenü einfügen. Dieses erfolgt über das &amp;lt;tt&amp;gt;&amp;lt;MenuBar&amp;gt;&amp;lt;/tt&amp;gt; Tag. Hier wird festgelegt, dass die Aktion in das ''File'' Menü eingefügt werden soll. Die Aktion selber wird auf die gleiche Art und Weise eingefügt wie bereits in der der Werkzeugleiste beschrieben. &lt;br /&gt;
&lt;br /&gt;
Bitte beachten Sie, dass sie auch eine dynamische Aktionsliste in die Konfigurationsdatei einfügen können, wenn Sie das &amp;lt;tt&amp;gt;&amp;lt;ActionList&amp;gt;&amp;lt;/tt&amp;gt; Tag benutzen. Mehr Informationen darüber finden Sie in der Methodenbeschreibung &amp;lt;tt&amp;gt;plugActionList()&amp;lt;/tt&amp;gt; der {{class|KXMLGUIClient}} Dokumentation.&lt;br /&gt;
&lt;br /&gt;
Ändern Sie jedesmal das &amp;quot;version&amp;quot; Attribut des Gui-Tags wenn Sie die .rc Datei geändert haben, damit ein Auffrisches des Systemcaches erfolgt. &lt;br /&gt;
&lt;br /&gt;
==CMake==&lt;br /&gt;
Da wir jetzt XmlGui benutzen, muß die &amp;lt;tt&amp;gt;tutorial3ui.rc&amp;lt;/tt&amp;gt; Datei irgendwo hin kopiert werden, wo KDE sie finden kann. '''Aus diesem Grund muss unser Programm irgendwo hin installiert werden.'''&lt;br /&gt;
&lt;br /&gt;
===CMakeLists.txt===&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
project(tutorial3)&lt;br /&gt;
&lt;br /&gt;
find_package(KDE4 REQUIRED)&lt;br /&gt;
include_directories( ${KDE4_INCLUDES} )&lt;br /&gt;
&lt;br /&gt;
set(tutorial3_SRCS &lt;br /&gt;
  main.cpp&lt;br /&gt;
  mainwindow.cpp&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
kde4_add_executable(tutorial3 ${tutorial3_SRCS})&lt;br /&gt;
&lt;br /&gt;
target_link_libraries(tutorial3 ${KDE4_KDEUI_LIBS})&lt;br /&gt;
&lt;br /&gt;
install(TARGETS tutorial3 DESTINATION ${BIN_INSTALL_DIR})&lt;br /&gt;
install( FILES tutorial3ui.rc &lt;br /&gt;
         DESTINATION  ${DATA_INSTALL_DIR}/tutorial3 )&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese Datei sieht fast genau so aus wie diejenige für Kapitel2, hat aber zwei extra Zeilen am Ende. Diese beschreiben, wohin die Dateien installiert werden sollen. Zunächst wird das &amp;lt;tt&amp;gt;tutorial3&amp;lt;/tt&amp;gt; Ziel in das Verzeichnis &amp;lt;tt&amp;gt;BIN_INSTALL_DIR&amp;lt;/tt&amp;gt; Verzeichnis installiert und anschließend die &amp;lt;tt&amp;gt;tutorial3ui.rc&amp;lt;/tt&amp;gt; Datei, die das Layout unseres Userinterfaces beschreibt in das Datenverzeichnis unserer Applikation. &lt;br /&gt;
&lt;br /&gt;
===Erzeugen, Installieren und Ausführen===&lt;br /&gt;
Wenn Sie keinen Schreibzugriff auf das KDE4 Installationsverzeichnis haben, können Sie das Programm auch in ein Verzeichnis innerhalb Ihres Heimatverzeichnissen installieren. &lt;br /&gt;
&lt;br /&gt;
Um CMake mitzuteilen, wohin das Programm installiert werden soll, setzen Sie den &amp;lt;tt&amp;gt;DCMAKE_INSTALL_PREFIX&amp;lt;/tt&amp;gt; Schalter. Um also das Programm in das KDE Verzeichnis zu installieren, rufen Sie&lt;br /&gt;
 cmake . -DCMAKE_INSTALL_PREFIX=$KDEDIR&lt;br /&gt;
 make install&lt;br /&gt;
 tutorial3&lt;br /&gt;
auf.&lt;br /&gt;
&lt;br /&gt;
Wenn man hingegen das Programm irgendwo lokal zu Testzwecken installieren will (bei der zurzeit etwas eingeschränkten Funktionalität unsere Applikation ist es vielleicht nicht unbedingt sinnvoll diese in das KDE Hauptverzeichnis zu installieren), wird mit dem Befehl&lt;br /&gt;
 cmake . -DCMAKE_INSTALL_PREFIX=/home/kde-devel/kdetmp&lt;br /&gt;
eine KDE-artige Verzeichnisstruktur innerhalb des ~/kdetmp Verzeichnissen angelegt und die Applikation in das {{path|/home/kde-devel/kdetmp/bin/tutorial3}} Verzeichnis kopiert.&lt;br /&gt;
&lt;br /&gt;
==Weiter geht's==&lt;br /&gt;
Jetzt können sie mit dem Kapitel [[Development/Tutorials/Saving_and_loading (de)| Laden und Speichern von Dateien]] fortfahren.&lt;br /&gt;
&lt;br /&gt;
[[Category:C++]]&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials/KConfig</id>
		<title>Development/Tutorials/KConfig</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials/KConfig"/>
				<updated>2007-12-31T18:18:52Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:I18n/Language Navigation Bar|Development/Tutorials/KConfig}}&lt;br /&gt;
{{TutorialBrowser|&lt;br /&gt;
&lt;br /&gt;
series=KConfig|&lt;br /&gt;
&lt;br /&gt;
name=Introduction to KConfig|&lt;br /&gt;
&lt;br /&gt;
next=[[../Using_KConfig_XT|Using KConfig XT]]|&lt;br /&gt;
&lt;br /&gt;
reading=None&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Abstract ==&lt;br /&gt;
&lt;br /&gt;
This tutorial looks at the KDE configuration data system, starting with an overview of the design fundamentals from an application developer's point of view. It then looks at the classes relevant to application development one by one before moving on to kiosk (user and group profiles) integration.&lt;br /&gt;
&lt;br /&gt;
== Design Essentials ==&lt;br /&gt;
&lt;br /&gt;
KConfig is designed to abstract away the concept of actual storage and retrieval of configuration settings behind an API that allows easy fetching and setting of information. Where and in what format the data is stored is not relevant to an application using KConfig. This keeps all KDE applications consistent in their handling of configurations while alleviating each and every application author to build such a system on their own from scratch, which can be a highly error prone exercise.&lt;br /&gt;
&lt;br /&gt;
A KConfig object represents a single configuration object. Each configuration object is referenced by its unique name and may be actually read from multiple local or remote files or services. Each application has a default configuration object associated with it and there is also a global configuration object.&lt;br /&gt;
&lt;br /&gt;
These configuration objects are broken down into a two level hierarchy: groups and keys. A configuration object can have any number of groups and each group can have one or more keys with associated values.&lt;br /&gt;
&lt;br /&gt;
Values stored may be of any number of data types. They are stored and retreived as the objects themselves. For example, a {{qt|QObject}} object is passed to a config object directly when storing a color value and when retreived a {{qt|QObject}} object is returned. Applications themselves therefore generally do not have to perform serialization and deserialization of objects themselves.&lt;br /&gt;
&lt;br /&gt;
== The KConfig Class ==&lt;br /&gt;
&lt;br /&gt;
The {{class|KConfig}} object is used to access a given configuration object. There are a number of ways to create a config object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
// a plain old read/write config object&lt;br /&gt;
KConfig config(&amp;quot;myapprc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// a specific file in the filesystem&lt;br /&gt;
// currently must be an INI style file&lt;br /&gt;
KConfig fullPath(&amp;quot;/etc/kderc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// not merged with global values&lt;br /&gt;
KConfig globalFree( &amp;quot;localsrc&amp;quot;, KConfig::NoGlobals );&lt;br /&gt;
&lt;br /&gt;
// not merged with globals or the $KDEDIRS hierarchy&lt;br /&gt;
KConfig simpleConfig( &amp;quot;simplerc&amp;quot;, KConfig::SimpleConfig );&lt;br /&gt;
&lt;br /&gt;
// config specific to a component, in this case a plugin&lt;br /&gt;
KConfig pluginConfig( componentData(), &amp;quot;pluginrc&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
// outside the standard config resource&lt;br /&gt;
KConfig dataResource( &amp;quot;data&amp;quot;, &amp;quot;myapp/somefile&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The KConfig object create on line 2 is a regular config object. We can read values from it, write new entries and ask for various properties of the object.  This object will be loaded from the config resource as determined by {{class|KStandardDirs}}, meaning that every instance of the &amp;lt;tt&amp;gt;myapprc&amp;lt;/tt&amp;gt; object in each of the directories in the config resource hierarchy will be merged to create the values seen in this object. This is how system wide and per-user/group profiles are generated and supported and it all happens transparently to the application itself.&lt;br /&gt;
&lt;br /&gt;
{{tip|For more information on how the merging works, see the [[KDE System Administration/KDE_Filesystem_Hierarchy|KDE Filesystem Hierarchy]] article.}}&lt;br /&gt;
&lt;br /&gt;
On line 6 we open a specific local file, this case {{path|/etc/kderc}}. This performs no merging of values and expects an INI style file.&lt;br /&gt;
&lt;br /&gt;
Line 9 sees the creation of a configuration object that is not merged with the global &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt; configuration object, while the configuration file on line 12 is additionally not merged with any files in the &amp;lt;tt&amp;gt;$KDEDIRS&amp;lt;/tt&amp;gt; hierarchy. This can noticeably improve performance in the case where one is simply reading values out of a simple configuration for which global values are not meaningful.&lt;br /&gt;
&lt;br /&gt;
Line 15 creates a configuration object using the {{class|KComponentData}} object that belongs to a plugin or other component. The plugin may have a different set of directories defined in its {{class|KStandardDirs}} and this is a way of ensuring that {{class|KConfig}} respects this.&lt;br /&gt;
&lt;br /&gt;
Finally on line 18 we see the creation of a configuration object that does not exist in the &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; resource but rather in the application &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; resource. You may use any resource that {{class|KStandardDirs}} is aware of, including ones that are added at runtime.&lt;br /&gt;
&lt;br /&gt;
=== Special Configuration Objects ===&lt;br /&gt;
&lt;br /&gt;
Each application has its own configuration object that uses the name provided to {{class|KAboutData}} appended with &amp;quot;rc&amp;quot; as its name. So an app named &amp;quot;myapp&amp;quot; would have the default configuration object of &amp;quot;myapprc&amp;quot;. This configuration file can be retrieved in this way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KComponentData&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
#include &amp;lt;KGlobal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    // note that this is actually a KSharedConfig&lt;br /&gt;
    // more on that class in a bit!&lt;br /&gt;
    KConfig* config = KGlobal::config();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The default configuration object for the application is accessed when no name is specified when creating a {{class|KConfig}} object. So we could also do this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    KConfig config;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additionally, each component may have its own configuration object. This is generally accessed via the plugin's &amp;lt;tt&amp;gt;componentData()&amp;lt;/tt&amp;gt; rather than &amp;lt;tt&amp;gt;{{class|KGlobal}}::mainComponent()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Finally there is a global configuration object, &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt;, that is shared by every application. It holds such information as the default application shortcuts for various actions. It is &amp;quot;blended&amp;quot; into the configuration object if the &amp;lt;tt&amp;gt;KConfig::IncludeGlobals&amp;lt;/tt&amp;gt; flag is passed to the {{class|KConfig}} constructor, which is the default.&lt;br /&gt;
&lt;br /&gt;
=== Commonly Useful Methods ===&lt;br /&gt;
&lt;br /&gt;
To save the current state of the configuration object we call the &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; method. This method is also called when the object is destroyed. If no changes have been made or the resource reports itself as non-writable (such as in the case of the user not having write permissions to the file) then no disk activity occurs. &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; merges changes performed concurrently by other processes - local changes have priority, though.&lt;br /&gt;
&lt;br /&gt;
If we want to make sure that we have the latest values from disk we can call &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt; which calls &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; and then reloads the data from disk.&lt;br /&gt;
&lt;br /&gt;
If we need to prevent the config object from saving already made modifications to disk we need to call &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt;. A particular use case for this is rolling back the configuration to the on-disk state by calling &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt; followed by &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Listing all groups in a configuration object is as simple as calling &amp;lt;tt&amp;gt;groupList()&amp;lt;/tt&amp;gt; as in this code snippet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::mainComponent().config();&lt;br /&gt;
&lt;br /&gt;
foreach ( const QString&amp;amp; group, config.groupList() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;next group:&amp;quot; &amp;lt;&amp;lt; group;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== KSharedConfig ==&lt;br /&gt;
&lt;br /&gt;
The {{class|KSharedConfig}} class is a reference counted version of {{class|KConfig}}. It thus provides a way to reference the same configuration object from multiple places in your application without the extra overhead of separate objects or concerns about syncronizing writes to disk even if the configuration object is updated from multiple code paths. &lt;br /&gt;
&lt;br /&gt;
Accessing a {{class|KSharedConfig}} object is as easy as this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KSharedConfigPtr config = KSharedConfig::openConfig();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;openConfig()&amp;lt;/tt&amp;gt; take the same parameters as {{class|KConfig}}'s constructors do, allowing one to define which configuration file to open, flags to control merging and non-&amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; resources.&lt;br /&gt;
&lt;br /&gt;
{{class|KSharedConfig}} is generally recommended over using {{class|KConfig}} itself, and the object returned from {{class|KComponentData}} is indeed a {{class|KSharedConfig}} object.&lt;br /&gt;
&lt;br /&gt;
== KConfigGroup ==&lt;br /&gt;
&lt;br /&gt;
Now that we have a configuration object, the next step is to actually use it. The first thing we must do is to define which group of key/value pairs we wish to access in the object. We do this by creating a KConfigGroup object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig config;&lt;br /&gt;
KConfigGroup generalGroup( &amp;amp;config, &amp;quot;General&amp;quot; );&lt;br /&gt;
KConfigGroup colorsGroup = config.group( &amp;quot;Colors&amp;quot; ); // ... or a bit differently ...&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can pass {{class|KConfig}} or {{class|KSharedConfig}} objects to {{class|KConfigGroup}}.&lt;br /&gt;
&lt;br /&gt;
Config groups can be nested as well:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfigGroup subGroup1( &amp;amp;generalGroup, &amp;quot;LessGeneral&amp;quot; );&lt;br /&gt;
KConfigGroup subGroup2 = colorsGroup.group( &amp;quot;Dialogs&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Reading Entries ==&lt;br /&gt;
&lt;br /&gt;
With a {{class|KConfigGroup}} object in hand reading entries is now quite straight forward:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
QString accountName = generalGroup.readEntry( &amp;quot;Account&amp;quot;,&lt;br /&gt;
                                              QString() );&lt;br /&gt;
QColor color = colorsGroup.readEntry( &amp;quot;background&amp;quot;,&lt;br /&gt;
                                      Qt::white );&lt;br /&gt;
QStringList list = generalGroup.readEntry( &amp;quot;List&amp;quot;,&lt;br /&gt;
                                           QStringList() );&lt;br /&gt;
QString path = generalGroup.readPathEntry( &amp;quot;SaveTo&amp;quot;,&lt;br /&gt;
                                           defaultPath );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As can be seen from the above, you can mix reads from different {{class|KConfigGroup}} objects created on the same {{class|KConfig}} object. The read methods take the key, which is case sensitive, as the first argument and the default value as the second argument. This argument controls what kind of data, e.g. a color in line 3 above, is to be expected as well as the type of object returned. The returned object is wrapped in a {{qt|QVariant}} to make this magic happen.&lt;br /&gt;
&lt;br /&gt;
There are a couple of special read methods, including &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; which returns a file system path. It is vital that one uses &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; if it is a path as this enables such features as roaming profiles to work properly.&lt;br /&gt;
&lt;br /&gt;
If no such key currently exists in the configuration object, the default value is returned instead. If there is a localized (e.g. translated into another language) entry for the key that matches the current locale, that is returned.&lt;br /&gt;
&lt;br /&gt;
== Writing Entries ==&lt;br /&gt;
&lt;br /&gt;
Setting new values is similarly straightforward:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
generalGroup.writeEntry( &amp;quot;Account&amp;quot;, accountName );&lt;br /&gt;
generalGroup.writePathEntry( &amp;quot;SaveTo&amp;quot;, savePath );&lt;br /&gt;
colorGroup.writeEntry( &amp;quot;background&amp;quot;, color );&lt;br /&gt;
generalGroup.config()-&amp;gt;sync();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note the use of &amp;lt;tt&amp;gt;writePathEntry&amp;lt;/tt&amp;gt; and how the type of object we use, such as {{qt|QColor}} on line 3, dictates how the data is serialized. Additionally, once we are done writing entries, &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; must be called on the config object for it to be saved to disk. We can also simply wait for the object to be destroyed, which triggers an automatic &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; if necessary.&lt;br /&gt;
&lt;br /&gt;
== KDesktopFile: A Special Case ==&lt;br /&gt;
&lt;br /&gt;
When is a configuration file not a configuration file? When it is a [http://freedesktop.org/wiki/Standards_2fdesktop_2dentry_2dspec desktop file]. These files, which are essentially configuration files at their heart, are used  to describe entries for application menus, mimetypes, plugins and various services.&lt;br /&gt;
&lt;br /&gt;
When accessing a .desktop file, one should instead use the {{class|KDesktopFile}} class which, while a {{class|KConfig}} class offering all the capabilities described above, offers a set of methods designed to make accessing standard attributes of these files consistent and reliable.&lt;br /&gt;
&lt;br /&gt;
== Kiosk: Lockdown and User/Group Profiles ==&lt;br /&gt;
&lt;br /&gt;
KConfig provides a powerful set of lockdown and configuration definition capabilities, collectively known as &amp;quot;Kiosk&amp;quot;, that many system administrators and system integrators rely on. While most of this framework is provided transparently to the application, there is occassion when an application will want to check on the read/write status of a configuration object.&lt;br /&gt;
&lt;br /&gt;
Entries in configuration objects that are locked down using the kiosk facilities are said to be ''immutable''. An application can check for immutability of entire configuration objects, groups or keys as shown in this example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::config();&lt;br /&gt;
&lt;br /&gt;
if ( config-&amp;gt;isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;configuration object is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
KConfigGroup group(config, &amp;quot;General&amp;quot;);&lt;br /&gt;
if ( group.isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;group General is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if ( group.entryIsImmutable(&amp;quot;URL&amp;quot;) ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;URL entry in group General is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This can be useful in particular situations where an action should be taken when an item is immutable. For instance, the KDE panels will not offer configuration options to the user or allow them to otherwise change the order of applets and icons when the panel's configuration object is marked as immutable.&lt;br /&gt;
&lt;br /&gt;
== KConfig XT ==&lt;br /&gt;
&lt;br /&gt;
There is a way to make certain use cases of KConfig easier, faster and more reliable: KConfig XT. In particular, for main application or plugin configuration objects and when syncing configuration dialogs and other interfaces with these values, KConfig XT can help immensely. It also  simultaneously documents the configuration options available, which makes every sys admin and system integrator that uses KDE that much more happy.&lt;br /&gt;
&lt;br /&gt;
[[../Using_KConfig_XT|The next tutorial in the KConfig series covers what KConfig XT is and how to use it.]]&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials/KConfig</id>
		<title>Development/Tutorials/KConfig</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials/KConfig"/>
				<updated>2007-12-31T18:18:38Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:I18n/Language Navigation Bar|Development/Tutorials/KConfig}}&lt;br /&gt;
{{TutorialBrowser|&lt;br /&gt;
&lt;br /&gt;
series=KConfig|&lt;br /&gt;
&lt;br /&gt;
name=Introduction to KConfig|&lt;br /&gt;
&lt;br /&gt;
next=[[../Using_KConfig_XT|Using KConfig XT]]|&lt;br /&gt;
&lt;br /&gt;
reading=none&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Abstract ==&lt;br /&gt;
&lt;br /&gt;
This tutorial looks at the KDE configuration data system, starting with an overview of the design fundamentals from an application developer's point of view. It then looks at the classes relevant to application development one by one before moving on to kiosk (user and group profiles) integration.&lt;br /&gt;
&lt;br /&gt;
== Design Essentials ==&lt;br /&gt;
&lt;br /&gt;
KConfig is designed to abstract away the concept of actual storage and retrieval of configuration settings behind an API that allows easy fetching and setting of information. Where and in what format the data is stored is not relevant to an application using KConfig. This keeps all KDE applications consistent in their handling of configurations while alleviating each and every application author to build such a system on their own from scratch, which can be a highly error prone exercise.&lt;br /&gt;
&lt;br /&gt;
A KConfig object represents a single configuration object. Each configuration object is referenced by its unique name and may be actually read from multiple local or remote files or services. Each application has a default configuration object associated with it and there is also a global configuration object.&lt;br /&gt;
&lt;br /&gt;
These configuration objects are broken down into a two level hierarchy: groups and keys. A configuration object can have any number of groups and each group can have one or more keys with associated values.&lt;br /&gt;
&lt;br /&gt;
Values stored may be of any number of data types. They are stored and retreived as the objects themselves. For example, a {{qt|QObject}} object is passed to a config object directly when storing a color value and when retreived a {{qt|QObject}} object is returned. Applications themselves therefore generally do not have to perform serialization and deserialization of objects themselves.&lt;br /&gt;
&lt;br /&gt;
== The KConfig Class ==&lt;br /&gt;
&lt;br /&gt;
The {{class|KConfig}} object is used to access a given configuration object. There are a number of ways to create a config object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
// a plain old read/write config object&lt;br /&gt;
KConfig config(&amp;quot;myapprc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// a specific file in the filesystem&lt;br /&gt;
// currently must be an INI style file&lt;br /&gt;
KConfig fullPath(&amp;quot;/etc/kderc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// not merged with global values&lt;br /&gt;
KConfig globalFree( &amp;quot;localsrc&amp;quot;, KConfig::NoGlobals );&lt;br /&gt;
&lt;br /&gt;
// not merged with globals or the $KDEDIRS hierarchy&lt;br /&gt;
KConfig simpleConfig( &amp;quot;simplerc&amp;quot;, KConfig::SimpleConfig );&lt;br /&gt;
&lt;br /&gt;
// config specific to a component, in this case a plugin&lt;br /&gt;
KConfig pluginConfig( componentData(), &amp;quot;pluginrc&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
// outside the standard config resource&lt;br /&gt;
KConfig dataResource( &amp;quot;data&amp;quot;, &amp;quot;myapp/somefile&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The KConfig object create on line 2 is a regular config object. We can read values from it, write new entries and ask for various properties of the object.  This object will be loaded from the config resource as determined by {{class|KStandardDirs}}, meaning that every instance of the &amp;lt;tt&amp;gt;myapprc&amp;lt;/tt&amp;gt; object in each of the directories in the config resource hierarchy will be merged to create the values seen in this object. This is how system wide and per-user/group profiles are generated and supported and it all happens transparently to the application itself.&lt;br /&gt;
&lt;br /&gt;
{{tip|For more information on how the merging works, see the [[KDE System Administration/KDE_Filesystem_Hierarchy|KDE Filesystem Hierarchy]] article.}}&lt;br /&gt;
&lt;br /&gt;
On line 6 we open a specific local file, this case {{path|/etc/kderc}}. This performs no merging of values and expects an INI style file.&lt;br /&gt;
&lt;br /&gt;
Line 9 sees the creation of a configuration object that is not merged with the global &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt; configuration object, while the configuration file on line 12 is additionally not merged with any files in the &amp;lt;tt&amp;gt;$KDEDIRS&amp;lt;/tt&amp;gt; hierarchy. This can noticeably improve performance in the case where one is simply reading values out of a simple configuration for which global values are not meaningful.&lt;br /&gt;
&lt;br /&gt;
Line 15 creates a configuration object using the {{class|KComponentData}} object that belongs to a plugin or other component. The plugin may have a different set of directories defined in its {{class|KStandardDirs}} and this is a way of ensuring that {{class|KConfig}} respects this.&lt;br /&gt;
&lt;br /&gt;
Finally on line 18 we see the creation of a configuration object that does not exist in the &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; resource but rather in the application &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; resource. You may use any resource that {{class|KStandardDirs}} is aware of, including ones that are added at runtime.&lt;br /&gt;
&lt;br /&gt;
=== Special Configuration Objects ===&lt;br /&gt;
&lt;br /&gt;
Each application has its own configuration object that uses the name provided to {{class|KAboutData}} appended with &amp;quot;rc&amp;quot; as its name. So an app named &amp;quot;myapp&amp;quot; would have the default configuration object of &amp;quot;myapprc&amp;quot;. This configuration file can be retrieved in this way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KComponentData&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
#include &amp;lt;KGlobal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    // note that this is actually a KSharedConfig&lt;br /&gt;
    // more on that class in a bit!&lt;br /&gt;
    KConfig* config = KGlobal::config();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The default configuration object for the application is accessed when no name is specified when creating a {{class|KConfig}} object. So we could also do this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    KConfig config;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additionally, each component may have its own configuration object. This is generally accessed via the plugin's &amp;lt;tt&amp;gt;componentData()&amp;lt;/tt&amp;gt; rather than &amp;lt;tt&amp;gt;{{class|KGlobal}}::mainComponent()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Finally there is a global configuration object, &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt;, that is shared by every application. It holds such information as the default application shortcuts for various actions. It is &amp;quot;blended&amp;quot; into the configuration object if the &amp;lt;tt&amp;gt;KConfig::IncludeGlobals&amp;lt;/tt&amp;gt; flag is passed to the {{class|KConfig}} constructor, which is the default.&lt;br /&gt;
&lt;br /&gt;
=== Commonly Useful Methods ===&lt;br /&gt;
&lt;br /&gt;
To save the current state of the configuration object we call the &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; method. This method is also called when the object is destroyed. If no changes have been made or the resource reports itself as non-writable (such as in the case of the user not having write permissions to the file) then no disk activity occurs. &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; merges changes performed concurrently by other processes - local changes have priority, though.&lt;br /&gt;
&lt;br /&gt;
If we want to make sure that we have the latest values from disk we can call &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt; which calls &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; and then reloads the data from disk.&lt;br /&gt;
&lt;br /&gt;
If we need to prevent the config object from saving already made modifications to disk we need to call &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt;. A particular use case for this is rolling back the configuration to the on-disk state by calling &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt; followed by &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Listing all groups in a configuration object is as simple as calling &amp;lt;tt&amp;gt;groupList()&amp;lt;/tt&amp;gt; as in this code snippet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::mainComponent().config();&lt;br /&gt;
&lt;br /&gt;
foreach ( const QString&amp;amp; group, config.groupList() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;next group:&amp;quot; &amp;lt;&amp;lt; group;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== KSharedConfig ==&lt;br /&gt;
&lt;br /&gt;
The {{class|KSharedConfig}} class is a reference counted version of {{class|KConfig}}. It thus provides a way to reference the same configuration object from multiple places in your application without the extra overhead of separate objects or concerns about syncronizing writes to disk even if the configuration object is updated from multiple code paths. &lt;br /&gt;
&lt;br /&gt;
Accessing a {{class|KSharedConfig}} object is as easy as this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KSharedConfigPtr config = KSharedConfig::openConfig();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;openConfig()&amp;lt;/tt&amp;gt; take the same parameters as {{class|KConfig}}'s constructors do, allowing one to define which configuration file to open, flags to control merging and non-&amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; resources.&lt;br /&gt;
&lt;br /&gt;
{{class|KSharedConfig}} is generally recommended over using {{class|KConfig}} itself, and the object returned from {{class|KComponentData}} is indeed a {{class|KSharedConfig}} object.&lt;br /&gt;
&lt;br /&gt;
== KConfigGroup ==&lt;br /&gt;
&lt;br /&gt;
Now that we have a configuration object, the next step is to actually use it. The first thing we must do is to define which group of key/value pairs we wish to access in the object. We do this by creating a KConfigGroup object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig config;&lt;br /&gt;
KConfigGroup generalGroup( &amp;amp;config, &amp;quot;General&amp;quot; );&lt;br /&gt;
KConfigGroup colorsGroup = config.group( &amp;quot;Colors&amp;quot; ); // ... or a bit differently ...&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can pass {{class|KConfig}} or {{class|KSharedConfig}} objects to {{class|KConfigGroup}}.&lt;br /&gt;
&lt;br /&gt;
Config groups can be nested as well:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfigGroup subGroup1( &amp;amp;generalGroup, &amp;quot;LessGeneral&amp;quot; );&lt;br /&gt;
KConfigGroup subGroup2 = colorsGroup.group( &amp;quot;Dialogs&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Reading Entries ==&lt;br /&gt;
&lt;br /&gt;
With a {{class|KConfigGroup}} object in hand reading entries is now quite straight forward:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
QString accountName = generalGroup.readEntry( &amp;quot;Account&amp;quot;,&lt;br /&gt;
                                              QString() );&lt;br /&gt;
QColor color = colorsGroup.readEntry( &amp;quot;background&amp;quot;,&lt;br /&gt;
                                      Qt::white );&lt;br /&gt;
QStringList list = generalGroup.readEntry( &amp;quot;List&amp;quot;,&lt;br /&gt;
                                           QStringList() );&lt;br /&gt;
QString path = generalGroup.readPathEntry( &amp;quot;SaveTo&amp;quot;,&lt;br /&gt;
                                           defaultPath );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As can be seen from the above, you can mix reads from different {{class|KConfigGroup}} objects created on the same {{class|KConfig}} object. The read methods take the key, which is case sensitive, as the first argument and the default value as the second argument. This argument controls what kind of data, e.g. a color in line 3 above, is to be expected as well as the type of object returned. The returned object is wrapped in a {{qt|QVariant}} to make this magic happen.&lt;br /&gt;
&lt;br /&gt;
There are a couple of special read methods, including &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; which returns a file system path. It is vital that one uses &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; if it is a path as this enables such features as roaming profiles to work properly.&lt;br /&gt;
&lt;br /&gt;
If no such key currently exists in the configuration object, the default value is returned instead. If there is a localized (e.g. translated into another language) entry for the key that matches the current locale, that is returned.&lt;br /&gt;
&lt;br /&gt;
== Writing Entries ==&lt;br /&gt;
&lt;br /&gt;
Setting new values is similarly straightforward:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
generalGroup.writeEntry( &amp;quot;Account&amp;quot;, accountName );&lt;br /&gt;
generalGroup.writePathEntry( &amp;quot;SaveTo&amp;quot;, savePath );&lt;br /&gt;
colorGroup.writeEntry( &amp;quot;background&amp;quot;, color );&lt;br /&gt;
generalGroup.config()-&amp;gt;sync();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note the use of &amp;lt;tt&amp;gt;writePathEntry&amp;lt;/tt&amp;gt; and how the type of object we use, such as {{qt|QColor}} on line 3, dictates how the data is serialized. Additionally, once we are done writing entries, &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; must be called on the config object for it to be saved to disk. We can also simply wait for the object to be destroyed, which triggers an automatic &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; if necessary.&lt;br /&gt;
&lt;br /&gt;
== KDesktopFile: A Special Case ==&lt;br /&gt;
&lt;br /&gt;
When is a configuration file not a configuration file? When it is a [http://freedesktop.org/wiki/Standards_2fdesktop_2dentry_2dspec desktop file]. These files, which are essentially configuration files at their heart, are used  to describe entries for application menus, mimetypes, plugins and various services.&lt;br /&gt;
&lt;br /&gt;
When accessing a .desktop file, one should instead use the {{class|KDesktopFile}} class which, while a {{class|KConfig}} class offering all the capabilities described above, offers a set of methods designed to make accessing standard attributes of these files consistent and reliable.&lt;br /&gt;
&lt;br /&gt;
== Kiosk: Lockdown and User/Group Profiles ==&lt;br /&gt;
&lt;br /&gt;
KConfig provides a powerful set of lockdown and configuration definition capabilities, collectively known as &amp;quot;Kiosk&amp;quot;, that many system administrators and system integrators rely on. While most of this framework is provided transparently to the application, there is occassion when an application will want to check on the read/write status of a configuration object.&lt;br /&gt;
&lt;br /&gt;
Entries in configuration objects that are locked down using the kiosk facilities are said to be ''immutable''. An application can check for immutability of entire configuration objects, groups or keys as shown in this example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::config();&lt;br /&gt;
&lt;br /&gt;
if ( config-&amp;gt;isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;configuration object is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
KConfigGroup group(config, &amp;quot;General&amp;quot;);&lt;br /&gt;
if ( group.isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;group General is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if ( group.entryIsImmutable(&amp;quot;URL&amp;quot;) ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;URL entry in group General is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This can be useful in particular situations where an action should be taken when an item is immutable. For instance, the KDE panels will not offer configuration options to the user or allow them to otherwise change the order of applets and icons when the panel's configuration object is marked as immutable.&lt;br /&gt;
&lt;br /&gt;
== KConfig XT ==&lt;br /&gt;
&lt;br /&gt;
There is a way to make certain use cases of KConfig easier, faster and more reliable: KConfig XT. In particular, for main application or plugin configuration objects and when syncing configuration dialogs and other interfaces with these values, KConfig XT can help immensely. It also  simultaneously documents the configuration options available, which makes every sys admin and system integrator that uses KDE that much more happy.&lt;br /&gt;
&lt;br /&gt;
[[../Using_KConfig_XT|The next tutorial in the KConfig series covers what KConfig XT is and how to use it.]]&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials/Using_KConfig_XT</id>
		<title>Development/Tutorials/Using KConfig XT</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials/Using_KConfig_XT"/>
				<updated>2007-12-31T18:18:09Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:I18n/Language Navigation Bar|Development/Tutorials/Using_KConfig_XT}}&lt;br /&gt;
{{TutorialBrowser|&lt;br /&gt;
&lt;br /&gt;
series=KConfig|&lt;br /&gt;
&lt;br /&gt;
pre=[[../KConfig|Introduction to KConfig]]|&lt;br /&gt;
&lt;br /&gt;
next=None|&lt;br /&gt;
&lt;br /&gt;
name=Using KConfig XT|&lt;br /&gt;
&lt;br /&gt;
reading=[http://api.kde.org/4.0-api/kdelibs-apidocs/kdecore/html/kconfig_compiler.html The KDE Configuration Compiler (KDE 4)]&amp;lt;br&amp;gt;[http://api.kde.org/3.5-api/kdelibs-apidocs/kdecore/html/kconfig_compiler.html The KDE Configuration Compiler (KDE 3)]&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Using KConfig XT ==&lt;br /&gt;
''Original Author'': Zack Rusin &amp;lt;[mailto:zack@kde.org zack@kde.org]&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This tutorial introduces the main concepts of the KconfigXT &lt;br /&gt;
configuration framework and shows how to efficiently use it in applications. It assumes that the reader has already developed a KDE application and is familiar with KConfig. A basic understanding of XML and concepts behind DTDs is also required.&lt;br /&gt;
  &lt;br /&gt;
The main idea behind KConfig XT is to make the life of application developers &lt;br /&gt;
easier while making the administration of large KDE installations more manageable.&lt;br /&gt;
The four basic parts of the new framework are: &lt;br /&gt;
&lt;br /&gt;
* KConfigSkeleton - a class in the libkdecore library which grants a more flexible access to the configuration options,&lt;br /&gt;
* XML file containing information about configuration options (the {{path|.kcfg}} file)&lt;br /&gt;
* An ini like file which provides the code generation options (the {{path|.kcfgc}} file)&lt;br /&gt;
* kconfig_compiler - which generates C++ source code from {{path|.kcfg}} and {{path|.kcfgc}} files. The generated class is based on KConfigSkeleton and provides an API for the application to access its configuration data.&lt;br /&gt;
&lt;br /&gt;
{{note|In this tutorial more advanced and optional features of KConfig XT and their descriptions are marked by ''italic text''. If you decide to skip them during the first reading, be sure to come back to them at some point. }}&lt;br /&gt;
&lt;br /&gt;
== .kcfg DTD Structure ==&lt;br /&gt;
&lt;br /&gt;
The structure of the {{path|.kcfg}} file is described by its DTD (kcfg.xsd - available from&lt;br /&gt;
[http://www.kde.org/standards/kcfg/1.0/kcfg.xsd here] (please note that browsers do not display DTDs in a visual form,&lt;br /&gt;
download the DTD directly and view it like a text file) or the kdecore &lt;br /&gt;
library). Please go through it before you go any further.  &lt;br /&gt;
&lt;br /&gt;
Lets create a simple .kcfg file. Please reference the code below as we go through each step.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE kcfg SYSTEM &lt;br /&gt;
    &amp;quot;http://www.kde.org/standards/kcfg/1.0/kcfg.xsd&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;kcfg&amp;gt;&lt;br /&gt;
  &amp;lt;kcfgfile name=&amp;quot;kjotsrc&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;include&amp;gt;kglobalsettings.h&amp;lt;/include&amp;gt;&lt;br /&gt;
  &amp;lt;group name=&amp;quot;kjots&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;entry name=&amp;quot;SplitterSizes&amp;quot; type=&amp;quot;IntList&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;label&amp;gt;How the main window is divided.&amp;lt;/label&amp;gt;&lt;br /&gt;
    &amp;lt;/entry&amp;gt;&lt;br /&gt;
    &amp;lt;entry name=&amp;quot;Width&amp;quot; type=&amp;quot;Int&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;label&amp;gt;Width of the main window.&amp;lt;/label&amp;gt;&lt;br /&gt;
      &amp;lt;default&amp;gt;600&amp;lt;/default&amp;gt;&lt;br /&gt;
    &amp;lt;/entry&amp;gt;&lt;br /&gt;
    &amp;lt;entry name=&amp;quot;Height&amp;quot; type=&amp;quot;Int&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;label&amp;gt;Height of the main window.&amp;lt;/label&amp;gt;&lt;br /&gt;
      &amp;lt;default&amp;gt;400&amp;lt;/default&amp;gt;&lt;br /&gt;
    &amp;lt;/entry&amp;gt;&lt;br /&gt;
    &amp;lt;entry name=&amp;quot;OpenBooks&amp;quot; type=&amp;quot;StringList&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;label&amp;gt;All books that are opened.&amp;lt;/label&amp;gt;&lt;br /&gt;
    &amp;lt;/entry&amp;gt;&lt;br /&gt;
    &amp;lt;entry name=&amp;quot;CurrentBook&amp;quot; type=&amp;quot;String&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;label&amp;gt;The book currently opened.&amp;lt;/label&amp;gt;&lt;br /&gt;
    &amp;lt;/entry&amp;gt;&lt;br /&gt;
    &amp;lt;entry name=&amp;quot;Font&amp;quot; type=&amp;quot;Font&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;label&amp;gt;The font used to display the contents of books.&amp;lt;/label&amp;gt;&lt;br /&gt;
      &amp;lt;default code=&amp;quot;true&amp;quot;&amp;gt;KGlobalSettings::generalFont()&amp;lt;/default&amp;gt;&lt;br /&gt;
    &amp;lt;/entry&amp;gt;&lt;br /&gt;
  &amp;lt;/group&amp;gt;&lt;br /&gt;
&amp;lt;/kcfg&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Use your favorite code editor to open a your_application_name{{path|.kcfg}} file (of course replacing your_application_name with the name of the application you want to convert to KConfig XT).&lt;br /&gt;
* Start that file by opening the &amp;amp;lt;kcfgfile&amp;amp;gt; tag which controls which KConfig file the data will be stored in. There are three possibilities:&lt;br /&gt;
*# If the &amp;amp;lt;kcfgfile&amp;amp;gt; tag has no attributes the generated code will use the application's default KConfig file (normally {{path|$HOME/.kde/config/&amp;lt;appname&amp;gt;rc}}).&lt;br /&gt;
*# ''The &amp;quot;name&amp;quot; attribute is used to manually specify a file name. If the value assigned to &amp;quot;name&amp;quot; is not an absolute file path, the file will be created in the default KDE config directory (normally {{path|$HOME/.kde/config}}).''&lt;br /&gt;
*# ''If you would like to be able to specify the config file at construction time, use &amp;amp;lt;kcfgfile arg=&amp;quot;true&amp;quot;&amp;amp;gt;. This causes the constructor of the generated class to take a KSharedConfig::Ptr as an argument, allowing you to construct multiple instances pointing to different files.''&lt;br /&gt;
* ''Add the optional &amp;amp;lt;include&amp;amp;gt; tags which may contain C++ header files that are needed to compile the code required to compute the default values.''&lt;br /&gt;
* The remaining entries in the XML file are grouped by the tag &amp;amp;lt;group&amp;amp;gt; which describes the corresponding groups in the configuration file.&lt;br /&gt;
*#The individual entries must have at least a name or a key. The key is used as the key in the config file. The name is used to create accessor and modifier functions. If &amp;amp;lt;key&amp;amp;gt; is not given, the name is used as the config file key. If &amp;amp;lt;key&amp;amp;gt; is given, but not &amp;amp;lt;name&amp;amp;gt;, the name is constructed by removing all spaces from the &amp;amp;lt;key&amp;amp;gt; contents.&lt;br /&gt;
*# Always add a label or a whatsthis tags to your application in which you describe the configuration options. The label tag is used for short descriptions of the entry, while whatsthis contains more verbose documentation. ''It's important for tools like KConfigEditor which can be used by systems administrators to setup machines over on the network.''&lt;br /&gt;
*# An entry must also have a type. The allowed types are: String, StringList, Font, Rect, Size, Color, Point, Int, UInt, Bool, Double, DateTime, Int64, UInt64 and Password. '' Besides those basic type the following special types are supported and include:''&lt;br /&gt;
*#* Path - This is a string that is specially treated as a file-path. In particular paths in the home directory are prefixed with $HOME when being stored in the configuration file.&lt;br /&gt;
*#* Enum - This indicates an enumeration. The possible enum values should be provided via the &amp;amp;lt;choices&amp;amp;gt; tag. Enum values are accessed as integers by the application but stored as string in the configuration file. This makes it possible to add more values at a later date without breaking compatibility.&lt;br /&gt;
*#* IntList - This indicates a list of integers. This information is provided to the application as QValueList&amp;amp;lt;int&amp;amp;gt;. Useful for storing QSplitter geometries.&lt;br /&gt;
*#* PathList - List of Path elements.&lt;br /&gt;
*# The min and max tags can be set to limit the value of the integer-type options.&lt;br /&gt;
*#''An entry can optionally have a default value which is used as default when the value isn't specified in any config file. Default values are interpreted as literal constant values. If a default value needs to be computed or if it needs to be obtained from a function call, the &amp;amp;lt;default&amp;amp;gt; tag should contain the code=&amp;quot;true&amp;quot; attribute. The contents of the &amp;amp;lt;default&amp;amp;gt; tag is then considered to be a C++ expression. ''&lt;br /&gt;
*#''Additional code for computing default values can be provided via the &amp;amp;lt;code&amp;amp;gt; tag. The contents of the &amp;amp;lt;code&amp;amp;gt; tag is inserted as-is. A typical use for this is to compute a common default value which can then be referenced by multiple entries that follow.''&lt;br /&gt;
*#''Optionally, the hidden option can also be added to the &amp;amp;lt;entry&amp;amp;gt;. The possible values are true and false.''&lt;br /&gt;
&lt;br /&gt;
== .kcfgc files ==&lt;br /&gt;
&lt;br /&gt;
After creating a {{path|.kcfg}} file create a {{path|.kcfgc}} file which describes the C++ file &lt;br /&gt;
generation options. The .kcfgc file is a simple ini file with the typical &lt;br /&gt;
&amp;quot;entry=value&amp;quot; format. To create a simple .kcfgc file follow these steps:&lt;br /&gt;
&lt;br /&gt;
# Open a new file in your favorite text editor.&lt;br /&gt;
# Start it with the &amp;quot;File=your_application_name.kcfg&amp;quot; entry which specifies where the configuration options for your application are stored.&lt;br /&gt;
# Add the &amp;quot;ClassName=YourConfigClassName&amp;quot; entry which specifies the name of the class that will be generated from the .kcfg file. Remember that the generated class will be derived from KConfigSkeleton. PLease make sure that YourConfigClassName is not a class name already used in your application. Save this file under {{path|yourconfigclassname.kcfgc.}} This will ensure the generation of the yourconfigclassname.{h,cpp} files where your configuration class will reside. &lt;br /&gt;
# Add any additional entries, which your application might need. Those additional entries include:&lt;br /&gt;
#* NameSpace - specifies the namespace in which the generated config class should reside,&lt;br /&gt;
#* Inherits - if you need the generated class to inherit your custom class,&lt;br /&gt;
#* Singleton - if the configuration class should be a singleton,&lt;br /&gt;
#* MemberVariables - specifies the access to the member variables, default is private,&lt;br /&gt;
#* ItemAccessors - relates to the above item, if member variables are public then it might make little sense to generate accessors. By default they are generated,&lt;br /&gt;
#* Mutators - similar to the above one, but applies to the mutator methods,&lt;br /&gt;
#* GlobalEnums - specifies whether enums should be class wide of whether they should be always explicitly prefixed with their type name,&lt;br /&gt;
#* UseEnumTypes - specifies whether enum values should be passed as type int or as their enum type in the return value of accessor functions and the arguments of mutator and signal functions.&lt;br /&gt;
&lt;br /&gt;
== Adjusting the CMakeLists.txt file ==&lt;br /&gt;
&lt;br /&gt;
After creating the .kcfg and .kcfgc files the next step is to adjust the &lt;br /&gt;
build to let kconfig_compiler generate the required class at compile time. Fortunately doing this is trivial and requires only one step, adding this line to the CMakeLists.txt file example:&lt;br /&gt;
&lt;br /&gt;
 kde4_add_kcfg_files(&amp;lt;project name&amp;gt;_SRCS settings.kcfgc)&lt;br /&gt;
&lt;br /&gt;
Alternatively, if a .moc file needs to be generated before compiling the generated source code, use&lt;br /&gt;
&lt;br /&gt;
 kde4_add_kcfg_files(&amp;lt;project name&amp;gt;_SRCS GENERATE_MOC settings.kcfgc)&lt;br /&gt;
&lt;br /&gt;
This assures that the configuration class is properly generated and that the .kcfg is installed so it can be used by tools like &lt;br /&gt;
the KConfigEditor.&lt;br /&gt;
&lt;br /&gt;
== Use and Dialogs ==&lt;br /&gt;
&lt;br /&gt;
After making all of the above changes you're ready to use KConfig XT. The &lt;br /&gt;
kconfig_compiler generated header file will have the name equal to the name of the .kcfg file but with a &amp;quot;.h&amp;quot; extension. Simply include that file wherever you want to access your configuration options.&lt;br /&gt;
&lt;br /&gt;
The use will depend on whether you have added the &amp;lt;tt&amp;gt;Singleton=true&amp;lt;/tt&amp;gt; entry to your .kcfgc file. &lt;br /&gt;
&lt;br /&gt;
One the nicest features of the KConfig XT is its seamless integration with the Qt &lt;br /&gt;
Designer generated dialogs. You can do that by using {{class|KConfigDialog}}. The &lt;br /&gt;
steps to do that are as follows: &lt;br /&gt;
&lt;br /&gt;
# Create the KConfigDialog and pass the instance of your configuration data as one of the arguments. The construct would look like the following example:&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;code cppqt&amp;gt;&lt;br /&gt;
KConfigDialog* dialog = new KConfigDialog( &lt;br /&gt;
         this, &amp;quot;settings&amp;quot;, YourAppSettings::self() );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
assuming that YourAppSettings is the value of the ClassName variable from the kcfgc file and the settings class is a singelton.&lt;br /&gt;
# In Qt Designer create widgets which should be used to configure your options. In order to make those widgets interact with the kcfg you have name each one of them using the following scheme:&lt;br /&gt;
## Prefix the Name of the widget which should control one of the options with &amp;quot;kcfg_&amp;quot;&lt;br /&gt;
## Append the &amp;quot;name&amp;quot; attribute value from your kcfg file which corresponds to option the given widget should control.&lt;br /&gt;
# Add the Qt Designer generated widget to the KConfigDialog.&lt;br /&gt;
# Show the dialog when you're done.&lt;br /&gt;
&lt;br /&gt;
== Example ==&lt;br /&gt;
&lt;br /&gt;
Here's an example usage of KConfig XT for the application named Example.&lt;br /&gt;
With the following example.kcfg file: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE kcfg SYSTEM &lt;br /&gt;
    &amp;quot;http://www.kde.org/standards/kcfg/1.0/kcfg.dtd&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;kcfg&amp;gt; &amp;lt;kcfgfile name=&amp;quot;examplerc&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;group name=&amp;quot;network&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;entry name=&amp;quot;ServerName&amp;quot; type=&amp;quot;String&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;label&amp;gt;Defines the sample server.&amp;lt;/label&amp;gt;&lt;br /&gt;
    &amp;lt;/entry&amp;gt;&lt;br /&gt;
    &amp;lt;entry name=&amp;quot;Port&amp;quot; type=&amp;quot;Int&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;label&amp;gt;Defines the server port&amp;lt;/label&amp;gt;&lt;br /&gt;
      &amp;lt;default&amp;gt;21&amp;lt;/default&amp;gt;&lt;br /&gt;
      &amp;lt;min&amp;gt;20&amp;lt;/min&amp;gt;&lt;br /&gt;
      &amp;lt;max&amp;gt;990&amp;lt;/max&amp;gt;&lt;br /&gt;
    &amp;lt;/entry&amp;gt;&lt;br /&gt;
  &amp;lt;/group&amp;gt;&lt;br /&gt;
&amp;lt;/kcfg&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And here's how to actually use the generated class. for the given kcfgc file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code ini&amp;gt;&lt;br /&gt;
File=example.kcfg &lt;br /&gt;
ClassName=ExampleSettings &lt;br /&gt;
Singleton=true &lt;br /&gt;
Mutators=true&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The header files wouldn't change, but the cpp files must now contain the &lt;br /&gt;
following code to access and store the configuration data :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
#include &amp;lt;ExampleSettings.h&amp;gt; &lt;br /&gt;
... &lt;br /&gt;
void ExampleClass::readConfig() { &lt;br /&gt;
        m_server  = ExampleSettings::serverName(); &lt;br /&gt;
        m_port    = ExampleSettings::port(); &lt;br /&gt;
} &lt;br /&gt;
void ExampleClass:saveSettings() { &lt;br /&gt;
        ExampleSettings::setServerName( m_server ); &lt;br /&gt;
        ExampleSettings::setPort( m_port ); &lt;br /&gt;
        ExampleSettings::writeConfig(); &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To add a dialog you need to create a Qt Designer widget with the widget names&lt;br /&gt;
corresponding to the names of the options they should edit and prefixed with &amp;quot;kcfg_&amp;quot;. &lt;br /&gt;
It could be something along the lines of:&lt;br /&gt;
&lt;br /&gt;
[[Image:kconfigxt.png|center|256px]]&lt;br /&gt;
&lt;br /&gt;
And you can use the dialog with the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt&amp;gt;&lt;br /&gt;
//An instance of your dialog could be already created and could be&lt;br /&gt;
// cached, in which case you want to display the cached dialog &lt;br /&gt;
// instead of creating another one&lt;br /&gt;
if ( KConfigDialog::showDialog( &amp;quot;settings&amp;quot; ) )&lt;br /&gt;
  return; &lt;br /&gt;
 &lt;br /&gt;
// KConfigDialog didn't find an instance of this dialog, so lets&lt;br /&gt;
// create it : &lt;br /&gt;
KConfigDialog* dialog = new KConfigDialog(this, &amp;quot;settings&amp;quot;,&lt;br /&gt;
                                          ExampleSettings::self()); &lt;br /&gt;
ExampleDesignerWidget* confWdg =  &lt;br /&gt;
                  new ExampleDesignerWidget( 0, &amp;quot;Example&amp;quot; ); &lt;br /&gt;
 &lt;br /&gt;
dialog-&amp;gt;addPage( confWdg, i18n(&amp;quot;Example&amp;quot;), &amp;quot;example&amp;quot; ); &lt;br /&gt;
 &lt;br /&gt;
//User edited the configuration - update your local copies of the &lt;br /&gt;
//configuration data &lt;br /&gt;
connect( dialog, SIGNAL(settingsChanged()), &lt;br /&gt;
         this, SLOT(updateConfiguration()) ); &lt;br /&gt;
 &lt;br /&gt;
dialog-&amp;gt;show();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And that's all it takes. You can have a look at [http://websvn.kde.org/trunk/KDE/kdegames/kreversi KReversi] and [http://websvn.kde.org/trunk/KDE/kdegames/ktron/ KTron] code in the [http://websvn.kde.org/trunk/KDE/kdegames kdegames module] to see a live example of KConfig XT!&lt;br /&gt;
&lt;br /&gt;
== Common Pitfalls and Tips ==&lt;br /&gt;
&lt;br /&gt;
* Do not forget to add the &amp;quot;type&amp;quot; attribute to the &amp;quot;entry&amp;quot; tag in your .kcfg file.&lt;br /&gt;
* Always try to add both the &amp;amp;lt;label&amp;amp;gt; and &amp;amp;lt;whatsthis&amp;amp;gt; tags to each entry.&lt;br /&gt;
* Putting the MemberVariables=public in your .kcfgc is usually a bad idea - you'll avoid accidental changes to those members by using the aggregation and forcing the use of the mutators.&lt;br /&gt;
* If your application doesn't have one central object (created before and destructed after; all others) then always put the Singleton=true entry in your .kcfgs file.&lt;br /&gt;
[[Category:C++]]&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials/Using_KConfig_XT</id>
		<title>Development/Tutorials/Using KConfig XT</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials/Using_KConfig_XT"/>
				<updated>2007-12-31T18:17:30Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:I18n/Language Navigation Bar|Development/Tutorials/Using_KConfig_XT}}&lt;br /&gt;
{{TutorialBrowser|&lt;br /&gt;
&lt;br /&gt;
series=KConfig|&lt;br /&gt;
&lt;br /&gt;
pre=[[../KConfig|Introduction to KConfig]]|&lt;br /&gt;
&lt;br /&gt;
next=none|&lt;br /&gt;
&lt;br /&gt;
name=Using KConfig XT|&lt;br /&gt;
&lt;br /&gt;
reading=[http://api.kde.org/4.0-api/kdelibs-apidocs/kdecore/html/kconfig_compiler.html The KDE Configuration Compiler (KDE 4)]&amp;lt;br&amp;gt;[http://api.kde.org/3.5-api/kdelibs-apidocs/kdecore/html/kconfig_compiler.html The KDE Configuration Compiler (KDE 3)]&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Using KConfig XT ==&lt;br /&gt;
''Original Author'': Zack Rusin &amp;lt;[mailto:zack@kde.org zack@kde.org]&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This tutorial introduces the main concepts of the KconfigXT &lt;br /&gt;
configuration framework and shows how to efficiently use it in applications. It assumes that the reader has already developed a KDE application and is familiar with KConfig. A basic understanding of XML and concepts behind DTDs is also required.&lt;br /&gt;
  &lt;br /&gt;
The main idea behind KConfig XT is to make the life of application developers &lt;br /&gt;
easier while making the administration of large KDE installations more manageable.&lt;br /&gt;
The four basic parts of the new framework are: &lt;br /&gt;
&lt;br /&gt;
* KConfigSkeleton - a class in the libkdecore library which grants a more flexible access to the configuration options,&lt;br /&gt;
* XML file containing information about configuration options (the {{path|.kcfg}} file)&lt;br /&gt;
* An ini like file which provides the code generation options (the {{path|.kcfgc}} file)&lt;br /&gt;
* kconfig_compiler - which generates C++ source code from {{path|.kcfg}} and {{path|.kcfgc}} files. The generated class is based on KConfigSkeleton and provides an API for the application to access its configuration data.&lt;br /&gt;
&lt;br /&gt;
{{note|In this tutorial more advanced and optional features of KConfig XT and their descriptions are marked by ''italic text''. If you decide to skip them during the first reading, be sure to come back to them at some point. }}&lt;br /&gt;
&lt;br /&gt;
== .kcfg DTD Structure ==&lt;br /&gt;
&lt;br /&gt;
The structure of the {{path|.kcfg}} file is described by its DTD (kcfg.xsd - available from&lt;br /&gt;
[http://www.kde.org/standards/kcfg/1.0/kcfg.xsd here] (please note that browsers do not display DTDs in a visual form,&lt;br /&gt;
download the DTD directly and view it like a text file) or the kdecore &lt;br /&gt;
library). Please go through it before you go any further.  &lt;br /&gt;
&lt;br /&gt;
Lets create a simple .kcfg file. Please reference the code below as we go through each step.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE kcfg SYSTEM &lt;br /&gt;
    &amp;quot;http://www.kde.org/standards/kcfg/1.0/kcfg.xsd&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;kcfg&amp;gt;&lt;br /&gt;
  &amp;lt;kcfgfile name=&amp;quot;kjotsrc&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;include&amp;gt;kglobalsettings.h&amp;lt;/include&amp;gt;&lt;br /&gt;
  &amp;lt;group name=&amp;quot;kjots&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;entry name=&amp;quot;SplitterSizes&amp;quot; type=&amp;quot;IntList&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;label&amp;gt;How the main window is divided.&amp;lt;/label&amp;gt;&lt;br /&gt;
    &amp;lt;/entry&amp;gt;&lt;br /&gt;
    &amp;lt;entry name=&amp;quot;Width&amp;quot; type=&amp;quot;Int&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;label&amp;gt;Width of the main window.&amp;lt;/label&amp;gt;&lt;br /&gt;
      &amp;lt;default&amp;gt;600&amp;lt;/default&amp;gt;&lt;br /&gt;
    &amp;lt;/entry&amp;gt;&lt;br /&gt;
    &amp;lt;entry name=&amp;quot;Height&amp;quot; type=&amp;quot;Int&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;label&amp;gt;Height of the main window.&amp;lt;/label&amp;gt;&lt;br /&gt;
      &amp;lt;default&amp;gt;400&amp;lt;/default&amp;gt;&lt;br /&gt;
    &amp;lt;/entry&amp;gt;&lt;br /&gt;
    &amp;lt;entry name=&amp;quot;OpenBooks&amp;quot; type=&amp;quot;StringList&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;label&amp;gt;All books that are opened.&amp;lt;/label&amp;gt;&lt;br /&gt;
    &amp;lt;/entry&amp;gt;&lt;br /&gt;
    &amp;lt;entry name=&amp;quot;CurrentBook&amp;quot; type=&amp;quot;String&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;label&amp;gt;The book currently opened.&amp;lt;/label&amp;gt;&lt;br /&gt;
    &amp;lt;/entry&amp;gt;&lt;br /&gt;
    &amp;lt;entry name=&amp;quot;Font&amp;quot; type=&amp;quot;Font&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;label&amp;gt;The font used to display the contents of books.&amp;lt;/label&amp;gt;&lt;br /&gt;
      &amp;lt;default code=&amp;quot;true&amp;quot;&amp;gt;KGlobalSettings::generalFont()&amp;lt;/default&amp;gt;&lt;br /&gt;
    &amp;lt;/entry&amp;gt;&lt;br /&gt;
  &amp;lt;/group&amp;gt;&lt;br /&gt;
&amp;lt;/kcfg&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Use your favorite code editor to open a your_application_name{{path|.kcfg}} file (of course replacing your_application_name with the name of the application you want to convert to KConfig XT).&lt;br /&gt;
* Start that file by opening the &amp;amp;lt;kcfgfile&amp;amp;gt; tag which controls which KConfig file the data will be stored in. There are three possibilities:&lt;br /&gt;
*# If the &amp;amp;lt;kcfgfile&amp;amp;gt; tag has no attributes the generated code will use the application's default KConfig file (normally {{path|$HOME/.kde/config/&amp;lt;appname&amp;gt;rc}}).&lt;br /&gt;
*# ''The &amp;quot;name&amp;quot; attribute is used to manually specify a file name. If the value assigned to &amp;quot;name&amp;quot; is not an absolute file path, the file will be created in the default KDE config directory (normally {{path|$HOME/.kde/config}}).''&lt;br /&gt;
*# ''If you would like to be able to specify the config file at construction time, use &amp;amp;lt;kcfgfile arg=&amp;quot;true&amp;quot;&amp;amp;gt;. This causes the constructor of the generated class to take a KSharedConfig::Ptr as an argument, allowing you to construct multiple instances pointing to different files.''&lt;br /&gt;
* ''Add the optional &amp;amp;lt;include&amp;amp;gt; tags which may contain C++ header files that are needed to compile the code required to compute the default values.''&lt;br /&gt;
* The remaining entries in the XML file are grouped by the tag &amp;amp;lt;group&amp;amp;gt; which describes the corresponding groups in the configuration file.&lt;br /&gt;
*#The individual entries must have at least a name or a key. The key is used as the key in the config file. The name is used to create accessor and modifier functions. If &amp;amp;lt;key&amp;amp;gt; is not given, the name is used as the config file key. If &amp;amp;lt;key&amp;amp;gt; is given, but not &amp;amp;lt;name&amp;amp;gt;, the name is constructed by removing all spaces from the &amp;amp;lt;key&amp;amp;gt; contents.&lt;br /&gt;
*# Always add a label or a whatsthis tags to your application in which you describe the configuration options. The label tag is used for short descriptions of the entry, while whatsthis contains more verbose documentation. ''It's important for tools like KConfigEditor which can be used by systems administrators to setup machines over on the network.''&lt;br /&gt;
*# An entry must also have a type. The allowed types are: String, StringList, Font, Rect, Size, Color, Point, Int, UInt, Bool, Double, DateTime, Int64, UInt64 and Password. '' Besides those basic type the following special types are supported and include:''&lt;br /&gt;
*#* Path - This is a string that is specially treated as a file-path. In particular paths in the home directory are prefixed with $HOME when being stored in the configuration file.&lt;br /&gt;
*#* Enum - This indicates an enumeration. The possible enum values should be provided via the &amp;amp;lt;choices&amp;amp;gt; tag. Enum values are accessed as integers by the application but stored as string in the configuration file. This makes it possible to add more values at a later date without breaking compatibility.&lt;br /&gt;
*#* IntList - This indicates a list of integers. This information is provided to the application as QValueList&amp;amp;lt;int&amp;amp;gt;. Useful for storing QSplitter geometries.&lt;br /&gt;
*#* PathList - List of Path elements.&lt;br /&gt;
*# The min and max tags can be set to limit the value of the integer-type options.&lt;br /&gt;
*#''An entry can optionally have a default value which is used as default when the value isn't specified in any config file. Default values are interpreted as literal constant values. If a default value needs to be computed or if it needs to be obtained from a function call, the &amp;amp;lt;default&amp;amp;gt; tag should contain the code=&amp;quot;true&amp;quot; attribute. The contents of the &amp;amp;lt;default&amp;amp;gt; tag is then considered to be a C++ expression. ''&lt;br /&gt;
*#''Additional code for computing default values can be provided via the &amp;amp;lt;code&amp;amp;gt; tag. The contents of the &amp;amp;lt;code&amp;amp;gt; tag is inserted as-is. A typical use for this is to compute a common default value which can then be referenced by multiple entries that follow.''&lt;br /&gt;
*#''Optionally, the hidden option can also be added to the &amp;amp;lt;entry&amp;amp;gt;. The possible values are true and false.''&lt;br /&gt;
&lt;br /&gt;
== .kcfgc files ==&lt;br /&gt;
&lt;br /&gt;
After creating a {{path|.kcfg}} file create a {{path|.kcfgc}} file which describes the C++ file &lt;br /&gt;
generation options. The .kcfgc file is a simple ini file with the typical &lt;br /&gt;
&amp;quot;entry=value&amp;quot; format. To create a simple .kcfgc file follow these steps:&lt;br /&gt;
&lt;br /&gt;
# Open a new file in your favorite text editor.&lt;br /&gt;
# Start it with the &amp;quot;File=your_application_name.kcfg&amp;quot; entry which specifies where the configuration options for your application are stored.&lt;br /&gt;
# Add the &amp;quot;ClassName=YourConfigClassName&amp;quot; entry which specifies the name of the class that will be generated from the .kcfg file. Remember that the generated class will be derived from KConfigSkeleton. PLease make sure that YourConfigClassName is not a class name already used in your application. Save this file under {{path|yourconfigclassname.kcfgc.}} This will ensure the generation of the yourconfigclassname.{h,cpp} files where your configuration class will reside. &lt;br /&gt;
# Add any additional entries, which your application might need. Those additional entries include:&lt;br /&gt;
#* NameSpace - specifies the namespace in which the generated config class should reside,&lt;br /&gt;
#* Inherits - if you need the generated class to inherit your custom class,&lt;br /&gt;
#* Singleton - if the configuration class should be a singleton,&lt;br /&gt;
#* MemberVariables - specifies the access to the member variables, default is private,&lt;br /&gt;
#* ItemAccessors - relates to the above item, if member variables are public then it might make little sense to generate accessors. By default they are generated,&lt;br /&gt;
#* Mutators - similar to the above one, but applies to the mutator methods,&lt;br /&gt;
#* GlobalEnums - specifies whether enums should be class wide of whether they should be always explicitly prefixed with their type name,&lt;br /&gt;
#* UseEnumTypes - specifies whether enum values should be passed as type int or as their enum type in the return value of accessor functions and the arguments of mutator and signal functions.&lt;br /&gt;
&lt;br /&gt;
== Adjusting the CMakeLists.txt file ==&lt;br /&gt;
&lt;br /&gt;
After creating the .kcfg and .kcfgc files the next step is to adjust the &lt;br /&gt;
build to let kconfig_compiler generate the required class at compile time. Fortunately doing this is trivial and requires only one step, adding this line to the CMakeLists.txt file example:&lt;br /&gt;
&lt;br /&gt;
 kde4_add_kcfg_files(&amp;lt;project name&amp;gt;_SRCS settings.kcfgc)&lt;br /&gt;
&lt;br /&gt;
Alternatively, if a .moc file needs to be generated before compiling the generated source code, use&lt;br /&gt;
&lt;br /&gt;
 kde4_add_kcfg_files(&amp;lt;project name&amp;gt;_SRCS GENERATE_MOC settings.kcfgc)&lt;br /&gt;
&lt;br /&gt;
This assures that the configuration class is properly generated and that the .kcfg is installed so it can be used by tools like &lt;br /&gt;
the KConfigEditor.&lt;br /&gt;
&lt;br /&gt;
== Use and Dialogs ==&lt;br /&gt;
&lt;br /&gt;
After making all of the above changes you're ready to use KConfig XT. The &lt;br /&gt;
kconfig_compiler generated header file will have the name equal to the name of the .kcfg file but with a &amp;quot;.h&amp;quot; extension. Simply include that file wherever you want to access your configuration options.&lt;br /&gt;
&lt;br /&gt;
The use will depend on whether you have added the &amp;lt;tt&amp;gt;Singleton=true&amp;lt;/tt&amp;gt; entry to your .kcfgc file. &lt;br /&gt;
&lt;br /&gt;
One the nicest features of the KConfig XT is its seamless integration with the Qt &lt;br /&gt;
Designer generated dialogs. You can do that by using {{class|KConfigDialog}}. The &lt;br /&gt;
steps to do that are as follows: &lt;br /&gt;
&lt;br /&gt;
# Create the KConfigDialog and pass the instance of your configuration data as one of the arguments. The construct would look like the following example:&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;code cppqt&amp;gt;&lt;br /&gt;
KConfigDialog* dialog = new KConfigDialog( &lt;br /&gt;
         this, &amp;quot;settings&amp;quot;, YourAppSettings::self() );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
assuming that YourAppSettings is the value of the ClassName variable from the kcfgc file and the settings class is a singelton.&lt;br /&gt;
# In Qt Designer create widgets which should be used to configure your options. In order to make those widgets interact with the kcfg you have name each one of them using the following scheme:&lt;br /&gt;
## Prefix the Name of the widget which should control one of the options with &amp;quot;kcfg_&amp;quot;&lt;br /&gt;
## Append the &amp;quot;name&amp;quot; attribute value from your kcfg file which corresponds to option the given widget should control.&lt;br /&gt;
# Add the Qt Designer generated widget to the KConfigDialog.&lt;br /&gt;
# Show the dialog when you're done.&lt;br /&gt;
&lt;br /&gt;
== Example ==&lt;br /&gt;
&lt;br /&gt;
Here's an example usage of KConfig XT for the application named Example.&lt;br /&gt;
With the following example.kcfg file: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE kcfg SYSTEM &lt;br /&gt;
    &amp;quot;http://www.kde.org/standards/kcfg/1.0/kcfg.dtd&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;kcfg&amp;gt; &amp;lt;kcfgfile name=&amp;quot;examplerc&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;group name=&amp;quot;network&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;entry name=&amp;quot;ServerName&amp;quot; type=&amp;quot;String&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;label&amp;gt;Defines the sample server.&amp;lt;/label&amp;gt;&lt;br /&gt;
    &amp;lt;/entry&amp;gt;&lt;br /&gt;
    &amp;lt;entry name=&amp;quot;Port&amp;quot; type=&amp;quot;Int&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;label&amp;gt;Defines the server port&amp;lt;/label&amp;gt;&lt;br /&gt;
      &amp;lt;default&amp;gt;21&amp;lt;/default&amp;gt;&lt;br /&gt;
      &amp;lt;min&amp;gt;20&amp;lt;/min&amp;gt;&lt;br /&gt;
      &amp;lt;max&amp;gt;990&amp;lt;/max&amp;gt;&lt;br /&gt;
    &amp;lt;/entry&amp;gt;&lt;br /&gt;
  &amp;lt;/group&amp;gt;&lt;br /&gt;
&amp;lt;/kcfg&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And here's how to actually use the generated class. for the given kcfgc file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code ini&amp;gt;&lt;br /&gt;
File=example.kcfg &lt;br /&gt;
ClassName=ExampleSettings &lt;br /&gt;
Singleton=true &lt;br /&gt;
Mutators=true&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The header files wouldn't change, but the cpp files must now contain the &lt;br /&gt;
following code to access and store the configuration data :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
#include &amp;lt;ExampleSettings.h&amp;gt; &lt;br /&gt;
... &lt;br /&gt;
void ExampleClass::readConfig() { &lt;br /&gt;
        m_server  = ExampleSettings::serverName(); &lt;br /&gt;
        m_port    = ExampleSettings::port(); &lt;br /&gt;
} &lt;br /&gt;
void ExampleClass:saveSettings() { &lt;br /&gt;
        ExampleSettings::setServerName( m_server ); &lt;br /&gt;
        ExampleSettings::setPort( m_port ); &lt;br /&gt;
        ExampleSettings::writeConfig(); &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To add a dialog you need to create a Qt Designer widget with the widget names&lt;br /&gt;
corresponding to the names of the options they should edit and prefixed with &amp;quot;kcfg_&amp;quot;. &lt;br /&gt;
It could be something along the lines of:&lt;br /&gt;
&lt;br /&gt;
[[Image:kconfigxt.png|center|256px]]&lt;br /&gt;
&lt;br /&gt;
And you can use the dialog with the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt&amp;gt;&lt;br /&gt;
//An instance of your dialog could be already created and could be&lt;br /&gt;
// cached, in which case you want to display the cached dialog &lt;br /&gt;
// instead of creating another one&lt;br /&gt;
if ( KConfigDialog::showDialog( &amp;quot;settings&amp;quot; ) )&lt;br /&gt;
  return; &lt;br /&gt;
 &lt;br /&gt;
// KConfigDialog didn't find an instance of this dialog, so lets&lt;br /&gt;
// create it : &lt;br /&gt;
KConfigDialog* dialog = new KConfigDialog(this, &amp;quot;settings&amp;quot;,&lt;br /&gt;
                                          ExampleSettings::self()); &lt;br /&gt;
ExampleDesignerWidget* confWdg =  &lt;br /&gt;
                  new ExampleDesignerWidget( 0, &amp;quot;Example&amp;quot; ); &lt;br /&gt;
 &lt;br /&gt;
dialog-&amp;gt;addPage( confWdg, i18n(&amp;quot;Example&amp;quot;), &amp;quot;example&amp;quot; ); &lt;br /&gt;
 &lt;br /&gt;
//User edited the configuration - update your local copies of the &lt;br /&gt;
//configuration data &lt;br /&gt;
connect( dialog, SIGNAL(settingsChanged()), &lt;br /&gt;
         this, SLOT(updateConfiguration()) ); &lt;br /&gt;
 &lt;br /&gt;
dialog-&amp;gt;show();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And that's all it takes. You can have a look at [http://websvn.kde.org/trunk/KDE/kdegames/kreversi KReversi] and [http://websvn.kde.org/trunk/KDE/kdegames/ktron/ KTron] code in the [http://websvn.kde.org/trunk/KDE/kdegames kdegames module] to see a live example of KConfig XT!&lt;br /&gt;
&lt;br /&gt;
== Common Pitfalls and Tips ==&lt;br /&gt;
&lt;br /&gt;
* Do not forget to add the &amp;quot;type&amp;quot; attribute to the &amp;quot;entry&amp;quot; tag in your .kcfg file.&lt;br /&gt;
* Always try to add both the &amp;amp;lt;label&amp;amp;gt; and &amp;amp;lt;whatsthis&amp;amp;gt; tags to each entry.&lt;br /&gt;
* Putting the MemberVariables=public in your .kcfgc is usually a bad idea - you'll avoid accidental changes to those members by using the aggregation and forcing the use of the mutators.&lt;br /&gt;
* If your application doesn't have one central object (created before and destructed after; all others) then always put the Singleton=true entry in your .kcfgs file.&lt;br /&gt;
[[Category:C++]]&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials/Updating_KConfig_Files</id>
		<title>Development/Tutorials/Updating KConfig Files</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials/Updating_KConfig_Files"/>
				<updated>2007-12-31T18:16:59Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:I18n/Language Navigation Bar|Development/Tutorials/Updating_KConfig_Files}}&lt;br /&gt;
{{TutorialBrowser|&lt;br /&gt;
&lt;br /&gt;
series=KConfig|&lt;br /&gt;
&lt;br /&gt;
pre=[[../KConfig| Introduction to KConfig]]|&lt;br /&gt;
&lt;br /&gt;
name=Updating KConfig files|&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=KConfig Update=&lt;br /&gt;
&lt;br /&gt;
This page describes how a developer can use the KConfig update mechanism (kconf_update) available in kdelibs to update a user's already existing config file to accomodate changes made to the format of the default config file.&lt;br /&gt;
&lt;br /&gt;
==Why should you use it?==&lt;br /&gt;
&lt;br /&gt;
Over time applications sometimes need to rearrange the way configuration options are stored. Since such an update shouldn't influence the configuration options that the user has selected, the application must take care that the options stored in the old way will still be honored.&lt;br /&gt;
&lt;br /&gt;
What used to happen is that the application looks up both the old and the&lt;br /&gt;
new configuration option and then decides which one to use. This method has several drawbacks:&lt;br /&gt;
* The application may need to read more configuration files than strictly needed, resulting in a slower startup.&lt;br /&gt;
* The application becomes bigger with code that will only be used once.&lt;br /&gt;
&lt;br /&gt;
kconf_update addresses these problems by offering a framework to update configuration files without adding code to the application itself.&lt;br /&gt;
&lt;br /&gt;
==How it works==&lt;br /&gt;
&lt;br /&gt;
Applications can install so called &amp;quot;update files&amp;quot; under&lt;br /&gt;
{{Path|$KDEDIR/share/apps/kconf_update.}} An update file has {{Path|.upd}} as an extension and contains instructions for transferring/converting configuration information from one place to another.&lt;br /&gt;
&lt;br /&gt;
Updating the configuration happens automatically, either when KDE gets started&lt;br /&gt;
or when kded detects a new update file in the above mentioned location.&lt;br /&gt;
&lt;br /&gt;
Update files are separated into sections. Each section has an id. When a&lt;br /&gt;
section describing a configuration change has been applied, the id will be&lt;br /&gt;
stored in the file {{Path|kconf_updaterc}}. This information is used to make sure that a configuration update is only performed once.&lt;br /&gt;
&lt;br /&gt;
If you overwrite an existing update file with a new version that contains a&lt;br /&gt;
new section, only the update instructions from this extra section will be&lt;br /&gt;
performed.&lt;br /&gt;
&lt;br /&gt;
==File format of the update file==&lt;br /&gt;
&lt;br /&gt;
Empty lines or lines that start with '#' are considered comments&lt;br /&gt;
Commas (,) are used to seperate fields and may not occur as part&lt;br /&gt;
of any field and all of the keywords are case-sensitive, i.e. you&lt;br /&gt;
cannot say &amp;quot;key&amp;quot; instead of &amp;quot;Key&amp;quot; for example.&lt;br /&gt;
&lt;br /&gt;
For the rest the file is parsed and executed sequentially from top to bottom.&lt;br /&gt;
Each line can contain one entry. The following entries are recognized:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;Id=&amp;lt;id&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With &amp;lt;id&amp;gt; identifying the group of update entries that follows. Once a group&lt;br /&gt;
of entries have been applied, their &amp;lt;id&amp;gt; is stored and this group of entries&lt;br /&gt;
will not be applied again.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
File=&amp;lt;oldfile&amp;gt;,&amp;lt;newfile&amp;gt;&lt;br /&gt;
File=&amp;lt;oldfile&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that configuration information is read from &amp;lt;oldfile&amp;gt; and written&lt;br /&gt;
to &amp;lt;newfile&amp;gt;. If you only specify &amp;lt;oldfile&amp;gt;, the information is read from&lt;br /&gt;
and as written to &amp;lt;oldfile&amp;gt;. Note that if the file does not exist&lt;br /&gt;
at the time kconf_update first checks, no related update will be performed.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Script=&amp;lt;script&amp;gt;[,&amp;lt;interpreter&amp;gt;]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;script&amp;gt; is the program that will be performing the updates. All entries from &amp;lt;oldfile&amp;gt; are piped into &amp;lt;script&amp;gt;. The output of &amp;lt;script&amp;gt;is used as new entries for &amp;lt;newfile&amp;gt;. Existing entries can be deleted by adding lines with &amp;quot;# DELETE [group]key&amp;quot; in the output of the script. To delete a whole group use &amp;quot;# DELETEGROUP [group]&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
There are two types of kconf_update scripts:&lt;br /&gt;
*Non-Compiled&lt;br /&gt;
*Compiled&lt;br /&gt;
&lt;br /&gt;
If &amp;lt;script&amp;gt; is written in a non-compiled language (such as ruby or perl), then it should be installed into &lt;br /&gt;
{{Path|${KCONF_UPDATE_INSTALL_DIR} }}. &lt;br /&gt;
&lt;br /&gt;
If &amp;lt;script&amp;gt; is a compiled application, it should be installed in {{Path|${BIN_INSTALL_DIR}/kconf_update_bin}}&lt;br /&gt;
&lt;br /&gt;
If the script command is issued after a &amp;quot;Group&amp;quot; command the behavior is slightly&lt;br /&gt;
different:&lt;br /&gt;
&lt;br /&gt;
All entries from &amp;lt;oldfile&amp;gt; in &amp;lt;oldgroup&amp;gt; are piped into &amp;lt;script&amp;gt;. The output&lt;br /&gt;
of script is used as new entries for &amp;lt;newfile&amp;gt; in &amp;lt;newgroup&amp;gt;, unless a different&lt;br /&gt;
group is specified with &amp;quot;[group]&amp;quot;. Existing entries can be deleted from&lt;br /&gt;
&amp;lt;oldgroup&amp;gt; by adding lines with &amp;quot;# DELETE key&amp;quot; in the output of the script.·&lt;br /&gt;
To delete &amp;lt;oldgroup&amp;gt; use &amp;quot;# DELETEGROUP&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;interpreter&amp;gt; can be something like &amp;quot;perl&amp;quot; or &amp;quot;ruby&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
It is also possible to have a script command without specifying &amp;lt;oldfile&amp;gt; or &amp;lt;newfile&amp;gt;. In that case the script is run but it will not be fed any input and its output will simply be discarded.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ScriptArguments=&amp;lt;arguments&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If specified, the arguments will be passed to &amp;lt;script&amp;gt;.&lt;br /&gt;
IMPORTANT: It has to be specified before Script=.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Group=&amp;lt;oldgroup&amp;gt;,&amp;lt;newgroup&amp;gt;&lt;br /&gt;
Group=&amp;lt;oldgroup&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that configuration information is read from the group &amp;lt;oldgroup&amp;gt;&lt;br /&gt;
and written to &amp;lt;newgroup&amp;gt;. If you only specify &amp;lt;oldgroup&amp;gt;, the information&lt;br /&gt;
is read from as well as written to &amp;lt;oldgroup&amp;gt;. You can use &amp;lt;default&amp;gt; to&lt;br /&gt;
specify keys that are not under any group.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
RemoveGroup=&amp;lt;oldgroup&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that &amp;lt;oldgroup&amp;gt; is removed entirely. This can be used&lt;br /&gt;
to remove obsolete entries or to force a revert to default values.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Options=&amp;lt;option1&amp;gt;, &amp;lt;option2&amp;gt;,&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With this entry you can specify options that apply to the next &amp;quot;Script&amp;quot;,&lt;br /&gt;
&amp;quot;Key&amp;quot; or &amp;quot;AllKeys&amp;quot; entry (only to the first!). Possible options are:&lt;br /&gt;
&lt;br /&gt;
*&amp;quot;copy&amp;quot; Copy the configuration item instead of moving it. This means that&lt;br /&gt;
the configuration item will not be deleted from &amp;lt;oldfile&amp;gt;/&amp;lt;oldgroup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;quot;overwrite&amp;quot; Normally, a configuration item is not moved if an item with the&lt;br /&gt;
new name already exists. When this option is specified the old configuration item will overwrite any existing item.&lt;br /&gt;
&lt;br /&gt;
Key=&amp;lt;oldkey&amp;gt;,&amp;lt;newkey&amp;gt;&lt;br /&gt;
Key=&amp;lt;oldkey&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that configuration information is read from the key &amp;lt;oldkey&amp;gt;&lt;br /&gt;
and written to &amp;lt;newkey&amp;gt;. If you only specify &amp;lt;oldkey&amp;gt;, the information&lt;br /&gt;
is read from as well as written to &amp;lt;oldkey&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
AllKeys&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that all configuration information in the selected group should&lt;br /&gt;
be moved (All keys).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
AllGroups&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that all configuration information from all keys in ALL·&lt;br /&gt;
groups should be moved.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
RemoveKey=&amp;lt;oldkey&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that &amp;lt;oldkey&amp;gt; is removed from the selected group. This can be used&lt;br /&gt;
to remove obsolete entries or to force a revert to default values.&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials/Updating_KConfig_Files</id>
		<title>Development/Tutorials/Updating KConfig Files</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials/Updating_KConfig_Files"/>
				<updated>2007-12-31T18:15:31Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: Undo revision 19014 by Rememberme (Talk)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:I18n/Language Navigation Bar|Development/Tutorials/Updating_KConfig_Files}}&lt;br /&gt;
{{TutorialBrowser|&lt;br /&gt;
&lt;br /&gt;
series=KConfig|&lt;br /&gt;
&lt;br /&gt;
pre=[[../Using_KConfig_XT| Using KConfig XT]]|&lt;br /&gt;
&lt;br /&gt;
name=Updating KConfig files|&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=KConfig Update=&lt;br /&gt;
&lt;br /&gt;
This page describes how a developer can use the KConfig update mechanism (kconf_update) available in kdelibs to update a user's already existing config file to accomodate changes made to the format of the default config file.&lt;br /&gt;
&lt;br /&gt;
==Why should you use it?==&lt;br /&gt;
&lt;br /&gt;
Over time applications sometimes need to rearrange the way configuration options are stored. Since such an update shouldn't influence the configuration options that the user has selected, the application must take care that the options stored in the old way will still be honored.&lt;br /&gt;
&lt;br /&gt;
What used to happen is that the application looks up both the old and the&lt;br /&gt;
new configuration option and then decides which one to use. This method has several drawbacks:&lt;br /&gt;
* The application may need to read more configuration files than strictly needed, resulting in a slower startup.&lt;br /&gt;
* The application becomes bigger with code that will only be used once.&lt;br /&gt;
&lt;br /&gt;
kconf_update addresses these problems by offering a framework to update configuration files without adding code to the application itself.&lt;br /&gt;
&lt;br /&gt;
==How it works==&lt;br /&gt;
&lt;br /&gt;
Applications can install so called &amp;quot;update files&amp;quot; under&lt;br /&gt;
{{Path|$KDEDIR/share/apps/kconf_update.}} An update file has {{Path|.upd}} as an extension and contains instructions for transferring/converting configuration information from one place to another.&lt;br /&gt;
&lt;br /&gt;
Updating the configuration happens automatically, either when KDE gets started&lt;br /&gt;
or when kded detects a new update file in the above mentioned location.&lt;br /&gt;
&lt;br /&gt;
Update files are separated into sections. Each section has an id. When a&lt;br /&gt;
section describing a configuration change has been applied, the id will be&lt;br /&gt;
stored in the file {{Path|kconf_updaterc}}. This information is used to make sure that a configuration update is only performed once.&lt;br /&gt;
&lt;br /&gt;
If you overwrite an existing update file with a new version that contains a&lt;br /&gt;
new section, only the update instructions from this extra section will be&lt;br /&gt;
performed.&lt;br /&gt;
&lt;br /&gt;
==File format of the update file==&lt;br /&gt;
&lt;br /&gt;
Empty lines or lines that start with '#' are considered comments&lt;br /&gt;
Commas (,) are used to seperate fields and may not occur as part&lt;br /&gt;
of any field and all of the keywords are case-sensitive, i.e. you&lt;br /&gt;
cannot say &amp;quot;key&amp;quot; instead of &amp;quot;Key&amp;quot; for example.&lt;br /&gt;
&lt;br /&gt;
For the rest the file is parsed and executed sequentially from top to bottom.&lt;br /&gt;
Each line can contain one entry. The following entries are recognized:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;Id=&amp;lt;id&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With &amp;lt;id&amp;gt; identifying the group of update entries that follows. Once a group&lt;br /&gt;
of entries have been applied, their &amp;lt;id&amp;gt; is stored and this group of entries&lt;br /&gt;
will not be applied again.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
File=&amp;lt;oldfile&amp;gt;,&amp;lt;newfile&amp;gt;&lt;br /&gt;
File=&amp;lt;oldfile&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that configuration information is read from &amp;lt;oldfile&amp;gt; and written&lt;br /&gt;
to &amp;lt;newfile&amp;gt;. If you only specify &amp;lt;oldfile&amp;gt;, the information is read from&lt;br /&gt;
and as written to &amp;lt;oldfile&amp;gt;. Note that if the file does not exist&lt;br /&gt;
at the time kconf_update first checks, no related update will be performed.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Script=&amp;lt;script&amp;gt;[,&amp;lt;interpreter&amp;gt;]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;script&amp;gt; is the program that will be performing the updates. All entries from &amp;lt;oldfile&amp;gt; are piped into &amp;lt;script&amp;gt;. The output of &amp;lt;script&amp;gt;is used as new entries for &amp;lt;newfile&amp;gt;. Existing entries can be deleted by adding lines with &amp;quot;# DELETE [group]key&amp;quot; in the output of the script. To delete a whole group use &amp;quot;# DELETEGROUP [group]&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
There are two types of kconf_update scripts:&lt;br /&gt;
*Non-Compiled&lt;br /&gt;
*Compiled&lt;br /&gt;
&lt;br /&gt;
If &amp;lt;script&amp;gt; is written in a non-compiled language (such as ruby or perl), then it should be installed into &lt;br /&gt;
{{Path|${KCONF_UPDATE_INSTALL_DIR} }}. &lt;br /&gt;
&lt;br /&gt;
If &amp;lt;script&amp;gt; is a compiled application, it should be installed in {{Path|${BIN_INSTALL_DIR}/kconf_update_bin}}&lt;br /&gt;
&lt;br /&gt;
If the script command is issued after a &amp;quot;Group&amp;quot; command the behavior is slightly&lt;br /&gt;
different:&lt;br /&gt;
&lt;br /&gt;
All entries from &amp;lt;oldfile&amp;gt; in &amp;lt;oldgroup&amp;gt; are piped into &amp;lt;script&amp;gt;. The output&lt;br /&gt;
of script is used as new entries for &amp;lt;newfile&amp;gt; in &amp;lt;newgroup&amp;gt;, unless a different&lt;br /&gt;
group is specified with &amp;quot;[group]&amp;quot;. Existing entries can be deleted from&lt;br /&gt;
&amp;lt;oldgroup&amp;gt; by adding lines with &amp;quot;# DELETE key&amp;quot; in the output of the script.·&lt;br /&gt;
To delete &amp;lt;oldgroup&amp;gt; use &amp;quot;# DELETEGROUP&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;interpreter&amp;gt; can be something like &amp;quot;perl&amp;quot; or &amp;quot;ruby&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
It is also possible to have a script command without specifying &amp;lt;oldfile&amp;gt; or &amp;lt;newfile&amp;gt;. In that case the script is run but it will not be fed any input and its output will simply be discarded.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ScriptArguments=&amp;lt;arguments&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If specified, the arguments will be passed to &amp;lt;script&amp;gt;.&lt;br /&gt;
IMPORTANT: It has to be specified before Script=.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Group=&amp;lt;oldgroup&amp;gt;,&amp;lt;newgroup&amp;gt;&lt;br /&gt;
Group=&amp;lt;oldgroup&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that configuration information is read from the group &amp;lt;oldgroup&amp;gt;&lt;br /&gt;
and written to &amp;lt;newgroup&amp;gt;. If you only specify &amp;lt;oldgroup&amp;gt;, the information&lt;br /&gt;
is read from as well as written to &amp;lt;oldgroup&amp;gt;. You can use &amp;lt;default&amp;gt; to&lt;br /&gt;
specify keys that are not under any group.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
RemoveGroup=&amp;lt;oldgroup&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that &amp;lt;oldgroup&amp;gt; is removed entirely. This can be used&lt;br /&gt;
to remove obsolete entries or to force a revert to default values.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Options=&amp;lt;option1&amp;gt;, &amp;lt;option2&amp;gt;,&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With this entry you can specify options that apply to the next &amp;quot;Script&amp;quot;,&lt;br /&gt;
&amp;quot;Key&amp;quot; or &amp;quot;AllKeys&amp;quot; entry (only to the first!). Possible options are:&lt;br /&gt;
&lt;br /&gt;
*&amp;quot;copy&amp;quot; Copy the configuration item instead of moving it. This means that&lt;br /&gt;
the configuration item will not be deleted from &amp;lt;oldfile&amp;gt;/&amp;lt;oldgroup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;quot;overwrite&amp;quot; Normally, a configuration item is not moved if an item with the&lt;br /&gt;
new name already exists. When this option is specified the old configuration item will overwrite any existing item.&lt;br /&gt;
&lt;br /&gt;
Key=&amp;lt;oldkey&amp;gt;,&amp;lt;newkey&amp;gt;&lt;br /&gt;
Key=&amp;lt;oldkey&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that configuration information is read from the key &amp;lt;oldkey&amp;gt;&lt;br /&gt;
and written to &amp;lt;newkey&amp;gt;. If you only specify &amp;lt;oldkey&amp;gt;, the information&lt;br /&gt;
is read from as well as written to &amp;lt;oldkey&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
AllKeys&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that all configuration information in the selected group should&lt;br /&gt;
be moved (All keys).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
AllGroups&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that all configuration information from all keys in ALL·&lt;br /&gt;
groups should be moved.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
RemoveKey=&amp;lt;oldkey&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that &amp;lt;oldkey&amp;gt; is removed from the selected group. This can be used&lt;br /&gt;
to remove obsolete entries or to force a revert to default values.&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials/Updating_KConfig_Files</id>
		<title>Development/Tutorials/Updating KConfig Files</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials/Updating_KConfig_Files"/>
				<updated>2007-12-31T18:15:16Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: Undo revision 19015 by Rememberme (Talk)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:I18n/Language Navigation Bar|Development/Tutorials/Updating_KConfig_Files}}&lt;br /&gt;
{{TutorialBrowser|&lt;br /&gt;
&lt;br /&gt;
series=KConfig|&lt;br /&gt;
&lt;br /&gt;
pre=[[../Using_KConfig_XT| Using KConfig XT]]|&lt;br /&gt;
&lt;br /&gt;
next=none&lt;br /&gt;
&lt;br /&gt;
name=Updating KConfig files|&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=KConfig Update=&lt;br /&gt;
&lt;br /&gt;
This page describes how a developer can use the KConfig update mechanism (kconf_update) available in kdelibs to update a user's already existing config file to accomodate changes made to the format of the default config file.&lt;br /&gt;
&lt;br /&gt;
==Why should you use it?==&lt;br /&gt;
&lt;br /&gt;
Over time applications sometimes need to rearrange the way configuration options are stored. Since such an update shouldn't influence the configuration options that the user has selected, the application must take care that the options stored in the old way will still be honored.&lt;br /&gt;
&lt;br /&gt;
What used to happen is that the application looks up both the old and the&lt;br /&gt;
new configuration option and then decides which one to use. This method has several drawbacks:&lt;br /&gt;
* The application may need to read more configuration files than strictly needed, resulting in a slower startup.&lt;br /&gt;
* The application becomes bigger with code that will only be used once.&lt;br /&gt;
&lt;br /&gt;
kconf_update addresses these problems by offering a framework to update configuration files without adding code to the application itself.&lt;br /&gt;
&lt;br /&gt;
==How it works==&lt;br /&gt;
&lt;br /&gt;
Applications can install so called &amp;quot;update files&amp;quot; under&lt;br /&gt;
{{Path|$KDEDIR/share/apps/kconf_update.}} An update file has {{Path|.upd}} as an extension and contains instructions for transferring/converting configuration information from one place to another.&lt;br /&gt;
&lt;br /&gt;
Updating the configuration happens automatically, either when KDE gets started&lt;br /&gt;
or when kded detects a new update file in the above mentioned location.&lt;br /&gt;
&lt;br /&gt;
Update files are separated into sections. Each section has an id. When a&lt;br /&gt;
section describing a configuration change has been applied, the id will be&lt;br /&gt;
stored in the file {{Path|kconf_updaterc}}. This information is used to make sure that a configuration update is only performed once.&lt;br /&gt;
&lt;br /&gt;
If you overwrite an existing update file with a new version that contains a&lt;br /&gt;
new section, only the update instructions from this extra section will be&lt;br /&gt;
performed.&lt;br /&gt;
&lt;br /&gt;
==File format of the update file==&lt;br /&gt;
&lt;br /&gt;
Empty lines or lines that start with '#' are considered comments&lt;br /&gt;
Commas (,) are used to seperate fields and may not occur as part&lt;br /&gt;
of any field and all of the keywords are case-sensitive, i.e. you&lt;br /&gt;
cannot say &amp;quot;key&amp;quot; instead of &amp;quot;Key&amp;quot; for example.&lt;br /&gt;
&lt;br /&gt;
For the rest the file is parsed and executed sequentially from top to bottom.&lt;br /&gt;
Each line can contain one entry. The following entries are recognized:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;Id=&amp;lt;id&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With &amp;lt;id&amp;gt; identifying the group of update entries that follows. Once a group&lt;br /&gt;
of entries have been applied, their &amp;lt;id&amp;gt; is stored and this group of entries&lt;br /&gt;
will not be applied again.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
File=&amp;lt;oldfile&amp;gt;,&amp;lt;newfile&amp;gt;&lt;br /&gt;
File=&amp;lt;oldfile&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that configuration information is read from &amp;lt;oldfile&amp;gt; and written&lt;br /&gt;
to &amp;lt;newfile&amp;gt;. If you only specify &amp;lt;oldfile&amp;gt;, the information is read from&lt;br /&gt;
and as written to &amp;lt;oldfile&amp;gt;. Note that if the file does not exist&lt;br /&gt;
at the time kconf_update first checks, no related update will be performed.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Script=&amp;lt;script&amp;gt;[,&amp;lt;interpreter&amp;gt;]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;script&amp;gt; is the program that will be performing the updates. All entries from &amp;lt;oldfile&amp;gt; are piped into &amp;lt;script&amp;gt;. The output of &amp;lt;script&amp;gt;is used as new entries for &amp;lt;newfile&amp;gt;. Existing entries can be deleted by adding lines with &amp;quot;# DELETE [group]key&amp;quot; in the output of the script. To delete a whole group use &amp;quot;# DELETEGROUP [group]&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
There are two types of kconf_update scripts:&lt;br /&gt;
*Non-Compiled&lt;br /&gt;
*Compiled&lt;br /&gt;
&lt;br /&gt;
If &amp;lt;script&amp;gt; is written in a non-compiled language (such as ruby or perl), then it should be installed into &lt;br /&gt;
{{Path|${KCONF_UPDATE_INSTALL_DIR} }}. &lt;br /&gt;
&lt;br /&gt;
If &amp;lt;script&amp;gt; is a compiled application, it should be installed in {{Path|${BIN_INSTALL_DIR}/kconf_update_bin}}&lt;br /&gt;
&lt;br /&gt;
If the script command is issued after a &amp;quot;Group&amp;quot; command the behavior is slightly&lt;br /&gt;
different:&lt;br /&gt;
&lt;br /&gt;
All entries from &amp;lt;oldfile&amp;gt; in &amp;lt;oldgroup&amp;gt; are piped into &amp;lt;script&amp;gt;. The output&lt;br /&gt;
of script is used as new entries for &amp;lt;newfile&amp;gt; in &amp;lt;newgroup&amp;gt;, unless a different&lt;br /&gt;
group is specified with &amp;quot;[group]&amp;quot;. Existing entries can be deleted from&lt;br /&gt;
&amp;lt;oldgroup&amp;gt; by adding lines with &amp;quot;# DELETE key&amp;quot; in the output of the script.·&lt;br /&gt;
To delete &amp;lt;oldgroup&amp;gt; use &amp;quot;# DELETEGROUP&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;interpreter&amp;gt; can be something like &amp;quot;perl&amp;quot; or &amp;quot;ruby&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
It is also possible to have a script command without specifying &amp;lt;oldfile&amp;gt; or &amp;lt;newfile&amp;gt;. In that case the script is run but it will not be fed any input and its output will simply be discarded.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ScriptArguments=&amp;lt;arguments&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If specified, the arguments will be passed to &amp;lt;script&amp;gt;.&lt;br /&gt;
IMPORTANT: It has to be specified before Script=.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Group=&amp;lt;oldgroup&amp;gt;,&amp;lt;newgroup&amp;gt;&lt;br /&gt;
Group=&amp;lt;oldgroup&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that configuration information is read from the group &amp;lt;oldgroup&amp;gt;&lt;br /&gt;
and written to &amp;lt;newgroup&amp;gt;. If you only specify &amp;lt;oldgroup&amp;gt;, the information&lt;br /&gt;
is read from as well as written to &amp;lt;oldgroup&amp;gt;. You can use &amp;lt;default&amp;gt; to&lt;br /&gt;
specify keys that are not under any group.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
RemoveGroup=&amp;lt;oldgroup&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that &amp;lt;oldgroup&amp;gt; is removed entirely. This can be used&lt;br /&gt;
to remove obsolete entries or to force a revert to default values.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Options=&amp;lt;option1&amp;gt;, &amp;lt;option2&amp;gt;,&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With this entry you can specify options that apply to the next &amp;quot;Script&amp;quot;,&lt;br /&gt;
&amp;quot;Key&amp;quot; or &amp;quot;AllKeys&amp;quot; entry (only to the first!). Possible options are:&lt;br /&gt;
&lt;br /&gt;
*&amp;quot;copy&amp;quot; Copy the configuration item instead of moving it. This means that&lt;br /&gt;
the configuration item will not be deleted from &amp;lt;oldfile&amp;gt;/&amp;lt;oldgroup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;quot;overwrite&amp;quot; Normally, a configuration item is not moved if an item with the&lt;br /&gt;
new name already exists. When this option is specified the old configuration item will overwrite any existing item.&lt;br /&gt;
&lt;br /&gt;
Key=&amp;lt;oldkey&amp;gt;,&amp;lt;newkey&amp;gt;&lt;br /&gt;
Key=&amp;lt;oldkey&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that configuration information is read from the key &amp;lt;oldkey&amp;gt;&lt;br /&gt;
and written to &amp;lt;newkey&amp;gt;. If you only specify &amp;lt;oldkey&amp;gt;, the information&lt;br /&gt;
is read from as well as written to &amp;lt;oldkey&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
AllKeys&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that all configuration information in the selected group should&lt;br /&gt;
be moved (All keys).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
AllGroups&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that all configuration information from all keys in ALL·&lt;br /&gt;
groups should be moved.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
RemoveKey=&amp;lt;oldkey&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that &amp;lt;oldkey&amp;gt; is removed from the selected group. This can be used&lt;br /&gt;
to remove obsolete entries or to force a revert to default values.&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials/Using_KConfig_XT</id>
		<title>Development/Tutorials/Using KConfig XT</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials/Using_KConfig_XT"/>
				<updated>2007-12-31T18:13:54Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: Undo revision 19012 by Rememberme (Talk)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:I18n/Language Navigation Bar|Development/Tutorials/Using_KConfig_XT}}&lt;br /&gt;
{{TutorialBrowser|&lt;br /&gt;
&lt;br /&gt;
series=KConfig|&lt;br /&gt;
&lt;br /&gt;
pre=[[../KConfig|Introduction to KConfig]]|&lt;br /&gt;
&lt;br /&gt;
name=Using KConfig XT|&lt;br /&gt;
&lt;br /&gt;
reading=[http://api.kde.org/4.0-api/kdelibs-apidocs/kdecore/html/kconfig_compiler.html The KDE Configuration Compiler (KDE 4)]&amp;lt;br&amp;gt;[http://api.kde.org/3.5-api/kdelibs-apidocs/kdecore/html/kconfig_compiler.html The KDE Configuration Compiler (KDE 3)]&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Using KConfig XT ==&lt;br /&gt;
''Original Author'': Zack Rusin &amp;lt;[mailto:zack@kde.org zack@kde.org]&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This tutorial introduces the main concepts of the KconfigXT &lt;br /&gt;
configuration framework and shows how to efficiently use it in applications. It assumes that the reader has already developed a KDE application and is familiar with KConfig. A basic understanding of XML and concepts behind DTDs is also required.&lt;br /&gt;
  &lt;br /&gt;
The main idea behind KConfig XT is to make the life of application developers &lt;br /&gt;
easier while making the administration of large KDE installations more manageable.&lt;br /&gt;
The four basic parts of the new framework are: &lt;br /&gt;
&lt;br /&gt;
* KConfigSkeleton - a class in the libkdecore library which grants a more flexible access to the configuration options,&lt;br /&gt;
* XML file containing information about configuration options (the {{path|.kcfg}} file)&lt;br /&gt;
* An ini like file which provides the code generation options (the {{path|.kcfgc}} file)&lt;br /&gt;
* kconfig_compiler - which generates C++ source code from {{path|.kcfg}} and {{path|.kcfgc}} files. The generated class is based on KConfigSkeleton and provides an API for the application to access its configuration data.&lt;br /&gt;
&lt;br /&gt;
{{note|In this tutorial more advanced and optional features of KConfig XT and their descriptions are marked by ''italic text''. If you decide to skip them during the first reading, be sure to come back to them at some point. }}&lt;br /&gt;
&lt;br /&gt;
== .kcfg DTD Structure ==&lt;br /&gt;
&lt;br /&gt;
The structure of the {{path|.kcfg}} file is described by its DTD (kcfg.xsd - available from&lt;br /&gt;
[http://www.kde.org/standards/kcfg/1.0/kcfg.xsd here] (please note that browsers do not display DTDs in a visual form,&lt;br /&gt;
download the DTD directly and view it like a text file) or the kdecore &lt;br /&gt;
library). Please go through it before you go any further.  &lt;br /&gt;
&lt;br /&gt;
Lets create a simple .kcfg file. Please reference the code below as we go through each step.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE kcfg SYSTEM &lt;br /&gt;
    &amp;quot;http://www.kde.org/standards/kcfg/1.0/kcfg.xsd&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;kcfg&amp;gt;&lt;br /&gt;
  &amp;lt;kcfgfile name=&amp;quot;kjotsrc&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;include&amp;gt;kglobalsettings.h&amp;lt;/include&amp;gt;&lt;br /&gt;
  &amp;lt;group name=&amp;quot;kjots&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;entry name=&amp;quot;SplitterSizes&amp;quot; type=&amp;quot;IntList&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;label&amp;gt;How the main window is divided.&amp;lt;/label&amp;gt;&lt;br /&gt;
    &amp;lt;/entry&amp;gt;&lt;br /&gt;
    &amp;lt;entry name=&amp;quot;Width&amp;quot; type=&amp;quot;Int&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;label&amp;gt;Width of the main window.&amp;lt;/label&amp;gt;&lt;br /&gt;
      &amp;lt;default&amp;gt;600&amp;lt;/default&amp;gt;&lt;br /&gt;
    &amp;lt;/entry&amp;gt;&lt;br /&gt;
    &amp;lt;entry name=&amp;quot;Height&amp;quot; type=&amp;quot;Int&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;label&amp;gt;Height of the main window.&amp;lt;/label&amp;gt;&lt;br /&gt;
      &amp;lt;default&amp;gt;400&amp;lt;/default&amp;gt;&lt;br /&gt;
    &amp;lt;/entry&amp;gt;&lt;br /&gt;
    &amp;lt;entry name=&amp;quot;OpenBooks&amp;quot; type=&amp;quot;StringList&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;label&amp;gt;All books that are opened.&amp;lt;/label&amp;gt;&lt;br /&gt;
    &amp;lt;/entry&amp;gt;&lt;br /&gt;
    &amp;lt;entry name=&amp;quot;CurrentBook&amp;quot; type=&amp;quot;String&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;label&amp;gt;The book currently opened.&amp;lt;/label&amp;gt;&lt;br /&gt;
    &amp;lt;/entry&amp;gt;&lt;br /&gt;
    &amp;lt;entry name=&amp;quot;Font&amp;quot; type=&amp;quot;Font&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;label&amp;gt;The font used to display the contents of books.&amp;lt;/label&amp;gt;&lt;br /&gt;
      &amp;lt;default code=&amp;quot;true&amp;quot;&amp;gt;KGlobalSettings::generalFont()&amp;lt;/default&amp;gt;&lt;br /&gt;
    &amp;lt;/entry&amp;gt;&lt;br /&gt;
  &amp;lt;/group&amp;gt;&lt;br /&gt;
&amp;lt;/kcfg&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Use your favorite code editor to open a your_application_name{{path|.kcfg}} file (of course replacing your_application_name with the name of the application you want to convert to KConfig XT).&lt;br /&gt;
* Start that file by opening the &amp;amp;lt;kcfgfile&amp;amp;gt; tag which controls which KConfig file the data will be stored in. There are three possibilities:&lt;br /&gt;
*# If the &amp;amp;lt;kcfgfile&amp;amp;gt; tag has no attributes the generated code will use the application's default KConfig file (normally {{path|$HOME/.kde/config/&amp;lt;appname&amp;gt;rc}}).&lt;br /&gt;
*# ''The &amp;quot;name&amp;quot; attribute is used to manually specify a file name. If the value assigned to &amp;quot;name&amp;quot; is not an absolute file path, the file will be created in the default KDE config directory (normally {{path|$HOME/.kde/config}}).''&lt;br /&gt;
*# ''If you would like to be able to specify the config file at construction time, use &amp;amp;lt;kcfgfile arg=&amp;quot;true&amp;quot;&amp;amp;gt;. This causes the constructor of the generated class to take a KSharedConfig::Ptr as an argument, allowing you to construct multiple instances pointing to different files.''&lt;br /&gt;
* ''Add the optional &amp;amp;lt;include&amp;amp;gt; tags which may contain C++ header files that are needed to compile the code required to compute the default values.''&lt;br /&gt;
* The remaining entries in the XML file are grouped by the tag &amp;amp;lt;group&amp;amp;gt; which describes the corresponding groups in the configuration file.&lt;br /&gt;
*#The individual entries must have at least a name or a key. The key is used as the key in the config file. The name is used to create accessor and modifier functions. If &amp;amp;lt;key&amp;amp;gt; is not given, the name is used as the config file key. If &amp;amp;lt;key&amp;amp;gt; is given, but not &amp;amp;lt;name&amp;amp;gt;, the name is constructed by removing all spaces from the &amp;amp;lt;key&amp;amp;gt; contents.&lt;br /&gt;
*# Always add a label or a whatsthis tags to your application in which you describe the configuration options. The label tag is used for short descriptions of the entry, while whatsthis contains more verbose documentation. ''It's important for tools like KConfigEditor which can be used by systems administrators to setup machines over on the network.''&lt;br /&gt;
*# An entry must also have a type. The allowed types are: String, StringList, Font, Rect, Size, Color, Point, Int, UInt, Bool, Double, DateTime, Int64, UInt64 and Password. '' Besides those basic type the following special types are supported and include:''&lt;br /&gt;
*#* Path - This is a string that is specially treated as a file-path. In particular paths in the home directory are prefixed with $HOME when being stored in the configuration file.&lt;br /&gt;
*#* Enum - This indicates an enumeration. The possible enum values should be provided via the &amp;amp;lt;choices&amp;amp;gt; tag. Enum values are accessed as integers by the application but stored as string in the configuration file. This makes it possible to add more values at a later date without breaking compatibility.&lt;br /&gt;
*#* IntList - This indicates a list of integers. This information is provided to the application as QValueList&amp;amp;lt;int&amp;amp;gt;. Useful for storing QSplitter geometries.&lt;br /&gt;
*#* PathList - List of Path elements.&lt;br /&gt;
*# The min and max tags can be set to limit the value of the integer-type options.&lt;br /&gt;
*#''An entry can optionally have a default value which is used as default when the value isn't specified in any config file. Default values are interpreted as literal constant values. If a default value needs to be computed or if it needs to be obtained from a function call, the &amp;amp;lt;default&amp;amp;gt; tag should contain the code=&amp;quot;true&amp;quot; attribute. The contents of the &amp;amp;lt;default&amp;amp;gt; tag is then considered to be a C++ expression. ''&lt;br /&gt;
*#''Additional code for computing default values can be provided via the &amp;amp;lt;code&amp;amp;gt; tag. The contents of the &amp;amp;lt;code&amp;amp;gt; tag is inserted as-is. A typical use for this is to compute a common default value which can then be referenced by multiple entries that follow.''&lt;br /&gt;
*#''Optionally, the hidden option can also be added to the &amp;amp;lt;entry&amp;amp;gt;. The possible values are true and false.''&lt;br /&gt;
&lt;br /&gt;
== .kcfgc files ==&lt;br /&gt;
&lt;br /&gt;
After creating a {{path|.kcfg}} file create a {{path|.kcfgc}} file which describes the C++ file &lt;br /&gt;
generation options. The .kcfgc file is a simple ini file with the typical &lt;br /&gt;
&amp;quot;entry=value&amp;quot; format. To create a simple .kcfgc file follow these steps:&lt;br /&gt;
&lt;br /&gt;
# Open a new file in your favorite text editor.&lt;br /&gt;
# Start it with the &amp;quot;File=your_application_name.kcfg&amp;quot; entry which specifies where the configuration options for your application are stored.&lt;br /&gt;
# Add the &amp;quot;ClassName=YourConfigClassName&amp;quot; entry which specifies the name of the class that will be generated from the .kcfg file. Remember that the generated class will be derived from KConfigSkeleton. PLease make sure that YourConfigClassName is not a class name already used in your application. Save this file under {{path|yourconfigclassname.kcfgc.}} This will ensure the generation of the yourconfigclassname.{h,cpp} files where your configuration class will reside. &lt;br /&gt;
# Add any additional entries, which your application might need. Those additional entries include:&lt;br /&gt;
#* NameSpace - specifies the namespace in which the generated config class should reside,&lt;br /&gt;
#* Inherits - if you need the generated class to inherit your custom class,&lt;br /&gt;
#* Singleton - if the configuration class should be a singleton,&lt;br /&gt;
#* MemberVariables - specifies the access to the member variables, default is private,&lt;br /&gt;
#* ItemAccessors - relates to the above item, if member variables are public then it might make little sense to generate accessors. By default they are generated,&lt;br /&gt;
#* Mutators - similar to the above one, but applies to the mutator methods,&lt;br /&gt;
#* GlobalEnums - specifies whether enums should be class wide of whether they should be always explicitly prefixed with their type name,&lt;br /&gt;
#* UseEnumTypes - specifies whether enum values should be passed as type int or as their enum type in the return value of accessor functions and the arguments of mutator and signal functions.&lt;br /&gt;
&lt;br /&gt;
== Adjusting the CMakeLists.txt file ==&lt;br /&gt;
&lt;br /&gt;
After creating the .kcfg and .kcfgc files the next step is to adjust the &lt;br /&gt;
build to let kconfig_compiler generate the required class at compile time. Fortunately doing this is trivial and requires only one step, adding this line to the CMakeLists.txt file example:&lt;br /&gt;
&lt;br /&gt;
 kde4_add_kcfg_files(&amp;lt;project name&amp;gt;_SRCS settings.kcfgc)&lt;br /&gt;
&lt;br /&gt;
Alternatively, if a .moc file needs to be generated before compiling the generated source code, use&lt;br /&gt;
&lt;br /&gt;
 kde4_add_kcfg_files(&amp;lt;project name&amp;gt;_SRCS GENERATE_MOC settings.kcfgc)&lt;br /&gt;
&lt;br /&gt;
This assures that the configuration class is properly generated and that the .kcfg is installed so it can be used by tools like &lt;br /&gt;
the KConfigEditor.&lt;br /&gt;
&lt;br /&gt;
== Use and Dialogs ==&lt;br /&gt;
&lt;br /&gt;
After making all of the above changes you're ready to use KConfig XT. The &lt;br /&gt;
kconfig_compiler generated header file will have the name equal to the name of the .kcfg file but with a &amp;quot;.h&amp;quot; extension. Simply include that file wherever you want to access your configuration options.&lt;br /&gt;
&lt;br /&gt;
The use will depend on whether you have added the &amp;lt;tt&amp;gt;Singleton=true&amp;lt;/tt&amp;gt; entry to your .kcfgc file. &lt;br /&gt;
&lt;br /&gt;
One the nicest features of the KConfig XT is its seamless integration with the Qt &lt;br /&gt;
Designer generated dialogs. You can do that by using {{class|KConfigDialog}}. The &lt;br /&gt;
steps to do that are as follows: &lt;br /&gt;
&lt;br /&gt;
# Create the KConfigDialog and pass the instance of your configuration data as one of the arguments. The construct would look like the following example:&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;code cppqt&amp;gt;&lt;br /&gt;
KConfigDialog* dialog = new KConfigDialog( &lt;br /&gt;
         this, &amp;quot;settings&amp;quot;, YourAppSettings::self() );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
assuming that YourAppSettings is the value of the ClassName variable from the kcfgc file and the settings class is a singelton.&lt;br /&gt;
# In Qt Designer create widgets which should be used to configure your options. In order to make those widgets interact with the kcfg you have name each one of them using the following scheme:&lt;br /&gt;
## Prefix the Name of the widget which should control one of the options with &amp;quot;kcfg_&amp;quot;&lt;br /&gt;
## Append the &amp;quot;name&amp;quot; attribute value from your kcfg file which corresponds to option the given widget should control.&lt;br /&gt;
# Add the Qt Designer generated widget to the KConfigDialog.&lt;br /&gt;
# Show the dialog when you're done.&lt;br /&gt;
&lt;br /&gt;
== Example ==&lt;br /&gt;
&lt;br /&gt;
Here's an example usage of KConfig XT for the application named Example.&lt;br /&gt;
With the following example.kcfg file: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE kcfg SYSTEM &lt;br /&gt;
    &amp;quot;http://www.kde.org/standards/kcfg/1.0/kcfg.dtd&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;kcfg&amp;gt; &amp;lt;kcfgfile name=&amp;quot;examplerc&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;group name=&amp;quot;network&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;entry name=&amp;quot;ServerName&amp;quot; type=&amp;quot;String&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;label&amp;gt;Defines the sample server.&amp;lt;/label&amp;gt;&lt;br /&gt;
    &amp;lt;/entry&amp;gt;&lt;br /&gt;
    &amp;lt;entry name=&amp;quot;Port&amp;quot; type=&amp;quot;Int&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;label&amp;gt;Defines the server port&amp;lt;/label&amp;gt;&lt;br /&gt;
      &amp;lt;default&amp;gt;21&amp;lt;/default&amp;gt;&lt;br /&gt;
      &amp;lt;min&amp;gt;20&amp;lt;/min&amp;gt;&lt;br /&gt;
      &amp;lt;max&amp;gt;990&amp;lt;/max&amp;gt;&lt;br /&gt;
    &amp;lt;/entry&amp;gt;&lt;br /&gt;
  &amp;lt;/group&amp;gt;&lt;br /&gt;
&amp;lt;/kcfg&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And here's how to actually use the generated class. for the given kcfgc file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code ini&amp;gt;&lt;br /&gt;
File=example.kcfg &lt;br /&gt;
ClassName=ExampleSettings &lt;br /&gt;
Singleton=true &lt;br /&gt;
Mutators=true&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The header files wouldn't change, but the cpp files must now contain the &lt;br /&gt;
following code to access and store the configuration data :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
#include &amp;lt;ExampleSettings.h&amp;gt; &lt;br /&gt;
... &lt;br /&gt;
void ExampleClass::readConfig() { &lt;br /&gt;
        m_server  = ExampleSettings::serverName(); &lt;br /&gt;
        m_port    = ExampleSettings::port(); &lt;br /&gt;
} &lt;br /&gt;
void ExampleClass:saveSettings() { &lt;br /&gt;
        ExampleSettings::setServerName( m_server ); &lt;br /&gt;
        ExampleSettings::setPort( m_port ); &lt;br /&gt;
        ExampleSettings::writeConfig(); &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To add a dialog you need to create a Qt Designer widget with the widget names&lt;br /&gt;
corresponding to the names of the options they should edit and prefixed with &amp;quot;kcfg_&amp;quot;. &lt;br /&gt;
It could be something along the lines of:&lt;br /&gt;
&lt;br /&gt;
[[Image:kconfigxt.png|center|256px]]&lt;br /&gt;
&lt;br /&gt;
And you can use the dialog with the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt&amp;gt;&lt;br /&gt;
//An instance of your dialog could be already created and could be&lt;br /&gt;
// cached, in which case you want to display the cached dialog &lt;br /&gt;
// instead of creating another one&lt;br /&gt;
if ( KConfigDialog::showDialog( &amp;quot;settings&amp;quot; ) )&lt;br /&gt;
  return; &lt;br /&gt;
 &lt;br /&gt;
// KConfigDialog didn't find an instance of this dialog, so lets&lt;br /&gt;
// create it : &lt;br /&gt;
KConfigDialog* dialog = new KConfigDialog(this, &amp;quot;settings&amp;quot;,&lt;br /&gt;
                                          ExampleSettings::self()); &lt;br /&gt;
ExampleDesignerWidget* confWdg =  &lt;br /&gt;
                  new ExampleDesignerWidget( 0, &amp;quot;Example&amp;quot; ); &lt;br /&gt;
 &lt;br /&gt;
dialog-&amp;gt;addPage( confWdg, i18n(&amp;quot;Example&amp;quot;), &amp;quot;example&amp;quot; ); &lt;br /&gt;
 &lt;br /&gt;
//User edited the configuration - update your local copies of the &lt;br /&gt;
//configuration data &lt;br /&gt;
connect( dialog, SIGNAL(settingsChanged()), &lt;br /&gt;
         this, SLOT(updateConfiguration()) ); &lt;br /&gt;
 &lt;br /&gt;
dialog-&amp;gt;show();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And that's all it takes. You can have a look at [http://websvn.kde.org/trunk/KDE/kdegames/kreversi KReversi] and [http://websvn.kde.org/trunk/KDE/kdegames/ktron/ KTron] code in the [http://websvn.kde.org/trunk/KDE/kdegames kdegames module] to see a live example of KConfig XT!&lt;br /&gt;
&lt;br /&gt;
== Common Pitfalls and Tips ==&lt;br /&gt;
&lt;br /&gt;
* Do not forget to add the &amp;quot;type&amp;quot; attribute to the &amp;quot;entry&amp;quot; tag in your .kcfg file.&lt;br /&gt;
* Always try to add both the &amp;amp;lt;label&amp;amp;gt; and &amp;amp;lt;whatsthis&amp;amp;gt; tags to each entry.&lt;br /&gt;
* Putting the MemberVariables=public in your .kcfgc is usually a bad idea - you'll avoid accidental changes to those members by using the aggregation and forcing the use of the mutators.&lt;br /&gt;
* If your application doesn't have one central object (created before and destructed after; all others) then always put the Singleton=true entry in your .kcfgs file.&lt;br /&gt;
[[Category:C++]]&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials/Updating_KConfig_Files</id>
		<title>Development/Tutorials/Updating KConfig Files</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials/Updating_KConfig_Files"/>
				<updated>2007-12-31T18:12:22Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:I18n/Language Navigation Bar|Development/Tutorials/Updating_KConfig_Files}}&lt;br /&gt;
{{TutorialBrowser|&lt;br /&gt;
&lt;br /&gt;
series=KConfig|&lt;br /&gt;
&lt;br /&gt;
pre=[[../Using_KConfig_XT| Using KConfig XT]]|&lt;br /&gt;
&lt;br /&gt;
next=none|&lt;br /&gt;
&lt;br /&gt;
name=Updating KConfig files|&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=KConfig Update=&lt;br /&gt;
&lt;br /&gt;
This page describes how a developer can use the KConfig update mechanism (kconf_update) available in kdelibs to update a user's already existing config file to accomodate changes made to the format of the default config file.&lt;br /&gt;
&lt;br /&gt;
==Why should you use it?==&lt;br /&gt;
&lt;br /&gt;
Over time applications sometimes need to rearrange the way configuration options are stored. Since such an update shouldn't influence the configuration options that the user has selected, the application must take care that the options stored in the old way will still be honored.&lt;br /&gt;
&lt;br /&gt;
What used to happen is that the application looks up both the old and the&lt;br /&gt;
new configuration option and then decides which one to use. This method has several drawbacks:&lt;br /&gt;
* The application may need to read more configuration files than strictly needed, resulting in a slower startup.&lt;br /&gt;
* The application becomes bigger with code that will only be used once.&lt;br /&gt;
&lt;br /&gt;
kconf_update addresses these problems by offering a framework to update configuration files without adding code to the application itself.&lt;br /&gt;
&lt;br /&gt;
==How it works==&lt;br /&gt;
&lt;br /&gt;
Applications can install so called &amp;quot;update files&amp;quot; under&lt;br /&gt;
{{Path|$KDEDIR/share/apps/kconf_update.}} An update file has {{Path|.upd}} as an extension and contains instructions for transferring/converting configuration information from one place to another.&lt;br /&gt;
&lt;br /&gt;
Updating the configuration happens automatically, either when KDE gets started&lt;br /&gt;
or when kded detects a new update file in the above mentioned location.&lt;br /&gt;
&lt;br /&gt;
Update files are separated into sections. Each section has an id. When a&lt;br /&gt;
section describing a configuration change has been applied, the id will be&lt;br /&gt;
stored in the file {{Path|kconf_updaterc}}. This information is used to make sure that a configuration update is only performed once.&lt;br /&gt;
&lt;br /&gt;
If you overwrite an existing update file with a new version that contains a&lt;br /&gt;
new section, only the update instructions from this extra section will be&lt;br /&gt;
performed.&lt;br /&gt;
&lt;br /&gt;
==File format of the update file==&lt;br /&gt;
&lt;br /&gt;
Empty lines or lines that start with '#' are considered comments&lt;br /&gt;
Commas (,) are used to seperate fields and may not occur as part&lt;br /&gt;
of any field and all of the keywords are case-sensitive, i.e. you&lt;br /&gt;
cannot say &amp;quot;key&amp;quot; instead of &amp;quot;Key&amp;quot; for example.&lt;br /&gt;
&lt;br /&gt;
For the rest the file is parsed and executed sequentially from top to bottom.&lt;br /&gt;
Each line can contain one entry. The following entries are recognized:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;Id=&amp;lt;id&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With &amp;lt;id&amp;gt; identifying the group of update entries that follows. Once a group&lt;br /&gt;
of entries have been applied, their &amp;lt;id&amp;gt; is stored and this group of entries&lt;br /&gt;
will not be applied again.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
File=&amp;lt;oldfile&amp;gt;,&amp;lt;newfile&amp;gt;&lt;br /&gt;
File=&amp;lt;oldfile&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that configuration information is read from &amp;lt;oldfile&amp;gt; and written&lt;br /&gt;
to &amp;lt;newfile&amp;gt;. If you only specify &amp;lt;oldfile&amp;gt;, the information is read from&lt;br /&gt;
and as written to &amp;lt;oldfile&amp;gt;. Note that if the file does not exist&lt;br /&gt;
at the time kconf_update first checks, no related update will be performed.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Script=&amp;lt;script&amp;gt;[,&amp;lt;interpreter&amp;gt;]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;script&amp;gt; is the program that will be performing the updates. All entries from &amp;lt;oldfile&amp;gt; are piped into &amp;lt;script&amp;gt;. The output of &amp;lt;script&amp;gt;is used as new entries for &amp;lt;newfile&amp;gt;. Existing entries can be deleted by adding lines with &amp;quot;# DELETE [group]key&amp;quot; in the output of the script. To delete a whole group use &amp;quot;# DELETEGROUP [group]&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
There are two types of kconf_update scripts:&lt;br /&gt;
*Non-Compiled&lt;br /&gt;
*Compiled&lt;br /&gt;
&lt;br /&gt;
If &amp;lt;script&amp;gt; is written in a non-compiled language (such as ruby or perl), then it should be installed into &lt;br /&gt;
{{Path|${KCONF_UPDATE_INSTALL_DIR} }}. &lt;br /&gt;
&lt;br /&gt;
If &amp;lt;script&amp;gt; is a compiled application, it should be installed in {{Path|${BIN_INSTALL_DIR}/kconf_update_bin}}&lt;br /&gt;
&lt;br /&gt;
If the script command is issued after a &amp;quot;Group&amp;quot; command the behavior is slightly&lt;br /&gt;
different:&lt;br /&gt;
&lt;br /&gt;
All entries from &amp;lt;oldfile&amp;gt; in &amp;lt;oldgroup&amp;gt; are piped into &amp;lt;script&amp;gt;. The output&lt;br /&gt;
of script is used as new entries for &amp;lt;newfile&amp;gt; in &amp;lt;newgroup&amp;gt;, unless a different&lt;br /&gt;
group is specified with &amp;quot;[group]&amp;quot;. Existing entries can be deleted from&lt;br /&gt;
&amp;lt;oldgroup&amp;gt; by adding lines with &amp;quot;# DELETE key&amp;quot; in the output of the script.·&lt;br /&gt;
To delete &amp;lt;oldgroup&amp;gt; use &amp;quot;# DELETEGROUP&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;interpreter&amp;gt; can be something like &amp;quot;perl&amp;quot; or &amp;quot;ruby&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
It is also possible to have a script command without specifying &amp;lt;oldfile&amp;gt; or &amp;lt;newfile&amp;gt;. In that case the script is run but it will not be fed any input and its output will simply be discarded.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ScriptArguments=&amp;lt;arguments&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If specified, the arguments will be passed to &amp;lt;script&amp;gt;.&lt;br /&gt;
IMPORTANT: It has to be specified before Script=.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Group=&amp;lt;oldgroup&amp;gt;,&amp;lt;newgroup&amp;gt;&lt;br /&gt;
Group=&amp;lt;oldgroup&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that configuration information is read from the group &amp;lt;oldgroup&amp;gt;&lt;br /&gt;
and written to &amp;lt;newgroup&amp;gt;. If you only specify &amp;lt;oldgroup&amp;gt;, the information&lt;br /&gt;
is read from as well as written to &amp;lt;oldgroup&amp;gt;. You can use &amp;lt;default&amp;gt; to&lt;br /&gt;
specify keys that are not under any group.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
RemoveGroup=&amp;lt;oldgroup&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that &amp;lt;oldgroup&amp;gt; is removed entirely. This can be used&lt;br /&gt;
to remove obsolete entries or to force a revert to default values.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Options=&amp;lt;option1&amp;gt;, &amp;lt;option2&amp;gt;,&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With this entry you can specify options that apply to the next &amp;quot;Script&amp;quot;,&lt;br /&gt;
&amp;quot;Key&amp;quot; or &amp;quot;AllKeys&amp;quot; entry (only to the first!). Possible options are:&lt;br /&gt;
&lt;br /&gt;
*&amp;quot;copy&amp;quot; Copy the configuration item instead of moving it. This means that&lt;br /&gt;
the configuration item will not be deleted from &amp;lt;oldfile&amp;gt;/&amp;lt;oldgroup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;quot;overwrite&amp;quot; Normally, a configuration item is not moved if an item with the&lt;br /&gt;
new name already exists. When this option is specified the old configuration item will overwrite any existing item.&lt;br /&gt;
&lt;br /&gt;
Key=&amp;lt;oldkey&amp;gt;,&amp;lt;newkey&amp;gt;&lt;br /&gt;
Key=&amp;lt;oldkey&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that configuration information is read from the key &amp;lt;oldkey&amp;gt;&lt;br /&gt;
and written to &amp;lt;newkey&amp;gt;. If you only specify &amp;lt;oldkey&amp;gt;, the information&lt;br /&gt;
is read from as well as written to &amp;lt;oldkey&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
AllKeys&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that all configuration information in the selected group should&lt;br /&gt;
be moved (All keys).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
AllGroups&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that all configuration information from all keys in ALL·&lt;br /&gt;
groups should be moved.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
RemoveKey=&amp;lt;oldkey&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that &amp;lt;oldkey&amp;gt; is removed from the selected group. This can be used&lt;br /&gt;
to remove obsolete entries or to force a revert to default values.&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials/Updating_KConfig_Files</id>
		<title>Development/Tutorials/Updating KConfig Files</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials/Updating_KConfig_Files"/>
				<updated>2007-12-31T18:12:05Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:I18n/Language Navigation Bar|Development/Tutorials/Updating_KConfig_Files}}&lt;br /&gt;
{{TutorialBrowser|&lt;br /&gt;
&lt;br /&gt;
series=KConfig|&lt;br /&gt;
&lt;br /&gt;
pre=[[../Using_KConfig_XT| Using KConfig XT]]|&lt;br /&gt;
&lt;br /&gt;
next=none&lt;br /&gt;
&lt;br /&gt;
name=Updating KConfig files|&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=KConfig Update=&lt;br /&gt;
&lt;br /&gt;
This page describes how a developer can use the KConfig update mechanism (kconf_update) available in kdelibs to update a user's already existing config file to accomodate changes made to the format of the default config file.&lt;br /&gt;
&lt;br /&gt;
==Why should you use it?==&lt;br /&gt;
&lt;br /&gt;
Over time applications sometimes need to rearrange the way configuration options are stored. Since such an update shouldn't influence the configuration options that the user has selected, the application must take care that the options stored in the old way will still be honored.&lt;br /&gt;
&lt;br /&gt;
What used to happen is that the application looks up both the old and the&lt;br /&gt;
new configuration option and then decides which one to use. This method has several drawbacks:&lt;br /&gt;
* The application may need to read more configuration files than strictly needed, resulting in a slower startup.&lt;br /&gt;
* The application becomes bigger with code that will only be used once.&lt;br /&gt;
&lt;br /&gt;
kconf_update addresses these problems by offering a framework to update configuration files without adding code to the application itself.&lt;br /&gt;
&lt;br /&gt;
==How it works==&lt;br /&gt;
&lt;br /&gt;
Applications can install so called &amp;quot;update files&amp;quot; under&lt;br /&gt;
{{Path|$KDEDIR/share/apps/kconf_update.}} An update file has {{Path|.upd}} as an extension and contains instructions for transferring/converting configuration information from one place to another.&lt;br /&gt;
&lt;br /&gt;
Updating the configuration happens automatically, either when KDE gets started&lt;br /&gt;
or when kded detects a new update file in the above mentioned location.&lt;br /&gt;
&lt;br /&gt;
Update files are separated into sections. Each section has an id. When a&lt;br /&gt;
section describing a configuration change has been applied, the id will be&lt;br /&gt;
stored in the file {{Path|kconf_updaterc}}. This information is used to make sure that a configuration update is only performed once.&lt;br /&gt;
&lt;br /&gt;
If you overwrite an existing update file with a new version that contains a&lt;br /&gt;
new section, only the update instructions from this extra section will be&lt;br /&gt;
performed.&lt;br /&gt;
&lt;br /&gt;
==File format of the update file==&lt;br /&gt;
&lt;br /&gt;
Empty lines or lines that start with '#' are considered comments&lt;br /&gt;
Commas (,) are used to seperate fields and may not occur as part&lt;br /&gt;
of any field and all of the keywords are case-sensitive, i.e. you&lt;br /&gt;
cannot say &amp;quot;key&amp;quot; instead of &amp;quot;Key&amp;quot; for example.&lt;br /&gt;
&lt;br /&gt;
For the rest the file is parsed and executed sequentially from top to bottom.&lt;br /&gt;
Each line can contain one entry. The following entries are recognized:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;Id=&amp;lt;id&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With &amp;lt;id&amp;gt; identifying the group of update entries that follows. Once a group&lt;br /&gt;
of entries have been applied, their &amp;lt;id&amp;gt; is stored and this group of entries&lt;br /&gt;
will not be applied again.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
File=&amp;lt;oldfile&amp;gt;,&amp;lt;newfile&amp;gt;&lt;br /&gt;
File=&amp;lt;oldfile&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that configuration information is read from &amp;lt;oldfile&amp;gt; and written&lt;br /&gt;
to &amp;lt;newfile&amp;gt;. If you only specify &amp;lt;oldfile&amp;gt;, the information is read from&lt;br /&gt;
and as written to &amp;lt;oldfile&amp;gt;. Note that if the file does not exist&lt;br /&gt;
at the time kconf_update first checks, no related update will be performed.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Script=&amp;lt;script&amp;gt;[,&amp;lt;interpreter&amp;gt;]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;script&amp;gt; is the program that will be performing the updates. All entries from &amp;lt;oldfile&amp;gt; are piped into &amp;lt;script&amp;gt;. The output of &amp;lt;script&amp;gt;is used as new entries for &amp;lt;newfile&amp;gt;. Existing entries can be deleted by adding lines with &amp;quot;# DELETE [group]key&amp;quot; in the output of the script. To delete a whole group use &amp;quot;# DELETEGROUP [group]&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
There are two types of kconf_update scripts:&lt;br /&gt;
*Non-Compiled&lt;br /&gt;
*Compiled&lt;br /&gt;
&lt;br /&gt;
If &amp;lt;script&amp;gt; is written in a non-compiled language (such as ruby or perl), then it should be installed into &lt;br /&gt;
{{Path|${KCONF_UPDATE_INSTALL_DIR} }}. &lt;br /&gt;
&lt;br /&gt;
If &amp;lt;script&amp;gt; is a compiled application, it should be installed in {{Path|${BIN_INSTALL_DIR}/kconf_update_bin}}&lt;br /&gt;
&lt;br /&gt;
If the script command is issued after a &amp;quot;Group&amp;quot; command the behavior is slightly&lt;br /&gt;
different:&lt;br /&gt;
&lt;br /&gt;
All entries from &amp;lt;oldfile&amp;gt; in &amp;lt;oldgroup&amp;gt; are piped into &amp;lt;script&amp;gt;. The output&lt;br /&gt;
of script is used as new entries for &amp;lt;newfile&amp;gt; in &amp;lt;newgroup&amp;gt;, unless a different&lt;br /&gt;
group is specified with &amp;quot;[group]&amp;quot;. Existing entries can be deleted from&lt;br /&gt;
&amp;lt;oldgroup&amp;gt; by adding lines with &amp;quot;# DELETE key&amp;quot; in the output of the script.·&lt;br /&gt;
To delete &amp;lt;oldgroup&amp;gt; use &amp;quot;# DELETEGROUP&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;interpreter&amp;gt; can be something like &amp;quot;perl&amp;quot; or &amp;quot;ruby&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
It is also possible to have a script command without specifying &amp;lt;oldfile&amp;gt; or &amp;lt;newfile&amp;gt;. In that case the script is run but it will not be fed any input and its output will simply be discarded.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ScriptArguments=&amp;lt;arguments&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If specified, the arguments will be passed to &amp;lt;script&amp;gt;.&lt;br /&gt;
IMPORTANT: It has to be specified before Script=.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Group=&amp;lt;oldgroup&amp;gt;,&amp;lt;newgroup&amp;gt;&lt;br /&gt;
Group=&amp;lt;oldgroup&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that configuration information is read from the group &amp;lt;oldgroup&amp;gt;&lt;br /&gt;
and written to &amp;lt;newgroup&amp;gt;. If you only specify &amp;lt;oldgroup&amp;gt;, the information&lt;br /&gt;
is read from as well as written to &amp;lt;oldgroup&amp;gt;. You can use &amp;lt;default&amp;gt; to&lt;br /&gt;
specify keys that are not under any group.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
RemoveGroup=&amp;lt;oldgroup&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that &amp;lt;oldgroup&amp;gt; is removed entirely. This can be used&lt;br /&gt;
to remove obsolete entries or to force a revert to default values.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Options=&amp;lt;option1&amp;gt;, &amp;lt;option2&amp;gt;,&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With this entry you can specify options that apply to the next &amp;quot;Script&amp;quot;,&lt;br /&gt;
&amp;quot;Key&amp;quot; or &amp;quot;AllKeys&amp;quot; entry (only to the first!). Possible options are:&lt;br /&gt;
&lt;br /&gt;
*&amp;quot;copy&amp;quot; Copy the configuration item instead of moving it. This means that&lt;br /&gt;
the configuration item will not be deleted from &amp;lt;oldfile&amp;gt;/&amp;lt;oldgroup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;quot;overwrite&amp;quot; Normally, a configuration item is not moved if an item with the&lt;br /&gt;
new name already exists. When this option is specified the old configuration item will overwrite any existing item.&lt;br /&gt;
&lt;br /&gt;
Key=&amp;lt;oldkey&amp;gt;,&amp;lt;newkey&amp;gt;&lt;br /&gt;
Key=&amp;lt;oldkey&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that configuration information is read from the key &amp;lt;oldkey&amp;gt;&lt;br /&gt;
and written to &amp;lt;newkey&amp;gt;. If you only specify &amp;lt;oldkey&amp;gt;, the information&lt;br /&gt;
is read from as well as written to &amp;lt;oldkey&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
AllKeys&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that all configuration information in the selected group should&lt;br /&gt;
be moved (All keys).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
AllGroups&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that all configuration information from all keys in ALL·&lt;br /&gt;
groups should be moved.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
RemoveKey=&amp;lt;oldkey&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that &amp;lt;oldkey&amp;gt; is removed from the selected group. This can be used&lt;br /&gt;
to remove obsolete entries or to force a revert to default values.&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials/Updating_KConfig_Files</id>
		<title>Development/Tutorials/Updating KConfig Files</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials/Updating_KConfig_Files"/>
				<updated>2007-12-31T18:11:26Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:I18n/Language Navigation Bar|Development/Tutorials/Updating_KConfig_Files}}&lt;br /&gt;
{{TutorialBrowser|&lt;br /&gt;
&lt;br /&gt;
series=KConfig|&lt;br /&gt;
&lt;br /&gt;
pre=[[../Using_KConfig_XT| Using KConfig XT]]|&lt;br /&gt;
&lt;br /&gt;
name=Updating KConfig files|&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=KConfig Update=&lt;br /&gt;
&lt;br /&gt;
This page describes how a developer can use the KConfig update mechanism (kconf_update) available in kdelibs to update a user's already existing config file to accomodate changes made to the format of the default config file.&lt;br /&gt;
&lt;br /&gt;
==Why should you use it?==&lt;br /&gt;
&lt;br /&gt;
Over time applications sometimes need to rearrange the way configuration options are stored. Since such an update shouldn't influence the configuration options that the user has selected, the application must take care that the options stored in the old way will still be honored.&lt;br /&gt;
&lt;br /&gt;
What used to happen is that the application looks up both the old and the&lt;br /&gt;
new configuration option and then decides which one to use. This method has several drawbacks:&lt;br /&gt;
* The application may need to read more configuration files than strictly needed, resulting in a slower startup.&lt;br /&gt;
* The application becomes bigger with code that will only be used once.&lt;br /&gt;
&lt;br /&gt;
kconf_update addresses these problems by offering a framework to update configuration files without adding code to the application itself.&lt;br /&gt;
&lt;br /&gt;
==How it works==&lt;br /&gt;
&lt;br /&gt;
Applications can install so called &amp;quot;update files&amp;quot; under&lt;br /&gt;
{{Path|$KDEDIR/share/apps/kconf_update.}} An update file has {{Path|.upd}} as an extension and contains instructions for transferring/converting configuration information from one place to another.&lt;br /&gt;
&lt;br /&gt;
Updating the configuration happens automatically, either when KDE gets started&lt;br /&gt;
or when kded detects a new update file in the above mentioned location.&lt;br /&gt;
&lt;br /&gt;
Update files are separated into sections. Each section has an id. When a&lt;br /&gt;
section describing a configuration change has been applied, the id will be&lt;br /&gt;
stored in the file {{Path|kconf_updaterc}}. This information is used to make sure that a configuration update is only performed once.&lt;br /&gt;
&lt;br /&gt;
If you overwrite an existing update file with a new version that contains a&lt;br /&gt;
new section, only the update instructions from this extra section will be&lt;br /&gt;
performed.&lt;br /&gt;
&lt;br /&gt;
==File format of the update file==&lt;br /&gt;
&lt;br /&gt;
Empty lines or lines that start with '#' are considered comments&lt;br /&gt;
Commas (,) are used to seperate fields and may not occur as part&lt;br /&gt;
of any field and all of the keywords are case-sensitive, i.e. you&lt;br /&gt;
cannot say &amp;quot;key&amp;quot; instead of &amp;quot;Key&amp;quot; for example.&lt;br /&gt;
&lt;br /&gt;
For the rest the file is parsed and executed sequentially from top to bottom.&lt;br /&gt;
Each line can contain one entry. The following entries are recognized:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;Id=&amp;lt;id&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With &amp;lt;id&amp;gt; identifying the group of update entries that follows. Once a group&lt;br /&gt;
of entries have been applied, their &amp;lt;id&amp;gt; is stored and this group of entries&lt;br /&gt;
will not be applied again.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
File=&amp;lt;oldfile&amp;gt;,&amp;lt;newfile&amp;gt;&lt;br /&gt;
File=&amp;lt;oldfile&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that configuration information is read from &amp;lt;oldfile&amp;gt; and written&lt;br /&gt;
to &amp;lt;newfile&amp;gt;. If you only specify &amp;lt;oldfile&amp;gt;, the information is read from&lt;br /&gt;
and as written to &amp;lt;oldfile&amp;gt;. Note that if the file does not exist&lt;br /&gt;
at the time kconf_update first checks, no related update will be performed.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Script=&amp;lt;script&amp;gt;[,&amp;lt;interpreter&amp;gt;]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;script&amp;gt; is the program that will be performing the updates. All entries from &amp;lt;oldfile&amp;gt; are piped into &amp;lt;script&amp;gt;. The output of &amp;lt;script&amp;gt;is used as new entries for &amp;lt;newfile&amp;gt;. Existing entries can be deleted by adding lines with &amp;quot;# DELETE [group]key&amp;quot; in the output of the script. To delete a whole group use &amp;quot;# DELETEGROUP [group]&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
There are two types of kconf_update scripts:&lt;br /&gt;
*Non-Compiled&lt;br /&gt;
*Compiled&lt;br /&gt;
&lt;br /&gt;
If &amp;lt;script&amp;gt; is written in a non-compiled language (such as ruby or perl), then it should be installed into &lt;br /&gt;
{{Path|${KCONF_UPDATE_INSTALL_DIR} }}. &lt;br /&gt;
&lt;br /&gt;
If &amp;lt;script&amp;gt; is a compiled application, it should be installed in {{Path|${BIN_INSTALL_DIR}/kconf_update_bin}}&lt;br /&gt;
&lt;br /&gt;
If the script command is issued after a &amp;quot;Group&amp;quot; command the behavior is slightly&lt;br /&gt;
different:&lt;br /&gt;
&lt;br /&gt;
All entries from &amp;lt;oldfile&amp;gt; in &amp;lt;oldgroup&amp;gt; are piped into &amp;lt;script&amp;gt;. The output&lt;br /&gt;
of script is used as new entries for &amp;lt;newfile&amp;gt; in &amp;lt;newgroup&amp;gt;, unless a different&lt;br /&gt;
group is specified with &amp;quot;[group]&amp;quot;. Existing entries can be deleted from&lt;br /&gt;
&amp;lt;oldgroup&amp;gt; by adding lines with &amp;quot;# DELETE key&amp;quot; in the output of the script.·&lt;br /&gt;
To delete &amp;lt;oldgroup&amp;gt; use &amp;quot;# DELETEGROUP&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;interpreter&amp;gt; can be something like &amp;quot;perl&amp;quot; or &amp;quot;ruby&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
It is also possible to have a script command without specifying &amp;lt;oldfile&amp;gt; or &amp;lt;newfile&amp;gt;. In that case the script is run but it will not be fed any input and its output will simply be discarded.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ScriptArguments=&amp;lt;arguments&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If specified, the arguments will be passed to &amp;lt;script&amp;gt;.&lt;br /&gt;
IMPORTANT: It has to be specified before Script=.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Group=&amp;lt;oldgroup&amp;gt;,&amp;lt;newgroup&amp;gt;&lt;br /&gt;
Group=&amp;lt;oldgroup&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that configuration information is read from the group &amp;lt;oldgroup&amp;gt;&lt;br /&gt;
and written to &amp;lt;newgroup&amp;gt;. If you only specify &amp;lt;oldgroup&amp;gt;, the information&lt;br /&gt;
is read from as well as written to &amp;lt;oldgroup&amp;gt;. You can use &amp;lt;default&amp;gt; to&lt;br /&gt;
specify keys that are not under any group.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
RemoveGroup=&amp;lt;oldgroup&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that &amp;lt;oldgroup&amp;gt; is removed entirely. This can be used&lt;br /&gt;
to remove obsolete entries or to force a revert to default values.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Options=&amp;lt;option1&amp;gt;, &amp;lt;option2&amp;gt;,&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With this entry you can specify options that apply to the next &amp;quot;Script&amp;quot;,&lt;br /&gt;
&amp;quot;Key&amp;quot; or &amp;quot;AllKeys&amp;quot; entry (only to the first!). Possible options are:&lt;br /&gt;
&lt;br /&gt;
*&amp;quot;copy&amp;quot; Copy the configuration item instead of moving it. This means that&lt;br /&gt;
the configuration item will not be deleted from &amp;lt;oldfile&amp;gt;/&amp;lt;oldgroup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;quot;overwrite&amp;quot; Normally, a configuration item is not moved if an item with the&lt;br /&gt;
new name already exists. When this option is specified the old configuration item will overwrite any existing item.&lt;br /&gt;
&lt;br /&gt;
Key=&amp;lt;oldkey&amp;gt;,&amp;lt;newkey&amp;gt;&lt;br /&gt;
Key=&amp;lt;oldkey&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that configuration information is read from the key &amp;lt;oldkey&amp;gt;&lt;br /&gt;
and written to &amp;lt;newkey&amp;gt;. If you only specify &amp;lt;oldkey&amp;gt;, the information&lt;br /&gt;
is read from as well as written to &amp;lt;oldkey&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
AllKeys&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that all configuration information in the selected group should&lt;br /&gt;
be moved (All keys).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
AllGroups&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that all configuration information from all keys in ALL·&lt;br /&gt;
groups should be moved.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
RemoveKey=&amp;lt;oldkey&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that &amp;lt;oldkey&amp;gt; is removed from the selected group. This can be used&lt;br /&gt;
to remove obsolete entries or to force a revert to default values.&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials/Using_KConfig_XT</id>
		<title>Development/Tutorials/Using KConfig XT</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials/Using_KConfig_XT"/>
				<updated>2007-12-31T18:07:03Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:I18n/Language Navigation Bar|Development/Tutorials/Using_KConfig_XT}}&lt;br /&gt;
{{TutorialBrowser|&lt;br /&gt;
&lt;br /&gt;
series=KConfig|&lt;br /&gt;
&lt;br /&gt;
pre=[[../KConfig|Introduction to KConfig]]|&lt;br /&gt;
&lt;br /&gt;
next=[[../Updating_KConfig_Files|Updating Kconfig Files]]|&lt;br /&gt;
&lt;br /&gt;
name=Using KConfig XT|&lt;br /&gt;
&lt;br /&gt;
reading=[http://api.kde.org/4.0-api/kdelibs-apidocs/kdecore/html/kconfig_compiler.html The KDE Configuration Compiler (KDE 4)]&amp;lt;br&amp;gt;[http://api.kde.org/3.5-api/kdelibs-apidocs/kdecore/html/kconfig_compiler.html The KDE Configuration Compiler (KDE 3)]&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Using KConfig XT ==&lt;br /&gt;
''Original Author'': Zack Rusin &amp;lt;[mailto:zack@kde.org zack@kde.org]&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This tutorial introduces the main concepts of the KconfigXT &lt;br /&gt;
configuration framework and shows how to efficiently use it in applications. It assumes that the reader has already developed a KDE application and is familiar with KConfig. A basic understanding of XML and concepts behind DTDs is also required.&lt;br /&gt;
  &lt;br /&gt;
The main idea behind KConfig XT is to make the life of application developers &lt;br /&gt;
easier while making the administration of large KDE installations more manageable.&lt;br /&gt;
The four basic parts of the new framework are: &lt;br /&gt;
&lt;br /&gt;
* KConfigSkeleton - a class in the libkdecore library which grants a more flexible access to the configuration options,&lt;br /&gt;
* XML file containing information about configuration options (the {{path|.kcfg}} file)&lt;br /&gt;
* An ini like file which provides the code generation options (the {{path|.kcfgc}} file)&lt;br /&gt;
* kconfig_compiler - which generates C++ source code from {{path|.kcfg}} and {{path|.kcfgc}} files. The generated class is based on KConfigSkeleton and provides an API for the application to access its configuration data.&lt;br /&gt;
&lt;br /&gt;
{{note|In this tutorial more advanced and optional features of KConfig XT and their descriptions are marked by ''italic text''. If you decide to skip them during the first reading, be sure to come back to them at some point. }}&lt;br /&gt;
&lt;br /&gt;
== .kcfg DTD Structure ==&lt;br /&gt;
&lt;br /&gt;
The structure of the {{path|.kcfg}} file is described by its DTD (kcfg.xsd - available from&lt;br /&gt;
[http://www.kde.org/standards/kcfg/1.0/kcfg.xsd here] (please note that browsers do not display DTDs in a visual form,&lt;br /&gt;
download the DTD directly and view it like a text file) or the kdecore &lt;br /&gt;
library). Please go through it before you go any further.  &lt;br /&gt;
&lt;br /&gt;
Lets create a simple .kcfg file. Please reference the code below as we go through each step.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE kcfg SYSTEM &lt;br /&gt;
    &amp;quot;http://www.kde.org/standards/kcfg/1.0/kcfg.xsd&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;kcfg&amp;gt;&lt;br /&gt;
  &amp;lt;kcfgfile name=&amp;quot;kjotsrc&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;include&amp;gt;kglobalsettings.h&amp;lt;/include&amp;gt;&lt;br /&gt;
  &amp;lt;group name=&amp;quot;kjots&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;entry name=&amp;quot;SplitterSizes&amp;quot; type=&amp;quot;IntList&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;label&amp;gt;How the main window is divided.&amp;lt;/label&amp;gt;&lt;br /&gt;
    &amp;lt;/entry&amp;gt;&lt;br /&gt;
    &amp;lt;entry name=&amp;quot;Width&amp;quot; type=&amp;quot;Int&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;label&amp;gt;Width of the main window.&amp;lt;/label&amp;gt;&lt;br /&gt;
      &amp;lt;default&amp;gt;600&amp;lt;/default&amp;gt;&lt;br /&gt;
    &amp;lt;/entry&amp;gt;&lt;br /&gt;
    &amp;lt;entry name=&amp;quot;Height&amp;quot; type=&amp;quot;Int&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;label&amp;gt;Height of the main window.&amp;lt;/label&amp;gt;&lt;br /&gt;
      &amp;lt;default&amp;gt;400&amp;lt;/default&amp;gt;&lt;br /&gt;
    &amp;lt;/entry&amp;gt;&lt;br /&gt;
    &amp;lt;entry name=&amp;quot;OpenBooks&amp;quot; type=&amp;quot;StringList&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;label&amp;gt;All books that are opened.&amp;lt;/label&amp;gt;&lt;br /&gt;
    &amp;lt;/entry&amp;gt;&lt;br /&gt;
    &amp;lt;entry name=&amp;quot;CurrentBook&amp;quot; type=&amp;quot;String&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;label&amp;gt;The book currently opened.&amp;lt;/label&amp;gt;&lt;br /&gt;
    &amp;lt;/entry&amp;gt;&lt;br /&gt;
    &amp;lt;entry name=&amp;quot;Font&amp;quot; type=&amp;quot;Font&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;label&amp;gt;The font used to display the contents of books.&amp;lt;/label&amp;gt;&lt;br /&gt;
      &amp;lt;default code=&amp;quot;true&amp;quot;&amp;gt;KGlobalSettings::generalFont()&amp;lt;/default&amp;gt;&lt;br /&gt;
    &amp;lt;/entry&amp;gt;&lt;br /&gt;
  &amp;lt;/group&amp;gt;&lt;br /&gt;
&amp;lt;/kcfg&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Use your favorite code editor to open a your_application_name{{path|.kcfg}} file (of course replacing your_application_name with the name of the application you want to convert to KConfig XT).&lt;br /&gt;
* Start that file by opening the &amp;amp;lt;kcfgfile&amp;amp;gt; tag which controls which KConfig file the data will be stored in. There are three possibilities:&lt;br /&gt;
*# If the &amp;amp;lt;kcfgfile&amp;amp;gt; tag has no attributes the generated code will use the application's default KConfig file (normally {{path|$HOME/.kde/config/&amp;lt;appname&amp;gt;rc}}).&lt;br /&gt;
*# ''The &amp;quot;name&amp;quot; attribute is used to manually specify a file name. If the value assigned to &amp;quot;name&amp;quot; is not an absolute file path, the file will be created in the default KDE config directory (normally {{path|$HOME/.kde/config}}).''&lt;br /&gt;
*# ''If you would like to be able to specify the config file at construction time, use &amp;amp;lt;kcfgfile arg=&amp;quot;true&amp;quot;&amp;amp;gt;. This causes the constructor of the generated class to take a KSharedConfig::Ptr as an argument, allowing you to construct multiple instances pointing to different files.''&lt;br /&gt;
* ''Add the optional &amp;amp;lt;include&amp;amp;gt; tags which may contain C++ header files that are needed to compile the code required to compute the default values.''&lt;br /&gt;
* The remaining entries in the XML file are grouped by the tag &amp;amp;lt;group&amp;amp;gt; which describes the corresponding groups in the configuration file.&lt;br /&gt;
*#The individual entries must have at least a name or a key. The key is used as the key in the config file. The name is used to create accessor and modifier functions. If &amp;amp;lt;key&amp;amp;gt; is not given, the name is used as the config file key. If &amp;amp;lt;key&amp;amp;gt; is given, but not &amp;amp;lt;name&amp;amp;gt;, the name is constructed by removing all spaces from the &amp;amp;lt;key&amp;amp;gt; contents.&lt;br /&gt;
*# Always add a label or a whatsthis tags to your application in which you describe the configuration options. The label tag is used for short descriptions of the entry, while whatsthis contains more verbose documentation. ''It's important for tools like KConfigEditor which can be used by systems administrators to setup machines over on the network.''&lt;br /&gt;
*# An entry must also have a type. The allowed types are: String, StringList, Font, Rect, Size, Color, Point, Int, UInt, Bool, Double, DateTime, Int64, UInt64 and Password. '' Besides those basic type the following special types are supported and include:''&lt;br /&gt;
*#* Path - This is a string that is specially treated as a file-path. In particular paths in the home directory are prefixed with $HOME when being stored in the configuration file.&lt;br /&gt;
*#* Enum - This indicates an enumeration. The possible enum values should be provided via the &amp;amp;lt;choices&amp;amp;gt; tag. Enum values are accessed as integers by the application but stored as string in the configuration file. This makes it possible to add more values at a later date without breaking compatibility.&lt;br /&gt;
*#* IntList - This indicates a list of integers. This information is provided to the application as QValueList&amp;amp;lt;int&amp;amp;gt;. Useful for storing QSplitter geometries.&lt;br /&gt;
*#* PathList - List of Path elements.&lt;br /&gt;
*# The min and max tags can be set to limit the value of the integer-type options.&lt;br /&gt;
*#''An entry can optionally have a default value which is used as default when the value isn't specified in any config file. Default values are interpreted as literal constant values. If a default value needs to be computed or if it needs to be obtained from a function call, the &amp;amp;lt;default&amp;amp;gt; tag should contain the code=&amp;quot;true&amp;quot; attribute. The contents of the &amp;amp;lt;default&amp;amp;gt; tag is then considered to be a C++ expression. ''&lt;br /&gt;
*#''Additional code for computing default values can be provided via the &amp;amp;lt;code&amp;amp;gt; tag. The contents of the &amp;amp;lt;code&amp;amp;gt; tag is inserted as-is. A typical use for this is to compute a common default value which can then be referenced by multiple entries that follow.''&lt;br /&gt;
*#''Optionally, the hidden option can also be added to the &amp;amp;lt;entry&amp;amp;gt;. The possible values are true and false.''&lt;br /&gt;
&lt;br /&gt;
== .kcfgc files ==&lt;br /&gt;
&lt;br /&gt;
After creating a {{path|.kcfg}} file create a {{path|.kcfgc}} file which describes the C++ file &lt;br /&gt;
generation options. The .kcfgc file is a simple ini file with the typical &lt;br /&gt;
&amp;quot;entry=value&amp;quot; format. To create a simple .kcfgc file follow these steps:&lt;br /&gt;
&lt;br /&gt;
# Open a new file in your favorite text editor.&lt;br /&gt;
# Start it with the &amp;quot;File=your_application_name.kcfg&amp;quot; entry which specifies where the configuration options for your application are stored.&lt;br /&gt;
# Add the &amp;quot;ClassName=YourConfigClassName&amp;quot; entry which specifies the name of the class that will be generated from the .kcfg file. Remember that the generated class will be derived from KConfigSkeleton. PLease make sure that YourConfigClassName is not a class name already used in your application. Save this file under {{path|yourconfigclassname.kcfgc.}} This will ensure the generation of the yourconfigclassname.{h,cpp} files where your configuration class will reside. &lt;br /&gt;
# Add any additional entries, which your application might need. Those additional entries include:&lt;br /&gt;
#* NameSpace - specifies the namespace in which the generated config class should reside,&lt;br /&gt;
#* Inherits - if you need the generated class to inherit your custom class,&lt;br /&gt;
#* Singleton - if the configuration class should be a singleton,&lt;br /&gt;
#* MemberVariables - specifies the access to the member variables, default is private,&lt;br /&gt;
#* ItemAccessors - relates to the above item, if member variables are public then it might make little sense to generate accessors. By default they are generated,&lt;br /&gt;
#* Mutators - similar to the above one, but applies to the mutator methods,&lt;br /&gt;
#* GlobalEnums - specifies whether enums should be class wide of whether they should be always explicitly prefixed with their type name,&lt;br /&gt;
#* UseEnumTypes - specifies whether enum values should be passed as type int or as their enum type in the return value of accessor functions and the arguments of mutator and signal functions.&lt;br /&gt;
&lt;br /&gt;
== Adjusting the CMakeLists.txt file ==&lt;br /&gt;
&lt;br /&gt;
After creating the .kcfg and .kcfgc files the next step is to adjust the &lt;br /&gt;
build to let kconfig_compiler generate the required class at compile time. Fortunately doing this is trivial and requires only one step, adding this line to the CMakeLists.txt file example:&lt;br /&gt;
&lt;br /&gt;
 kde4_add_kcfg_files(&amp;lt;project name&amp;gt;_SRCS settings.kcfgc)&lt;br /&gt;
&lt;br /&gt;
Alternatively, if a .moc file needs to be generated before compiling the generated source code, use&lt;br /&gt;
&lt;br /&gt;
 kde4_add_kcfg_files(&amp;lt;project name&amp;gt;_SRCS GENERATE_MOC settings.kcfgc)&lt;br /&gt;
&lt;br /&gt;
This assures that the configuration class is properly generated and that the .kcfg is installed so it can be used by tools like &lt;br /&gt;
the KConfigEditor.&lt;br /&gt;
&lt;br /&gt;
== Use and Dialogs ==&lt;br /&gt;
&lt;br /&gt;
After making all of the above changes you're ready to use KConfig XT. The &lt;br /&gt;
kconfig_compiler generated header file will have the name equal to the name of the .kcfg file but with a &amp;quot;.h&amp;quot; extension. Simply include that file wherever you want to access your configuration options.&lt;br /&gt;
&lt;br /&gt;
The use will depend on whether you have added the &amp;lt;tt&amp;gt;Singleton=true&amp;lt;/tt&amp;gt; entry to your .kcfgc file. &lt;br /&gt;
&lt;br /&gt;
One the nicest features of the KConfig XT is its seamless integration with the Qt &lt;br /&gt;
Designer generated dialogs. You can do that by using {{class|KConfigDialog}}. The &lt;br /&gt;
steps to do that are as follows: &lt;br /&gt;
&lt;br /&gt;
# Create the KConfigDialog and pass the instance of your configuration data as one of the arguments. The construct would look like the following example:&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;code cppqt&amp;gt;&lt;br /&gt;
KConfigDialog* dialog = new KConfigDialog( &lt;br /&gt;
         this, &amp;quot;settings&amp;quot;, YourAppSettings::self() );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
assuming that YourAppSettings is the value of the ClassName variable from the kcfgc file and the settings class is a singelton.&lt;br /&gt;
# In Qt Designer create widgets which should be used to configure your options. In order to make those widgets interact with the kcfg you have name each one of them using the following scheme:&lt;br /&gt;
## Prefix the Name of the widget which should control one of the options with &amp;quot;kcfg_&amp;quot;&lt;br /&gt;
## Append the &amp;quot;name&amp;quot; attribute value from your kcfg file which corresponds to option the given widget should control.&lt;br /&gt;
# Add the Qt Designer generated widget to the KConfigDialog.&lt;br /&gt;
# Show the dialog when you're done.&lt;br /&gt;
&lt;br /&gt;
== Example ==&lt;br /&gt;
&lt;br /&gt;
Here's an example usage of KConfig XT for the application named Example.&lt;br /&gt;
With the following example.kcfg file: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE kcfg SYSTEM &lt;br /&gt;
    &amp;quot;http://www.kde.org/standards/kcfg/1.0/kcfg.dtd&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;kcfg&amp;gt; &amp;lt;kcfgfile name=&amp;quot;examplerc&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;group name=&amp;quot;network&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;entry name=&amp;quot;ServerName&amp;quot; type=&amp;quot;String&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;label&amp;gt;Defines the sample server.&amp;lt;/label&amp;gt;&lt;br /&gt;
    &amp;lt;/entry&amp;gt;&lt;br /&gt;
    &amp;lt;entry name=&amp;quot;Port&amp;quot; type=&amp;quot;Int&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;label&amp;gt;Defines the server port&amp;lt;/label&amp;gt;&lt;br /&gt;
      &amp;lt;default&amp;gt;21&amp;lt;/default&amp;gt;&lt;br /&gt;
      &amp;lt;min&amp;gt;20&amp;lt;/min&amp;gt;&lt;br /&gt;
      &amp;lt;max&amp;gt;990&amp;lt;/max&amp;gt;&lt;br /&gt;
    &amp;lt;/entry&amp;gt;&lt;br /&gt;
  &amp;lt;/group&amp;gt;&lt;br /&gt;
&amp;lt;/kcfg&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And here's how to actually use the generated class. for the given kcfgc file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code ini&amp;gt;&lt;br /&gt;
File=example.kcfg &lt;br /&gt;
ClassName=ExampleSettings &lt;br /&gt;
Singleton=true &lt;br /&gt;
Mutators=true&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The header files wouldn't change, but the cpp files must now contain the &lt;br /&gt;
following code to access and store the configuration data :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
#include &amp;lt;ExampleSettings.h&amp;gt; &lt;br /&gt;
... &lt;br /&gt;
void ExampleClass::readConfig() { &lt;br /&gt;
        m_server  = ExampleSettings::serverName(); &lt;br /&gt;
        m_port    = ExampleSettings::port(); &lt;br /&gt;
} &lt;br /&gt;
void ExampleClass:saveSettings() { &lt;br /&gt;
        ExampleSettings::setServerName( m_server ); &lt;br /&gt;
        ExampleSettings::setPort( m_port ); &lt;br /&gt;
        ExampleSettings::writeConfig(); &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To add a dialog you need to create a Qt Designer widget with the widget names&lt;br /&gt;
corresponding to the names of the options they should edit and prefixed with &amp;quot;kcfg_&amp;quot;. &lt;br /&gt;
It could be something along the lines of:&lt;br /&gt;
&lt;br /&gt;
[[Image:kconfigxt.png|center|256px]]&lt;br /&gt;
&lt;br /&gt;
And you can use the dialog with the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt&amp;gt;&lt;br /&gt;
//An instance of your dialog could be already created and could be&lt;br /&gt;
// cached, in which case you want to display the cached dialog &lt;br /&gt;
// instead of creating another one&lt;br /&gt;
if ( KConfigDialog::showDialog( &amp;quot;settings&amp;quot; ) )&lt;br /&gt;
  return; &lt;br /&gt;
 &lt;br /&gt;
// KConfigDialog didn't find an instance of this dialog, so lets&lt;br /&gt;
// create it : &lt;br /&gt;
KConfigDialog* dialog = new KConfigDialog(this, &amp;quot;settings&amp;quot;,&lt;br /&gt;
                                          ExampleSettings::self()); &lt;br /&gt;
ExampleDesignerWidget* confWdg =  &lt;br /&gt;
                  new ExampleDesignerWidget( 0, &amp;quot;Example&amp;quot; ); &lt;br /&gt;
 &lt;br /&gt;
dialog-&amp;gt;addPage( confWdg, i18n(&amp;quot;Example&amp;quot;), &amp;quot;example&amp;quot; ); &lt;br /&gt;
 &lt;br /&gt;
//User edited the configuration - update your local copies of the &lt;br /&gt;
//configuration data &lt;br /&gt;
connect( dialog, SIGNAL(settingsChanged()), &lt;br /&gt;
         this, SLOT(updateConfiguration()) ); &lt;br /&gt;
 &lt;br /&gt;
dialog-&amp;gt;show();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And that's all it takes. You can have a look at [http://websvn.kde.org/trunk/KDE/kdegames/kreversi KReversi] and [http://websvn.kde.org/trunk/KDE/kdegames/ktron/ KTron] code in the [http://websvn.kde.org/trunk/KDE/kdegames kdegames module] to see a live example of KConfig XT!&lt;br /&gt;
&lt;br /&gt;
== Common Pitfalls and Tips ==&lt;br /&gt;
&lt;br /&gt;
* Do not forget to add the &amp;quot;type&amp;quot; attribute to the &amp;quot;entry&amp;quot; tag in your .kcfg file.&lt;br /&gt;
* Always try to add both the &amp;amp;lt;label&amp;amp;gt; and &amp;amp;lt;whatsthis&amp;amp;gt; tags to each entry.&lt;br /&gt;
* Putting the MemberVariables=public in your .kcfgc is usually a bad idea - you'll avoid accidental changes to those members by using the aggregation and forcing the use of the mutators.&lt;br /&gt;
* If your application doesn't have one central object (created before and destructed after; all others) then always put the Singleton=true entry in your .kcfgs file.&lt;br /&gt;
[[Category:C++]]&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials/Updating_KConfig_Files</id>
		<title>Development/Tutorials/Updating KConfig Files</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials/Updating_KConfig_Files"/>
				<updated>2007-12-31T14:43:07Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:I18n/Language Navigation Bar|Development/Tutorials/Updating_KConfig_Files}}&lt;br /&gt;
{{TutorialBrowser|&lt;br /&gt;
&lt;br /&gt;
series=KConfig|&lt;br /&gt;
&lt;br /&gt;
pre=[[../KConfig|Introduction to KConfig]]|&lt;br /&gt;
&lt;br /&gt;
name=Updating KConfig files|&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=KConfig Update=&lt;br /&gt;
&lt;br /&gt;
This page describes how a developer can use the KConfig update mechanism (kconf_update) available in kdelibs to update a user's already existing config file to accomodate changes made to the format of the default config file.&lt;br /&gt;
&lt;br /&gt;
==Why should you use it?==&lt;br /&gt;
&lt;br /&gt;
Over time applications sometimes need to rearrange the way configuration options are stored. Since such an update shouldn't influence the configuration options that the user has selected, the application must take care that the options stored in the old way will still be honored.&lt;br /&gt;
&lt;br /&gt;
What used to happen is that the application looks up both the old and the&lt;br /&gt;
new configuration option and then decides which one to use. This method has several drawbacks:&lt;br /&gt;
* The application may need to read more configuration files than strictly needed, resulting in a slower startup.&lt;br /&gt;
* The application becomes bigger with code that will only be used once.&lt;br /&gt;
&lt;br /&gt;
kconf_update addresses these problems by offering a framework to update configuration files without adding code to the application itself.&lt;br /&gt;
&lt;br /&gt;
==How it works==&lt;br /&gt;
&lt;br /&gt;
Applications can install so called &amp;quot;update files&amp;quot; under&lt;br /&gt;
{{Path|$KDEDIR/share/apps/kconf_update.}} An update file has {{Path|.upd}} as an extension and contains instructions for transferring/converting configuration information from one place to another.&lt;br /&gt;
&lt;br /&gt;
Updating the configuration happens automatically, either when KDE gets started&lt;br /&gt;
or when kded detects a new update file in the above mentioned location.&lt;br /&gt;
&lt;br /&gt;
Update files are separated into sections. Each section has an id. When a&lt;br /&gt;
section describing a configuration change has been applied, the id will be&lt;br /&gt;
stored in the file {{Path|kconf_updaterc}}. This information is used to make sure that a configuration update is only performed once.&lt;br /&gt;
&lt;br /&gt;
If you overwrite an existing update file with a new version that contains a&lt;br /&gt;
new section, only the update instructions from this extra section will be&lt;br /&gt;
performed.&lt;br /&gt;
&lt;br /&gt;
==File format of the update file==&lt;br /&gt;
&lt;br /&gt;
Empty lines or lines that start with '#' are considered comments&lt;br /&gt;
Commas (,) are used to seperate fields and may not occur as part&lt;br /&gt;
of any field and all of the keywords are case-sensitive, i.e. you&lt;br /&gt;
cannot say &amp;quot;key&amp;quot; instead of &amp;quot;Key&amp;quot; for example.&lt;br /&gt;
&lt;br /&gt;
For the rest the file is parsed and executed sequentially from top to bottom.&lt;br /&gt;
Each line can contain one entry. The following entries are recognized:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;Id=&amp;lt;id&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With &amp;lt;id&amp;gt; identifying the group of update entries that follows. Once a group&lt;br /&gt;
of entries have been applied, their &amp;lt;id&amp;gt; is stored and this group of entries&lt;br /&gt;
will not be applied again.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
File=&amp;lt;oldfile&amp;gt;,&amp;lt;newfile&amp;gt;&lt;br /&gt;
File=&amp;lt;oldfile&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that configuration information is read from &amp;lt;oldfile&amp;gt; and written&lt;br /&gt;
to &amp;lt;newfile&amp;gt;. If you only specify &amp;lt;oldfile&amp;gt;, the information is read from&lt;br /&gt;
and as written to &amp;lt;oldfile&amp;gt;. Note that if the file does not exist&lt;br /&gt;
at the time kconf_update first checks, no related update will be performed.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Script=&amp;lt;script&amp;gt;[,&amp;lt;interpreter&amp;gt;]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;script&amp;gt; is the program that will be performing the updates. All entries from &amp;lt;oldfile&amp;gt; are piped into &amp;lt;script&amp;gt;. The output of &amp;lt;script&amp;gt;is used as new entries for &amp;lt;newfile&amp;gt;. Existing entries can be deleted by adding lines with &amp;quot;# DELETE [group]key&amp;quot; in the output of the script. To delete a whole group use &amp;quot;# DELETEGROUP [group]&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
There are two types of kconf_update scripts:&lt;br /&gt;
*Non-Compiled&lt;br /&gt;
*Compiled&lt;br /&gt;
&lt;br /&gt;
If &amp;lt;script&amp;gt; is written in a non-compiled language (such as ruby or perl), then it should be installed into &lt;br /&gt;
{{Path|${KCONF_UPDATE_INSTALL_DIR} }}. &lt;br /&gt;
&lt;br /&gt;
If &amp;lt;script&amp;gt; is a compiled application, it should be installed in {{Path|${BIN_INSTALL_DIR}/kconf_update_bin}}&lt;br /&gt;
&lt;br /&gt;
If the script command is issued after a &amp;quot;Group&amp;quot; command the behavior is slightly&lt;br /&gt;
different:&lt;br /&gt;
&lt;br /&gt;
All entries from &amp;lt;oldfile&amp;gt; in &amp;lt;oldgroup&amp;gt; are piped into &amp;lt;script&amp;gt;. The output&lt;br /&gt;
of script is used as new entries for &amp;lt;newfile&amp;gt; in &amp;lt;newgroup&amp;gt;, unless a different&lt;br /&gt;
group is specified with &amp;quot;[group]&amp;quot;. Existing entries can be deleted from&lt;br /&gt;
&amp;lt;oldgroup&amp;gt; by adding lines with &amp;quot;# DELETE key&amp;quot; in the output of the script.·&lt;br /&gt;
To delete &amp;lt;oldgroup&amp;gt; use &amp;quot;# DELETEGROUP&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;interpreter&amp;gt; can be something like &amp;quot;perl&amp;quot; or &amp;quot;ruby&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
It is also possible to have a script command without specifying &amp;lt;oldfile&amp;gt; or &amp;lt;newfile&amp;gt;. In that case the script is run but it will not be fed any input and its output will simply be discarded.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ScriptArguments=&amp;lt;arguments&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If specified, the arguments will be passed to &amp;lt;script&amp;gt;.&lt;br /&gt;
IMPORTANT: It has to be specified before Script=.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Group=&amp;lt;oldgroup&amp;gt;,&amp;lt;newgroup&amp;gt;&lt;br /&gt;
Group=&amp;lt;oldgroup&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that configuration information is read from the group &amp;lt;oldgroup&amp;gt;&lt;br /&gt;
and written to &amp;lt;newgroup&amp;gt;. If you only specify &amp;lt;oldgroup&amp;gt;, the information&lt;br /&gt;
is read from as well as written to &amp;lt;oldgroup&amp;gt;. You can use &amp;lt;default&amp;gt; to&lt;br /&gt;
specify keys that are not under any group.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
RemoveGroup=&amp;lt;oldgroup&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that &amp;lt;oldgroup&amp;gt; is removed entirely. This can be used&lt;br /&gt;
to remove obsolete entries or to force a revert to default values.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Options=&amp;lt;option1&amp;gt;, &amp;lt;option2&amp;gt;,&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With this entry you can specify options that apply to the next &amp;quot;Script&amp;quot;,&lt;br /&gt;
&amp;quot;Key&amp;quot; or &amp;quot;AllKeys&amp;quot; entry (only to the first!). Possible options are:&lt;br /&gt;
&lt;br /&gt;
*&amp;quot;copy&amp;quot; Copy the configuration item instead of moving it. This means that&lt;br /&gt;
the configuration item will not be deleted from &amp;lt;oldfile&amp;gt;/&amp;lt;oldgroup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;quot;overwrite&amp;quot; Normally, a configuration item is not moved if an item with the&lt;br /&gt;
new name already exists. When this option is specified the old configuration item will overwrite any existing item.&lt;br /&gt;
&lt;br /&gt;
Key=&amp;lt;oldkey&amp;gt;,&amp;lt;newkey&amp;gt;&lt;br /&gt;
Key=&amp;lt;oldkey&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that configuration information is read from the key &amp;lt;oldkey&amp;gt;&lt;br /&gt;
and written to &amp;lt;newkey&amp;gt;. If you only specify &amp;lt;oldkey&amp;gt;, the information&lt;br /&gt;
is read from as well as written to &amp;lt;oldkey&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
AllKeys&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that all configuration information in the selected group should&lt;br /&gt;
be moved (All keys).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
AllGroups&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that all configuration information from all keys in ALL·&lt;br /&gt;
groups should be moved.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
RemoveKey=&amp;lt;oldkey&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifies that &amp;lt;oldkey&amp;gt; is removed from the selected group. This can be used&lt;br /&gt;
to remove obsolete entries or to force a revert to default values.&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials/Using_KConfig_XT</id>
		<title>Development/Tutorials/Using KConfig XT</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials/Using_KConfig_XT"/>
				<updated>2007-12-31T14:42:18Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:I18n/Language Navigation Bar|Development/Tutorials/Using_KConfig_XT}}&lt;br /&gt;
{{TutorialBrowser|&lt;br /&gt;
&lt;br /&gt;
series=KConfig|&lt;br /&gt;
&lt;br /&gt;
pre=[[../KConfig|Introduction to KConfig]]|&lt;br /&gt;
&lt;br /&gt;
name=Using KConfig XT|&lt;br /&gt;
&lt;br /&gt;
reading=[http://api.kde.org/4.0-api/kdelibs-apidocs/kdecore/html/kconfig_compiler.html The KDE Configuration Compiler (KDE 4)]&amp;lt;br&amp;gt;[http://api.kde.org/3.5-api/kdelibs-apidocs/kdecore/html/kconfig_compiler.html The KDE Configuration Compiler (KDE 3)]&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Using KConfig XT ==&lt;br /&gt;
''Original Author'': Zack Rusin &amp;lt;[mailto:zack@kde.org zack@kde.org]&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This tutorial introduces the main concepts of the KconfigXT &lt;br /&gt;
configuration framework and shows how to efficiently use it in applications. It assumes that the reader has already developed a KDE application and is familiar with KConfig. A basic understanding of XML and concepts behind DTDs is also required.&lt;br /&gt;
  &lt;br /&gt;
The main idea behind KConfig XT is to make the life of application developers &lt;br /&gt;
easier while making the administration of large KDE installations more manageable.&lt;br /&gt;
The four basic parts of the new framework are: &lt;br /&gt;
&lt;br /&gt;
* KConfigSkeleton - a class in the libkdecore library which grants a more flexible access to the configuration options,&lt;br /&gt;
* XML file containing information about configuration options (the {{path|.kcfg}} file)&lt;br /&gt;
* An ini like file which provides the code generation options (the {{path|.kcfgc}} file)&lt;br /&gt;
* kconfig_compiler - which generates C++ source code from {{path|.kcfg}} and {{path|.kcfgc}} files. The generated class is based on KConfigSkeleton and provides an API for the application to access its configuration data.&lt;br /&gt;
&lt;br /&gt;
{{note|In this tutorial more advanced and optional features of KConfig XT and their descriptions are marked by ''italic text''. If you decide to skip them during the first reading, be sure to come back to them at some point. }}&lt;br /&gt;
&lt;br /&gt;
== .kcfg DTD Structure ==&lt;br /&gt;
&lt;br /&gt;
The structure of the {{path|.kcfg}} file is described by its DTD (kcfg.xsd - available from&lt;br /&gt;
[http://www.kde.org/standards/kcfg/1.0/kcfg.xsd here] (please note that browsers do not display DTDs in a visual form,&lt;br /&gt;
download the DTD directly and view it like a text file) or the kdecore &lt;br /&gt;
library). Please go through it before you go any further.  &lt;br /&gt;
&lt;br /&gt;
Lets create a simple .kcfg file. Please reference the code below as we go through each step.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE kcfg SYSTEM &lt;br /&gt;
    &amp;quot;http://www.kde.org/standards/kcfg/1.0/kcfg.xsd&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;kcfg&amp;gt;&lt;br /&gt;
  &amp;lt;kcfgfile name=&amp;quot;kjotsrc&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;include&amp;gt;kglobalsettings.h&amp;lt;/include&amp;gt;&lt;br /&gt;
  &amp;lt;group name=&amp;quot;kjots&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;entry name=&amp;quot;SplitterSizes&amp;quot; type=&amp;quot;IntList&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;label&amp;gt;How the main window is divided.&amp;lt;/label&amp;gt;&lt;br /&gt;
    &amp;lt;/entry&amp;gt;&lt;br /&gt;
    &amp;lt;entry name=&amp;quot;Width&amp;quot; type=&amp;quot;Int&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;label&amp;gt;Width of the main window.&amp;lt;/label&amp;gt;&lt;br /&gt;
      &amp;lt;default&amp;gt;600&amp;lt;/default&amp;gt;&lt;br /&gt;
    &amp;lt;/entry&amp;gt;&lt;br /&gt;
    &amp;lt;entry name=&amp;quot;Height&amp;quot; type=&amp;quot;Int&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;label&amp;gt;Height of the main window.&amp;lt;/label&amp;gt;&lt;br /&gt;
      &amp;lt;default&amp;gt;400&amp;lt;/default&amp;gt;&lt;br /&gt;
    &amp;lt;/entry&amp;gt;&lt;br /&gt;
    &amp;lt;entry name=&amp;quot;OpenBooks&amp;quot; type=&amp;quot;StringList&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;label&amp;gt;All books that are opened.&amp;lt;/label&amp;gt;&lt;br /&gt;
    &amp;lt;/entry&amp;gt;&lt;br /&gt;
    &amp;lt;entry name=&amp;quot;CurrentBook&amp;quot; type=&amp;quot;String&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;label&amp;gt;The book currently opened.&amp;lt;/label&amp;gt;&lt;br /&gt;
    &amp;lt;/entry&amp;gt;&lt;br /&gt;
    &amp;lt;entry name=&amp;quot;Font&amp;quot; type=&amp;quot;Font&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;label&amp;gt;The font used to display the contents of books.&amp;lt;/label&amp;gt;&lt;br /&gt;
      &amp;lt;default code=&amp;quot;true&amp;quot;&amp;gt;KGlobalSettings::generalFont()&amp;lt;/default&amp;gt;&lt;br /&gt;
    &amp;lt;/entry&amp;gt;&lt;br /&gt;
  &amp;lt;/group&amp;gt;&lt;br /&gt;
&amp;lt;/kcfg&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Use your favorite code editor to open a your_application_name{{path|.kcfg}} file (of course replacing your_application_name with the name of the application you want to convert to KConfig XT).&lt;br /&gt;
* Start that file by opening the &amp;amp;lt;kcfgfile&amp;amp;gt; tag which controls which KConfig file the data will be stored in. There are three possibilities:&lt;br /&gt;
*# If the &amp;amp;lt;kcfgfile&amp;amp;gt; tag has no attributes the generated code will use the application's default KConfig file (normally {{path|$HOME/.kde/config/&amp;lt;appname&amp;gt;rc}}).&lt;br /&gt;
*# ''The &amp;quot;name&amp;quot; attribute is used to manually specify a file name. If the value assigned to &amp;quot;name&amp;quot; is not an absolute file path, the file will be created in the default KDE config directory (normally {{path|$HOME/.kde/config}}).''&lt;br /&gt;
*# ''If you would like to be able to specify the config file at construction time, use &amp;amp;lt;kcfgfile arg=&amp;quot;true&amp;quot;&amp;amp;gt;. This causes the constructor of the generated class to take a KSharedConfig::Ptr as an argument, allowing you to construct multiple instances pointing to different files.''&lt;br /&gt;
* ''Add the optional &amp;amp;lt;include&amp;amp;gt; tags which may contain C++ header files that are needed to compile the code required to compute the default values.''&lt;br /&gt;
* The remaining entries in the XML file are grouped by the tag &amp;amp;lt;group&amp;amp;gt; which describes the corresponding groups in the configuration file.&lt;br /&gt;
*#The individual entries must have at least a name or a key. The key is used as the key in the config file. The name is used to create accessor and modifier functions. If &amp;amp;lt;key&amp;amp;gt; is not given, the name is used as the config file key. If &amp;amp;lt;key&amp;amp;gt; is given, but not &amp;amp;lt;name&amp;amp;gt;, the name is constructed by removing all spaces from the &amp;amp;lt;key&amp;amp;gt; contents.&lt;br /&gt;
*# Always add a label or a whatsthis tags to your application in which you describe the configuration options. The label tag is used for short descriptions of the entry, while whatsthis contains more verbose documentation. ''It's important for tools like KConfigEditor which can be used by systems administrators to setup machines over on the network.''&lt;br /&gt;
*# An entry must also have a type. The allowed types are: String, StringList, Font, Rect, Size, Color, Point, Int, UInt, Bool, Double, DateTime, Int64, UInt64 and Password. '' Besides those basic type the following special types are supported and include:''&lt;br /&gt;
*#* Path - This is a string that is specially treated as a file-path. In particular paths in the home directory are prefixed with $HOME when being stored in the configuration file.&lt;br /&gt;
*#* Enum - This indicates an enumeration. The possible enum values should be provided via the &amp;amp;lt;choices&amp;amp;gt; tag. Enum values are accessed as integers by the application but stored as string in the configuration file. This makes it possible to add more values at a later date without breaking compatibility.&lt;br /&gt;
*#* IntList - This indicates a list of integers. This information is provided to the application as QValueList&amp;amp;lt;int&amp;amp;gt;. Useful for storing QSplitter geometries.&lt;br /&gt;
*#* PathList - List of Path elements.&lt;br /&gt;
*# The min and max tags can be set to limit the value of the integer-type options.&lt;br /&gt;
*#''An entry can optionally have a default value which is used as default when the value isn't specified in any config file. Default values are interpreted as literal constant values. If a default value needs to be computed or if it needs to be obtained from a function call, the &amp;amp;lt;default&amp;amp;gt; tag should contain the code=&amp;quot;true&amp;quot; attribute. The contents of the &amp;amp;lt;default&amp;amp;gt; tag is then considered to be a C++ expression. ''&lt;br /&gt;
*#''Additional code for computing default values can be provided via the &amp;amp;lt;code&amp;amp;gt; tag. The contents of the &amp;amp;lt;code&amp;amp;gt; tag is inserted as-is. A typical use for this is to compute a common default value which can then be referenced by multiple entries that follow.''&lt;br /&gt;
*#''Optionally, the hidden option can also be added to the &amp;amp;lt;entry&amp;amp;gt;. The possible values are true and false.''&lt;br /&gt;
&lt;br /&gt;
== .kcfgc files ==&lt;br /&gt;
&lt;br /&gt;
After creating a {{path|.kcfg}} file create a {{path|.kcfgc}} file which describes the C++ file &lt;br /&gt;
generation options. The .kcfgc file is a simple ini file with the typical &lt;br /&gt;
&amp;quot;entry=value&amp;quot; format. To create a simple .kcfgc file follow these steps:&lt;br /&gt;
&lt;br /&gt;
# Open a new file in your favorite text editor.&lt;br /&gt;
# Start it with the &amp;quot;File=your_application_name.kcfg&amp;quot; entry which specifies where the configuration options for your application are stored.&lt;br /&gt;
# Add the &amp;quot;ClassName=YourConfigClassName&amp;quot; entry which specifies the name of the class that will be generated from the .kcfg file. Remember that the generated class will be derived from KConfigSkeleton. PLease make sure that YourConfigClassName is not a class name already used in your application. Save this file under {{path|yourconfigclassname.kcfgc.}} This will ensure the generation of the yourconfigclassname.{h,cpp} files where your configuration class will reside. &lt;br /&gt;
# Add any additional entries, which your application might need. Those additional entries include:&lt;br /&gt;
#* NameSpace - specifies the namespace in which the generated config class should reside,&lt;br /&gt;
#* Inherits - if you need the generated class to inherit your custom class,&lt;br /&gt;
#* Singleton - if the configuration class should be a singleton,&lt;br /&gt;
#* MemberVariables - specifies the access to the member variables, default is private,&lt;br /&gt;
#* ItemAccessors - relates to the above item, if member variables are public then it might make little sense to generate accessors. By default they are generated,&lt;br /&gt;
#* Mutators - similar to the above one, but applies to the mutator methods,&lt;br /&gt;
#* GlobalEnums - specifies whether enums should be class wide of whether they should be always explicitly prefixed with their type name,&lt;br /&gt;
#* UseEnumTypes - specifies whether enum values should be passed as type int or as their enum type in the return value of accessor functions and the arguments of mutator and signal functions.&lt;br /&gt;
&lt;br /&gt;
== Adjusting the CMakeLists.txt file ==&lt;br /&gt;
&lt;br /&gt;
After creating the .kcfg and .kcfgc files the next step is to adjust the &lt;br /&gt;
build to let kconfig_compiler generate the required class at compile time. Fortunately doing this is trivial and requires only one step, adding this line to the CMakeLists.txt file example:&lt;br /&gt;
&lt;br /&gt;
 kde4_add_kcfg_files(&amp;lt;project name&amp;gt;_SRCS settings.kcfgc)&lt;br /&gt;
&lt;br /&gt;
Alternatively, if a .moc file needs to be generated before compiling the generated source code, use&lt;br /&gt;
&lt;br /&gt;
 kde4_add_kcfg_files(&amp;lt;project name&amp;gt;_SRCS GENERATE_MOC settings.kcfgc)&lt;br /&gt;
&lt;br /&gt;
This assures that the configuration class is properly generated and that the .kcfg is installed so it can be used by tools like &lt;br /&gt;
the KConfigEditor.&lt;br /&gt;
&lt;br /&gt;
== Use and Dialogs ==&lt;br /&gt;
&lt;br /&gt;
After making all of the above changes you're ready to use KConfig XT. The &lt;br /&gt;
kconfig_compiler generated header file will have the name equal to the name of the .kcfg file but with a &amp;quot;.h&amp;quot; extension. Simply include that file wherever you want to access your configuration options.&lt;br /&gt;
&lt;br /&gt;
The use will depend on whether you have added the &amp;lt;tt&amp;gt;Singleton=true&amp;lt;/tt&amp;gt; entry to your .kcfgc file. &lt;br /&gt;
&lt;br /&gt;
One the nicest features of the KConfig XT is its seamless integration with the Qt &lt;br /&gt;
Designer generated dialogs. You can do that by using {{class|KConfigDialog}}. The &lt;br /&gt;
steps to do that are as follows: &lt;br /&gt;
&lt;br /&gt;
# Create the KConfigDialog and pass the instance of your configuration data as one of the arguments. The construct would look like the following example:&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;code cppqt&amp;gt;&lt;br /&gt;
KConfigDialog* dialog = new KConfigDialog( &lt;br /&gt;
         this, &amp;quot;settings&amp;quot;, YourAppSettings::self() );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
assuming that YourAppSettings is the value of the ClassName variable from the kcfgc file and the settings class is a singelton.&lt;br /&gt;
# In Qt Designer create widgets which should be used to configure your options. In order to make those widgets interact with the kcfg you have name each one of them using the following scheme:&lt;br /&gt;
## Prefix the Name of the widget which should control one of the options with &amp;quot;kcfg_&amp;quot;&lt;br /&gt;
## Append the &amp;quot;name&amp;quot; attribute value from your kcfg file which corresponds to option the given widget should control.&lt;br /&gt;
# Add the Qt Designer generated widget to the KConfigDialog.&lt;br /&gt;
# Show the dialog when you're done.&lt;br /&gt;
&lt;br /&gt;
== Example ==&lt;br /&gt;
&lt;br /&gt;
Here's an example usage of KConfig XT for the application named Example.&lt;br /&gt;
With the following example.kcfg file: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE kcfg SYSTEM &lt;br /&gt;
    &amp;quot;http://www.kde.org/standards/kcfg/1.0/kcfg.dtd&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;kcfg&amp;gt; &amp;lt;kcfgfile name=&amp;quot;examplerc&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;group name=&amp;quot;network&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;entry name=&amp;quot;ServerName&amp;quot; type=&amp;quot;String&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;label&amp;gt;Defines the sample server.&amp;lt;/label&amp;gt;&lt;br /&gt;
    &amp;lt;/entry&amp;gt;&lt;br /&gt;
    &amp;lt;entry name=&amp;quot;Port&amp;quot; type=&amp;quot;Int&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;label&amp;gt;Defines the server port&amp;lt;/label&amp;gt;&lt;br /&gt;
      &amp;lt;default&amp;gt;21&amp;lt;/default&amp;gt;&lt;br /&gt;
      &amp;lt;min&amp;gt;20&amp;lt;/min&amp;gt;&lt;br /&gt;
      &amp;lt;max&amp;gt;990&amp;lt;/max&amp;gt;&lt;br /&gt;
    &amp;lt;/entry&amp;gt;&lt;br /&gt;
  &amp;lt;/group&amp;gt;&lt;br /&gt;
&amp;lt;/kcfg&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And here's how to actually use the generated class. for the given kcfgc file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code ini&amp;gt;&lt;br /&gt;
File=example.kcfg &lt;br /&gt;
ClassName=ExampleSettings &lt;br /&gt;
Singleton=true &lt;br /&gt;
Mutators=true&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The header files wouldn't change, but the cpp files must now contain the &lt;br /&gt;
following code to access and store the configuration data :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
#include &amp;lt;ExampleSettings.h&amp;gt; &lt;br /&gt;
... &lt;br /&gt;
void ExampleClass::readConfig() { &lt;br /&gt;
        m_server  = ExampleSettings::serverName(); &lt;br /&gt;
        m_port    = ExampleSettings::port(); &lt;br /&gt;
} &lt;br /&gt;
void ExampleClass:saveSettings() { &lt;br /&gt;
        ExampleSettings::setServerName( m_server ); &lt;br /&gt;
        ExampleSettings::setPort( m_port ); &lt;br /&gt;
        ExampleSettings::writeConfig(); &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To add a dialog you need to create a Qt Designer widget with the widget names&lt;br /&gt;
corresponding to the names of the options they should edit and prefixed with &amp;quot;kcfg_&amp;quot;. &lt;br /&gt;
It could be something along the lines of:&lt;br /&gt;
&lt;br /&gt;
[[Image:kconfigxt.png|center|256px]]&lt;br /&gt;
&lt;br /&gt;
And you can use the dialog with the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt&amp;gt;&lt;br /&gt;
//An instance of your dialog could be already created and could be&lt;br /&gt;
// cached, in which case you want to display the cached dialog &lt;br /&gt;
// instead of creating another one&lt;br /&gt;
if ( KConfigDialog::showDialog( &amp;quot;settings&amp;quot; ) )&lt;br /&gt;
  return; &lt;br /&gt;
 &lt;br /&gt;
// KConfigDialog didn't find an instance of this dialog, so lets&lt;br /&gt;
// create it : &lt;br /&gt;
KConfigDialog* dialog = new KConfigDialog(this, &amp;quot;settings&amp;quot;,&lt;br /&gt;
                                          ExampleSettings::self()); &lt;br /&gt;
ExampleDesignerWidget* confWdg =  &lt;br /&gt;
                  new ExampleDesignerWidget( 0, &amp;quot;Example&amp;quot; ); &lt;br /&gt;
 &lt;br /&gt;
dialog-&amp;gt;addPage( confWdg, i18n(&amp;quot;Example&amp;quot;), &amp;quot;example&amp;quot; ); &lt;br /&gt;
 &lt;br /&gt;
//User edited the configuration - update your local copies of the &lt;br /&gt;
//configuration data &lt;br /&gt;
connect( dialog, SIGNAL(settingsChanged()), &lt;br /&gt;
         this, SLOT(updateConfiguration()) ); &lt;br /&gt;
 &lt;br /&gt;
dialog-&amp;gt;show();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And that's all it takes. You can have a look at [http://websvn.kde.org/trunk/KDE/kdegames/kreversi KReversi] and [http://websvn.kde.org/trunk/KDE/kdegames/ktron/ KTron] code in the [http://websvn.kde.org/trunk/KDE/kdegames kdegames module] to see a live example of KConfig XT!&lt;br /&gt;
&lt;br /&gt;
== Common Pitfalls and Tips ==&lt;br /&gt;
&lt;br /&gt;
* Do not forget to add the &amp;quot;type&amp;quot; attribute to the &amp;quot;entry&amp;quot; tag in your .kcfg file.&lt;br /&gt;
* Always try to add both the &amp;amp;lt;label&amp;amp;gt; and &amp;amp;lt;whatsthis&amp;amp;gt; tags to each entry.&lt;br /&gt;
* Putting the MemberVariables=public in your .kcfgc is usually a bad idea - you'll avoid accidental changes to those members by using the aggregation and forcing the use of the mutators.&lt;br /&gt;
* If your application doesn't have one central object (created before and destructed after; all others) then always put the Singleton=true entry in your .kcfgs file.&lt;br /&gt;
[[Category:C++]]&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials/KConfig</id>
		<title>Development/Tutorials/KConfig</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials/KConfig"/>
				<updated>2007-12-31T14:41:21Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:I18n/Language Navigation Bar|Development/Tutorials/KConfig}}&lt;br /&gt;
{{TutorialBrowser|&lt;br /&gt;
&lt;br /&gt;
series=KConfig|&lt;br /&gt;
&lt;br /&gt;
name=Introduction to KConfig|&lt;br /&gt;
&lt;br /&gt;
next=[[../Using_KConfig_XT|Using KConfig XT]]&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Abstract ==&lt;br /&gt;
&lt;br /&gt;
This tutorial looks at the KDE configuration data system, starting with an overview of the design fundamentals from an application developer's point of view. It then looks at the classes relevant to application development one by one before moving on to kiosk (user and group profiles) integration.&lt;br /&gt;
&lt;br /&gt;
== Design Essentials ==&lt;br /&gt;
&lt;br /&gt;
KConfig is designed to abstract away the concept of actual storage and retrieval of configuration settings behind an API that allows easy fetching and setting of information. Where and in what format the data is stored is not relevant to an application using KConfig. This keeps all KDE applications consistent in their handling of configurations while alleviating each and every application author to build such a system on their own from scratch, which can be a highly error prone exercise.&lt;br /&gt;
&lt;br /&gt;
A KConfig object represents a single configuration object. Each configuration object is referenced by its unique name and may be actually read from multiple local or remote files or services. Each application has a default configuration object associated with it and there is also a global configuration object.&lt;br /&gt;
&lt;br /&gt;
These configuration objects are broken down into a two level hierarchy: groups and keys. A configuration object can have any number of groups and each group can have one or more keys with associated values.&lt;br /&gt;
&lt;br /&gt;
Values stored may be of any number of data types. They are stored and retreived as the objects themselves. For example, a {{qt|QObject}} object is passed to a config object directly when storing a color value and when retreived a {{qt|QObject}} object is returned. Applications themselves therefore generally do not have to perform serialization and deserialization of objects themselves.&lt;br /&gt;
&lt;br /&gt;
== The KConfig Class ==&lt;br /&gt;
&lt;br /&gt;
The {{class|KConfig}} object is used to access a given configuration object. There are a number of ways to create a config object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
// a plain old read/write config object&lt;br /&gt;
KConfig config(&amp;quot;myapprc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// a specific file in the filesystem&lt;br /&gt;
// currently must be an INI style file&lt;br /&gt;
KConfig fullPath(&amp;quot;/etc/kderc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// not merged with global values&lt;br /&gt;
KConfig globalFree( &amp;quot;localsrc&amp;quot;, KConfig::NoGlobals );&lt;br /&gt;
&lt;br /&gt;
// not merged with globals or the $KDEDIRS hierarchy&lt;br /&gt;
KConfig simpleConfig( &amp;quot;simplerc&amp;quot;, KConfig::SimpleConfig );&lt;br /&gt;
&lt;br /&gt;
// config specific to a component, in this case a plugin&lt;br /&gt;
KConfig pluginConfig( componentData(), &amp;quot;pluginrc&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
// outside the standard config resource&lt;br /&gt;
KConfig dataResource( &amp;quot;data&amp;quot;, &amp;quot;myapp/somefile&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The KConfig object create on line 2 is a regular config object. We can read values from it, write new entries and ask for various properties of the object.  This object will be loaded from the config resource as determined by {{class|KStandardDirs}}, meaning that every instance of the &amp;lt;tt&amp;gt;myapprc&amp;lt;/tt&amp;gt; object in each of the directories in the config resource hierarchy will be merged to create the values seen in this object. This is how system wide and per-user/group profiles are generated and supported and it all happens transparently to the application itself.&lt;br /&gt;
&lt;br /&gt;
{{tip|For more information on how the merging works, see the [[KDE System Administration/KDE_Filesystem_Hierarchy|KDE Filesystem Hierarchy]] article.}}&lt;br /&gt;
&lt;br /&gt;
On line 6 we open a specific local file, this case {{path|/etc/kderc}}. This performs no merging of values and expects an INI style file.&lt;br /&gt;
&lt;br /&gt;
Line 9 sees the creation of a configuration object that is not merged with the global &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt; configuration object, while the configuration file on line 12 is additionally not merged with any files in the &amp;lt;tt&amp;gt;$KDEDIRS&amp;lt;/tt&amp;gt; hierarchy. This can noticeably improve performance in the case where one is simply reading values out of a simple configuration for which global values are not meaningful.&lt;br /&gt;
&lt;br /&gt;
Line 15 creates a configuration object using the {{class|KComponentData}} object that belongs to a plugin or other component. The plugin may have a different set of directories defined in its {{class|KStandardDirs}} and this is a way of ensuring that {{class|KConfig}} respects this.&lt;br /&gt;
&lt;br /&gt;
Finally on line 18 we see the creation of a configuration object that does not exist in the &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; resource but rather in the application &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; resource. You may use any resource that {{class|KStandardDirs}} is aware of, including ones that are added at runtime.&lt;br /&gt;
&lt;br /&gt;
=== Special Configuration Objects ===&lt;br /&gt;
&lt;br /&gt;
Each application has its own configuration object that uses the name provided to {{class|KAboutData}} appended with &amp;quot;rc&amp;quot; as its name. So an app named &amp;quot;myapp&amp;quot; would have the default configuration object of &amp;quot;myapprc&amp;quot;. This configuration file can be retrieved in this way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KComponentData&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
#include &amp;lt;KGlobal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    // note that this is actually a KSharedConfig&lt;br /&gt;
    // more on that class in a bit!&lt;br /&gt;
    KConfig* config = KGlobal::config();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The default configuration object for the application is accessed when no name is specified when creating a {{class|KConfig}} object. So we could also do this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KConfig&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyClass::MyClass()&lt;br /&gt;
{&lt;br /&gt;
    KConfig config;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additionally, each component may have its own configuration object. This is generally accessed via the plugin's &amp;lt;tt&amp;gt;componentData()&amp;lt;/tt&amp;gt; rather than &amp;lt;tt&amp;gt;{{class|KGlobal}}::mainComponent()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Finally there is a global configuration object, &amp;lt;tt&amp;gt;kdeglobals&amp;lt;/tt&amp;gt;, that is shared by every application. It holds such information as the default application shortcuts for various actions. It is &amp;quot;blended&amp;quot; into the configuration object if the &amp;lt;tt&amp;gt;KConfig::IncludeGlobals&amp;lt;/tt&amp;gt; flag is passed to the {{class|KConfig}} constructor, which is the default.&lt;br /&gt;
&lt;br /&gt;
=== Commonly Useful Methods ===&lt;br /&gt;
&lt;br /&gt;
To save the current state of the configuration object we call the &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; method. This method is also called when the object is destroyed. If no changes have been made or the resource reports itself as non-writable (such as in the case of the user not having write permissions to the file) then no disk activity occurs. &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; merges changes performed concurrently by other processes - local changes have priority, though.&lt;br /&gt;
&lt;br /&gt;
If we want to make sure that we have the latest values from disk we can call &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt; which calls &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; and then reloads the data from disk.&lt;br /&gt;
&lt;br /&gt;
If we need to prevent the config object from saving already made modifications to disk we need to call &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt;. A particular use case for this is rolling back the configuration to the on-disk state by calling &amp;lt;tt&amp;gt;markAsClean()&amp;lt;/tt&amp;gt; followed by &amp;lt;tt&amp;gt;reparseConfiguration()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Listing all groups in a configuration object is as simple as calling &amp;lt;tt&amp;gt;groupList()&amp;lt;/tt&amp;gt; as in this code snippet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::mainComponent().config();&lt;br /&gt;
&lt;br /&gt;
foreach ( const QString&amp;amp; group, config.groupList() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;next group:&amp;quot; &amp;lt;&amp;lt; group;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== KSharedConfig ==&lt;br /&gt;
&lt;br /&gt;
The {{class|KSharedConfig}} class is a reference counted version of {{class|KConfig}}. It thus provides a way to reference the same configuration object from multiple places in your application without the extra overhead of separate objects or concerns about syncronizing writes to disk even if the configuration object is updated from multiple code paths. &lt;br /&gt;
&lt;br /&gt;
Accessing a {{class|KSharedConfig}} object is as easy as this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KSharedConfigPtr config = KSharedConfig::openConfig();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;openConfig()&amp;lt;/tt&amp;gt; take the same parameters as {{class|KConfig}}'s constructors do, allowing one to define which configuration file to open, flags to control merging and non-&amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; resources.&lt;br /&gt;
&lt;br /&gt;
{{class|KSharedConfig}} is generally recommended over using {{class|KConfig}} itself, and the object returned from {{class|KComponentData}} is indeed a {{class|KSharedConfig}} object.&lt;br /&gt;
&lt;br /&gt;
== KConfigGroup ==&lt;br /&gt;
&lt;br /&gt;
Now that we have a configuration object, the next step is to actually use it. The first thing we must do is to define which group of key/value pairs we wish to access in the object. We do this by creating a KConfigGroup object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig config;&lt;br /&gt;
KConfigGroup generalGroup( &amp;amp;config, &amp;quot;General&amp;quot; );&lt;br /&gt;
KConfigGroup colorsGroup = config.group( &amp;quot;Colors&amp;quot; ); // ... or a bit differently ...&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can pass {{class|KConfig}} or {{class|KSharedConfig}} objects to {{class|KConfigGroup}}.&lt;br /&gt;
&lt;br /&gt;
Config groups can be nested as well:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfigGroup subGroup1( &amp;amp;generalGroup, &amp;quot;LessGeneral&amp;quot; );&lt;br /&gt;
KConfigGroup subGroup2 = colorsGroup.group( &amp;quot;Dialogs&amp;quot; );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Reading Entries ==&lt;br /&gt;
&lt;br /&gt;
With a {{class|KConfigGroup}} object in hand reading entries is now quite straight forward:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
QString accountName = generalGroup.readEntry( &amp;quot;Account&amp;quot;,&lt;br /&gt;
                                              QString() );&lt;br /&gt;
QColor color = colorsGroup.readEntry( &amp;quot;background&amp;quot;,&lt;br /&gt;
                                      Qt::white );&lt;br /&gt;
QStringList list = generalGroup.readEntry( &amp;quot;List&amp;quot;,&lt;br /&gt;
                                           QStringList() );&lt;br /&gt;
QString path = generalGroup.readPathEntry( &amp;quot;SaveTo&amp;quot;,&lt;br /&gt;
                                           defaultPath );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As can be seen from the above, you can mix reads from different {{class|KConfigGroup}} objects created on the same {{class|KConfig}} object. The read methods take the key, which is case sensitive, as the first argument and the default value as the second argument. This argument controls what kind of data, e.g. a color in line 3 above, is to be expected as well as the type of object returned. The returned object is wrapped in a {{qt|QVariant}} to make this magic happen.&lt;br /&gt;
&lt;br /&gt;
There are a couple of special read methods, including &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; which returns a file system path. It is vital that one uses &amp;lt;tt&amp;gt;readPathEntry&amp;lt;/tt&amp;gt; if it is a path as this enables such features as roaming profiles to work properly.&lt;br /&gt;
&lt;br /&gt;
If no such key currently exists in the configuration object, the default value is returned instead. If there is a localized (e.g. translated into another language) entry for the key that matches the current locale, that is returned.&lt;br /&gt;
&lt;br /&gt;
== Writing Entries ==&lt;br /&gt;
&lt;br /&gt;
Setting new values is similarly straightforward:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
generalGroup.writeEntry( &amp;quot;Account&amp;quot;, accountName );&lt;br /&gt;
generalGroup.writePathEntry( &amp;quot;SaveTo&amp;quot;, savePath );&lt;br /&gt;
colorGroup.writeEntry( &amp;quot;background&amp;quot;, color );&lt;br /&gt;
generalGroup.config()-&amp;gt;sync();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note the use of &amp;lt;tt&amp;gt;writePathEntry&amp;lt;/tt&amp;gt; and how the type of object we use, such as {{qt|QColor}} on line 3, dictates how the data is serialized. Additionally, once we are done writing entries, &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; must be called on the config object for it to be saved to disk. We can also simply wait for the object to be destroyed, which triggers an automatic &amp;lt;tt&amp;gt;sync()&amp;lt;/tt&amp;gt; if necessary.&lt;br /&gt;
&lt;br /&gt;
== KDesktopFile: A Special Case ==&lt;br /&gt;
&lt;br /&gt;
When is a configuration file not a configuration file? When it is a [http://freedesktop.org/wiki/Standards_2fdesktop_2dentry_2dspec desktop file]. These files, which are essentially configuration files at their heart, are used  to describe entries for application menus, mimetypes, plugins and various services.&lt;br /&gt;
&lt;br /&gt;
When accessing a .desktop file, one should instead use the {{class|KDesktopFile}} class which, while a {{class|KConfig}} class offering all the capabilities described above, offers a set of methods designed to make accessing standard attributes of these files consistent and reliable.&lt;br /&gt;
&lt;br /&gt;
== Kiosk: Lockdown and User/Group Profiles ==&lt;br /&gt;
&lt;br /&gt;
KConfig provides a powerful set of lockdown and configuration definition capabilities, collectively known as &amp;quot;Kiosk&amp;quot;, that many system administrators and system integrators rely on. While most of this framework is provided transparently to the application, there is occassion when an application will want to check on the read/write status of a configuration object.&lt;br /&gt;
&lt;br /&gt;
Entries in configuration objects that are locked down using the kiosk facilities are said to be ''immutable''. An application can check for immutability of entire configuration objects, groups or keys as shown in this example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
KConfig* config = KGlobal::config();&lt;br /&gt;
&lt;br /&gt;
if ( config-&amp;gt;isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;configuration object is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
KConfigGroup group(config, &amp;quot;General&amp;quot;);&lt;br /&gt;
if ( group.isImmutable() ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;group General is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if ( group.entryIsImmutable(&amp;quot;URL&amp;quot;) ) {&lt;br /&gt;
    kDebug() &amp;lt;&amp;lt; &amp;quot;URL entry in group General is immutable&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This can be useful in particular situations where an action should be taken when an item is immutable. For instance, the KDE panels will not offer configuration options to the user or allow them to otherwise change the order of applets and icons when the panel's configuration object is marked as immutable.&lt;br /&gt;
&lt;br /&gt;
== KConfig XT ==&lt;br /&gt;
&lt;br /&gt;
There is a way to make certain use cases of KConfig easier, faster and more reliable: KConfig XT. In particular, for main application or plugin configuration objects and when syncing configuration dialogs and other interfaces with these values, KConfig XT can help immensely. It also  simultaneously documents the configuration options available, which makes every sys admin and system integrator that uses KDE that much more happy.&lt;br /&gt;
&lt;br /&gt;
[[../Using_KConfig_XT|The next tutorial in the KConfig series covers what KConfig XT is and how to use it.]]&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/KDE_TechBase:Contributors</id>
		<title>KDE TechBase:Contributors</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/KDE_TechBase:Contributors"/>
				<updated>2007-12-31T14:37:06Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: /* German Team */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Welcome to the contributors page.&lt;br /&gt;
&lt;br /&gt;
'''This site contains a list of ''active'' contributors. It should help to build teams which maintain KDE TechBase's content. If you have questions about KDE TechBase you can ask/email the corresponding person.'''&lt;br /&gt;
&lt;br /&gt;
Please add yourself to the list where appropriate. If you are inactive, please remove yourself again.&lt;br /&gt;
&lt;br /&gt;
== Administrators ==&lt;br /&gt;
&lt;br /&gt;
This is a list of KDE TechBase administrators.&lt;br /&gt;
&lt;br /&gt;
* [[User:Danimo|Danimo]]&lt;br /&gt;
* [[User:Dhaumann|Dhaumann]], &amp;lt;dhaumann at kde dot org&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Reviewers and Article Writers ==&lt;br /&gt;
&lt;br /&gt;
If you are continuously reviewing KDE TechBase changes or writing articles add yourself to the list.&lt;br /&gt;
&lt;br /&gt;
* [[User:Dhaumann|Dhaumann]], &amp;lt;dhaumann at kde dot org&amp;gt;&lt;br /&gt;
* [[User:Milliams|Milliams]]&lt;br /&gt;
* name, &amp;lt;email&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Translation Teams ==&lt;br /&gt;
&lt;br /&gt;
KDE TechBase is [[Help:Wiki Translation|translated]] into many languages. If you translate pages please add yourself to the right translation team.&lt;br /&gt;
&lt;br /&gt;
=== Chinese(simplified) Team ===&lt;br /&gt;
* [[User:Liangqi|Liangqi]], cavendish.qi at gmail dot com&lt;br /&gt;
* name, &amp;lt;email&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Spanish Team ===&lt;br /&gt;
* [[User:Mjp ttc|Mjp ttc]], mjp_ttc at yahoo dot com&lt;br /&gt;
* name, &amp;lt;email&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== German Team ===&lt;br /&gt;
* [[User:DrSlowDecay|DrSlowDecay]], kde at metalhorde dot de&lt;br /&gt;
* [[User:Rememberme|rememberme]] redict dot info at gmx dot net&lt;br /&gt;
* name, &amp;lt;email&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Italian Team ===&lt;br /&gt;
* [[User:Thunder Teaser|Thunder Teaser]], totokid at gmail dot com&lt;br /&gt;
* name, &amp;lt;email&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ... Team ===&lt;br /&gt;
* name, &amp;lt;email&amp;gt;&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/User:Rememberme</id>
		<title>User:Rememberme</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/User:Rememberme"/>
				<updated>2007-12-31T14:36:37Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: New page: Translating some Documentation to German.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Translating some Documentation to German.&lt;/div&gt;</summary>
		<author><name>Rememberme</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials/KCmdLineArgs_(de)</id>
		<title>Development/Tutorials/KCmdLineArgs (de)</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials/KCmdLineArgs_(de)"/>
				<updated>2007-12-31T13:28:05Z</updated>
		
		<summary type="html">&lt;p&gt;Rememberme: New page: {{Template:I18n/Language Navigation Bar|Development/Tutorials/KCmdLineArgs}}  {{TutorialBrowser|  series=Anleitung für Anfänger|  name=Befehlszeilen Argumente (Under construction)|  pre=...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:I18n/Language Navigation Bar|Development/Tutorials/KCmdLineArgs}}&lt;br /&gt;
&lt;br /&gt;
{{TutorialBrowser|&lt;br /&gt;
&lt;br /&gt;
series=Anleitung für Anfänger|&lt;br /&gt;
&lt;br /&gt;
name=Befehlszeilen Argumente (Under construction)|&lt;br /&gt;
&lt;br /&gt;
pre=[[Development/Tutorials/Saving and loading (de)|Anleitung 4 - Laden und Speichern von Dateien]]|&lt;br /&gt;
&lt;br /&gt;
next=[[Development/Tutorials/###|Tutorial 6 - ###]])| &lt;br /&gt;
&lt;br /&gt;
reading={{class|KCmdLineArgs}} {{class|KCmdLineOptions}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Zusammenfassung==&lt;br /&gt;
&lt;br /&gt;
In diesem Kapitel werden sie lernen ihrer Anwendung zu ermöglichen, Dateien über die Befehlszeile zu öffnen oder sogar mit 'Öffnen mit' von Dolphin aus zu verwenden.&lt;br /&gt;
&lt;br /&gt;
[[image:introtokdetutorial5.png|frame|center]]&lt;br /&gt;
&lt;br /&gt;
== The Code ==&lt;br /&gt;
&lt;br /&gt;
===main.cpp===&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;lt;KApplication&amp;gt;&lt;br /&gt;
#include &amp;lt;KAboutData&amp;gt;&lt;br /&gt;
#include &amp;lt;KCmdLineArgs&amp;gt;&lt;br /&gt;
#include &amp;lt;KUrl&amp;gt; //new&lt;br /&gt;
 &lt;br /&gt;
#include &amp;quot;mainwindow.h&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
int main (int argc, char *argv[])&lt;br /&gt;
{&lt;br /&gt;
  KAboutData aboutData( &amp;quot;tutorial5&amp;quot;, &amp;quot;tutorial5&amp;quot;,&lt;br /&gt;
      ki18n(&amp;quot;Tutorial 5&amp;quot;), &amp;quot;1.0&amp;quot;,&lt;br /&gt;
      ki18n(&amp;quot;A simple text area which can load and save.&amp;quot;),&lt;br /&gt;
      KAboutData::License_GPL,&lt;br /&gt;
      ki18n(&amp;quot;Copyright (c) 2007 Developer&amp;quot;) );&lt;br /&gt;
  KCmdLineArgs::init( argc, argv, &amp;amp;aboutData );&lt;br /&gt;
&lt;br /&gt;
  KCmdLineOptions options; //new&lt;br /&gt;
  options.add(&amp;quot;+[file]&amp;quot;, ki18n(&amp;quot;Document to open&amp;quot;)); //new&lt;br /&gt;
  KCmdLineArgs::addCmdLineOptions(options); //new&lt;br /&gt;
&lt;br /&gt;
  KApplication app;&lt;br /&gt;
 &lt;br /&gt;
  MainWindow* window = new MainWindow();&lt;br /&gt;
  window-&amp;gt;show();&lt;br /&gt;
&lt;br /&gt;
  KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); //new&lt;br /&gt;
  if(args-&amp;gt;count()) //new&lt;br /&gt;
  {&lt;br /&gt;
    window-&amp;gt;openFile(args-&amp;gt;url(0).url()); //new&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return app.exec();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===mainwindow.h===&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#ifndef MAINWINDOW_H&lt;br /&gt;
#define MAINWINDOW_H&lt;br /&gt;
 &lt;br /&gt;
#include &amp;lt;KXmlGuiWindow&amp;gt;&lt;br /&gt;
#include &amp;lt;KTextEdit&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
class MainWindow : public KXmlGuiWindow&lt;br /&gt;
{&lt;br /&gt;
  Q_OBJECT&lt;br /&gt;
  &lt;br /&gt;
  public:&lt;br /&gt;
    MainWindow(QWidget *parent=0);&lt;br /&gt;
    void openFile(const QString &amp;amp;inputFileName); //new&lt;br /&gt;
  &lt;br /&gt;
  private:&lt;br /&gt;
    KTextEdit* textArea;&lt;br /&gt;
    void setupActions();&lt;br /&gt;
    QString fileName;&lt;br /&gt;
 &lt;br /&gt;
  private slots:&lt;br /&gt;
    void newFile();&lt;br /&gt;
    void openFile();&lt;br /&gt;
    void saveFile();&lt;br /&gt;
    void saveFileAs();&lt;br /&gt;
    void saveFileAs(const QString &amp;amp;outputFileName);&lt;br /&gt;
};&lt;br /&gt;
 &lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===mainwindow.cpp===&lt;br /&gt;
&amp;lt;code cppqt n&amp;gt;&lt;br /&gt;
#include &amp;quot;mainwindow.h&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
#include &amp;lt;KApplication&amp;gt;&lt;br /&gt;
#include &amp;lt;KAction&amp;gt;&lt;br /&gt;
#include &amp;lt;KLocale&amp;gt;&lt;br /&gt;
#include &amp;lt;KActionCollection&amp;gt;&lt;br /&gt;
#include &amp;lt;KStandardAction&amp;gt;&lt;br /&gt;
#include &amp;lt;KFileDialog&amp;gt;&lt;br /&gt;
#include &amp;lt;KMessageBox&amp;gt;&lt;br /&gt;
#include &amp;lt;KIO/NetAccess&amp;gt;&lt;br /&gt;
#include &amp;lt;KSaveFile&amp;gt;&lt;br /&gt;
#include &amp;lt;QTextStream&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
MainWindow::MainWindow(QWidget *parent)&lt;br /&gt;
    : KXmlGuiWindow(parent),&lt;br /&gt;
      fileName(QString())&lt;br /&gt;
{&lt;br /&gt;
  textArea = new KTextEdit;&lt;br /&gt;
  setCentralWidget(textArea);&lt;br /&gt;
 &lt;br /&gt;
  setupActions();&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
void MainWindow::setupActions()&lt;br /&gt;
{&lt;br /&gt;
  KAction* clearAction = new KAction(this);&lt;br /&gt;
  clearAction-&amp;gt;setText(i18n(&amp;quot;Clear&amp;quot;));&lt;br /&gt;
  clearAction-&amp;gt;setIcon(KIcon(&amp;quot;document-new&amp;quot;));&lt;br /&gt;
  clearAction-&amp;gt;setShortcut(Qt::CTRL + Qt::Key_W);&lt;br /&gt;
  actionCollection()-&amp;gt;addAction(&amp;quot;clear&amp;quot;, clearAction);&lt;br /&gt;
  connect(clearAction, SIGNAL(triggered(bool)),&lt;br /&gt;
          textArea, SLOT(clear()));&lt;br /&gt;
 &lt;br /&gt;
  KStandardAction::quit(kapp, SLOT(quit()),&lt;br /&gt;
                        actionCollection());&lt;br /&gt;
 &lt;br /&gt;
  KStandardAction::open(this, SLOT(openFile()),&lt;br /&gt;
                        actionCollection());&lt;br /&gt;
 &lt;br /&gt;
  KStandardAction::save(this, SLOT(saveFile()),&lt;br /&gt;
                        actionCollection());&lt;br /&gt;
 &lt;br /&gt;
  KStandardAction::saveAs(this, SLOT(saveFileAs()),&lt;br /&gt;
                        actionCollection());&lt;br /&gt;
 &lt;br /&gt;
  KStandardAction::openNew(this, SLOT(newFile()),&lt;br /&gt;
                        actionCollection());&lt;br /&gt;
 &lt;br /&gt;
  setupGUI();&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
void MainWindow::newFile()&lt;br /&gt;
{&lt;br /&gt;
  fileName.clear();&lt;br /&gt;
  textArea-&amp;gt;clear();&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
void MainWindow::saveFileAs(const QString &amp;amp;outputFileName)&lt;br /&gt;
{&lt;br /&gt;
  KSaveFile file(outputFileName);&lt;br /&gt;
  file.open();&lt;br /&gt;
  &lt;br /&gt;
  QByteArray outputByteArray;&lt;br /&gt;
  outputByteArray.append(textArea-&amp;gt;toPlainText());&lt;br /&gt;
  file.write(outputByteArray);&lt;br /&gt;
  file.finalize();&lt;br /&gt;
  file.close();&lt;br /&gt;
  &lt;br /&gt;
  fileName = outputFileName;&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
void MainWindow::saveFileAs()&lt;br /&gt;
{&lt;br /&gt;
  saveFileAs(KFileDialog::getSaveFileName());&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
void MainWindow::saveFile()&lt;br /&gt;
{&lt;br /&gt;
  if(!fileName.isEmpty())&lt;br /&gt;
  {&lt;br /&gt;
    saveFileAs(fileName);&lt;br /&gt;
  }&lt;br /&gt;
  else&lt;br /&gt;
  {&lt;br /&gt;
    saveFileAs();&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
void MainWindow::openFile() //changed&lt;br /&gt;
{&lt;br /&gt;
  openFile(KFileDialog::getOpenFileName());&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void MainWindow::openFile(const QString &amp;amp;inputFileName) //new&lt;br /&gt;
{&lt;br /&gt;
  QString tmpFile;&lt;br /&gt;
  if(KIO::NetAccess::download(inputFileName, tmpFile, &lt;br /&gt;
         this))&lt;br /&gt;
  {&lt;br /&gt;
    QFile file(tmpFile);&lt;br /&gt;
    file.open(QIODevice::ReadOnly);&lt;br /&gt;
    textArea-&amp;gt;setPlainText(QTextStream(&amp;amp;file).readAll());&lt;br /&gt;
    fileName = inputFileName;&lt;br /&gt;
 &lt;br /&gt;
    KIO::NetAccess::removeTempFile(tmpFile);&lt;br /&gt;
  }&lt;br /&gt;
  else&lt;br /&gt;
  {&lt;br /&gt;
    KMessageBox::error(this, &lt;br /&gt;
        KIO::NetAccess::lastErrorString());&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===tutorial4ui.rc===&lt;br /&gt;
&amp;lt;code xml n&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE kpartgui SYSTEM &amp;quot;kpartgui.dtd&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;gui name=&amp;quot;tutorial5&amp;quot; version=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;ToolBar name=&amp;quot;mainToolBar&amp;quot; &amp;gt;&lt;br /&gt;
    &amp;lt;text&amp;gt;Main Toolbar&amp;lt;/text&amp;gt;&lt;br /&gt;
    &amp;lt;Action name=&amp;quot;clear&amp;quot; /&amp;gt;&lt;br /&gt;
  &amp;lt;/ToolBar&amp;gt;&lt;br /&gt;
  &amp;lt;MenuBar&amp;gt;&lt;br /&gt;
    &amp;lt;Menu name=&amp;quot;file&amp;quot; &amp;gt;&lt;br /&gt;
      &amp;lt;Action name=&amp;quot;clear&amp;quot; /&amp;gt;&lt;br /&gt;
    &amp;lt;/Menu&amp;gt;&lt;br /&gt;
  &amp;lt;/MenuBar&amp;gt;&lt;br /&gt;
&amp;lt;/gui&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Dies ist identisch mit &amp;lt;tt&amp;gt;tutorial'X'ui.rc&amp;lt;/tt&amp;gt; aus den letzten beiden Anleitungen ausser dass &amp;lt;tt&amp;gt;name&amp;lt;/tt&amp;gt; zu 'tutorial5' geändert wurde.&lt;br /&gt;
&lt;br /&gt;
==Erklärung==&lt;br /&gt;
&lt;br /&gt;
===mainwindow.h===&lt;br /&gt;
&lt;br /&gt;
Hier haben wir nichts weiteres gemacht als eine neue &amp;lt;tt&amp;gt;openFile&amp;lt;/tt&amp;gt; Funktion hinzuzufügen, die einen &amp;lt;tt&amp;gt;QString&amp;lt;/tt&amp;gt; annimmt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code cppqt&amp;gt;&lt;br /&gt;
void openFile(const QString &amp;amp;inputFileName);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===mainwindow.cpp===&lt;br /&gt;
&lt;br /&gt;
Hier gibt es keinen neuen Code, nur Umordnen. Alles aus &amp;lt;tt&amp;gt;void openFile()&amp;lt;/tt&amp;gt; wurde in &amp;lt;tt&amp;gt;void openFile(const QString &amp;amp;inputFileName)&amp;lt;/tt&amp;gt; verschoben, ausser der Aufruf an &amp;lt;tt&amp;gt;KFileDialog::getOpenFileName()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Auf diese Weise können wir &amp;lt;tt&amp;gt;openFile()&amp;lt;/tt&amp;gt; aufrufen, wenn wir einen Dialog anzeigen möchten, oder wir können &amp;lt;tt&amp;gt;openFile(QString)&amp;lt;/tt&amp;gt; aufrufen, falls wir den Namen der Datei bereits kennen.&lt;br /&gt;
&lt;br /&gt;
===main.cpp===&lt;br /&gt;
&lt;br /&gt;
Hier passiert die ganze {{class|KCmdLineArgs}} Hexerei.&lt;br /&gt;
&lt;br /&gt;
==Erzeugen, Installieren und Ausführen==&lt;br /&gt;
&lt;br /&gt;
===CMakeLists.txt===&lt;br /&gt;
&amp;lt;code ini n&amp;gt;&lt;br /&gt;
project(tutorial5)&lt;br /&gt;
 &lt;br /&gt;
find_package(KDE4 REQUIRED)&lt;br /&gt;
include_directories( ${KDE4_INCLUDES} )&lt;br /&gt;
 &lt;br /&gt;
set(tutorial5_SRCS &lt;br /&gt;
  main.cpp&lt;br /&gt;
  mainwindow.cpp&lt;br /&gt;
)&lt;br /&gt;
 &lt;br /&gt;
kde4_add_executable(tutorial5 ${tutorial5_SRCS})&lt;br /&gt;
 &lt;br /&gt;
target_link_libraries(tutorial5 ${KDE4_KDEUI_LIBS}&lt;br /&gt;
                                ${KDE4_KIO_LIBS})&lt;br /&gt;
 &lt;br /&gt;
install(TARGETS tutorial5 DESTINATION ${BIN_INSTALL_DIR})&lt;br /&gt;
install( FILES tutorial5ui.rc &lt;br /&gt;
         DESTINATION  ${DATA_INSTALL_DIR}/tutorial5 )&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mit dieser Datei kann die Anleitung auf die gleiche Weise erstellt und ausgeführt werden wie Anleitung 3 und 4. Für mehr Informationen siehe [[Development/Tutorials/Using KActions (de)|Anleitung 3]].&lt;br /&gt;
&lt;br /&gt;
 mkdir build &amp;amp;&amp;amp; cd build&lt;br /&gt;
 cmake .. -DCMAKE_INSTALL_PREFIX=$HOME&lt;br /&gt;
 make install&lt;br /&gt;
 $HOME/bin/tutorial5&lt;br /&gt;
&lt;br /&gt;
==Weiter Geht's==&lt;br /&gt;
Now you can move on to the ### (TODO [[User:milliams]]) tutorial.&lt;br /&gt;
&lt;br /&gt;
[[Category:C++]]&lt;/div