(Replaced references to QValueList with QList) |
m (Fix syntax highlighting.) |
||
| Line 38: | Line 38: | ||
Lets create a simple .kcfg file. Please reference the code below as we go through each step. | Lets create a simple .kcfg file. Please reference the code below as we go through each step. | ||
| − | < | + | <syntaxhighlight lang="xml"> |
<?xml version="1.0" encoding="UTF-8"?> | <?xml version="1.0" encoding="UTF-8"?> | ||
<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0" | <kcfg xmlns="http://www.kde.org/standards/kcfg/1.0" | ||
| Line 70: | Line 70: | ||
</group> | </group> | ||
</kcfg> | </kcfg> | ||
| − | </ | + | </syntaxhighlight> |
* 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). | * 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). | ||
| Line 117: | Line 117: | ||
After creating the .kcfg and .kcfgc files the next step is to adjust the | After creating the .kcfg and .kcfgc files the next step is to adjust the | ||
build to let kconfig_compiler generate the required class at compile time. For in-source builds, doing this is trivial and requires only one step, adding this two lines to the CMakeLists.txt file example (asuming your files are named settings.kcfg and settings.kcfgc): | build to let kconfig_compiler generate the required class at compile time. For in-source builds, doing this is trivial and requires only one step, adding this two lines to the CMakeLists.txt file example (asuming your files are named settings.kcfg and settings.kcfgc): | ||
| − | + | <pre> | |
| − | + | kde4_add_kcfg_files(<project name>_SRCS settings.kcfgc) | |
| − | + | install(FILES settings.kcfg DESTINATION ${KCFG_INSTALL_DIR}) | |
| − | + | </pre> | |
Alternatively, if a .moc file needs to be generated before compiling the generated source code, use | Alternatively, if a .moc file needs to be generated before compiling the generated source code, use | ||
| − | + | <pre> | |
| − | + | kde4_add_kcfg_files(<project name>_SRCS GENERATE_MOC settings.kcfgc) | |
| − | + | install(FILES settings.kcfg DESTINATION ${KCFG_INSTALL_DIR}) | |
| − | + | </pre> | |
| − | This assures that the configuration class is properly generated (kde4_add_kcfg_files) and that the .kcfg is installed so it can be used by tools like the KConfigEditor (install). | + | This assures that the configuration class is properly generated (<tt>kde4_add_kcfg_files</tt>) and that the .kcfg is installed so it can be used by tools like the KConfigEditor (<tt>install</tt>). |
=== out-of-source builds === | === out-of-source builds === | ||
| Line 132: | Line 132: | ||
Out-of-source builds require one more step. | Out-of-source builds require one more step. | ||
| − | '''The problem:''' In out-of-source builds, the code that is generated by kconfig_compiler is saved in the build tree. So how can we still include the header generated by kconfig_compiler with a simple | + | '''The problem:''' In out-of-source builds, the code that is generated by kconfig_compiler is saved in the build tree. So how can we still include the header generated by kconfig_compiler with a simple <tt>#include "settings.h"</tt>? |
'''The solution:''' Probably you have yet a line similar to the following line in your CMakeLists.txt: | '''The solution:''' Probably you have yet a line similar to the following line in your CMakeLists.txt: | ||
| − | + | <pre> | |
| − | + | include_directories(${QT_INCLUDE} ${KDE4_INCLUDES}) | |
| − | + | </pre> | |
Add the variable ''CMAKE_CURRENT_BINARY_DIR'', so that you get something like this: | Add the variable ''CMAKE_CURRENT_BINARY_DIR'', so that you get something like this: | ||
| − | + | <pre> | |
| − | + | include_directories(${QT_INCLUDE} ${KDE4_INCLUDES} ${CMAKE_CURRENT_BINARY_DIR}) | |
| − | + | </pre> | |
| − | Notice that you should call | + | Notice that you should call <tt>include_directories</tt> only once in your project. (When you call <tt>include_directories</tt> in your base source directory, but than call it another time in a subdirectory (added by <tt>add_subdirectory</tt>), then the second call will be ignored.) |
== Use and Dialogs == | == Use and Dialogs == | ||
| Line 157: | Line 157: | ||
# Create the KConfigDialog and pass the instance of your configuration data as one of the arguments. The construct would look like the following example: | # Create the KConfigDialog and pass the instance of your configuration data as one of the arguments. The construct would look like the following example: | ||
| − | < | + | <syntaxhighlight lang="cpp-qt"> |
KConfigDialog* dialog = new KConfigDialog( | KConfigDialog* dialog = new KConfigDialog( | ||
this, "settings", YourAppSettings::self() ); | this, "settings", YourAppSettings::self() ); | ||
| − | </ | + | </syntaxhighlight> |
assuming that YourAppSettings is the value of the ClassName variable from the kcfgc file and the settings class is a singelton. | assuming that YourAppSettings is the value of the ClassName variable from the kcfgc file and the settings class is a singelton. | ||
| Line 174: | Line 174: | ||
With the following example.kcfg file: | With the following example.kcfg file: | ||
| − | < | + | <syntaxhighlight lang="xml"> |
<?xml version="1.0" encoding="UTF-8"?> | <?xml version="1.0" encoding="UTF-8"?> | ||
<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0" | <kcfg xmlns="http://www.kde.org/standards/kcfg/1.0" | ||
| Line 193: | Line 193: | ||
</group> | </group> | ||
</kcfg> | </kcfg> | ||
| − | </ | + | </syntaxhighlight> |
And here's how to actually use the generated class. for the given kcfgc file. | And here's how to actually use the generated class. for the given kcfgc file. | ||
| − | < | + | <syntaxhighlight lang="ini"> |
File=example.kcfg | File=example.kcfg | ||
ClassName=ExampleSettings | ClassName=ExampleSettings | ||
Singleton=true | Singleton=true | ||
Mutators=true | Mutators=true | ||
| − | </ | + | </syntaxhighlight> |
The header files wouldn't change, but the cpp files must now contain the | The header files wouldn't change, but the cpp files must now contain the | ||
following code to access and store the configuration data : | following code to access and store the configuration data : | ||
| − | < | + | <syntaxhighlight lang="cpp-qt"> |
... | ... | ||
#include <ExampleSettings.h> | #include <ExampleSettings.h> | ||
| Line 220: | Line 220: | ||
ExampleSettings::self()->writeConfig(); | ExampleSettings::self()->writeConfig(); | ||
} | } | ||
| − | </ | + | </syntaxhighlight> |
self() returns the current instance of the object. You need to call writeConfig() this way, since it's a virtual method. | self() returns the current instance of the object. You need to call writeConfig() this way, since it's a virtual method. | ||
| Line 232: | Line 232: | ||
And you can use the dialog with the following code: | And you can use the dialog with the following code: | ||
| − | < | + | <syntaxhighlight lang="cpp-qt"> |
| − | //An instance of your dialog could be already created and could be | + | // An instance of your dialog could be already created and could be |
// cached, in which case you want to display the cached dialog | // cached, in which case you want to display the cached dialog | ||
// instead of creating another one | // instead of creating another one | ||
| Line 248: | Line 248: | ||
dialog->addPage( confWdg, i18n("Example"), "example" ); | dialog->addPage( confWdg, i18n("Example"), "example" ); | ||
| − | //User edited the configuration - update your local copies of the | + | // User edited the configuration - update your local copies of the |
| − | //configuration data | + | // configuration data |
connect( dialog, SIGNAL(settingsChanged()), | connect( dialog, SIGNAL(settingsChanged()), | ||
this, SLOT(updateConfiguration()) ); | this, SLOT(updateConfiguration()) ); | ||
dialog->show(); | dialog->show(); | ||
| − | </ | + | </syntaxhighlight> |
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! | 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! | ||
Contents |
Languages: عربي | Asturianu | Català | Česky | Kaszëbsczi | Dansk | Deutsch | English | Esperanto | Español | Eesti | فارسی | Suomi | Français | Galego | Italiano | 日本語 | 한국어 | Norwegian | Polski | Português Brasileiro | Română | Русский | Svenska | Slovenčina | Slovenščina | српски | Türkçe | Tiếng Việt | Українська | 简体中文 | 繁體中文
| Tutorial Series | KConfig |
| Previous | Introduction to KConfig Introduction to CMake |
| What's Next | None |
| Further Reading | The KDE Configuration Compiler (KDE 4) The KDE Configuration Compiler (KDE 3) |
Original Author: Zack Rusin <zack@kde.org>
This tutorial introduces the main concepts of the KconfigXT 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 XML Schema is also required.
The main idea behind KConfig XT is to make the life of application developers easier while making the administration of large KDE installations more manageable. The four basic parts of the new framework are:
| 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. |
The structure of the .kcfg file is described by its XML Schema (kcfg.xsd - available from here or from the kdecore library ). Please go through it before you go any further.
Lets create a simple .kcfg file. Please reference the code below as we go through each step.
<?xml version="1.0" encoding="UTF-8"?> <kcfg xmlns="http://www.kde.org/standards/kcfg/1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0 http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" > <kcfgfile name="kjotsrc"/> <include>kglobalsettings.h</include> <group name="kjots"> <entry name="SplitterSizes" type="IntList"> <label>How the main window is divided.</label> </entry> <entry name="Width" type="Int"> <label>Width of the main window.</label> <default>600</default> </entry> <entry name="Height" type="Int"> <label>Height of the main window.</label> <default>400</default> </entry> <entry name="OpenBooks" type="StringList"> <label>All books that are opened.</label> </entry> <entry name="CurrentBook" type="String"> <label>The book currently opened.</label> </entry> <entry name="Font" type="Font"> <label>The font used to display the contents of books.</label> <default code="true">KGlobalSettings::generalFont()</default> </entry> </group> </kcfg>
After creating a .kcfg file create a .kcfgc file which describes the C++ file generation options. The .kcfgc file is a simple ini file with the typical "entry=value" format. To create a simple .kcfgc file follow these steps:
For details see the description of kconfig_compiler: [1]
After creating the .kcfg and .kcfgc files the next step is to adjust the build to let kconfig_compiler generate the required class at compile time. For in-source builds, doing this is trivial and requires only one step, adding this two lines to the CMakeLists.txt file example (asuming your files are named settings.kcfg and settings.kcfgc):
kde4_add_kcfg_files(<project name>_SRCS settings.kcfgc)
install(FILES settings.kcfg DESTINATION ${KCFG_INSTALL_DIR})
Alternatively, if a .moc file needs to be generated before compiling the generated source code, use
kde4_add_kcfg_files(<project name>_SRCS GENERATE_MOC settings.kcfgc)
install(FILES settings.kcfg DESTINATION ${KCFG_INSTALL_DIR})
This assures that the configuration class is properly generated (kde4_add_kcfg_files) and that the .kcfg is installed so it can be used by tools like the KConfigEditor (install).
Out-of-source builds require one more step.
The problem: In out-of-source builds, the code that is generated by kconfig_compiler is saved in the build tree. So how can we still include the header generated by kconfig_compiler with a simple #include "settings.h"?
The solution: Probably you have yet a line similar to the following line in your CMakeLists.txt:
include_directories(${QT_INCLUDE} ${KDE4_INCLUDES})
Add the variable CMAKE_CURRENT_BINARY_DIR, so that you get something like this:
include_directories(${QT_INCLUDE} ${KDE4_INCLUDES} ${CMAKE_CURRENT_BINARY_DIR})
Notice that you should call include_directories only once in your project. (When you call include_directories in your base source directory, but than call it another time in a subdirectory (added by add_subdirectory), then the second call will be ignored.)
After making all of the above changes you're ready to use KConfig XT. The kconfig_compiler generated header file will have the name equal to the name of the .kcfg file but with a ".h" extension. Simply include that file wherever you want to access your configuration options.
The use will depend on whether you have added the Singleton=true entry to your .kcfgc file.
One the nicest features of the KConfig XT is its seamless integration with the Qt Designer generated dialogs. You can do that by using KConfigDialog. The steps to do that are as follows:
KConfigDialog* dialog = new KConfigDialog( this, "settings", YourAppSettings::self() );
assuming that YourAppSettings is the value of the ClassName variable from the kcfgc file and the settings class is a singelton.
Here's an example usage of KConfig XT for the application named Example. With the following example.kcfg file:
<?xml version="1.0" encoding="UTF-8"?> <kcfg xmlns="http://www.kde.org/standards/kcfg/1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0 http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" > <kcfgfile name="examplerc"/> <group name="network"> <entry name="ServerName" type="String"> <label>Defines the sample server.</label> </entry> <entry name="Port" type="Int"> <label>Defines the server port</label> <default>21</default> <min>20</min> <max>990</max> </entry> </group> </kcfg>
And here's how to actually use the generated class. for the given kcfgc file.
File=example.kcfg ClassName=ExampleSettings Singleton=true Mutators=true
The header files wouldn't change, but the cpp files must now contain the following code to access and store the configuration data :
... #include <ExampleSettings.h> ... void ExampleClass::readConfig() { m_server = ExampleSettings::serverName(); m_port = ExampleSettings::port(); } void ExampleClass::saveSettings() { ExampleSettings::setServerName( m_server ); ExampleSettings::setPort( m_port ); ExampleSettings::self()->writeConfig(); }
self() returns the current instance of the object. You need to call writeConfig() this way, since it's a virtual method.
To add a dialog you need to create a Qt Designer widget with the widget names corresponding to the names of the options they should edit and prefixed with "kcfg_". It could be something along the lines of:
And you can use the dialog with the following code:
// An instance of your dialog could be already created and could be // cached, in which case you want to display the cached dialog // instead of creating another one if ( KConfigDialog::showDialog( "settings" ) ) return; // KConfigDialog didn't find an instance of this dialog, so lets // create it : KConfigDialog* dialog = new KConfigDialog(this, "settings", ExampleSettings::self()); ExampleDesignerWidget* confWdg = new ExampleDesignerWidget( 0, "Example" ); dialog->addPage( confWdg, i18n("Example"), "example" ); // User edited the configuration - update your local copies of the // configuration data connect( dialog, SIGNAL(settingsChanged()), this, SLOT(updateConfiguration()) ); dialog->show();
And that's all it takes. You can have a look at KReversi and KTron code in the kdegames module to see a live example of KConfig XT!