Contents |
原作者: Zack Rusin <zack@kde.org>
本教程介绍了Kconfig XT配置框架的主要概念,并演示了如何在应用程序里快速使用它。本文假设读者已经开发过KDE应用程序,并且熟悉KConfig。同时也要求了解XML及XML Schema的概念。
KConfig XT框架背后的主要想法是,更方便地管理庞大的KDE安装,让应用程序开发者生活得更惬意。
这个新框架有四个基本部分:
.kcfg文件的结构由它的XML Schema描述(kcfg.xsd - 可从这里或者kdecore库里下载)。请在继续阅读本教程之前,略读一遍这个小文件。
首先让我们来创建一个简单的.kcfg文件,请参看下面这段示例,来学习各个步骤。
<?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>
创建完一个.kcfg文件后,还需要创建一个.kcfgc文件来描述C++代码的生成细节。.kcfgc文件是一个简单的ini格式文件,使用"entry=value"格式。可以按照以下的步骤来创建一个简单的.kcfgc文件:
更详细的kconfig_compiler说明: [1]
创建完.kcfg文件和.kcfgc文件后,下一步是调整编译参数,让kconfig_compiler在编译时生成必要的类。对于在源码目录里的编译,调整很少,只需要添加下面这两行代码到CMakeLists.txt中(这里假设您的配置文件叫做settings.kcfg和settings.kcfgc):
kde4_add_kcfg_files(<project name>_SRCS settings.kcfgc)
install(FILES settings.kcfg DESTINATION ${KCFG_INSTALL_DIR})
另外,如果在编译生成的源代码之前要生成.moc文件,使用下面这两行代码:
kde4_add_kcfg_files(<project name>_SRCS GENERATE_MOC settings.kcfgc)
install(FILES settings.kcfg DESTINATION ${KCFG_INSTALL_DIR})
以上代码确保了配置类自动生成(kde4_add_kcfg_files),并且.kcfg文件正确地安装以便被KConfigEditor等工具使用(install)。
对于在源码目录外编译的情况,需要多一个步骤。
问题:对于在源码目录外的编译,kconfig_compiler所生成的代码被保存在了编译目录中。此时,如何在源代码中简单地使用#include "settings.h"来包含kconfig_compiler所生成的头文件呢?
方案:也许您的CMakeLists.txt里有一行下面这样的代码:
include_directories(${QT_INCLUDE} ${KDE4_INCLUDES})
给它加上一个变量CMAKE_CURRENT_BINARY_DIR,结果如下:
include_directories(${QT_INCLUDE} ${KDE4_INCLUDES} ${CMAKE_CURRENT_BINARY_DIR})
需要注意的是,在您的工程中应当只调用一次include_directories。(如果您在源码根目录里调用了一次include_directories,但是又在其他的子目录(由add_subdirectory添加的目录)中调用了一次,那么第二次include_directories调用将会被忽略。)
做完以上的步骤之后,您已经为使用KConfig XT框架准备完毕了。kconfig_compiler将生成与.kcfg文件同名的代码文件(后缀替换成".h")。在您需要访问配置项的源代码中#include该头文件即可。
只有在.kcfgc文件中添加了Singleton=true,您才能使用本特性。
KConfig XT的最强之处在于,它与Qt设计器生成的对话框能无缝集成。您可是通过使用KConfigDialog来实现。步骤如下:
KConfigDialog* dialog = new KConfigDialog( this, "settings", YourAppSettings::self() );
这里假设YourAppSettings是kcfgc中ClassName变量的值。并且该配置类是单例模式。
此处使用KConfig XT框架的例子。应用程序的名字叫做Example。
它的.kcfg文件如下:
<?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>
然后配置生成的配置类的细节。.kcfgc文件如下:
File=example.kcfg ClassName=ExampleSettings Singleton=true Mutators=true
程序源代码的头文件不需要变动,只需要在cpp文件中包含如下的代码来访问和修改配置项数据:
... #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()返回的是对象的实例。所有的writeConfig()都得这样调用,因为它是一个虚函数方法。(其他的读取和设置选项的方法是静态方法。)
要想增加一个配置对话框,您的Qt设计器生成的widget的名字需要与它们对应的选项的名字相同,并且加上"kcfg_"前缀。例如:
然后您就可以照着下面的代码来使用该配置对话框:
// 对话框的实例可能已经创建过并缓存着, // 因此可以直接显示该缓存的对话框,而无须又创建一个 if ( KConfigDialog::showDialog( "settings" ) ) return; // KConfigDialog并没有找到对话框的缓存,所有创建新的吧: KConfigDialog* dialog = new KConfigDialog(this, "settings", ExampleSettings::self()); ExampleDesignerWidget* confWdg = new ExampleDesignerWidget( 0, "Example" ); dialog->addPage( confWdg, i18n("Example"), "example" ); // 用户更改对话框里的配置项,然后您更新本地的配置 connect( dialog, SIGNAL(settingsChanged()), this, SLOT(updateConfiguration()) ); dialog->show();
这就是全部的内容。您可以查看一下kdegames模块里面的KReversi和KTron的源代码,看看KConfig XT的真实的例子!