aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJenkins CI <null@kde.org>2013-12-18 00:45:18 +0000
committerJenkins CI <null@kde.org>2013-12-18 00:45:18 +0000
commitc38b88497a833e482e6892b72c8f52adec6de857 (patch)
tree8c2d4b788cf54ab2179ffe53515d276feaeba2d1
downloadkconfig-c38b88497a833e482e6892b72c8f52adec6de857.tar.gz
kconfig-c38b88497a833e482e6892b72c8f52adec6de857.tar.bz2
Initial import from the monolithic kdelibs.
This is the beginning of revision history for this module. If you want to look at revision history older than this, please refer to the techbase wiki for how to use Git history grafting. At the time of writing, this wiki is located here: http://community.kde.org/Frameworks/GitOldHistory If you have already performed the grafting and you don't see any history beyond this commit, try running "git log" with the "--follow" argument. Branched from the monolithic repo, kdelibs frameworks branch, at commit 162066dbbecde401a7347a1cff4fe72a9c919f58
-rw-r--r--tier1/kconfig/CMakeLists.txt60
-rw-r--r--tier1/kconfig/COPYING.LIB510
-rw-r--r--tier1/kconfig/DESIGN106
-rw-r--r--tier1/kconfig/KF5ConfigConfig.cmake.in11
-rw-r--r--tier1/kconfig/KF5ConfigMacros.cmake84
-rw-r--r--tier1/kconfig/Mainpage.dox1
-rw-r--r--tier1/kconfig/TODO175
-rw-r--r--tier1/kconfig/autotests/CMakeLists.txt59
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/CMakeLists.txt212
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/kconfigcompiler_test.cpp181
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/kconfigcompiler_test.h42
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/myprefs.h12
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test1.cpp.ref72
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test1.h.ref197
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test1.kcfg55
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test1.kcfgc18
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test10.cpp.ref46
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test10.h.ref50
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test10.kcfg13
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test10.kcfgc4
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test10main.cpp32
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test11.cpp.ref278
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test11.h.ref572
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test11.kcfg136
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test11.kcfgc13
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test11_types.h31
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test11a.cpp.ref187
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test11a.h.ref480
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test11a.kcfg135
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test11a.kcfgc13
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test11main.cpp34
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test12.cpp.ref22
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test12.h.ref36
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test12.kcfg10
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test12.kcfgc1
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test12main.cpp28
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test1main.cpp31
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test2.cpp.ref96
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test2.h.ref335
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test2.kcfg78
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test2.kcfgc11
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test2main.cpp31
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test3.cpp.ref29
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test3.h.ref140
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test3.kcfg26
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test3.kcfgc12
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test3a.cpp.ref29
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test3a.h.ref142
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test3a.kcfg26
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test3a.kcfgc12
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test3amain.cpp31
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test3main.cpp31
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test4.cpp.ref178
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test4.h.ref171
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test4.kcfg56
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test4.kcfgc11
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test4main.cpp32
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test5.cpp.ref88
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test5.h.ref123
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test5.kcfg42
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test5.kcfgc11
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test5main.cpp32
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test6.cpp.ref31
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test6.h.ref94
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test6.kcfg25
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test6.kcfgc11
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test6main.cpp32
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test7.cpp.ref31
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test7.h.ref94
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test7.kcfg25
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test7.kcfgc11
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test7main.cpp32
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test8a.cpp.ref22
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test8a.h.ref62
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test8a.kcfg17
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test8a.kcfgc3
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test8b.cpp.ref52
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test8b.h.ref92
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test8b.kcfg21
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test8b.kcfgc6
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test8main.cpp36
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test9.cpp.ref35
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test9.h.ref83
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test9.kcfg24
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test9.kcfgc18
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test9main.cpp45
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test_dpointer.cpp.ref348
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test_dpointer.h.ref220
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test_dpointer.kcfg78
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test_dpointer.kcfgc11
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test_dpointer_main.cpp32
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test_signal.cpp.ref73
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test_signal.h.ref153
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test_signal.kcfg45
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test_signal.kcfgc7
-rw-r--r--tier1/kconfig/autotests/kconfig_compiler/test_signal_main.cpp32
-rw-r--r--tier1/kconfig/autotests/kconfigguitest.cpp145
-rw-r--r--tier1/kconfig/autotests/kconfigguitest.h35
-rw-r--r--tier1/kconfig/autotests/kconfigloadertest.cpp208
-rw-r--r--tier1/kconfig/autotests/kconfigloadertest.h63
-rw-r--r--tier1/kconfig/autotests/kconfigloadertest.xml71
-rw-r--r--tier1/kconfig/autotests/kconfignokdehometest.cpp64
-rw-r--r--tier1/kconfig/autotests/kconfigskeletontest.cpp111
-rw-r--r--tier1/kconfig/autotests/kconfigskeletontest.h44
-rw-r--r--tier1/kconfig/autotests/kconfigtest.cpp1634
-rw-r--r--tier1/kconfig/autotests/kconfigtest.h86
-rw-r--r--tier1/kconfig/autotests/kdesktopfiletest.cpp138
-rw-r--r--tier1/kconfig/autotests/kdesktopfiletest.h36
-rw-r--r--tier1/kconfig/autotests/kentrymaptest.cpp202
-rw-r--r--tier1/kconfig/autotests/kentrymaptest.h57
-rw-r--r--tier1/kconfig/autotests/ksharedconfigtest.cpp83
-rw-r--r--tier1/kconfig/autotests/kstandardshortcuttest.cpp59
-rw-r--r--tier1/kconfig/autotests/kstandardshortcuttest.h38
-rw-r--r--tier1/kconfig/autotests/test_kconf_update.cpp553
-rw-r--r--tier1/kconfig/autotests/test_kconf_update.h36
-rw-r--r--tier1/kconfig/autotests/test_kconfigutils.cpp149
-rw-r--r--tier1/kconfig/autotests/test_kconfigutils.h36
-rw-r--r--tier1/kconfig/docs/DESIGN.kconfig224
-rw-r--r--tier1/kconfig/docs/README.kiosk817
-rw-r--r--tier1/kconfig/src/CMakeLists.txt4
-rw-r--r--tier1/kconfig/src/core/CMakeLists.txt53
-rw-r--r--tier1/kconfig/src/core/bufferfragment_p.h181
-rw-r--r--tier1/kconfig/src/core/conversion_check.h120
-rw-r--r--tier1/kconfig/src/core/kauthorized.cpp393
-rw-r--r--tier1/kconfig/src/core/kauthorized.h73
-rw-r--r--tier1/kconfig/src/core/kconfig.cpp931
-rw-r--r--tier1/kconfig/src/core/kconfig.h397
-rw-r--r--tier1/kconfig/src/core/kconfig_p.h110
-rw-r--r--tier1/kconfig/src/core/kconfigbackend.cpp123
-rw-r--r--tier1/kconfig/src/core/kconfigbackend.desktop86
-rw-r--r--tier1/kconfig/src/core/kconfigbackend.h211
-rw-r--r--tier1/kconfig/src/core/kconfigbase.cpp112
-rw-r--r--tier1/kconfig/src/core/kconfigbase.h184
-rw-r--r--tier1/kconfig/src/core/kconfigbase_p.h30
-rw-r--r--tier1/kconfig/src/core/kconfigdata.cpp317
-rw-r--r--tier1/kconfig/src/core/kconfigdata.h237
-rw-r--r--tier1/kconfig/src/core/kconfiggroup.cpp1243
-rw-r--r--tier1/kconfig/src/core/kconfiggroup.h767
-rw-r--r--tier1/kconfig/src/core/kconfiggroup_p.h42
-rw-r--r--tier1/kconfig/src/core/kconfigini.cpp770
-rw-r--r--tier1/kconfig/src/core/kconfigini_p.h81
-rw-r--r--tier1/kconfig/src/core/kcoreconfigskeleton.cpp1343
-rw-r--r--tier1/kconfig/src/core/kcoreconfigskeleton.h1407
-rw-r--r--tier1/kconfig/src/core/kcoreconfigskeleton_p.h64
-rw-r--r--tier1/kconfig/src/core/kdesktopfile.cpp366
-rw-r--r--tier1/kconfig/src/core/kdesktopfile.h252
-rw-r--r--tier1/kconfig/src/core/kemailsettings.cpp269
-rw-r--r--tier1/kconfig/src/core/kemailsettings.h176
-rw-r--r--tier1/kconfig/src/core/ksharedconfig.cpp122
-rw-r--r--tier1/kconfig/src/core/ksharedconfig.h88
-rw-r--r--tier1/kconfig/src/gui/CMakeLists.txt41
-rw-r--r--tier1/kconfig/src/gui/kconfiggroupgui.cpp197
-rw-r--r--tier1/kconfig/src/gui/kconfiggui.cpp51
-rw-r--r--tier1/kconfig/src/gui/kconfiggui.h58
-rw-r--r--tier1/kconfig/src/gui/kconfigloader.cpp442
-rw-r--r--tier1/kconfig/src/gui/kconfigloader.h176
-rw-r--r--tier1/kconfig/src/gui/kconfigloader_p.h222
-rw-r--r--tier1/kconfig/src/gui/kconfigloaderhandler_p.h68
-rw-r--r--tier1/kconfig/src/gui/kconfigskeleton.cpp121
-rw-r--r--tier1/kconfig/src/gui/kconfigskeleton.h140
-rw-r--r--tier1/kconfig/src/gui/kstandardshortcut.cpp377
-rw-r--r--tier1/kconfig/src/gui/kstandardshortcut.h482
-rw-r--r--tier1/kconfig/src/gui/kwindowconfig.cpp83
-rw-r--r--tier1/kconfig/src/gui/kwindowconfig.h58
-rw-r--r--tier1/kconfig/src/kconf_update/CMakeLists.txt17
-rw-r--r--tier1/kconfig/src/kconf_update/Mainpage.dox31
-rw-r--r--tier1/kconfig/src/kconf_update/README.kconf_update248
-rw-r--r--tier1/kconfig/src/kconf_update/config-kconf.h.cmake4
-rw-r--r--tier1/kconfig/src/kconf_update/kconf_update.cpp967
-rw-r--r--tier1/kconfig/src/kconf_update/kconfigutils.cpp127
-rw-r--r--tier1/kconfig/src/kconf_update/kconfigutils.h43
-rw-r--r--tier1/kconfig/src/kconfig_compiler/CMakeLists.txt15
-rw-r--r--tier1/kconfig/src/kconfig_compiler/README.dox446
-rw-r--r--tier1/kconfig/src/kconfig_compiler/TODO0
-rwxr-xr-xtier1/kconfig/src/kconfig_compiler/checkkcfg.pl83
-rw-r--r--tier1/kconfig/src/kconfig_compiler/kcfg.xsd234
-rw-r--r--tier1/kconfig/src/kconfig_compiler/kconfig_compiler.cpp2338
177 files changed, 30131 insertions, 0 deletions
diff --git a/tier1/kconfig/CMakeLists.txt b/tier1/kconfig/CMakeLists.txt
new file mode 100644
index 00000000..c7a7c934
--- /dev/null
+++ b/tier1/kconfig/CMakeLists.txt
@@ -0,0 +1,60 @@
+cmake_minimum_required(VERSION 2.8.12)
+
+project(KConfig)
+
+find_package(ECM 0.0.9 REQUIRED NO_MODULE)
+set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR})
+
+set(QT_REQUIRED_VERSION 5.2.0)
+
+find_package(Qt5 ${QT_REQUIRED_VERSION} CONFIG REQUIRED Widgets Xml Test Concurrent)
+include(KDEInstallDirs)
+include(KDEFrameworkCompilerSettings)
+include(KDECMakeSettings)
+
+include(FeatureSummary)
+include(ECMSetupVersion)
+
+set(KF5_VERSION "5.0.0")
+
+ecm_setup_version(${KF5_VERSION} VARIABLE_PREFIX KCONFIG
+ VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/kconfig_version.h"
+ PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/KF5ConfigConfigVersion.cmake")
+
+
+# Needed for the tests or examples to build correctly
+set(KConfig_KCFGC_EXECUTABLE kconfig_compiler)
+include(KF5ConfigMacros.cmake)
+
+add_subdirectory(src)
+add_subdirectory(autotests)
+
+
+# create a Config.cmake and a ConfigVersion.cmake file and install them
+set(CMAKECONFIG_INSTALL_DIR "${CMAKECONFIG_INSTALL_PREFIX}/KF5Config")
+
+include(CMakePackageConfigHelpers)
+
+configure_package_config_file("${CMAKE_CURRENT_SOURCE_DIR}/KF5ConfigConfig.cmake.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/KF5ConfigConfig.cmake"
+ INSTALL_DESTINATION ${CMAKECONFIG_INSTALL_DIR}
+ )
+
+install(FILES "${CMAKE_CURRENT_BINARY_DIR}/KF5ConfigConfig.cmake"
+ "${CMAKE_CURRENT_BINARY_DIR}/KF5ConfigConfigVersion.cmake"
+ "${CMAKE_CURRENT_SOURCE_DIR}/KF5ConfigMacros.cmake"
+ DESTINATION "${CMAKECONFIG_INSTALL_DIR}"
+ COMPONENT Devel )
+
+
+install(EXPORT KF5ConfigTargets DESTINATION "${CMAKECONFIG_INSTALL_DIR}"
+ FILE KF5ConfigTargets.cmake NAMESPACE KF5:: COMPONENT Devel)
+
+
+install(FILES ${CMAKE_CURRENT_BINARY_DIR}/kconfig_version.h
+ DESTINATION ${INCLUDE_INSTALL_DIR} COMPONENT Devel )
+
+
+if ("${CMAKE_BINARY_DIR}" STREQUAL "${CMAKE_CURRENT_BINARY_DIR}")
+ feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES)
+endif()
diff --git a/tier1/kconfig/COPYING.LIB b/tier1/kconfig/COPYING.LIB
new file mode 100644
index 00000000..2d2d780e
--- /dev/null
+++ b/tier1/kconfig/COPYING.LIB
@@ -0,0 +1,510 @@
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations
+below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it
+becomes a de-facto standard. To achieve this, non-free programs must
+be allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control
+compilation and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at least
+ three years, to give the same user the materials specified in
+ Subsection 6a, above, for a charge no more than the cost of
+ performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply, and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License
+may add an explicit geographical distribution limitation excluding those
+countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms
+of the ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library.
+It is safest to attach them to the start of each source file to most
+effectively convey the exclusion of warranty; and each file should
+have at least the "copyright" line and a pointer to where the full
+notice is found.
+
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or
+your school, if any, to sign a "copyright disclaimer" for the library,
+if necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James
+ Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
+
diff --git a/tier1/kconfig/DESIGN b/tier1/kconfig/DESIGN
new file mode 100644
index 00000000..3cccc1ca
--- /dev/null
+++ b/tier1/kconfig/DESIGN
@@ -0,0 +1,106 @@
+If you add a major new feature, suggest using it in
+http://techbase.kde.org/Development/Tutorials/KConfig
+
+kconfigdata.h contains definitions of the data formats used by kconfig.
+
+Configuration entries are stored as "KEntry". They are indexed with "KEntryKey".
+The primary store is a "KEntryMap" which is defined as a QMap from "KEntryKey"
+to "KEntry"
+
+KEntry's are stored in order in the KEntryMap. The most significant sort
+criteria is mGroup. This means that all entries who belong in the same group,
+are grouped in the QMap as well.
+
+The start of a group is indicated with a KEntryKey with an empty mKey and a
+dummy KEntry. This allows us to search for the start of the group and then to
+iterate until we end up in another group. That way we will find all entries
+of a certain group.
+
+Entries that are localised with the _current_ locale are stored with bLocal
+set to true. Entries that are localised with another locale are either not
+stored at all (default), or with the localization as part of the key and bRaw
+set to true (when reading a file in order to merge it).
+
+Entries that are being read from a location other than the location to
+which is written back are marked as "default" and will be added both as
+normal entry as well as an entry with the key marked as default.
+
+When the configuration is synced to disk, the current on-disk state is re-read
+into a temporary map, updated with dirty (modified) entries from the
+current config object's entry map and then written back.
+
+
+Note that there is a subtle difference between revertToDefault() and deleteEntry().
+revertToDefault() will change the entry to the default value set by the system
+administrator (Via e.g. $KDEDIR/share/config) or, if no such default was set,
+non-existant.
+deleteEntry() will make the entry non-existant. If if the system administrator
+has specified a default value, the local entry is marked with [$d].
+
+Entries are marked "immutable" if the key is followed by [$i]. This means
+that a user can not override these entries.
+
+
+------------------------------------------------------------------------------
+
+KConfig XT
+==========
+
+My buzzword picker offered KConfig XT ("eXtended Technology") and KConfig NG
+("Next Generation"). Since the planned changes are ment to be evolutionary
+rather than revolutionary, KConfig NG was dropped.
+
+Goals
+=====
+
+* Have the default value for config entries defined in 1 place. Currently it is
+not uncommon to have them defined in three places:
+ 1) In the application that reads the setting in order to use it
+ 2) In the settings dialog when reading the setting
+ 3) In the settings dialog when selecting "Use defaults".
+
+* Provide type-information about config entries to facilate "KConfEdit" like
+tools. Ideally type-information also includes range-information; this is even
+mandatory if enums become an explicit type.
+
+* Facilitate the documentation of config entries.
+
+KCoreConfigSkeleton
+ |
+ v
+ KConfigSkeleton /--< myapp.kcfg
+ | /
+ |*---------------<
+ |kconfig_compiler \
+ | \--< myconfig.kcfgc
+ v
+ MyConfig <-----KConfigDialogManager----> MyConfigWidget *---< myconfigwidget.ui
+ uic
+
+KCoreConfigSkeleton/ base class for deriving classes that store application
+KConfigSkeleton: specific options providing type-safety and single-point
+ defaults.
+
+MyConfig: An application specific class that offers configuration options
+ to the applications via variables or accessor functions and that
+ handles type-safety and defaults. MyConfig is just an example
+ name, the application developer choses the actual name.
+
+myapp.kcfg: File describing the configuration options used by a specific
+ application. myapp.kcfg is just an example name, the application
+ developer choses the actual name.
+
+myconfig.kcfgc: Implementation specific code generation instructions
+ for the MyConfig class. myconfig.kcfgc is
+ just an example name, the application developer
+ choses the actual name.
+
+KConfigDialogManager: Class that links widgets in a dialog up with their
+ corresponding confguration options in a configuration
+ object derived from KConfigSkeleton.
+
+MyConfigWidget: Dialog generated from a .ui description file. Widget names
+ in the dialog that start with "kcfg_" refer to configuration
+ options.
+
+See http://techbase.kde.org/Development/Tutorials/Using_KConfig_XT
diff --git a/tier1/kconfig/KF5ConfigConfig.cmake.in b/tier1/kconfig/KF5ConfigConfig.cmake.in
new file mode 100644
index 00000000..12ff7c63
--- /dev/null
+++ b/tier1/kconfig/KF5ConfigConfig.cmake.in
@@ -0,0 +1,11 @@
+@PACKAGE_INIT@
+
+# Any changes in this ".cmake" file will be overwritten by CMake, the source is the ".cmake.in" file.
+
+
+include("${CMAKE_CURRENT_LIST_DIR}/KF5ConfigTargets.cmake")
+
+find_dependency(Qt5Xml "@REQUIRED_QT_VERSION@")
+
+unset( _KDE4_KCONFIG_COMPILER_DEP)
+include("${CMAKE_CURRENT_LIST_DIR}/KF5ConfigMacros.cmake")
diff --git a/tier1/kconfig/KF5ConfigMacros.cmake b/tier1/kconfig/KF5ConfigMacros.cmake
new file mode 100644
index 00000000..bf2615b3
--- /dev/null
+++ b/tier1/kconfig/KF5ConfigMacros.cmake
@@ -0,0 +1,84 @@
+# KCONFIG_ADD_KCFG_FILES (SRCS_VAR [GENERATE_MOC] [USE_RELATIVE_PATH] file1.kcfgc ... fileN.kcfgc)
+# Use this to add KDE config compiler files to your application/library.
+# Use optional GENERATE_MOC to generate moc if you use signals in your kcfg files.
+# Use optional USE_RELATIVE_PATH to generate the classes in the build following the given
+# relative path to the file.
+#
+# Copyright (c) 2006-2009 Alexander Neundorf, <neundorf@kde.org>
+# Copyright (c) 2006, 2007, Laurent Montel, <montel@kde.org>
+# Copyright (c) 2007 Matthias Kretz <kretz@kde.org>
+#
+# Redistribution and use is allowed according to the terms of the BSD license.
+# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
+
+macro (KCONFIG_ADD_KCFG_FILES _sources )
+ foreach (_current_ARG ${ARGN})
+ if( ${_current_ARG} STREQUAL "GENERATE_MOC" )
+ set(_kcfg_generatemoc TRUE)
+ endif()
+
+ if( ${_current_ARG} STREQUAL "USE_RELATIVE_PATH" )
+ set(_kcfg_relativepath TRUE)
+ endif()
+ endforeach ()
+
+ foreach (_current_FILE ${ARGN})
+
+ if(NOT ${_current_FILE} STREQUAL "GENERATE_MOC" AND NOT ${_current_FILE} STREQUAL "USE_RELATIVE_PATH")
+ get_filename_component(_tmp_FILE ${_current_FILE} ABSOLUTE)
+ get_filename_component(_abs_PATH ${_tmp_FILE} PATH)
+
+ if (_kcfg_relativepath) # Process relative path only if the option was set
+ # Get relative path
+ get_filename_component(_rel_PATH ${_current_FILE} PATH)
+
+ if (IS_ABSOLUTE ${_rel_PATH})
+ # We got an absolute path
+ set(_rel_PATH "")
+ endif ()
+ endif ()
+
+ get_filename_component(_basename ${_tmp_FILE} NAME_WE)
+ # If we had a relative path and we're asked to use it, then change the basename accordingly
+ if(NOT ${_rel_PATH} STREQUAL "")
+ set(_basename ${_rel_PATH}/${_basename})
+ endif()
+
+ file(READ ${_tmp_FILE} _contents)
+ string(REGEX REPLACE "^(.*\n)?File=([^\n]+kcfg).*\n.*$" "\\2" _kcfg_FILENAME "${_contents}")
+ set(_src_FILE ${CMAKE_CURRENT_BINARY_DIR}/${_basename}.cpp)
+ set(_header_FILE ${CMAKE_CURRENT_BINARY_DIR}/${_basename}.h)
+ set(_moc_FILE ${CMAKE_CURRENT_BINARY_DIR}/${_basename}.moc)
+ set(_kcfg_FILE ${_abs_PATH}/${_kcfg_FILENAME})
+ # Maybe the .kcfg is a generated file?
+ if(NOT EXISTS "${_kcfg_FILE}")
+ set(_kcfg_FILE ${CMAKE_CURRENT_BINARY_DIR}/${_kcfg_FILENAME})
+ endif()
+
+ if(NOT EXISTS "${_kcfg_FILE}")
+ message(ERROR "${_kcfg_FILENAME} not found; tried in ${_abs_PATH} and ${CMAKE_CURRENT_BINARY_DIR}")
+ endif()
+
+ # make sure the directory exist in the build directory
+ if(NOT EXISTS "${CMAKE_CURRENT_BINARY_DIR}/${_rel_PATH}")
+ file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${_rel_PATH})
+ endif()
+
+ # the command for creating the source file from the kcfg file
+ add_custom_command(OUTPUT ${_header_FILE} ${_src_FILE}
+ COMMAND KF5::kconfig_compiler
+ ARGS ${_kcfg_FILE} ${_tmp_FILE} -d ${CMAKE_CURRENT_BINARY_DIR}/${_rel_PATH}
+ MAIN_DEPENDENCY ${_tmp_FILE}
+ DEPENDS ${_kcfg_FILE} ${_KDE4_KCONFIG_COMPILER_DEP} )
+
+ if(_kcfg_generatemoc)
+ qt5_generate_moc(${_header_FILE} ${_moc_FILE} )
+ set_source_files_properties(${_src_FILE} PROPERTIES SKIP_AUTOMOC TRUE) # don't run automoc on this file
+ list(APPEND ${_sources} ${_moc_FILE})
+ endif()
+
+ list(APPEND ${_sources} ${_src_FILE} ${_header_FILE})
+ endif(NOT ${_current_FILE} STREQUAL "GENERATE_MOC" AND NOT ${_current_FILE} STREQUAL "USE_RELATIVE_PATH")
+ endforeach (_current_FILE)
+
+endmacro (KCONFIG_ADD_KCFG_FILES)
diff --git a/tier1/kconfig/Mainpage.dox b/tier1/kconfig/Mainpage.dox
new file mode 100644
index 00000000..7e0699f9
--- /dev/null
+++ b/tier1/kconfig/Mainpage.dox
@@ -0,0 +1 @@
+// DOXYGEN_SET_PROJECT_NAME = KConfig
diff --git a/tier1/kconfig/TODO b/tier1/kconfig/TODO
new file mode 100644
index 00000000..4346ee13
--- /dev/null
+++ b/tier1/kconfig/TODO
@@ -0,0 +1,175 @@
+bugs
+====
+
+- make expandString stuff consistent
+- KConfigGroup::exists() should return true only if the group contains
+ any non-deleted entries (?)
+- immutable groups with no entries are not written out and thus lose
+ their immutability.
+- "C" & "en_US" should be detected early and converted to a null string
+ (but also save the original string, so locale() semantics don't change
+ at that point).
+
+wishes
+======
+
+- use lazy loading
+ - load as soon as the first KConfigGroup is instanciated
+ - lazy parsing of values is interesting, too - see kconfig_take2 branch
+- add $\\VAR and $\\(cmd) escapes to list-quote expanded string
+- possibly:
+ - preserve unchanged parts of the config literally. problem: comments
+ might become stale. so if a comment is already there, add an additional
+ comment that indicates that the value was changed (include old value?).
+ - api to actively add comments to files, groups and keys
+ - option to start these comments with ## as a sign that they should not
+ trigger the above change indicator logic.
+ - guaranteeing that write order of new keys is preserved
+ - detect commented out entries and put actual entries with the same key
+ right behind them
+- possibly: selective multi-level master diversion
+ - this is to support roaming profiles that have machine/user/etc. specific
+ settings
+ - files, groups and keys can have [$m] and [$s] markers; these cascade
+ within each file only. the least significant object (farthest away from
+ the master) with an effective $m mode becomes the master (i.e., is
+ written to and not read past).
+ default is $m for the master file and $s for the default files.
+ - the CascadeConfig flag being unset doesn't make things exactly simpler
+ - can kdeglobals be handled by this?
+ - does this really make sense? promoting an object to profile wide status
+ is a conscious decision - which probably needs to be repeated every time
+ the value changes.
+
+internals
+=========
+
+- clear up bDeleted vs. isNull in entrymap
+- make entrymap truly hierarchical
+ - an entry map contains its flags, a map of keys and a map of submaps.
+ it does NOT contain its name and has no parent pointer.
+ - when creating a kconfiggroup, ask parent for the respective submap
+ and link it if it is present. if it is not, create one at write op,
+ link it and tell parent to add it to its entry map. both query and
+ creation are recursive, obviously.
+ a kconfiggroup DOES contain its name and has a parent pointer.
+ - 3)
+- 4)
+
+3)
+> We wouldn't have to worry about the KEntryGroup being removed out from
+> under us, because the only way that should happen is if the config
+> object is destroyed or reparsed, and in those cases you shouldn't be
+> using a KConfigGroup from prior to that.
+>
+i don't think "this is stupid and will not happen" works; [...]
+given that cascaded parsing includes writing to existing maps, i think
+the simplest approach is clearing the existing structure from keymaps
+and resetting the attributes, but leaving the subgroup maps populated,
+thus keeping any group refs valid.
+the question is about the type of reference held to the entry map.
+originally i had thought of pointers. a map would be linked only if it
+really existed, otherwise the pointer would be null (thus indicating
+reads to return the default immediately and writes to ask the parent to
+create a submap). however, keeping that consistent with deletions would
+be a nightmare, and with the rescan changing the groups underneath
+impossible without each map having a list of referring configgroups.
+therefore it might make more sense to always create a corresponding tree
+of empty maps when a configroup for a non-existing group is instanciated
+- these groups won't be written out (they have no entries and cannot be
+immutable) and access to non-existing groups (esp. without an subsequent
+write that would actually create it) is rare, so the performance and
+memory overhead of this "eager" approach is likely to be negligible. as
+a middle way one could use a pointer and lazily populate it on first
+access whithout putting semantics into the pointer being already set,
+but i don't think the added complexity will pay off.
+
+4)
+> > > > hmm, wait. maybe it would be better if the map did not do actual
+> > > > permission checking. the frontent is peppered with asserts already
+> > >
+> > > that's the group doing permission checking, if this group is immutable
+> > > then the entry can't be changed. plus, now that KEntryKey doesn't know
+> > > what group it belongs to KEntryMap can't check if the group is
+> > > immutable.
+> > >
+> > > > (need to consider how to handle release builds). in the backend, the
+> > > > ugly immutableGroups hack would be unnecessary.
+> > >
+> > > no, immutableGroups would still be necessary unless i remove all
+> > > checking from KGroupEntry and KEntryMap. but, then checks for
+> > > immutable would have to be used everywhere that an entry might be
+> > > changed.
+> > >
+> > yes - and the frontend already handles it and the backend *should*
+> > handle it (issue warnings for trying to overwrite $i settings).
+>
+> i don't know, i think most handling of the immutability of a group
+> can/should be handled by the KGroupEntry itself. this way we can keep
+> all the data about a group in one place and let KGroupEntry keep
+> itself in a consistent/valid state.
+>
+dunno, either. the use cases are:
+- backend: writing immutable objects is fine, as long as the
+ immutability does not come from a pre-existing default.
+ given that there will be multiple backends, it sounds like
+ centralizing the check and warning reporting might make sense. otoh,
+ such a low-level function might not have enough context to make a
+ useful message.
+- frontend: obviously, writing immutable objects is not permitted. this
+ is already checked everywhere through asserts. in non-debug builds
+ these asserts have no effect, but if a write gets that far it means
+ that the app already permitted changing the option in the first place
+ due to failure to check for immutability. i don't see much point in
+ preventing the illegitimate change from being saved, as it can be
+ repeated anyway (i'm not really convinced of security through
+ exhaustion/boredom of the attacker :).
+i'm not sure whether that means that the two use cases need separate
+mutators or whether the mutator should not apply any immutability
+semantics at all.
+
+
+overwriting semantics
+=====================
+
+generally:
+- localized entries cannot exist without an unlocalized "primary" entry,
+ so writing a localized key when no corresponding unlocalized key
+ exists should print a warning and copy the value to the unlocalized
+ key.
+- a primary entry in the user config overshadows not only the immediate
+ default, but also any localizations of the default. applies also to a
+ [$d] marker, obviously.
+ a localized entry in the user config overshadows only that
+ localization from the default.
+
+write ops:
+> > - writing an entry with the localization flag changes really only that
+> > key.
+> > trying to change the globality of the key prints a warning and does
+> > nothing.
+- key exists in local config => overwritten
+- key does not exist => created
+yes, that's the trivial case.
+
+> > - writing an entry without the localization flag deletes all
+> > localizations.
+> > in this case, changing the globality of the key poses no problem.
+- the key itself is handled trivially
+- if localizations exist in the local config, they are actively purged
+- localizations in the default config don't matter, as they will be
+ overshadowed by the unlocalized key in the local config
+
+> > - deleting an entry also deletes all localizations.
+- if default exists, write [$d] entry
+- if no default exists, delete entry
+- if localizations exist in the local config, they are actively purged
+- localizations in the default config don't matter, as they will be
+ overshadowed by the unlocalized key in the local config (as
+ localizations cannot exist without a primary key, a deletion marker
+ key will be present).
+
+> > - reverting a key to default also restores all localizations.
+- any local entries are actively purged
+
+
diff --git a/tier1/kconfig/autotests/CMakeLists.txt b/tier1/kconfig/autotests/CMakeLists.txt
new file mode 100644
index 00000000..e4790f69
--- /dev/null
+++ b/tier1/kconfig/autotests/CMakeLists.txt
@@ -0,0 +1,59 @@
+
+remove_definitions(-DQT_NO_CAST_FROM_ASCII)
+
+include(ECMMarkAsTest)
+
+find_package(Qt5 5.2.0 CONFIG REQUIRED Concurrent Test Widgets)
+
+macro(KCONFIGCORE_UNIT_TESTS)
+ foreach(_testname ${ARGN})
+ add_executable(${_testname} ${_testname}.cpp) # TODO NOGUI
+ add_test(kconfigcore-${_testname} ${_testname})
+ target_link_libraries(${_testname} KF5::ConfigCore Qt5::Test Qt5::Concurrent)
+ ecm_mark_as_test(${_testname})
+ endforeach()
+endmacro()
+
+macro(KCONFIGGUI_UNIT_TESTS)
+ foreach(_testname ${ARGN})
+ add_executable(${_testname} ${_testname}.cpp)
+ add_test(kconfiggui-${_testname} ${_testname})
+ target_link_libraries(${_testname} KF5::ConfigGui Qt5::Test)
+ ecm_mark_as_test(${_testname})
+ endforeach()
+endmacro()
+
+kconfigcore_unit_tests(
+ kconfignokdehometest
+ kconfigtest
+ kdesktopfiletest
+ ksharedconfigtest
+ test_kconf_update
+)
+
+target_include_directories(test_kconf_update PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/../src/kconf_update)
+
+# compile KEntryMap into the test since it's not exported
+set(kentrymaptest_SRCS kentrymaptest.cpp ../src/core/kconfigdata.cpp)
+add_executable(kentrymaptest ${kentrymaptest_SRCS})
+add_test(kconfigcore-kentrymaptest kentrymaptest)
+target_link_libraries(kentrymaptest KF5::ConfigCore Qt5::Test)
+ecm_mark_as_test(kentrymaptest)
+
+# compile KConfigUtils into the test since it's not exported
+set(test_kconfigutils_SRCS test_kconfigutils ../src/kconf_update/kconfigutils.cpp)
+add_executable(test_kconfigutils ${test_kconfigutils_SRCS})
+add_test(kconfigcore-test_kconfigutils test_kconfigutils)
+target_link_libraries(test_kconfigutils KF5::ConfigCore Qt5::Test)
+target_include_directories(test_kconfigutils PRIVATE ../src/kconf_update)
+ecm_mark_as_test(test_kconfigutils)
+
+kconfiggui_unit_tests(
+ kconfigguitest
+ kconfigloadertest
+ kconfigskeletontest
+ kstandardshortcuttest
+)
+
+add_subdirectory(kconfig_compiler)
+
diff --git a/tier1/kconfig/autotests/kconfig_compiler/CMakeLists.txt b/tier1/kconfig/autotests/kconfig_compiler/CMakeLists.txt
new file mode 100644
index 00000000..ef2fd407
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/CMakeLists.txt
@@ -0,0 +1,212 @@
+
+#test5.cpp test5.h: $(srcdir)/test5.kcfg ../kconfig_compiler $(srcdir)/test5.kcfgc
+# ../kconfig_compiler $(srcdir)/test5.kcfg $(srcdir)/test5.kcfgc
+
+macro(GEN_KCFG_TEST_SOURCE _testName _srcs)
+ add_custom_command(
+ OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${_testName}.cpp ${CMAKE_CURRENT_BINARY_DIR}/${_testName}.h
+ COMMAND ${KConfig_KCFGC_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/${_testName}.kcfg ${CMAKE_CURRENT_SOURCE_DIR}/${_testName}.kcfgc
+ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${_testName}.kcfg ${CMAKE_CURRENT_SOURCE_DIR}/${_testName}.kcfgc kconfig_compiler)
+
+# set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/${_testName}.h PROPERTIES GENERATED TRUE)
+ qt5_generate_moc(${CMAKE_CURRENT_BINARY_DIR}/${_testName}.h ${CMAKE_CURRENT_BINARY_DIR}/${_testName}.moc )
+# do not run automoc on the generated file
+ set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/${_testName}.cpp PROPERTIES SKIP_AUTOMOC TRUE)
+ set( ${_srcs} ${${_srcs}} ${CMAKE_CURRENT_BINARY_DIR}/${_testName}.cpp ${CMAKE_CURRENT_BINARY_DIR}/${_testName}.h )
+
+ set_property(SOURCE ${CMAKE_CURRENT_BINARY_DIR}/${_testName}.cpp APPEND PROPERTY OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${_testName}.moc )
+endmacro(GEN_KCFG_TEST_SOURCE)
+
+include(ECMMarkAsTest)
+
+########### next target ###############
+
+set(test1_SRCS test1main.cpp )
+
+
+gen_kcfg_test_source(test1 test1_SRCS)
+
+add_executable(test1 ${test1_SRCS})
+ecm_mark_as_test(test1)
+target_link_libraries(test1 KF5::ConfigGui)
+
+
+########### next target ###############
+
+set(test2_SRCS test2main.cpp )
+
+
+gen_kcfg_test_source(test2 test2_SRCS)
+
+add_executable(test2 ${test2_SRCS})
+ecm_mark_as_test(test2)
+target_link_libraries(test2 KF5::ConfigGui)
+
+
+########### next target ###############
+
+set(test3_SRCS test3main.cpp )
+
+
+gen_kcfg_test_source(test3 test3_SRCS)
+
+add_executable(test3 ${test3_SRCS})
+ecm_mark_as_test(test3)
+target_link_libraries(test3 KF5::ConfigGui)
+
+
+########### next target ###############
+
+set(test3a_SRCS test3amain.cpp )
+
+
+gen_kcfg_test_source(test3a test3a_SRCS)
+
+add_executable(test3a ${test3a_SRCS})
+ecm_mark_as_test(test3a)
+target_link_libraries(test3a KF5::ConfigGui)
+
+
+########### next target ###############
+
+set(test4_SRCS test4main.cpp )
+
+
+gen_kcfg_test_source(test4 test4_SRCS)
+
+add_executable(test4 ${test4_SRCS})
+ecm_mark_as_test(test4)
+target_link_libraries(test4 KF5::ConfigGui)
+
+
+########### next target ###############
+
+set(test5_SRCS test5main.cpp )
+
+
+gen_kcfg_test_source(test5 test5_SRCS)
+
+add_executable(test5 ${test5_SRCS})
+ecm_mark_as_test(test5)
+target_link_libraries(test5 KF5::ConfigGui)
+
+
+########### next target ###############
+
+set(test6_SRCS test6main.cpp )
+
+
+gen_kcfg_test_source(test6 test6_SRCS)
+
+add_executable(test6 ${test6_SRCS})
+ecm_mark_as_test(test6)
+target_link_libraries(test6 KF5::ConfigGui)
+
+
+########### next target ###############
+
+set(test7_SRCS test7main.cpp )
+
+
+gen_kcfg_test_source(test7 test7_SRCS)
+
+add_executable(test7 ${test7_SRCS})
+ecm_mark_as_test(test7)
+target_link_libraries(test7 KF5::ConfigGui)
+
+
+########### next target ###############
+
+set(test8_SRCS test8main.cpp )
+
+
+gen_kcfg_test_source(test8a test8_SRCS)
+gen_kcfg_test_source(test8b test8_SRCS)
+
+add_executable(test8 ${test8_SRCS})
+ecm_mark_as_test(test8)
+target_link_libraries(test8 KF5::ConfigGui)
+
+
+########### next target ###############
+
+set(test9_SRCS test9main.cpp )
+
+
+gen_kcfg_test_source(test9 test9_SRCS)
+
+add_executable(test9 ${test9_SRCS})
+ecm_mark_as_test(test9)
+target_link_libraries(test9 KF5::ConfigGui)
+
+
+########### next target ###############
+
+set(test10_SRCS test10main.cpp )
+
+
+gen_kcfg_test_source(test10 test10_SRCS)
+
+add_executable(test10 ${test10_SRCS})
+ecm_mark_as_test(test10)
+target_link_libraries(test10 KF5::ConfigGui)
+
+
+########### next target ###############
+
+set(test11_SRCS test11main.cpp )
+
+
+gen_kcfg_test_source(test11 test11_SRCS)
+gen_kcfg_test_source(test11a test11_SRCS)
+
+add_executable(test11 ${test11_SRCS})
+ecm_mark_as_test(test11)
+target_link_libraries(test11 KF5::ConfigGui)
+
+
+########### next target ###############
+
+set(test12_SRCS test12main.cpp )
+
+gen_kcfg_test_source(test12 test12_SRCS)
+
+add_executable(test12 ${test12_SRCS})
+ecm_mark_as_test(test12)
+target_link_libraries(test12 KF5::ConfigGui)
+
+
+########### next target ###############
+
+set(test_dpointer_SRCS test_dpointer_main.cpp )
+
+gen_kcfg_test_source(test_dpointer test_dpointer_SRCS)
+
+add_executable(test_dpointer ${test_dpointer_SRCS})
+ecm_mark_as_test(test_dpointer)
+target_link_libraries(test_dpointer KF5::ConfigGui)
+
+
+########### next target ###############
+
+set(test_signal_SRCS test_signal_main.cpp )
+gen_kcfg_test_source(test_signal test_signal_SRCS)
+add_executable(test_signal ${test_signal_SRCS})
+ecm_mark_as_test(test_signal)
+target_link_libraries(test_signal KF5::ConfigGui)
+
+########### next target ###############
+
+set(kconfigcompiler_test_SRCS kconfigcompiler_test.cpp )
+add_executable(kconfigcompiler_test ${kconfigcompiler_test_SRCS})
+ecm_mark_as_test(kconfigcompiler_test)
+add_test(kconfig-kconfigcompiler kconfigcompiler_test)
+
+target_link_libraries(kconfigcompiler_test Qt5::Test )
+
+########### install files ###############
+
+
+
+
+
diff --git a/tier1/kconfig/autotests/kconfig_compiler/kconfigcompiler_test.cpp b/tier1/kconfig/autotests/kconfig_compiler/kconfigcompiler_test.cpp
new file mode 100644
index 00000000..a9bf52c8
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/kconfigcompiler_test.cpp
@@ -0,0 +1,181 @@
+/*
+ Tests for KConfig Compiler
+
+ Copyright (c) 2005 by Duncan Mac-Vicar <duncan@kde.org>
+ Copyright (c) 2009 by Pino Toscano <pino@kde.org>
+
+ *************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Lesser General Public *
+ * License as published by the Free Software Foundation; either *
+ * version 2 of the License, or (at your option) any later version. *
+ * *
+ *************************************************************************
+*/
+
+#include <QtCore/QDir>
+#include <QtCore/QFile>
+#include <QtCore/QProcess>
+#include <QtCore/QString>
+#include <QtTest/QtTest>
+#include <qstandardpaths.h>
+#include "kconfigcompiler_test.h"
+
+// QT5 TODO QTEST_GUILESS_MAIN(KConfigCompiler_Test)
+QTEST_MAIN(KConfigCompiler_Test)
+
+typedef const char * CompilerTestSet[];
+
+static CompilerTestSet testCases =
+{
+ "test1.cpp", "test1.h",
+ "test2.cpp", "test2.h",
+ "test3.cpp", "test3.h",
+ "test3a.cpp", "test3a.h",
+ "test4.cpp", "test4.h",
+ "test5.cpp", "test5.h",
+ "test6.cpp", "test6.h",
+ "test7.cpp", "test7.h",
+ "test8a.cpp", "test8a.h",
+ "test8b.cpp", "test8b.h",
+ "test9.h", "test9.cpp",
+ "test10.h", "test10.cpp",
+ "test11.h", "test11.cpp",
+ "test11a.h", "test11a.cpp",
+ "test12.h", "test12.cpp",
+ "test_dpointer.cpp", "test_dpointer.h",
+ "test_signal.cpp", "test_signal.h",
+ NULL
+};
+
+static CompilerTestSet testCasesToRun =
+{
+ "test1",
+ "test2",
+ "test3",
+ "test3a",
+ "test4",
+ "test5",
+ "test6",
+ "test7",
+ "test8",
+ "test9",
+ "test10",
+ "test11",
+ "test12",
+ "test_dpointer",
+ "test_signal",
+ 0
+};
+
+#if 0
+static CompilerTestSet willFailCases =
+{
+ // where is that QDir coming from?
+ //"test9.cpp", NULL
+ NULL
+};
+#endif
+
+void KConfigCompiler_Test::initTestCase()
+{
+ m_diffExe = QStandardPaths::findExecutable("diff");
+ if (!m_diffExe.isEmpty()) {
+ m_diff.setFileName(QDir::currentPath() + QLatin1String("/kconfigcompiler_test_differences.diff"));
+ if (m_diff.exists()) {
+ m_diff.remove();
+ }
+ }
+}
+
+void KConfigCompiler_Test::testBaselineComparison_data()
+{
+ QTest::addColumn<QString>("testName");
+
+ for (const char **it = testCases; *it; ++it) {
+ QTest::newRow(*it) << QString::fromLatin1(*it);
+ }
+}
+
+void KConfigCompiler_Test::testBaselineComparison()
+{
+ QFETCH(QString, testName);
+
+ QFile file(QFINDTESTDATA(testName));
+ QFile fileRef(QFINDTESTDATA(testName + QLatin1String(".ref")));
+
+ if (!file.open(QIODevice::ReadOnly)) {
+ qWarning() << "Failed to open" << file.fileName();
+ QFAIL("Can't open file for comparison");
+ }
+ if (!fileRef.open(QIODevice::ReadOnly)) {
+ qWarning() << "Failed to open" << fileRef.fileName();
+ QFAIL("Can't open file for comparison");
+ }
+ QString content = file.readAll();
+ QString contentRef = fileRef.readAll();
+
+ if (content != contentRef) {
+ appendFileDiff(fileRef.fileName(), file.fileName());
+ }
+ // use split('\n') to avoid
+ // the whole output shown inline
+ QCOMPARE(content.split('\n'), contentRef.split('\n'));
+ QVERIFY(content == contentRef);
+}
+
+void KConfigCompiler_Test::testRunning_data()
+{
+ QTest::addColumn<QString>("testName");
+
+ for (const char **it = testCasesToRun; *it; ++it) {
+ QTest::newRow(*it) << QString::fromLatin1(*it);
+ }
+}
+
+void KConfigCompiler_Test::testRunning()
+{
+ QFETCH(QString, testName);
+
+#ifdef Q_OS_WIN
+ testName += QStringLiteral(".exe");
+#endif
+
+ QString program = QFINDTESTDATA(testName);
+ QVERIFY2(QFile::exists(program), qPrintable(program + QLatin1String(" must exist!")));
+ QProcess process;
+ process.start(program, QIODevice::ReadOnly);
+ if (process.waitForStarted()) {
+ QVERIFY(process.waitForFinished());
+ }
+ QCOMPARE((int)process.error(), (int)QProcess::UnknownError);
+ QCOMPARE(process.exitCode(), 0);
+}
+
+
+void KConfigCompiler_Test::appendFileDiff(const QString &oldFile, const QString &newFile)
+{
+ if (m_diffExe.isEmpty()) {
+ return;
+ }
+ if (!m_diff.isOpen()) {
+ if (!m_diff.open(QIODevice::WriteOnly)) {
+ return;
+ }
+ }
+
+ QStringList args;
+ args << "-u";
+ args << QFileInfo(oldFile).absoluteFilePath();
+ args << QFileInfo(newFile).absoluteFilePath();
+
+ QProcess process;
+ process.start(m_diffExe, args, QIODevice::ReadOnly);
+ process.waitForStarted();
+ process.waitForFinished();
+ if (process.exitCode() == 1) {
+ QByteArray out = process.readAllStandardOutput();
+ m_diff.write(out);
+ }
+}
diff --git a/tier1/kconfig/autotests/kconfig_compiler/kconfigcompiler_test.h b/tier1/kconfig/autotests/kconfig_compiler/kconfigcompiler_test.h
new file mode 100644
index 00000000..53ad18a0
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/kconfigcompiler_test.h
@@ -0,0 +1,42 @@
+/*
+ Tests for KConfig Compiler
+
+ Copyright (c) 2005 by Duncan Mac-Vicar <duncan@kde.org>
+ Copyright (c) 2009 by Pino Toscano <pino@kde.org>
+
+ *************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Lesser General Public *
+ * License as published by the Free Software Foundation; either *
+ * version 2 of the License, or (at your option) any later version. *
+ * *
+ *************************************************************************
+*/
+
+#ifndef KCONFIGCOMPILER_TEST_H
+#define KCONFIGCOMPILER_TEST_H
+
+#include <QtCore/QFile>
+#include <QtCore/QObject>
+
+class QString;
+
+class KConfigCompiler_Test : public QObject
+{
+ Q_OBJECT
+private Q_SLOTS:
+ void initTestCase();
+ void testBaselineComparison_data();
+ void testBaselineComparison();
+ void testRunning_data();
+ void testRunning();
+private:
+ void appendFileDiff(const QString &oldFile, const QString &newFile);
+
+ QString m_diffExe;
+ QFile m_diff;
+};
+
+#endif
+
diff --git a/tier1/kconfig/autotests/kconfig_compiler/myprefs.h b/tier1/kconfig/autotests/kconfig_compiler/myprefs.h
new file mode 100644
index 00000000..4d12eeb7
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/myprefs.h
@@ -0,0 +1,12 @@
+#ifndef MYPREFS_H
+#define MYPREFS_H
+
+#include <kconfigskeleton.h>
+
+class MyPrefs : public KConfigSkeleton
+{
+ public:
+ MyPrefs( const QString &a ) : KConfigSkeleton( a ) {}
+};
+
+#endif
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test1.cpp.ref b/tier1/kconfig/autotests/kconfig_compiler/test1.cpp.ref
new file mode 100644
index 00000000..611ce5c1
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test1.cpp.ref
@@ -0,0 +1,72 @@
+// This file is generated by kconfig_compiler from test1.kcfg.
+// All changes you do to this file will be lost.
+
+#include "test1.h"
+
+Test1::Test1( const QString & transport, const QString & folder )
+ : KConfigSkeleton( QLatin1String( "examplerc" ) )
+ , mParamtransport(transport)
+ , mParamfolder(folder)
+{
+ setCurrentGroup( QString( QLatin1String( "General-%1" ) ).arg( mParamfolder ) );
+
+ KConfigSkeleton::ItemBool *itemOneOption;
+ itemOneOption = new KConfigSkeleton::ItemBool( currentGroup(), QLatin1String( "OneOption" ), mOneOption, true );
+ addItem( itemOneOption, QLatin1String( "OneOption" ) );
+ KConfigSkeleton::ItemInt *itemAnotherOption;
+ itemAnotherOption = new KConfigSkeleton::ItemInt( currentGroup(), QLatin1String( "Another Option" ), mAnotherOption, 5 );
+ addItem( itemAnotherOption, QLatin1String( "AnotherOption" ) );
+ QList<KConfigSkeleton::ItemEnum::Choice> valuesListOption;
+ {
+ KConfigSkeleton::ItemEnum::Choice choice;
+ choice.name = QLatin1String("One");
+ valuesListOption.append( choice );
+ }
+ {
+ KConfigSkeleton::ItemEnum::Choice choice;
+ choice.name = QLatin1String("Two");
+ valuesListOption.append( choice );
+ }
+ {
+ KConfigSkeleton::ItemEnum::Choice choice;
+ choice.name = QLatin1String("Three");
+ valuesListOption.append( choice );
+ }
+ KConfigSkeleton::ItemEnum *itemListOption;
+ itemListOption = new KConfigSkeleton::ItemEnum( currentGroup(), QLatin1String( "ListOption" ), mListOption, valuesListOption, EnumListOption::One );
+ addItem( itemListOption, QLatin1String( "ListOption" ) );
+
+ setCurrentGroup( QLatin1String( "MyOptions" ) );
+
+ KConfigSkeleton::ItemString *itemMyString;
+ itemMyString = new KConfigSkeleton::ItemString( currentGroup(), QLatin1String( "MyString" ), mMyString, QLatin1String( "Default String" ) );
+ addItem( itemMyString, QLatin1String( "MyString" ) );
+ KConfigSkeleton::ItemPath *itemMyPath;
+ itemMyPath = new KConfigSkeleton::ItemPath( currentGroup(), QLatin1String( "MyPath" ), mMyPath, QDir::homePath()+QString::fromLatin1(".hidden_file") );
+ addItem( itemMyPath, QLatin1String( "MyPath" ) );
+ KConfigSkeleton::ItemInt *itemAnotherOption2;
+ itemAnotherOption2 = new KConfigSkeleton::ItemInt( currentGroup(), QLatin1String( "Another Option" ), mAnotherOption2, 10 );
+ addItem( itemAnotherOption2, QLatin1String( "AnotherOption2" ) );
+ QStringList defaultMyStringList;
+ defaultMyStringList.append( QString::fromUtf8( "up" ) );
+ defaultMyStringList.append( QString::fromUtf8( "down" ) );
+
+ KConfigSkeleton::ItemStringList *itemMyStringList;
+ itemMyStringList = new KConfigSkeleton::ItemStringList( currentGroup(), QLatin1String( "MyStringList" ), mMyStringList, defaultMyStringList );
+ addItem( itemMyStringList, QLatin1String( "MyStringList" ) );
+ QStringList defaultMyStringListHidden;
+ defaultMyStringListHidden.append( QString::fromUtf8( "up" ) );
+ defaultMyStringListHidden.append( QString::fromUtf8( "down" ) );
+
+ KConfigSkeleton::ItemStringList *itemMyStringListHidden;
+ itemMyStringListHidden = new KConfigSkeleton::ItemStringList( currentGroup(), QLatin1String( "MyStringListHidden" ), mMyStringListHidden, defaultMyStringListHidden );
+ addItem( itemMyStringListHidden, QLatin1String( "MyStringListHidden" ) );
+ KConfigSkeleton::ItemInt *itemMyNumber;
+ itemMyNumber = new KConfigSkeleton::ItemInt( currentGroup(), QString( QLatin1String( "List-%1-%2" ) ).arg( mParamtransport ).arg( mParamfolder ), mMyNumber, 1 );
+ addItem( itemMyNumber, QLatin1String( "MyNumber" ) );
+}
+
+Test1::~Test1()
+{
+}
+
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test1.h.ref b/tier1/kconfig/autotests/kconfig_compiler/test1.h.ref
new file mode 100644
index 00000000..57fa4bf8
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test1.h.ref
@@ -0,0 +1,197 @@
+// This file is generated by kconfig_compiler from test1.kcfg.
+// All changes you do to this file will be lost.
+#ifndef TEST1_H
+#define TEST1_H
+
+#include <kconfigskeleton.h>
+#include <QCoreApplication>
+#include <QDebug>
+
+#include <qdir.h>
+class Test1 : public KConfigSkeleton
+{
+ public:
+ class EnumListOption
+ {
+ public:
+ enum type { One, Two, Three, COUNT };
+ };
+
+ Test1( const QString & transport, const QString & folder );
+ ~Test1();
+
+ /**
+ Set One option
+ */
+ void setOneOption( bool v )
+ {
+ if (!isImmutable( QString::fromLatin1( "OneOption" ) ))
+ mOneOption = v;
+ }
+
+ /**
+ Get One option
+ */
+ bool oneOption() const
+ {
+ return mOneOption;
+ }
+
+ /**
+ Set Another option
+ */
+ void setAnotherOption( int v )
+ {
+ if (!isImmutable( QString::fromLatin1( "AnotherOption" ) ))
+ mAnotherOption = v;
+ }
+
+ /**
+ Get Another option
+ */
+ int anotherOption() const
+ {
+ return mAnotherOption;
+ }
+
+ /**
+ Set This is some funky option
+ */
+ void setListOption( int v )
+ {
+ if (!isImmutable( QString::fromLatin1( "ListOption" ) ))
+ mListOption = v;
+ }
+
+ /**
+ Get This is some funky option
+ */
+ int listOption() const
+ {
+ return mListOption;
+ }
+
+ /**
+ Set This is a string
+ */
+ void setMyString( const QString & v )
+ {
+ if (!isImmutable( QString::fromLatin1( "MyString" ) ))
+ mMyString = v;
+ }
+
+ /**
+ Get This is a string
+ */
+ QString myString() const
+ {
+ return mMyString;
+ }
+
+ /**
+ Set This is a path
+ */
+ void setMyPath( const QString & v )
+ {
+ if (!isImmutable( QString::fromLatin1( "MyPath" ) ))
+ mMyPath = v;
+ }
+
+ /**
+ Get This is a path
+ */
+ QString myPath() const
+ {
+ return mMyPath;
+ }
+
+ /**
+ Set Another option
+ */
+ void setAnotherOption2( int v )
+ {
+ if (!isImmutable( QString::fromLatin1( "AnotherOption2" ) ))
+ mAnotherOption2 = v;
+ }
+
+ /**
+ Get Another option
+ */
+ int anotherOption2() const
+ {
+ return mAnotherOption2;
+ }
+
+ /**
+ Set MyStringList
+ */
+ void setMyStringList( const QStringList & v )
+ {
+ if (!isImmutable( QString::fromLatin1( "MyStringList" ) ))
+ mMyStringList = v;
+ }
+
+ /**
+ Get MyStringList
+ */
+ QStringList myStringList() const
+ {
+ return mMyStringList;
+ }
+
+ /**
+ Set MyStringListHidden
+ */
+ void setMyStringListHidden( const QStringList & v )
+ {
+ if (!isImmutable( QString::fromLatin1( "MyStringListHidden" ) ))
+ mMyStringListHidden = v;
+ }
+
+ /**
+ Get MyStringListHidden
+ */
+ QStringList myStringListHidden() const
+ {
+ return mMyStringListHidden;
+ }
+
+ /**
+ Set List Number
+ */
+ void setMyNumber( int v )
+ {
+ if (!isImmutable( QString::fromLatin1( "MyNumber" ) ))
+ mMyNumber = v;
+ }
+
+ /**
+ Get List Number
+ */
+ int myNumber() const
+ {
+ return mMyNumber;
+ }
+
+ protected:
+ QString mParamtransport;
+ QString mParamfolder;
+
+ // General-$(folder)
+ bool mOneOption;
+ int mAnotherOption;
+ int mListOption;
+
+ // MyOptions
+ QString mMyString;
+ QString mMyPath;
+ int mAnotherOption2;
+ QStringList mMyStringList;
+ QStringList mMyStringListHidden;
+ int mMyNumber;
+
+ private:
+};
+
+#endif
+
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test1.kcfg b/tier1/kconfig/autotests/kconfig_compiler/test1.kcfg
new file mode 100644
index 00000000..819bdac5
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test1.kcfg
@@ -0,0 +1,55 @@
+<?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" >
+ <include>qdir.h</include>
+ <kcfgfile name="examplerc">
+ <parameter name="transport" />
+ <parameter name="folder" />
+ </kcfgfile>
+ <group name="General-$(folder)">
+ <entry name="OneOption" type="Bool">
+ <label>One option</label>
+ <default>true</default>
+ </entry>
+ <entry name="AnotherOption" type="Int" key="Another Option">
+ <label>Another option</label>
+ <default>5</default>
+ </entry>
+ <entry name="ListOption" type="Enum">
+ <label>This is some funky option</label>
+ <whatsthis>And this is a longer description of this option. Just wondering, how will the translations of those be handled?</whatsthis>
+ <choices>
+ <choice name="One"/>
+ <choice name="Two"/>
+ <choice name="Three"/>
+ </choices>
+ <default>One</default>
+ </entry>
+ </group>
+ <group name="MyOptions">
+ <entry name="MyString" type="String">
+ <label>This is a string</label>
+ <default>Default String</default>
+ </entry>
+ <entry name="MyPath" type="Path">
+ <label>This is a path</label>
+ <default code="true">QDir::homePath()+QString::fromLatin1(".hidden_file")</default>
+ </entry>
+ <entry name="AnotherOption2" type="Int" key="Another Option">
+ <label>Another option</label>
+ <default>10</default>
+ </entry>
+ <entry name="MyStringList" type="StringList">
+ <default>up,down</default>
+ </entry>
+ <entry name="MyStringListHidden" hidden="true" type="StringList">
+ <default>up,down</default>
+ </entry>
+ <entry name="MyNumber" type="Int" key="List-$(transport)-$(folder)">
+ <label>List Number</label>
+ <default>1</default>
+ </entry>
+ </group>
+</kcfg>
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test1.kcfgc b/tier1/kconfig/autotests/kconfig_compiler/test1.kcfgc
new file mode 100644
index 00000000..6e0edd36
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test1.kcfgc
@@ -0,0 +1,18 @@
+# Code generation options for kconfig_compiler
+ClassName=Test1
+#
+# Singleton=false
+#
+# Inherits=KConfigSkeleton
+#
+# IncludeFiles=libkdepim/kpimprefs.h
+#
+# MemberVariables=public
+#
+### The following line includes the file exampleprefs_base_addon.h
+### It can be used to add extra functions and variables to the
+### class.
+# CustomAdditions=true
+#
+### Provide setFooBar(int) style functions
+Mutators=true
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test10.cpp.ref b/tier1/kconfig/autotests/kconfig_compiler/test10.cpp.ref
new file mode 100644
index 00000000..ac28ab2f
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test10.cpp.ref
@@ -0,0 +1,46 @@
+// This file is generated by kconfig_compiler from test10.kcfg.
+// All changes you do to this file will be lost.
+
+#include "test10.h"
+
+#include <qglobal.h>
+#include <QtCore/QFile>
+
+class Test10Helper
+{
+ public:
+ Test10Helper() : q(0) {}
+ ~Test10Helper() { delete q; }
+ Test10 *q;
+};
+Q_GLOBAL_STATIC(Test10Helper, s_globalTest10)
+Test10 *Test10::self()
+{
+ if (!s_globalTest10()->q) {
+ new Test10;
+ s_globalTest10()->q->readConfig();
+ }
+
+ return s_globalTest10()->q;
+}
+
+Test10::Test10( )
+ : KConfigSkeleton( QLatin1String( "test10rc" ) )
+{
+ Q_ASSERT(!s_globalTest10()->q);
+ s_globalTest10()->q = this;
+ setCurrentGroup( QLatin1String( "Foo" ) );
+
+ KConfigSkeleton::ItemUrl *itemFooBar;
+ itemFooBar = new KConfigSkeleton::ItemUrl( currentGroup(), QLatin1String( "foo bar" ), mFooBar );
+ addItem( itemFooBar, QLatin1String( "FooBar" ) );
+ KConfigSkeleton::ItemUrlList *itemBarFoo;
+ itemBarFoo = new KConfigSkeleton::ItemUrlList( currentGroup(), QLatin1String( "bar foo" ), mBarFoo );
+ addItem( itemBarFoo, QLatin1String( "BarFoo" ) );
+}
+
+Test10::~Test10()
+{
+ s_globalTest10()->q = 0;
+}
+
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test10.h.ref b/tier1/kconfig/autotests/kconfig_compiler/test10.h.ref
new file mode 100644
index 00000000..f3f441d3
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test10.h.ref
@@ -0,0 +1,50 @@
+// This file is generated by kconfig_compiler from test10.kcfg.
+// All changes you do to this file will be lost.
+#ifndef TEST10_H
+#define TEST10_H
+
+#include <kconfigskeleton.h>
+#include <QCoreApplication>
+#include <QDebug>
+
+class Test10 : public KConfigSkeleton
+{
+ public:
+
+ static Test10 *self();
+ ~Test10();
+
+
+ /**
+ Get foo bar
+ */
+ static
+ QUrl fooBar()
+ {
+ return self()->mFooBar;
+ }
+
+
+ /**
+ Get bar foo
+ */
+ static
+ QList<QUrl> barFoo()
+ {
+ return self()->mBarFoo;
+ }
+
+ protected:
+ Test10();
+ friend class Test10Helper;
+
+
+ // Foo
+ QUrl mFooBar;
+ QList<QUrl> mBarFoo;
+
+ private:
+};
+
+#endif
+
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test10.kcfg b/tier1/kconfig/autotests/kconfig_compiler/test10.kcfg
new file mode 100644
index 00000000..d7be2c3d
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test10.kcfg
@@ -0,0 +1,13 @@
+<?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="test10rc"/>
+
+ <group name="Foo">
+ <entry name="FooBar" key="foo bar" type="Url"/>
+ <entry name="BarFoo" key="bar foo" type="UrlList"/>
+ </group>
+
+</kcfg>
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test10.kcfgc b/tier1/kconfig/autotests/kconfig_compiler/test10.kcfgc
new file mode 100644
index 00000000..83ac2111
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test10.kcfgc
@@ -0,0 +1,4 @@
+# Code generation options for kconfig_compiler
+File=test10.kcfg
+ClassName=Test10
+Singleton=true
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test10main.cpp b/tier1/kconfig/autotests/kconfig_compiler/test10main.cpp
new file mode 100644
index 00000000..9e9a7db8
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test10main.cpp
@@ -0,0 +1,32 @@
+/*
+Copyright (c) 2007 Andreas Pakulat <apaku@gmx.de>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "test10.h"
+#include <QGuiApplication>
+
+int main( int argc, char **argv )
+{
+ QGuiApplication app(argc, argv);
+ Q_UNUSED(app);
+ Test10 *t = Test10::self();
+ delete t;
+ return 0;
+}
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test11.cpp.ref b/tier1/kconfig/autotests/kconfig_compiler/test11.cpp.ref
new file mode 100644
index 00000000..5a1f5b92
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test11.cpp.ref
@@ -0,0 +1,278 @@
+// This file is generated by kconfig_compiler from test11.kcfg.
+// All changes you do to this file will be lost.
+
+#include "test11.h"
+
+Test11::Test11( )
+ : MyPrefs( QLatin1String( "korganizerrc" ) )
+{
+ setCurrentGroup( QLatin1String( "General" ) );
+
+ mAutoSaveItem = new MyPrefs::ItemBool( currentGroup(), QLatin1String( "Auto Save" ), mAutoSave, false );
+ mAutoSaveItem->setLabel( QCoreApplication::translate("Test11", "Enable automatic saving of calendar") );
+ mAutoSaveItem->setWhatsThis( QCoreApplication::translate("Test11", "WhatsThis text for AutoSave option") );
+ addItem( mAutoSaveItem, QLatin1String( "AutoSave" ) );
+ mAutoSaveIntervalItem = new MyPrefs::ItemInt( currentGroup(), QLatin1String( "Auto Save Interval" ), mAutoSaveInterval, 10 );
+ mAutoSaveIntervalItem->setLabel( QCoreApplication::translate("Test11", "Auto Save Interval") );
+ addItem( mAutoSaveIntervalItem, QLatin1String( "AutoSaveInterval" ) );
+ mConfirmItem = new MyPrefs::ItemBool( currentGroup(), QLatin1String( "Confirm Deletes" ), mConfirm, true );
+ mConfirmItem->setLabel( QCoreApplication::translate("Test11", "Confirm deletes") );
+ addItem( mConfirmItem, QLatin1String( "Confirm" ) );
+ mArchiveFileItem = new MyPrefs::ItemString( currentGroup(), QLatin1String( "Archive File" ), mArchiveFile );
+ mArchiveFileItem->setLabel( QCoreApplication::translate("Test11", "Archive File") );
+ addItem( mArchiveFileItem, QLatin1String( "ArchiveFile" ) );
+ QList<MyPrefs::ItemEnum::Choice> valuesDestination;
+ {
+ MyPrefs::ItemEnum::Choice choice;
+ choice.name = QLatin1String("standardDestination");
+ valuesDestination.append( choice );
+ }
+ {
+ MyPrefs::ItemEnum::Choice choice;
+ choice.name = QLatin1String("askDestination");
+ valuesDestination.append( choice );
+ }
+ {
+ MyPrefs::ItemEnum::Choice choice;
+ choice.name = QLatin1String("argl1");
+ choice.label = QCoreApplication::translate("Test11", "Argl1 Label");
+ valuesDestination.append( choice );
+ }
+ {
+ MyPrefs::ItemEnum::Choice choice;
+ choice.name = QLatin1String("argl2");
+ choice.whatsThis = QCoreApplication::translate("Test11", "Argl2 Whatsthis");
+ valuesDestination.append( choice );
+ }
+ {
+ MyPrefs::ItemEnum::Choice choice;
+ choice.name = QLatin1String("argl3");
+ choice.label = QCoreApplication::translate("Test11", "Argl3 Label");
+ choice.whatsThis = QCoreApplication::translate("Test11", "Argl3 Whatsthis");
+ valuesDestination.append( choice );
+ }
+ mDestinationItem = new MyPrefs::ItemEnum( currentGroup(), QLatin1String( "Destination" ), mDestination, valuesDestination, EnumDestination::standardDestination );
+ mDestinationItem->setLabel( QCoreApplication::translate("Test11", "New Events/Todos Should") );
+ addItem( mDestinationItem, QLatin1String( "Destination" ) );
+
+ setCurrentGroup( QLatin1String( "Views" ) );
+
+ mHourSizeItem = new MyPrefs::ItemInt( currentGroup(), QLatin1String( "Hour Size" ), mHourSize, 10 );
+ mHourSizeItem->setLabel( QCoreApplication::translate("Test11", "Hour Size") );
+ addItem( mHourSizeItem, QLatin1String( "HourSize" ) );
+ mSelectionStartsEditorItem = new MyPrefs::ItemBool( currentGroup(), QLatin1String( "SelectionStartsEditor" ), mSelectionStartsEditor, false );
+ mSelectionStartsEditorItem->setLabel( QCoreApplication::translate("Test11", "Time range selection in agenda view starts event editor") );
+ addItem( mSelectionStartsEditorItem, QLatin1String( "SelectionStartsEditor" ) );
+
+ setCurrentGroup( QLatin1String( "KOrganizer Plugins" ) );
+
+ QStringList defaultSelectedPlugins;
+ defaultSelectedPlugins.append( QString::fromUtf8( "holidays" ) );
+ defaultSelectedPlugins.append( QString::fromUtf8( "webexport" ) );
+
+ mSelectedPluginsItem = new MyPrefs::ItemStringList( currentGroup(), QLatin1String( "SelectedPlugins" ), mSelectedPlugins, defaultSelectedPlugins );
+ mSelectedPluginsItem->setLabel( QCoreApplication::translate("Test11", "SelectedPlugins") );
+ addItem( mSelectedPluginsItem, QLatin1String( "SelectedPlugins" ) );
+
+ setCurrentGroup( QLatin1String( "Colors" ) );
+
+ mHighlightColorItem = new MyPrefs::ItemColor( currentGroup(), QLatin1String( "Highlight Color" ), mHighlightColor, QColor( 100, 100, 255 ) );
+ mHighlightColorItem->setLabel( QCoreApplication::translate("Test11", "Highlight color") );
+ addItem( mHighlightColorItem, QLatin1String( "HighlightColor" ) );
+ mAgendaBgColorItem = new MyPrefs::ItemColor( currentGroup(), QLatin1String( "Agenda Background Color" ), mAgendaBgColor, QColor( 255, 255, 255 ) );
+ mAgendaBgColorItem->setLabel( QCoreApplication::translate("Test11", "Agenda view background color") );
+ addItem( mAgendaBgColorItem, QLatin1String( "AgendaBgColor" ) );
+
+ setCurrentGroup( QLatin1String( "Fonts" ) );
+
+ mTimeBarFontItem = new MyPrefs::ItemFont( currentGroup(), QLatin1String( "TimeBar Font" ), mTimeBarFont );
+ mTimeBarFontItem->setLabel( QCoreApplication::translate("Test11", "Time bar") );
+ addItem( mTimeBarFontItem, QLatin1String( "TimeBarFont" ) );
+
+ setCurrentGroup( QLatin1String( "Email" ) );
+
+ QList<MyPrefs::ItemEnum::Choice> valuesEmailClient;
+ {
+ MyPrefs::ItemEnum::Choice choice;
+ choice.name = QLatin1String("sendmail");
+ choice.label = /*: @option */ QCoreApplication::translate("Test11", "Sendmail");
+ valuesEmailClient.append( choice );
+ }
+ {
+ MyPrefs::ItemEnum::Choice choice;
+ choice.name = QLatin1String("kmail");
+ choice.label = /*: @option */ QCoreApplication::translate("Test11", "KMail");
+ valuesEmailClient.append( choice );
+ }
+ mEmailClientItem = new MyPrefs::ItemEnum( currentGroup(), QLatin1String( "EmailClient" ), mEmailClient, valuesEmailClient, kmail );
+ mEmailClientItem->setLabel( /*: @label */ QCoreApplication::translate("Test11", "Email client") );
+ mEmailClientItem->setWhatsThis( /*: @info:whatsthis */ QCoreApplication::translate("Test11", "<para>How to send email when an email alarm is triggered.<list><item>KMail: The email is sent automatically via <application>KMail</application>. <application>KMail</application> is started first if necessary.</item><item>Sendmail: The email is sent automatically. This option will only work if your system is configured to use <application>sendmail</application> or a sendmail compatible mail transport agent.</item></list></para>") );
+ addItem( mEmailClientItem, QLatin1String( "EmailClient" ) );
+ QList<MyPrefs::ItemEnum::Choice> valuesDefaultReminderUnits;
+ {
+ MyPrefs::ItemEnum::Choice choice;
+ choice.name = QLatin1String("Minutes");
+ valuesDefaultReminderUnits.append( choice );
+ }
+ {
+ MyPrefs::ItemEnum::Choice choice;
+ choice.name = QLatin1String("HoursMinutes");
+ choice.label = /*: @option */ QCoreApplication::translate("Test11", "Hours/Minutes");
+ valuesDefaultReminderUnits.append( choice );
+ }
+ mDefaultReminderUnitsItem = new MyPrefs::ItemEnum( currentGroup(), QLatin1String( "RemindUnits" ), mDefaultReminderUnits, valuesDefaultReminderUnits, TimePeriod::HoursMinutes );
+ mDefaultReminderUnitsItem->setLabel( /*: @label */ QCoreApplication::translate("Test11", "Reminder units") );
+ mDefaultReminderUnitsItem->setToolTip( /*: @info:tooltip */ QCoreApplication::translate("Test11", "Default reminder time units in the alarm edit dialog.") );
+ mDefaultReminderUnitsItem->setWhatsThis( /*: @info:whatsthis */ QCoreApplication::translate("Test11", "Default reminder time units in the alarm edit dialog.") );
+ addItem( mDefaultReminderUnitsItem, QLatin1String( "DefaultReminderUnits" ) );
+
+ setCurrentGroup( QLatin1String( "QueueRates" ) );
+
+ QList< QList<int> > defaultRate;
+ QList< int > defaultRateInit;
+
+ defaultRateInit.append( 15 );
+ defaultRateInit.append( 60 );
+ defaultRateInit.append( 0 );
+ defaultRate.append( defaultRateInit );
+
+ defaultRateInit.clear();
+ defaultRateInit.append( 40 );
+ defaultRateInit.append( 60 );
+ defaultRateInit.append( 0 );
+ defaultRate.append( defaultRateInit );
+
+ defaultRateInit.clear();
+ defaultRateInit.append( 1 );
+ defaultRateInit.append( 1 );
+ defaultRateInit.append( 0 );
+ defaultRate.append( defaultRateInit );
+
+ QList<int> defaultqueueRate;
+
+ mQueueRateItem[0] = new MyPrefs::ItemIntList( currentGroup(), QLatin1String( "EmptyingRate 0" ), mQueueRate[0], defaultRate[0] );
+ mQueueRateItem[0]->setLabel( QCoreApplication::translate("Test11", "EmptyingRate queueRate$(QueueIndex)") );
+ addItem( mQueueRateItem[0], QLatin1String( "queueRate0" ) );
+ mQueueRateItem[1] = new MyPrefs::ItemIntList( currentGroup(), QLatin1String( "EmptyingRate 1" ), mQueueRate[1], defaultqueueRate );
+ mQueueRateItem[1]->setLabel( QCoreApplication::translate("Test11", "EmptyingRate queueRate$(QueueIndex)") );
+ addItem( mQueueRateItem[1], QLatin1String( "queueRate1" ) );
+ mQueueRateItem[2] = new MyPrefs::ItemIntList( currentGroup(), QLatin1String( "EmptyingRate 2" ), mQueueRate[2], defaultRate[2] );
+ mQueueRateItem[2]->setLabel( QCoreApplication::translate("Test11", "EmptyingRate queueRate$(QueueIndex)") );
+ addItem( mQueueRateItem[2], QLatin1String( "queueRate2" ) );
+ mShowQueueTunerItem = new MyPrefs::ItemBool( currentGroup(), QLatin1String( "ShowQueueTuner" ), mShowQueueTuner, false );
+ mShowQueueTunerItem->setLabel( QCoreApplication::translate("Test11", "ShowQueueTuner") );
+ addItem( mShowQueueTunerItem, QLatin1String( "ShowQueueTuner" ) );
+}
+
+bool Test11::defaultAutoSaveValue_helper() const
+{
+
+ return false;
+}
+
+int Test11::defaultAutoSaveIntervalValue_helper() const
+{
+
+ return 10;
+}
+
+bool Test11::defaultConfirmValue_helper() const
+{
+
+ return true;
+}
+
+int Test11::defaultDestinationValue_helper() const
+{
+
+ return EnumDestination::standardDestination;
+}
+
+int Test11::defaultHourSizeValue_helper() const
+{
+
+ return 10;
+}
+
+bool Test11::defaultSelectionStartsEditorValue_helper() const
+{
+
+ return false;
+}
+
+QStringList Test11::defaultSelectedPluginsValue_helper() const
+{
+ QStringList defaultSelectedPlugins;
+ defaultSelectedPlugins.append( QString::fromUtf8( "holidays" ) );
+ defaultSelectedPlugins.append( QString::fromUtf8( "webexport" ) );
+
+ return defaultSelectedPlugins;
+}
+
+QColor Test11::defaultHighlightColorValue_helper() const
+{
+
+ return QColor( 100, 100, 255 );
+}
+
+QColor Test11::defaultAgendaBgColorValue_helper() const
+{
+
+ return QColor( 255, 255, 255 );
+}
+
+int Test11::defaultEmailClientValue_helper() const
+{
+
+ return kmail;
+}
+
+int Test11::defaultDefaultReminderUnitsValue_helper() const
+{
+
+ return TimePeriod::HoursMinutes;
+}
+
+QList<int> Test11::defaultQueueRateValue_helper( int i ) const
+{
+ QList< QList<int> > defaultRate;
+ QList< int > defaultRateInit;
+
+ defaultRateInit.append( 15 );
+ defaultRateInit.append( 60 );
+ defaultRateInit.append( 0 );
+ defaultRate.append( defaultRateInit );
+
+ defaultRateInit.clear();
+ defaultRateInit.append( 40 );
+ defaultRateInit.append( 60 );
+ defaultRateInit.append( 0 );
+ defaultRate.append( defaultRateInit );
+
+ defaultRateInit.clear();
+ defaultRateInit.append( 1 );
+ defaultRateInit.append( 1 );
+ defaultRateInit.append( 0 );
+ defaultRate.append( defaultRateInit );
+
+ QList<int> defaultqueueRate;
+
+ switch (i) {
+ case 0: return defaultRate[0];
+ case 2: return defaultRate[2];
+ default:
+ return defaultqueueRate;
+ }
+
+}
+
+bool Test11::defaultShowQueueTunerValue_helper() const
+{
+
+ return false;
+}
+
+Test11::~Test11()
+{
+}
+
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test11.h.ref b/tier1/kconfig/autotests/kconfig_compiler/test11.h.ref
new file mode 100644
index 00000000..b5eeb74c
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test11.h.ref
@@ -0,0 +1,572 @@
+// This file is generated by kconfig_compiler from test11.kcfg.
+// All changes you do to this file will be lost.
+#ifndef TEST11_H
+#define TEST11_H
+
+#include <myprefs.h>
+
+#include <qglobal.h>
+#include <kconfigskeleton.h>
+#include <QCoreApplication>
+#include <QDebug>
+
+#include "test11_types.h"
+class Test11 : public MyPrefs
+{
+ public:
+ class EnumDestination
+ {
+ public:
+ enum type { standardDestination, askDestination, argl1, argl2, argl3, COUNT };
+ };
+ enum MailClient { sendmail, kmail };
+
+ Test11( );
+ ~Test11();
+
+ /**
+ Set Enable automatic saving of calendar
+ */
+ void setAutoSave( bool v )
+ {
+ if (!isImmutable( QString::fromLatin1( "AutoSave" ) ))
+ mAutoSave = v;
+ }
+
+ /**
+ Get Enable automatic saving of calendar
+ */
+ bool autoSave() const
+ {
+ return mAutoSave;
+ }
+
+ /**
+ Get Enable automatic saving of calendar default value
+ */
+ bool defaultAutoSaveValue() const
+ {
+ return defaultAutoSaveValue_helper();
+ }
+
+ /**
+ Get Item object corresponding to AutoSave()
+ */
+ ItemBool *autoSaveItem()
+ {
+ return mAutoSaveItem;
+ }
+
+ /**
+ Set Auto Save Interval
+ */
+ void setAutoSaveInterval( int v )
+ {
+ if (!isImmutable( QString::fromLatin1( "AutoSaveInterval" ) ))
+ mAutoSaveInterval = v;
+ }
+
+ /**
+ Get Auto Save Interval
+ */
+ int autoSaveInterval() const
+ {
+ return mAutoSaveInterval;
+ }
+
+ /**
+ Get Auto Save Interval default value
+ */
+ int defaultAutoSaveIntervalValue() const
+ {
+ return defaultAutoSaveIntervalValue_helper();
+ }
+
+ /**
+ Get Item object corresponding to AutoSaveInterval()
+ */
+ ItemInt *autoSaveIntervalItem()
+ {
+ return mAutoSaveIntervalItem;
+ }
+
+ /**
+ Set Confirm deletes
+ */
+ void setConfirm( bool v )
+ {
+ if (!isImmutable( QString::fromLatin1( "Confirm" ) ))
+ mConfirm = v;
+ }
+
+ /**
+ Get Confirm deletes
+ */
+ bool confirm() const
+ {
+ return mConfirm;
+ }
+
+ /**
+ Get Confirm deletes default value
+ */
+ bool defaultConfirmValue() const
+ {
+ return defaultConfirmValue_helper();
+ }
+
+ /**
+ Get Item object corresponding to Confirm()
+ */
+ ItemBool *confirmItem()
+ {
+ return mConfirmItem;
+ }
+
+ /**
+ Set Archive File
+ */
+ void setArchiveFile( const QString & v )
+ {
+ if (!isImmutable( QString::fromLatin1( "ArchiveFile" ) ))
+ mArchiveFile = v;
+ }
+
+ /**
+ Get Archive File
+ */
+ QString archiveFile() const
+ {
+ return mArchiveFile;
+ }
+
+ /**
+ Get Item object corresponding to ArchiveFile()
+ */
+ ItemString *archiveFileItem()
+ {
+ return mArchiveFileItem;
+ }
+
+ /**
+ Set New Events/Todos Should
+ */
+ void setDestination( EnumDestination::type v )
+ {
+ if (!isImmutable( QString::fromLatin1( "Destination" ) ))
+ mDestination = v;
+ }
+
+ /**
+ Get New Events/Todos Should
+ */
+ EnumDestination::type destination() const
+ {
+ return static_cast<EnumDestination::type>(mDestination);
+ }
+
+ /**
+ Get New Events/Todos Should default value
+ */
+ EnumDestination::type defaultDestinationValue() const
+ {
+ return static_cast<EnumDestination::type>(defaultDestinationValue_helper());
+ }
+
+ /**
+ Get Item object corresponding to Destination()
+ */
+ ItemEnum *destinationItem()
+ {
+ return mDestinationItem;
+ }
+
+ /**
+ Set Hour Size
+ */
+ void setHourSize( int v )
+ {
+ if (!isImmutable( QString::fromLatin1( "HourSize" ) ))
+ mHourSize = v;
+ }
+
+ /**
+ Get Hour Size
+ */
+ int hourSize() const
+ {
+ return mHourSize;
+ }
+
+ /**
+ Get Hour Size default value
+ */
+ int defaultHourSizeValue() const
+ {
+ return defaultHourSizeValue_helper();
+ }
+
+ /**
+ Get Item object corresponding to HourSize()
+ */
+ ItemInt *hourSizeItem()
+ {
+ return mHourSizeItem;
+ }
+
+ /**
+ Set Time range selection in agenda view starts event editor
+ */
+ void setSelectionStartsEditor( bool v )
+ {
+ if (!isImmutable( QString::fromLatin1( "SelectionStartsEditor" ) ))
+ mSelectionStartsEditor = v;
+ }
+
+ /**
+ Get Time range selection in agenda view starts event editor
+ */
+ bool selectionStartsEditor() const
+ {
+ return mSelectionStartsEditor;
+ }
+
+ /**
+ Get Time range selection in agenda view starts event editor default value
+ */
+ bool defaultSelectionStartsEditorValue() const
+ {
+ return defaultSelectionStartsEditorValue_helper();
+ }
+
+ /**
+ Get Item object corresponding to SelectionStartsEditor()
+ */
+ ItemBool *selectionStartsEditorItem()
+ {
+ return mSelectionStartsEditorItem;
+ }
+
+ /**
+ Set SelectedPlugins
+ */
+ void setSelectedPlugins( const QStringList & v )
+ {
+ if (!isImmutable( QString::fromLatin1( "SelectedPlugins" ) ))
+ mSelectedPlugins = v;
+ }
+
+ /**
+ Get SelectedPlugins
+ */
+ QStringList selectedPlugins() const
+ {
+ return mSelectedPlugins;
+ }
+
+ /**
+ Get SelectedPlugins default value
+ */
+ QStringList defaultSelectedPluginsValue() const
+ {
+ return defaultSelectedPluginsValue_helper();
+ }
+
+ /**
+ Get Item object corresponding to SelectedPlugins()
+ */
+ ItemStringList *selectedPluginsItem()
+ {
+ return mSelectedPluginsItem;
+ }
+
+ /**
+ Set Highlight color
+ */
+ void setHighlightColor( const QColor & v )
+ {
+ if (!isImmutable( QString::fromLatin1( "HighlightColor" ) ))
+ mHighlightColor = v;
+ }
+
+ /**
+ Get Highlight color
+ */
+ QColor highlightColor() const
+ {
+ return mHighlightColor;
+ }
+
+ /**
+ Get Highlight color default value
+ */
+ QColor defaultHighlightColorValue() const
+ {
+ return defaultHighlightColorValue_helper();
+ }
+
+ /**
+ Get Item object corresponding to HighlightColor()
+ */
+ ItemColor *highlightColorItem()
+ {
+ return mHighlightColorItem;
+ }
+
+ /**
+ Set Agenda view background color
+ */
+ void setAgendaBgColor( const QColor & v )
+ {
+ if (!isImmutable( QString::fromLatin1( "AgendaBgColor" ) ))
+ mAgendaBgColor = v;
+ }
+
+ /**
+ Get Agenda view background color
+ */
+ QColor agendaBgColor() const
+ {
+ return mAgendaBgColor;
+ }
+
+ /**
+ Get Agenda view background color default value
+ */
+ QColor defaultAgendaBgColorValue() const
+ {
+ return defaultAgendaBgColorValue_helper();
+ }
+
+ /**
+ Get Item object corresponding to AgendaBgColor()
+ */
+ ItemColor *agendaBgColorItem()
+ {
+ return mAgendaBgColorItem;
+ }
+
+ /**
+ Set Time bar
+ */
+ void setTimeBarFont( const QFont & v )
+ {
+ if (!isImmutable( QString::fromLatin1( "TimeBarFont" ) ))
+ mTimeBarFont = v;
+ }
+
+ /**
+ Get Time bar
+ */
+ QFont timeBarFont() const
+ {
+ return mTimeBarFont;
+ }
+
+ /**
+ Get Item object corresponding to TimeBarFont()
+ */
+ ItemFont *timeBarFontItem()
+ {
+ return mTimeBarFontItem;
+ }
+
+ /**
+ Set Email client
+ */
+ void setEmailClient( MailClient v )
+ {
+ if (!isImmutable( QString::fromLatin1( "EmailClient" ) ))
+ mEmailClient = v;
+ }
+
+ /**
+ Get Email client
+ */
+ MailClient emailClient() const
+ {
+ return static_cast<MailClient>(mEmailClient);
+ }
+
+ /**
+ Get Email client default value
+ */
+ MailClient defaultEmailClientValue() const
+ {
+ return static_cast<MailClient>(defaultEmailClientValue_helper());
+ }
+
+ /**
+ Get Item object corresponding to EmailClient()
+ */
+ ItemEnum *emailClientItem()
+ {
+ return mEmailClientItem;
+ }
+
+ /**
+ Set Reminder units
+ */
+ void setDefaultReminderUnits( TimePeriod::Units v )
+ {
+ if (!isImmutable( QString::fromLatin1( "DefaultReminderUnits" ) ))
+ mDefaultReminderUnits = v;
+ }
+
+ /**
+ Get Reminder units
+ */
+ TimePeriod::Units defaultReminderUnits() const
+ {
+ return static_cast<TimePeriod::Units>(mDefaultReminderUnits);
+ }
+
+ /**
+ Get Reminder units default value
+ */
+ TimePeriod::Units defaultDefaultReminderUnitsValue() const
+ {
+ return static_cast<TimePeriod::Units>(defaultDefaultReminderUnitsValue_helper());
+ }
+
+ /**
+ Get Item object corresponding to DefaultReminderUnits()
+ */
+ ItemEnum *defaultReminderUnitsItem()
+ {
+ return mDefaultReminderUnitsItem;
+ }
+
+ /**
+ Set EmptyingRate $(QueueIndex)
+ */
+ void setQueueRate( int i, const QList<int> & v )
+ {
+ if (!isImmutable( QString::fromLatin1( "queueRate%1" ).arg( i ) ))
+ mQueueRate[i] = v;
+ }
+
+ /**
+ Get EmptyingRate $(QueueIndex)
+ */
+ QList<int> queueRate( int i ) const
+ {
+ return mQueueRate[i];
+ }
+
+ /**
+ Get EmptyingRate $(QueueIndex) default value
+ */
+ QList<int> defaultQueueRateValue( int i ) const
+ {
+ return defaultQueueRateValue_helper( i );
+ }
+
+ /**
+ Get Item object corresponding to queueRate()
+ */
+ ItemIntList *queueRateItem( int i )
+ {
+ return mQueueRateItem[i];
+ }
+
+ /**
+ Set ShowQueueTuner
+ */
+ void setShowQueueTuner( bool v )
+ {
+ if (!isImmutable( QString::fromLatin1( "ShowQueueTuner" ) ))
+ mShowQueueTuner = v;
+ }
+
+ /**
+ Get ShowQueueTuner
+ */
+ bool showQueueTuner() const
+ {
+ return mShowQueueTuner;
+ }
+
+ /**
+ Get ShowQueueTuner default value
+ */
+ bool defaultShowQueueTunerValue() const
+ {
+ return defaultShowQueueTunerValue_helper();
+ }
+
+ /**
+ Get Item object corresponding to ShowQueueTuner()
+ */
+ ItemBool *showQueueTunerItem()
+ {
+ return mShowQueueTunerItem;
+ }
+
+ protected:
+ public:
+
+ // General
+ bool mAutoSave;
+ bool defaultAutoSaveValue_helper() const;
+ int mAutoSaveInterval;
+ int defaultAutoSaveIntervalValue_helper() const;
+ bool mConfirm;
+ bool defaultConfirmValue_helper() const;
+ QString mArchiveFile;
+ QString defaultArchiveFileValue_helper() const;
+ int mDestination;
+ int defaultDestinationValue_helper() const;
+
+ // Views
+ int mHourSize;
+ int defaultHourSizeValue_helper() const;
+ bool mSelectionStartsEditor;
+ bool defaultSelectionStartsEditorValue_helper() const;
+
+ // KOrganizer Plugins
+ QStringList mSelectedPlugins;
+ QStringList defaultSelectedPluginsValue_helper() const;
+
+ // Colors
+ QColor mHighlightColor;
+ QColor defaultHighlightColorValue_helper() const;
+ QColor mAgendaBgColor;
+ QColor defaultAgendaBgColorValue_helper() const;
+
+ // Fonts
+ QFont mTimeBarFont;
+ QFont defaultTimeBarFontValue_helper() const;
+
+ // Email
+ int mEmailClient;
+ int defaultEmailClientValue_helper() const;
+ int mDefaultReminderUnits;
+ int defaultDefaultReminderUnitsValue_helper() const;
+
+ // QueueRates
+ QList<int> mQueueRate[3];
+ QList<int> defaultQueueRateValue_helper( int i ) const;
+ bool mShowQueueTuner;
+ bool defaultShowQueueTunerValue_helper() const;
+
+ private:
+ ItemBool *mAutoSaveItem;
+ ItemInt *mAutoSaveIntervalItem;
+ ItemBool *mConfirmItem;
+ ItemString *mArchiveFileItem;
+ ItemEnum *mDestinationItem;
+ ItemInt *mHourSizeItem;
+ ItemBool *mSelectionStartsEditorItem;
+ ItemStringList *mSelectedPluginsItem;
+ ItemColor *mHighlightColorItem;
+ ItemColor *mAgendaBgColorItem;
+ ItemFont *mTimeBarFontItem;
+ ItemEnum *mEmailClientItem;
+ ItemEnum *mDefaultReminderUnitsItem;
+ ItemIntList *mQueueRateItem[3];
+ ItemBool *mShowQueueTunerItem;
+};
+
+#endif
+
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test11.kcfg b/tier1/kconfig/autotests/kconfig_compiler/test11.kcfg
new file mode 100644
index 00000000..d82e1326
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test11.kcfg
@@ -0,0 +1,136 @@
+<?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" >
+
+ <include>"test11_types.h"</include>
+
+ <kcfgfile name="korganizerrc"/>
+
+ <group name="General">
+ <entry type="Bool" key="Auto Save">
+ <label>Enable automatic saving of calendar</label>
+ <whatsthis>WhatsThis text for AutoSave option</whatsthis>
+ <default>false</default>
+ </entry>
+ <entry type="Int" key="Auto Save Interval">
+ <default>10</default>
+ </entry>
+ <entry type="Bool" key="Confirm Deletes" name="Confirm">
+ <label>Confirm deletes</label>
+ <default>true</default>
+ </entry>
+ <entry type="String" key="Archive File">
+ </entry>
+ <entry type="Enum" key="Destination" name="Destination">
+ <label>New Events/Todos Should</label>
+ <choices>
+ <choice name="standardDestination">
+ </choice>
+ <choice name="askDestination">
+ </choice>
+ <choice name="argl1">
+ <label>Argl1 Label</label>
+ </choice>
+ <choice name="argl2">
+ <whatsthis>Argl2 Whatsthis</whatsthis>
+ </choice>
+ <choice name="argl3">
+ <label>Argl3 Label</label>
+ <whatsthis>Argl3 Whatsthis</whatsthis>
+ </choice>
+ </choices>
+ <default>standardDestination</default>
+ </entry>
+ </group>
+
+ <group name="Views">
+ <entry type="Int" key="Hour Size">
+ <default>10</default>
+ </entry>
+ <entry type="Bool" name="SelectionStartsEditor">
+ <label>Time range selection in agenda view starts event editor</label>
+ <default>false</default>
+ </entry>
+ </group>
+
+ <group name="KOrganizer Plugins">
+ <entry type="StringList" name="SelectedPlugins">
+ <default>holidays,webexport</default>
+ </entry>
+ </group>
+
+ <group name="Colors">
+ <entry type="Color" key="Highlight Color">
+ <label>Highlight color</label>
+ <default>100, 100, 255</default>
+ </entry>
+ <entry type="Color" key="Agenda Background Color" name="AgendaBgColor">
+ <label>Agenda view background color</label>
+ <default>255, 255, 255</default>
+ </entry>
+ </group>
+
+ <group name="Fonts">
+ <entry type="Font" key="TimeBar Font">
+ <label>Time bar</label>
+ </entry>
+ </group>
+
+ <group name="Email">
+ <entry name="EmailClient" key="EmailClient" type="Enum">
+ <label context="@label">Email client</label>
+ <whatsthis context="@info:whatsthis">&lt;para>How to send email when an email alarm is triggered.&lt;list>&lt;item>KMail: The email is sent automatically via &lt;application>KMail&lt;/application>. &lt;application>KMail&lt;/application> is started first if necessary.&lt;/item>&lt;item>Sendmail: The email is sent automatically. This option will only work if your system is configured to use &lt;application>sendmail&lt;/application> or a sendmail compatible mail transport agent.&lt;/item>&lt;/list>&lt;/para></whatsthis>
+ <choices name="MailClient">
+ <choice name="sendmail"><label context="@option">Sendmail</label></choice>
+ <choice name="kmail"><label context="@option">KMail</label></choice>
+ </choices>
+ <default>kmail</default>
+ </entry>
+
+ <entry name="DefaultReminderUnits" key="RemindUnits" type="Enum">
+ <label context="@label">Reminder units</label>
+ <whatsthis context="@info:whatsthis">Default reminder time units in the alarm edit dialog.</whatsthis>
+ <tooltip context="@info:tooltip">Default reminder time units in the alarm edit dialog.</tooltip>
+ <choices name="TimePeriod::Units">
+ <choice name="Minutes"></choice>
+ <choice name="HoursMinutes"><label context="@option">Hours/Minutes</label></choice>
+ </choices>
+ <default>HoursMinutes</default>
+ </entry>
+ </group>
+
+ <group name="QueueRates">
+ <entry name="queueRate$(QueueIndex)" type="IntList" key="EmptyingRate $(QueueIndex)">
+ <!-- kconfig_compiler really should do this for me... -->
+ <code> QList&lt; QList&lt;int&gt; &gt; defaultRate;
+ QList&lt; int &gt; defaultRateInit;
+
+ defaultRateInit.append( 15 );
+ defaultRateInit.append( 60 );
+ defaultRateInit.append( 0 );
+ defaultRate.append( defaultRateInit );
+
+ defaultRateInit.clear();
+ defaultRateInit.append( 40 );
+ defaultRateInit.append( 60 );
+ defaultRateInit.append( 0 );
+ defaultRate.append( defaultRateInit );
+
+ defaultRateInit.clear();
+ defaultRateInit.append( 1 );
+ defaultRateInit.append( 1 );
+ defaultRateInit.append( 0 );
+ defaultRate.append( defaultRateInit );
+ </code>
+ <parameter name="QueueIndex" type="Int" max="2"/>
+ <default param="0" code="true">defaultRate[0]</default>
+ <default param="2" code="true">defaultRate[2]</default>
+ </entry>
+ <entry key="ShowQueueTuner" type="Bool">
+ <default>false</default>
+ </entry>
+ </group>
+
+</kcfg>
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test11.kcfgc b/tier1/kconfig/autotests/kconfig_compiler/test11.kcfgc
new file mode 100644
index 00000000..2b6fee15
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test11.kcfgc
@@ -0,0 +1,13 @@
+# Code generation options for kconfig_compiler
+File=test11.kcfg
+ClassName=Test11
+Singleton=false
+Mutators=true
+Inherits=MyPrefs
+IncludeFiles=myprefs.h
+MemberVariables=public
+GlobalEnums=false
+ItemAccessors=true
+SetUserTexts=true
+UseEnumTypes=true
+DefaultValueGetters=true
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test11_types.h b/tier1/kconfig/autotests/kconfig_compiler/test11_types.h
new file mode 100644
index 00000000..5b21aa97
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test11_types.h
@@ -0,0 +1,31 @@
+/*
+Copyright (c) 2009 Pino Toscano <pino@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef TEST11_TYPES_H
+#define TEST11_TYPES_H
+
+class TimePeriod
+{
+public:
+ enum Units { Minutes, HoursMinutes, Days, Weeks };
+};
+
+#endif
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test11a.cpp.ref b/tier1/kconfig/autotests/kconfig_compiler/test11a.cpp.ref
new file mode 100644
index 00000000..f826fc16
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test11a.cpp.ref
@@ -0,0 +1,187 @@
+// This file is generated by kconfig_compiler from test11a.kcfg.
+// All changes you do to this file will be lost.
+
+#include "test11a.h"
+
+Test11a::Test11a( )
+ : MyPrefs( QLatin1String( "korganizerrc" ) )
+{
+ setCurrentGroup( QLatin1String( "General" ) );
+
+ mAutoSaveItem = new MyPrefs::ItemBool( currentGroup(), QLatin1String( "Auto Save" ), mAutoSave, false );
+ mAutoSaveItem->setLabel( QCoreApplication::translate("Test11a", "Enable automatic saving of calendar") );
+ mAutoSaveItem->setWhatsThis( QCoreApplication::translate("Test11a", "WhatsThis text for AutoSave option") );
+ addItem( mAutoSaveItem, QLatin1String( "AutoSave" ) );
+ mAutoSaveIntervalItem = new MyPrefs::ItemInt( currentGroup(), QLatin1String( "Auto Save Interval" ), mAutoSaveInterval, 10 );
+ mAutoSaveIntervalItem->setLabel( QCoreApplication::translate("Test11a", "Auto Save Interval") );
+ addItem( mAutoSaveIntervalItem, QLatin1String( "AutoSaveInterval" ) );
+ mConfirmItem = new MyPrefs::ItemBool( currentGroup(), QLatin1String( "Confirm Deletes" ), mConfirm, true );
+ mConfirmItem->setLabel( QCoreApplication::translate("Test11a", "Confirm deletes") );
+ addItem( mConfirmItem, QLatin1String( "Confirm" ) );
+ mArchiveFileItem = new MyPrefs::ItemString( currentGroup(), QLatin1String( "Archive File" ), mArchiveFile );
+ mArchiveFileItem->setLabel( QCoreApplication::translate("Test11a", "Archive File") );
+ addItem( mArchiveFileItem, QLatin1String( "ArchiveFile" ) );
+ QList<MyPrefs::ItemEnum::Choice> valuesDestination;
+ {
+ MyPrefs::ItemEnum::Choice choice;
+ choice.name = QLatin1String("standardDestination");
+ valuesDestination.append( choice );
+ }
+ {
+ MyPrefs::ItemEnum::Choice choice;
+ choice.name = QLatin1String("askDestination");
+ valuesDestination.append( choice );
+ }
+ {
+ MyPrefs::ItemEnum::Choice choice;
+ choice.name = QLatin1String("argl1");
+ choice.label = QCoreApplication::translate("Test11a", "Argl1 Label");
+ valuesDestination.append( choice );
+ }
+ {
+ MyPrefs::ItemEnum::Choice choice;
+ choice.name = QLatin1String("argl2");
+ choice.whatsThis = QCoreApplication::translate("Test11a", "Argl2 Whatsthis");
+ valuesDestination.append( choice );
+ }
+ {
+ MyPrefs::ItemEnum::Choice choice;
+ choice.name = QLatin1String("argl3");
+ choice.label = QCoreApplication::translate("Test11a", "Argl3 Label");
+ choice.whatsThis = QCoreApplication::translate("Test11a", "Argl3 Whatsthis");
+ valuesDestination.append( choice );
+ }
+ mDestinationItem = new MyPrefs::ItemEnum( currentGroup(), QLatin1String( "Destination" ), mDestination, valuesDestination, EnumDestination::standardDestination );
+ mDestinationItem->setLabel( QCoreApplication::translate("Test11a", "New Events/Todos Should") );
+ addItem( mDestinationItem, QLatin1String( "Destination" ) );
+
+ setCurrentGroup( QLatin1String( "Views" ) );
+
+ mHourSizeItem = new MyPrefs::ItemInt( currentGroup(), QLatin1String( "Hour Size" ), mHourSize, 10 );
+ mHourSizeItem->setLabel( QCoreApplication::translate("Test11a", "Hour Size") );
+ addItem( mHourSizeItem, QLatin1String( "HourSize" ) );
+ mSelectionStartsEditorItem = new MyPrefs::ItemBool( currentGroup(), QLatin1String( "SelectionStartsEditor" ), mSelectionStartsEditor, false );
+ mSelectionStartsEditorItem->setLabel( QCoreApplication::translate("Test11a", "Time range selection in agenda view starts event editor") );
+ addItem( mSelectionStartsEditorItem, QLatin1String( "SelectionStartsEditor" ) );
+
+ setCurrentGroup( QLatin1String( "KOrganizer Plugins" ) );
+
+ QStringList defaultSelectedPlugins;
+ defaultSelectedPlugins.append( QString::fromUtf8( "holidays" ) );
+ defaultSelectedPlugins.append( QString::fromUtf8( "webexport" ) );
+
+ mSelectedPluginsItem = new MyPrefs::ItemStringList( currentGroup(), QLatin1String( "SelectedPlugins" ), mSelectedPlugins, defaultSelectedPlugins );
+ mSelectedPluginsItem->setLabel( QCoreApplication::translate("Test11a", "SelectedPlugins") );
+ addItem( mSelectedPluginsItem, QLatin1String( "SelectedPlugins" ) );
+
+ setCurrentGroup( QLatin1String( "Colors" ) );
+
+ mHighlightColorItem = new MyPrefs::ItemColor( currentGroup(), QLatin1String( "Highlight Color" ), mHighlightColor, QColor( 100, 100, 255 ) );
+ mHighlightColorItem->setLabel( QCoreApplication::translate("Test11a", "Highlight color") );
+ addItem( mHighlightColorItem, QLatin1String( "HighlightColor" ) );
+ mAgendaBgColorItem = new MyPrefs::ItemColor( currentGroup(), QLatin1String( "Agenda Background Color" ), mAgendaBgColor, QColor( 255, 255, 255 ) );
+ mAgendaBgColorItem->setLabel( QCoreApplication::translate("Test11a", "Agenda view background color") );
+ addItem( mAgendaBgColorItem, QLatin1String( "AgendaBgColor" ) );
+
+ setCurrentGroup( QLatin1String( "Fonts" ) );
+
+ mTimeBarFontItem = new MyPrefs::ItemFont( currentGroup(), QLatin1String( "TimeBar Font" ), mTimeBarFont );
+ mTimeBarFontItem->setLabel( QCoreApplication::translate("Test11a", "Time bar") );
+ addItem( mTimeBarFontItem, QLatin1String( "TimeBarFont" ) );
+
+ setCurrentGroup( QLatin1String( "Email" ) );
+
+ QList<MyPrefs::ItemEnum::Choice> valuesEmailClient;
+ {
+ MyPrefs::ItemEnum::Choice choice;
+ choice.name = QLatin1String("sendmail");
+ choice.label = /*: @option */ QCoreApplication::translate("Test11a", "Sendmail");
+ valuesEmailClient.append( choice );
+ }
+ {
+ MyPrefs::ItemEnum::Choice choice;
+ choice.name = QLatin1String("kmail");
+ choice.label = /*: @option */ QCoreApplication::translate("Test11a", "KMail");
+ valuesEmailClient.append( choice );
+ }
+ mEmailClientItem = new MyPrefs::ItemEnum( currentGroup(), QLatin1String( "EmailClient" ), mEmailClient, valuesEmailClient, kmail );
+ mEmailClientItem->setLabel( /*: @label */ QCoreApplication::translate("Test11a", "Email client") );
+ mEmailClientItem->setWhatsThis( /*: @info:whatsthis */ QCoreApplication::translate("Test11a", "<para>How to send email when an email alarm is triggered.<list><item>KMail: The email is sent automatically via <application>KMail</application>. <application>KMail</application> is started first if necessary.</item><item>Sendmail: The email is sent automatically. This option will only work if your system is configured to use <application>sendmail</application> or a sendmail compatible mail transport agent.</item></list></para>") );
+ addItem( mEmailClientItem, QLatin1String( "EmailClient" ) );
+ QList<MyPrefs::ItemEnum::Choice> valuesDefaultReminderUnits;
+ {
+ MyPrefs::ItemEnum::Choice choice;
+ choice.name = QLatin1String("Minutes");
+ valuesDefaultReminderUnits.append( choice );
+ }
+ {
+ MyPrefs::ItemEnum::Choice choice;
+ choice.name = QLatin1String("HoursMinutes");
+ choice.label = /*: @option */ QCoreApplication::translate("Test11a", "Hours/Minutes");
+ valuesDefaultReminderUnits.append( choice );
+ }
+ mDefaultReminderUnitsItem = new MyPrefs::ItemEnum( currentGroup(), QLatin1String( "RemindUnits" ), mDefaultReminderUnits, valuesDefaultReminderUnits, TimePeriod::HoursMinutes );
+ mDefaultReminderUnitsItem->setLabel( /*: @label */ QCoreApplication::translate("Test11a", "Reminder units") );
+ mDefaultReminderUnitsItem->setWhatsThis( /*: @info:whatsthis */ QCoreApplication::translate("Test11a", "Default reminder time units in the alarm edit dialog.") );
+ addItem( mDefaultReminderUnitsItem, QLatin1String( "DefaultReminderUnits" ) );
+
+ setCurrentGroup( QLatin1String( "QueueRates" ) );
+
+ QList< QList<int> > defaultRate;
+ QList< int > defaultRateInit;
+
+ defaultRateInit.append( 15 );
+ defaultRateInit.append( 60 );
+ defaultRateInit.append( 0 );
+ defaultRate.append( defaultRateInit );
+
+ defaultRateInit.clear();
+ defaultRateInit.append( 40 );
+ defaultRateInit.append( 60 );
+ defaultRateInit.append( 0 );
+ defaultRate.append( defaultRateInit );
+
+ defaultRateInit.clear();
+ defaultRateInit.append( 1 );
+ defaultRateInit.append( 1 );
+ defaultRateInit.append( 0 );
+ defaultRate.append( defaultRateInit );
+
+ QList<int> defaultqueueRate;
+
+ mQueueRateItem[0] = new MyPrefs::ItemIntList( currentGroup(), QLatin1String( "EmptyingRate 0" ), mQueueRate[0], defaultRate[0] );
+ mQueueRateItem[0]->setLabel( QCoreApplication::translate("Test11a", "EmptyingRate queueRate$(QueueIndex)") );
+ addItem( mQueueRateItem[0], QLatin1String( "queueRate0" ) );
+ mQueueRateItem[1] = new MyPrefs::ItemIntList( currentGroup(), QLatin1String( "EmptyingRate 1" ), mQueueRate[1], defaultqueueRate );
+ mQueueRateItem[1]->setLabel( QCoreApplication::translate("Test11a", "EmptyingRate queueRate$(QueueIndex)") );
+ addItem( mQueueRateItem[1], QLatin1String( "queueRate1" ) );
+ mQueueRateItem[2] = new MyPrefs::ItemIntList( currentGroup(), QLatin1String( "EmptyingRate 2" ), mQueueRate[2], defaultRate[2] );
+ mQueueRateItem[2]->setLabel( QCoreApplication::translate("Test11a", "EmptyingRate queueRate$(QueueIndex)") );
+ addItem( mQueueRateItem[2], QLatin1String( "queueRate2" ) );
+ mShowQueueTunerItem = new MyPrefs::ItemBool( currentGroup(), QLatin1String( "ShowQueueTuner" ), mShowQueueTuner, false );
+ mShowQueueTunerItem->setLabel( QCoreApplication::translate("Test11a", "ShowQueueTuner") );
+ addItem( mShowQueueTunerItem, QLatin1String( "ShowQueueTuner" ) );
+}
+
+int Test11a::defaultDestinationValue_helper() const
+{
+
+ return EnumDestination::standardDestination;
+}
+
+bool Test11a::defaultSelectionStartsEditorValue_helper() const
+{
+
+ return false;
+}
+
+int Test11a::defaultDefaultReminderUnitsValue_helper() const
+{
+
+ return TimePeriod::HoursMinutes;
+}
+
+Test11a::~Test11a()
+{
+}
+
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test11a.h.ref b/tier1/kconfig/autotests/kconfig_compiler/test11a.h.ref
new file mode 100644
index 00000000..4410ce29
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test11a.h.ref
@@ -0,0 +1,480 @@
+// This file is generated by kconfig_compiler from test11a.kcfg.
+// All changes you do to this file will be lost.
+#ifndef TEST11A_H
+#define TEST11A_H
+
+#include <myprefs.h>
+
+#include <qglobal.h>
+#include <kconfigskeleton.h>
+#include <QCoreApplication>
+#include <QDebug>
+
+#include "test11_types.h"
+class Test11a : public MyPrefs
+{
+ public:
+ class EnumDestination
+ {
+ public:
+ enum type { standardDestination, askDestination, argl1, argl2, argl3, COUNT };
+ };
+ enum MailClient { sendmail, kmail };
+
+ Test11a( );
+ ~Test11a();
+
+ /**
+ Set Enable automatic saving of calendar
+ */
+ void setAutoSave( bool v )
+ {
+ if (!isImmutable( QString::fromLatin1( "AutoSave" ) ))
+ mAutoSave = v;
+ }
+
+ /**
+ Get Enable automatic saving of calendar
+ */
+ bool autoSave() const
+ {
+ return mAutoSave;
+ }
+
+ /**
+ Get Item object corresponding to AutoSave()
+ */
+ ItemBool *autoSaveItem()
+ {
+ return mAutoSaveItem;
+ }
+
+ /**
+ Set Auto Save Interval
+ */
+ void setAutoSaveInterval( int v )
+ {
+ if (!isImmutable( QString::fromLatin1( "AutoSaveInterval" ) ))
+ mAutoSaveInterval = v;
+ }
+
+ /**
+ Get Auto Save Interval
+ */
+ int autoSaveInterval() const
+ {
+ return mAutoSaveInterval;
+ }
+
+ /**
+ Get Item object corresponding to AutoSaveInterval()
+ */
+ ItemInt *autoSaveIntervalItem()
+ {
+ return mAutoSaveIntervalItem;
+ }
+
+ /**
+ Set Confirm deletes
+ */
+ void setConfirm( bool v )
+ {
+ if (!isImmutable( QString::fromLatin1( "Confirm" ) ))
+ mConfirm = v;
+ }
+
+ /**
+ Get Confirm deletes
+ */
+ bool confirm() const
+ {
+ return mConfirm;
+ }
+
+ /**
+ Get Item object corresponding to Confirm()
+ */
+ ItemBool *confirmItem()
+ {
+ return mConfirmItem;
+ }
+
+ /**
+ Set Archive File
+ */
+ void setArchiveFile( const QString & v )
+ {
+ if (!isImmutable( QString::fromLatin1( "ArchiveFile" ) ))
+ mArchiveFile = v;
+ }
+
+ /**
+ Get Archive File
+ */
+ QString archiveFile() const
+ {
+ return mArchiveFile;
+ }
+
+ /**
+ Get Item object corresponding to ArchiveFile()
+ */
+ ItemString *archiveFileItem()
+ {
+ return mArchiveFileItem;
+ }
+
+ /**
+ Set New Events/Todos Should
+ */
+ void setDestination( EnumDestination::type v )
+ {
+ if (!isImmutable( QString::fromLatin1( "Destination" ) ))
+ mDestination = v;
+ }
+
+ /**
+ Get New Events/Todos Should
+ */
+ EnumDestination::type destination() const
+ {
+ return static_cast<EnumDestination::type>(mDestination);
+ }
+
+ /**
+ Get New Events/Todos Should default value
+ */
+ EnumDestination::type defaultDestinationValue() const
+ {
+ return static_cast<EnumDestination::type>(defaultDestinationValue_helper());
+ }
+
+ /**
+ Get Item object corresponding to Destination()
+ */
+ ItemEnum *destinationItem()
+ {
+ return mDestinationItem;
+ }
+
+ /**
+ Set Hour Size
+ */
+ void setHourSize( int v )
+ {
+ if (!isImmutable( QString::fromLatin1( "HourSize" ) ))
+ mHourSize = v;
+ }
+
+ /**
+ Get Hour Size
+ */
+ int hourSize() const
+ {
+ return mHourSize;
+ }
+
+ /**
+ Get Item object corresponding to HourSize()
+ */
+ ItemInt *hourSizeItem()
+ {
+ return mHourSizeItem;
+ }
+
+ /**
+ Set Time range selection in agenda view starts event editor
+ */
+ void setSelectionStartsEditor( bool v )
+ {
+ if (!isImmutable( QString::fromLatin1( "SelectionStartsEditor" ) ))
+ mSelectionStartsEditor = v;
+ }
+
+ /**
+ Get Time range selection in agenda view starts event editor
+ */
+ bool selectionStartsEditor() const
+ {
+ return mSelectionStartsEditor;
+ }
+
+ /**
+ Get Time range selection in agenda view starts event editor default value
+ */
+ bool defaultSelectionStartsEditorValue() const
+ {
+ return defaultSelectionStartsEditorValue_helper();
+ }
+
+ /**
+ Get Item object corresponding to SelectionStartsEditor()
+ */
+ ItemBool *selectionStartsEditorItem()
+ {
+ return mSelectionStartsEditorItem;
+ }
+
+ /**
+ Set SelectedPlugins
+ */
+ void setSelectedPlugins( const QStringList & v )
+ {
+ if (!isImmutable( QString::fromLatin1( "SelectedPlugins" ) ))
+ mSelectedPlugins = v;
+ }
+
+ /**
+ Get SelectedPlugins
+ */
+ QStringList selectedPlugins() const
+ {
+ return mSelectedPlugins;
+ }
+
+ /**
+ Get Item object corresponding to SelectedPlugins()
+ */
+ ItemStringList *selectedPluginsItem()
+ {
+ return mSelectedPluginsItem;
+ }
+
+ /**
+ Set Highlight color
+ */
+ void setHighlightColor( const QColor & v )
+ {
+ if (!isImmutable( QString::fromLatin1( "HighlightColor" ) ))
+ mHighlightColor = v;
+ }
+
+ /**
+ Get Highlight color
+ */
+ QColor highlightColor() const
+ {
+ return mHighlightColor;
+ }
+
+ /**
+ Get Item object corresponding to HighlightColor()
+ */
+ ItemColor *highlightColorItem()
+ {
+ return mHighlightColorItem;
+ }
+
+ /**
+ Set Agenda view background color
+ */
+ void setAgendaBgColor( const QColor & v )
+ {
+ if (!isImmutable( QString::fromLatin1( "AgendaBgColor" ) ))
+ mAgendaBgColor = v;
+ }
+
+ /**
+ Get Agenda view background color
+ */
+ QColor agendaBgColor() const
+ {
+ return mAgendaBgColor;
+ }
+
+ /**
+ Get Item object corresponding to AgendaBgColor()
+ */
+ ItemColor *agendaBgColorItem()
+ {
+ return mAgendaBgColorItem;
+ }
+
+ /**
+ Set Time bar
+ */
+ void setTimeBarFont( const QFont & v )
+ {
+ if (!isImmutable( QString::fromLatin1( "TimeBarFont" ) ))
+ mTimeBarFont = v;
+ }
+
+ /**
+ Get Time bar
+ */
+ QFont timeBarFont() const
+ {
+ return mTimeBarFont;
+ }
+
+ /**
+ Get Item object corresponding to TimeBarFont()
+ */
+ ItemFont *timeBarFontItem()
+ {
+ return mTimeBarFontItem;
+ }
+
+ /**
+ Set Email client
+ */
+ void setEmailClient( MailClient v )
+ {
+ if (!isImmutable( QString::fromLatin1( "EmailClient" ) ))
+ mEmailClient = v;
+ }
+
+ /**
+ Get Email client
+ */
+ MailClient emailClient() const
+ {
+ return static_cast<MailClient>(mEmailClient);
+ }
+
+ /**
+ Get Item object corresponding to EmailClient()
+ */
+ ItemEnum *emailClientItem()
+ {
+ return mEmailClientItem;
+ }
+
+ /**
+ Set Reminder units
+ */
+ void setDefaultReminderUnits( TimePeriod::Units v )
+ {
+ if (!isImmutable( QString::fromLatin1( "DefaultReminderUnits" ) ))
+ mDefaultReminderUnits = v;
+ }
+
+ /**
+ Get Reminder units
+ */
+ TimePeriod::Units defaultReminderUnits() const
+ {
+ return static_cast<TimePeriod::Units>(mDefaultReminderUnits);
+ }
+
+ /**
+ Get Reminder units default value
+ */
+ TimePeriod::Units defaultDefaultReminderUnitsValue() const
+ {
+ return static_cast<TimePeriod::Units>(defaultDefaultReminderUnitsValue_helper());
+ }
+
+ /**
+ Get Item object corresponding to DefaultReminderUnits()
+ */
+ ItemEnum *defaultReminderUnitsItem()
+ {
+ return mDefaultReminderUnitsItem;
+ }
+
+ /**
+ Set EmptyingRate $(QueueIndex)
+ */
+ void setQueueRate( int i, const QList<int> & v )
+ {
+ if (!isImmutable( QString::fromLatin1( "queueRate%1" ).arg( i ) ))
+ mQueueRate[i] = v;
+ }
+
+ /**
+ Get EmptyingRate $(QueueIndex)
+ */
+ QList<int> queueRate( int i ) const
+ {
+ return mQueueRate[i];
+ }
+
+ /**
+ Get Item object corresponding to queueRate()
+ */
+ ItemIntList *queueRateItem( int i )
+ {
+ return mQueueRateItem[i];
+ }
+
+ /**
+ Set ShowQueueTuner
+ */
+ void setShowQueueTuner( bool v )
+ {
+ if (!isImmutable( QString::fromLatin1( "ShowQueueTuner" ) ))
+ mShowQueueTuner = v;
+ }
+
+ /**
+ Get ShowQueueTuner
+ */
+ bool showQueueTuner() const
+ {
+ return mShowQueueTuner;
+ }
+
+ /**
+ Get Item object corresponding to ShowQueueTuner()
+ */
+ ItemBool *showQueueTunerItem()
+ {
+ return mShowQueueTunerItem;
+ }
+
+ protected:
+ public:
+
+ // General
+ bool mAutoSave;
+ int mAutoSaveInterval;
+ bool mConfirm;
+ QString mArchiveFile;
+ int mDestination;
+ int defaultDestinationValue_helper() const;
+
+ // Views
+ int mHourSize;
+ bool mSelectionStartsEditor;
+ bool defaultSelectionStartsEditorValue_helper() const;
+
+ // KOrganizer Plugins
+ QStringList mSelectedPlugins;
+
+ // Colors
+ QColor mHighlightColor;
+ QColor mAgendaBgColor;
+
+ // Fonts
+ QFont mTimeBarFont;
+
+ // Email
+ int mEmailClient;
+ int mDefaultReminderUnits;
+ int defaultDefaultReminderUnitsValue_helper() const;
+
+ // QueueRates
+ QList<int> mQueueRate[3];
+ bool mShowQueueTuner;
+
+ private:
+ ItemBool *mAutoSaveItem;
+ ItemInt *mAutoSaveIntervalItem;
+ ItemBool *mConfirmItem;
+ ItemString *mArchiveFileItem;
+ ItemEnum *mDestinationItem;
+ ItemInt *mHourSizeItem;
+ ItemBool *mSelectionStartsEditorItem;
+ ItemStringList *mSelectedPluginsItem;
+ ItemColor *mHighlightColorItem;
+ ItemColor *mAgendaBgColorItem;
+ ItemFont *mTimeBarFontItem;
+ ItemEnum *mEmailClientItem;
+ ItemEnum *mDefaultReminderUnitsItem;
+ ItemIntList *mQueueRateItem[3];
+ ItemBool *mShowQueueTunerItem;
+};
+
+#endif
+
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test11a.kcfg b/tier1/kconfig/autotests/kconfig_compiler/test11a.kcfg
new file mode 100644
index 00000000..da027067
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test11a.kcfg
@@ -0,0 +1,135 @@
+<?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" >
+
+ <include>"test11_types.h"</include>
+
+ <kcfgfile name="korganizerrc"/>
+
+ <group name="General">
+ <entry type="Bool" key="Auto Save">
+ <label>Enable automatic saving of calendar</label>
+ <whatsthis>WhatsThis text for AutoSave option</whatsthis>
+ <default>false</default>
+ </entry>
+ <entry type="Int" key="Auto Save Interval">
+ <default>10</default>
+ </entry>
+ <entry type="Bool" key="Confirm Deletes" name="Confirm">
+ <label>Confirm deletes</label>
+ <default>true</default>
+ </entry>
+ <entry type="String" key="Archive File">
+ </entry>
+ <entry type="Enum" key="Destination" name="Destination">
+ <label>New Events/Todos Should</label>
+ <choices>
+ <choice name="standardDestination">
+ </choice>
+ <choice name="askDestination">
+ </choice>
+ <choice name="argl1">
+ <label>Argl1 Label</label>
+ </choice>
+ <choice name="argl2">
+ <whatsthis>Argl2 Whatsthis</whatsthis>
+ </choice>
+ <choice name="argl3">
+ <label>Argl3 Label</label>
+ <whatsthis>Argl3 Whatsthis</whatsthis>
+ </choice>
+ </choices>
+ <default>standardDestination</default>
+ </entry>
+ </group>
+
+ <group name="Views">
+ <entry type="Int" key="Hour Size">
+ <default>10</default>
+ </entry>
+ <entry type="Bool" name="SelectionStartsEditor">
+ <label>Time range selection in agenda view starts event editor</label>
+ <default>false</default>
+ </entry>
+ </group>
+
+ <group name="KOrganizer Plugins">
+ <entry type="StringList" name="SelectedPlugins">
+ <default>holidays,webexport</default>
+ </entry>
+ </group>
+
+ <group name="Colors">
+ <entry type="Color" key="Highlight Color">
+ <label>Highlight color</label>
+ <default>100, 100, 255</default>
+ </entry>
+ <entry type="Color" key="Agenda Background Color" name="AgendaBgColor">
+ <label>Agenda view background color</label>
+ <default>255, 255, 255</default>
+ </entry>
+ </group>
+
+ <group name="Fonts">
+ <entry type="Font" key="TimeBar Font">
+ <label>Time bar</label>
+ </entry>
+ </group>
+
+ <group name="Email">
+ <entry name="EmailClient" key="EmailClient" type="Enum">
+ <label context="@label">Email client</label>
+ <whatsthis context="@info:whatsthis">&lt;para>How to send email when an email alarm is triggered.&lt;list>&lt;item>KMail: The email is sent automatically via &lt;application>KMail&lt;/application>. &lt;application>KMail&lt;/application> is started first if necessary.&lt;/item>&lt;item>Sendmail: The email is sent automatically. This option will only work if your system is configured to use &lt;application>sendmail&lt;/application> or a sendmail compatible mail transport agent.&lt;/item>&lt;/list>&lt;/para></whatsthis>
+ <choices name="MailClient">
+ <choice name="sendmail"><label context="@option">Sendmail</label></choice>
+ <choice name="kmail"><label context="@option">KMail</label></choice>
+ </choices>
+ <default>kmail</default>
+ </entry>
+
+ <entry name="DefaultReminderUnits" key="RemindUnits" type="Enum">
+ <label context="@label">Reminder units</label>
+ <whatsthis context="@info:whatsthis">Default reminder time units in the alarm edit dialog.</whatsthis>
+ <choices name="TimePeriod::Units">
+ <choice name="Minutes"></choice>
+ <choice name="HoursMinutes"><label context="@option">Hours/Minutes</label></choice>
+ </choices>
+ <default>HoursMinutes</default>
+ </entry>
+ </group>
+
+ <group name="QueueRates">
+ <entry name="queueRate$(QueueIndex)" type="IntList" key="EmptyingRate $(QueueIndex)">
+ <!-- kconfig_compiler really should do this for me... -->
+ <code> QList&lt; QList&lt;int&gt; &gt; defaultRate;
+ QList&lt; int &gt; defaultRateInit;
+
+ defaultRateInit.append( 15 );
+ defaultRateInit.append( 60 );
+ defaultRateInit.append( 0 );
+ defaultRate.append( defaultRateInit );
+
+ defaultRateInit.clear();
+ defaultRateInit.append( 40 );
+ defaultRateInit.append( 60 );
+ defaultRateInit.append( 0 );
+ defaultRate.append( defaultRateInit );
+
+ defaultRateInit.clear();
+ defaultRateInit.append( 1 );
+ defaultRateInit.append( 1 );
+ defaultRateInit.append( 0 );
+ defaultRate.append( defaultRateInit );
+ </code>
+ <parameter name="QueueIndex" type="Int" max="2"/>
+ <default param="0" code="true">defaultRate[0]</default>
+ <default param="2" code="true">defaultRate[2]</default>
+ </entry>
+ <entry key="ShowQueueTuner" type="Bool">
+ <default>false</default>
+ </entry>
+ </group>
+
+</kcfg>
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test11a.kcfgc b/tier1/kconfig/autotests/kconfig_compiler/test11a.kcfgc
new file mode 100644
index 00000000..cf0b0d8d
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test11a.kcfgc
@@ -0,0 +1,13 @@
+# Code generation options for kconfig_compiler
+File=test11a.kcfg
+ClassName=Test11a
+Singleton=false
+Mutators=true
+Inherits=MyPrefs
+IncludeFiles=myprefs.h
+MemberVariables=public
+GlobalEnums=false
+ItemAccessors=true
+SetUserTexts=true
+UseEnumTypes=true
+DefaultValueGetters=Destination,SelectionStartsEditor,DefaultReminderUnits
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test11main.cpp b/tier1/kconfig/autotests/kconfig_compiler/test11main.cpp
new file mode 100644
index 00000000..4f5fc80c
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test11main.cpp
@@ -0,0 +1,34 @@
+/*
+Copyright (c) 2009 Pino Toscano <pino@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#include "test11.h"
+#include "test11a.h"
+#include <QGuiApplication>
+
+int main( int argc, char **argv )
+{
+ QGuiApplication app(argc, argv);
+ Q_UNUSED(app);
+ Test11 *t = new Test11();
+ Test11a *t2 = new Test11a();
+ delete t;
+ delete t2;
+ return 0;
+}
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test12.cpp.ref b/tier1/kconfig/autotests/kconfig_compiler/test12.cpp.ref
new file mode 100644
index 00000000..69d5bba9
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test12.cpp.ref
@@ -0,0 +1,22 @@
+// This file is generated by kconfig_compiler from test12.kcfg.
+// All changes you do to this file will be lost.
+
+#include "test12.h"
+
+Test12::Test12( )
+ : KConfigSkeleton( QLatin1String( "muondatasourcesrc" ) )
+{
+ setCurrentGroup( QLatin1String( "muon" ) );
+
+ QList<QUrl> defaultRnRSource;
+ defaultRnRSource.append( QUrl::fromUserInput(QString::fromUtf8( "http://kde.org" ) ) );
+
+ KConfigSkeleton::ItemUrlList *itemRnRSource;
+ itemRnRSource = new KConfigSkeleton::ItemUrlList( currentGroup(), QLatin1String( "RnRSource" ), mRnRSource, defaultRnRSource );
+ addItem( itemRnRSource, QLatin1String( "RnRSource" ) );
+}
+
+Test12::~Test12()
+{
+}
+
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test12.h.ref b/tier1/kconfig/autotests/kconfig_compiler/test12.h.ref
new file mode 100644
index 00000000..d55414ec
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test12.h.ref
@@ -0,0 +1,36 @@
+// This file is generated by kconfig_compiler from test12.kcfg.
+// All changes you do to this file will be lost.
+#ifndef TEST12_H
+#define TEST12_H
+
+#include <qglobal.h>
+#include <kconfigskeleton.h>
+#include <QCoreApplication>
+#include <QDebug>
+
+class Test12 : public KConfigSkeleton
+{
+ public:
+
+ Test12( );
+ ~Test12();
+
+
+ /**
+ Get RnRSource
+ */
+ QList<QUrl> rnRSource() const
+ {
+ return mRnRSource;
+ }
+
+ protected:
+
+ // muon
+ QList<QUrl> mRnRSource;
+
+ private:
+};
+
+#endif
+
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test12.kcfg b/tier1/kconfig/autotests/kconfig_compiler/test12.kcfg
new file mode 100644
index 00000000..57663ab9
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test12.kcfg
@@ -0,0 +1,10 @@
+<?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="muondatasourcesrc"/>
+ <group name="muon">
+ <entry name="RnRSource" type="UrlList"><default>http://kde.org</default></entry>
+ </group>
+</kcfg>
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test12.kcfgc b/tier1/kconfig/autotests/kconfig_compiler/test12.kcfgc
new file mode 100644
index 00000000..1ed82e7e
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test12.kcfgc
@@ -0,0 +1 @@
+ClassName=Test12
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test12main.cpp b/tier1/kconfig/autotests/kconfig_compiler/test12main.cpp
new file mode 100644
index 00000000..b8a05294
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test12main.cpp
@@ -0,0 +1,28 @@
+/*
+Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#include "test12.h"
+
+int main( int, char** )
+{
+ Test12 *t = new Test12();
+ delete t;
+ return 0;
+}
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test1main.cpp b/tier1/kconfig/autotests/kconfig_compiler/test1main.cpp
new file mode 100644
index 00000000..f1f61c0a
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test1main.cpp
@@ -0,0 +1,31 @@
+/*
+Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#include "test1.h"
+#include <QGuiApplication>
+
+int main( int argc, char **argv )
+{
+ QGuiApplication app(argc, argv);
+ Q_UNUSED(app);
+ Test1 *t = new Test1( QString(), QString() );
+ delete t;
+ return 0;
+}
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test2.cpp.ref b/tier1/kconfig/autotests/kconfig_compiler/test2.cpp.ref
new file mode 100644
index 00000000..476b34c5
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test2.cpp.ref
@@ -0,0 +1,96 @@
+// This file is generated by kconfig_compiler from test2.kcfg.
+// All changes you do to this file will be lost.
+
+#include "test2.h"
+
+Test2::Test2( )
+ : MyPrefs( QLatin1String( "korganizerrc" ) )
+{
+ setCurrentGroup( QLatin1String( "General" ) );
+
+ mAutoSaveItem = new MyPrefs::ItemBool( currentGroup(), QLatin1String( "Auto Save" ), mAutoSave, false );
+ mAutoSaveItem->setLabel( QCoreApplication::translate("Test2", "Enable automatic saving of calendar") );
+ mAutoSaveItem->setWhatsThis( QCoreApplication::translate("Test2", "WhatsThis text for AutoSave option") );
+ addItem( mAutoSaveItem, QLatin1String( "AutoSave" ) );
+ mAutoSaveIntervalItem = new MyPrefs::ItemInt( currentGroup(), QLatin1String( "Auto Save Interval" ), mAutoSaveInterval, 10 );
+ mAutoSaveIntervalItem->setLabel( QCoreApplication::translate("Test2", "Auto Save Interval") );
+ addItem( mAutoSaveIntervalItem, QLatin1String( "AutoSaveInterval" ) );
+ mConfirmItem = new MyPrefs::ItemBool( currentGroup(), QLatin1String( "Confirm Deletes" ), mConfirm, true );
+ mConfirmItem->setLabel( QCoreApplication::translate("Test2", "Confirm deletes") );
+ addItem( mConfirmItem, QLatin1String( "Confirm" ) );
+ mArchiveFileItem = new MyPrefs::ItemString( currentGroup(), QLatin1String( "Archive File" ), mArchiveFile );
+ mArchiveFileItem->setLabel( QCoreApplication::translate("Test2", "Archive File") );
+ addItem( mArchiveFileItem, QLatin1String( "ArchiveFile" ) );
+ QList<MyPrefs::ItemEnum::Choice> valuesDestination;
+ {
+ MyPrefs::ItemEnum::Choice choice;
+ choice.name = QLatin1String("standardDestination");
+ valuesDestination.append( choice );
+ }
+ {
+ MyPrefs::ItemEnum::Choice choice;
+ choice.name = QLatin1String("askDestination");
+ valuesDestination.append( choice );
+ }
+ {
+ MyPrefs::ItemEnum::Choice choice;
+ choice.name = QLatin1String("argl1");
+ choice.label = QCoreApplication::translate("Test2", "Argl1 Label");
+ valuesDestination.append( choice );
+ }
+ {
+ MyPrefs::ItemEnum::Choice choice;
+ choice.name = QLatin1String("argl2");
+ choice.whatsThis = QCoreApplication::translate("Test2", "Argl2 Whatsthis");
+ valuesDestination.append( choice );
+ }
+ {
+ MyPrefs::ItemEnum::Choice choice;
+ choice.name = QLatin1String("argl3");
+ choice.label = QCoreApplication::translate("Test2", "Argl3 Label");
+ choice.whatsThis = QCoreApplication::translate("Test2", "Argl3 Whatsthis");
+ valuesDestination.append( choice );
+ }
+ mDestinationItem = new MyPrefs::ItemEnum( currentGroup(), QLatin1String( "Destination" ), mDestination, valuesDestination, standardDestination );
+ mDestinationItem->setLabel( QCoreApplication::translate("Test2", "New Events/Todos Should") );
+ addItem( mDestinationItem, QLatin1String( "Destination" ) );
+
+ setCurrentGroup( QLatin1String( "Views" ) );
+
+ mHourSizeItem = new MyPrefs::ItemInt( currentGroup(), QLatin1String( "Hour Size" ), mHourSize, 10 );
+ mHourSizeItem->setLabel( QCoreApplication::translate("Test2", "Hour Size") );
+ addItem( mHourSizeItem, QLatin1String( "HourSize" ) );
+ mSelectionStartsEditorItem = new MyPrefs::ItemBool( currentGroup(), QLatin1String( "SelectionStartsEditor" ), mSelectionStartsEditor, false );
+ mSelectionStartsEditorItem->setLabel( QCoreApplication::translate("Test2", "Time range selection in agenda view starts event editor") );
+ addItem( mSelectionStartsEditorItem, QLatin1String( "SelectionStartsEditor" ) );
+
+ setCurrentGroup( QLatin1String( "KOrganizer Plugins" ) );
+
+ QStringList defaultSelectedPlugins;
+ defaultSelectedPlugins.append( QString::fromUtf8( "holidays" ) );
+ defaultSelectedPlugins.append( QString::fromUtf8( "webexport" ) );
+
+ mSelectedPluginsItem = new MyPrefs::ItemStringList( currentGroup(), QLatin1String( "SelectedPlugins" ), mSelectedPlugins, defaultSelectedPlugins );
+ mSelectedPluginsItem->setLabel( QCoreApplication::translate("Test2", "SelectedPlugins") );
+ addItem( mSelectedPluginsItem, QLatin1String( "SelectedPlugins" ) );
+
+ setCurrentGroup( QLatin1String( "Colors" ) );
+
+ mHighlightColorItem = new MyPrefs::ItemColor( currentGroup(), QLatin1String( "Highlight Color" ), mHighlightColor, QColor( 100, 100, 255 ) );
+ mHighlightColorItem->setLabel( QCoreApplication::translate("Test2", "Highlight color") );
+ addItem( mHighlightColorItem, QLatin1String( "HighlightColor" ) );
+ mAgendaBgColorItem = new MyPrefs::ItemColor( currentGroup(), QLatin1String( "Agenda Background Color" ), mAgendaBgColor, QColor( 255, 255, 255 ) );
+ mAgendaBgColorItem->setLabel( QCoreApplication::translate("Test2", "Agenda view background color") );
+ addItem( mAgendaBgColorItem, QLatin1String( "AgendaBgColor" ) );
+
+ setCurrentGroup( QLatin1String( "Fonts" ) );
+
+ mTimeBarFontItem = new MyPrefs::ItemFont( currentGroup(), QLatin1String( "TimeBar Font" ), mTimeBarFont );
+ mTimeBarFontItem->setLabel( QCoreApplication::translate("Test2", "Time bar") );
+ addItem( mTimeBarFontItem, QLatin1String( "TimeBarFont" ) );
+}
+
+Test2::~Test2()
+{
+}
+
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test2.h.ref b/tier1/kconfig/autotests/kconfig_compiler/test2.h.ref
new file mode 100644
index 00000000..49af161e
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test2.h.ref
@@ -0,0 +1,335 @@
+// This file is generated by kconfig_compiler from test2.kcfg.
+// All changes you do to this file will be lost.
+#ifndef TEST2_H
+#define TEST2_H
+
+#include <myprefs.h>
+
+#include <qglobal.h>
+#include <kconfigskeleton.h>
+#include <QCoreApplication>
+#include <QDebug>
+
+class Test2 : public MyPrefs
+{
+ public:
+ enum EnumDestination { standardDestination, askDestination, argl1, argl2, argl3 };
+
+ Test2( );
+ ~Test2();
+
+ /**
+ Set Enable automatic saving of calendar
+ */
+ void setAutoSave( bool v )
+ {
+ if (!isImmutable( QString::fromLatin1( "AutoSave" ) ))
+ mAutoSave = v;
+ }
+
+ /**
+ Get Enable automatic saving of calendar
+ */
+ bool autoSave() const
+ {
+ return mAutoSave;
+ }
+
+ /**
+ Get Item object corresponding to AutoSave()
+ */
+ ItemBool *autoSaveItem()
+ {
+ return mAutoSaveItem;
+ }
+
+ /**
+ Set Auto Save Interval
+ */
+ void setAutoSaveInterval( int v )
+ {
+ if (!isImmutable( QString::fromLatin1( "AutoSaveInterval" ) ))
+ mAutoSaveInterval = v;
+ }
+
+ /**
+ Get Auto Save Interval
+ */
+ int autoSaveInterval() const
+ {
+ return mAutoSaveInterval;
+ }
+
+ /**
+ Get Item object corresponding to AutoSaveInterval()
+ */
+ ItemInt *autoSaveIntervalItem()
+ {
+ return mAutoSaveIntervalItem;
+ }
+
+ /**
+ Set Confirm deletes
+ */
+ void setConfirm( bool v )
+ {
+ if (!isImmutable( QString::fromLatin1( "Confirm" ) ))
+ mConfirm = v;
+ }
+
+ /**
+ Get Confirm deletes
+ */
+ bool confirm() const
+ {
+ return mConfirm;
+ }
+
+ /**
+ Get Item object corresponding to Confirm()
+ */
+ ItemBool *confirmItem()
+ {
+ return mConfirmItem;
+ }
+
+ /**
+ Set Archive File
+ */
+ void setArchiveFile( const QString & v )
+ {
+ if (!isImmutable( QString::fromLatin1( "ArchiveFile" ) ))
+ mArchiveFile = v;
+ }
+
+ /**
+ Get Archive File
+ */
+ QString archiveFile() const
+ {
+ return mArchiveFile;
+ }
+
+ /**
+ Get Item object corresponding to ArchiveFile()
+ */
+ ItemString *archiveFileItem()
+ {
+ return mArchiveFileItem;
+ }
+
+ /**
+ Set New Events/Todos Should
+ */
+ void setDestination( int v )
+ {
+ if (!isImmutable( QString::fromLatin1( "Destination" ) ))
+ mDestination = v;
+ }
+
+ /**
+ Get New Events/Todos Should
+ */
+ int destination() const
+ {
+ return mDestination;
+ }
+
+ /**
+ Get Item object corresponding to Destination()
+ */
+ ItemEnum *destinationItem()
+ {
+ return mDestinationItem;
+ }
+
+ /**
+ Set Hour Size
+ */
+ void setHourSize( int v )
+ {
+ if (!isImmutable( QString::fromLatin1( "HourSize" ) ))
+ mHourSize = v;
+ }
+
+ /**
+ Get Hour Size
+ */
+ int hourSize() const
+ {
+ return mHourSize;
+ }
+
+ /**
+ Get Item object corresponding to HourSize()
+ */
+ ItemInt *hourSizeItem()
+ {
+ return mHourSizeItem;
+ }
+
+ /**
+ Set Time range selection in agenda view starts event editor
+ */
+ void setSelectionStartsEditor( bool v )
+ {
+ if (!isImmutable( QString::fromLatin1( "SelectionStartsEditor" ) ))
+ mSelectionStartsEditor = v;
+ }
+
+ /**
+ Get Time range selection in agenda view starts event editor
+ */
+ bool selectionStartsEditor() const
+ {
+ return mSelectionStartsEditor;
+ }
+
+ /**
+ Get Item object corresponding to SelectionStartsEditor()
+ */
+ ItemBool *selectionStartsEditorItem()
+ {
+ return mSelectionStartsEditorItem;
+ }
+
+ /**
+ Set SelectedPlugins
+ */
+ void setSelectedPlugins( const QStringList & v )
+ {
+ if (!isImmutable( QString::fromLatin1( "SelectedPlugins" ) ))
+ mSelectedPlugins = v;
+ }
+
+ /**
+ Get SelectedPlugins
+ */
+ QStringList selectedPlugins() const
+ {
+ return mSelectedPlugins;
+ }
+
+ /**
+ Get Item object corresponding to SelectedPlugins()
+ */
+ ItemStringList *selectedPluginsItem()
+ {
+ return mSelectedPluginsItem;
+ }
+
+ /**
+ Set Highlight color
+ */
+ void setHighlightColor( const QColor & v )
+ {
+ if (!isImmutable( QString::fromLatin1( "HighlightColor" ) ))
+ mHighlightColor = v;
+ }
+
+ /**
+ Get Highlight color
+ */
+ QColor highlightColor() const
+ {
+ return mHighlightColor;
+ }
+
+ /**
+ Get Item object corresponding to HighlightColor()
+ */
+ ItemColor *highlightColorItem()
+ {
+ return mHighlightColorItem;
+ }
+
+ /**
+ Set Agenda view background color
+ */
+ void setAgendaBgColor( const QColor & v )
+ {
+ if (!isImmutable( QString::fromLatin1( "AgendaBgColor" ) ))
+ mAgendaBgColor = v;
+ }
+
+ /**
+ Get Agenda view background color
+ */
+ QColor agendaBgColor() const
+ {
+ return mAgendaBgColor;
+ }
+
+ /**
+ Get Item object corresponding to AgendaBgColor()
+ */
+ ItemColor *agendaBgColorItem()
+ {
+ return mAgendaBgColorItem;
+ }
+
+ /**
+ Set Time bar
+ */
+ void setTimeBarFont( const QFont & v )
+ {
+ if (!isImmutable( QString::fromLatin1( "TimeBarFont" ) ))
+ mTimeBarFont = v;
+ }
+
+ /**
+ Get Time bar
+ */
+ QFont timeBarFont() const
+ {
+ return mTimeBarFont;
+ }
+
+ /**
+ Get Item object corresponding to TimeBarFont()
+ */
+ ItemFont *timeBarFontItem()
+ {
+ return mTimeBarFontItem;
+ }
+
+ protected:
+ public:
+
+ // General
+ bool mAutoSave;
+ int mAutoSaveInterval;
+ bool mConfirm;
+ QString mArchiveFile;
+ int mDestination;
+
+ // Views
+ int mHourSize;
+ bool mSelectionStartsEditor;
+
+ // KOrganizer Plugins
+ QStringList mSelectedPlugins;
+
+ // Colors
+ QColor mHighlightColor;
+ QColor mAgendaBgColor;
+
+ // Fonts
+ QFont mTimeBarFont;
+
+ private:
+ ItemBool *mAutoSaveItem;
+ ItemInt *mAutoSaveIntervalItem;
+ ItemBool *mConfirmItem;
+ ItemString *mArchiveFileItem;
+ ItemEnum *mDestinationItem;
+ ItemInt *mHourSizeItem;
+ ItemBool *mSelectionStartsEditorItem;
+ ItemStringList *mSelectedPluginsItem;
+ ItemColor *mHighlightColorItem;
+ ItemColor *mAgendaBgColorItem;
+ ItemFont *mTimeBarFontItem;
+};
+
+#endif
+
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test2.kcfg b/tier1/kconfig/autotests/kconfig_compiler/test2.kcfg
new file mode 100644
index 00000000..3b19e270
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test2.kcfg
@@ -0,0 +1,78 @@
+<?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="korganizerrc"/>
+
+ <group name="General">
+ <entry type="Bool" key="Auto Save">
+ <label>Enable automatic saving of calendar</label>
+ <whatsthis>WhatsThis text for AutoSave option</whatsthis>
+ <default>false</default>
+ </entry>
+ <entry type="Int" key="Auto Save Interval">
+ <default>10</default>
+ </entry>
+ <entry type="Bool" key="Confirm Deletes" name="Confirm">
+ <label>Confirm deletes</label>
+ <default>true</default>
+ </entry>
+ <entry type="String" key="Archive File">
+ </entry>
+ <entry type="Enum" key="Destination" name="Destination">
+ <label>New Events/Todos Should</label>
+ <choices>
+ <choice name="standardDestination">
+ </choice>
+ <choice name="askDestination">
+ </choice>
+ <choice name="argl1">
+ <label>Argl1 Label</label>
+ </choice>
+ <choice name="argl2">
+ <whatsthis>Argl2 Whatsthis</whatsthis>
+ </choice>
+ <choice name="argl3">
+ <label>Argl3 Label</label>
+ <whatsthis>Argl3 Whatsthis</whatsthis>
+ </choice>
+ </choices>
+ <default>standardDestination</default>
+ </entry>
+ </group>
+
+ <group name="Views">
+ <entry type="Int" key="Hour Size">
+ <default>10</default>
+ </entry>
+ <entry type="Bool" name="SelectionStartsEditor">
+ <label>Time range selection in agenda view starts event editor</label>
+ <default>false</default>
+ </entry>
+ </group>
+
+ <group name="KOrganizer Plugins">
+ <entry type="StringList" name="SelectedPlugins">
+ <default>holidays,webexport</default>
+ </entry>
+ </group>
+
+ <group name="Colors">
+ <entry type="Color" key="Highlight Color">
+ <label>Highlight color</label>
+ <default>100, 100, 255</default>
+ </entry>
+ <entry type="Color" key="Agenda Background Color" name="AgendaBgColor">
+ <label>Agenda view background color</label>
+ <default>255, 255, 255</default>
+ </entry>
+ </group>
+
+ <group name="Fonts">
+ <entry type="Font" key="TimeBar Font">
+ <label>Time bar</label>
+ </entry>
+ </group>
+
+</kcfg>
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test2.kcfgc b/tier1/kconfig/autotests/kconfig_compiler/test2.kcfgc
new file mode 100644
index 00000000..56620d2f
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test2.kcfgc
@@ -0,0 +1,11 @@
+# Code generation options for kconfig_compiler
+File=test2.kcfg
+ClassName=Test2
+Singleton=false
+Mutators=true
+Inherits=MyPrefs
+IncludeFiles=myprefs.h
+MemberVariables=public
+GlobalEnums=true
+ItemAccessors=true
+SetUserTexts=true
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test2main.cpp b/tier1/kconfig/autotests/kconfig_compiler/test2main.cpp
new file mode 100644
index 00000000..80203c65
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test2main.cpp
@@ -0,0 +1,31 @@
+/*
+Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#include "test2.h"
+#include <QGuiApplication>
+
+int main( int argc, char **argv )
+{
+ QGuiApplication app(argc, argv);
+ Q_UNUSED(app);
+ Test2 *t = new Test2();
+ delete t;
+ return 0;
+}
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test3.cpp.ref b/tier1/kconfig/autotests/kconfig_compiler/test3.cpp.ref
new file mode 100644
index 00000000..0c9187a1
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test3.cpp.ref
@@ -0,0 +1,29 @@
+// This file is generated by kconfig_compiler from test3.kcfg.
+// All changes you do to this file will be lost.
+
+#include "test3.h"
+
+using namespace TestNameSpace;
+
+Test3::Test3( )
+ : KConfigSkeleton( QLatin1String( "test3rc" ) )
+{
+ setCurrentGroup( QLatin1String( "General" ) );
+
+ mAutoSaveItem = new KConfigSkeleton::ItemBool( currentGroup(), QLatin1String( "Auto Save" ), mAutoSave, false );
+ addItem( mAutoSaveItem, QLatin1String( "AutoSave" ) );
+
+ setCurrentGroup( QLatin1String( "Blah" ) );
+
+ mBlubbItem = new KConfigSkeleton::ItemInt( currentGroup(), QLatin1String( "Blubb" ), mBlubb, 10 );
+ addItem( mBlubbItem, QLatin1String( "Blubb" ) );
+ mBlahBlahItem = new KConfigSkeleton::ItemString( currentGroup(), QLatin1String( "BlahBlah" ), mBlahBlah, QLatin1String( "a string" ) );
+ addItem( mBlahBlahItem, QLatin1String( "BlahBlah" ) );
+ mMyPasswordItem = new KConfigSkeleton::ItemPassword( currentGroup(), QLatin1String( "MyPassword" ), mMyPassword );
+ addItem( mMyPasswordItem, QLatin1String( "MyPassword" ) );
+}
+
+Test3::~Test3()
+{
+}
+
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test3.h.ref b/tier1/kconfig/autotests/kconfig_compiler/test3.h.ref
new file mode 100644
index 00000000..931e2e26
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test3.h.ref
@@ -0,0 +1,140 @@
+// This file is generated by kconfig_compiler from test3.kcfg.
+// All changes you do to this file will be lost.
+#ifndef TESTNAMESPACE_TEST3_H
+#define TESTNAMESPACE_TEST3_H
+
+#include <qglobal.h>
+#include <kconfigskeleton.h>
+#include <QCoreApplication>
+#include <QDebug>
+
+namespace TestNameSpace {
+
+class Test3 : public KConfigSkeleton
+{
+ public:
+
+ Test3( );
+ ~Test3();
+
+ /**
+ Set Enable automatic saving of calendar
+ */
+ void setAutoSave( bool v )
+ {
+ if (!isImmutable( QString::fromLatin1( "AutoSave" ) ))
+ mAutoSave = v;
+ }
+
+ /**
+ Get Enable automatic saving of calendar
+ */
+ bool autoSave() const
+ {
+ return mAutoSave;
+ }
+
+ /**
+ Get Item object corresponding to AutoSave()
+ */
+ ItemBool *autoSaveItem()
+ {
+ return mAutoSaveItem;
+ }
+
+ /**
+ Set Blubb
+ */
+ void setBlubb( int v )
+ {
+ if (!isImmutable( QString::fromLatin1( "Blubb" ) ))
+ mBlubb = v;
+ }
+
+ /**
+ Get Blubb
+ */
+ int blubb() const
+ {
+ return mBlubb;
+ }
+
+ /**
+ Get Item object corresponding to Blubb()
+ */
+ ItemInt *blubbItem()
+ {
+ return mBlubbItem;
+ }
+
+ /**
+ Set BlahBlah
+ */
+ void setBlahBlah( const QString & v )
+ {
+ if (!isImmutable( QString::fromLatin1( "BlahBlah" ) ))
+ mBlahBlah = v;
+ }
+
+ /**
+ Get BlahBlah
+ */
+ QString blahBlah() const
+ {
+ return mBlahBlah;
+ }
+
+ /**
+ Get Item object corresponding to BlahBlah()
+ */
+ ItemString *blahBlahItem()
+ {
+ return mBlahBlahItem;
+ }
+
+ /**
+ Set MyPassword
+ */
+ void setMyPassword( const QString & v )
+ {
+ if (!isImmutable( QString::fromLatin1( "MyPassword" ) ))
+ mMyPassword = v;
+ }
+
+ /**
+ Get MyPassword
+ */
+ QString myPassword() const
+ {
+ return mMyPassword;
+ }
+
+ /**
+ Get Item object corresponding to MyPassword()
+ */
+ ItemPassword *myPasswordItem()
+ {
+ return mMyPasswordItem;
+ }
+
+ protected:
+
+ // General
+ bool mAutoSave;
+
+ // Blah
+ int mBlubb;
+ QString mBlahBlah;
+ QString mMyPassword;
+
+ private:
+ ItemBool *mAutoSaveItem;
+ ItemInt *mBlubbItem;
+ ItemString *mBlahBlahItem;
+ ItemPassword *mMyPasswordItem;
+};
+
+}
+
+#endif
+
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test3.kcfg b/tier1/kconfig/autotests/kconfig_compiler/test3.kcfg
new file mode 100644
index 00000000..77916da4
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test3.kcfg
@@ -0,0 +1,26 @@
+<?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="test3rc"/>
+
+ <group name="General">
+ <entry type="Bool" key="Auto Save">
+ <label>Enable automatic saving of calendar</label>
+ <whatsthis>WhatsThis text for AutoSave option</whatsthis>
+ <default>false</default>
+ </entry>
+ </group>
+
+ <group name="Blah">
+ <entry type="Int" name="Blubb">
+ <default>10</default>
+ </entry>
+ <entry type="String" name="BlahBlah">
+ <default>a string</default>
+ </entry>
+ <entry type="Password" name="MyPassword"/>
+ </group>
+
+</kcfg>
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test3.kcfgc b/tier1/kconfig/autotests/kconfig_compiler/test3.kcfgc
new file mode 100644
index 00000000..ca2c2205
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test3.kcfgc
@@ -0,0 +1,12 @@
+# Code generation options for kconfig_compiler
+File=test3.kcfg
+NameSpace=TestNameSpace
+ClassName=Test3
+#Singleton=false
+Mutators=true
+#Inherits=MyPrefs
+#IncludeFiles=myprefs.h
+#MemberVariables=public
+GlobalEnums=true
+ItemAccessors=true
+#SetUserTexts=true
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test3a.cpp.ref b/tier1/kconfig/autotests/kconfig_compiler/test3a.cpp.ref
new file mode 100644
index 00000000..34321e9e
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test3a.cpp.ref
@@ -0,0 +1,29 @@
+// This file is generated by kconfig_compiler from test3a.kcfg.
+// All changes you do to this file will be lost.
+
+#include "test3a.h"
+
+using namespace TestNameSpace::InnerNameSpace;
+
+Test3a::Test3a( )
+ : KConfigSkeleton( QLatin1String( "test3arc" ) )
+{
+ setCurrentGroup( QLatin1String( "General" ) );
+
+ mAutoSaveItem = new KConfigSkeleton::ItemBool( currentGroup(), QLatin1String( "Auto Save" ), mAutoSave, false );
+ addItem( mAutoSaveItem, QLatin1String( "AutoSave" ) );
+
+ setCurrentGroup( QLatin1String( "Blah" ) );
+
+ mBlubbItem = new KConfigSkeleton::ItemInt( currentGroup(), QLatin1String( "Blubb" ), mBlubb, 10 );
+ addItem( mBlubbItem, QLatin1String( "Blubb" ) );
+ mBlahBlahItem = new KConfigSkeleton::ItemString( currentGroup(), QLatin1String( "BlahBlah" ), mBlahBlah, QLatin1String( "a string" ) );
+ addItem( mBlahBlahItem, QLatin1String( "BlahBlah" ) );
+ mMyPasswordItem = new KConfigSkeleton::ItemPassword( currentGroup(), QLatin1String( "MyPassword" ), mMyPassword );
+ addItem( mMyPasswordItem, QLatin1String( "MyPassword" ) );
+}
+
+Test3a::~Test3a()
+{
+}
+
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test3a.h.ref b/tier1/kconfig/autotests/kconfig_compiler/test3a.h.ref
new file mode 100644
index 00000000..56d672a3
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test3a.h.ref
@@ -0,0 +1,142 @@
+// This file is generated by kconfig_compiler from test3a.kcfg.
+// All changes you do to this file will be lost.
+#ifndef TESTNAMESPACE_INNERNAMESPACE_TEST3A_H
+#define TESTNAMESPACE_INNERNAMESPACE_TEST3A_H
+
+#include <qglobal.h>
+#include <kconfigskeleton.h>
+#include <QCoreApplication>
+#include <QDebug>
+
+namespace TestNameSpace {
+namespace InnerNameSpace {
+
+class Test3a : public KConfigSkeleton
+{
+ public:
+
+ Test3a( );
+ ~Test3a();
+
+ /**
+ Set Enable automatic saving of calendar
+ */
+ void setAutoSave( bool v )
+ {
+ if (!isImmutable( QString::fromLatin1( "AutoSave" ) ))
+ mAutoSave = v;
+ }
+
+ /**
+ Get Enable automatic saving of calendar
+ */
+ bool autoSave() const
+ {
+ return mAutoSave;
+ }
+
+ /**
+ Get Item object corresponding to AutoSave()
+ */
+ ItemBool *autoSaveItem()
+ {
+ return mAutoSaveItem;
+ }
+
+ /**
+ Set Blubb
+ */
+ void setBlubb( int v )
+ {
+ if (!isImmutable( QString::fromLatin1( "Blubb" ) ))
+ mBlubb = v;
+ }
+
+ /**
+ Get Blubb
+ */
+ int blubb() const
+ {
+ return mBlubb;
+ }
+
+ /**
+ Get Item object corresponding to Blubb()
+ */
+ ItemInt *blubbItem()
+ {
+ return mBlubbItem;
+ }
+
+ /**
+ Set BlahBlah
+ */
+ void setBlahBlah( const QString & v )
+ {
+ if (!isImmutable( QString::fromLatin1( "BlahBlah" ) ))
+ mBlahBlah = v;
+ }
+
+ /**
+ Get BlahBlah
+ */
+ QString blahBlah() const
+ {
+ return mBlahBlah;
+ }
+
+ /**
+ Get Item object corresponding to BlahBlah()
+ */
+ ItemString *blahBlahItem()
+ {
+ return mBlahBlahItem;
+ }
+
+ /**
+ Set MyPassword
+ */
+ void setMyPassword( const QString & v )
+ {
+ if (!isImmutable( QString::fromLatin1( "MyPassword" ) ))
+ mMyPassword = v;
+ }
+
+ /**
+ Get MyPassword
+ */
+ QString myPassword() const
+ {
+ return mMyPassword;
+ }
+
+ /**
+ Get Item object corresponding to MyPassword()
+ */
+ ItemPassword *myPasswordItem()
+ {
+ return mMyPasswordItem;
+ }
+
+ protected:
+
+ // General
+ bool mAutoSave;
+
+ // Blah
+ int mBlubb;
+ QString mBlahBlah;
+ QString mMyPassword;
+
+ private:
+ ItemBool *mAutoSaveItem;
+ ItemInt *mBlubbItem;
+ ItemString *mBlahBlahItem;
+ ItemPassword *mMyPasswordItem;
+};
+
+}
+}
+
+#endif
+
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test3a.kcfg b/tier1/kconfig/autotests/kconfig_compiler/test3a.kcfg
new file mode 100644
index 00000000..d49b4d65
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test3a.kcfg
@@ -0,0 +1,26 @@
+<?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="test3arc"/>
+
+ <group name="General">
+ <entry type="Bool" key="Auto Save">
+ <label>Enable automatic saving of calendar</label>
+ <whatsthis>WhatsThis text for AutoSave option</whatsthis>
+ <default>false</default>
+ </entry>
+ </group>
+
+ <group name="Blah">
+ <entry type="Int" name="Blubb">
+ <default>10</default>
+ </entry>
+ <entry type="String" name="BlahBlah">
+ <default>a string</default>
+ </entry>
+ <entry type="Password" name="MyPassword"/>
+ </group>
+
+</kcfg>
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test3a.kcfgc b/tier1/kconfig/autotests/kconfig_compiler/test3a.kcfgc
new file mode 100644
index 00000000..ca849a81
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test3a.kcfgc
@@ -0,0 +1,12 @@
+# Code generation options for kconfig_compiler
+File=test3a.kcfg
+NameSpace=TestNameSpace::InnerNameSpace
+ClassName=Test3a
+#Singleton=false
+Mutators=true
+#Inherits=MyPrefs
+#IncludeFiles=myprefs.h
+#MemberVariables=public
+GlobalEnums=true
+ItemAccessors=true
+#SetUserTexts=true
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test3amain.cpp b/tier1/kconfig/autotests/kconfig_compiler/test3amain.cpp
new file mode 100644
index 00000000..fa33f1cb
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test3amain.cpp
@@ -0,0 +1,31 @@
+/*
+Copyright (c) 2009 Pino Toscano <pino@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#include "test3a.h"
+#include <QGuiApplication>
+
+int main( int argc, char **argv )
+{
+ QGuiApplication app(argc, argv);
+ Q_UNUSED(app);
+ TestNameSpace::InnerNameSpace::Test3a *t = new TestNameSpace::InnerNameSpace::Test3a();
+ delete t;
+ return 0;
+}
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test3main.cpp b/tier1/kconfig/autotests/kconfig_compiler/test3main.cpp
new file mode 100644
index 00000000..bf2846c1
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test3main.cpp
@@ -0,0 +1,31 @@
+/*
+Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#include "test3.h"
+#include <QGuiApplication>
+
+int main( int argc, char **argv )
+{
+ QGuiApplication app(argc, argv);
+ Q_UNUSED(app);
+ TestNameSpace::Test3 *t = new TestNameSpace::Test3();
+ delete t;
+ return 0;
+}
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test4.cpp.ref b/tier1/kconfig/autotests/kconfig_compiler/test4.cpp.ref
new file mode 100644
index 00000000..171d655d
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test4.cpp.ref
@@ -0,0 +1,178 @@
+// This file is generated by kconfig_compiler from test4.kcfg.
+// All changes you do to this file will be lost.
+
+#include "test4.h"
+
+#include <qglobal.h>
+#include <QtCore/QFile>
+
+class Test4Helper
+{
+ public:
+ Test4Helper() : q(0) {}
+ ~Test4Helper() { delete q; }
+ Test4 *q;
+};
+Q_GLOBAL_STATIC(Test4Helper, s_globalTest4)
+Test4 *Test4::self()
+{
+ if (!s_globalTest4()->q) {
+ new Test4;
+ s_globalTest4()->q->readConfig();
+ }
+
+ return s_globalTest4()->q;
+}
+
+const char* const Test4::EnumButton::enumToString[] = { "right", "mid", "left" };
+
+Test4::Test4( )
+ : KConfigSkeleton( QLatin1String( "test4rc" ) )
+{
+ Q_ASSERT(!s_globalTest4()->q);
+ s_globalTest4()->q = this;
+ setCurrentGroup( QLatin1String( "Foo" ) );
+
+QColor defaultColor[4] = { Qt::red, Qt::blue, Qt::green, Qt::black };
+ KConfigSkeleton::ItemColor *itemColor[4];
+ itemColor[0] = new KConfigSkeleton::ItemColor( currentGroup(), QLatin1String( "color #0" ), mColor[0], defaultColor[0] );
+ addItem( itemColor[0], QLatin1String( "Color0" ) );
+ itemColor[1] = new KConfigSkeleton::ItemColor( currentGroup(), QLatin1String( "color #1" ), mColor[1], defaultColor[1] );
+ addItem( itemColor[1], QLatin1String( "Color1" ) );
+ itemColor[2] = new KConfigSkeleton::ItemColor( currentGroup(), QLatin1String( "color #2" ), mColor[2], defaultColor[2] );
+ addItem( itemColor[2], QLatin1String( "Color2" ) );
+ itemColor[3] = new KConfigSkeleton::ItemColor( currentGroup(), QLatin1String( "color #3" ), mColor[3], defaultColor[3] );
+ addItem( itemColor[3], QLatin1String( "Color3" ) );
+ QList<KConfigSkeleton::ItemEnum::Choice> valuesMouseAction;
+ {
+ KConfigSkeleton::ItemEnum::Choice choice;
+ choice.name = QLatin1String("Encrypt");
+ valuesMouseAction.append( choice );
+ }
+ {
+ KConfigSkeleton::ItemEnum::Choice choice;
+ choice.name = QLatin1String("Decrypt");
+ valuesMouseAction.append( choice );
+ }
+ {
+ KConfigSkeleton::ItemEnum::Choice choice;
+ choice.name = QLatin1String("CrashNBurn");
+ valuesMouseAction.append( choice );
+ }
+ {
+ KConfigSkeleton::ItemEnum::Choice choice;
+ choice.name = QLatin1String("PumpNDump");
+ valuesMouseAction.append( choice );
+ }
+ KConfigSkeleton::ItemEnum *itemMouseAction[3];
+ itemMouseAction[0] = new KConfigSkeleton::ItemEnum( currentGroup(), QLatin1String( "right_mouse_action" ), mMouseAction[0], valuesMouseAction, EnumMouseAction::Decrypt );
+ addItem( itemMouseAction[0], QLatin1String( "MouseActionright" ) );
+ itemMouseAction[1] = new KConfigSkeleton::ItemEnum( currentGroup(), QLatin1String( "mid_mouse_action" ), mMouseAction[1], valuesMouseAction, EnumMouseAction::Encrypt );
+ addItem( itemMouseAction[1], QLatin1String( "MouseActionmid" ) );
+ itemMouseAction[2] = new KConfigSkeleton::ItemEnum( currentGroup(), QLatin1String( "left_mouse_action" ), mMouseAction[2], valuesMouseAction, EnumMouseAction::PumpNDump );
+ addItem( itemMouseAction[2], QLatin1String( "MouseActionleft" ) );
+ KConfigSkeleton::ItemColor *itemGrayColor[11];
+ itemGrayColor[0] = new KConfigSkeleton::ItemColor( currentGroup(), QLatin1String( "gray color #0" ), mGrayColor[0],
+ QColor::fromRgbF(0 / 10.0, 0 / 10.0, 0 / 10.0)
+ );
+ addItem( itemGrayColor[0], QLatin1String( "GrayColor0" ) );
+ itemGrayColor[1] = new KConfigSkeleton::ItemColor( currentGroup(), QLatin1String( "gray color #1" ), mGrayColor[1],
+ QColor::fromRgbF(1 / 10.0, 1 / 10.0, 1 / 10.0)
+ );
+ addItem( itemGrayColor[1], QLatin1String( "GrayColor1" ) );
+ itemGrayColor[2] = new KConfigSkeleton::ItemColor( currentGroup(), QLatin1String( "gray color #2" ), mGrayColor[2],
+ QColor::fromRgbF(2 / 10.0, 2 / 10.0, 2 / 10.0)
+ );
+ addItem( itemGrayColor[2], QLatin1String( "GrayColor2" ) );
+ itemGrayColor[3] = new KConfigSkeleton::ItemColor( currentGroup(), QLatin1String( "gray color #3" ), mGrayColor[3],
+ QColor::fromRgbF(3 / 10.0, 3 / 10.0, 3 / 10.0)
+ );
+ addItem( itemGrayColor[3], QLatin1String( "GrayColor3" ) );
+ itemGrayColor[4] = new KConfigSkeleton::ItemColor( currentGroup(), QLatin1String( "gray color #4" ), mGrayColor[4],
+ QColor::fromRgbF(4 / 10.0, 4 / 10.0, 4 / 10.0)
+ );
+ addItem( itemGrayColor[4], QLatin1String( "GrayColor4" ) );
+ itemGrayColor[5] = new KConfigSkeleton::ItemColor( currentGroup(), QLatin1String( "gray color #5" ), mGrayColor[5],
+ QColor::fromRgbF(5 / 10.0, 5 / 10.0, 5 / 10.0)
+ );
+ addItem( itemGrayColor[5], QLatin1String( "GrayColor5" ) );
+ itemGrayColor[6] = new KConfigSkeleton::ItemColor( currentGroup(), QLatin1String( "gray color #6" ), mGrayColor[6],
+ QColor::fromRgbF(6 / 10.0, 6 / 10.0, 6 / 10.0)
+ );
+ addItem( itemGrayColor[6], QLatin1String( "GrayColor6" ) );
+ itemGrayColor[7] = new KConfigSkeleton::ItemColor( currentGroup(), QLatin1String( "gray color #7" ), mGrayColor[7],
+ QColor::fromRgbF(7 / 10.0, 7 / 10.0, 7 / 10.0)
+ );
+ addItem( itemGrayColor[7], QLatin1String( "GrayColor7" ) );
+ itemGrayColor[8] = new KConfigSkeleton::ItemColor( currentGroup(), QLatin1String( "gray color #8" ), mGrayColor[8],
+ QColor::fromRgbF(8 / 10.0, 8 / 10.0, 8 / 10.0)
+ );
+ addItem( itemGrayColor[8], QLatin1String( "GrayColor8" ) );
+ itemGrayColor[9] = new KConfigSkeleton::ItemColor( currentGroup(), QLatin1String( "gray color #9" ), mGrayColor[9],
+ QColor::fromRgbF(9 / 10.0, 9 / 10.0, 9 / 10.0)
+ );
+ addItem( itemGrayColor[9], QLatin1String( "GrayColor9" ) );
+ itemGrayColor[10] = new KConfigSkeleton::ItemColor( currentGroup(), QLatin1String( "gray color #10" ), mGrayColor[10],
+ QColor::fromRgbF(10 / 10.0, 10 / 10.0, 10 / 10.0)
+ );
+ addItem( itemGrayColor[10], QLatin1String( "GrayColor10" ) );
+ KConfigSkeleton::ItemString *itemColorString[11];
+ itemColorString[0] = new KConfigSkeleton::ItemString( currentGroup(), QLatin1String( "color string #0" ), mColorString[0],
+ QString::number(0)
+ );
+ addItem( itemColorString[0], QLatin1String( "ColorString0" ) );
+ itemColorString[1] = new KConfigSkeleton::ItemString( currentGroup(), QLatin1String( "color string #1" ), mColorString[1],
+ QString::number(1)
+ );
+ addItem( itemColorString[1], QLatin1String( "ColorString1" ) );
+ itemColorString[2] = new KConfigSkeleton::ItemString( currentGroup(), QLatin1String( "color string #2" ), mColorString[2],
+ QString::number(2)
+ );
+ addItem( itemColorString[2], QLatin1String( "ColorString2" ) );
+ itemColorString[3] = new KConfigSkeleton::ItemString( currentGroup(), QLatin1String( "color string #3" ), mColorString[3],
+ QString::number(3)
+ );
+ addItem( itemColorString[3], QLatin1String( "ColorString3" ) );
+ itemColorString[4] = new KConfigSkeleton::ItemString( currentGroup(), QLatin1String( "color string #4" ), mColorString[4],
+ QString::number(4)
+ );
+ addItem( itemColorString[4], QLatin1String( "ColorString4" ) );
+ itemColorString[5] = new KConfigSkeleton::ItemString( currentGroup(), QLatin1String( "color string #5" ), mColorString[5],
+ QString::number(5)
+ );
+ addItem( itemColorString[5], QLatin1String( "ColorString5" ) );
+ itemColorString[6] = new KConfigSkeleton::ItemString( currentGroup(), QLatin1String( "color string #6" ), mColorString[6],
+ QString::number(6)
+ );
+ addItem( itemColorString[6], QLatin1String( "ColorString6" ) );
+ itemColorString[7] = new KConfigSkeleton::ItemString( currentGroup(), QLatin1String( "color string #7" ), mColorString[7],
+ QString::number(7)
+ );
+ addItem( itemColorString[7], QLatin1String( "ColorString7" ) );
+ itemColorString[8] = new KConfigSkeleton::ItemString( currentGroup(), QLatin1String( "color string #8" ), mColorString[8],
+ QString::number(8)
+ );
+ addItem( itemColorString[8], QLatin1String( "ColorString8" ) );
+ itemColorString[9] = new KConfigSkeleton::ItemString( currentGroup(), QLatin1String( "color string #9" ), mColorString[9],
+ QString::number(9)
+ );
+ addItem( itemColorString[9], QLatin1String( "ColorString9" ) );
+ itemColorString[10] = new KConfigSkeleton::ItemString( currentGroup(), QLatin1String( "color string #10" ), mColorString[10],
+ QString::number(10)
+ );
+ addItem( itemColorString[10], QLatin1String( "ColorString10" ) );
+ KConfigSkeleton::ItemString *itemFooBar;
+ itemFooBar = new KConfigSkeleton::ItemString( currentGroup(), QLatin1String( "foo bar" ), mFooBar );
+ addItem( itemFooBar, QLatin1String( "FooBar" ) );
+ KConfigSkeleton::ItemInt *itemAge;
+ itemAge = new KConfigSkeleton::ItemInt( currentGroup(), QLatin1String( "Age" ), mAge, 35 );
+ itemAge->setMinValue(8);
+ itemAge->setMaxValue(88);
+ addItem( itemAge, QLatin1String( "Age" ) );
+}
+
+Test4::~Test4()
+{
+ s_globalTest4()->q = 0;
+}
+
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test4.h.ref b/tier1/kconfig/autotests/kconfig_compiler/test4.h.ref
new file mode 100644
index 00000000..991a4f7d
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test4.h.ref
@@ -0,0 +1,171 @@
+// This file is generated by kconfig_compiler from test4.kcfg.
+// All changes you do to this file will be lost.
+#ifndef TEST4_H
+#define TEST4_H
+
+#include <kconfigskeleton.h>
+#include <QCoreApplication>
+#include <QDebug>
+
+class Test4 : public KConfigSkeleton
+{
+ public:
+ class EnumMouseAction
+ {
+ public:
+ enum type { Encrypt, Decrypt, CrashNBurn, PumpNDump, COUNT };
+ };
+ class EnumButton
+ {
+ public:
+ enum type { right, mid, left, COUNT };
+ static const char* const enumToString[];
+ };
+
+ static Test4 *self();
+ ~Test4();
+
+ /**
+ Set Block colors.
+ */
+ static
+ void setColor( int i, const QColor & v )
+ {
+ if (!self()->isImmutable( QString::fromLatin1( "Color%1" ).arg( i ) ))
+ self()->mColor[i] = v;
+ }
+
+ /**
+ Get Block colors.
+ */
+ static
+ QColor color( int i )
+ {
+ return self()->mColor[i];
+ }
+
+ /**
+ Set Mouse actions.
+ */
+ static
+ void setMouseAction( int i, int v )
+ {
+ if (!self()->isImmutable( QString::fromLatin1( "MouseAction%1" ).arg( QLatin1String( EnumButton::enumToString[i] ) ) ))
+ self()->mMouseAction[i] = v;
+ }
+
+ /**
+ Get Mouse actions.
+ */
+ static
+ int mouseAction( int i )
+ {
+ return self()->mMouseAction[i];
+ }
+
+ /**
+ Set Gray colors.
+ */
+ static
+ void setGrayColor( int i, const QColor & v )
+ {
+ if (!self()->isImmutable( QString::fromLatin1( "GrayColor%1" ).arg( i ) ))
+ self()->mGrayColor[i] = v;
+ }
+
+ /**
+ Get Gray colors.
+ */
+ static
+ QColor grayColor( int i )
+ {
+ return self()->mGrayColor[i];
+ }
+
+ /**
+ Set Gray colors as string.
+ */
+ static
+ void setColorString( int i, const QString & v )
+ {
+ if (!self()->isImmutable( QString::fromLatin1( "ColorString%1" ).arg( i ) ))
+ self()->mColorString[i] = v;
+ }
+
+ /**
+ Get Gray colors as string.
+ */
+ static
+ QString colorString( int i )
+ {
+ return self()->mColorString[i];
+ }
+
+ /**
+ Set foo bar
+ */
+ static
+ void setFooBar( const QString & v )
+ {
+ if (!self()->isImmutable( QString::fromLatin1( "FooBar" ) ))
+ self()->mFooBar = v;
+ }
+
+ /**
+ Get foo bar
+ */
+ static
+ QString fooBar()
+ {
+ return self()->mFooBar;
+ }
+
+ /**
+ Set Age
+ */
+ static
+ void setAge( int v )
+ {
+ if (v < 8)
+ {
+ qDebug() << "setAge: value " << v << " is less than the minimum value of 8";
+ v = 8;
+ }
+
+ if (v > 88)
+ {
+ qDebug() << "setAge: value " << v << " is greater than the maximum value of 88";
+ v = 88;
+ }
+
+ if (!self()->isImmutable( QString::fromLatin1( "Age" ) ))
+ self()->mAge = v;
+ }
+
+ /**
+ Get Age
+ */
+ static
+ int age()
+ {
+ return self()->mAge;
+ }
+
+ protected:
+ Test4();
+ friend class Test4Helper;
+
+
+ // Foo
+ QColor mColor[4];
+ int mMouseAction[3];
+ QColor mGrayColor[11];
+ QString mColorString[11];
+ QString mFooBar;
+ int mAge;
+
+ private:
+};
+
+#endif
+
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test4.kcfg b/tier1/kconfig/autotests/kconfig_compiler/test4.kcfg
new file mode 100644
index 00000000..0919b46f
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test4.kcfg
@@ -0,0 +1,56 @@
+<?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="test4rc"/>
+
+ <group name="Foo">
+ <entry name="Color$(Number)" type="Color" key="color #$(Number)">
+ <parameter name="Number" type="Int" max="3"/>
+ <label>Block colors.</label>
+ <code>QColor defaultColor[4] = { Qt::red, Qt::blue, Qt::green, Qt::black };</code>
+ <default code="true">defaultColor[$(Number)]</default>
+ </entry>
+ <entry name="MouseAction$(Button)" type="Enum" key="$(Button)_mouse_action">
+ <parameter name="Button" type="Enum">
+ <values>
+ <value>right</value>
+ <value>mid</value>
+ <value>left</value>
+ </values>
+ </parameter>
+ <label>Mouse actions.</label>
+ <choices>
+ <choice name="Encrypt"/>
+ <choice name="Decrypt"/>
+ <choice name="CrashNBurn"/>
+ <choice name="PumpNDump"/>
+ </choices>
+ <default param="right">Decrypt</default>
+ <default param="mid">Encrypt</default>
+ <default param="left">PumpNDump</default>
+ </entry>
+ <entry name="GrayColor$(Number)" type="Color" key="gray color #$(Number)">
+ <parameter name="Number" type="Int" max="10"/>
+ <label>Gray colors.</label>
+ <default code="true">
+ QColor::fromRgbF($(Number) / 10.0, $(Number) / 10.0, $(Number) / 10.0)
+ </default>
+ </entry>
+ <entry name="ColorString$(Number)" type="String" key="color string #$(Number)">
+ <parameter name="Number" type="Int" max="10"/>
+ <label>Gray colors as string.</label>
+ <default code="true">
+ QString::number($(Number))
+ </default>
+ </entry>
+ <entry name="FooBar" key="foo bar" type="String"/>
+ <entry name="Age" type="Int">
+ <default>35</default>
+ <min>8</min>
+ <max>88</max>
+ </entry>
+ </group>
+
+</kcfg>
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test4.kcfgc b/tier1/kconfig/autotests/kconfig_compiler/test4.kcfgc
new file mode 100644
index 00000000..754706df
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test4.kcfgc
@@ -0,0 +1,11 @@
+# Code generation options for kconfig_compiler
+File=test4.kcfg
+ClassName=Test4
+Singleton=true
+Mutators=true
+#Inherits=MyPrefs
+#IncludeFiles=myprefs.h
+#MemberVariables=public
+GlobalEnums=false
+ItemAccessors=false
+#SetUserTexts=true
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test4main.cpp b/tier1/kconfig/autotests/kconfig_compiler/test4main.cpp
new file mode 100644
index 00000000..3ef924c8
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test4main.cpp
@@ -0,0 +1,32 @@
+/*
+Copyright (c) 2003,2004 Waldo Bastian <bastian@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "test4.h"
+#include <QGuiApplication>
+
+int main( int argc, char **argv )
+{
+ QGuiApplication app(argc, argv);
+ Q_UNUSED(app);
+ Test4 *t = Test4::self();
+ delete t;
+ return 0;
+}
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test5.cpp.ref b/tier1/kconfig/autotests/kconfig_compiler/test5.cpp.ref
new file mode 100644
index 00000000..2a95dcda
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test5.cpp.ref
@@ -0,0 +1,88 @@
+// This file is generated by kconfig_compiler from test5.kcfg.
+// All changes you do to this file will be lost.
+
+#include "test5.h"
+
+#include <qglobal.h>
+#include <QtCore/QFile>
+
+class Test5Helper
+{
+ public:
+ Test5Helper() : q(0) {}
+ ~Test5Helper() { delete q; }
+ Test5 *q;
+};
+Q_GLOBAL_STATIC(Test5Helper, s_globalTest5)
+Test5 *Test5::self()
+{
+ if (!s_globalTest5()->q) {
+ new Test5;
+ s_globalTest5()->q->readConfig();
+ }
+
+ return s_globalTest5()->q;
+}
+
+const char* const Test5::EnumButtonToString[] = { "right", "mid", "left" };
+
+Test5::Test5( )
+ : KConfigSkeleton( QLatin1String( "test4rc" ) )
+{
+ Q_ASSERT(!s_globalTest5()->q);
+ s_globalTest5()->q = this;
+ setCurrentGroup( QLatin1String( "Foo" ) );
+
+QColor defaultColor[4] = { Qt::red, Qt::blue, Qt::green, Qt::black };
+ KConfigSkeleton::ItemColor *itemColor[4];
+ itemColor[0] = new KConfigSkeleton::ItemColor( currentGroup(), QLatin1String( "color #0" ), mColor[0], defaultColor[0] );
+ addItem( itemColor[0], QLatin1String( "Color0" ) );
+ itemColor[1] = new KConfigSkeleton::ItemColor( currentGroup(), QLatin1String( "color #1" ), mColor[1], defaultColor[1] );
+ addItem( itemColor[1], QLatin1String( "Color1" ) );
+ itemColor[2] = new KConfigSkeleton::ItemColor( currentGroup(), QLatin1String( "color #2" ), mColor[2], defaultColor[2] );
+ addItem( itemColor[2], QLatin1String( "Color2" ) );
+ itemColor[3] = new KConfigSkeleton::ItemColor( currentGroup(), QLatin1String( "color #3" ), mColor[3], defaultColor[3] );
+ addItem( itemColor[3], QLatin1String( "Color3" ) );
+ QList<KConfigSkeleton::ItemEnum::Choice> valuesMouseAction;
+ {
+ KConfigSkeleton::ItemEnum::Choice choice;
+ choice.name = QLatin1String("Encrypt");
+ valuesMouseAction.append( choice );
+ }
+ {
+ KConfigSkeleton::ItemEnum::Choice choice;
+ choice.name = QLatin1String("Decrypt");
+ valuesMouseAction.append( choice );
+ }
+ {
+ KConfigSkeleton::ItemEnum::Choice choice;
+ choice.name = QLatin1String("CrashNBurn");
+ valuesMouseAction.append( choice );
+ }
+ {
+ KConfigSkeleton::ItemEnum::Choice choice;
+ choice.name = QLatin1String("PumpNDump");
+ valuesMouseAction.append( choice );
+ }
+ KConfigSkeleton::ItemEnum *itemMouseAction[3];
+ itemMouseAction[0] = new KConfigSkeleton::ItemEnum( currentGroup(), QLatin1String( "right_mouse_action" ), mMouseAction[0], valuesMouseAction, Decrypt );
+ addItem( itemMouseAction[0], QLatin1String( "MouseActionright" ) );
+ itemMouseAction[1] = new KConfigSkeleton::ItemEnum( currentGroup(), QLatin1String( "mid_mouse_action" ), mMouseAction[1], valuesMouseAction, Encrypt );
+ addItem( itemMouseAction[1], QLatin1String( "MouseActionmid" ) );
+ itemMouseAction[2] = new KConfigSkeleton::ItemEnum( currentGroup(), QLatin1String( "left_mouse_action" ), mMouseAction[2], valuesMouseAction, PumpNDump );
+ addItem( itemMouseAction[2], QLatin1String( "MouseActionleft" ) );
+ KConfigSkeleton::ItemString *itemFooBar;
+ itemFooBar = new KConfigSkeleton::ItemString( currentGroup(), QLatin1String( "foo bar" ), mFooBar );
+ addItem( itemFooBar, QLatin1String( "FooBar" ) );
+ KConfigSkeleton::ItemInt *itemAge;
+ itemAge = new KConfigSkeleton::ItemInt( currentGroup(), QLatin1String( "Age" ), mAge, 35 );
+ itemAge->setMinValue(8);
+ itemAge->setMaxValue(88);
+ addItem( itemAge, QLatin1String( "Age" ) );
+}
+
+Test5::~Test5()
+{
+ s_globalTest5()->q = 0;
+}
+
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test5.h.ref b/tier1/kconfig/autotests/kconfig_compiler/test5.h.ref
new file mode 100644
index 00000000..46a591c1
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test5.h.ref
@@ -0,0 +1,123 @@
+// This file is generated by kconfig_compiler from test5.kcfg.
+// All changes you do to this file will be lost.
+#ifndef TEST5_H
+#define TEST5_H
+
+#include <kconfigskeleton.h>
+#include <QCoreApplication>
+#include <QDebug>
+
+class Test5 : public KConfigSkeleton
+{
+ public:
+ enum EnumMouseAction { Encrypt, Decrypt, CrashNBurn, PumpNDump };
+ enum EnumButton { right, mid, left };
+ static const char* const EnumButtonToString[];
+
+ static Test5 *self();
+ ~Test5();
+
+ /**
+ Set Block colors.
+ */
+ static
+ void setColor( int i, const QColor & v )
+ {
+ if (!self()->isImmutable( QString::fromLatin1( "Color%1" ).arg( i ) ))
+ self()->mColor[i] = v;
+ }
+
+ /**
+ Get Block colors.
+ */
+ static
+ QColor color( int i )
+ {
+ return self()->mColor[i];
+ }
+
+ /**
+ Set Mouse actions.
+ */
+ static
+ void setMouseAction( int i, int v )
+ {
+ if (!self()->isImmutable( QString::fromLatin1( "MouseAction%1" ).arg( QLatin1String( EnumButtonToString[i] ) ) ))
+ self()->mMouseAction[i] = v;
+ }
+
+ /**
+ Get Mouse actions.
+ */
+ static
+ int mouseAction( int i )
+ {
+ return self()->mMouseAction[i];
+ }
+
+ /**
+ Set foo bar
+ */
+ static
+ void setFooBar( const QString & v )
+ {
+ if (!self()->isImmutable( QString::fromLatin1( "FooBar" ) ))
+ self()->mFooBar = v;
+ }
+
+ /**
+ Get foo bar
+ */
+ static
+ QString fooBar()
+ {
+ return self()->mFooBar;
+ }
+
+ /**
+ Set Age
+ */
+ static
+ void setAge( int v )
+ {
+ if (v < 8)
+ {
+ qDebug() << "setAge: value " << v << " is less than the minimum value of 8";
+ v = 8;
+ }
+
+ if (v > 88)
+ {
+ qDebug() << "setAge: value " << v << " is greater than the maximum value of 88";
+ v = 88;
+ }
+
+ if (!self()->isImmutable( QString::fromLatin1( "Age" ) ))
+ self()->mAge = v;
+ }
+
+ /**
+ Get Age
+ */
+ static
+ int age()
+ {
+ return self()->mAge;
+ }
+
+ protected:
+ Test5();
+ friend class Test5Helper;
+
+
+ // Foo
+ QColor mColor[4];
+ int mMouseAction[3];
+ QString mFooBar;
+ int mAge;
+
+ private:
+};
+
+#endif
+
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test5.kcfg b/tier1/kconfig/autotests/kconfig_compiler/test5.kcfg
new file mode 100644
index 00000000..d8ef2bfa
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test5.kcfg
@@ -0,0 +1,42 @@
+<?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="test4rc"/>
+
+ <group name="Foo">
+ <entry name="Color$(Number)" type="Color" key="color #$(Number)">
+ <parameter name="Number" type="Int" max="3"/>
+ <label>Block colors.</label>
+ <code>QColor defaultColor[4] = { Qt::red, Qt::blue, Qt::green, Qt::black };</code>
+ <default code="true">defaultColor[$(Number)]</default>
+ </entry>
+ <entry name="MouseAction$(Button)" type="Enum" key="$(Button)_mouse_action">
+ <parameter name="Button" type="Enum">
+ <values>
+ <value>right</value>
+ <value>mid</value>
+ <value>left</value>
+ </values>
+ </parameter>
+ <label>Mouse actions.</label>
+ <choices>
+ <choice name="Encrypt"/>
+ <choice name="Decrypt"/>
+ <choice name="CrashNBurn"/>
+ <choice name="PumpNDump"/>
+ </choices>
+ <default param="right">Decrypt</default>
+ <default param="mid">Encrypt</default>
+ <default param="left">PumpNDump</default>
+ </entry>
+ <entry name="FooBar" key="foo bar" type="String"/>
+ <entry name="Age" type="Int">
+ <default>35</default>
+ <min>8</min>
+ <max>88</max>
+ </entry>
+ </group>
+
+</kcfg>
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test5.kcfgc b/tier1/kconfig/autotests/kconfig_compiler/test5.kcfgc
new file mode 100644
index 00000000..663005e5
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test5.kcfgc
@@ -0,0 +1,11 @@
+# Code generation options for kconfig_compiler
+File=test5.kcfg
+ClassName=Test5
+Singleton=true
+Mutators=true
+#Inherits=MyPrefs
+#IncludeFiles=myprefs.h
+#MemberVariables=public
+GlobalEnums=true
+ItemAccessors=false
+#SetUserTexts=true
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test5main.cpp b/tier1/kconfig/autotests/kconfig_compiler/test5main.cpp
new file mode 100644
index 00000000..55e30d07
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test5main.cpp
@@ -0,0 +1,32 @@
+/*
+Copyright (c) 2004 Waldo Bastian <bastian@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "test5.h"
+#include <QGuiApplication>
+
+int main( int argc, char **argv )
+{
+ QGuiApplication app(argc, argv);
+ Q_UNUSED(app);
+ Test5 *t = Test5::self();
+ delete t;
+ return 0;
+}
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test6.cpp.ref b/tier1/kconfig/autotests/kconfig_compiler/test6.cpp.ref
new file mode 100644
index 00000000..0fce03a3
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test6.cpp.ref
@@ -0,0 +1,31 @@
+// This file is generated by kconfig_compiler from test6.kcfg.
+// All changes you do to this file will be lost.
+
+#include "test6.h"
+
+Test6::Test6( const QString & Number )
+ : KConfigSkeleton( QLatin1String( "test4rc" ) )
+ , mParamNumber(Number)
+{
+ setCurrentGroup( QLatin1String( "Foo" ) );
+
+ KConfigSkeleton::ItemColor *itemColor;
+ itemColor = new KConfigSkeleton::ItemColor( currentGroup(), QString( QLatin1String( "color #%1" ) ).arg( mParamNumber ), mColor, QColor( "red" ) );
+ addItem( itemColor, QLatin1String( "Color" ) );
+
+ setCurrentGroup( QString( QLatin1String( "Bar%1" ) ).arg( mParamNumber ) );
+
+ KConfigSkeleton::ItemString *itemFooBar;
+ itemFooBar = new KConfigSkeleton::ItemString( currentGroup(), QLatin1String( "foo bar" ), mFooBar );
+ addItem( itemFooBar, QLatin1String( "FooBar" ) );
+ KConfigSkeleton::ItemInt *itemAge;
+ itemAge = new KConfigSkeleton::ItemInt( currentGroup(), QLatin1String( "Age" ), mAge, 35 );
+ itemAge->setMinValue(8);
+ itemAge->setMaxValue(88);
+ addItem( itemAge, QLatin1String( "Age" ) );
+}
+
+Test6::~Test6()
+{
+}
+
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test6.h.ref b/tier1/kconfig/autotests/kconfig_compiler/test6.h.ref
new file mode 100644
index 00000000..f1fb59fd
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test6.h.ref
@@ -0,0 +1,94 @@
+// This file is generated by kconfig_compiler from test6.kcfg.
+// All changes you do to this file will be lost.
+#ifndef TEST6_H
+#define TEST6_H
+
+#include <kconfigskeleton.h>
+#include <QCoreApplication>
+#include <QDebug>
+
+class Test6 : public KConfigSkeleton
+{
+ public:
+
+ Test6( const QString & Number );
+ ~Test6();
+
+ /**
+ Set Block colors.
+ */
+ void setColor( const QColor & v )
+ {
+ if (!isImmutable( QString::fromLatin1( "Color" ) ))
+ mColor = v;
+ }
+
+ /**
+ Get Block colors.
+ */
+ QColor color() const
+ {
+ return mColor;
+ }
+
+ /**
+ Set foo bar
+ */
+ void setFooBar( const QString & v )
+ {
+ if (!isImmutable( QString::fromLatin1( "FooBar" ) ))
+ mFooBar = v;
+ }
+
+ /**
+ Get foo bar
+ */
+ QString fooBar() const
+ {
+ return mFooBar;
+ }
+
+ /**
+ Set Age
+ */
+ void setAge( int v )
+ {
+ if (v < 8)
+ {
+ qDebug() << "setAge: value " << v << " is less than the minimum value of 8";
+ v = 8;
+ }
+
+ if (v > 88)
+ {
+ qDebug() << "setAge: value " << v << " is greater than the maximum value of 88";
+ v = 88;
+ }
+
+ if (!isImmutable( QString::fromLatin1( "Age" ) ))
+ mAge = v;
+ }
+
+ /**
+ Get Age
+ */
+ int age() const
+ {
+ return mAge;
+ }
+
+ protected:
+ QString mParamNumber;
+
+ // Foo
+ QColor mColor;
+
+ // Bar$(Number)
+ QString mFooBar;
+ int mAge;
+
+ private:
+};
+
+#endif
+
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test6.kcfg b/tier1/kconfig/autotests/kconfig_compiler/test6.kcfg
new file mode 100644
index 00000000..e59fa88f
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test6.kcfg
@@ -0,0 +1,25 @@
+<?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="test4rc">
+ <parameter name="Number" type="String"/>
+ </kcfgfile>
+
+ <group name="Foo">
+ <entry name="Color" type="Color" key="color #$(Number)">
+ <label>Block colors.</label>
+ <default>red</default>
+ </entry>
+ </group>
+ <group name="Bar$(Number)">
+ <entry name="FooBar" key="foo bar" type="String"/>
+ <entry name="Age" type="Int">
+ <default>35</default>
+ <min>8</min>
+ <max>88</max>
+ </entry>
+ </group>
+
+</kcfg>
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test6.kcfgc b/tier1/kconfig/autotests/kconfig_compiler/test6.kcfgc
new file mode 100644
index 00000000..b69dc152
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test6.kcfgc
@@ -0,0 +1,11 @@
+# Code generation options for kconfig_compiler
+File=test6.kcfg
+ClassName=Test6
+Singleton=false
+Mutators=true
+#Inherits=MyPrefs
+#IncludeFiles=myprefs.h
+#MemberVariables=public
+GlobalEnums=true
+ItemAccessors=false
+#SetUserTexts=true
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test6main.cpp b/tier1/kconfig/autotests/kconfig_compiler/test6main.cpp
new file mode 100644
index 00000000..a60d8378
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test6main.cpp
@@ -0,0 +1,32 @@
+/*
+Copyright (c) 2004 Waldo Bastian <bastian@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "test6.h"
+#include <QGuiApplication>
+
+int main( int argc, char **argv )
+{
+ QGuiApplication app(argc, argv);
+ Q_UNUSED(app);
+ Test6 *t = new Test6(QString());
+ delete t;
+ return 0;
+}
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test7.cpp.ref b/tier1/kconfig/autotests/kconfig_compiler/test7.cpp.ref
new file mode 100644
index 00000000..4ee7d280
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test7.cpp.ref
@@ -0,0 +1,31 @@
+// This file is generated by kconfig_compiler from test7.kcfg.
+// All changes you do to this file will be lost.
+
+#include "test7.h"
+
+Test7::Test7( int Number )
+ : KConfigSkeleton( QLatin1String( "test7rc" ) )
+ , mParamNumber(Number)
+{
+ setCurrentGroup( QLatin1String( "Foo" ) );
+
+ KConfigSkeleton::ItemColor *itemColor;
+ itemColor = new KConfigSkeleton::ItemColor( currentGroup(), QString( QLatin1String( "color #%1" ) ).arg( mParamNumber ), mColor, QColor( "red" ) );
+ addItem( itemColor, QLatin1String( "Color" ) );
+
+ setCurrentGroup( QString( QLatin1String( "Bar%1" ) ).arg( mParamNumber ) );
+
+ KConfigSkeleton::ItemString *itemFooBar;
+ itemFooBar = new KConfigSkeleton::ItemString( currentGroup(), QLatin1String( "foo bar" ), mFooBar );
+ addItem( itemFooBar, QLatin1String( "FooBar" ) );
+ KConfigSkeleton::ItemInt *itemAge;
+ itemAge = new KConfigSkeleton::ItemInt( currentGroup(), QLatin1String( "Age" ), mAge, 35 );
+ itemAge->setMinValue(8);
+ itemAge->setMaxValue(88);
+ addItem( itemAge, QLatin1String( "Age" ) );
+}
+
+Test7::~Test7()
+{
+}
+
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test7.h.ref b/tier1/kconfig/autotests/kconfig_compiler/test7.h.ref
new file mode 100644
index 00000000..417c75ad
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test7.h.ref
@@ -0,0 +1,94 @@
+// This file is generated by kconfig_compiler from test7.kcfg.
+// All changes you do to this file will be lost.
+#ifndef TEST7_H
+#define TEST7_H
+
+#include <kconfigskeleton.h>
+#include <QCoreApplication>
+#include <QDebug>
+
+class Test7 : public KConfigSkeleton
+{
+ public:
+
+ Test7( int Number );
+ ~Test7();
+
+ /**
+ Set Block colors.
+ */
+ void setColor( const QColor & v )
+ {
+ if (!isImmutable( QString::fromLatin1( "Color" ) ))
+ mColor = v;
+ }
+
+ /**
+ Get Block colors.
+ */
+ QColor color() const
+ {
+ return mColor;
+ }
+
+ /**
+ Set foo bar
+ */
+ void setFooBar( const QString & v )
+ {
+ if (!isImmutable( QString::fromLatin1( "FooBar" ) ))
+ mFooBar = v;
+ }
+
+ /**
+ Get foo bar
+ */
+ QString fooBar() const
+ {
+ return mFooBar;
+ }
+
+ /**
+ Set Age
+ */
+ void setAge( int v )
+ {
+ if (v < 8)
+ {
+ qDebug() << "setAge: value " << v << " is less than the minimum value of 8";
+ v = 8;
+ }
+
+ if (v > 88)
+ {
+ qDebug() << "setAge: value " << v << " is greater than the maximum value of 88";
+ v = 88;
+ }
+
+ if (!isImmutable( QString::fromLatin1( "Age" ) ))
+ mAge = v;
+ }
+
+ /**
+ Get Age
+ */
+ int age() const
+ {
+ return mAge;
+ }
+
+ protected:
+ int mParamNumber;
+
+ // Foo
+ QColor mColor;
+
+ // Bar$(Number)
+ QString mFooBar;
+ int mAge;
+
+ private:
+};
+
+#endif
+
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test7.kcfg b/tier1/kconfig/autotests/kconfig_compiler/test7.kcfg
new file mode 100644
index 00000000..0a7fd327
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test7.kcfg
@@ -0,0 +1,25 @@
+<?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="test7rc">
+ <parameter name="Number" type="Int"/>
+ </kcfgfile>
+
+ <group name="Foo">
+ <entry name="Color" type="Color" key="color #$(Number)">
+ <label>Block colors.</label>
+ <default>red</default>
+ </entry>
+ </group>
+ <group name="Bar$(Number)">
+ <entry name="FooBar" key="foo bar" type="String"/>
+ <entry name="Age" type="Int">
+ <default>35</default>
+ <min>8</min>
+ <max>88</max>
+ </entry>
+ </group>
+
+</kcfg>
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test7.kcfgc b/tier1/kconfig/autotests/kconfig_compiler/test7.kcfgc
new file mode 100644
index 00000000..9a6c4095
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test7.kcfgc
@@ -0,0 +1,11 @@
+# Code generation options for kconfig_compiler
+File=test7.kcfg
+ClassName=Test7
+Singleton=false
+Mutators=true
+#Inherits=MyPrefs
+#IncludeFiles=myprefs.h
+#MemberVariables=public
+GlobalEnums=true
+ItemAccessors=false
+#SetUserTexts=true
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test7main.cpp b/tier1/kconfig/autotests/kconfig_compiler/test7main.cpp
new file mode 100644
index 00000000..bf55be20
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test7main.cpp
@@ -0,0 +1,32 @@
+/*
+Copyright (c) 2004 Waldo Bastian <bastian@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "test7.h"
+#include <QGuiApplication>
+
+int main( int argc, char **argv )
+{
+ QGuiApplication app(argc, argv);
+ Q_UNUSED(app);
+ Test7 *t = new Test7(42);
+ delete t;
+ return 0;
+}
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test8a.cpp.ref b/tier1/kconfig/autotests/kconfig_compiler/test8a.cpp.ref
new file mode 100644
index 00000000..af85f0ce
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test8a.cpp.ref
@@ -0,0 +1,22 @@
+// This file is generated by kconfig_compiler from test8a.kcfg.
+// All changes you do to this file will be lost.
+
+#include "test8a.h"
+
+Test8a::Test8a( KSharedConfig::Ptr config )
+ : KConfigSkeleton( config )
+{
+ setCurrentGroup( QLatin1String( "Group" ) );
+
+ KConfigSkeleton::ItemFont *itemFont;
+ itemFont = new KConfigSkeleton::ItemFont( currentGroup(), QLatin1String( "Font" ), mFont, QFont() );
+ addItem( itemFont, QLatin1String( "Font" ) );
+ KConfigSkeleton::ItemFont *itemTitleFont;
+ itemTitleFont = new KConfigSkeleton::ItemFont( currentGroup(), QLatin1String( "TitleFont" ), mTitleFont, QFont() );
+ addItem( itemTitleFont, QLatin1String( "TitleFont" ) );
+}
+
+Test8a::~Test8a()
+{
+}
+
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test8a.h.ref b/tier1/kconfig/autotests/kconfig_compiler/test8a.h.ref
new file mode 100644
index 00000000..fd1b3648
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test8a.h.ref
@@ -0,0 +1,62 @@
+// This file is generated by kconfig_compiler from test8a.kcfg.
+// All changes you do to this file will be lost.
+#ifndef TEST8A_H
+#define TEST8A_H
+
+#include <qglobal.h>
+#include <kconfigskeleton.h>
+#include <QCoreApplication>
+#include <QDebug>
+
+class Test8a : public KConfigSkeleton
+{
+ public:
+
+ Test8a( KSharedConfig::Ptr config = KSharedConfig::openConfig() );
+ ~Test8a();
+
+ /**
+ Set Font
+ */
+ void setFont( const QFont & v )
+ {
+ if (!isImmutable( QString::fromLatin1( "Font" ) ))
+ mFont = v;
+ }
+
+ /**
+ Get Font
+ */
+ QFont font() const
+ {
+ return mFont;
+ }
+
+ /**
+ Set TitleFont
+ */
+ void setTitleFont( const QFont & v )
+ {
+ if (!isImmutable( QString::fromLatin1( "TitleFont" ) ))
+ mTitleFont = v;
+ }
+
+ /**
+ Get TitleFont
+ */
+ QFont titleFont() const
+ {
+ return mTitleFont;
+ }
+
+ protected:
+
+ // Group
+ QFont mFont;
+ QFont mTitleFont;
+
+ private:
+};
+
+#endif
+
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test8a.kcfg b/tier1/kconfig/autotests/kconfig_compiler/test8a.kcfg
new file mode 100644
index 00000000..24038a69
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test8a.kcfg
@@ -0,0 +1,17 @@
+<?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 arg="true"/>
+
+ <group name="Group">
+ <entry name="Font" type="Font">
+ <default code="true">QFont()</default>
+ </entry>
+
+ <entry name="TitleFont" type="Font">
+ <default code="true">QFont()</default>
+ </entry>
+ </group>
+</kcfg>
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test8a.kcfgc b/tier1/kconfig/autotests/kconfig_compiler/test8a.kcfgc
new file mode 100644
index 00000000..5f63c31c
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test8a.kcfgc
@@ -0,0 +1,3 @@
+File=test8a.kcfg
+ClassName=Test8a
+Mutators=true
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test8b.cpp.ref b/tier1/kconfig/autotests/kconfig_compiler/test8b.cpp.ref
new file mode 100644
index 00000000..ba0c8b47
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test8b.cpp.ref
@@ -0,0 +1,52 @@
+// This file is generated by kconfig_compiler from test8b.kcfg.
+// All changes you do to this file will be lost.
+
+#include "test8b.h"
+
+#include <qglobal.h>
+#include <QtCore/QFile>
+
+class Test8bHelper
+{
+ public:
+ Test8bHelper() : q(0) {}
+ ~Test8bHelper() { delete q; }
+ Test8b *q;
+};
+Q_GLOBAL_STATIC(Test8bHelper, s_globalTest8b)
+Test8b *Test8b::self()
+{
+ if (!s_globalTest8b()->q) {
+ new Test8b;
+ s_globalTest8b()->q->readConfig();
+ }
+
+ return s_globalTest8b()->q;
+}
+
+Test8b::Test8b( )
+ : Test8a()
+{
+ Q_ASSERT(!s_globalTest8b()->q);
+ s_globalTest8b()->q = this;
+ setCurrentGroup( QLatin1String( "Group8b1" ) );
+
+ Test8a::ItemUInt *itemSomething;
+ itemSomething = new Test8a::ItemUInt( currentGroup(), QLatin1String( "Something" ), mSomething, 60 );
+ addItem( itemSomething, QLatin1String( "Something" ) );
+
+ setCurrentGroup( QLatin1String( "Group8b2" ) );
+
+ Test8a::ItemBool *itemFooBoo;
+ itemFooBoo = new Test8a::ItemBool( currentGroup(), QLatin1String( "FooBoo" ), mFooBoo, false );
+ addItem( itemFooBoo, QLatin1String( "FooBoo" ) );
+ Test8a::ItemUInt *itemPort;
+ itemPort = new Test8a::ItemUInt( currentGroup(), QLatin1String( "Port" ), mPort, 1000 );
+ addItem( itemPort, QLatin1String( "Port" ) );
+}
+
+Test8b::~Test8b()
+{
+ s_globalTest8b()->q = 0;
+}
+
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test8b.h.ref b/tier1/kconfig/autotests/kconfig_compiler/test8b.h.ref
new file mode 100644
index 00000000..140bbb90
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test8b.h.ref
@@ -0,0 +1,92 @@
+// This file is generated by kconfig_compiler from test8b.kcfg.
+// All changes you do to this file will be lost.
+#ifndef TEST8B_H
+#define TEST8B_H
+
+#include <test8a.h>
+
+#include <kconfigskeleton.h>
+#include <QCoreApplication>
+#include <QDebug>
+
+class Test8b : public Test8a
+{
+ public:
+
+ static Test8b *self();
+ ~Test8b();
+
+ /**
+ Set Something
+ */
+ static
+ void setSomething( uint v )
+ {
+ if (!self()->isImmutable( QString::fromLatin1( "Something" ) ))
+ self()->mSomething = v;
+ }
+
+ /**
+ Get Something
+ */
+ static
+ uint something()
+ {
+ return self()->mSomething;
+ }
+
+ /**
+ Set FooBoo
+ */
+ static
+ void setFooBoo( bool v )
+ {
+ if (!self()->isImmutable( QString::fromLatin1( "FooBoo" ) ))
+ self()->mFooBoo = v;
+ }
+
+ /**
+ Get FooBoo
+ */
+ static
+ bool fooBoo()
+ {
+ return self()->mFooBoo;
+ }
+
+ /**
+ Set Port
+ */
+ static
+ void setPort( uint v )
+ {
+ if (!self()->isImmutable( QString::fromLatin1( "Port" ) ))
+ self()->mPort = v;
+ }
+
+ /**
+ Get Port
+ */
+ static
+ uint port()
+ {
+ return self()->mPort;
+ }
+
+ protected:
+ Test8b();
+ friend class Test8bHelper;
+
+
+ // Group8b1
+ uint mSomething;
+
+ // Group8b2
+ bool mFooBoo;
+ uint mPort;
+
+ private:
+};
+
+#endif
+
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test8b.kcfg b/tier1/kconfig/autotests/kconfig_compiler/test8b.kcfg
new file mode 100644
index 00000000..3e203a15
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test8b.kcfg
@@ -0,0 +1,21 @@
+<?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" >
+ <group name="Group8b1">
+ <entry name="Something" type="UInt">
+ <default>60</default>
+ </entry>
+ </group>
+
+ <group name="Group8b2">
+ <entry name="FooBoo" type="Bool">
+ <default>false</default>
+ </entry>
+
+ <entry name="Port" type="UInt">
+ <default>1000</default>
+ </entry>
+ </group>
+</kcfg>
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test8b.kcfgc b/tier1/kconfig/autotests/kconfig_compiler/test8b.kcfgc
new file mode 100644
index 00000000..7be05520
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test8b.kcfgc
@@ -0,0 +1,6 @@
+File=test8b.kcfg
+ClassName=Test8b
+Mutators=true
+Singleton=true
+IncludeFiles=test8a.h
+Inherits=Test8a
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test8main.cpp b/tier1/kconfig/autotests/kconfig_compiler/test8main.cpp
new file mode 100644
index 00000000..c4576911
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test8main.cpp
@@ -0,0 +1,36 @@
+/*
+Copyright (c) 2005 Michael Brade <brade@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "test8a.h"
+#include "test8b.h"
+#include <QGuiApplication>
+
+int main( int argc, char **argv )
+{
+ QGuiApplication app(argc, argv);
+ Q_UNUSED(app);
+ Test8a *config1 = new Test8a( KSharedConfig::openConfig( QString() ) );
+ Test8a *config2 = new Test8a();
+ Test8b::self();
+ delete config1;
+ delete config2;
+ return 0;
+}
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test9.cpp.ref b/tier1/kconfig/autotests/kconfig_compiler/test9.cpp.ref
new file mode 100644
index 00000000..af90acd9
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test9.cpp.ref
@@ -0,0 +1,35 @@
+// This file is generated by kconfig_compiler from test9.kcfg.
+// All changes you do to this file will be lost.
+
+#include "test9.h"
+
+Test9::Test9( const QString & transport, const QString & folder )
+ : KConfigSkeleton( QLatin1String( "examplerc" ) )
+ , mParamtransport(transport)
+ , mParamfolder(folder)
+{
+ setCurrentGroup( QLatin1String( "MyOptionsXX" ) );
+
+ QStringList defaultMyStringList;
+ defaultMyStringList.append( QString::fromUtf8( "up" ) );
+ defaultMyStringList.append( QString::fromUtf8( "down" ) );
+
+ KConfigSkeleton::ItemStringList *itemMyStringList;
+ itemMyStringList = new KConfigSkeleton::ItemStringList( currentGroup(), QLatin1String( "MyStringList" ), mMyStringList, defaultMyStringList );
+ addItem( itemMyStringList, QLatin1String( "MyStringList" ) );
+ QStringList defaultMyPathList;
+ defaultMyPathList.append( QString::fromUtf8( "/home" ) );
+ defaultMyPathList.append( QString::fromUtf8( "~" ) );
+
+ KConfigSkeleton::ItemPathList *itemMyPathList;
+ itemMyPathList = new KConfigSkeleton::ItemPathList( currentGroup(), QLatin1String( "MyPathList" ), mMyPathList, defaultMyPathList );
+ addItem( itemMyPathList, QLatin1String( "MyPathList" ) );
+ KConfigSkeleton::ItemPathList *itemMyPathsList2;
+ itemMyPathsList2 = new KConfigSkeleton::ItemPathList( currentGroup(), QLatin1String( "MyPathsList2" ), mMyPathsList2, QStringList(QString::fromLatin1("/usr/bin")) << QDir::homePath() );
+ addItem( itemMyPathsList2, QLatin1String( "MyPathsList2" ) );
+}
+
+Test9::~Test9()
+{
+}
+
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test9.h.ref b/tier1/kconfig/autotests/kconfig_compiler/test9.h.ref
new file mode 100644
index 00000000..02b3d479
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test9.h.ref
@@ -0,0 +1,83 @@
+// This file is generated by kconfig_compiler from test9.kcfg.
+// All changes you do to this file will be lost.
+#ifndef TEST9_H
+#define TEST9_H
+
+#include <kconfigskeleton.h>
+#include <QCoreApplication>
+#include <QDebug>
+
+#include <qdir.h>
+class Test9 : public KConfigSkeleton
+{
+ public:
+
+ Test9( const QString & transport, const QString & folder );
+ ~Test9();
+
+ /**
+ Set MyStringList
+ */
+ void setMyStringList( const QStringList & v )
+ {
+ if (!isImmutable( QString::fromLatin1( "MyStringList" ) ))
+ mMyStringList = v;
+ }
+
+ /**
+ Get MyStringList
+ */
+ QStringList myStringList() const
+ {
+ return mMyStringList;
+ }
+
+ /**
+ Set This is a list of paths
+ */
+ void setMyPathList( const QStringList & v )
+ {
+ if (!isImmutable( QString::fromLatin1( "MyPathList" ) ))
+ mMyPathList = v;
+ }
+
+ /**
+ Get This is a list of paths
+ */
+ QStringList myPathList() const
+ {
+ return mMyPathList;
+ }
+
+ /**
+ Set This is an additional test for PathList
+ */
+ void setMyPathsList2( const QStringList & v )
+ {
+ if (!isImmutable( QString::fromLatin1( "MyPathsList2" ) ))
+ mMyPathsList2 = v;
+ }
+
+ /**
+ Get This is an additional test for PathList
+ */
+ QStringList myPathsList2() const
+ {
+ return mMyPathsList2;
+ }
+
+ protected:
+ public:
+ QString mParamtransport;
+ QString mParamfolder;
+
+ // MyOptionsXX
+ QStringList mMyStringList;
+ QStringList mMyPathList;
+ QStringList mMyPathsList2;
+
+ private:
+};
+
+#endif
+
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test9.kcfg b/tier1/kconfig/autotests/kconfig_compiler/test9.kcfg
new file mode 100644
index 00000000..73e96f49
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test9.kcfg
@@ -0,0 +1,24 @@
+<?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" >
+ <include>qdir.h</include>
+ <kcfgfile name="examplerc">
+ <parameter name="transport" />
+ <parameter name="folder" />
+ </kcfgfile>
+ <group name="MyOptionsXX">
+ <entry name="MyStringList" type="StringList">
+ <default>up,down</default>
+ </entry>
+ <entry name="MyPathList" type="PathList">
+ <label>This is a list of paths</label>
+ <default>/home,~</default>
+ </entry>
+ <entry name="MyPathsList2" type="PathList">
+ <label>This is an additional test for PathList</label>
+ <default code="true">QStringList(QString::fromLatin1("/usr/bin")) &lt;&lt; QDir::homePath()</default>
+ </entry>
+ </group>
+</kcfg>
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test9.kcfgc b/tier1/kconfig/autotests/kconfig_compiler/test9.kcfgc
new file mode 100644
index 00000000..d4423338
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test9.kcfgc
@@ -0,0 +1,18 @@
+# Code generation options for kconfig_compiler
+ClassName=Test9
+#
+# Singleton=false
+#
+# Inherits=KConfigSkeleton
+#
+# IncludeFiles=libkdepim/kpimprefs.h
+#
+MemberVariables=public
+#
+### The following line includes the file exampleprefs_base_addon.h
+### It can be used to add extra functions and variables to the
+### class.
+# CustomAdditions=true
+#
+### Provide setFooBar(int) style functions
+Mutators=true
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test9main.cpp b/tier1/kconfig/autotests/kconfig_compiler/test9main.cpp
new file mode 100644
index 00000000..352613aa
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test9main.cpp
@@ -0,0 +1,45 @@
+/*
+Copyright (c) 2005 Helge Deller <deller@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#include "test9.h"
+#include <QtCore/QDir>
+#include <QGuiApplication>
+#include <QDebug>
+
+int main( int argc, char **argv )
+{
+ QGuiApplication app(argc, argv);
+ Q_UNUSED(app);
+ Test9 *t = new Test9( QString(), QString() );
+
+ QStringList myPathsList2 = t->myPathsList2();
+ qWarning() << myPathsList2;
+
+ // add another path
+ QStringList newlist;
+ myPathsList2 << QDir::homePath() + QString::fromLatin1("/.kde");
+ qWarning() << myPathsList2;
+
+ t->setMyPathsList2(myPathsList2);
+ qWarning() << t->myPathsList2();
+
+ delete t;
+ return 0;
+}
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test_dpointer.cpp.ref b/tier1/kconfig/autotests/kconfig_compiler/test_dpointer.cpp.ref
new file mode 100644
index 00000000..ffe931e5
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test_dpointer.cpp.ref
@@ -0,0 +1,348 @@
+// This file is generated by kconfig_compiler from test_dpointer.kcfg.
+// All changes you do to this file will be lost.
+
+#include "test_dpointer.h"
+
+#include <qglobal.h>
+#include <QtCore/QFile>
+
+class TestDPointerPrivate
+{
+ public:
+
+ // General
+ bool autoSave;
+ int autoSaveInterval;
+ bool confirm;
+ QString archiveFile;
+ int destination;
+
+ // Views
+ int hourSize;
+ bool selectionStartsEditor;
+
+ // KOrganizer Plugins
+ QStringList selectedPlugins;
+
+ // Colors
+ QColor highlightColor;
+ QColor agendaBgColor;
+
+ // Fonts
+ QFont timeBarFont;
+
+ // items
+ KConfigSkeleton::ItemBool *autoSaveItem;
+ KConfigSkeleton::ItemInt *autoSaveIntervalItem;
+ KConfigSkeleton::ItemBool *confirmItem;
+ KConfigSkeleton::ItemString *archiveFileItem;
+ KConfigSkeleton::ItemEnum *destinationItem;
+ KConfigSkeleton::ItemInt *hourSizeItem;
+ KConfigSkeleton::ItemBool *selectionStartsEditorItem;
+ KConfigSkeleton::ItemStringList *selectedPluginsItem;
+ KConfigSkeleton::ItemColor *highlightColorItem;
+ KConfigSkeleton::ItemColor *agendaBgColorItem;
+ KConfigSkeleton::ItemFont *timeBarFontItem;
+};
+
+class TestDPointerHelper
+{
+ public:
+ TestDPointerHelper() : q(0) {}
+ ~TestDPointerHelper() { delete q; }
+ TestDPointer *q;
+};
+Q_GLOBAL_STATIC(TestDPointerHelper, s_globalTestDPointer)
+TestDPointer *TestDPointer::self()
+{
+ if (!s_globalTestDPointer()->q) {
+ new TestDPointer;
+ s_globalTestDPointer()->q->readConfig();
+ }
+
+ return s_globalTestDPointer()->q;
+}
+
+TestDPointer::TestDPointer( )
+ : KConfigSkeleton( QLatin1String( "korganizerrc" ) )
+{
+ d = new TestDPointerPrivate;
+ Q_ASSERT(!s_globalTestDPointer()->q);
+ s_globalTestDPointer()->q = this;
+ setCurrentGroup( QLatin1String( "General" ) );
+
+ d->autoSaveItem = new KConfigSkeleton::ItemBool( currentGroup(), QLatin1String( "Auto Save" ), d->autoSave, false );
+ d->autoSaveItem->setLabel( QCoreApplication::translate("TestDPointer", "Enable automatic saving of calendar") );
+ d->autoSaveItem->setWhatsThis( QCoreApplication::translate("TestDPointer", "WhatsThis text for AutoSave option") );
+ addItem( d->autoSaveItem, QLatin1String( "AutoSave" ) );
+ d->autoSaveIntervalItem = new KConfigSkeleton::ItemInt( currentGroup(), QLatin1String( "Auto Save Interval" ), d->autoSaveInterval, 10 );
+ d->autoSaveIntervalItem->setLabel( QCoreApplication::translate("TestDPointer", "Auto Save Interval") );
+ addItem( d->autoSaveIntervalItem, QLatin1String( "AutoSaveInterval" ) );
+ d->confirmItem = new KConfigSkeleton::ItemBool( currentGroup(), QLatin1String( "Confirm Deletes" ), d->confirm, true );
+ d->confirmItem->setLabel( QCoreApplication::translate("TestDPointer", "Confirm deletes") );
+ addItem( d->confirmItem, QLatin1String( "Confirm" ) );
+ d->archiveFileItem = new KConfigSkeleton::ItemString( currentGroup(), QLatin1String( "Archive File" ), d->archiveFile );
+ d->archiveFileItem->setLabel( QCoreApplication::translate("TestDPointer", "Archive File") );
+ addItem( d->archiveFileItem, QLatin1String( "ArchiveFile" ) );
+ QList<KConfigSkeleton::ItemEnum::Choice> valuesDestination;
+ {
+ KConfigSkeleton::ItemEnum::Choice choice;
+ choice.name = QLatin1String("standardDestination");
+ valuesDestination.append( choice );
+ }
+ {
+ KConfigSkeleton::ItemEnum::Choice choice;
+ choice.name = QLatin1String("askDestination");
+ valuesDestination.append( choice );
+ }
+ {
+ KConfigSkeleton::ItemEnum::Choice choice;
+ choice.name = QLatin1String("argl1");
+ choice.label = QCoreApplication::translate("TestDPointer", "Argl1 Label");
+ valuesDestination.append( choice );
+ }
+ {
+ KConfigSkeleton::ItemEnum::Choice choice;
+ choice.name = QLatin1String("argl2");
+ choice.whatsThis = QCoreApplication::translate("TestDPointer", "Argl2 Whatsthis");
+ valuesDestination.append( choice );
+ }
+ {
+ KConfigSkeleton::ItemEnum::Choice choice;
+ choice.name = QLatin1String("argl3");
+ choice.label = QCoreApplication::translate("TestDPointer", "Argl3 Label");
+ choice.whatsThis = QCoreApplication::translate("TestDPointer", "Argl3 Whatsthis");
+ valuesDestination.append( choice );
+ }
+ d->destinationItem = new KConfigSkeleton::ItemEnum( currentGroup(), QLatin1String( "Destination" ), d->destination, valuesDestination, EnumDestination::standardDestination );
+ d->destinationItem->setLabel( QCoreApplication::translate("TestDPointer", "New Events/Todos Should") );
+ addItem( d->destinationItem, QLatin1String( "Destination" ) );
+
+ setCurrentGroup( QLatin1String( "Views" ) );
+
+ d->hourSizeItem = new KConfigSkeleton::ItemInt( currentGroup(), QLatin1String( "Hour Size" ), d->hourSize, 10 );
+ d->hourSizeItem->setLabel( QCoreApplication::translate("TestDPointer", "Hour Size") );
+ addItem( d->hourSizeItem, QLatin1String( "HourSize" ) );
+ d->selectionStartsEditorItem = new KConfigSkeleton::ItemBool( currentGroup(), QLatin1String( "SelectionStartsEditor" ), d->selectionStartsEditor, false );
+ d->selectionStartsEditorItem->setLabel( QCoreApplication::translate("TestDPointer", "Time range selection in agenda view starts event editor") );
+ addItem( d->selectionStartsEditorItem, QLatin1String( "SelectionStartsEditor" ) );
+
+ setCurrentGroup( QLatin1String( "KOrganizer Plugins" ) );
+
+ QStringList defaultSelectedPlugins;
+ defaultSelectedPlugins.append( QString::fromUtf8( "holidays" ) );
+ defaultSelectedPlugins.append( QString::fromUtf8( "webexport" ) );
+
+ d->selectedPluginsItem = new KConfigSkeleton::ItemStringList( currentGroup(), QLatin1String( "SelectedPlugins" ), d->selectedPlugins, defaultSelectedPlugins );
+ d->selectedPluginsItem->setLabel( QCoreApplication::translate("TestDPointer", "SelectedPlugins") );
+ addItem( d->selectedPluginsItem, QLatin1String( "SelectedPlugins" ) );
+
+ setCurrentGroup( QLatin1String( "Colors" ) );
+
+ d->highlightColorItem = new KConfigSkeleton::ItemColor( currentGroup(), QLatin1String( "Highlight Color" ), d->highlightColor, QColor( 100, 100, 255 ) );
+ d->highlightColorItem->setLabel( QCoreApplication::translate("TestDPointer", "Highlight color") );
+ addItem( d->highlightColorItem, QLatin1String( "HighlightColor" ) );
+ d->agendaBgColorItem = new KConfigSkeleton::ItemColor( currentGroup(), QLatin1String( "Agenda Background Color" ), d->agendaBgColor, QColor( 255, 255, 255 ) );
+ d->agendaBgColorItem->setLabel( QCoreApplication::translate("TestDPointer", "Agenda view background color") );
+ addItem( d->agendaBgColorItem, QLatin1String( "AgendaBgColor" ) );
+
+ setCurrentGroup( QLatin1String( "Fonts" ) );
+
+ d->timeBarFontItem = new KConfigSkeleton::ItemFont( currentGroup(), QLatin1String( "TimeBar Font" ), d->timeBarFont );
+ d->timeBarFontItem->setLabel( QCoreApplication::translate("TestDPointer", "Time bar") );
+ addItem( d->timeBarFontItem, QLatin1String( "TimeBarFont" ) );
+}
+
+void TestDPointer::setAutoSave( bool v )
+{
+ if (!self()->isImmutable( QString::fromLatin1( "AutoSave" ) ))
+ self()->d->autoSave = v;
+}
+
+bool TestDPointer::autoSave()
+{
+ return self()->d->autoSave;
+}
+
+
+KConfigSkeleton::ItemBool *TestDPointer::autoSaveItem()
+{
+ return d->autoSaveItem;
+}
+
+void TestDPointer::setAutoSaveInterval( int v )
+{
+ if (!self()->isImmutable( QString::fromLatin1( "AutoSaveInterval" ) ))
+ self()->d->autoSaveInterval = v;
+}
+
+int TestDPointer::autoSaveInterval()
+{
+ return self()->d->autoSaveInterval;
+}
+
+
+KConfigSkeleton::ItemInt *TestDPointer::autoSaveIntervalItem()
+{
+ return d->autoSaveIntervalItem;
+}
+
+void TestDPointer::setConfirm( bool v )
+{
+ if (!self()->isImmutable( QString::fromLatin1( "Confirm" ) ))
+ self()->d->confirm = v;
+}
+
+bool TestDPointer::confirm()
+{
+ return self()->d->confirm;
+}
+
+
+KConfigSkeleton::ItemBool *TestDPointer::confirmItem()
+{
+ return d->confirmItem;
+}
+
+void TestDPointer::setArchiveFile( const QString & v )
+{
+ if (!self()->isImmutable( QString::fromLatin1( "ArchiveFile" ) ))
+ self()->d->archiveFile = v;
+}
+
+QString TestDPointer::archiveFile()
+{
+ return self()->d->archiveFile;
+}
+
+
+KConfigSkeleton::ItemString *TestDPointer::archiveFileItem()
+{
+ return d->archiveFileItem;
+}
+
+void TestDPointer::setDestination( int v )
+{
+ if (!self()->isImmutable( QString::fromLatin1( "Destination" ) ))
+ self()->d->destination = v;
+}
+
+int TestDPointer::destination()
+{
+ return self()->d->destination;
+}
+
+
+KConfigSkeleton::ItemEnum *TestDPointer::destinationItem()
+{
+ return d->destinationItem;
+}
+
+void TestDPointer::setHourSize( int v )
+{
+ if (!self()->isImmutable( QString::fromLatin1( "HourSize" ) ))
+ self()->d->hourSize = v;
+}
+
+int TestDPointer::hourSize()
+{
+ return self()->d->hourSize;
+}
+
+
+KConfigSkeleton::ItemInt *TestDPointer::hourSizeItem()
+{
+ return d->hourSizeItem;
+}
+
+void TestDPointer::setSelectionStartsEditor( bool v )
+{
+ if (!self()->isImmutable( QString::fromLatin1( "SelectionStartsEditor" ) ))
+ self()->d->selectionStartsEditor = v;
+}
+
+bool TestDPointer::selectionStartsEditor()
+{
+ return self()->d->selectionStartsEditor;
+}
+
+
+KConfigSkeleton::ItemBool *TestDPointer::selectionStartsEditorItem()
+{
+ return d->selectionStartsEditorItem;
+}
+
+void TestDPointer::setSelectedPlugins( const QStringList & v )
+{
+ if (!self()->isImmutable( QString::fromLatin1( "SelectedPlugins" ) ))
+ self()->d->selectedPlugins = v;
+}
+
+QStringList TestDPointer::selectedPlugins()
+{
+ return self()->d->selectedPlugins;
+}
+
+
+KConfigSkeleton::ItemStringList *TestDPointer::selectedPluginsItem()
+{
+ return d->selectedPluginsItem;
+}
+
+void TestDPointer::setHighlightColor( const QColor & v )
+{
+ if (!self()->isImmutable( QString::fromLatin1( "HighlightColor" ) ))
+ self()->d->highlightColor = v;
+}
+
+QColor TestDPointer::highlightColor()
+{
+ return self()->d->highlightColor;
+}
+
+
+KConfigSkeleton::ItemColor *TestDPointer::highlightColorItem()
+{
+ return d->highlightColorItem;
+}
+
+void TestDPointer::setAgendaBgColor( const QColor & v )
+{
+ if (!self()->isImmutable( QString::fromLatin1( "AgendaBgColor" ) ))
+ self()->d->agendaBgColor = v;
+}
+
+QColor TestDPointer::agendaBgColor()
+{
+ return self()->d->agendaBgColor;
+}
+
+
+KConfigSkeleton::ItemColor *TestDPointer::agendaBgColorItem()
+{
+ return d->agendaBgColorItem;
+}
+
+void TestDPointer::setTimeBarFont( const QFont & v )
+{
+ if (!self()->isImmutable( QString::fromLatin1( "TimeBarFont" ) ))
+ self()->d->timeBarFont = v;
+}
+
+QFont TestDPointer::timeBarFont()
+{
+ return self()->d->timeBarFont;
+}
+
+
+KConfigSkeleton::ItemFont *TestDPointer::timeBarFontItem()
+{
+ return d->timeBarFontItem;
+}
+
+TestDPointer::~TestDPointer()
+{
+ delete d;
+ s_globalTestDPointer()->q = 0;
+}
+
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test_dpointer.h.ref b/tier1/kconfig/autotests/kconfig_compiler/test_dpointer.h.ref
new file mode 100644
index 00000000..e10c8c7c
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test_dpointer.h.ref
@@ -0,0 +1,220 @@
+// This file is generated by kconfig_compiler from test_dpointer.kcfg.
+// All changes you do to this file will be lost.
+#ifndef TESTDPOINTER_H
+#define TESTDPOINTER_H
+
+#include <kconfigskeleton.h>
+#include <QCoreApplication>
+#include <QDebug>
+
+class TestDPointerPrivate;
+
+class TestDPointer : public KConfigSkeleton
+{
+ public:
+ class EnumDestination
+ {
+ public:
+ enum type { standardDestination, askDestination, argl1, argl2, argl3, COUNT };
+ };
+
+ static TestDPointer *self();
+ ~TestDPointer();
+
+ /**
+ Set Enable automatic saving of calendar
+ */
+ static
+ void setAutoSave( bool v );
+
+ /**
+ Get Enable automatic saving of calendar
+ */
+ static
+ bool autoSave();
+
+ /**
+ Get Item object corresponding to AutoSave()
+ */
+ ItemBool *autoSaveItem();
+
+ /**
+ Set Auto Save Interval
+ */
+ static
+ void setAutoSaveInterval( int v );
+
+ /**
+ Get Auto Save Interval
+ */
+ static
+ int autoSaveInterval();
+
+ /**
+ Get Item object corresponding to AutoSaveInterval()
+ */
+ ItemInt *autoSaveIntervalItem();
+
+ /**
+ Set Confirm deletes
+ */
+ static
+ void setConfirm( bool v );
+
+ /**
+ Get Confirm deletes
+ */
+ static
+ bool confirm();
+
+ /**
+ Get Item object corresponding to Confirm()
+ */
+ ItemBool *confirmItem();
+
+ /**
+ Set Archive File
+ */
+ static
+ void setArchiveFile( const QString & v );
+
+ /**
+ Get Archive File
+ */
+ static
+ QString archiveFile();
+
+ /**
+ Get Item object corresponding to ArchiveFile()
+ */
+ ItemString *archiveFileItem();
+
+ /**
+ Set New Events/Todos Should
+ */
+ static
+ void setDestination( int v );
+
+ /**
+ Get New Events/Todos Should
+ */
+ static
+ int destination();
+
+ /**
+ Get Item object corresponding to Destination()
+ */
+ ItemEnum *destinationItem();
+
+ /**
+ Set Hour Size
+ */
+ static
+ void setHourSize( int v );
+
+ /**
+ Get Hour Size
+ */
+ static
+ int hourSize();
+
+ /**
+ Get Item object corresponding to HourSize()
+ */
+ ItemInt *hourSizeItem();
+
+ /**
+ Set Time range selection in agenda view starts event editor
+ */
+ static
+ void setSelectionStartsEditor( bool v );
+
+ /**
+ Get Time range selection in agenda view starts event editor
+ */
+ static
+ bool selectionStartsEditor();
+
+ /**
+ Get Item object corresponding to SelectionStartsEditor()
+ */
+ ItemBool *selectionStartsEditorItem();
+
+ /**
+ Set SelectedPlugins
+ */
+ static
+ void setSelectedPlugins( const QStringList & v );
+
+ /**
+ Get SelectedPlugins
+ */
+ static
+ QStringList selectedPlugins();
+
+ /**
+ Get Item object corresponding to SelectedPlugins()
+ */
+ ItemStringList *selectedPluginsItem();
+
+ /**
+ Set Highlight color
+ */
+ static
+ void setHighlightColor( const QColor & v );
+
+ /**
+ Get Highlight color
+ */
+ static
+ QColor highlightColor();
+
+ /**
+ Get Item object corresponding to HighlightColor()
+ */
+ ItemColor *highlightColorItem();
+
+ /**
+ Set Agenda view background color
+ */
+ static
+ void setAgendaBgColor( const QColor & v );
+
+ /**
+ Get Agenda view background color
+ */
+ static
+ QColor agendaBgColor();
+
+ /**
+ Get Item object corresponding to AgendaBgColor()
+ */
+ ItemColor *agendaBgColorItem();
+
+ /**
+ Set Time bar
+ */
+ static
+ void setTimeBarFont( const QFont & v );
+
+ /**
+ Get Time bar
+ */
+ static
+ QFont timeBarFont();
+
+ /**
+ Get Item object corresponding to TimeBarFont()
+ */
+ ItemFont *timeBarFontItem();
+
+ protected:
+ TestDPointer();
+ friend class TestDPointerHelper;
+
+ private:
+ TestDPointerPrivate *d;
+};
+
+#endif
+
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test_dpointer.kcfg b/tier1/kconfig/autotests/kconfig_compiler/test_dpointer.kcfg
new file mode 100644
index 00000000..3b19e270
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test_dpointer.kcfg
@@ -0,0 +1,78 @@
+<?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="korganizerrc"/>
+
+ <group name="General">
+ <entry type="Bool" key="Auto Save">
+ <label>Enable automatic saving of calendar</label>
+ <whatsthis>WhatsThis text for AutoSave option</whatsthis>
+ <default>false</default>
+ </entry>
+ <entry type="Int" key="Auto Save Interval">
+ <default>10</default>
+ </entry>
+ <entry type="Bool" key="Confirm Deletes" name="Confirm">
+ <label>Confirm deletes</label>
+ <default>true</default>
+ </entry>
+ <entry type="String" key="Archive File">
+ </entry>
+ <entry type="Enum" key="Destination" name="Destination">
+ <label>New Events/Todos Should</label>
+ <choices>
+ <choice name="standardDestination">
+ </choice>
+ <choice name="askDestination">
+ </choice>
+ <choice name="argl1">
+ <label>Argl1 Label</label>
+ </choice>
+ <choice name="argl2">
+ <whatsthis>Argl2 Whatsthis</whatsthis>
+ </choice>
+ <choice name="argl3">
+ <label>Argl3 Label</label>
+ <whatsthis>Argl3 Whatsthis</whatsthis>
+ </choice>
+ </choices>
+ <default>standardDestination</default>
+ </entry>
+ </group>
+
+ <group name="Views">
+ <entry type="Int" key="Hour Size">
+ <default>10</default>
+ </entry>
+ <entry type="Bool" name="SelectionStartsEditor">
+ <label>Time range selection in agenda view starts event editor</label>
+ <default>false</default>
+ </entry>
+ </group>
+
+ <group name="KOrganizer Plugins">
+ <entry type="StringList" name="SelectedPlugins">
+ <default>holidays,webexport</default>
+ </entry>
+ </group>
+
+ <group name="Colors">
+ <entry type="Color" key="Highlight Color">
+ <label>Highlight color</label>
+ <default>100, 100, 255</default>
+ </entry>
+ <entry type="Color" key="Agenda Background Color" name="AgendaBgColor">
+ <label>Agenda view background color</label>
+ <default>255, 255, 255</default>
+ </entry>
+ </group>
+
+ <group name="Fonts">
+ <entry type="Font" key="TimeBar Font">
+ <label>Time bar</label>
+ </entry>
+ </group>
+
+</kcfg>
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test_dpointer.kcfgc b/tier1/kconfig/autotests/kconfig_compiler/test_dpointer.kcfgc
new file mode 100644
index 00000000..48baa376
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test_dpointer.kcfgc
@@ -0,0 +1,11 @@
+# Code generation options for kconfig_compiler
+File=test_dpointer.kcfg
+ClassName=TestDPointer
+Singleton=true
+Mutators=true
+#Inherits=MyPrefs
+#IncludeFiles=myprefs.h
+MemberVariables=dpointer
+#GlobalEnums=true
+ItemAccessors=true
+SetUserTexts=true
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test_dpointer_main.cpp b/tier1/kconfig/autotests/kconfig_compiler/test_dpointer_main.cpp
new file mode 100644
index 00000000..6e4cb806
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test_dpointer_main.cpp
@@ -0,0 +1,32 @@
+/*
+Copyright (c) 2005 Duncan Mac-Vicar P. <duncan@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "test_dpointer.h"
+#include <QGuiApplication>
+
+int main( int argc, char **argv )
+{
+ QGuiApplication app(argc, argv);
+ Q_UNUSED(app);
+ TestDPointer *t = TestDPointer::self();
+ delete t;
+ return 0;
+}
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test_signal.cpp.ref b/tier1/kconfig/autotests/kconfig_compiler/test_signal.cpp.ref
new file mode 100644
index 00000000..1dad37b5
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test_signal.cpp.ref
@@ -0,0 +1,73 @@
+// This file is generated by kconfig_compiler from test_signal.kcfg.
+// All changes you do to this file will be lost.
+
+#include "test_signal.h"
+
+#include <qglobal.h>
+#include <QtCore/QFile>
+
+class TestSignalHelper
+{
+ public:
+ TestSignalHelper() : q(0) {}
+ ~TestSignalHelper() { delete q; }
+ TestSignal *q;
+};
+Q_GLOBAL_STATIC(TestSignalHelper, s_globalTestSignal)
+TestSignal *TestSignal::self()
+{
+ if (!s_globalTestSignal()->q) {
+ new TestSignal;
+ s_globalTestSignal()->q->readConfig();
+ }
+
+ return s_globalTestSignal()->q;
+}
+
+TestSignal::TestSignal( )
+ : KConfigSkeleton( QLatin1String( "kconfig_compiler_test_rc" ) )
+ , mSettingsChanged(0)
+{
+ Q_ASSERT(!s_globalTestSignal()->q);
+ s_globalTestSignal()->q = this;
+ setCurrentGroup( QLatin1String( "Appearance" ) );
+
+ KConfigSkeleton::ItemString *itemEmoticonTheme;
+ itemEmoticonTheme = new KConfigSkeleton::ItemString( currentGroup(), QLatin1String( "emoticonTheme" ), mEmoticonTheme, QLatin1String( "Default" ) );
+ addItem( itemEmoticonTheme, QLatin1String( "emoticonTheme" ) );
+ KConfigSkeleton::ItemBool *itemUseEmoticon;
+ itemUseEmoticon = new KConfigSkeleton::ItemBool( currentGroup(), QLatin1String( "useEmoticon" ), mUseEmoticon, true );
+ addItem( itemUseEmoticon, QLatin1String( "useEmoticon" ) );
+ KConfigSkeleton::ItemBool *itemEmoticonRequireSpace;
+ itemEmoticonRequireSpace = new KConfigSkeleton::ItemBool( currentGroup(), QLatin1String( "emoticonRequireSpace" ), mEmoticonRequireSpace, true );
+ addItem( itemEmoticonRequireSpace, QLatin1String( "emoticonRequireSpace" ) );
+ KConfigSkeleton::ItemString *itemStylePath;
+ itemStylePath = new KConfigSkeleton::ItemString( currentGroup(), QLatin1String( "stylePath" ), mStylePath );
+ addItem( itemStylePath, QLatin1String( "stylePath" ) );
+ KConfigSkeleton::ItemString *itemStyleCSSVariant;
+ itemStyleCSSVariant = new KConfigSkeleton::ItemString( currentGroup(), QLatin1String( "styleVariant" ), mStyleCSSVariant );
+ addItem( itemStyleCSSVariant, QLatin1String( "StyleCSSVariant" ) );
+}
+
+TestSignal::~TestSignal()
+{
+ s_globalTestSignal()->q = 0;
+}
+
+bool TestSignal::usrWriteConfig()
+{
+ const bool res = KConfigSkeleton::usrWriteConfig();
+ if (!res) return false;
+
+ if ( mSettingsChanged & signalEmoticonSettingsChanged )
+ emit emoticonSettingsChanged();
+
+ if ( mSettingsChanged & signalStyleChanged )
+ emit styleChanged(mStylePath, mStyleCSSVariant);
+
+ mSettingsChanged = 0;
+ return true;
+}
+
+#include "test_signal.moc"
+
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test_signal.h.ref b/tier1/kconfig/autotests/kconfig_compiler/test_signal.h.ref
new file mode 100644
index 00000000..801ff926
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test_signal.h.ref
@@ -0,0 +1,153 @@
+// This file is generated by kconfig_compiler from test_signal.kcfg.
+// All changes you do to this file will be lost.
+#ifndef TESTSIGNAL_H
+#define TESTSIGNAL_H
+
+#include <kconfigskeleton.h>
+#include <QCoreApplication>
+#include <QDebug>
+
+class TestSignal : public KConfigSkeleton
+{
+ Q_OBJECT
+ public:
+
+ enum {
+ signalEmoticonSettingsChanged = 0x1,
+ signalStyleChanged = 0x2
+ };
+
+ static TestSignal *self();
+ ~TestSignal();
+
+ /**
+ Set Current emoticon theme.
+ */
+ static
+ void setEmoticonTheme( const QString & v )
+ {
+ if (!self()->isImmutable( QString::fromLatin1( "emoticonTheme" ) )) {
+ self()->mEmoticonTheme = v;
+ self()->mSettingsChanged |= signalEmoticonSettingsChanged;
+ }
+ }
+
+ /**
+ Get Current emoticon theme.
+ */
+ static
+ QString emoticonTheme()
+ {
+ return self()->mEmoticonTheme;
+ }
+
+ /**
+ Set Enable emoticon support in Kopete.
+ */
+ static
+ void setUseEmoticon( bool v )
+ {
+ if (!self()->isImmutable( QString::fromLatin1( "useEmoticon" ) )) {
+ self()->mUseEmoticon = v;
+ self()->mSettingsChanged |= signalEmoticonSettingsChanged;
+ }
+ }
+
+ /**
+ Get Enable emoticon support in Kopete.
+ */
+ static
+ bool useEmoticon()
+ {
+ return self()->mUseEmoticon;
+ }
+
+ /**
+ Set Use strict mode in emoticon parsing.
+ */
+ static
+ void setEmoticonRequireSpace( bool v )
+ {
+ if (!self()->isImmutable( QString::fromLatin1( "emoticonRequireSpace" ) )) {
+ self()->mEmoticonRequireSpace = v;
+ self()->mSettingsChanged |= signalEmoticonSettingsChanged;
+ }
+ }
+
+ /**
+ Get Use strict mode in emoticon parsing.
+ */
+ static
+ bool emoticonRequireSpace()
+ {
+ return self()->mEmoticonRequireSpace;
+ }
+
+ /**
+ Set Absolute path to a directory containing a Adium/Kopete chat window style.
+ */
+ static
+ void setStylePath( const QString & v )
+ {
+ if (!self()->isImmutable( QString::fromLatin1( "stylePath" ) )) {
+ self()->mStylePath = v;
+ self()->mSettingsChanged |= signalStyleChanged;
+ }
+ }
+
+ /**
+ Get Absolute path to a directory containing a Adium/Kopete chat window style.
+ */
+ static
+ QString stylePath()
+ {
+ return self()->mStylePath;
+ }
+
+ /**
+ Set Relative path to a CSS variant for the current style.
+ */
+ static
+ void setStyleCSSVariant( const QString & v )
+ {
+ if (!self()->isImmutable( QString::fromLatin1( "StyleCSSVariant" ) ))
+ self()->mStyleCSSVariant = v;
+ }
+
+ /**
+ Get Relative path to a CSS variant for the current style.
+ */
+ static
+ QString styleCSSVariant()
+ {
+ return self()->mStyleCSSVariant;
+ }
+
+
+ Q_SIGNALS:
+ void emoticonSettingsChanged();
+
+ /**
+ Tell when a complete style change.
+ */
+ void styleChanged(const QString & stylePath, const QString & StyleCSSVariant);
+
+ protected:
+ TestSignal();
+ friend class TestSignalHelper;
+
+ virtual bool usrWriteConfig();
+
+ // Appearance
+ QString mEmoticonTheme;
+ bool mUseEmoticon;
+ bool mEmoticonRequireSpace;
+ QString mStylePath;
+ QString mStyleCSSVariant;
+
+ private:
+ uint mSettingsChanged;
+};
+
+#endif
+
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test_signal.kcfg b/tier1/kconfig/autotests/kconfig_compiler/test_signal.kcfg
new file mode 100644
index 00000000..1b2c36ec
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test_signal.kcfg
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Author: Michaël Larouche-->
+<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="kconfig_compiler_test_rc"/>
+
+ <signal name="emoticonSettingsChanged" />
+
+ <signal name="styleChanged">
+ <label>Tell when a complete style change.</label>
+ <argument type="String">stylePath</argument>
+ <argument type="String">StyleCSSVariant</argument>
+ </signal>
+
+ <group name="Appearance">
+ <!-- Emoticon config -->
+ <entry key="emoticonTheme" type="String">
+ <label>Current emoticon theme.</label>
+ <default>Default</default>
+ <emit signal="emoticonSettingsChanged" />
+ </entry>
+ <entry key="useEmoticon" type="Bool">
+ <label>Enable emoticon support in Kopete.</label>
+ <default>true</default>
+ <emit signal="emoticonSettingsChanged" />
+ </entry>
+ <entry key="emoticonRequireSpace" type="Bool">
+ <label>Use strict mode in emoticon parsing.</label>
+ <default>true</default>
+ <emit signal="emoticonSettingsChanged" />
+ </entry>
+
+ <!-- Chat Window Style preferences -->
+ <entry key="stylePath" type="String">
+ <label>Absolute path to a directory containing a Adium/Kopete chat window style.</label>
+ <emit signal="styleChanged" />
+ </entry>
+
+ <entry key="styleVariant" type="String" name="StyleCSSVariant">
+ <label>Relative path to a CSS variant for the current style.</label>
+ </entry>
+ </group>
+</kcfg>
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test_signal.kcfgc b/tier1/kconfig/autotests/kconfig_compiler/test_signal.kcfgc
new file mode 100644
index 00000000..b2a2fc06
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test_signal.kcfgc
@@ -0,0 +1,7 @@
+File=test_signal.kcfg
+ClassName=TestSignal
+Singleton=true
+Mutators=true
+MemberVariables=private
+GlobalEnums=false
+ItemAccessors=false
diff --git a/tier1/kconfig/autotests/kconfig_compiler/test_signal_main.cpp b/tier1/kconfig/autotests/kconfig_compiler/test_signal_main.cpp
new file mode 100644
index 00000000..3189e79a
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfig_compiler/test_signal_main.cpp
@@ -0,0 +1,32 @@
+/*
+Copyright (c) 2006 Michael Larouche <michael.larouche@kdemail.net>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "test_signal.h"
+#include <QGuiApplication>
+
+int main( int argc, char **argv )
+{
+ QGuiApplication app(argc, argv);
+ Q_UNUSED(app);
+ TestSignal *t = TestSignal::self();
+ delete t;
+ return 0;
+}
diff --git a/tier1/kconfig/autotests/kconfigguitest.cpp b/tier1/kconfig/autotests/kconfigguitest.cpp
new file mode 100644
index 00000000..225f1719
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfigguitest.cpp
@@ -0,0 +1,145 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1997 Matthias Kalle Dalheimer (kalle@kde.org)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <QtTest/QtTestGui>
+#include "kconfigguitest.h"
+
+#include <kconfig.h>
+#include <QDir>
+#include <QFont>
+#include <kconfiggroup.h>
+#include <kconfigskeleton.h>
+
+QTEST_MAIN( KConfigTest )
+
+#define COLORENTRY1 QColor("steelblue")
+#define COLORENTRY2 QColor(235, 235, 100, 125)
+#define COLORENTRY3 QColor(234, 234, 127)
+#define FONTENTRY QFont("Times", 16, QFont::Normal)
+
+void KConfigTest::initTestCase()
+{
+ // cheat the linker on windows to link against kconfiggui
+ KConfigSkeleton foo;
+ Q_UNUSED(foo);
+
+ KConfig sc( "kconfigtest" );
+
+ KConfigGroup cg(&sc, "ComplexTypes");
+ cg.writeEntry( "colorEntry1", COLORENTRY1 );
+ cg.writeEntry( "colorEntry2", COLORENTRY2 );
+ cg.writeEntry( "colorEntry3", (QList<int>() << 234 << 234 << 127));
+ cg.writeEntry( "colorEntry4", (QList<int>() << 235 << 235 << 100 << 125));
+ cg.writeEntry( "fontEntry", FONTENTRY );
+ QVERIFY(sc.sync());
+
+ KConfig sc1("kdebugrc");
+ KConfigGroup sg0(&sc1, "0");
+ sg0.writeEntry("AbortFatal", false);
+ sg0.writeEntry("WarnOutput", 0);
+ sg0.writeEntry("FatalOutput", 0);
+ QVERIFY(sc1.sync());
+}
+
+void KConfigTest::cleanupTestCase()
+{
+ QDir local(QDir::homePath() + "/.kde-unit-test/share/config");
+
+ Q_FOREACH(const QString &file, local.entryList(QDir::Files))
+ if(!local.remove(file))
+ qWarning("%s: removing failed", qPrintable( file ));
+
+ QCOMPARE((int)local.entryList(QDir::Files).count(), 0);
+
+ local.cdUp();
+ local.rmpath("config");
+}
+
+void KConfigTest::testComplex()
+{
+ KConfig sc2( "kconfigtest" );
+ KConfigGroup sc3(&sc2, "ComplexTypes");
+
+ QCOMPARE( QVariant(sc3.readEntry( "colorEntry1", QColor(Qt::black) )).toString(),
+ QVariant(COLORENTRY1).toString() );
+ QCOMPARE( sc3.readEntry( "colorEntry1", QColor() ), COLORENTRY1 );
+ QCOMPARE( sc3.readEntry( "colorEntry2", QColor() ), COLORENTRY2 );
+ QCOMPARE( sc3.readEntry( "colorEntry3", QColor() ), COLORENTRY3 );
+ QCOMPARE( sc3.readEntry( "colorEntry4", QColor() ), COLORENTRY2 );
+ QCOMPARE( sc3.readEntry( "defaultColorTest", QColor("black") ), QColor("black") );
+ QCOMPARE( sc3.readEntry( "fontEntry", QFont() ), FONTENTRY );
+}
+
+void KConfigTest::testInvalid()
+{
+ KConfig sc( "kconfigtest" );
+
+ // all of these should print a message to the kdebug.dbg file
+ KConfigGroup sc3(&sc, "InvalidTypes" );
+
+ QList<int> list;
+
+ // 1 element list
+ list << 1;
+ sc3.writeEntry( QString("badList"), list);
+ QVERIFY(sc.sync());
+
+ QVERIFY( sc3.readEntry( "badList", QColor() ) == QColor() );
+
+ // 2 element list
+ list << 2;
+ sc3.writeEntry( "badList", list);
+ QVERIFY(sc.sync());
+
+ QVERIFY( sc3.readEntry( "badList", QColor() ) == QColor() );
+
+ // 3 element list
+ list << 303;
+ sc3.writeEntry( "badList", list);
+ QVERIFY(sc.sync());
+
+ QVERIFY( sc3.readEntry( "badList", QColor() ) == QColor() ); // out of bounds
+
+ // 4 element list
+ list << 4;
+ sc3.writeEntry( "badList", list );
+ QVERIFY(sc.sync());
+
+ QVERIFY( sc3.readEntry( "badList", QColor() ) == QColor() ); // out of bounds
+
+ list[2] = -3;
+ sc3.writeEntry( "badList", list );
+ QVERIFY(sc.sync());
+ QVERIFY( sc3.readEntry( "badList", QColor() ) == QColor() ); // out of bounds
+
+ // 5 element list
+ list[2] = 3;
+ list << 5;
+ sc3.writeEntry( "badList", list);
+ QVERIFY(sc.sync());
+
+ QVERIFY( sc3.readEntry( "badList", QColor() ) == QColor() );
+
+ // 6 element list
+ list << 6;
+ sc3.writeEntry( "badList", list);
+ QVERIFY(sc.sync());
+
+ QVERIFY( sc3.readEntry( "badList", QColor() ) == QColor() );
+}
diff --git a/tier1/kconfig/autotests/kconfigguitest.h b/tier1/kconfig/autotests/kconfigguitest.h
new file mode 100644
index 00000000..2ac7261d
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfigguitest.h
@@ -0,0 +1,35 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1997 Matthias Kalle Dalheimer (kalle@kde.org)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#ifndef KCONFIGTEST_H
+#define KCONFIGTEST_H
+
+#include <QtCore/QObject>
+
+class KConfigTest : public QObject
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+ void testComplex();
+ void testInvalid();
+ void initTestCase();
+ void cleanupTestCase();
+};
+
+#endif /* KCONFIGTEST_H */
diff --git a/tier1/kconfig/autotests/kconfigloadertest.cpp b/tier1/kconfig/autotests/kconfigloadertest.cpp
new file mode 100644
index 00000000..a4403da9
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfigloadertest.cpp
@@ -0,0 +1,208 @@
+/********************************************************************************
+* Copyright 2010 by Martin Blumenstingl <darklight.xdarklight@googlemail.com> *
+* *
+* This library is free software; you can redistribute it and/or *
+* modify it under the terms of the GNU Library General Public *
+* License as published by the Free Software Foundation; either *
+* version 2 of the License, or (at your option) any later version. *
+* *
+* This library is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
+* Library General Public License for more details. *
+* *
+* You should have received a copy of the GNU Library General Public License *
+* along with this library; see the file COPYING.LIB. If not, write to *
+* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, *
+* Boston, MA 02110-1301, USA. *
+*********************************************************************************/
+#include "kconfigloadertest.h"
+
+#include <kconfig.h>
+#include <kconfiggroup.h>
+#include <kconfigskeleton.h>
+#include <kconfigloader.h>
+
+Q_DECLARE_METATYPE(QList<int>)
+
+#define TEST_NAME QString::fromLatin1("kconfigloadertest")
+
+#define GET_CONFIG_ITEM_VALUE(type, configName) \
+ KConfigSkeletonItem* item = cl->findItem(TEST_NAME, configName); \
+ /* Check if we got back a valid item. */ \
+ QVERIFY(item != 0); \
+ /* Cast the item to the given type. */ \
+ type typeItem = dynamic_cast<type>(item); \
+ /* Make sure the cast was successful. */ \
+ QVERIFY(typeItem != 0);
+
+void ConfigLoaderTest::init()
+{
+ QString fileName = TEST_NAME + QString::fromLatin1(".xml");
+ configFile = new QFile(QFINDTESTDATA(QString::fromLatin1("/") + fileName));
+ cl = new KConfigLoader(configFile->fileName(), configFile);
+}
+
+void ConfigLoaderTest::cleanup()
+{
+ delete cl;
+ delete configFile;
+}
+
+void ConfigLoaderTest::boolDefaultValue()
+{
+ GET_CONFIG_ITEM_VALUE(KCoreConfigSkeleton::ItemBool*, "DefaultBoolItem");
+
+ QVERIFY(typeItem->isEqual(true));
+}
+
+void ConfigLoaderTest::colorDefaultValue()
+{
+ GET_CONFIG_ITEM_VALUE(KConfigSkeleton::ItemColor*, "DefaultColorItem");
+
+ QVERIFY(typeItem->isEqual(QColor("#00FF00")));
+}
+
+void ConfigLoaderTest::dateTimeDefaultValue()
+{
+ GET_CONFIG_ITEM_VALUE(KCoreConfigSkeleton::ItemDateTime*, "DefaultDateTimeItem");
+
+ QVERIFY(typeItem->isEqual(QDateTime::fromString("Thu Sep 09 2010")));
+}
+
+void ConfigLoaderTest::enumDefaultValue()
+{
+ GET_CONFIG_ITEM_VALUE(KConfigSkeleton::ItemEnum*, "DefaultEnumItem");
+
+ QVERIFY(typeItem->isEqual(3));
+}
+
+void ConfigLoaderTest::fontDefaultValue()
+{
+ GET_CONFIG_ITEM_VALUE(KConfigSkeleton::ItemFont*, "DefaultFontItem");
+
+ QVERIFY(typeItem->isEqual(QFont("DejaVu Sans")));
+}
+
+void ConfigLoaderTest::intDefaultValue()
+{
+ GET_CONFIG_ITEM_VALUE(KCoreConfigSkeleton::ItemInt*, "DefaultIntItem");
+
+ QVERIFY(typeItem->isEqual(27));
+}
+
+void ConfigLoaderTest::passwordDefaultValue()
+{
+ GET_CONFIG_ITEM_VALUE(KConfigSkeleton::ItemPassword*, "DefaultPasswordItem");
+
+ QVERIFY(typeItem->isEqual(QString::fromLatin1("h4x.")));
+}
+
+void ConfigLoaderTest::pathDefaultValue()
+{
+ GET_CONFIG_ITEM_VALUE(KConfigSkeleton::ItemPath*, "DefaultPathItem");
+
+ QVERIFY(typeItem->isEqual(QString::fromLatin1("/dev/null")));
+}
+
+void ConfigLoaderTest::stringDefaultValue()
+{
+ GET_CONFIG_ITEM_VALUE(KConfigSkeleton::ItemString*, "DefaultStringItem");
+
+ QVERIFY(typeItem->isEqual(QString::fromLatin1("TestString")));
+}
+
+void ConfigLoaderTest::stringListDefaultValue()
+{
+ GET_CONFIG_ITEM_VALUE(KConfigSkeleton::ItemStringList*, "DefaultStringListItem");
+
+ // Create a string list with the expected values.
+ QStringList expected;
+ expected.append("One");
+ expected.append("Two");
+ expected.append("Three");
+ expected.append("Four");
+ expected.append("Five");
+
+ QVERIFY(typeItem->isEqual(expected));
+}
+
+void ConfigLoaderTest::uintDefaultValue()
+{
+ GET_CONFIG_ITEM_VALUE(KCoreConfigSkeleton::ItemUInt*, "DefaultUIntItem");
+
+ QVERIFY(typeItem->isEqual(7U));
+}
+
+void ConfigLoaderTest::urlDefaultValue()
+{
+ GET_CONFIG_ITEM_VALUE(KCoreConfigSkeleton::ItemUrl*, "DefaultUrlItem");
+
+ QVERIFY(typeItem->isEqual(QUrl("http://kde.org")));
+}
+
+void ConfigLoaderTest::doubleDefaultValue()
+{
+ GET_CONFIG_ITEM_VALUE(KCoreConfigSkeleton::ItemDouble*, "DefaultDoubleItem");
+
+ QVERIFY(typeItem->isEqual(13.37));
+}
+
+void ConfigLoaderTest::intListDefaultValue()
+{
+ GET_CONFIG_ITEM_VALUE(KCoreConfigSkeleton::ItemIntList*, "DefaultIntListItem");
+
+ // Create a int list with the expected values.
+ QList<int> expected;
+ expected.append(1);
+ expected.append(1);
+ expected.append(2);
+ expected.append(3);
+ expected.append(5);
+ expected.append(8);
+
+ QVERIFY(typeItem->isEqual(qVariantFromValue(expected)));
+}
+
+void ConfigLoaderTest::longLongDefaultValue()
+{
+ GET_CONFIG_ITEM_VALUE(KCoreConfigSkeleton::ItemLongLong*, "DefaultLongLongItem");
+
+ QVERIFY(typeItem->isEqual(Q_INT64_C(-9211372036854775808)));
+}
+
+void ConfigLoaderTest::pointDefaultValue()
+{
+ GET_CONFIG_ITEM_VALUE(KCoreConfigSkeleton::ItemPoint*, "DefaultPointItem");
+
+ QVERIFY(typeItem->isEqual(QPoint(185, 857)));
+}
+
+void ConfigLoaderTest::rectDefaultValue()
+{
+ GET_CONFIG_ITEM_VALUE(KCoreConfigSkeleton::ItemRect*, "DefaultRectItem");
+
+ // Create a new QRect with the expected value.
+ QRect expected;
+ expected.setCoords(3, 7, 951, 358);
+
+ QVERIFY(typeItem->isEqual(expected));
+}
+
+void ConfigLoaderTest::sizeDefaultValue()
+{
+ GET_CONFIG_ITEM_VALUE(KCoreConfigSkeleton::ItemSize*, "DefaultSizeItem");
+
+ QVERIFY(typeItem->isEqual(QSize(640, 480)));
+}
+
+void ConfigLoaderTest::ulongLongDefaultValue()
+{
+ GET_CONFIG_ITEM_VALUE(KCoreConfigSkeleton::ItemULongLong*, "DefaultULongLongItem");
+
+ QVERIFY(typeItem->isEqual(Q_UINT64_C(9223372036854775806)));
+}
+
+
+QTEST_MAIN(ConfigLoaderTest)
+
diff --git a/tier1/kconfig/autotests/kconfigloadertest.h b/tier1/kconfig/autotests/kconfigloadertest.h
new file mode 100644
index 00000000..be8c7629
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfigloadertest.h
@@ -0,0 +1,63 @@
+/********************************************************************************
+* Copyright 2010 by Martin Blumenstingl <darklight.xdarklight@googlemail.com> *
+* *
+* This library is free software; you can redistribute it and/or *
+* modify it under the terms of the GNU Library General Public *
+* License as published by the Free Software Foundation; either *
+* version 2 of the License, or (at your option) any later version. *
+* *
+* This library is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
+* Library General Public License for more details. *
+* *
+* You should have received a copy of the GNU Library General Public License *
+* along with this library; see the file COPYING.LIB. If not, write to *
+* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, *
+* Boston, MA 02110-1301, USA. *
+*********************************************************************************/
+
+#ifndef KCONFIGLOADERTEST_H
+#define KCONFIGLOADERTEST_H
+
+#include <QtTest/QtTest>
+
+class KConfigLoader;
+
+class QFile;
+
+class ConfigLoaderTest : public QObject
+{
+ Q_OBJECT
+
+public Q_SLOTS:
+ void init();
+ void cleanup();
+
+private Q_SLOTS:
+ void boolDefaultValue();
+ void colorDefaultValue();
+ void dateTimeDefaultValue();
+ void enumDefaultValue();
+ void fontDefaultValue();
+ void intDefaultValue();
+ void passwordDefaultValue();
+ void pathDefaultValue();
+ void stringDefaultValue();
+ void stringListDefaultValue();
+ void uintDefaultValue();
+ void urlDefaultValue();
+ void doubleDefaultValue();
+ void intListDefaultValue();
+ void longLongDefaultValue();
+ void pointDefaultValue();
+ void rectDefaultValue();
+ void sizeDefaultValue();
+ void ulongLongDefaultValue();
+
+private:
+ KConfigLoader* cl;
+ QFile* configFile;
+};
+
+#endif
diff --git a/tier1/kconfig/autotests/kconfigloadertest.xml b/tier1/kconfig/autotests/kconfigloadertest.xml
new file mode 100644
index 00000000..024880f4
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfigloadertest.xml
@@ -0,0 +1,71 @@
+<?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="keystatusplasmoidrc"/>
+
+ <group name="kconfigloadertest">
+ <entry name="DefaultBoolItem" type="Bool">
+ <default>true</default>
+ </entry>
+ <entry name="DefaultColorItem" type="Color">
+ <default>#00FF00</default>
+ </entry>
+ <entry name="DefaultDateTimeItem" type="DateTime">
+ <default>Thu Sep 09 2010</default>
+ </entry>
+ <entry name="DefaultEnumItem" type="Enum">
+ <default>3</default>
+ <choice name="One" value="1" />
+ <choice name="Two" value="2" />
+ <choice name="Three" value="3" />
+ <choice name="Four" value="4" />
+ </entry>
+ <entry name="DefaultFontItem" type="Font">
+ <default>DejaVu Sans</default>
+ </entry>
+ <entry name="DefaultIntItem" type="Int">
+ <default>27</default>
+ </entry>
+ <entry name="DefaultPasswordItem" type="Password">
+ <default>h4x.</default>
+ </entry>
+ <entry name="DefaultPathItem" type="Path">
+ <default>/dev/null</default>
+ </entry>
+ <entry name="DefaultStringItem" type="String">
+ <default>TestString</default>
+ </entry>
+ <entry name="DefaultStringListItem" type="StringList">
+ <default>One,Two,Three,Four,Five</default>
+ </entry>
+ <entry name="DefaultUIntItem" type="UInt">
+ <default>7</default>
+ </entry>
+ <entry name="DefaultUrlItem" type="Url">
+ <default>http://kde.org</default>
+ </entry>
+ <entry name="DefaultDoubleItem" type="Double">
+ <default>13.37</default>
+ </entry>
+ <entry name="DefaultIntListItem" type="IntList">
+ <default>1,1,2,3,5,8</default>
+ </entry>
+ <entry name="DefaultLongLongItem" type="LongLong">
+ <default>-9211372036854775808</default>
+ </entry>
+ <entry name="DefaultPointItem" type="Point">
+ <default>185,857</default>
+ </entry>
+ <entry name="DefaultRectItem" type="Rect">
+ <default>3,7,951,358</default>
+ </entry>
+ <entry name="DefaultSizeItem" type="Size">
+ <default>640,480</default>
+ </entry>
+ <entry name="DefaultULongLongItem" type="ULongLong">
+ <default>9223372036854775806</default>
+ </entry>
+ </group>
+</kcfg>
diff --git a/tier1/kconfig/autotests/kconfignokdehometest.cpp b/tier1/kconfig/autotests/kconfignokdehometest.cpp
new file mode 100644
index 00000000..0c7d8265
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfignokdehometest.cpp
@@ -0,0 +1,64 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2011 David Faure <faure@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <QObject>
+
+#include <QtTest/QtTest>
+#include <QStandardPaths>
+#include <ksharedconfig.h>
+
+#include <kconfig.h>
+#include <kconfiggroup.h>
+
+class KConfigNoKdeHomeTest : public QObject
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+ void testNoKdeHome();
+};
+
+
+void KConfigNoKdeHomeTest::testNoKdeHome()
+{
+ QStandardPaths::setTestModeEnabled(true);
+ QString configPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation);
+ QDir configDir(configPath);
+ configDir.removeRecursively();
+ QVERIFY(!QFile::exists(configPath));
+
+ // Do what kf5-config does, and ensure the config directory doesn't get created (#233892)
+ QVERIFY(!QFile::exists(configPath));
+ KSharedConfig::openConfig();
+ QVERIFY(!QFile::exists(configPath));
+
+ // Now try to actually save something, see if it works.
+ KConfigGroup group(KSharedConfig::openConfig(), "Group");
+ group.writeEntry("Key", "Value");
+ group.sync();
+ QVERIFY(QFile::exists(configPath));
+ QVERIFY(QFile::exists(configPath + QStringLiteral("/kconfignokdehometestrc")));
+
+ // Cleanup
+ configDir.removeRecursively();
+}
+
+QTEST_MAIN(KConfigNoKdeHomeTest)
+
+#include "kconfignokdehometest.moc"
diff --git a/tier1/kconfig/autotests/kconfigskeletontest.cpp b/tier1/kconfig/autotests/kconfigskeletontest.cpp
new file mode 100644
index 00000000..d3b30e84
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfigskeletontest.cpp
@@ -0,0 +1,111 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2006 Olivier Goffart <ogoffart at kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "kconfigskeletontest.h"
+
+#include <kconfig.h>
+#include <QFont>
+#include <QtTest/QtTestGui>
+
+
+QTEST_MAIN( KConfigSkeletonTest)
+
+
+#define DEFAULT_SETTING1 false
+#define DEFAULT_SETTING2 QColor(1,2,3)
+#define DEFAULT_SETTING3 QFont("helvetica",12)
+#define DEFAULT_SETTING4 QString("Hello World")
+
+#define WRITE_SETTING1 true
+#define WRITE_SETTING2 QColor(3,2,1)
+#define WRITE_SETTING3 QFont("helvetica",14)
+#define WRITE_SETTING4 QString("KDE")
+
+void KConfigSkeletonTest::initTestCase()
+{
+ setCurrentGroup("MyGroup");
+ addItemBool("MySetting1", mMyBool, DEFAULT_SETTING1);
+ addItemColor("MySetting2", mMyColor, DEFAULT_SETTING2);
+
+ setCurrentGroup("MyOtherGroup");
+ addItemFont("MySetting3", mMyFont, DEFAULT_SETTING3);
+ addItemString("MySetting4", mMyString, DEFAULT_SETTING4);
+
+ QCOMPARE(mMyBool, DEFAULT_SETTING1);
+ QCOMPARE(mMyColor, DEFAULT_SETTING2);
+ QCOMPARE(mMyFont, DEFAULT_SETTING3);
+ QCOMPARE(mMyString, DEFAULT_SETTING4);
+}
+
+void KConfigSkeletonTest::testSimple()
+{
+ mMyBool = WRITE_SETTING1;
+ mMyColor = WRITE_SETTING2;
+ mMyFont = WRITE_SETTING3;
+ mMyString = WRITE_SETTING4;
+
+ writeConfig ();
+
+ mMyBool = false;
+ mMyColor = QColor();
+ mMyString.clear();
+ mMyFont = QFont();
+
+ readConfig ();
+
+ QCOMPARE(mMyBool, WRITE_SETTING1);
+ QCOMPARE(mMyColor, WRITE_SETTING2);
+ QCOMPARE(mMyFont, WRITE_SETTING3);
+ QCOMPARE(mMyString, WRITE_SETTING4);
+
+}
+
+void KConfigSkeletonTest::testRemoveItem()
+{
+ QVERIFY(findItem("MySetting1"));
+ removeItem("MySetting1");
+ QVERIFY(!findItem("MySetting1"));
+}
+
+void KConfigSkeletonTest::testClear()
+{
+ QVERIFY(findItem("MySetting2"));
+ QVERIFY(findItem("MySetting3"));
+ QVERIFY(findItem("MySetting4"));
+
+ clearItems();
+
+ QVERIFY(!findItem("MySetting2"));
+ QVERIFY(!findItem("MySetting3"));
+ QVERIFY(!findItem("MySetting4"));
+}
+
+void KConfigSkeletonTest::testDefaults()
+{
+ setDefaults ();
+
+ QCOMPARE(mMyBool, DEFAULT_SETTING1);
+ QCOMPARE(mMyColor, DEFAULT_SETTING2);
+ QCOMPARE(mMyFont, DEFAULT_SETTING3);
+ QCOMPARE(mMyString, DEFAULT_SETTING4);
+
+ writeConfig();
+}
+
+
diff --git a/tier1/kconfig/autotests/kconfigskeletontest.h b/tier1/kconfig/autotests/kconfigskeletontest.h
new file mode 100644
index 00000000..f65739dc
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfigskeletontest.h
@@ -0,0 +1,44 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2006 Olivier Goffart <ogoffart at kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#ifndef KCONFIGSKELETONTEST_H
+#define KCONFIGSKELETONTEST_H
+
+#include <kconfigskeleton.h>
+
+class KConfigSkeletonTest : public KConfigSkeleton
+{
+ Q_OBJECT
+ public:
+
+private Q_SLOTS:
+ void initTestCase();
+ void testSimple();
+ void testDefaults();
+ void testRemoveItem();
+ void testClear();
+
+private:
+ bool mMyBool;
+ QColor mMyColor;
+ QFont mMyFont;
+ QString mMyString;
+
+};
+
+#endif
diff --git a/tier1/kconfig/autotests/kconfigtest.cpp b/tier1/kconfig/autotests/kconfigtest.cpp
new file mode 100644
index 00000000..1aed5151
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfigtest.cpp
@@ -0,0 +1,1634 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1997 Matthias Kalle Dalheimer (kalle@kde.org)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+// Qt5 TODO: re-enable. No point in doing it before, it breaks on QString::fromUtf8(QByteArray), which exists in qt5.
+#undef QT_NO_CAST_FROM_BYTEARRAY
+
+#include "kconfigtest.h"
+
+#include <QtTest/QtTest>
+#include <qtemporarydir.h>
+#include <QStandardPaths>
+#include <kdesktopfile.h>
+
+#include <ksharedconfig.h>
+#include <kconfiggroup.h>
+
+#ifdef Q_OS_UNIX
+#include <utime.h>
+#endif
+#ifndef Q_OS_WIN
+#include <unistd.h> // gethostname
+#endif
+
+KCONFIGGROUP_DECLARE_ENUM_QOBJECT(KConfigTest,Testing)
+KCONFIGGROUP_DECLARE_FLAGS_QOBJECT(KConfigTest,Flags)
+
+QTEST_MAIN( KConfigTest )
+
+#define BOOLENTRY1 true
+#define BOOLENTRY2 false
+#define STRINGENTRY1 "hello"
+#define STRINGENTRY2 " hello"
+#define STRINGENTRY3 "hello "
+#define STRINGENTRY4 " hello "
+#define STRINGENTRY5 " "
+#define STRINGENTRY6 ""
+#define UTF8BITENTRY "Hello äöü"
+#define TRANSLATEDSTRINGENTRY1 "bonjour"
+#define BYTEARRAYENTRY QByteArray( "\x00\xff\x7f\x3c abc\x00\x00", 10 )
+#define ESCAPEKEY " []\0017[]==]"
+#define ESCAPEENTRY "[]\170[]]=3=]\\] "
+#define DOUBLEENTRY 123456.78912345
+#define FLOATENTRY 123.567f
+#define POINTENTRY QPoint( 4351, 1235 )
+#define SIZEENTRY QSize( 10, 20 )
+#define RECTENTRY QRect( 10, 23, 5321, 13 )
+#define DATETIMEENTRY QDateTime( QDate( 2002, 06, 23 ), QTime( 12, 55, 40 ) )
+#define STRINGLISTENTRY (QStringList( "Hello," ) << " World")
+#define STRINGLISTEMPTYENTRY QStringList()
+#define STRINGLISTJUSTEMPTYELEMENT QStringList(QString())
+#define STRINGLISTEMPTYTRAINLINGELEMENT (QStringList( "Hi" ) << QString())
+#define STRINGLISTESCAPEODDENTRY (QStringList( "Hello\\\\\\" ) << "World")
+#define STRINGLISTESCAPEEVENENTRY (QStringList( "Hello\\\\\\\\" ) << "World")
+#define STRINGLISTESCAPECOMMAENTRY (QStringList( "Hel\\\\\\,\\\\,\\,\\\\\\\\,lo" ) << "World")
+#define INTLISTENTRY1 QList<int>() << 1 << 2 << 3 << 4
+#define BYTEARRAYLISTENTRY1 QList<QByteArray>() << "" << "1,2" << "end"
+#define VARIANTLISTENTRY (QVariantList() << true << false << QString("joe") << 10023)
+#define VARIANTLISTENTRY2 (QVariantList() << POINTENTRY << SIZEENTRY)
+#define HOMEPATH QString(QDir::homePath()+"/foo")
+#define HOMEPATHESCAPE QString(QDir::homePath()+"/foo/$HOME")
+#define DOLLARGROUP "$i"
+
+void KConfigTest::initTestCase()
+{
+ // ensure we don't use files in the real config directory
+ QStandardPaths::setTestModeEnabled(true);
+ QString testConfigDir = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation);
+
+ // to make sure all files from a previous failed run are deleted
+ cleanupTestCase();
+
+
+ KConfig sc( "kconfigtest" );
+
+ KConfigGroup cg(&sc, "AAA");
+ cg.writeEntry("stringEntry1", STRINGENTRY1,
+ KConfig::Persistent|KConfig::Global);
+ cg.deleteEntry("stringEntry2", KConfig::Global);
+
+ cg = KConfigGroup(&sc, "Hello");
+ cg.writeEntry( "boolEntry1", BOOLENTRY1 );
+ cg.writeEntry( "boolEntry2", BOOLENTRY2 );
+
+ QByteArray data( UTF8BITENTRY );
+ QCOMPARE( data.size(), 12 ); // the source file is in utf8
+ QCOMPARE( QString::fromUtf8(data).length(), 9 );
+ cg.writeEntry ("Test", data);
+ cg.writeEntry( "bytearrayEntry", BYTEARRAYENTRY );
+ cg.writeEntry( ESCAPEKEY, ESCAPEENTRY );
+ cg.writeEntry( "emptyEntry", "");
+ cg.writeEntry( "stringEntry1", STRINGENTRY1 );
+ cg.writeEntry( "stringEntry2", STRINGENTRY2 );
+ cg.writeEntry( "stringEntry3", STRINGENTRY3 );
+ cg.writeEntry( "stringEntry4", STRINGENTRY4 );
+ cg.writeEntry( "stringEntry5", STRINGENTRY5 );
+ cg.writeEntry( "urlEntry1", QUrl("http://qt-project.org") );
+ cg.writeEntry( "keywith=equalsign", STRINGENTRY1 );
+ cg.deleteEntry( "stringEntry5" );
+ cg.deleteEntry( "stringEntry6" ); // deleting a nonexistent entry
+ cg.writeEntry( "byteArrayEntry1", QByteArray( STRINGENTRY1 ),
+ KConfig::Global|KConfig::Persistent );
+ cg.writeEntry( "doubleEntry1", DOUBLEENTRY );
+ cg.writeEntry( "floatEntry1", FLOATENTRY );
+
+ sc.deleteGroup("deleteMe"); // deleting a nonexistent group
+
+ cg = KConfigGroup(&sc, "Complex Types");
+ cg.writeEntry( "rectEntry", RECTENTRY );
+ cg.writeEntry( "pointEntry", POINTENTRY );
+ cg.writeEntry( "sizeEntry", SIZEENTRY );
+ cg.writeEntry( "dateTimeEntry", DATETIMEENTRY );
+ cg.writeEntry( "dateEntry", DATETIMEENTRY.date() );
+
+ KConfigGroup ct = cg;
+ cg = KConfigGroup(&ct, "Nested Group 1");
+ cg.writeEntry("stringentry1", STRINGENTRY1);
+
+ cg = KConfigGroup(&ct, "Nested Group 2");
+ cg.writeEntry( "stringEntry2", STRINGENTRY2 );
+
+ cg = KConfigGroup(&cg, "Nested Group 2.1");
+ cg.writeEntry( "stringEntry3", STRINGENTRY3 );
+
+ cg = KConfigGroup(&ct, "Nested Group 3");
+ cg.writeEntry( "stringEntry3", STRINGENTRY3 );
+
+ cg = KConfigGroup(&sc, "List Types" );
+ cg.writeEntry( "listOfIntsEntry1", INTLISTENTRY1 );
+ cg.writeEntry( "listOfByteArraysEntry1", BYTEARRAYLISTENTRY1 );
+ cg.writeEntry( "stringListEntry", STRINGLISTENTRY );
+ cg.writeEntry( "stringListEmptyEntry", STRINGLISTEMPTYENTRY );
+ cg.writeEntry( "stringListJustEmptyElement", STRINGLISTJUSTEMPTYELEMENT );
+ cg.writeEntry( "stringListEmptyTrailingElement", STRINGLISTEMPTYTRAINLINGELEMENT );
+ cg.writeEntry( "stringListEscapeOddEntry", STRINGLISTESCAPEODDENTRY );
+ cg.writeEntry( "stringListEscapeEvenEntry", STRINGLISTESCAPEEVENENTRY );
+ cg.writeEntry( "stringListEscapeCommaEntry", STRINGLISTESCAPECOMMAENTRY );
+ cg.writeEntry( "variantListEntry", VARIANTLISTENTRY );
+
+ cg = KConfigGroup(&sc, "Path Type" );
+ cg.writePathEntry( "homepath", HOMEPATH );
+ cg.writePathEntry( "homepathescape", HOMEPATHESCAPE );
+
+ cg = KConfigGroup(&sc, "Enum Types" );
+ writeEntry( cg, "enum-10", Tens );
+ writeEntry( cg, "enum-100", Hundreds );
+ writeEntry( cg, "flags-bit0", Flags(bit0));
+ writeEntry( cg, "flags-bit0-bit1", Flags(bit0|bit1) );
+
+ cg = KConfigGroup(&sc, "ParentGroup" );
+ KConfigGroup cg1(&cg, "SubGroup1" );
+ cg1.writeEntry( "somestring", "somevalue" );
+ cg.writeEntry( "parentgrpstring", "somevalue" );
+ KConfigGroup cg2(&cg, "SubGroup2" );
+ cg2.writeEntry( "substring", "somevalue" );
+ KConfigGroup cg3(&cg, "SubGroup/3");
+ cg3.writeEntry( "sub3string", "somevalue" );
+
+ QVERIFY(sc.isDirty());
+ QVERIFY(sc.sync());
+ QVERIFY(!sc.isDirty());
+
+ QVERIFY2(QFile::exists(testConfigDir + QStringLiteral("/kconfigtest")),
+ qPrintable(testConfigDir + QStringLiteral("/kconfigtest must exist")));
+ QVERIFY2(QFile::exists(testConfigDir + QStringLiteral("/kdeglobals")),
+ qPrintable(testConfigDir + QStringLiteral("/kdeglobals must exist")));
+
+
+ KConfig sc1("kdebugrc", KConfig::SimpleConfig);
+ KConfigGroup sg0(&sc1, "0");
+ sg0.writeEntry("AbortFatal", false);
+ sg0.writeEntry("WarnOutput", 0);
+ sg0.writeEntry("FatalOutput", 0);
+ QVERIFY(sc1.sync());
+
+ //Setup stuff to test KConfig::addConfigSources()
+ KConfig devcfg("specificrc");
+ KConfigGroup devonlygrp(&devcfg, "Specific Only Group");
+ devonlygrp.writeEntry("ExistingEntry", "DevValue");
+ KConfigGroup devandbasegrp(&devcfg, "Shared Group");
+ devandbasegrp.writeEntry("SomeSharedEntry", "DevValue");
+ devandbasegrp.writeEntry("SomeSpecificOnlyEntry", "DevValue");
+ QVERIFY(devcfg.sync());
+ KConfig basecfg("baserc");
+ KConfigGroup basegrp(&basecfg, "Base Only Group");
+ basegrp.writeEntry("ExistingEntry", "BaseValue");
+ KConfigGroup baseanddevgrp(&basecfg, "Shared Group");
+ baseanddevgrp.writeEntry("SomeSharedEntry", "BaseValue");
+ baseanddevgrp.writeEntry("SomeBaseOnlyEntry", "BaseValue");
+ QVERIFY(basecfg.sync());
+
+ KConfig gecfg("groupescapetest", KConfig::SimpleConfig);
+ cg = KConfigGroup(&gecfg, DOLLARGROUP);
+ cg.writeEntry( "entry", "doesntmatter" );
+
+}
+
+void KConfigTest::cleanupTestCase()
+{
+ //ensure we don't delete the real directory
+ QStandardPaths::setTestModeEnabled(true);
+ QDir localConfig(QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation));
+ //qDebug() << "Erasing" << localConfig;
+ localConfig.removeRecursively();
+ QVERIFY(!localConfig.exists());
+}
+
+
+static QList<QByteArray> readLinesFrom(const QString& path)
+{
+ QFile file(path);
+ const bool opened = file.open(QIODevice::ReadOnly|QIODevice::Text);
+ Q_ASSERT(opened);
+ Q_UNUSED(opened);
+ QList<QByteArray> lines;
+ QByteArray line;
+ do {
+ line = file.readLine();
+ if (!line.isEmpty())
+ lines.append(line);
+ } while(!line.isEmpty());
+ return lines;
+}
+
+static QList<QByteArray> readLines(const char* fileName = "kconfigtest")
+{
+ const QString path = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + '/' + fileName;
+ Q_ASSERT(!path.isEmpty());
+ return readLinesFrom(path);
+}
+
+// see also testDefaults, which tests reverting with a defaults (global) file available
+void KConfigTest::testDirtyAfterRevert()
+{
+ KConfig sc( "kconfigtest_revert" );
+
+ KConfigGroup cg(&sc, "Hello");
+ cg.revertToDefault( "does_not_exist" );
+ QVERIFY(!sc.isDirty());
+ cg.writeEntry("Test", "Correct");
+ QVERIFY(sc.isDirty());
+ sc.sync();
+ QVERIFY(!sc.isDirty());
+
+ cg.revertToDefault("Test");
+ QVERIFY(sc.isDirty());
+ QVERIFY(sc.sync());
+ QVERIFY(!sc.isDirty());
+
+ cg.revertToDefault("Test");
+ QVERIFY(!sc.isDirty());
+}
+
+void KConfigTest::testRevertAllEntries()
+{
+ // this tests the case were we revert (delete) all entries in a file,
+ // leaving a blank file
+ {
+ KConfig sc( "konfigtest2", KConfig::SimpleConfig );
+ KConfigGroup cg( &sc, "Hello" );
+ cg.writeEntry( "Test", "Correct" );
+ }
+
+ {
+ KConfig sc( "konfigtest2", KConfig::SimpleConfig );
+ KConfigGroup cg( &sc, "Hello" );
+ QCOMPARE( cg.readEntry( "Test", "Default" ), QString("Correct") );
+ cg.revertToDefault( "Test" );
+ }
+
+ KConfig sc( "konfigtest2", KConfig::SimpleConfig );
+ KConfigGroup cg( &sc, "Hello" );
+ QCOMPARE( cg.readEntry( "Test", "Default" ), QString("Default") );
+}
+
+void KConfigTest::testSimple()
+{
+ // kdeglobals (which was created in initTestCase) must be found this way:
+ const QStringList kdeglobals = QStandardPaths::locateAll(QStandardPaths::GenericConfigLocation, QLatin1String("kdeglobals"));
+ QVERIFY(!kdeglobals.isEmpty());
+
+ KConfig sc2( "kconfigtest" );
+ QCOMPARE(sc2.name(), QString("kconfigtest"));
+
+ // make sure groupList() isn't returning something it shouldn't
+ Q_FOREACH(const QString& group, sc2.groupList()) {
+ QVERIFY(!group.isEmpty() && group != "<default>");
+ QVERIFY(!group.contains(QChar(0x1d)));
+ }
+
+ KConfigGroup sc3( &sc2, "AAA");
+
+ QVERIFY( sc3.hasKey( "stringEntry1" ) ); // from kdeglobals
+ QVERIFY( !sc3.isEntryImmutable("stringEntry1") );
+ QCOMPARE( sc3.readEntry( "stringEntry1" ), QString( STRINGENTRY1 ) );
+
+ QVERIFY( !sc3.hasKey( "stringEntry2" ) );
+ QCOMPARE( sc3.readEntry( "stringEntry2", QString("bla") ), QString( "bla" ) );
+
+ QVERIFY( !sc3.hasDefault( "stringEntry1" ) );
+
+ sc3 = KConfigGroup(&sc2, "Hello");
+ QCOMPARE( sc3.readEntry( "Test", QByteArray() ), QByteArray( UTF8BITENTRY ) );
+ QCOMPARE( sc3.readEntry( "bytearrayEntry", QByteArray() ), BYTEARRAYENTRY );
+ QCOMPARE( sc3.readEntry( ESCAPEKEY ), QString( ESCAPEENTRY ) );
+ QCOMPARE( sc3.readEntry( "Test", QString() ), QString::fromUtf8( UTF8BITENTRY ) );
+ QCOMPARE( sc3.readEntry( "emptyEntry"/*, QString("Fietsbel")*/), QString("") );
+ QCOMPARE( sc3.readEntry("emptyEntry", QString("Fietsbel")).isEmpty(), true );
+ QCOMPARE( sc3.readEntry( "stringEntry1" ), QString( STRINGENTRY1 ) );
+ QCOMPARE( sc3.readEntry( "stringEntry2" ), QString( STRINGENTRY2 ) );
+ QCOMPARE( sc3.readEntry( "stringEntry3" ), QString( STRINGENTRY3 ) );
+ QCOMPARE( sc3.readEntry( "stringEntry4" ), QString( STRINGENTRY4 ) );
+ QVERIFY( !sc3.hasKey( "stringEntry5" ) );
+ QCOMPARE( sc3.readEntry( "stringEntry5", QString("test") ), QString( "test" ) );
+ QVERIFY( !sc3.hasKey( "stringEntry6" ) );
+ QCOMPARE( sc3.readEntry( "stringEntry6", QString("foo") ), QString( "foo" ) );
+ QCOMPARE( sc3.readEntry( "urlEntry1", QUrl() ), QUrl("http://qt-project.org") );
+ QCOMPARE( sc3.readEntry( "boolEntry1", BOOLENTRY1 ), BOOLENTRY1 );
+ QCOMPARE( sc3.readEntry( "boolEntry2", false ), BOOLENTRY2 );
+ QCOMPARE( sc3.readEntry("keywith=equalsign", QString("wrong")), QString(STRINGENTRY1));
+ QCOMPARE( sc3.readEntry( "byteArrayEntry1", QByteArray() ),
+ QByteArray( STRINGENTRY1 ) );
+ QCOMPARE( sc3.readEntry( "doubleEntry1", 0.0 ), DOUBLEENTRY );
+ QCOMPARE( sc3.readEntry( "floatEntry1", 0.0f ), FLOATENTRY );
+}
+
+void KConfigTest::testDefaults()
+{
+ KConfig config("defaulttest", KConfig::NoGlobals);
+ const QString defaultsFile = "defaulttest.defaults";
+ KConfig defaults(defaultsFile, KConfig::SimpleConfig);
+
+ const QString Default("Default");
+ const QString NotDefault("Not Default");
+ const QString Value1(STRINGENTRY1);
+ const QString Value2(STRINGENTRY2);
+
+ KConfigGroup group = defaults.group("any group");
+ group.writeEntry("entry1", Default);
+ QVERIFY(group.sync());
+
+ group = config.group("any group");
+ group.writeEntry("entry1", Value1);
+ group.writeEntry("entry2", Value2);
+ QVERIFY(group.sync());
+
+ config.addConfigSources(QStringList() << QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + '/' + defaultsFile);
+
+ config.setReadDefaults(true);
+ QCOMPARE(group.readEntry("entry1", QString()), Default);
+ QCOMPARE(group.readEntry("entry2", NotDefault), NotDefault); // no default for entry2
+
+ config.setReadDefaults(false);
+ QCOMPARE(group.readEntry("entry1", Default), Value1);
+ QCOMPARE(group.readEntry("entry2", NotDefault), Value2);
+
+ group.revertToDefault("entry1");
+ QCOMPARE(group.readEntry("entry1", QString()), Default);
+ group.revertToDefault("entry2");
+ QCOMPARE(group.readEntry("entry2", QString()), QString());
+
+ // TODO test reverting localized entries
+
+ Q_ASSERT(config.isDirty());
+ group.sync();
+
+ // Check that everything is OK on disk, too
+ KConfig reader("defaulttest", KConfig::NoGlobals);
+ reader.addConfigSources(QStringList() << QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + '/' + defaultsFile);
+ KConfigGroup readerGroup = reader.group("any group");
+ QCOMPARE(readerGroup.readEntry("entry1", QString()), Default);
+ QCOMPARE(readerGroup.readEntry("entry2", QString()), QString());
+}
+
+void KConfigTest::testLocale()
+{
+ KConfig config("kconfigtest.locales", KConfig::SimpleConfig);
+ const QString Translated(TRANSLATEDSTRINGENTRY1);
+ const QString Untranslated(STRINGENTRY1);
+
+ KConfigGroup group = config.group("Hello");
+ group.writeEntry("stringEntry1", Untranslated);
+ config.setLocale("fr");
+ group.writeEntry("stringEntry1", Translated, KConfig::Localized|KConfig::Persistent);
+ QVERIFY(config.sync());
+
+ QCOMPARE(group.readEntry("stringEntry1", QString()), Translated);
+ QCOMPARE(group.readEntryUntranslated("stringEntry1"), Untranslated);
+
+ config.setLocale("C"); // strings written in the "C" locale are written as nonlocalized
+ group.writeEntry("stringEntry1", Untranslated, KConfig::Localized|KConfig::Persistent);
+ QVERIFY(config.sync());
+
+ QCOMPARE(group.readEntry("stringEntry1", QString()), Untranslated);
+}
+
+void KConfigTest::testEncoding()
+{
+ QString groupstr = QString::fromUtf8("UTF-8:\xc3\xb6l");
+
+ KConfig c( "kconfigtestencodings" );
+ KConfigGroup cg(&c, groupstr);
+ cg.writeEntry("key", "value");
+ QVERIFY(c.sync());
+
+ QList<QByteArray> lines = readLines("kconfigtestencodings");
+ QCOMPARE(lines.count(), 2);
+ QCOMPARE(lines.first(), QByteArray("[UTF-8:\xc3\xb6l]\n"));
+
+ KConfig c2( "kconfigtestencodings" );
+ KConfigGroup cg2(&c2, groupstr);
+ QVERIFY(cg2.readEntry("key") == QByteArray("value"));
+
+ QVERIFY(c2.groupList().contains(groupstr));
+}
+
+void KConfigTest::testLists()
+{
+ KConfig sc2( "kconfigtest" );
+ KConfigGroup sc3(&sc2, "List Types");
+
+ QCOMPARE( sc3.readEntry( QString("stringListEntry"), QStringList()),
+ STRINGLISTENTRY );
+
+ QCOMPARE( sc3.readEntry( QString("stringListEmptyEntry"), QStringList("wrong") ),
+ STRINGLISTEMPTYENTRY );
+
+ QCOMPARE( sc3.readEntry( QString("stringListJustEmptyElement"), QStringList() ),
+ STRINGLISTJUSTEMPTYELEMENT );
+
+ QCOMPARE( sc3.readEntry( QString("stringListEmptyTrailingElement"), QStringList() ),
+ STRINGLISTEMPTYTRAINLINGELEMENT );
+
+ QCOMPARE( sc3.readEntry( QString("stringListEscapeOddEntry"), QStringList()),
+ STRINGLISTESCAPEODDENTRY );
+
+ QCOMPARE( sc3.readEntry( QString("stringListEscapeEvenEntry"), QStringList()),
+ STRINGLISTESCAPEEVENENTRY );
+
+ QCOMPARE( sc3.readEntry( QString("stringListEscapeCommaEntry"), QStringList()),
+ STRINGLISTESCAPECOMMAENTRY );
+
+ QCOMPARE( sc3.readEntry( "listOfIntsEntry1" ), QString::fromLatin1( "1,2,3,4" ) );
+ QList<int> expectedIntList = INTLISTENTRY1;
+ QVERIFY( sc3.readEntry( "listOfIntsEntry1", QList<int>() ) == expectedIntList );
+
+ QCOMPARE( QVariant(sc3.readEntry( "variantListEntry", VARIANTLISTENTRY )).toStringList(),
+ QVariant(VARIANTLISTENTRY).toStringList() );
+
+ QCOMPARE( sc3.readEntry( "listOfByteArraysEntry1", QList<QByteArray>()), BYTEARRAYLISTENTRY1 );
+}
+
+void KConfigTest::testPath()
+{
+ KConfig sc2( "kconfigtest" );
+ KConfigGroup sc3(&sc2, "Path Type");
+ QCOMPARE( sc3.readPathEntry( "homepath", QString() ), HOMEPATH );
+ QCOMPARE( sc3.readPathEntry( "homepathescape", QString() ), HOMEPATHESCAPE );
+ QCOMPARE( sc3.entryMap()["homepath"], HOMEPATH );
+
+ {
+ QFile file(QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + "/pathtest");
+ file.open(QIODevice::WriteOnly|QIODevice::Text);
+ QTextStream out(&file);
+ out.setCodec("UTF-8");
+ out << "[Test Group]" << endl
+ << "homePath=$HOME/foo" << endl
+ << "homePath2=file://$HOME/foo" << endl
+ << "withBraces[$e]=file://${HOME}/foo" << endl
+ << "URL[$e]=file://${HOME}/foo" << endl
+ << "hostname[$e]=$(hostname)" << endl
+ << "noeol=foo"; // no EOL
+ }
+ KConfig cf2("pathtest");
+ KConfigGroup group = cf2.group("Test Group");
+ QVERIFY(group.hasKey("homePath"));
+ QCOMPARE(group.readPathEntry("homePath", QString()), HOMEPATH);
+ QVERIFY(group.hasKey("homePath2"));
+ QCOMPARE(group.readPathEntry("homePath2", QString()), QString("file://" + HOMEPATH) );
+ QVERIFY(group.hasKey("withBraces"));
+ QCOMPARE(group.readPathEntry("withBraces", QString()), QString("file://" + HOMEPATH) );
+ QVERIFY(group.hasKey("URL"));
+ QCOMPARE(group.readEntry("URL", QString()), QString("file://" + HOMEPATH) );
+#if !defined(Q_OS_WIN32) && !defined(Q_OS_MAC)
+ // I don't know if this will work on windows
+ // This test hangs on OS X
+ QVERIFY(group.hasKey("hostname"));
+ char hostname[256];
+ QVERIFY(::gethostname(hostname, sizeof(hostname)) == 0);
+ QCOMPARE(group.readEntry("hostname", QString()), QString::fromLatin1(hostname));
+#endif
+ QVERIFY(group.hasKey("noeol"));
+ QCOMPARE(group.readEntry("noeol", QString()), QString("foo"));
+}
+
+void KConfigTest::testPersistenceOfExpandFlagForPath()
+{
+ // This test checks that a path entry starting with $HOME is still flagged
+ // with the expand flag after the config was altered without rewriting the
+ // path entry.
+
+ // 1st step: Open the config, add a new dummy entry and then sync the config
+ // back to the storage.
+ {
+ KConfig sc2( "kconfigtest" );
+ KConfigGroup sc3(&sc2, "Path Type");
+ sc3.writeEntry( "dummy", "dummy" );
+ QVERIFY(sc2.sync());
+ }
+
+ // 2nd step: Call testPath() again. Rewriting the config must not break
+ // the testPath() test.
+ testPath();
+}
+
+void KConfigTest::testComplex()
+{
+ KConfig sc2( "kconfigtest" );
+ KConfigGroup sc3(&sc2, "Complex Types");
+
+ QCOMPARE( sc3.readEntry( "pointEntry", QPoint() ), POINTENTRY );
+ QCOMPARE( sc3.readEntry( "sizeEntry", SIZEENTRY ), SIZEENTRY);
+ QCOMPARE( sc3.readEntry( "rectEntry", QRect(1,2,3,4) ), RECTENTRY );
+ QCOMPARE( sc3.readEntry( "dateTimeEntry", QDateTime() ).toString(Qt::ISODate),
+ DATETIMEENTRY.toString(Qt::ISODate) );
+ QCOMPARE( sc3.readEntry( "dateEntry", QDate() ).toString(Qt::ISODate),
+ DATETIMEENTRY.date().toString(Qt::ISODate) );
+ QCOMPARE( sc3.readEntry( "dateTimeEntry", QDate() ), DATETIMEENTRY.date() );
+}
+
+void KConfigTest::testEnums()
+{
+ KConfig sc("kconfigtest");
+ KConfigGroup sc3(&sc, "Enum Types" );
+
+ QCOMPARE( sc3.readEntry( "enum-10" ), QString("Tens"));
+ QVERIFY( readEntry( sc3, "enum-100", Ones) != Ones);
+ QVERIFY( readEntry( sc3, "enum-100", Ones) != Tens);
+
+ QCOMPARE( sc3.readEntry( "flags-bit0" ), QString("bit0"));
+ QVERIFY( readEntry( sc3, "flags-bit0", Flags() ) == bit0 );
+
+ int eid = staticMetaObject.indexOfEnumerator( "Flags" );
+ QVERIFY( eid != -1 );
+ QMetaEnum me = staticMetaObject.enumerator( eid );
+ Flags bitfield = bit0|bit1;
+
+ QCOMPARE( sc3.readEntry( "flags-bit0-bit1" ), QString( me.valueToKeys(bitfield) ) );
+ QVERIFY( readEntry( sc3, "flags-bit0-bit1", Flags() ) == bitfield );
+}
+
+void KConfigTest::testEntryMap()
+{
+ KConfig sc("kconfigtest");
+ KConfigGroup cg(&sc, "Hello");
+ QMap<QString, QString> entryMap = cg.entryMap();
+ qDebug() << entryMap.keys();
+ QCOMPARE(entryMap.value("stringEntry1"), QString(STRINGENTRY1));
+ QCOMPARE(entryMap.value("stringEntry2"), QString(STRINGENTRY2));
+ QCOMPARE(entryMap.value("stringEntry3"), QString(STRINGENTRY3));
+ QCOMPARE(entryMap.value("stringEntry4"), QString(STRINGENTRY4));
+ QVERIFY(!entryMap.contains("stringEntry5"));
+ QVERIFY(!entryMap.contains("stringEntry6"));
+ QCOMPARE(entryMap.value("Test"), QString::fromUtf8(UTF8BITENTRY));
+ QCOMPARE(entryMap.value("bytearrayEntry"), QString::fromUtf8(BYTEARRAYENTRY));
+ QCOMPARE(entryMap.value("emptyEntry"), QString());
+ QVERIFY(entryMap.contains("emptyEntry"));
+ QCOMPARE(entryMap.value("boolEntry1"), QString(BOOLENTRY1?"true":"false"));
+ QCOMPARE(entryMap.value("boolEntry2"), QString(BOOLENTRY2?"true":"false"));
+ QCOMPARE(entryMap.value("keywith=equalsign"), QString(STRINGENTRY1));
+ QCOMPARE(entryMap.value("byteArrayEntry1"), QString(STRINGENTRY1));
+ QCOMPARE(entryMap.value("doubleEntry1"), QString::number(DOUBLEENTRY, 'g', 15));
+ QCOMPARE(entryMap.value("floatEntry1"), QString::number(FLOATENTRY, 'g', 8));
+}
+
+void KConfigTest::testInvalid()
+{
+ KConfig sc( "kconfigtest" );
+
+ // all of these should print a message to the kdebug.dbg file
+ KConfigGroup sc3(&sc, "Invalid Types" );
+ sc3.writeEntry( "badList", VARIANTLISTENTRY2 );
+
+ QList<int> list;
+
+ // 1 element list
+ list << 1;
+ sc3.writeEntry( QString("badList"), list);
+
+ QVERIFY( sc3.readEntry( "badList", QPoint() ) == QPoint() );
+ QVERIFY( sc3.readEntry( "badList", QRect() ) == QRect() );
+ QVERIFY( sc3.readEntry( "badList", QSize() ) == QSize() );
+ QVERIFY( sc3.readEntry( "badList", QDate() ) == QDate() );
+ QVERIFY( sc3.readEntry( "badList", QDateTime() ) == QDateTime() );
+
+ // 2 element list
+ list << 2;
+ sc3.writeEntry( "badList", list);
+
+ QVERIFY( sc3.readEntry( "badList", QRect() ) == QRect() );
+ QVERIFY( sc3.readEntry( "badList", QDate() ) == QDate() );
+ QVERIFY( sc3.readEntry( "badList", QDateTime() ) == QDateTime() );
+
+ // 3 element list
+ list << 303;
+ sc3.writeEntry( "badList", list);
+
+ QVERIFY( sc3.readEntry( "badList", QPoint() ) == QPoint() );
+ QVERIFY( sc3.readEntry( "badList", QRect() ) == QRect() );
+ QVERIFY( sc3.readEntry( "badList", QSize() ) == QSize() );
+ QVERIFY( sc3.readEntry( "badList", QDate() ) == QDate() ); // out of bounds
+ QVERIFY( sc3.readEntry( "badList", QDateTime() ) == QDateTime() );
+
+ // 4 element list
+ list << 4;
+ sc3.writeEntry( "badList", list );
+
+ QVERIFY( sc3.readEntry( "badList", QPoint() ) == QPoint() );
+ QVERIFY( sc3.readEntry( "badList", QSize() ) == QSize() );
+ QVERIFY( sc3.readEntry( "badList", QDate() ) == QDate() );
+ QVERIFY( sc3.readEntry( "badList", QDateTime() ) == QDateTime() );
+
+ // 5 element list
+ list[2] = 3;
+ list << 5;
+ sc3.writeEntry( "badList", list);
+
+ QVERIFY( sc3.readEntry( "badList", QPoint() ) == QPoint() );
+ QVERIFY( sc3.readEntry( "badList", QRect() ) == QRect() );
+ QVERIFY( sc3.readEntry( "badList", QSize() ) == QSize() );
+ QVERIFY( sc3.readEntry( "badList", QDate() ) == QDate() );
+ QVERIFY( sc3.readEntry( "badList", QDateTime() ) == QDateTime() );
+
+ // 6 element list
+ list << 6;
+ sc3.writeEntry( "badList", list);
+
+ QVERIFY( sc3.readEntry( "badList", QPoint() ) == QPoint() );
+ QVERIFY( sc3.readEntry( "badList", QRect() ) == QRect() );
+ QVERIFY( sc3.readEntry( "badList", QSize() ) == QSize() );
+}
+
+void KConfigTest::testChangeGroup()
+{
+ KConfig sc( "kconfigtest" );
+ KConfigGroup sc3(&sc, "Hello");
+ QCOMPARE(sc3.name(), QString("Hello"));
+ KConfigGroup newGroup(sc3);
+#ifndef KDE_NO_DEPRECATED
+ newGroup.changeGroup("FooBar"); // deprecated!
+ QCOMPARE(newGroup.name(), QString("FooBar"));
+ QCOMPARE(sc3.name(), QString("Hello")); // unchanged
+
+ // Write into the "changed group" and check that it works
+ newGroup.writeEntry("InFooBar", "FB");
+ QCOMPARE(KConfigGroup(&sc, "FooBar").entryMap().value("InFooBar"), QString("FB"));
+ QCOMPARE(KConfigGroup(&sc, "Hello").entryMap().value("InFooBar"), QString());
+#endif
+
+ KConfigGroup rootGroup(sc.group(""));
+ QCOMPARE(rootGroup.name(), QString("<default>"));
+ KConfigGroup sc32(rootGroup.group("Hello"));
+ QCOMPARE(sc32.name(), QString("Hello"));
+ KConfigGroup newGroup2(sc32);
+#ifndef KDE_NO_DEPRECATED
+ newGroup2.changeGroup("FooBar"); // deprecated!
+ QCOMPARE(newGroup2.name(), QString("FooBar"));
+ QCOMPARE(sc32.name(), QString("Hello")); // unchanged
+#endif
+}
+
+// Simple test for deleteEntry
+void KConfigTest::testDeleteEntry()
+{
+ const char* configFile = "kconfigdeletetest";
+ {
+ KConfig conf(configFile);
+ conf.group("Hello").writeEntry("DelKey", "ToBeDeleted");
+ }
+ const QList<QByteArray> lines = readLines(configFile);
+ Q_ASSERT(lines.contains("[Hello]\n"));
+ Q_ASSERT(lines.contains("DelKey=ToBeDeleted\n"));
+
+ KConfig sc(configFile);
+ KConfigGroup group(&sc, "Hello");
+
+ group.deleteEntry("DelKey");
+ QCOMPARE( group.readEntry("DelKey", QString("Fietsbel")), QString("Fietsbel") );
+
+ QVERIFY(group.sync());
+ Q_ASSERT(!readLines(configFile).contains("DelKey=ToBeDeleted\n"));
+ QCOMPARE( group.readEntry("DelKey", QString("still deleted")), QString("still deleted") );
+}
+
+void KConfigTest::testDelete()
+{
+ KConfig sc( "kconfigtest" );
+
+ KConfigGroup ct(&sc, "Complex Types");
+
+ // First delete a nested group
+ KConfigGroup delgr(&ct, "Nested Group 3");
+ QVERIFY(delgr.exists());
+ QVERIFY(ct.hasGroup("Nested Group 3"));
+ delgr.deleteGroup();
+ QVERIFY(!delgr.exists());
+ QVERIFY(!ct.hasGroup("Nested Group 3"));
+ QVERIFY(ct.groupList().contains("Nested Group 3"));
+
+ KConfigGroup ng(&ct, "Nested Group 2");
+ QVERIFY(sc.hasGroup("Complex Types"));
+ QVERIFY(!sc.hasGroup("Does not exist"));
+ sc.deleteGroup("Complex Types");
+ QCOMPARE(sc.group("Complex Types").keyList().count(), 0);
+ QVERIFY(!sc.hasGroup("Complex Types")); // #192266
+ QVERIFY(!sc.group("Complex Types").exists());
+ QVERIFY(!ct.hasGroup("Nested Group 1"));
+
+ QCOMPARE(ct.group("Nested Group 1").keyList().count(), 0);
+ QCOMPARE(ct.group("Nested Group 2").keyList().count(), 0);
+ QCOMPARE(ng.group("Nested Group 2.1").keyList().count(), 0);
+
+ KConfigGroup cg(&sc , "AAA" );
+ cg.deleteGroup();
+ QVERIFY( sc.entryMap("Complex Types").isEmpty() );
+ QVERIFY( sc.entryMap("AAA").isEmpty() );
+ QVERIFY( !sc.entryMap("Hello").isEmpty() ); //not deleted group
+ QVERIFY( sc.entryMap("FooBar").isEmpty() ); //inexistant group
+
+ QVERIFY(cg.sync());
+ // Check what happens on disk
+ const QList<QByteArray> lines = readLines();
+ //qDebug() << lines;
+ QVERIFY(!lines.contains("[Complex Types]\n"));
+ QVERIFY(!lines.contains("[Complex Types][Nested Group 1]\n"));
+ QVERIFY(!lines.contains("[Complex Types][Nested Group 2]\n"));
+ QVERIFY(!lines.contains("[Complex Types][Nested Group 2.1]\n"));
+ QVERIFY(!lines.contains("[AAA]\n"));
+ QVERIFY(lines.contains("[Hello]\n")); // a group that was not deleted
+
+ // test for entries that are marked as deleted when there is no default
+ KConfig cf("kconfigtest", KConfig::SimpleConfig); // make sure there are no defaults
+ cg = cf.group("Portable Devices");
+ cg.writeEntry("devices|manual|(null)", "whatever");
+ cg.writeEntry("devices|manual|/mnt/ipod", "/mnt/ipod");
+ QVERIFY(cf.sync());
+
+ int count=0;
+ Q_FOREACH(const QByteArray& item, readLines())
+ if (item.startsWith("devices|")) // krazy:exclude=strings
+ count++;
+ QCOMPARE(count, 2);
+ cg.deleteEntry("devices|manual|/mnt/ipod");
+ QVERIFY(cf.sync());
+ Q_FOREACH(const QByteArray& item, readLines())
+ QVERIFY(!item.contains("ipod"));
+}
+
+void KConfigTest::testDefaultGroup()
+{
+ KConfig sc( "kconfigtest" );
+ KConfigGroup defaultGroup(&sc, "<default>");
+ QCOMPARE(defaultGroup.name(), QString("<default>"));
+ QVERIFY(!defaultGroup.exists());
+ defaultGroup.writeEntry("TestKey", "defaultGroup");
+ QVERIFY(defaultGroup.exists());
+ QCOMPARE(defaultGroup.readEntry("TestKey", QString()), QString("defaultGroup"));
+ QVERIFY(sc.sync());
+
+ {
+ // Test reading it
+ KConfig sc2("kconfigtest");
+ KConfigGroup defaultGroup2(&sc2, "<default>");
+ QCOMPARE(defaultGroup2.name(), QString("<default>"));
+ QVERIFY(defaultGroup2.exists());
+ QCOMPARE(defaultGroup2.readEntry("TestKey", QString()), QString("defaultGroup"));
+ }
+ {
+ // Test reading it
+ KConfig sc2("kconfigtest");
+ KConfigGroup emptyGroup(&sc2, "");
+ QCOMPARE(emptyGroup.name(), QString("<default>"));
+ QVERIFY(emptyGroup.exists());
+ QCOMPARE(emptyGroup.readEntry("TestKey", QString()), QString("defaultGroup"));
+ }
+
+ QList<QByteArray> lines = readLines();
+ QVERIFY(!lines.contains("[]\n"));
+ QCOMPARE(lines.first(), QByteArray("TestKey=defaultGroup\n"));
+
+ // Now that the group exists make sure it isn't returned from groupList()
+ Q_FOREACH(const QString& group, sc.groupList()) {
+ QVERIFY(!group.isEmpty() && group != "<default>");
+ }
+
+ defaultGroup.deleteGroup();
+ QVERIFY(sc.sync());
+
+ // Test if deleteGroup worked
+ lines = readLines();
+ QVERIFY(lines.first() != QByteArray("TestKey=defaultGroup\n"));
+}
+
+void KConfigTest::testEmptyGroup()
+{
+ KConfig sc( "kconfigtest" );
+ KConfigGroup emptyGroup(&sc, "");
+ QCOMPARE(emptyGroup.name(), QString("<default>")); // confusing, heh?
+ QVERIFY(!emptyGroup.exists());
+ emptyGroup.writeEntry("TestKey", "emptyGroup");
+ QVERIFY(emptyGroup.exists());
+ QCOMPARE(emptyGroup.readEntry("TestKey", QString()), QString("emptyGroup"));
+ QVERIFY(sc.sync());
+
+ {
+ // Test reading it
+ KConfig sc2("kconfigtest");
+ KConfigGroup defaultGroup(&sc2, "<default>");
+ QCOMPARE(defaultGroup.name(), QString("<default>"));
+ QVERIFY(defaultGroup.exists());
+ QCOMPARE(defaultGroup.readEntry("TestKey", QString()), QString("emptyGroup"));
+ }
+ {
+ // Test reading it
+ KConfig sc2("kconfigtest");
+ KConfigGroup emptyGroup2(&sc2, "");
+ QCOMPARE(emptyGroup2.name(), QString("<default>"));
+ QVERIFY(emptyGroup2.exists());
+ QCOMPARE(emptyGroup2.readEntry("TestKey", QString()), QString("emptyGroup"));
+ }
+
+ QList<QByteArray> lines = readLines();
+ QVERIFY(!lines.contains("[]\n")); // there's no support for the [] group, in fact.
+ QCOMPARE(lines.first(), QByteArray("TestKey=emptyGroup\n"));
+
+ // Now that the group exists make sure it isn't returned from groupList()
+ Q_FOREACH(const QString& group, sc.groupList()) {
+ QVERIFY(!group.isEmpty() && group != "<default>");
+ }
+ emptyGroup.deleteGroup();
+ QVERIFY(sc.sync());
+
+ // Test if deleteGroup worked
+ lines = readLines();
+ QVERIFY(lines.first() != QByteArray("TestKey=defaultGroup\n"));
+}
+
+void KConfigTest::testCascadingWithLocale()
+{
+ // This test relies on XDG_CONFIG_DIRS, which only has effect on Unix.
+ // Cascading (more than two levels) isn't available at all on Windows.
+#ifdef Q_OS_UNIX
+ QTemporaryDir middleDir;
+ QTemporaryDir globalDir;
+ qputenv("XDG_CONFIG_DIRS", qPrintable(middleDir.path() + QString(":") + globalDir.path()));
+
+ const QString globalConfigDir = globalDir.path();
+ QVERIFY(QDir().mkpath(globalConfigDir));
+ QFile global(globalConfigDir + "/foo.desktop");
+ QVERIFY(global.open(QIODevice::WriteOnly|QIODevice::Text));
+ QTextStream globalOut(&global);
+ globalOut << "[Group]" << endl
+ << "FromGlobal=true" << endl
+ << "FromGlobal[fr]=vrai" << endl
+ << "Name=Testing" << endl
+ << "Name[fr]=FR" << endl
+ << "Other=Global" << endl
+ << "Other[fr]=Global_FR" << endl;
+ global.close();
+
+ const QString middleConfigDir = middleDir.path();
+ QVERIFY(QDir().mkpath(middleConfigDir));
+ QFile local(middleConfigDir + "/foo.desktop");
+ QVERIFY(local.open(QIODevice::WriteOnly|QIODevice::Text));
+ QTextStream out(&local);
+ out << "[Group]" << endl
+ << "FromLocal=true" << endl
+ << "FromLocal[fr]=vrai" << endl
+ << "Name=Local Testing" << endl
+ << "Name[fr]=FR" << endl
+ << "Other=English Only" << endl;
+ local.close();
+
+ KConfig config("foo.desktop");
+ KConfigGroup group = config.group("Group");
+ QCOMPARE(group.readEntry("FromGlobal"), QString("true"));
+ QCOMPARE(group.readEntry("FromLocal"), QString("true"));
+ QCOMPARE(group.readEntry("Name"), QString("Local Testing"));
+ config.setLocale("fr");
+ QCOMPARE(group.readEntry("FromGlobal"), QString("vrai"));
+ QCOMPARE(group.readEntry("FromLocal"), QString("vrai"));
+ QCOMPARE(group.readEntry("Name"), QString("FR"));
+ QCOMPARE(group.readEntry("Other"), QString("English Only")); // Global_FR is locally overriden
+#endif
+}
+
+void KConfigTest::testMerge()
+{
+ KConfig config("mergetest", KConfig::SimpleConfig);
+
+ KConfigGroup cg = config.group("some group");
+ cg.writeEntry("entry", " random entry");
+ cg.writeEntry("another entry", "blah blah blah");
+
+ { // simulate writing by another process
+ QFile file(QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + "/mergetest");
+ file.open(QIODevice::WriteOnly|QIODevice::Text);
+ QTextStream out(&file);
+ out.setCodec("UTF-8");
+ out << "[Merged Group]" << endl
+ << "entry1=Testing" << endl
+ << "entry2=More Testing" << endl
+ << "[some group]" << endl
+ << "entry[fr]=French" << endl
+ << "entry[es]=Spanish" << endl
+ << "entry[de]=German" << endl;
+ }
+ QVERIFY(config.sync());
+
+ {
+ QList<QByteArray> lines;
+ // this is what the file should look like
+ lines << "[Merged Group]\n"
+ << "entry1=Testing\n"
+ << "entry2=More Testing\n"
+ << "\n"
+ << "[some group]\n"
+ << "another entry=blah blah blah\n"
+ << "entry=\\srandom entry\n"
+ << "entry[de]=German\n"
+ << "entry[es]=Spanish\n"
+ << "entry[fr]=French\n";
+ QFile file(QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + "/mergetest");
+ file.open(QIODevice::ReadOnly|QIODevice::Text);
+ Q_FOREACH (const QByteArray& line, lines) {
+ QCOMPARE(line, file.readLine());
+ }
+ }
+}
+
+void KConfigTest::testImmutable()
+{
+ {
+ QFile file(QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + "/immutabletest");
+ file.open(QIODevice::WriteOnly|QIODevice::Text);
+ QTextStream out(&file);
+ out.setCodec("UTF-8");
+ out << "[$i]" << endl
+ << "entry1=Testing" << endl
+ << "[group][$i]" << endl
+ << "[group][subgroup][$i]" << endl;
+ }
+
+ KConfig config("immutabletest", KConfig::SimpleConfig);
+ QVERIFY(config.isGroupImmutable(QByteArray()));
+ KConfigGroup cg = config.group(QByteArray());
+ QVERIFY(cg.isEntryImmutable("entry1"));
+ KConfigGroup cg1 = config.group("group");
+ QVERIFY(cg1.isImmutable());
+ KConfigGroup cg1a = cg.group("group");
+ QVERIFY(cg1a.isImmutable());
+ KConfigGroup cg2 = cg1.group("subgroup");
+ QVERIFY(cg2.isImmutable());
+}
+
+void KConfigTest::testOptionOrder()
+{
+ {
+ QFile file(QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + "/doubleattrtest");
+ file.open(QIODevice::WriteOnly|QIODevice::Text);
+ QTextStream out(&file);
+ out.setCodec("UTF-8");
+ out << "[group3]" << endl
+ << "entry2=unlocalized" << endl
+ << "entry2[$i][de_DE]=t2" << endl;
+ }
+ KConfig config("doubleattrtest", KConfig::SimpleConfig);
+ config.setLocale("de_DE");
+ KConfigGroup cg3 = config.group("group3");
+ QVERIFY(!cg3.isImmutable());
+ QCOMPARE(cg3.readEntry("entry2",""), QString("t2"));
+ QVERIFY(cg3.isEntryImmutable("entry2"));
+ config.setLocale("C");
+ QCOMPARE(cg3.readEntry("entry2",""), QString("unlocalized"));
+ QVERIFY(!cg3.isEntryImmutable("entry2"));
+ cg3.writeEntry("entry2","modified");
+ QVERIFY(config.sync());
+
+ {
+ QList<QByteArray> lines;
+ // this is what the file should look like
+ lines << "[group3]\n"
+ << "entry2=modified\n"
+ << "entry2[de_DE][$i]=t2\n";
+
+ QFile file(QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + "/doubleattrtest");
+ file.open(QIODevice::ReadOnly|QIODevice::Text);
+ Q_FOREACH (const QByteArray& line, lines) {
+ QCOMPARE(line, file.readLine());
+ }
+ }
+}
+
+
+void KConfigTest::testGroupEscape()
+{
+ KConfig config("groupescapetest", KConfig::SimpleConfig);
+ QVERIFY( config.group(DOLLARGROUP).exists() );
+}
+
+void KConfigTest::testSubGroup()
+{
+ KConfig sc( "kconfigtest" );
+ KConfigGroup cg( &sc, "ParentGroup" );
+ QCOMPARE(cg.readEntry( "parentgrpstring", ""), QString("somevalue") );
+ KConfigGroup subcg1( &cg, "SubGroup1");
+ QCOMPARE(subcg1.name(), QString("SubGroup1"));
+ QCOMPARE(subcg1.readEntry( "somestring", ""), QString("somevalue") );
+ KConfigGroup subcg2( &cg, "SubGroup2");
+ QCOMPARE(subcg2.name(), QString("SubGroup2"));
+ QCOMPARE(subcg2.readEntry( "substring", ""), QString("somevalue") );
+ KConfigGroup subcg3( &cg, "SubGroup/3");
+ QCOMPARE(subcg3.readEntry( "sub3string", ""), QString("somevalue") );
+ QCOMPARE(subcg3.name(), QString("SubGroup/3"));
+ KConfigGroup rcg( &sc, "" );
+ KConfigGroup srcg( &rcg, "ParentGroup" );
+ QCOMPARE(srcg.readEntry( "parentgrpstring", ""), QString("somevalue") );
+
+ QStringList groupList = cg.groupList();
+ groupList.sort(); // comes from QSet, so order is undefined
+ QCOMPARE(groupList, (QStringList() << "SubGroup/3" << "SubGroup1" << "SubGroup2"));
+
+ const QStringList expectedSubgroup3Keys = (QStringList() << "sub3string");
+ QCOMPARE(subcg3.keyList(), expectedSubgroup3Keys);
+ const QStringList expectedParentGroupKeys(QStringList() << "parentgrpstring");
+
+ QCOMPARE(cg.keyList(), expectedParentGroupKeys);
+
+ QCOMPARE(QStringList(cg.entryMap().keys()), expectedParentGroupKeys);
+ QCOMPARE(QStringList(subcg3.entryMap().keys()), expectedSubgroup3Keys);
+
+ // Create A group containing only other groups. We want to make sure it
+ // shows up in groupList of sc
+ KConfigGroup neg(&sc, "NoEntryGroup");
+ KConfigGroup negsub1(&neg, "NEG Child1");
+ negsub1.writeEntry( "entry", "somevalue" );
+ KConfigGroup negsub2(&neg, "NEG Child2");
+ KConfigGroup negsub3(&neg, "NEG Child3");
+ KConfigGroup negsub31(&negsub3, "NEG Child3-1");
+ KConfigGroup negsub4(&neg, "NEG Child4");
+ KConfigGroup negsub41(&negsub4, "NEG Child4-1");
+ negsub41.writeEntry( "entry", "somevalue" );
+
+ // A group exists if it has content
+ QVERIFY(negsub1.exists());
+
+ // But it doesn't exist if it has no content
+ // Ossi and David say: this is how it's supposed to work.
+ // However you could add a dummy entry for now, or we could add a "Persist" feature to kconfig groups
+ // which would make it written out, much like "immutable" already makes them persistent.
+ QVERIFY(!negsub2.exists());
+
+ // A subgroup does not qualify as content if it is also empty
+ QVERIFY(!negsub3.exists());
+
+ // A subgroup with content is ok
+ QVERIFY(negsub4.exists());
+
+ // Only subgroups with content show up in groupList()
+ //QEXPECT_FAIL("", "Empty subgroups do not show up in groupList()", Continue);
+ //QCOMPARE(neg.groupList(), QStringList() << "NEG Child1" << "NEG Child2" << "NEG Child3" << "NEG Child4");
+ // This is what happens
+ QStringList groups = neg.groupList();
+ groups.sort(); // Qt5 made the ordering unreliable, due to QHash
+ QCOMPARE(groups, QStringList() << "NEG Child1" << "NEG Child4");
+
+ // make sure groupList() isn't returning something it shouldn't
+ Q_FOREACH(const QString& group, sc.groupList()) {
+ QVERIFY(!group.isEmpty() && group != "<default>");
+ QVERIFY(!group.contains(QChar(0x1d)));
+ QVERIFY(!group.contains("subgroup"));
+ QVERIFY(!group.contains("SubGroup"));
+ }
+
+ QVERIFY(sc.sync());
+
+ // Check that the empty groups are not written out.
+ const QList<QByteArray> lines = readLines();
+ QVERIFY(lines.contains("[NoEntryGroup][NEG Child1]\n"));
+ QVERIFY(!lines.contains("[NoEntryGroup][NEG Child2]\n"));
+ QVERIFY(!lines.contains("[NoEntryGroup][NEG Child3]\n"));
+ QVERIFY(!lines.contains("[NoEntryGroup][NEG Child4]\n")); // implicit group, not written out
+ QVERIFY(lines.contains("[NoEntryGroup][NEG Child4][NEG Child4-1]\n"));
+}
+
+void KConfigTest::testAddConfigSources()
+{
+ KConfig cf("specificrc");
+
+ cf.addConfigSources(QStringList() << QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + "/baserc");
+ cf.reparseConfiguration();
+
+ KConfigGroup specificgrp(&cf, "Specific Only Group");
+ QCOMPARE(specificgrp.readEntry("ExistingEntry", ""), QString("DevValue"));
+
+ KConfigGroup sharedgrp(&cf, "Shared Group");
+ QCOMPARE(sharedgrp.readEntry("SomeSpecificOnlyEntry",""), QString("DevValue"));
+ QCOMPARE(sharedgrp.readEntry("SomeBaseOnlyEntry",""), QString("BaseValue"));
+ QCOMPARE(sharedgrp.readEntry("SomeSharedEntry",""), QString("DevValue"));
+
+ KConfigGroup basegrp(&cf, "Base Only Group");
+ QCOMPARE(basegrp.readEntry("ExistingEntry", ""), QString("BaseValue"));
+ basegrp.writeEntry("New Entry Base Only", "SomeValue");
+
+ KConfigGroup newgrp(&cf, "New Group");
+ newgrp.writeEntry("New Entry", "SomeValue");
+
+ QVERIFY(cf.sync());
+
+ KConfig plaincfg("specificrc");
+
+ KConfigGroup newgrp2(&plaincfg, "New Group");
+ QCOMPARE(newgrp2.readEntry("New Entry", ""), QString("SomeValue"));
+
+ KConfigGroup basegrp2(&plaincfg, "Base Only Group");
+ QCOMPARE(basegrp2.readEntry("New Entry Base Only", ""), QString("SomeValue"));
+}
+
+void KConfigTest::testGroupCopyTo()
+{
+ KConfig cf1("kconfigtest");
+ KConfigGroup original = cf1.group("Enum Types");
+
+ KConfigGroup copy = cf1.group("Enum Types Copy");
+ original.copyTo(&copy); // copy from one group to another
+ QCOMPARE(copy.entryMap(), original.entryMap());
+
+ KConfig cf2("copy_of_kconfigtest", KConfig::SimpleConfig);
+ QVERIFY(!cf2.hasGroup(original.name()));
+ QVERIFY(!cf2.hasGroup(copy.name()));
+
+ KConfigGroup newGroup = cf2.group(original.name());
+ original.copyTo(&newGroup); // copy from one file to another
+ QVERIFY(cf2.hasGroup(original.name()));
+ QVERIFY(!cf2.hasGroup(copy.name())); // make sure we didn't copy more than we wanted
+ QCOMPARE(newGroup.entryMap(), original.entryMap());
+}
+
+void KConfigTest::testConfigCopyToSync()
+{
+ KConfig cf1("kconfigtest");
+ // Prepare source file
+ KConfigGroup group(&cf1, "CopyToTest");
+ group.writeEntry("Type", "Test");
+ QVERIFY(cf1.sync());
+
+ // Copy to "destination"
+ const QString destination = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + "/kconfigcopytotest";
+ QFile::remove(destination);
+
+ KConfig cf2("kconfigcopytotest");
+ KConfigGroup group2(&cf2, "CopyToTest");
+
+ group.copyTo(&group2);
+
+ QString testVal = group2.readEntry("Type");
+ QCOMPARE(testVal, QString("Test"));
+ // should write to disk the copied data from group
+ QVERIFY(cf2.sync());
+ QVERIFY(QFile::exists(destination));
+}
+
+void KConfigTest::testConfigCopyTo()
+{
+ KConfig cf1("kconfigtest");
+ {
+ // Prepare source file
+ KConfigGroup group(&cf1, "CopyToTest");
+ group.writeEntry("Type", "Test");
+ QVERIFY(cf1.sync());
+ }
+
+ {
+ // Copy to "destination"
+ const QString destination = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + "/kconfigcopytotest";
+ QFile::remove(destination);
+ KConfig cf2;
+ cf1.copyTo(destination, &cf2);
+ KConfigGroup group2(&cf2, "CopyToTest");
+ QString testVal = group2.readEntry("Type");
+ QCOMPARE(testVal, QString("Test"));
+ QVERIFY(cf2.sync());
+ QVERIFY(QFile::exists(destination));
+ }
+
+ // Check copied config file on disk
+ KConfig cf3("kconfigcopytotest");
+ KConfigGroup group3(&cf3, "CopyToTest");
+ QString testVal = group3.readEntry("Type");
+ QCOMPARE(testVal, QString("Test"));
+}
+
+void KConfigTest::testReparent()
+{
+ KConfig cf("kconfigtest");
+ const QString name("Enum Types");
+ KConfigGroup group = cf.group(name);
+ const QMap<QString, QString> originalMap = group.entryMap();
+ KConfigGroup parent = cf.group("Parent Group");
+
+ QVERIFY(!parent.hasGroup(name));
+
+ QVERIFY(group.entryMap() == originalMap);
+
+ group.reparent(&parent); // see if it can be made a sub-group of another group
+ QVERIFY(parent.hasGroup(name));
+ QCOMPARE(group.entryMap(), originalMap);
+
+ group.reparent(&cf); // see if it can make it a top-level group again
+// QVERIFY(!parent.hasGroup(name));
+ QCOMPARE(group.entryMap(), originalMap);
+}
+
+static void ageTimeStamp(const QString& path, int nsec)
+{
+#ifdef Q_OS_UNIX
+ QDateTime mtime = QFileInfo(path).lastModified().addSecs(-nsec);
+ struct utimbuf utbuf;
+ utbuf.actime = mtime.toTime_t();
+ utbuf.modtime = utbuf.actime;
+ utime(QFile::encodeName(path), &utbuf);
+#else
+ QTest::qSleep(nsec * 1000);
+#endif
+}
+
+void KConfigTest::testWriteOnSync()
+{
+ QDateTime oldStamp, newStamp;
+ KConfig sc("kconfigtest", KConfig::IncludeGlobals);
+
+ // Age the timestamp of global config file a few sec, and collect it.
+ QString globFile = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + "/kdeglobals";
+ ageTimeStamp(globFile, 2); // age 2 sec
+ oldStamp = QFileInfo(globFile).lastModified();
+
+ // Add a local entry and sync the config.
+ // Should not rewrite the global config file.
+ KConfigGroup cgLocal(&sc, "Locals");
+ cgLocal.writeEntry("someLocalString", "whatever");
+ QVERIFY(sc.sync());
+
+ // Verify that the timestamp of global config file didn't change.
+ newStamp = QFileInfo(globFile).lastModified();
+ QCOMPARE(newStamp, oldStamp);
+
+ // Age the timestamp of local config file a few sec, and collect it.
+ QString locFile = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + "/kconfigtest";
+ ageTimeStamp(locFile, 2); // age 2 sec
+ oldStamp = QFileInfo(locFile).lastModified();
+
+ // Add a global entry and sync the config.
+ // Should not rewrite the local config file.
+ KConfigGroup cgGlobal(&sc, "Globals");
+ cgGlobal.writeEntry("someGlobalString", "whatever",
+ KConfig::Persistent|KConfig::Global);
+ QVERIFY(sc.sync());
+
+ // Verify that the timestamp of local config file didn't change.
+ newStamp = QFileInfo(locFile).lastModified();
+ QCOMPARE(newStamp, oldStamp);
+}
+
+void KConfigTest::testFailOnReadOnlyFileSync()
+{
+ KConfig sc("kconfigfailonreadonlytest");
+ KConfigGroup cgLocal(&sc, "Locals");
+
+ cgLocal.writeEntry("someLocalString", "whatever");
+ QVERIFY(cgLocal.sync());
+
+ QFile f(QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + '/' + sc.name());
+ QVERIFY(f.exists());
+ QVERIFY(f.setPermissions(QFileDevice::ReadOwner));
+
+ cgLocal.writeEntry("someLocalString", "whatever2");
+ QVERIFY(!cgLocal.sync());
+
+ QVERIFY(f.setPermissions(QFileDevice::ReadOwner | QFileDevice::WriteOwner));
+ QVERIFY(f.remove());
+}
+
+void KConfigTest::testDirtyOnEqual()
+{
+ QDateTime oldStamp, newStamp;
+ KConfig sc("kconfigtest");
+
+ // Initialize value
+ KConfigGroup cgLocal(&sc, "random");
+ cgLocal.writeEntry("theKey", "whatever");
+ QVERIFY(sc.sync());
+
+ // Age the timestamp of local config file a few sec, and collect it.
+ QString locFile = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + "/kconfigtest";
+ ageTimeStamp(locFile, 2); // age 2 sec
+ oldStamp = QFileInfo(locFile).lastModified();
+
+ // Write exactly the same again
+ cgLocal.writeEntry("theKey", "whatever");
+ // This should be a no-op
+ QVERIFY(sc.sync());
+
+ // Verify that the timestamp of local config file didn't change.
+ newStamp = QFileInfo(locFile).lastModified();
+ QCOMPARE(newStamp, oldStamp);
+}
+
+void KConfigTest::testDirtyOnEqualOverdo()
+{
+ QByteArray val1("\0""one", 4);
+ QByteArray val2("\0""two", 4);
+ QByteArray defvalr;
+
+ KConfig sc("kconfigtest");
+ KConfigGroup cgLocal(&sc, "random");
+ cgLocal.writeEntry("someKey", val1);
+ QCOMPARE(cgLocal.readEntry("someKey", defvalr), val1);
+ cgLocal.writeEntry("someKey", val2);
+ QCOMPARE(cgLocal.readEntry("someKey", defvalr), val2);
+}
+
+
+void KConfigTest::testCreateDir()
+{
+ // Test auto-creating the parent directory when needed (KConfigIniBackend::createEnclosing)
+ QString kdehome = QDir::home().canonicalPath() + "/.kde-unit-test";
+ QString subdir = kdehome + "/newsubdir";
+ QString file = subdir + "/foo.desktop";
+ QFile::remove(file);
+ QDir().rmdir(subdir);
+ QVERIFY(!QDir().exists(subdir));
+ KDesktopFile desktopFile(file);
+ desktopFile.desktopGroup().writeEntry("key", "value");
+ QVERIFY(desktopFile.sync());
+ QVERIFY(QFile::exists(file));
+
+ // Cleanup
+ QFile::remove(file);
+ QDir().rmdir(subdir);
+}
+
+void KConfigTest::testSyncOnExit()
+{
+ // Often, the KGlobalPrivate global static's destructor ends up calling ~KConfig ->
+ // KConfig::sync ... and if that code triggers KGlobal code again then things could crash.
+ // So here's a test for modifying KSharedConfig::openConfig() and not syncing, the process exit will sync.
+ KConfigGroup grp(KSharedConfig::openConfig(), "syncOnExit");
+ grp.writeEntry("key", "value");
+}
+
+void KConfigTest::testSharedConfig()
+{
+ // Can I use a KConfigGroup even after the KSharedConfigPtr goes out of scope?
+ KConfigGroup myConfigGroup;
+ {
+ KSharedConfigPtr config = KSharedConfig::openConfig("kconfigtest");
+ myConfigGroup = KConfigGroup(config, "Hello");
+ }
+ QCOMPARE(myConfigGroup.readEntry("stringEntry1"), QString(STRINGENTRY1));
+}
+
+void KConfigTest::testLocaleConfig()
+{
+ // Initialize the testdata
+ QDir dir;
+ QString subdir = QDir::home().canonicalPath() + "/.kde-unit-test/";
+ dir.mkpath(subdir);
+ QString file = subdir + "/localized.test";
+ QFile::remove(file);
+ QFile f(file);
+ QVERIFY(f.open(QIODevice::WriteOnly));
+ QTextStream ts(&f);
+ ts << "[Test_Wrong]\n";
+ ts << "foo[ca]=5\n";
+ ts << "foostring[ca]=nice\n";
+ ts << "foobool[ca]=true\n";
+ ts << "[Test_Right]\n";
+ ts << "foo=5\n";
+ ts << "foo[ca]=5\n";
+ ts << "foostring=primary\n";
+ ts << "foostring[ca]=nice\n";
+ ts << "foobool=primary\n";
+ ts << "foobool[ca]=true\n";
+ f.close();
+
+ // Load the testdata
+ QVERIFY(QFile::exists(file));
+ KConfig config(file);
+ config.setLocale("ca");
+
+ // This group has only localized values. That is not supported. The values
+ // should be dropped on loading.
+ KConfigGroup cg(&config, "Test_Wrong");
+ QEXPECT_FAIL("", "The localized values are not dropped", Continue);
+ QVERIFY(!cg.hasKey("foo"));
+ QEXPECT_FAIL("", "The localized values are not dropped", Continue);
+ QVERIFY(!cg.hasKey("foostring"));
+ QEXPECT_FAIL("", "The localized values are not dropped", Continue);
+ QVERIFY(!cg.hasKey("foobool"));
+
+ // Now check the correct config group
+ KConfigGroup cg2(&config, "Test_Right");
+ QCOMPARE(cg2.readEntry("foo"), QString("5"));
+ QCOMPARE(cg2.readEntry("foo", 3), 5);
+ QCOMPARE(cg2.readEntry("foostring"), QString("nice"));
+ QCOMPARE(cg2.readEntry("foostring", "ugly"), QString("nice"));
+ QCOMPARE(cg2.readEntry("foobool"), QString("true"));
+ QCOMPARE(cg2.readEntry("foobool", false), true);
+
+ // Clean up after the testcase
+ QFile::remove(file);
+}
+
+
+void KConfigTest::testDeleteWhenLocalized()
+{
+ // Initialize the testdata
+ QDir dir;
+ QString subdir = QDir::home().canonicalPath() + "/.kde-unit-test/";
+ dir.mkpath(subdir);
+ QString file = subdir + "/localized_delete.test";
+ QFile::remove(file);
+ QFile f(file);
+ QVERIFY(f.open(QIODevice::WriteOnly));
+ QTextStream ts(&f);
+ ts << "[Test4711]\n";
+ ts << "foo=3\n";
+ ts << "foo[ca]=5\n";
+ ts << "foo[de]=7\n";
+ ts << "foostring=ugly\n";
+ ts << "foostring[ca]=nice\n";
+ ts << "foostring[de]=schoen\n";
+ ts << "foobool=false\n";
+ ts << "foobool[ca]=true\n";
+ ts << "foobool[de]=true\n";
+ f.close();
+
+ // Load the testdata. We start in locale "ca".
+ QVERIFY(QFile::exists(file));
+ KConfig config(file);
+ config.setLocale("ca");
+ KConfigGroup cg(&config, "Test4711");
+
+ // Delete a value. Once with localized, once with Normal
+ cg.deleteEntry("foostring", KConfigBase::Persistent | KConfigBase::Localized);
+ cg.deleteEntry("foobool");
+ QVERIFY(config.sync());
+
+ // The value is now gone. The others are still there. Everything correct
+ // here.
+ QVERIFY(!cg.hasKey("foostring"));
+ QVERIFY(!cg.hasKey("foobool"));
+ QVERIFY(cg.hasKey("foo"));
+
+ // The current state is: (Just return before this comment.)
+ // [...]
+ // foobool[ca]=true
+ // foobool[de]=wahr
+ // foostring=ugly
+ // foostring[de]=schoen
+
+ // Now switch the locale to "de" and repeat the checks. Results should be
+ // the same. But they currently are not. The localized value are
+ // independent of each other. All values are still there in "de".
+ config.setLocale("de");
+ QEXPECT_FAIL("", "Currently localized values are not deleted correctly", Continue);
+ QVERIFY(!cg.hasKey("foostring"));
+ QEXPECT_FAIL("", "Currently localized values are not deleted correctly", Continue);
+ QVERIFY(!cg.hasKey("foobool"));
+ QVERIFY(cg.hasKey("foo"));
+ // Check where the wrong values come from.
+ // We get the "de" value.
+ QCOMPARE(cg.readEntry("foostring", "nothing"), QString("schoen"));
+ // We get the "de" value.
+ QCOMPARE(cg.readEntry("foobool", false), true);
+
+ // Now switch the locale back "ca" and repeat the checks. Results are
+ // again different.
+ config.setLocale("ca");
+ // This line worked above. But now it fails.
+ QEXPECT_FAIL("", "Currently localized values are not deleted correctly", Continue);
+ QVERIFY(!cg.hasKey("foostring"));
+ // This line worked above too.
+ QEXPECT_FAIL("", "Currently localized values are not deleted correctly", Continue);
+ QVERIFY(!cg.hasKey("foobool"));
+ QVERIFY(cg.hasKey("foo"));
+ // Check where the wrong values come from.
+ // We get the primary value because the "ca" value was deleted.
+ QCOMPARE(cg.readEntry("foostring", "nothing"), QString("ugly"));
+ // We get the "ca" value.
+ QCOMPARE(cg.readEntry("foobool", false), true);
+
+ // Now test the deletion of a group.
+ cg.deleteGroup();
+ QVERIFY(config.sync());
+
+ // Current state: [ca] and [de] entries left... oops.
+ //qDebug() << readLinesFrom(file);
+
+ // Bug: The group still exists [because of the localized entries]...
+ QVERIFY(cg.exists());
+ QVERIFY(!cg.hasKey("foo"));
+ QVERIFY(!cg.hasKey("foostring"));
+ QEXPECT_FAIL("", "Currently localized values are not deleted correctly", Continue);
+ QVERIFY(!cg.hasKey("foobool"));
+
+ // Now switch the locale to "de" and repeat the checks. All values
+ // still here because only the primary values are deleted.
+ config.setLocale("de");
+ QEXPECT_FAIL("", "Currently localized values are not deleted correctly", Continue);
+ QVERIFY(!cg.hasKey("foo"));
+ QEXPECT_FAIL("", "Currently localized values are not deleted correctly", Continue);
+ QVERIFY(!cg.hasKey("foostring"));
+ QEXPECT_FAIL("", "Currently localized values are not deleted correctly", Continue);
+ QVERIFY(!cg.hasKey("foobool"));
+ // Check where the wrong values come from.
+ // We get the "de" value.
+ QCOMPARE(cg.readEntry("foostring", "nothing"), QString("schoen"));
+ // We get the "de" value.
+ QCOMPARE(cg.readEntry("foobool", false), true);
+ // We get the "de" value.
+ QCOMPARE(cg.readEntry("foo", 0), 7);
+
+ // Now switch the locale to "ca" and repeat the checks
+ // "foostring" is now really gone because both the primary value and the
+ // "ca" value are deleted.
+ config.setLocale("ca");
+ QEXPECT_FAIL("", "Currently localized values are not deleted correctly", Continue);
+ QVERIFY(!cg.hasKey("foo"));
+ QVERIFY(!cg.hasKey("foostring"));
+ QEXPECT_FAIL("", "Currently localized values are not deleted correctly", Continue);
+ QVERIFY(!cg.hasKey("foobool"));
+ // Check where the wrong values come from.
+ // We get the "ca" value.
+ QCOMPARE(cg.readEntry("foobool", false), true);
+ // We get the "ca" value.
+ QCOMPARE(cg.readEntry("foo", 0), 5);
+
+ // Cleanup
+ QFile::remove(file);
+}
+
+
+void KConfigTest::testKdeGlobals()
+{
+ {
+ KConfig glob("kdeglobals");
+ KConfigGroup general(&glob, "General");
+ general.writeEntry("testKG", "1");
+ QVERIFY(glob.sync());
+ }
+
+ KConfig globRead("kdeglobals");
+ const KConfigGroup general(&globRead, "General");
+ QCOMPARE(general.readEntry("testKG"), QString("1"));
+
+ // Check we wrote into kdeglobals
+ const QList<QByteArray> lines = readLines("kdeglobals");
+ QVERIFY(lines.contains("[General]\n"));
+ QVERIFY(lines.contains("testKG=1\n"));
+
+ // Writing using NoGlobals
+ {
+ KConfig glob("kdeglobals", KConfig::NoGlobals);
+ KConfigGroup general(&glob, "General");
+ general.writeEntry("testKG", "2");
+ QVERIFY(glob.sync());
+ }
+ globRead.reparseConfiguration();
+ QCOMPARE(general.readEntry("testKG"), QString("2"));
+
+ // Reading using NoGlobals
+ {
+ KConfig globReadNoGlob("kdeglobals", KConfig::NoGlobals);
+ const KConfigGroup generalNoGlob(&globReadNoGlob, "General");
+ QCOMPARE(generalNoGlob.readEntry("testKG"), QString("2"));
+ }
+
+ // TODO now use kconfigtest and writeEntry(,Global) -> should go into kdeglobals
+}
+
+void KConfigTest::testAnonymousConfig()
+{
+ KConfig anonConfig(QString(), KConfig::SimpleConfig);
+ KConfigGroup general(&anonConfig, "General");
+ QCOMPARE(general.readEntry("testKG"), QString()); // no kdeglobals merging
+ general.writeEntry("Foo", "Bar");
+ QCOMPARE(general.readEntry("Foo"), QString("Bar"));
+}
+
+#include <QThreadPool>
+#include <qtconcurrentrun.h>
+
+// To find multithreading bugs: valgrind --tool=helgrind --track-lockorders=no ./kconfigtest testThreads
+void KConfigTest::testThreads()
+{
+ QThreadPool::globalInstance()->setMaxThreadCount(6);
+ QList<QFuture<void> > futures;
+ // Run in parallel some tests that work on different config files,
+ // otherwise unexpected things might indeed happen.
+ futures << QtConcurrent::run(this, &KConfigTest::testAddConfigSources);
+ futures << QtConcurrent::run(this, &KConfigTest::testSimple);
+ futures << QtConcurrent::run(this, &KConfigTest::testDefaults);
+ // QEXPECT_FAIL triggers race conditions, it should be fixed to use QThreadStorage...
+ //futures << QtConcurrent::run(this, &KConfigTest::testDeleteWhenLocalized);
+ //futures << QtConcurrent::run(this, &KConfigTest::testEntryMap);
+ Q_FOREACH(QFuture<void> f, futures) // krazy:exclude=foreach
+ f.waitForFinished();
+}
diff --git a/tier1/kconfig/autotests/kconfigtest.h b/tier1/kconfig/autotests/kconfigtest.h
new file mode 100644
index 00000000..ba929086
--- /dev/null
+++ b/tier1/kconfig/autotests/kconfigtest.h
@@ -0,0 +1,86 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1997 Matthias Kalle Dalheimer (kalle@kde.org)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#ifndef KCONFIGTEST_H
+#define KCONFIGTEST_H
+
+#include <QtCore/QObject>
+
+class KConfigTest : public QObject
+{
+ Q_OBJECT
+ Q_ENUMS(Testing)
+ Q_FLAGS(Flags)
+
+public:
+ enum Testing { Ones=1, Tens=10, Hundreds=100};
+ enum bits { bit0=1, bit1=2, bit2=4, bit3=8 };
+ Q_DECLARE_FLAGS(Flags, bits)
+
+private Q_SLOTS:
+ void initTestCase();
+ void cleanupTestCase();
+ void testSimple();
+ void testDefaults();
+ void testLists();
+ void testLocale();
+ void testEncoding();
+ void testPath();
+ void testPersistenceOfExpandFlagForPath();
+ void testComplex();
+ void testEnums();
+ void testEntryMap();
+ void testInvalid();
+ void testDeleteEntry();
+ void testDelete();
+ void testDeleteWhenLocalized();
+ void testDefaultGroup();
+ void testEmptyGroup();
+ void testCascadingWithLocale();
+ void testMerge();
+ void testImmutable();
+ void testGroupEscape();
+ void testRevertAllEntries();
+ void testChangeGroup();
+ void testGroupCopyTo();
+ void testConfigCopyTo();
+ void testConfigCopyToSync();
+ void testReparent();
+ void testAnonymousConfig();
+
+ void testSubGroup();
+ void testAddConfigSources();
+ void testWriteOnSync();
+ void testFailOnReadOnlyFileSync();
+ void testDirtyOnEqual();
+ void testDirtyOnEqualOverdo();
+ void testCreateDir();
+ void testSharedConfig();
+ void testOptionOrder();
+ void testLocaleConfig();
+ void testDirtyAfterRevert();
+ void testKdeGlobals();
+
+ void testThreads();
+
+ // should be last
+ void testSyncOnExit();
+};
+Q_DECLARE_OPERATORS_FOR_FLAGS(KConfigTest::Flags)
+
+#endif /* KCONFIGTEST_H */
diff --git a/tier1/kconfig/autotests/kdesktopfiletest.cpp b/tier1/kconfig/autotests/kdesktopfiletest.cpp
new file mode 100644
index 00000000..d77e3a50
--- /dev/null
+++ b/tier1/kconfig/autotests/kdesktopfiletest.cpp
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2006 David Faure <faure@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License version 2 as published by the Free Software Foundation;
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#include "kdesktopfiletest.h"
+#include <kconfiggroup.h>
+#include <qtemporaryfile.h>
+
+#include "kdesktopfile.h"
+
+#include <QtTest>
+
+QTEST_MAIN( KDesktopFileTest )
+
+void KDesktopFileTest::testRead()
+{
+ QTemporaryFile file("testReadXXXXXX.desktop");
+ QVERIFY( file.open() );
+ const QString fileName = file.fileName();
+ QTextStream ts( &file );
+ ts <<
+ "[Desktop Entry]\n"
+ "Type=Application\n"
+ "Name=My Application\n"
+ "Icon=foo\n"
+ "\n";
+ file.close();
+ QVERIFY(QFile::exists(fileName));
+ QVERIFY(KDesktopFile::isDesktopFile(fileName));
+ KDesktopFile df(fileName);
+ QCOMPARE(df.readType(), QString::fromLatin1("Application"));
+ QVERIFY(df.hasApplicationType());
+ QCOMPARE(df.readName(), QString::fromLatin1("My Application"));
+ QCOMPARE(df.readIcon(), QString::fromLatin1("foo"));
+ QVERIFY(!df.hasLinkType());
+ QCOMPARE(df.fileName(), QFileInfo(fileName).canonicalFilePath());
+}
+
+void KDesktopFileTest::testSuccessfulTryExec()
+{
+ QTemporaryFile file;
+ QVERIFY( file.open() );
+ const QString fileName = file.fileName();
+ QTextStream ts( &file );
+ ts <<
+ "[Desktop Entry]\n"
+ "TryExec=whoami\n"
+ "\n";
+ file.close();
+ QVERIFY(QFile::exists(fileName));
+ KDesktopFile df(fileName);
+ QCOMPARE(df.tryExec(), true);
+}
+
+void KDesktopFileTest::testUnsuccessfulTryExec()
+{
+ QTemporaryFile file;
+ QVERIFY( file.open() );
+ const QString fileName = file.fileName();
+ QTextStream ts( &file );
+ ts <<
+ "[Desktop Entry]\n"
+ "TryExec=/does/not/exist\n"
+ "\n";
+ file.close();
+ QVERIFY(QFile::exists(fileName));
+ KDesktopFile df(fileName);
+ QCOMPARE(df.tryExec(), false);
+}
+
+void KDesktopFileTest::testActionGroup()
+{
+ QTemporaryFile file;
+ QVERIFY( file.open() );
+ const QString fileName = file.fileName();
+ QTextStream ts( &file );
+ ts <<
+ "[Desktop Entry]\n"
+ "Actions=encrypt;\n"
+ "[Desktop Action encrypt]\n"
+ "Name=Encrypt file\n"
+ "\n";
+ file.close();
+ QVERIFY(QFile::exists(fileName));
+ KDesktopFile df(fileName);
+ QCOMPARE(df.readType(), QString());
+ QCOMPARE(df.fileName(), fileName);
+ QCOMPARE(df.readActions(), QStringList() << "encrypt");
+ QCOMPARE(df.hasActionGroup("encrypt"), true);
+ QCOMPARE(df.hasActionGroup("doesnotexist"), false);
+ KConfigGroup cg = df.actionGroup("encrypt");
+ QVERIFY(cg.hasKey("Name"));
+ QCOMPARE(cg.readEntry("Name"), QString("Encrypt file"));
+}
+
+void KDesktopFileTest::testIsAuthorizedDesktopFile()
+{
+ QTemporaryFile file("testAuthXXXXXX.desktop");
+ QVERIFY( file.open() );
+ const QString fileName = file.fileName();
+ QTextStream ts( &file );
+ ts <<
+ "[Desktop Entry]\n"
+ "Type=Application\n"
+ "Name=My Application\n"
+ "Exec=kfoo\n"
+ "\n";
+ file.close();
+ QVERIFY(QFile::exists(fileName));
+ QVERIFY(!KDesktopFile::isAuthorizedDesktopFile(fileName));
+
+ const QString installedFile = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QLatin1String("/kde5/services/") + "http_cache_cleaner.desktop");
+ if (!installedFile.isEmpty()) {
+ QVERIFY(KDesktopFile::isAuthorizedDesktopFile(installedFile));
+ } else {
+ qWarning("Skipping test for http_cache_cleaner.desktop, not found. kio not installed?");
+ }
+
+ const QString autostartFile = QStandardPaths::locate(QStandardPaths::GenericConfigLocation, QLatin1String("autostart/") + "plasma-desktop.desktop");
+ if (!autostartFile.isEmpty()) {
+ QVERIFY(KDesktopFile::isAuthorizedDesktopFile(autostartFile));
+ } else {
+ qWarning("Skipping test for plasma-desktop.desktop, not found. kde-workspace not installed?");
+ }
+}
diff --git a/tier1/kconfig/autotests/kdesktopfiletest.h b/tier1/kconfig/autotests/kdesktopfiletest.h
new file mode 100644
index 00000000..d57351fd
--- /dev/null
+++ b/tier1/kconfig/autotests/kdesktopfiletest.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2006 David Faure <faure@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License version 2 as published by the Free Software Foundation;
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef KDESKTOPFILETEST_H
+#define KDESKTOPFILETEST_H
+
+#include <QtCore/QObject>
+
+class KDesktopFileTest : public QObject
+{
+ Q_OBJECT
+private Q_SLOTS:
+ void testRead();
+ void testUnsuccessfulTryExec();
+ void testSuccessfulTryExec();
+ void testActionGroup();
+ void testIsAuthorizedDesktopFile();
+
+};
+
+#endif /* KDESKTOPFILETEST_H */
diff --git a/tier1/kconfig/autotests/kentrymaptest.cpp b/tier1/kconfig/autotests/kentrymaptest.cpp
new file mode 100644
index 00000000..9e926d65
--- /dev/null
+++ b/tier1/kconfig/autotests/kentrymaptest.cpp
@@ -0,0 +1,202 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2007 Thomas Braxton (kde.braxton@gmail.com)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "kentrymaptest.h"
+
+#include <QtTest>
+#include "kconfigdata.h"
+
+
+const QByteArray group1("A Group");
+const QByteArray key1("A Key");
+const QByteArray key2("Another Key");
+const QByteArray value1("A value");
+const QByteArray value2("A different value");
+
+QTEST_MAIN( KEntryMapTest )
+
+void KEntryMapTest::testKeyOrder()
+{
+ const KEntryKey groupMarker(group1);
+ const KEntryKey entry(group1, key1);
+ const KEntryKey localized(group1, key1, true, false);
+ const KEntryKey localizedDefault(group1, key1, true, true);
+ const KEntryKey defaultEntry(group1, key1, false, true);
+
+ // group marker should come before all entries
+ QVERIFY(groupMarker < entry);
+ QVERIFY(groupMarker < defaultEntry);
+ QVERIFY(groupMarker < localized);
+ QVERIFY(groupMarker < localizedDefault);
+
+ // localized should come before entry
+ QVERIFY(localized < entry);
+
+ // localized-default should come after localized entry
+ QVERIFY(localized < localizedDefault);
+
+ // localized-default should come before non-localized entry
+ QVERIFY(localizedDefault < entry);
+
+ // default should come after entry
+ QVERIFY(entry < defaultEntry);
+}
+
+void KEntryMapTest::testSimple()
+{
+ KEntryMap map;
+
+ map.setEntry(group1, key1, value1, EntryOptions());
+ QCOMPARE(map.size(), 2); // the group marker & 1 key
+ map.setEntry(group1, key2, value2, EntryOptions());
+ QCOMPARE(map.size(), 3); // the group marker & 2 keys
+
+ QVERIFY(map.findEntry(group1) != map.end());
+ QVERIFY(map.findEntry(group1.toLower()) == map.end());
+
+ QVERIFY(map.findEntry(group1, key1) != map.end());
+ QVERIFY(map.findEntry(group1, key1.toLower()) == map.end());
+ QVERIFY(map.findEntry(group1, key2) != map.end());
+ QVERIFY(map.findEntry(group1, key2.toUpper()) == map.end());
+
+ QByteArray found = map.findEntry(group1, key1)->mValue;
+ QVERIFY(found == value1);
+ QVERIFY(found != value2);
+
+ found = map.findEntry(group1, key2)->mValue;
+ QVERIFY(found != value1);
+ QVERIFY(found == value2);
+}
+
+void KEntryMapTest::testDirty()
+{
+ KEntryMap map;
+ bool ret = map.setEntry(group1, key1, value1, EntryDefault);
+ QCOMPARE(ret, true);
+ ret = map.setEntry(group1, key1, value1, EntryDefault);
+ QCOMPARE(ret, false);
+ ret = map.setEntry(group1, key2, value2, EntryOptions());
+ QCOMPARE(ret, true);
+ ret = map.setEntry(group1, key2, value2, EntryOptions());
+ QCOMPARE(ret, false);
+}
+
+void KEntryMapTest::testDefault()
+{
+ KEntryMap map;
+
+ map.setEntry(group1, key1, value1, EntryDefault);
+ QCOMPARE(map.size(), 3); // group marker, default, entry
+ map.setEntry(group1, key2, value2, EntryOptions());
+ QCOMPARE(map.size(), 4); // group marker, default1, entry1, entry2
+
+ const KEntryMap::ConstIterator defaultEntry(map.findEntry(group1, key1, SearchDefaults));
+ const KEntryMap::ConstIterator entry1(map.findEntry(group1, key1));
+ const KEntryMap::ConstIterator entry2(map.findEntry(group1, key2));
+
+ // default set for entry1
+ QVERIFY(defaultEntry != map.constEnd());
+ QCOMPARE(defaultEntry->mValue, entry1->mValue);
+
+ // no default set for entry2
+ QVERIFY(map.findEntry(group1, key2, SearchDefaults) == map.end());
+
+ // change from default
+ map.setEntry(group1, key1, value2, EntryOptions());
+ QVERIFY(defaultEntry->mValue != entry1->mValue);
+ QVERIFY(entry1 != entry2);
+ QCOMPARE(entry1->mValue, entry2->mValue);
+
+ // revert entry1
+ map.revertEntry(group1, key1);
+ QCOMPARE(defaultEntry->mValue, entry1->mValue);
+
+ // revert entry2, no default --> should be marked as deleted
+ map.revertEntry(group1, key2);
+ QCOMPARE(entry2->mValue, QByteArray());
+ QVERIFY(entry2->bDirty);
+ QVERIFY(entry2->bReverted);
+}
+
+void KEntryMapTest::testDelete()
+{
+ KEntryMap map;
+
+ map.setEntry(group1, key1, value1, EntryDefault);
+ map.setEntry(group1, key2, value2, EntryDefault);
+ QCOMPARE(map.size(), 5);
+
+ map.setEntry(group1, key2, QByteArray(), EntryDeleted|EntryDirty);
+ QCOMPARE(map.size(), 5); // entry should still be in map, so it can override merged entries later
+ QCOMPARE(map.findEntry(group1, key2)->mValue, QByteArray());
+}
+
+void KEntryMapTest::testGlobal()
+{
+ KEntryMap map;
+
+ map.setEntry(group1, key1, value1, EntryGlobal);
+ QCOMPARE(map.findEntry(group1, key1)->bGlobal, true);
+
+ // this should create a new key that is not "global"
+ map.setEntry(group1, key1, value2, EntryOptions());
+ QVERIFY(!map.findEntry(group1, key1)->bGlobal);
+}
+
+void KEntryMapTest::testImmutable()
+{
+ KEntryMap map;
+
+ map.setEntry(group1, key1, value1, EntryImmutable);
+ QCOMPARE(map.findEntry(group1, key1)->bImmutable, true); // verify the immutable bit was set
+
+ map.setEntry(group1, key1, value2, EntryOptions());
+ QCOMPARE(map.findEntry(group1, key1)->mValue, value1); // verify the value didn't change
+
+ map.clear();
+
+ map.setEntry(group1, QByteArray(), QByteArray(), EntryImmutable);
+ QCOMPARE(map.findEntry(group1)->bImmutable, true); // verify the group is immutable
+
+ map.setEntry(group1, key1, value1, EntryOptions()); // should be ignored since the group is immutable
+ QVERIFY(map.findEntry(group1, key1) == map.end());
+}
+
+void KEntryMapTest::testLocale()
+{
+ const QByteArray translatedDefault("hola");
+ const QByteArray translated("bonjour");
+ const QByteArray untranslated("hello");
+ KEntryMap map;
+
+ map.setEntry(group1, key1, untranslated, EntryDefault);
+ QCOMPARE(map.findEntry(group1, key1)->mValue, untranslated);
+ QCOMPARE(map.findEntry(group1, key1, SearchLocalized)->mValue, untranslated); // no localized value yet
+
+ map.setEntry(group1, key1, translated, EntryLocalized);
+
+ QCOMPARE(map.findEntry(group1, key1, SearchLocalized)->mValue, translated); // has localized value now
+ QVERIFY(map.findEntry(group1, key1, SearchLocalized)->mValue != map.findEntry(group1, key1)->mValue);
+ QCOMPARE(map.findEntry(group1, key1, SearchDefaults|SearchLocalized)->mValue, untranslated); // default should still be untranslated
+
+ map.setEntry(group1, key1, translatedDefault, EntryDefault|EntryLocalized);
+ QCOMPARE(map.findEntry(group1, key1, SearchLocalized)->mValue, translatedDefault);
+ map.setEntry(group1, key1, translated, EntryLocalized); // set the translated entry to a different locale
+ QCOMPARE(map.findEntry(group1, key1, SearchLocalized)->mValue, translated);
+}
diff --git a/tier1/kconfig/autotests/kentrymaptest.h b/tier1/kconfig/autotests/kentrymaptest.h
new file mode 100644
index 00000000..2855b5c4
--- /dev/null
+++ b/tier1/kconfig/autotests/kentrymaptest.h
@@ -0,0 +1,57 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2007 Thomas Braxton (kde.braxton@gmail.com)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KENTRYMAPTEST_H
+#define KENTRYMAPTEST_H
+
+#include <QtCore/QObject>
+#include "kconfigdata.h"
+
+class KEntryMapTest : public QObject
+{
+ Q_OBJECT
+
+public:
+ typedef KEntryMap::EntryOptions EntryOptions;
+ typedef KEntryMap::SearchFlags SearchFlags;
+
+ typedef KEntryMap::SearchFlag SearchFlag;
+ static const SearchFlag SearchLocalized=KEntryMap::SearchLocalized;
+ static const SearchFlag SearchDefaults=KEntryMap::SearchDefaults;
+
+ typedef KEntryMap::EntryOption EntryOption;
+ static const EntryOption EntryDirty=KEntryMap::EntryDirty;
+ static const EntryOption EntryGlobal=KEntryMap::EntryGlobal;
+ static const EntryOption EntryImmutable=KEntryMap::EntryImmutable;
+ static const EntryOption EntryDeleted=KEntryMap::EntryDeleted;
+ static const EntryOption EntryExpansion=KEntryMap::EntryExpansion;
+ static const EntryOption EntryDefault=KEntryMap::EntryDefault;
+ static const EntryOption EntryLocalized=KEntryMap::EntryLocalized;
+private Q_SLOTS:
+ void testKeyOrder();
+ void testSimple();
+ void testDirty();
+ void testDefault();
+ void testDelete();
+ void testGlobal();
+ void testImmutable();
+ void testLocale();
+};
+
+#endif // KENTRYMAPTEST_H
diff --git a/tier1/kconfig/autotests/ksharedconfigtest.cpp b/tier1/kconfig/autotests/ksharedconfigtest.cpp
new file mode 100644
index 00000000..165322a3
--- /dev/null
+++ b/tier1/kconfig/autotests/ksharedconfigtest.cpp
@@ -0,0 +1,83 @@
+/*
+ This file is part of the KDE libraries
+ Copyright (c) 2012 David Faure <faure@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <QtTest>
+#include <ksharedconfig.h>
+#include <kconfiggroup.h>
+
+class KSharedConfigTest : public QObject
+{
+ Q_OBJECT
+private Q_SLOTS:
+ void initTestCase();
+ void testUnicity();
+ void testReadWrite();
+ void testReadWriteSync();
+private:
+ QString m_path;
+};
+
+void KSharedConfigTest::initTestCase()
+{
+ QStandardPaths::enableTestMode(true);
+
+ m_path = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + "/ksharedconfigtestrc";
+ QFile::remove(m_path);
+}
+
+void KSharedConfigTest::testUnicity()
+{
+ KSharedConfig::Ptr cfg1 = KSharedConfig::openConfig();
+ KSharedConfig::Ptr cfg2 = KSharedConfig::openConfig();
+ QCOMPARE(cfg1.data(), cfg2.data());
+}
+
+void KSharedConfigTest::testReadWrite()
+{
+ const int value = 1;
+ {
+ KConfigGroup cg(KSharedConfig::openConfig(), "KSharedConfigTest");
+ cg.writeEntry("NumKey", value);
+ }
+ {
+ KConfigGroup cg(KSharedConfig::openConfig(), "KSharedConfigTest");
+ QCOMPARE(cg.readEntry("NumKey", 0), 1);
+ }
+}
+
+void KSharedConfigTest::testReadWriteSync()
+{
+ const int value = 1;
+ {
+ KConfigGroup cg(KSharedConfig::openConfig(), "KSharedConfigTest");
+ cg.writeEntry("NumKey", value);
+ }
+ QVERIFY(!QFile::exists(m_path));
+ QVERIFY(KSharedConfig::openConfig()->sync());
+ QVERIFY(QFile::exists(m_path));
+ {
+ KConfigGroup cg(KSharedConfig::openConfig(), "KSharedConfigTest");
+ QCOMPARE(cg.readEntry("NumKey", 0), 1);
+ }
+}
+
+QTEST_MAIN(KSharedConfigTest)
+
+#include "ksharedconfigtest.moc"
diff --git a/tier1/kconfig/autotests/kstandardshortcuttest.cpp b/tier1/kconfig/autotests/kstandardshortcuttest.cpp
new file mode 100644
index 00000000..847cd074
--- /dev/null
+++ b/tier1/kconfig/autotests/kstandardshortcuttest.cpp
@@ -0,0 +1,59 @@
+/* This file is part of the KDE libraries
+ Copyright (c) 2005 David Faure <faure@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <QtTest/QtTest>
+#include "kstandardshortcuttest.h"
+
+QTEST_MAIN( KStandardShortcutTest) // GUI needed by KAccel
+
+#include <kstandardshortcut.h>
+
+void KStandardShortcutTest::testShortcutDefault()
+{
+ QCOMPARE( QKeySequence::listToString(KStandardShortcut::hardcodedDefaultShortcut( KStandardShortcut::FullScreen )), QLatin1String( "Ctrl+Shift+F" ) );
+ QCOMPARE( QKeySequence::listToString(KStandardShortcut::hardcodedDefaultShortcut( KStandardShortcut::BeginningOfLine )), QLatin1String( "Home" ) );
+ QCOMPARE( QKeySequence::listToString(KStandardShortcut::hardcodedDefaultShortcut( KStandardShortcut::EndOfLine )), QLatin1String( "End" ) );
+ QCOMPARE( QKeySequence::listToString(KStandardShortcut::hardcodedDefaultShortcut( KStandardShortcut::Home )), QLatin1String( "Alt+Home; Home Page" ) );
+}
+
+void KStandardShortcutTest::testName()
+{
+ QCOMPARE( KStandardShortcut::name( KStandardShortcut::BeginningOfLine ), QLatin1String( "BeginningOfLine" ) );
+ QCOMPARE( KStandardShortcut::name( KStandardShortcut::EndOfLine ), QLatin1String( "EndOfLine" ) );
+ QCOMPARE( KStandardShortcut::name( KStandardShortcut::Home ), QLatin1String( "Home" ) );
+}
+
+void KStandardShortcutTest::testLabel()
+{
+ // Tests run in English, right?
+ QCOMPARE( KStandardShortcut::label( KStandardShortcut::FindNext ), QLatin1String( "Find Next" ) );
+ QCOMPARE( KStandardShortcut::label( KStandardShortcut::Home ), QLatin1String( "Home" ) );
+}
+
+void KStandardShortcutTest::testShortcut()
+{
+ QCOMPARE( QKeySequence::listToString(KStandardShortcut::shortcut( KStandardShortcut::ZoomIn )), QKeySequence::listToString(KStandardShortcut::zoomIn()) );
+}
+
+void KStandardShortcutTest::testFindStdAccel()
+{
+ QCOMPARE( KStandardShortcut::find( QString( "Ctrl+F" ) ), KStandardShortcut::Find );
+ QCOMPARE( KStandardShortcut::find( QString( "Ctrl+Shift+Alt+G" ) ), KStandardShortcut::AccelNone );
+}
+
diff --git a/tier1/kconfig/autotests/kstandardshortcuttest.h b/tier1/kconfig/autotests/kstandardshortcuttest.h
new file mode 100644
index 00000000..91be854b
--- /dev/null
+++ b/tier1/kconfig/autotests/kstandardshortcuttest.h
@@ -0,0 +1,38 @@
+/* This file is part of the KDE libraries
+ Copyright (c) 2005 David Faure <faure@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KSTDACCELTEST_H
+#define KSTDACCELTEST_H
+
+#include <QtCore/QObject>
+
+class KStandardShortcutTest : public QObject
+{
+ Q_OBJECT
+private Q_SLOTS:
+ // KStandardShortcut tests
+ void testShortcutDefault();
+ void testName();
+ void testLabel();
+ void testShortcut();
+ void testFindStdAccel();
+};
+
+
+#endif
diff --git a/tier1/kconfig/autotests/test_kconf_update.cpp b/tier1/kconfig/autotests/test_kconf_update.cpp
new file mode 100644
index 00000000..8fae1c74
--- /dev/null
+++ b/tier1/kconfig/autotests/test_kconf_update.cpp
@@ -0,0 +1,553 @@
+/* This file is part of the KDE libraries
+ Copyright 2010 Canonical Ltd
+ Author: Aurélien Gâteau <aurelien.gateau@canonical.com>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License (LGPL) as published by the Free Software Foundation;
+ either version 2 of the License, or (at your option) any later
+ version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#include "test_kconf_update.h"
+
+// Qt
+#include <QFile>
+#include <QDir>
+#include <QSharedPointer>
+#include <QtCore/QProcess>
+#include <qtemporaryfile.h>
+#include <qstandardpaths.h>
+#include "config-kconf.h"
+
+#include <qtest.h>
+
+// QT5 TODO QTEST_GUILESS_MAIN(TestKConfUpdate)
+QTEST_MAIN(TestKConfUpdate)
+
+static void writeFile(const QString &path, const QString &content)
+{
+ QFile file(path);
+ bool ok = file.open(QIODevice::WriteOnly);
+ Q_UNUSED(ok) // silence warnings
+ Q_ASSERT(ok);
+ file.write(content.toUtf8());
+}
+
+static QString readFile(const QString &path)
+{
+ QFile file(path);
+ bool ok = file.open(QIODevice::ReadOnly);
+ Q_UNUSED(ok) // silence warnings
+ Q_ASSERT(ok);
+ return QString::fromUtf8(file.readAll());
+}
+
+static QTemporaryFile* writeUpdFile(const QString &content)
+{
+ QTemporaryFile* file = new QTemporaryFile(QDir::tempPath() + QLatin1String("/test_kconf_update_XXXXXX.upd"));
+ bool ok = file->open();
+ Q_UNUSED(ok) // silence warnings
+ Q_ASSERT(ok);
+ file->write(content.toUtf8());
+ file->flush();
+ return file;
+}
+
+static void runKConfUpdate(const QString &updPath)
+{
+ QString exePath = KCONF_UPDATE_BINARY_DIR "/kconf_update";
+ QVERIFY(QFile::exists(exePath));
+ QProcess::execute(exePath, QStringList() << "--debug" << updPath);
+}
+
+void TestKConfUpdate::test_data()
+{
+ QTest::addColumn<QString>("updContent");
+ QTest::addColumn<QString>("oldConfName");
+ QTest::addColumn<QString>("oldConfContent");
+ QTest::addColumn<QString>("newConfName");
+ QTest::addColumn<QString>("expectedNewConfContent");
+ QTest::addColumn<QString>("expectedOldConfContent");
+
+ QTest::newRow("moveKeysSameFile")
+ <<
+ "File=testrc\n"
+ "Group=group\n"
+ "Key=old,new\n"
+ "Options=overwrite\n"
+ <<
+ "testrc"
+ <<
+ "[group]\n"
+ "old=value\n"
+ <<
+ "testrc"
+ <<
+ "[$Version]\n"
+ "update_info=%1\n"
+ "\n"
+ "[group]\n"
+ "new=value\n"
+ <<
+ ""
+ ;
+ QTest::newRow("moveKeysOtherFile")
+ <<
+ "File=oldrc,newrc\n"
+ "Group=group1,group2\n"
+ "Key=old,new\n"
+ "Options=overwrite\n"
+ <<
+ "oldrc"
+ <<
+ "[group1]\n"
+ "old=value\n"
+ "[stay]\n"
+ "foo=bar\n"
+ <<
+ "newrc"
+ <<
+ "[$Version]\n"
+ "update_info=%1\n"
+ "\n"
+ "[group2]\n"
+ "new=value\n"
+ <<
+ "[$Version]\n"
+ "update_info=%1\n"
+ "\n"
+ "[stay]\n"
+ "foo=bar\n"
+ ;
+ QTest::newRow("allKeys")
+ <<
+ "File=testrc\n"
+ "Group=group1,group2\n"
+ "AllKeys\n"
+ <<
+ "testrc"
+ <<
+ "[group1]\n"
+ "key1=value1\n"
+ "key2=value2\n"
+ "\n"
+ "[stay]\n"
+ "foo=bar\n"
+ <<
+ "testrc"
+ <<
+ "[$Version]\n"
+ "update_info=%1\n"
+ "\n"
+ "[group2]\n"
+ "key1=value1\n"
+ "key2=value2\n"
+ "\n"
+ "[stay]\n"
+ "foo=bar\n"
+ <<
+ ""
+ ;
+ QTest::newRow("allKeysSubGroup")
+ <<
+ "File=testrc\n"
+ "Group=[group][sub1],[group][sub2]\n"
+ "AllKeys\n"
+ <<
+ "testrc"
+ <<
+ "[group][sub1]\n"
+ "key1=value1\n"
+ "key2=value2\n"
+ "\n"
+ "[group][sub1][subsub]\n"
+ "key3=value3\n"
+ "key4=value4\n"
+ "\n"
+ "[stay]\n"
+ "foo=bar\n"
+ <<
+ "testrc"
+ <<
+ "[$Version]\n"
+ "update_info=%1\n"
+ "\n"
+ "[group][sub2]\n"
+ "key1=value1\n"
+ "key2=value2\n"
+ "\n"
+ "[group][sub2][subsub]\n"
+ "key3=value3\n"
+ "key4=value4\n"
+ "\n"
+ "[stay]\n"
+ "foo=bar\n"
+ <<
+ ""
+ ;
+ QTest::newRow("removeGroup")
+ <<
+ "File=testrc\n"
+ "RemoveGroup=remove\n"
+ <<
+ "testrc"
+ <<
+ "[keep]\n"
+ "key=value\n"
+ ""
+ "[remove]\n"
+ "key=value\n"
+ <<
+ "testrc"
+ <<
+ "[$Version]\n"
+ "update_info=%1\n"
+ "\n"
+ "[keep]\n"
+ "key=value\n"
+ <<
+ ""
+ ;
+ QTest::newRow("moveKeysSameFileDontExist")
+ <<
+ "File=testrc\n"
+ "Group=group,group2\n"
+ "Key=key1\n"
+ "Key=key2\n"
+ <<
+ "testrc"
+ <<
+ "[group]\n"
+ "key1=value1\n"
+ "key3=value3\n"
+ <<
+ "testrc"
+ <<
+ "[$Version]\n"
+ "update_info=%1\n"
+ "\n"
+ "[group]\n"
+ "key3=value3\n"
+ "\n"
+ "[group2]\n"
+ "key1=value1\n"
+ <<
+ ""
+ ;
+}
+
+void TestKConfUpdate::test()
+{
+ QFETCH(QString, updContent);
+ QFETCH(QString, oldConfName);
+ QFETCH(QString, oldConfContent);
+ QFETCH(QString, newConfName);
+ QFETCH(QString, expectedNewConfContent);
+ QFETCH(QString, expectedOldConfContent);
+
+ // Prepend the Id= field to the upd content
+ updContent = QString("Id=%1\n").arg(QTest::currentDataTag()) + updContent;
+
+ QString oldConfPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + QLatin1Char('/') + oldConfName;
+ QString newConfPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + QLatin1Char('/') + newConfName;
+
+ QFile::remove(oldConfPath);
+ QFile::remove(newConfPath);
+
+ writeFile(oldConfPath, oldConfContent);
+ QSharedPointer<QTemporaryFile> updFile(writeUpdFile(updContent));
+ runKConfUpdate(updFile->fileName());
+
+ QString updateInfo = QString("%1:%2")
+ .arg(updFile->fileName().section('/', -1))
+ .arg(QTest::currentDataTag());
+
+ QString newConfContentAfter = readFile(newConfPath);
+ expectedNewConfContent = expectedNewConfContent.arg(updateInfo);
+ QCOMPARE(newConfContentAfter, expectedNewConfContent);
+
+ if (oldConfName != newConfName) {
+ QString oldConfContentAfter = readFile(oldConfPath);
+ expectedOldConfContent = expectedOldConfContent.arg(updateInfo);
+ QCOMPARE(oldConfContentAfter, expectedOldConfContent);
+ }
+}
+
+void TestKConfUpdate::testScript_data()
+{
+ QTest::addColumn<QString>("updContent");
+ QTest::addColumn<QString>("updScript");
+ QTest::addColumn<QString>("oldConfContent");
+ QTest::addColumn<QString>("expectedNewConfContent");
+
+ QTest::newRow("delete-key")
+ <<
+ "File=testrc\n"
+ "Group=group\n"
+ "Script=test.sh,sh\n"
+ <<
+ "echo '# DELETE deprecated'\n"
+ <<
+ "[group]\n"
+ "deprecated=foo\n"
+ "valid=bar\n"
+ <<
+ "[$Version]\n"
+ "update_info=%1\n"
+ "\n"
+ "[group]\n"
+ "valid=bar\n"
+ ;
+
+ QTest::newRow("delete-key2")
+ <<
+ "File=testrc\n"
+ "Script=test.sh,sh\n"
+ <<
+ "echo '# DELETE [group]deprecated'\n"
+ "echo '# DELETE [group][sub]deprecated2'\n"
+ <<
+ "[group]\n"
+ "deprecated=foo\n"
+ "valid=bar\n"
+ "\n"
+ "[group][sub]\n"
+ "deprecated2=foo\n"
+ "valid2=bar\n"
+ <<
+ "[$Version]\n"
+ "update_info=%1\n"
+ "\n"
+ "[group]\n"
+ "valid=bar\n"
+ "\n"
+ "[group][sub]\n"
+ "valid2=bar\n"
+ ;
+
+ QTest::newRow("delete-group")
+ <<
+ "File=testrc\n"
+ "Script=test.sh,sh\n"
+ <<
+ "echo '# DELETEGROUP [group1]'\n"
+ "echo '# DELETEGROUP [group2][sub]'\n"
+ <<
+ "[group1]\n"
+ "key=value\n"
+ "\n"
+ "[group2]\n"
+ "valid=bar\n"
+ "\n"
+ "[group2][sub]\n"
+ "key=value\n"
+ <<
+ "[$Version]\n"
+ "update_info=%1\n"
+ "\n"
+ "[group2]\n"
+ "valid=bar\n"
+ ;
+
+ QTest::newRow("delete-group2")
+ <<
+ "File=testrc\n"
+ "Group=group\n"
+ "Script=test.sh,sh\n"
+ <<
+ "echo '# DELETEGROUP'\n"
+ <<
+ "[group]\n"
+ "key=value\n"
+ "\n"
+ "[group2]\n"
+ "valid=bar\n"
+ <<
+ "[$Version]\n"
+ "update_info=%1\n"
+ "\n"
+ "[group2]\n"
+ "valid=bar\n"
+ ;
+
+ QTest::newRow("new-key")
+ <<
+ "File=testrc\n"
+ "Script=test.sh,sh\n"
+ <<
+ "echo '[group]'\n"
+ "echo 'new=value'\n"
+ <<
+ "[group]\n"
+ "valid=bar\n"
+ <<
+ "[$Version]\n"
+ "update_info=%1\n"
+ "\n"
+ "[group]\n"
+ "new=value\n"
+ "valid=bar\n"
+ ;
+
+ QTest::newRow("modify-key-no-overwrite")
+ <<
+ "File=testrc\n"
+ "Script=test.sh,sh\n"
+ <<
+ "echo '[group]'\n"
+ "echo 'existing=new'\n"
+ <<
+ "[group]\n"
+ "existing=old\n"
+ <<
+ "[$Version]\n"
+ "update_info=%1\n"
+ "\n"
+ "[group]\n"
+ "existing=old\n"
+ ;
+
+ QTest::newRow("modify-key-overwrite")
+ <<
+ "File=testrc\n"
+ "Options=overwrite\n"
+ "Script=test.sh,sh\n"
+ <<
+ "echo '[group]'\n"
+ "echo 'existing=new'\n"
+ <<
+ "[group]\n"
+ "existing=old\n"
+ <<
+ "[$Version]\n"
+ "update_info=%1\n"
+ "\n"
+ "[group]\n"
+ "existing=new\n"
+ ;
+
+ QTest::newRow("new-key-in-subgroup")
+ <<
+ "File=testrc\n"
+ "Script=test.sh,sh\n"
+ <<
+ "echo '[group][sub]'\n"
+ "echo 'new=value2'\n"
+ <<
+ "[group][sub]\n"
+ "existing=foo\n"
+ <<
+ "[$Version]\n"
+ "update_info=%1\n"
+ "\n"
+ "[group][sub]\n"
+ "existing=foo\n"
+ "new=value2\n"
+ ;
+
+ QTest::newRow("new-key-in-subgroup2")
+ <<
+ "File=testrc\n"
+ "Script=test.sh,sh\n"
+ <<
+ "echo '[group][sub]'\n"
+ "echo 'new=value3'\n"
+ <<
+ "[group][sub]\n"
+ "existing=foo\n"
+ <<
+ "[$Version]\n"
+ "update_info=%1\n"
+ "\n"
+ "[group][sub]\n"
+ "existing=foo\n"
+ "new=value3\n"
+ ;
+
+ QTest::newRow("filter")
+ <<
+ "File=testrc\n"
+ "Script=test.sh,sh\n"
+ <<
+ "echo '# DELETE [group]changed'\n"
+ "sed s/value/VALUE/\n"
+ <<
+ "[group]\n"
+ "changed=value\n"
+ "unchanged=value\n"
+ <<
+ "[$Version]\n"
+ "update_info=%1\n"
+ "\n"
+ "[group]\n"
+ "changed=VALUE\n"
+ "unchanged=value\n"
+ ;
+
+ QTest::newRow("filter-subgroup")
+ <<
+ "File=testrc\n"
+ "Script=test.sh,sh\n"
+ <<
+ "echo '# DELETE [group][sub]changed'\n"
+ "sed s/value/VALUE/\n"
+ <<
+ "[group]\n"
+ "unchanged=value\n"
+ "\n"
+ "[group][sub]\n"
+ "changed=value\n"
+ "unchanged=value\n"
+ <<
+ "[$Version]\n"
+ "update_info=%1\n"
+ "\n"
+ "[group]\n"
+ "unchanged=value\n"
+ "\n"
+ "[group][sub]\n"
+ "changed=VALUE\n"
+ "unchanged=value\n"
+ ;
+}
+
+void TestKConfUpdate::testScript()
+{
+ QFETCH(QString, updContent);
+ QFETCH(QString, updScript);
+ QFETCH(QString, oldConfContent);
+ QFETCH(QString, expectedNewConfContent);
+
+ // Prepend the Id= field to the upd content
+ updContent = QString("Id=%1\n").arg(QTest::currentDataTag()) + updContent;
+
+ QSharedPointer<QTemporaryFile> updFile(writeUpdFile(updContent));
+
+ const QString scriptDir = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/kconf_update";
+ QVERIFY(QDir().mkpath(scriptDir));
+ QString scriptPath = scriptDir + "/test.sh";
+ writeFile(scriptPath, updScript);
+
+ QString confPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + QLatin1Char('/') + "testrc";
+ writeFile(confPath, oldConfContent);
+
+ runKConfUpdate(updFile->fileName());
+
+ QString updateInfo = QString("%1:%2")
+ .arg(updFile->fileName().section('/', -1))
+ .arg(QTest::currentDataTag());
+ QString newConfContent = readFile(confPath);
+ expectedNewConfContent = expectedNewConfContent.arg(updateInfo);
+ QCOMPARE(newConfContent, expectedNewConfContent);
+}
+
diff --git a/tier1/kconfig/autotests/test_kconf_update.h b/tier1/kconfig/autotests/test_kconf_update.h
new file mode 100644
index 00000000..1b3151f1
--- /dev/null
+++ b/tier1/kconfig/autotests/test_kconf_update.h
@@ -0,0 +1,36 @@
+/* This file is part of the KDE libraries
+ Copyright 2010 Canonical Ltd
+ Author: Aurélien Gâteau <aurelien.gateau@canonical.com>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License (LGPL) as published by the Free Software Foundation;
+ either version 2 of the License, or (at your option) any later
+ version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#ifndef TEST_KCONF_UPDATE_H
+#define TEST_KCONF_UPDATE_H
+
+#include <QObject>
+
+class TestKConfUpdate : public QObject
+{
+ Q_OBJECT
+private Q_SLOTS:
+ void test_data();
+ void test();
+ void testScript_data();
+ void testScript();
+};
+
+#endif /* TEST_KCONF_UPDATE_H */
diff --git a/tier1/kconfig/autotests/test_kconfigutils.cpp b/tier1/kconfig/autotests/test_kconfigutils.cpp
new file mode 100644
index 00000000..176d771f
--- /dev/null
+++ b/tier1/kconfig/autotests/test_kconfigutils.cpp
@@ -0,0 +1,149 @@
+/* This file is part of the KDE libraries
+ Copyright 2010 Canonical Ltd
+ Author: Aurélien Gâteau <aurelien.gateau@canonical.com>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License (LGPL) as published by the Free Software Foundation;
+ either version 2 of the License, or (at your option) any later
+ version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#include "test_kconfigutils.h"
+
+#include <qdebug.h>
+#include <qtest.h>
+
+// Local
+#include "kconfigutils.h"
+
+// QT5 TODO QTEST_GUILESS_MAIN(TestKConfigUtils)
+QTEST_MAIN(TestKConfigUtils)
+
+void TestKConfigUtils::testParseGroupString_data()
+{
+ QTest::addColumn<QString>("input");
+ QTest::addColumn<QStringList>("expected");
+ QTest::addColumn<bool>("expectedOk");
+
+ QTest::newRow("simple-group")
+ << " group "
+ << (QStringList() << "group")
+ << true
+ ;
+
+ QTest::newRow("sub-group")
+ << "[group][sub]"
+ << (QStringList() << "group" << "sub")
+ << true
+ ;
+
+ QTest::newRow("crazy-sub-group")
+ << "[a\\ttab\\x5d[and some hex esc\\x61pe]"
+ << (QStringList() << "a\ttab" << "and some hex escape")
+ << true
+ ;
+
+ QTest::newRow("missing-closing-brace")
+ << "[group][sub"
+ << QStringList()
+ << false
+ ;
+}
+
+void TestKConfigUtils::testParseGroupString()
+{
+ QFETCH(QString, input);
+ QFETCH(QStringList, expected);
+ QFETCH(bool, expectedOk);
+
+ bool ok;
+ QString error;
+ QStringList output = KConfigUtils::parseGroupString(input, &ok, &error);
+ QCOMPARE(output, expected);
+ QCOMPARE(ok, expectedOk);
+ if (ok) {
+ QVERIFY(error.isEmpty());
+ } else {
+ QVERIFY(!error.isEmpty());
+ qDebug() << error;
+ }
+}
+
+void TestKConfigUtils::testUnescapeString_data()
+{
+ QTest::addColumn<QString>("input");
+ QTest::addColumn<QString>("expected");
+ QTest::addColumn<bool>("expectedOk");
+
+ QTest::newRow("plain")
+ << "Some text"
+ << "Some text"
+ << true
+ ;
+
+ QTest::newRow("single-char-escapes")
+ << "01\\s23\\t45\\n67\\r89\\\\"
+ << "01 23\t45\n67\r89\\"
+ << true
+ ;
+
+ QTest::newRow("hex-escapes")
+ << "kd\\x65"
+ << "kde"
+ << true
+ ;
+
+ QTest::newRow("unfinished-hex-escape")
+ << "kd\\x6"
+ << ""
+ << false
+ ;
+
+ QTest::newRow("invalid-hex-escape")
+ << "kd\\xzz"
+ << ""
+ << false
+ ;
+
+ QTest::newRow("invalid-escape-sequence")
+ << "Foo\\a"
+ << ""
+ << false
+ ;
+
+ QTest::newRow("unfinished-escape-sequence")
+ << "Foo\\"
+ << ""
+ << false
+ ;
+}
+
+void TestKConfigUtils::testUnescapeString()
+{
+ QFETCH(QString, input);
+ QFETCH(QString, expected);
+ QFETCH(bool, expectedOk);
+
+ bool ok;
+ QString error;
+ QString output = KConfigUtils::unescapeString(input, &ok, &error);
+ QCOMPARE(output, expected);
+ QCOMPARE(ok, expectedOk);
+ if (ok) {
+ QVERIFY(error.isEmpty());
+ } else {
+ QVERIFY(!error.isEmpty());
+ qDebug() << error;
+ }
+}
+
diff --git a/tier1/kconfig/autotests/test_kconfigutils.h b/tier1/kconfig/autotests/test_kconfigutils.h
new file mode 100644
index 00000000..2b8c5762
--- /dev/null
+++ b/tier1/kconfig/autotests/test_kconfigutils.h
@@ -0,0 +1,36 @@
+/* This file is part of the KDE libraries
+ Copyright 2010 Canonical Ltd
+ Author: Aurélien Gâteau <aurelien.gateau@canonical.com>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License (LGPL) as published by the Free Software Foundation;
+ either version 2 of the License, or (at your option) any later
+ version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#ifndef TEST_KCONFIGUTILS_H
+#define TEST_KCONFIGUTILS_H
+
+#include <QObject>
+
+class TestKConfigUtils : public QObject
+{
+ Q_OBJECT
+private Q_SLOTS:
+ void testParseGroupString_data();
+ void testParseGroupString();
+ void testUnescapeString_data();
+ void testUnescapeString();
+};
+
+#endif /* TEST_KCONFIGUTILS_H */
diff --git a/tier1/kconfig/docs/DESIGN.kconfig b/tier1/kconfig/docs/DESIGN.kconfig
new file mode 100644
index 00000000..1aa0a3f8
--- /dev/null
+++ b/tier1/kconfig/docs/DESIGN.kconfig
@@ -0,0 +1,224 @@
+kconfigdata.h contains definitions of the data formats used by kconfig.
+
+Configuration entries are stored as "KEntry". They are indexed with "KEntryKey".
+The primary store is a "KEntryMap" which is defined as a QMap from "KEntryKey"
+to "KEntry"
+
+KEntry's are stored in order in the KEntryMap. The most significant sort
+criteria is mGroup. This means that all entries who belong in the same group,
+are grouped in the QMap as well.
+
+The start of a group is indicated with a KEntryKey with an empty mKey and a
+dummy KEntry. This allows us to search for the start of the group and then to
+iterate until we end up in another group. That way we will find all entries
+of a certain group.
+
+Entries that are localised with the _current_ locale are stored with bLocal
+set to true. Entries that are localised with another locale are either not
+stored at all (default), or with the localization as part of the key (when
+reading a file in order to merge it).
+[WABA: Does it make sense to keep both localized and non-localised around?
+Can't we just let the localised version override the non-localised version?]
+
+Currently the localization bit is the least significant sort criteria, that
+means that the localised version always follows the non-localised version
+immediately.
+
+<Changed for KDE 3.0>
+Entries that are being read from a location other than the location to
+which is written back are marked as "default" and will be added both as
+normal entry as well as an entry with the key marked as default.
+
+When entries are written to disk, it is checked whether the entry to write
+is equal to the default, if so the entry will not be written. The default
+entry always follows directly after the normal entry, due to the sorting.
+(After that the localised version follows)
+
+When entries are written to disk, it is checked whether the entry to write
+is equal to the default, if so the entry will not be written.
+</Changed>
+
+Open question:
+Should unmodified entries that are written back be compared with the default
+too? This seems to be mostly a transition issue.
+
+<Changed during KDE 3.0 / 3.2>
+Extra functions:
+
+bool isEntryImmutable(key); // Can entry be modified?
+bool hasDefault(key); // Is there a system wide default set for the entry?
+void revertToDefault(key); // Restore to default
+void deleteEntry(key); // Remove entry
+
+Note that there is a subtle difference between revertToDefault() and deleteEntry().
+revertToDefault() will change the entry to the default value set by the system
+administrator (Via e.g. $KDEDIR/share/config) or, if no such default was set,
+non-existant.
+deleteEntry() will make the entry non-existant.
+
+Entries are marked "immutable" if the key is followed by [$i]. This means
+that a user can not override these entries.
+
+Entries can be marked as deleted if they are followed by [$d]. This
+is needed if the system administrator has specified a default value but the
+entry was deleted (made 'non-existant'). In that case we can't just leave
+the entry out since that would mean we get the default from the system
+administrator back the next time we read the file.
+</changed>
+
+When an entry is read with readEntry(key, defaultValue), non-existing
+entries will return "defaultValue" while hasKey(key) will return "false"
+for such entries.
+
+Currently all entries are stored in memory. When KConfig is "sync()'ed"
+it reads the file that it is about to overwrite (for the second time), it
+then merges in the entries it has in memory and writes the result back to
+the file. It does NOT update its map of entries in memory with the entries
+(re)read from disk. It only updates the entries in memory when
+"reparseConfiguration()" is called.
+
+
+Open Question: The standard writeEntry() function returns the original value,
+is this needed? Nobody seems to use it.
+
+Open Question: The bPersistent flag doesn't seem to be used... could it be removed?
+
+Open Question: Is the bNLS flag needed? Localised entries seem to be mostly
+useful for default files, are they ever created by the user itself?
+
+Open Question: Would it be worthwhile to lock a user option that is equal to the
+default so that it doesn't change when the default changes?
+
+
+KDE3.0 Changes
+==============
+
+*) writeEntry now returns void instead of QString.
+*) deleteEntry functions added
+
+
+------------------------------------------------------------------------------
+
+KConfig XT
+==========
+
+My buzzword picker offered KConfig XT ("eXtended Technology") and KConfig NG
+("Next Generation"). Since the planned changes are ment to be evolutionary
+rather than revolutionary, KConfig NG was dropped.
+
+Goals
+=====
+
+* Have the default value for config entries defined in 1 place. Currently it is
+not uncommon to have them defined in three places:
+ 1) In the application that reads the setting in order to use it
+ 2) In the settings dialog when reading the setting
+ 3) In the settings dialog when selecting "Use defaults".
+
+* Provide type-information about config entries to facilate "KConfEdit" like
+tools. Ideally type-information also includes range-information; this is even
+mandatory if enums become an explicit type.
+
+* Facilitate the documentation of config entries.
+
+
+Instead of relying on the defaults that are hard-coded in the application,
+rely on default configuration files being installed in $KDEDIR. The technical
+changes required for this are very minimal, it is mostly a change in policy.
+
+Type information can be provide by preceding every entry with a formalized
+comment.
+
+Work to be done:
+* KConfig needs to be extended to provide access to the default values provided
+by the default config files. KConfig already stores this information internally.
+(DONE)
+* A formal comment structure needs to be designed that can convey type-information.
+Preferably in such a way that it is easily parsable by both machine and user.
+* KConfig needs to be extended, or another class created, that is able to parse
+the formalized comments.
+* A tool needs to be developed that can assist developers with the generation
+and verification of default configuration files including type-information.
+
+Drawbacks:
+* We rely on default configuration files being properly installed.
+* The user can break applications by making improper modifications to these
+files.
+* It is not possible to store defaults settings in a config file that are
+of a dynamic nature. Examples are settings derived from other settings,
+e.g. a color setting could be derived from the current color theme, or
+e.g. the default high score user name which is determined by the user
+currently logged in.
+
+
+Some random ideas:
+* The format of the entries would be something like this:
+
+[Mail Settings]
+#!Type=string
+#!Description=SMTP server to use for sending mail
+#!Description[nl]=SMTP server voor het versturen van mail
+Host=wantelbos.zogje.fr
+
+- the type could be subclassed more, e.g. strings can be "email", "hostname",
+ "url", etc.
+
+- having translations in these files is very arguable. external po's would be
+ better.
+
+
+
+Class overview
+
+ KConfigBase
+ |
+ v
+ KConfigBackend <-----> KConfig <------> KConfigSkeleton /--< myapp.kcfg
+ | | | /
+ v v |*---------------<
+KConfigINIBackend KSimpleConfig |kconfig_compiler \
+ | \--< myconfig.kcfg-codegen
+ v
+ MyConfig <-----KConfigDialogManager----> MyConfigWidget *---< myconfigwidget.ui
+ uic
+
+KConfigBase: defines API for generic config class
+
+KConfig: functional generic config class that supports merging of cascaded
+ configuration files
+
+KSimpleConfig: functional generic config class without support for cascading
+ configuration files.
+
+KConfigBackend: defines API for config backend, t.i. the actual handling
+ of the storage method and storage format.
+
+KConfigINIBackend: the standard (and only one so far) class that implements
+ the config backend using the file-based .INI format
+ for configuration files
+
+KConfigSkeleton: base class for deriving classes that store application
+ specific options providing type-safety and single-point
+ defaults.
+
+MyConfig: An application specific class that offers configuration options
+ to the applications via variables or accessor functions and that
+ handles type-safety and defaults. MyConfig is just an example
+ name, the application developer choses the actual name.
+
+myapp.kcfg: File describing the configuration options used by a specific
+ application. myapp.kcfg is just an example name, the application
+ developer choses the actual name.
+
+myconfig.kcfg-codegen: Implementation specific code generation instructions
+ for the MyConfig class. myconfig.kcfg-codegen is
+ just an example name, the application developer
+ choses the actual name.
+
+KConfigDialogManager: Class that links widgets in a dialog up with their
+ corresponding confguration options in a configuration
+ object derived from KConfigSkeleton.
+
+MyConfigWidget: Dialog generated from a .ui description file. Widget names
+ in the dialog that start with "kcfg_" refer to configuration
+ options.
diff --git a/tier1/kconfig/docs/README.kiosk b/tier1/kconfig/docs/README.kiosk
new file mode 100644
index 00000000..4974acef
--- /dev/null
+++ b/tier1/kconfig/docs/README.kiosk
@@ -0,0 +1,817 @@
+In KDE-3 a kiosk-framework has been introduced.
+
+One of the driving forces behind KDE is to put the user in control and
+give him or her a large amount of possibilities to adjust KDE to his or her
+liking. However, in some situations it is required to reduce the possibilities
+of KDE, e.g. because the system is to be used for one or more specific
+dedicated tasks only.
+
+The kiosk-framework provides an easy way to disable certain features within
+KDE to create a more controlled environment.
+
+KDE's kiosk-framework builds on KDE's configuration framework and adds a
+simple application API that applications can query to get authorisation
+for certain operations.
+
+The KDE kiosk-framework should be used IN ADDITION to the standard UNIX
+security measures.
+
+The configuration framework in KDE
+==================================
+
+Since the very beginning KDE makes use of file-hierarchy to store resources
+for its applications. Resources range from icons, wallpapers, fonts to
+sounds, menu-descriptions and configuration files.
+
+In KDE1 there were two locations were resources could be located: The
+resources provided by the system were located under $KDEDIR and user-
+specific resources were located under $HOME/.kde.
+
+In KDE2 resource management has been largely abstracted by the introduction
+of the KStandardDirs class and has become much more flexible. The user /
+administrator can now specify a variable number of locations where resources
+can be found. A list of locations can either be specified via $KDEDIRS
+(notice the extra 'S'), via /etc/kde4rc and even via the kdeglobals config
+file. The location where user-specific resources can be found can be
+set with $KDEHOME (The default is $HOME/.kde). Changes made by the user
+are always written back to $KDEHOME.
+
+Both KDE1 and KDE2 feature so called "cascading configuration files": There
+can be multiple configuration files with the same name in the various
+locations for (config) resources, when that is the case, the information of
+all these configuration files is combined on a key by key basis. If the same
+key (within a certain group) is defined in more than one place, the value
+of the key for the config file that was read last will override any previously
+read values. Configuration files under $KDEHOME are always read last. This
+ensures that after a configuration entry is written, the same value wil be
+read back.
+
+In KDE3 two important changes have been made:
+
+* Default values are no longer written.
+When a configuration file in a location other than $KDEHOME defines a value
+for a key and the application subsequently writes out a new configuration file
+to $KDEHOME, that configuration file will only contain an entry for the key
+if its value differs from the value read from the other file.
+
+This counters the problem that changing default configuration files under
+$KDEDIR would not take effect for users, since these users would most likely
+have their own copy of these settings under $KDEHOME. KDE will make sure
+not to copy these settings so changes made under $KDEDIR will affect all users
+that haven't explicitly changed the affected settings to something else.
+
+* Configuration entries can be marked "immutable".
+Starting with KDE-3, configuration entries can be marked "immutable". When a
+configuration entry is immutable it means that configuration files that are
+read later will not be able to override its value. Immutable entries cannot
+be changed via KConfig and if the entry is present under $KDEHOME it will
+be ignored.
+
+Entries can be marked immutable on 4 different levels:
+
+- On an entry by entry basis by appending "[$i]" after the key.
+
+Example:
+[MyGroup]
+someKey[$i]=42
+
+- On a group by group basis by appending "[$i]" after the group. All entries
+specified in the group will be marked immutable and no new entries can be
+added to the group.
+
+Example:
+[MyGroup][$i]
+someKey=42
+
+- On a file by file basis by starting the file with [$i].
+
+Example:
+[$i]
+[MyGroup]
+someKey=42
+[MyOtherGroup]
+someOtherKey=11
+
+- On a directory basis. [Not yet implemented]
+
+- The filesystem can also be used to mark files immutable. If KDE does not
+have write-access to the user's version of a configuration file, the file
+will be automatically considered immutable.
+
+To make the configuration file of Dolphin immutable one could for
+example use the commands below.
+
+Example:
+chown root.root /home/user/.kde/share/config/dolphinrc
+chmod 644 /home/user/.kde/share/config/dolphinrc
+
+If you do this, the user will be warned that the configuration file is not
+writable. Since you will normally not want that, you can add the following
+two lines to the application's configuration file (or to kdeglobals to
+disable the warning for all applications):
+
+[KDE Action Restrictions]
+warn_unwritable_config=true
+
+Note that the above example is not fool-proof, the user can potentially still
+rename either the root-owned dolphinrc file or any of the directories in
+the path to another name and create a new dolphinrc _with_ write-access.
+
+KDE Action Restrictions
+=======================
+
+Most functionality within KDE is coupled to so called actions. For example when a user
+selects the File->Open option in the menubar of a KDE application, the "file_open"
+action is activated. Likewise, toolbar icons are usually also coupled to actions. KDE
+makes it possible to disable functionality by restricting specific actions. By restricting the
+"file_open" action for example, the corresponding entry in the menubar and the corresponding icon on
+the toolbar, if any, will disappear.
+
+To restrict access to function the kdeglobals file should contain the
+group "[KDE Action Restrictions]", each action can then be restricted by
+adding "<action>=false". E.g. to disable the action "shell_access" one
+would add:
+[KDE Action Restrictions][$i]
+shell_access=false
+
+Actions that refer to menu and toolbar actions are prefixed with 'action/'.
+The following standard actions are defined:
+
+action/file_new
+action/file_open
+action/file_open_recent
+action/file_save
+action/file_save_as
+action/file_revert
+action/file_close
+action/file_print
+action/file_print_preview
+action/file_mail
+action/file_quit
+action/edit_undo
+action/edit_redo
+action/edit_cut
+action/edit_copy
+action/edit_paste
+action/edit_select_all
+action/edit_deselect
+action/edit_find
+action/edit_find_next
+action/edit_find_last
+action/edit_replace
+action/view_actual_size
+action/view_fit_to_page
+action/view_fit_to_width
+action/view_fit_to_height
+action/view_zoom_in
+action/view_zoom_out
+action/view_zoom
+action/view_redisplay
+action/go_up
+action/go_back
+action/go_forward
+action/go_home
+action/go_previous
+action/go_next
+action/go_goto
+action/go_goto_page
+action/go_goto_line
+action/go_first
+action/go_last
+action/bookmarks // See note below
+action/bookmark_add
+action/bookmark_edit
+action/tools_spelling
+action/options_show_menubar
+action/options_show_toolbar // See note below
+action/options_show_statusbar
+action/options_save_options
+action/options_configure
+action/options_configure_keybinding
+action/options_configure_toolbars
+action/options_configure_notifications
+action/help // See note below
+action/help_contents
+action/help_whats_this
+action/help_report_bug
+action/help_about_app
+action/help_about_kde
+action/fullscreen
+
+Actions in the KDE File Dialog:
+action/home // Go to home directory
+action/up // Go to parent directory
+action/back // Go to previous directory
+action/forward // Go to next directory
+action/reload // Reload directory
+action/mkdir // Create new directory
+action/toggleSpeedbar // Show/hide sidebar
+action/sorting menu // Sorting options
+action/short view // Select short view
+action/detailed view // Select detailed view
+action/show hidden // Show/hide hidden files
+action/preview // Show/hide preview
+action/separate dirs // Show/hide separate directories
+
+
+Konqueror & KDesktop related:
+action/editfiletype
+action/properties
+action/openwith
+action/openintab
+action/kdesktop_rmb // RMB menu, see note below
+action/iconview_preview
+action/sharefile // File sharing, see note below
+action/sendURL // Send Link Address
+action/sendPage // Send File
+action/devnew // Create New -> Device
+action/incIconSize // Increase icon size
+action/decIconSize // Decrease icon size
+action/go // Entire go menu
+action/configdesktop // Configure desktop in RMB menu, see also Control Module Restrictions
+action/executeshellcommand // In Konqueror Tools menu, see also shell_access
+action/show_dot // Show Hidden Files, see note below
+
+
+Kicker related:
+action/kicker_rmb // RMB menu
+action/menuedit
+
+
+KWin related:
+action/kwin_rmb // RMB window context menu
+
+Konsole related:
+action/konsole_rmb // RMB context menu
+
+action/settings // Entire settings menu
+action/show_menubar
+action/show_toolbar
+action/scrollbar
+action/fullscreen
+action/bell
+action/font
+action/keyboard
+action/schema
+action/size
+action/history
+action/save_default
+action/save_sessions_profile
+action/options_configure_notifications
+action/options_configure_keybinding
+action/options_configure
+
+action/send_signal
+action/bookmarks
+action/add_bookmark
+action/edit_bookmarks
+action/clear_terminal
+action/reset_clear_terminal
+action/find_history
+action/find_next
+action/find_previous
+action/save_history
+action/clear_history
+action/clear_all_histories
+action/detach_session
+action/rename_session
+action/zmodem_upload
+action/monitor_activity
+action/monitor_silence
+action/send_input_to_all_sessions
+action/close_session
+action/new_session
+action/activate_menu
+action/list_sessions
+action/move_session_left
+action/move_session_right
+action/previous_session
+action/next_session
+action/switch_to_session_1
+action/switch_to_session_2
+action/switch_to_session_3
+action/switch_to_session_4
+action/switch_to_session_5
+action/switch_to_session_6
+action/switch_to_session_7
+action/switch_to_session_8
+action/switch_to_session_9
+action/switch_to_session_10
+action/switch_to_session_11
+action/switch_to_session_12
+action/bigger_font
+action/smaller_font
+action/toggle_bidi
+
+
+
+Notes:
+* action/options_show_toolbar will also disable the "Toolbars" submenu
+ if present.
+* action/bookmarks also disables action/bookmark_add and action/bookmark_edit
+* action/help is not yet fully implemented
+* action/kdesktop_rmb disables the RMB menu but some actions may still be accesible
+ via keyboard shortcuts: cut/copy/rename/trash/delete
+* action/iconview_preview disables the option to toggle previews on or off
+ in icon mode but the actual preview settings remains unaffected.
+ To disable previews you also need to add the following lines to
+ konqiconviewrc:
+ [Settings]
+ PreviewsEnabled[$i]=false
+* action/show_dot disables the option to toggle showing hidden files, the actual
+ setting remains unaffected.
+ To disable showing hidden files, add the following lines to konqiconviewrc:
+ [Settings]
+ ShowDotFiles[$i]=false
+* action/sharefile disables file sharing from the UI, but you may also want
+ to disable filesharing altogether.
+
+
+Applications may use additional actions that they defined themselves.
+You can get a list of the actions used by a certain applications by using the
+following qdbus command:
+
+qdbus org.kde.myapp-id | grep actions | cut -d '/' -f 4,5
+
+Actions that refer to applications that need to be run as a different user
+are prefixed by user/ and identified by the username. For example:
+
+user/root=false
+
+will disable all application entries that require root access.
+
+
+Printing related action restrictions:
+
+print/system
+ - disables the option to select the printing system (backend). It is
+ recommended to disable this option once the correct printing
+ system has been configured.
+
+print/properties
+ - disables the button to change printer properties or to add a new printer.
+
+print/options
+ - disables the button to select additional print options.
+
+print/copies
+ - disables the panel that allows users to make more than one copy.
+
+print/selection
+ - disables the options that allows selecting a (pseudo) printer or
+ change any of the printer properties. Make sure that a proper
+ default printer has been selected before disabling this option.
+ Disabling this option also disables print/system, print/options
+ and print/properties.
+
+print/dialog
+ - disables the complete print dialog. Selecting the print option will
+ immediately print the selected document using default settings.
+ Make sure that a system wide default printer has been selected.
+ No application specific settings are honored.
+
+Other defined actions:
+
+shell_access
+ - defines whether a shell suitable for entering random commands
+ may be started. This also determines whether the "Run Command"
+ option (Alt-F2) can be used to run shell-commands and arbitrary
+ executables. Likewise, executables placed in the user's
+ Autostart folder will no longer be executed. Applications can
+ still be autostarted by placing .desktop files in the $KDEHOME/Autostart
+ or $KDEDIR/share/autostart directory.
+ See also run_desktop_files.
+
+custom_config
+ - defines whether the --config command line option should be honored.
+ The --config command line option can be used to circumvent
+ locked-down configuration files.
+
+logout
+ - defines whether the user will be able to logout from KDE.
+
+lock_screen
+ - defines whether the user will be able to lock the screen.
+
+run_command
+ - defines whether the "Run Command" (Alt-F2) option is available.
+
+movable_toolbars
+ - define whether toolbars may be moved around by the user.
+ See also action/options_show_toolbar.
+
+editable_desktop_icons
+ - define whether icons on the desktop can be moved, renamed,
+ deleted or added. You might want to set the path for
+ the Desktop to some read-only directory as well.
+ (Instead of $HOME/Desktop)
+
+run_desktop_files
+ - defines whether users may execute desktop files that are not
+ part of the default desktop, KDE menu, registered services and
+ autostarting services.
+ * The default desktop includes the files under
+ $KDEDIR/share/kdesktop/Desktop but _NOT_ the files under
+ $HOME/Desktop.
+ * The KDE menu includes all files under $KDEDIR/share/applnk and
+ $XDGDIR/applications
+ * Registered services includes all files under $KDEDIR/share/services.
+ * Autostarting services include all files under $KDEDIR/share/autostart
+ but _NOT_ the files under $KDEHOME/Autostart
+
+ You probably also want to activate the following resource
+ restictions:
+ "appdata_kdesktop" - To restrict the default desktop.
+ "apps" - To restrict the KDE menu.
+ "xdgdata-apps" - To restrict the KDE menu.
+ "services" - To restrict registered services.
+ "autostart" - To restrict autostarting services.
+ Otherwise users can still execute .desktop files by placing them
+ in e.g. $KDEHOME/share/kdesktop/Desktop
+
+lineedit_text_completion
+ - defines whether input lines should have the potential to remember
+ any previously entered data and make suggestions based on this
+ when typing. When a single account is shared by multiple people you
+ may wish to disable this out of privacy concerns.
+
+start_new_session
+ - defines whether the user may start a second X session.
+ See also the kdm configuration.
+
+switch_user
+ - defines whether user switching via kdm is allowed
+
+skip_drm
+ - defines if the user may omit DRM checking.
+ Currently only used by kpdf
+
+Screensaver related:
+opengl_screensavers
+ - defines whether OpenGL screensavers are allowed to be used.
+
+manipulatescreen_screensavers
+ - defines whether screensavers that manipulate an image of the screen
+ (e.g. moving chunks of the screen around) are allowed to be used.
+
+When configuration files are marked immutable in whole or in part the user will no
+longer be able to make permanent changes to the settings that have been marked
+immutable. Ideally the application will recognize this and will no longer offer the
+user the possibility to change these settings. Unfortunately not all applications
+support this at the moment. It's therefor possible that the user will still be
+presented with an option in the user interface to change a setting that is
+immutable, changes made this way will not be saved though. In some cases the
+user may be able to use the changed setting till the application terminates, in
+other cases the changed setting will simply be ignored and the application will
+continue to work with the immutable setting.
+
+The following applications currently detect when their configuration files have been
+marked immutable and adjust their user interface accordingly:
+
+* kicker - By marking the kickerrc config file as immutable, the panel will be
+"locked down" and it will not be possible to make any changes to it.
+
+* kdesktop - By marking the kdesktoprc config file as immutable, the desktop
+will be "locked down" and it will no longer be possible to select
+"Configure Desktop" from its menus.
+
+* kcalc - By marking the kcalcrc config file as immutable, the "Configure" button
+will not be shown
+
+Application .desktop files can have an additional field "X-KDE-AuthorizeAction".
+If this field is present the .desktop file is only considered if the action(s)
+mentioned in this field has been authorized. If multiple actions are listed
+they should be separated by commas (','). So if the .desktop file of an application
+lists one or more actions this way and the user has no authorization for one
+of these actions then the application will not appear in the KDE menu and will not
+be used by KDE for opening files.
+
+IMPORTANT NOTE:
+Changing restrictions may influence the data that is cached in the ksycoca
+database. Since changes to .../share/config/kdeglobals do not trigger an
+automatic ksycoca update you need to force an update manually.
+To force an update of the ksycoca database touch the file
+.../share/services/update_ksycoca. This will force a user's sycoca database
+to be rebuild the next time the user logs in.
+
+KDE URL Restrictions
+====================
+
+It is also possible to restrict URL related actions. The restriction framework
+can disable URL actions based on the action, the URL in question and in some cases
+the referring URL. URLs can be matched based on protocol, host and path.
+
+The syntax for adding URL action restrictions to kdeglobals is as follows:
+
+[KDE URL Restrictions]
+rule_count=<N>
+rule_1=<action>,<referingURL_protocol>,<referingURL_host>,<referingURL_path>,<URL_protocol>,<URL_host>,<URL_path>,<enabled>
+...
+rule_N=<action>,<referingURL_protocol>,<referingURL_host>,<referingURL_path>,<URL_protocol>,<URL_host>,<URL_path>,<enabled>
+
+The following actions are supported:
+redirect - e.g. a html-page obtained via HTTP could redirect itself to file:/path/some-file. This
+ is disabled by default but could be explicitly enabled for a specific HTTP host.
+ This also applies to links contained in html documents.
+ Example: rule_1=redirect,http,myhost.acme.com,,file,,,true
+
+list - This controls which directories can be browsed with KDE's file-dialogs. If a user
+ should only be able to browse files under home directory one could use:
+ rule_1=list,,,,file,,,false
+ rule_2=list,,,,file,,$HOME,true
+ The first rule disables browing any directories on the local filesystem. The second rule
+ then enables browsing the users home directory.
+
+open - This controls which files can be opened by the user in applications. It also
+ affects where users can save files. To only allow a user to open the files
+ in his own home directory one could use:
+ rule_1=open,,,,file,,,false
+ rule_2=open,,,,file,,$HOME,true
+ rule_3=open,,,,file,,$TMP,true
+ Note that with the above, users would still be able to open files from
+ the internet. Note that the user is also given access to $TMP in order to
+ ensure correct operation of KDE applications. $TMP is replaced with the
+ temporary directory that KDE uses for this user.
+
+Some remarks:
+* empty entries match everything
+* host names may start with a wildcard, e.g. "*.acme.com"
+* a protocol also matches similar protocols that start with the same name,
+ e.g. "http" matches both http and https. You can use "http!" if you only want to
+ match http (and not https)
+* specifying a path matches all URLs that start with the same path. For better results
+ you should not include a trailing slash. If you want to specify one specific path, you can
+ add an exclamation mark. E.g. "/srv" matches both "/srv" and "/srv/www" but "/srv!" only
+ matches "/srv" and not "/srv/www".
+
+
+KDE Resource Restrictions
+==========================
+Most KDE applications make use of additional resource files that are typically
+located in directories under $KDEDIR/share. By default KDE allows users to
+override any of these resources by placing files in the same location
+under $KDEHOME/share. For example, Konsole stores profiles under
+$KDEDIR/share/konsole and users can add additional profiles by
+installing files in $KDEHOME/share/konsole.
+
+KDE Resource Restrictions make it possible to restrict the lookup of files
+to directories outside of $KDEHOME only.
+
+The following resources are defined:
+
+autostart - share/autostart
+data - share
+html - share/doc/HTML
+icon - share/icon
+config - share/config
+pixmap - share/pixmaps
+apps - share/applnk
+xdgdata-apps - share/applications
+sound - share/sounds
+locale - share/locale
+services - share/services
+servicetypes - share/servicetypes
+mime - share/mimelnk
+wallpaper - share/wallpapers
+templates - share/templates
+exe - bin
+lib - lib
+
+See http://api.kde.org/4.x-api/kdelibs-apidocs/kdecore/html/classKStandardDirs.html
+for a more up-to-date list of resources.
+
+For the purpose of resource restrictions there are two special resources:
+all - covers all resources
+data_<appname> - covers the sub section for <appname> in the data resource.
+
+To restrict resources the kdeglobals file should contain the
+group "[KDE Resource Restrictions]", each resource can then be restricted by
+adding "<resource>=false". E.g. to restrict the "wallpaper" resource to
+$KDEDIR/share/wallpapers one would add:
+[KDE Resource Restrictions][$i]
+wallpaper=false
+
+And to prevent a user from adding additional konsole profiles, one would add:
+[KDE Resource Restrictions][$i]
+data_konsole=false
+
+
+Control Module Restrictions
+===========================
+
+It is possible to restrict access to particular control modules.
+Although it is possible to remove control modules from the Control
+Center by editing the menu structure, such modules will then still
+be available to applications. A better way is to use the control
+module restrictions offered by KIOSK:
+
+[KDE Control Module Restrictions][$i]
+<menu-id>=false
+
+Some example menu-ids are:
+
+kde-display.desktop
+kde-proxy.desktop
+kde-screensaver.desktop
+
+See also kcmshell --list for a list of all the base names.
+
+Expansion of environment variables in KDE config files.
+=======================================================
+
+Since KDE-3.1, arbitrary entries in configuration files can contain environment
+variables. In order to use this the entry must be marked with [$e].
+
+Example:
+Name[$e]=$USER
+
+When the "Name" entry is read $USER will be replaced with the value of the
+$USER environment variable. Note that the application will replace $USER
+with the value of the environment variable after saving. To prevent this
+combine the $e option with $i (immmutable) option.
+
+Example:
+Name[$ei]=$USER
+
+The above will make that the "Name" entry will always return the value of
+the $USER environment variable. The user will not be able to change this entry.
+
+The following syntax is also supported:
+Name[$ei]=${USER}
+
+
+Shell Commands in KDE config files.
+===================================
+
+Since KDE-3.1 arbitrary entries in configuration files can contain shell
+commands. This way the value of a configuration entry can be determined
+dynamically at runtime. In order to use this the entry must be marked
+with [$e].
+
+Example:
+Host[$e]=$(hostname)
+
+
+KDE Kiosk Application API
+==========================
+
+Three new methods have been added to KApplication:
+
+- bool authorize(QString action); // Generic actions
+- bool authorizeKAction(QString action); // For KActions exclusively
+- bool authorizeURLAction(QString, referringURL, destinationURL) // URL Handling
+
+Automatic Logout
+================
+
+Since KDE 3.4 it is possible to automatically logout users that have been idle
+for a certain period of time.
+
+WARNING: Be careful with this option, logging out a user may result in dataloss!
+
+In kdesktoprc you can use the following entry to enable automatic logout:
+
+[ScreenSaver]
+AutoLogout=true
+AutoLogoutTimeout=600
+
+The AutoLogoutTimeout is the time in seconds that the user has to be idle before
+his session is logged out.
+
+
+Users can be associated with Profile(s)
+=======================================
+
+A user can be associated with one or more profiles. A profile indicates a
+configuration set that applies to a group of users. Each profile has a name
+to identify it. If a user is associated with more than one profile then the
+order of the two profiles is important. Settings associated with one profile
+could override the settings in the other profile, depending on the order.
+
+
+Mapping profiles to users
+=========================
+
+A mapping file determines which profile(s) should be used for which user.
+The mapping file can be configured in /etc/kde4rc in the [Directories] group:
+
+ [Directories]
+ userProfileMapFile=/etc/kde-user-profile
+
+Profiles can be mapped to individual users based on username, or profiles can
+be mapped to groups of users based on the UNIX group(s) the users are part of.
+(See man 1 groups)
+
+
+Mapping profiles to individual users
+====================================
+
+The mapping file can contain a [Users] section for mapping profiles to
+an individual user. The [Users] section contains the user's account name
+followed by one or more profiles as follow:
+
+ [Users]
+ bastian=developer
+ adrians=developer,packager
+
+The above example assigns to user "bastian" the profile "developer". To user
+"adrians" it assigns the two profiles "developer" and "packager". The order
+in which the profiles are listed makes a difference, settings in earlier
+profiles overrule settings in profiles that are listed after it. In the above
+case of user "adrians", wherever the "developer" and "packager" profiles contain
+conflicting settings, the settings of the "developer" profile will take precedent.
+
+If a user has an entry under the [Users] section, this entry will determine all
+profiles that are applicable to the user. The user will not be assigned any
+additional profiles based on the groups the user is part of.
+
+Mapping profiles to user groups
+===============================
+
+If a user has no entry under the [Users] section in the mapping file, the profiles
+that are applicable to the user will be based on the UNIX group(s) the user is
+part of.
+
+The groups and the order in which the groups are considered is determined by
+the following entry in the [General] section of the mapping file:
+
+ [General]
+ groups=pkgs,devel,bofh
+
+Each of these groups should have an entry under the [Groups] section that defines
+which profile(s) belongs to that group. This looks as follows:
+
+ [Groups]
+ pkgs=packager
+ devel=developer
+ bofh=admin,packager,developer
+
+For each group that a user is part of, the corresponding profile(s) are used. The
+order in which the groups are listed in the "groups" entry, determines the resulting
+order of all the applicable profiles. If multiple profiles are applicable to a
+particular user and a profile contains settings that conflict with settings in
+another profile then the settings in the earlier listed profile take precedent.
+
+So if, based on the example above, a user is part of the "pkgs" group then the
+"packager" profile will be used for that user. If the user is part of the "devel"
+group then the "developer" profile will be used. Users that are part of the "bofh"
+group will use the "admin", "packager" as well as the "developer" profile. In case
+of conflict, settings in the "admin" profile will take precedent over settings
+in the "packager" or "developer" profiles.
+
+If the user is part of both the "pkgs" and "devel" groups, then both the "packager"
+and "developer" profiles will be used. In case of conflicting settings between the
+two profiles, the "packager" profile will take precedent because the "pkgs" group
+associated with the profile was listed before the "devel" group.
+
+The "groups" command can be used to see to which groups a user belongs:
+
+ > groups coolo
+ coolo : users uucp dialout audio video cdrecording devel
+
+Note that in general only a few groups will have profiles associated with them.
+In the example above only the "devel" group has a profile associated with it,
+the other groups do not and will be ignored.
+
+If there is no profile defined for any of the groups that the user is in, the
+user will be assigned the "default" profile.
+
+
+The Profile determines the directory prefixes
+=============================================
+
+The global KDE configuration file (e.g. kdeglobals or /etc/kde4rc) can
+contain config-groups that are associated with a certain user profile.
+Such a config-group is treated similar as the [Directories] config-group.
+
+The name of a such config-group is [Directories-<ProfileName>]
+
+
+Integration with KIOSK Admin Tool
+=================================
+
+The KIOSK Admin Tool uses /etc/kde4rc as source for all its profile
+information. For this it uses the following keys in the
+[Directories-<ProfileName>] config-group:
+
+ # Short text describing this profile
+ ProfileDescription=
+
+ # Files will be installed with the uid of this user
+ ProfileInstallUser=
+
+The KIOSK Admin Tool uses the first directory from the prefixes= entry
+as default installation directory for this profile.
+
+
+Default setting as example
+==========================
+
+The following snipped could be added to /etc/kde4rc to define a "default" profile:
+
+ [Directories-default]
+ ProfileDescription=Default profile
+ ProfileDescription[de]=Defaultprofiel
+ ProfileInstallUser=root
+ prefixes=/var/run/kde-profile/default
+
diff --git a/tier1/kconfig/src/CMakeLists.txt b/tier1/kconfig/src/CMakeLists.txt
new file mode 100644
index 00000000..caa7a43d
--- /dev/null
+++ b/tier1/kconfig/src/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_subdirectory(core)
+add_subdirectory(gui)
+add_subdirectory(kconfig_compiler)
+add_subdirectory(kconf_update)
diff --git a/tier1/kconfig/src/core/CMakeLists.txt b/tier1/kconfig/src/core/CMakeLists.txt
new file mode 100644
index 00000000..ea272d31
--- /dev/null
+++ b/tier1/kconfig/src/core/CMakeLists.txt
@@ -0,0 +1,53 @@
+
+find_package(Qt5Core 5.2.0 REQUIRED NO_MODULE)
+
+set(libkconfigcore_SRCS
+ kconfig.cpp
+ kconfigbase.cpp
+ kconfigdata.cpp
+ kconfiggroup.cpp
+ kconfigbackend.cpp
+ kconfigini.cpp
+ kdesktopfile.cpp
+ ksharedconfig.cpp
+ kcoreconfigskeleton.cpp
+ kauthorized.cpp
+ kemailsettings.cpp
+)
+
+add_library(KF5ConfigCore ${libkconfigcore_SRCS})
+generate_export_header(KF5ConfigCore BASE_NAME KConfigCore)
+add_library(KF5::ConfigCore ALIAS KF5ConfigCore)
+
+target_link_libraries(KF5ConfigCore PUBLIC Qt5::Core)
+if(WIN32)
+ target_link_libraries(KF5ConfigCore PRIVATE ${KDEWIN_LIBRARIES})
+endif()
+
+if(IS_ABSOLUTE "${INCLUDE_INSTALL_DIR}")
+ target_include_directories(KF5ConfigCore INTERFACE "$<INSTALL_INTERFACE:${INCLUDE_INSTALL_DIR}>" )
+else()
+ target_include_directories(KF5ConfigCore INTERFACE "$<INSTALL_INTERFACE:${CMAKE_INSTALL_PREFIX}/${INCLUDE_INSTALL_DIR}>" )
+endif()
+
+set_target_properties(KF5ConfigCore PROPERTIES VERSION ${KCONFIG_VERSION_STRING}
+ SOVERSION ${KCONFIG_SOVERSION}
+ EXPORT_NAME ConfigCore
+)
+
+install(TARGETS KF5ConfigCore EXPORT KF5ConfigTargets ${INSTALL_TARGETS_DEFAULT_ARGS})
+
+install( FILES
+ ${CMAKE_CURRENT_BINARY_DIR}/kconfigcore_export.h
+ conversion_check.h
+ kconfig.h
+ #kconfigbackend.h re-enable post-API review and implementation (4.2?)
+ kconfigbase.h
+ kconfiggroup.h
+ kdesktopfile.h
+ ksharedconfig.h
+ kcoreconfigskeleton.h
+ kauthorized.h
+ kemailsettings.h
+ DESTINATION ${INCLUDE_INSTALL_DIR} COMPONENT Devel
+)
diff --git a/tier1/kconfig/src/core/bufferfragment_p.h b/tier1/kconfig/src/core/bufferfragment_p.h
new file mode 100644
index 00000000..5a753ad4
--- /dev/null
+++ b/tier1/kconfig/src/core/bufferfragment_p.h
@@ -0,0 +1,181 @@
+/*
+ This file is part of the KDE libraries
+ Copyright (c) 2008 Jakub Stachowski <qbast@go2.pl>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef BUFFERFRAGMENT_H
+#define BUFFERFRAGMENT_H
+
+#define bf_isspace(str) ((str == ' ') || (str == '\t') || (str == '\r'))
+
+// This class provides wrapper around fragment of existing buffer (array of bytes).
+// If underlying buffer gets deleted, all BufferFragment objects referencing it become invalid.
+// Use toByteArray() to make deep copy of the buffer fragment.
+//
+// API is designed to subset of QByteArray methods with some changes:
+// - trim() is like QByteArray.trimmed(), but it modifies current object
+// - truncateLeft() provides way to cut off beginning of the buffer
+// - split() works more like strtok_r than QByteArray.split()
+// - truncateLeft() and mid() require position argument to be valid
+
+class KConfigIniBackend::BufferFragment
+{
+
+public:
+
+ BufferFragment() : d(0), len(0)
+ {
+ }
+
+ BufferFragment(char* buf, int size) : d(buf), len(size)
+ {
+ }
+
+ int length() const
+ {
+ return len;
+ }
+
+ char at(unsigned int i) const
+ {
+ Q_ASSERT(i < len);
+ return d[i];
+ }
+
+ void clear()
+ {
+ len = 0;
+ }
+
+ const char* constData() const
+ {
+ return d;
+ }
+
+ char* data() const
+ {
+ return d;
+ }
+
+ void trim()
+ {
+ while (bf_isspace(*d) && len > 0) {
+ d++;
+ len--;
+ }
+ while (len > 0 && bf_isspace(d[len - 1]))
+ len--;
+ }
+
+ // similar to strtok_r . On first call variable pointed by start should be set to 0.
+ // Each call will update *start to new starting position.
+ BufferFragment split(char c, unsigned int* start)
+ {
+ while (*start < len) {
+ int end = indexOf(c, *start);
+ if (end == -1) end = len;
+ BufferFragment line(d + (*start), end - (*start));
+ *start = end + 1;
+ return line;
+ }
+ return BufferFragment();
+ }
+
+ bool isEmpty() const
+ {
+ return (len == 0);
+ }
+
+ BufferFragment left(unsigned int size) const
+ {
+ return BufferFragment(d, qMin(size,len));
+ }
+
+ void truncateLeft(unsigned int size)
+ {
+ Q_ASSERT(size <= len);
+ d += size;
+ len -= size;
+ }
+
+ void truncate(unsigned int pos)
+ {
+ if (pos < len) len = pos;
+ }
+
+ bool isNull() const
+ {
+ return (d == 0);
+ }
+
+ BufferFragment mid(unsigned int pos, int length=-1) const
+ {
+ Q_ASSERT(pos < len);
+ int size = length;
+ if (length == -1 || (pos + length) > len)
+ size = len - pos;
+ return BufferFragment(d + pos, size);
+ }
+
+ bool operator==(const QByteArray& other) const
+ {
+ return (other.size() == (int)len && memcmp(d,other.constData(),len) == 0);
+ }
+
+ bool operator!=(const QByteArray& other) const
+ {
+ return (other.size() != (int)len || memcmp(d,other.constData(),len) != 0);
+ }
+
+ int indexOf(char c, unsigned int from = 0) const
+ {
+ const char* cursor = d + from - 1;
+ const char* end = d + len;
+ while ( ++cursor < end)
+ if (*cursor ==c )
+ return cursor - d;
+ return -1;
+ }
+
+ int lastIndexOf(char c) const
+ {
+ int from = len - 1;
+ while (from >= 0)
+ if (d[from] == c)
+ return from;
+ else
+ from--;
+ return -1;
+ }
+
+ QByteArray toByteArray() const {
+ return QByteArray(d,len);
+ }
+
+ // this is faster than toByteArray, but returned QByteArray becomes invalid
+ // when buffer for this BufferFragment disappears
+ QByteArray toVolatileByteArray() const {
+ return QByteArray::fromRawData(d, len);
+ }
+
+private:
+ char* d;
+ unsigned int len;
+};
+
+#endif
diff --git a/tier1/kconfig/src/core/conversion_check.h b/tier1/kconfig/src/core/conversion_check.h
new file mode 100644
index 00000000..23bdcf04
--- /dev/null
+++ b/tier1/kconfig/src/core/conversion_check.h
@@ -0,0 +1,120 @@
+/*
+ This file is part of the KDE libraries
+ Copyright (c) 2006 Thomas Braxton <brax108@cox.net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+
+#ifndef CONVERSION_CHECK_H
+#define CONVERSION_CHECK_H
+
+#include <QtCore/QString>
+#include <QtCore/QDate>
+#include <QtCore/QPoint>
+#include <QtCore/QSize>
+#include <QtCore/QRect>
+#include <QtCore/QVariant>
+
+class QColor;
+class QFont;
+
+namespace ConversionCheck {
+
+// used to distinguish between supported/unsupported types
+struct supported { };
+struct unsupported { };
+
+// traits type class to define support for constraints
+template <typename T>
+struct QVconvertible
+{
+ typedef unsupported toQString;
+ typedef unsupported toQVariant;
+};
+
+// constraint classes
+template <typename T>
+struct type_toQString
+{
+ void constraint() { supported x = y; Q_UNUSED(x); }
+ typename QVconvertible<T>::toQString y;
+};
+
+template <typename T>
+struct type_toQVariant
+{
+ void constraint() { supported x = y; Q_UNUSED(x); }
+ typename QVconvertible<T>::toQVariant y;
+};
+
+
+// check if T is convertible to QString thru QVariant
+// if not supported can't be used in QList<T> functions
+template <typename T>
+inline void to_QString()
+{
+ void (type_toQString<T>::*x)() = &type_toQString<T>::constraint;
+ Q_UNUSED(x);
+}
+
+// check if T is convertible to QVariant & supported in readEntry/writeEntry
+template <typename T>
+inline void to_QVariant()
+{
+ void (type_toQVariant<T>::*x)() = &type_toQVariant<T>::constraint;
+ Q_UNUSED(x);
+}
+
+// define for all types handled in readEntry/writeEntry
+// string_support - is supported by QVariant(type).toString(),
+// can be used in QList<T> functions
+// variant_support - has a QVariant constructor
+#define QVConversions(type, string_support, variant_support) \
+template <> struct QVconvertible<type> {\
+ typedef string_support toQString;\
+ typedef variant_support toQVariant;\
+}
+
+// The only types needed here are the types handled in readEntry/writeEntry
+// the default QVconvertible will take care of the rest.
+QVConversions(bool, supported, supported);
+QVConversions(int, supported, supported);
+QVConversions(unsigned int, supported, supported);
+QVConversions(long long, supported, supported);
+QVConversions(unsigned long long, supported, supported);
+QVConversions(float, supported, supported);
+QVConversions(double, supported, supported);
+QVConversions(QString, supported, supported);
+QVConversions(QColor, unsupported, supported);
+QVConversions(QFont, supported, supported);
+QVConversions(QDateTime, unsupported, supported);
+QVConversions(QDate, unsupported, supported);
+QVConversions(QSize, unsupported, supported);
+QVConversions(QRect, unsupported, supported);
+QVConversions(QPoint, unsupported, supported);
+QVConversions(QSizeF, unsupported, supported);
+QVConversions(QRectF, unsupported, supported);
+QVConversions(QPointF, unsupported, supported);
+QVConversions(QByteArray, supported, supported);
+QVConversions(QStringList, unsupported, supported);
+QVConversions(QVariantList, unsupported, supported);
+QVConversions(QUrl, supported, supported);
+QVConversions(QList<QUrl>, unsupported, supported);
+}
+
+#endif
+
diff --git a/tier1/kconfig/src/core/kauthorized.cpp b/tier1/kconfig/src/core/kauthorized.cpp
new file mode 100644
index 00000000..abf479ca
--- /dev/null
+++ b/tier1/kconfig/src/core/kauthorized.cpp
@@ -0,0 +1,393 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1997 Matthias Kalle Dalheimer (kalle@kde.org)
+ Copyright (C) 1998, 1999, 2000 Waldo Bastian <bastian@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "kauthorized.h"
+
+#include <QtCore/QDir>
+#include <QtCore/QRegExp>
+#include <QList>
+#include <QUrl>
+
+#include <QCoreApplication>
+#include <ksharedconfig.h>
+#include <stdlib.h> // srand(), rand()
+#ifndef Q_OS_WIN
+#include <unistd.h>
+#include <netdb.h>
+#endif
+
+#include <kconfiggroup.h>
+
+#include <QMutex>
+#include <QMutexLocker>
+
+extern bool kde_kiosk_exception;
+
+
+class URLActionRule
+{
+ public:
+#define checkExactMatch(s, b) \
+ if (s.isEmpty()) b = true; \
+ else if (s[s.length()-1] == QLatin1Char('!')) \
+ { b = false; s.truncate(s.length()-1); } \
+ else b = true;
+#define checkStartWildCard(s, b) \
+ if (s.isEmpty()) b = true; \
+ else if (s[0] == QLatin1Char('*')) \
+ { b = true; s = s.mid(1); } \
+ else b = false;
+#define checkEqual(s, b) \
+ b = (s == QString::fromLatin1("="));
+
+ URLActionRule(const QByteArray &act,
+ const QString &bProt, const QString &bHost, const QString &bPath,
+ const QString &dProt, const QString &dHost, const QString &dPath,
+ bool perm)
+ : action(act),
+ baseProt(bProt), baseHost(bHost), basePath(bPath),
+ destProt(dProt), destHost(dHost), destPath(dPath),
+ permission(perm)
+ {
+ checkExactMatch(baseProt, baseProtWildCard);
+ checkStartWildCard(baseHost, baseHostWildCard);
+ checkExactMatch(basePath, basePathWildCard);
+ checkExactMatch(destProt, destProtWildCard);
+ checkStartWildCard(destHost, destHostWildCard);
+ checkExactMatch(destPath, destPathWildCard);
+ checkEqual(destProt, destProtEqual);
+ checkEqual(destHost, destHostEqual);
+ }
+
+ bool baseMatch(const QUrl &url, const QString &protClass) const
+ {
+ if (baseProtWildCard)
+ {
+ if ( !baseProt.isEmpty() && !url.scheme().startsWith(baseProt) &&
+ (protClass.isEmpty() || (protClass != baseProt)) )
+ return false;
+ }
+ else
+ {
+ if ( (url.scheme() != baseProt) &&
+ (protClass.isEmpty() || (protClass != baseProt)) )
+ return false;
+ }
+ if (baseHostWildCard)
+ {
+ if (!baseHost.isEmpty() && !url.host().endsWith(baseHost))
+ return false;
+ }
+ else
+ {
+ if (url.host() != baseHost)
+ return false;
+ }
+ if (basePathWildCard)
+ {
+ if (!basePath.isEmpty() && !url.path().startsWith(basePath))
+ return false;
+ }
+ else
+ {
+ if (url.path() != basePath)
+ return false;
+ }
+ return true;
+ }
+
+ bool destMatch(const QUrl &url, const QString &protClass, const QUrl &base, const QString &baseClass) const
+ {
+ if (destProtEqual)
+ {
+ if ( (url.scheme() != base.scheme()) &&
+ (protClass.isEmpty() || baseClass.isEmpty() || protClass != baseClass) )
+ return false;
+ }
+ else if (destProtWildCard)
+ {
+ if ( !destProt.isEmpty() && !url.scheme().startsWith(destProt) &&
+ (protClass.isEmpty() || (protClass != destProt)) )
+ return false;
+ }
+ else
+ {
+ if ( (url.scheme() != destProt) &&
+ (protClass.isEmpty() || (protClass != destProt)) )
+ return false;
+ }
+ if (destHostWildCard)
+ {
+ if (!destHost.isEmpty() && !url.host().endsWith(destHost))
+ return false;
+ }
+ else if (destHostEqual)
+ {
+ if (url.host() != base.host())
+ return false;
+ }
+ else
+ {
+ if (url.host() != destHost)
+ return false;
+ }
+ if (destPathWildCard)
+ {
+ if (!destPath.isEmpty() && !url.path().startsWith(destPath))
+ return false;
+ }
+ else
+ {
+ if (url.path() != destPath)
+ return false;
+ }
+ return true;
+ }
+
+ QByteArray action;
+ QString baseProt;
+ QString baseHost;
+ QString basePath;
+ QString destProt;
+ QString destHost;
+ QString destPath;
+ bool baseProtWildCard : 1;
+ bool baseHostWildCard : 1;
+ bool basePathWildCard : 1;
+ bool destProtWildCard : 1;
+ bool destHostWildCard : 1;
+ bool destPathWildCard : 1;
+ bool destProtEqual : 1;
+ bool destHostEqual : 1;
+ bool permission;
+};
+
+class KAuthorizedPrivate {
+public:
+ KAuthorizedPrivate()
+ : actionRestrictions( false ), blockEverything(false),mutex(QMutex::Recursive)
+ {
+ Q_ASSERT_X(QCoreApplication::instance(),"KAuthorizedPrivate()","There has to be an existing QCoreApplication::instance() pointer");
+
+ KSharedConfig::Ptr config = KSharedConfig::openConfig();
+
+ Q_ASSERT_X(config,"KAuthorizedPrivate()","There has to be an existing KSharedConfig::openConfig() pointer");
+ if (!config) {
+ blockEverything=true;
+ return;
+ }
+ actionRestrictions = config->hasGroup("KDE Action Restrictions" ) && !kde_kiosk_exception;
+ }
+
+ ~KAuthorizedPrivate()
+ {
+ }
+
+ bool actionRestrictions : 1;
+ bool blockEverything : 1;
+ QList<URLActionRule> urlActionRestrictions;
+ QMutex mutex;
+};
+
+Q_GLOBAL_STATIC(KAuthorizedPrivate,authPrivate)
+#define MY_D KAuthorizedPrivate *d=authPrivate();
+
+
+bool KAuthorized::authorize(const QString &genericAction)
+{
+ MY_D
+ if (d->blockEverything) return false;
+
+ if (!d->actionRestrictions)
+ return true;
+
+ KConfigGroup cg(KSharedConfig::openConfig(), "KDE Action Restrictions");
+ return cg.readEntry(genericAction, true);
+}
+
+bool KAuthorized::authorizeKAction(const QString& action)
+{
+ MY_D
+ if (d->blockEverything) return false;
+ if (!d->actionRestrictions || action.isEmpty())
+ return true;
+
+ return authorize(QLatin1String("action/") + action);
+}
+
+bool KAuthorized::authorizeControlModule(const QString &menuId)
+{
+ if (menuId.isEmpty() || kde_kiosk_exception)
+ return true;
+ KConfigGroup cg(KSharedConfig::openConfig(), "KDE Control Module Restrictions");
+ return cg.readEntry(menuId, true);
+}
+
+QStringList KAuthorized::authorizeControlModules(const QStringList &menuIds)
+{
+ KConfigGroup cg(KSharedConfig::openConfig(), "KDE Control Module Restrictions");
+ QStringList result;
+ for(QStringList::ConstIterator it = menuIds.begin();
+ it != menuIds.end(); ++it)
+ {
+ if (cg.readEntry(*it, true))
+ result.append(*it);
+ }
+ return result;
+}
+
+static void initUrlActionRestrictions()
+{
+ MY_D
+ const QString Any;
+
+ d->urlActionRestrictions.clear();
+ d->urlActionRestrictions.append(
+ URLActionRule("open", Any, Any, Any, Any, Any, Any, true));
+ d->urlActionRestrictions.append(
+ URLActionRule("list", Any, Any, Any, Any, Any, Any, true));
+// TEST:
+// d->urlActionRestrictions.append(
+// URLActionRule("list", Any, Any, Any, Any, Any, Any, false));
+// d->urlActionRestrictions.append(
+// URLActionRule("list", Any, Any, Any, "file", Any, QDir::homePath(), true));
+ d->urlActionRestrictions.append(
+ URLActionRule("link", Any, Any, Any, QLatin1String(":internet"), Any, Any, true));
+ d->urlActionRestrictions.append(
+ URLActionRule("redirect", Any, Any, Any, QLatin1String(":internet"), Any, Any, true));
+
+ // We allow redirections to file: but not from internet protocols, redirecting to file:
+ // is very popular among io-slaves and we don't want to break them
+ d->urlActionRestrictions.append(
+ URLActionRule("redirect", Any, Any, Any, QLatin1String("file"), Any, Any, true));
+ d->urlActionRestrictions.append(
+ URLActionRule("redirect", QLatin1String(":internet"), Any, Any, QLatin1String("file"), Any, Any, false));
+
+ // local protocols may redirect everywhere
+ d->urlActionRestrictions.append(
+ URLActionRule("redirect", QLatin1String(":local"), Any, Any, Any, Any, Any, true));
+
+ // Anyone may redirect to about:
+ d->urlActionRestrictions.append(
+ URLActionRule("redirect", Any, Any, Any, QLatin1String("about"), Any, Any, true));
+
+ // Anyone may redirect to mailto:
+ d->urlActionRestrictions.append(
+ URLActionRule("redirect", Any, Any, Any, QLatin1String("mailto"), Any, Any, true));
+
+ // Anyone may redirect to itself, cq. within it's own group
+ d->urlActionRestrictions.append(
+ URLActionRule("redirect", Any, Any, Any, QLatin1String("="), Any, Any, true));
+
+ d->urlActionRestrictions.append(
+ URLActionRule("redirect", QLatin1String("about"), Any, Any, Any, Any, Any, true));
+
+
+ KConfigGroup cg(KSharedConfig::openConfig(), "KDE URL Restrictions");
+ int count = cg.readEntry("rule_count", 0);
+ QString keyFormat = QString::fromLatin1("rule_%1");
+ for(int i = 1; i <= count; i++)
+ {
+ QString key = keyFormat.arg(i);
+ const QStringList rule = cg.readEntry(key, QStringList());
+ if (rule.count() != 8)
+ continue;
+ const QByteArray action = rule[0].toLatin1();
+ QString refProt = rule[1];
+ QString refHost = rule[2];
+ QString refPath = rule[3];
+ QString urlProt = rule[4];
+ QString urlHost = rule[5];
+ QString urlPath = rule[6];
+ bool bEnabled = (rule[7].toLower() == QLatin1String("true"));
+
+ if (refPath.startsWith(QLatin1String("$HOME")))
+ refPath.replace(0, 5, QDir::homePath());
+ else if (refPath.startsWith(QLatin1Char('~')))
+ refPath.replace(0, 1, QDir::homePath());
+ if (urlPath.startsWith(QLatin1String("$HOME")))
+ urlPath.replace(0, 5, QDir::homePath());
+ else if (urlPath.startsWith(QLatin1Char('~')))
+ urlPath.replace(0, 1, QDir::homePath());
+
+ if (refPath.startsWith(QLatin1String("$TMP")))
+ refPath.replace(0, 4, QDir::tempPath());
+ if (urlPath.startsWith(QLatin1String("$TMP")))
+ urlPath.replace(0, 4, QDir::tempPath());
+
+ d->urlActionRestrictions.append(
+ URLActionRule( action, refProt, refHost, refPath, urlProt, urlHost, urlPath, bEnabled));
+ }
+}
+
+namespace KAuthorized
+{
+// Called by KAuthorized::allowUrlAction in KIO
+KCONFIGCORE_EXPORT void allowUrlActionInternal(const QString &action, const QUrl &_baseURL, const QUrl &_destURL)
+{
+ MY_D
+ QMutexLocker locker((&d->mutex));
+
+#if QT_VERSION >= QT_VERSION_CHECK(5, 3, 0)
+ const QString basePath = _baseURL.adjusted(QUrl::StripTrailingSlash).path();
+ const QString destPath = _destURL.adjusted(QUrl::StripTrailingSlash).path();
+#else
+ const QString basePath = QUrl(_baseURL.toString(QUrl::StripTrailingSlash)).path();
+ const QString destPath = QUrl(_destURL.toString(QUrl::StripTrailingSlash)).path();
+#endif
+
+ d->urlActionRestrictions.append( URLActionRule
+ ( action.toLatin1(), _baseURL.scheme(), _baseURL.host(), basePath,
+ _destURL.scheme(), _destURL.host(), destPath, true));
+}
+
+// Called by KAuthorized::authorizeUrlAction in KIO
+KCONFIGCORE_EXPORT bool authorizeUrlActionInternal(const QString& action, const QUrl &_baseURL, const QUrl &_destURL, const QString& baseClass, const QString& destClass)
+{
+ MY_D
+ QMutexLocker locker(&(d->mutex));
+ if (d->blockEverything) return false;
+
+ if (_destURL.isEmpty())
+ return true;
+
+ bool result = false;
+ if (d->urlActionRestrictions.isEmpty())
+ initUrlActionRestrictions();
+
+ QUrl baseURL(_baseURL);
+ baseURL.setPath(QDir::cleanPath(baseURL.path()));
+
+ QUrl destURL(_destURL);
+ destURL.setPath(QDir::cleanPath(destURL.path()));
+
+ Q_FOREACH(const URLActionRule &rule, d->urlActionRestrictions) {
+ if ((result != rule.permission) && // No need to check if it doesn't make a difference
+ (action == QLatin1String(rule.action.constData())) &&
+ rule.baseMatch(baseURL, baseClass) &&
+ rule.destMatch(destURL, destClass, baseURL, baseClass))
+ {
+ result = rule.permission;
+ }
+ }
+ return result;
+}
+
+} // namespace
diff --git a/tier1/kconfig/src/core/kauthorized.h b/tier1/kconfig/src/core/kauthorized.h
new file mode 100644
index 00000000..a16368a8
--- /dev/null
+++ b/tier1/kconfig/src/core/kauthorized.h
@@ -0,0 +1,73 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1997 Matthias Kalle Dalheimer (kalle@kde.org)
+ Copyright (c) 1998, 1999 Waldo Bastian <bastian@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KAUTHORIZED_H
+#define KAUTHORIZED_H
+
+#include <kconfigcore_export.h>
+
+class QUrl;
+class QString;
+class QStringList;
+
+/**
+* Kiosk authorization framework
+*
+* Core functionality, see kauthorized.h for authorizeUrlAction.
+*/
+namespace KAuthorized
+{
+ /**
+ * Returns whether a certain action is authorized
+ * @param genericAction The name of a generic action
+ * @return true if the action is authorized
+ * @todo what are the generic actions?
+ */
+ KCONFIGCORE_EXPORT bool authorize(const QString& genericAction);
+
+ /**
+ * Returns whether a certain KAction is authorized.
+ *
+ * @param action The name of a KAction action. The name is prepended
+ * with "action/" before being passed to authorize()
+ * @return true if the KAction is authorized
+ */
+ KCONFIGCORE_EXPORT bool authorizeKAction(const QString& action);
+
+ /**
+ * Returns whether access to a certain control module is authorized.
+ *
+ * @param menuId identifying the control module, e.g. kde-mouse.desktop
+ * @return true if access to the module is authorized, false otherwise.
+ */
+ KCONFIGCORE_EXPORT bool authorizeControlModule(const QString& menuId);
+
+ /**
+ * Returns which control modules from a given list are authorized for access.
+ *
+ * @param menuIds list of menu-ids of control modules;
+ * an example of a menu-id is kde-mouse.desktop.
+ * @return Those control modules for which access has been authorized.
+ */
+ KCONFIGCORE_EXPORT QStringList authorizeControlModules(const QStringList& menuIds);
+
+}
+
+#endif
diff --git a/tier1/kconfig/src/core/kconfig.cpp b/tier1/kconfig/src/core/kconfig.cpp
new file mode 100644
index 00000000..b311a366
--- /dev/null
+++ b/tier1/kconfig/src/core/kconfig.cpp
@@ -0,0 +1,931 @@
+/*
+ This file is part of the KDE libraries
+ Copyright (c) 2006, 2007 Thomas Braxton <kde.braxton@gmail.com>
+ Copyright (c) 1999 Preston Brown <pbrown@kde.org>
+ Copyright (c) 1997-1999 Matthias Kalle Dalheimer <kalle@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+// Qt5 TODO: re-enable. No point in doing it before, it breaks on QString::fromUtf8(QByteArray), which exists in qt5.
+#undef QT_NO_CAST_FROM_BYTEARRAY
+
+#include "kconfig.h"
+#include "kconfig_p.h"
+
+#include <cstdlib>
+#include <fcntl.h>
+
+#ifdef Q_OS_WIN
+static inline FILE* popen(const char *cmd, const char *mode) { return _popen(cmd, mode); }
+static inline int pclose(FILE* stream) { return _pclose(stream); }
+#else
+#include <unistd.h>
+#endif
+
+#include "kconfigbackend.h"
+#include "kconfiggroup.h"
+
+#include <qcoreapplication.h>
+#include <qprocess.h>
+#include <qstandardpaths.h>
+#include <qbytearray.h>
+#include <qfile.h>
+#include <qlocale.h>
+#include <qdir.h>
+#include <QtCore/QProcess>
+#include <QtCore/QSet>
+
+bool KConfigPrivate::mappingsRegistered=false;
+
+KConfigPrivate::KConfigPrivate(KConfig::OpenFlags flags,
+ QStandardPaths::StandardLocation resourceType)
+ : openFlags(flags), resourceType(resourceType), mBackend(0),
+ bDynamicBackend(true), bDirty(false), bReadDefaults(false),
+ bFileImmutable(false), bForceGlobal(false), bSuppressGlobal(false),
+ configState(KConfigBase::NoAccess)
+{
+ sGlobalFileName = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + QLatin1String("/kdeglobals");
+
+ static int use_etc_kderc = -1;
+ if (use_etc_kderc < 0)
+ use_etc_kderc = !qEnvironmentVariableIsSet("KDE_SKIP_KDERC"); // for unit tests
+ if (use_etc_kderc) {
+
+ etc_kderc =
+#ifdef Q_OS_WIN
+ QFile::decodeName( qgetenv("WINDIR") + "/kde4rc" );
+#else
+ QLatin1String("/etc/kde4rc");
+#endif
+ if (!QFileInfo(etc_kderc).isReadable()) {
+ etc_kderc.clear();
+ }
+ }
+
+// if (!mappingsRegistered) {
+// KEntryMap tmp;
+// if (!etc_kderc.isEmpty()) {
+// QExplicitlySharedDataPointer<KConfigBackend> backend = KConfigBackend::create(etc_kderc, QLatin1String("INI"));
+// backend->parseConfig( "en_US", tmp, KConfigBackend::ParseDefaults);
+// }
+// const QString kde4rc(QDir::home().filePath(".kde4rc"));
+// if (KStandardDirs::checkAccess(kde4rc, R_OK)) {
+// QExplicitlySharedDataPointer<KConfigBackend> backend = KConfigBackend::create(kde4rc, QLatin1String("INI"));
+// backend->parseConfig( "en_US", tmp, KConfigBackend::ParseOptions());
+// }
+// KConfigBackend::registerMappings(tmp);
+// mappingsRegistered = true;
+// }
+
+#if 0 // KDE4 code
+ setLocale(KLocale::global()->language());
+#else
+ setLocale(QLocale::system().name());
+#endif
+}
+
+
+bool KConfigPrivate::lockLocal()
+{
+ if (mBackend) {
+ return mBackend->lock();
+ }
+ // anonymous object - pretend we locked it
+ return true;
+}
+
+void KConfigPrivate::copyGroup(const QByteArray& source, const QByteArray& destination,
+ KConfigGroup *otherGroup, KConfigBase::WriteConfigFlags flags) const
+{
+ KEntryMap& otherMap = otherGroup->config()->d_ptr->entryMap;
+ const int len = source.length();
+ const bool sameName = (destination == source);
+
+ // we keep this bool outside the foreach loop so that if
+ // the group is empty, we don't end up marking the other config
+ // as dirty erroneously
+ bool dirtied = false;
+
+ for (KEntryMap::ConstIterator entryMapIt( entryMap.constBegin() ); entryMapIt != entryMap.constEnd(); ++entryMapIt) {
+ const QByteArray& group = entryMapIt.key().mGroup;
+
+ if (!group.startsWith(source)) // nothing to do
+ continue;
+
+ // don't copy groups that start with the same prefix, but are not sub-groups
+ if (group.length() > len && group[len] != '\x1d')
+ continue;
+
+ KEntryKey newKey = entryMapIt.key();
+
+ if (flags & KConfigBase::Localized) {
+ newKey.bLocal = true;
+ }
+
+ if (!sameName)
+ newKey.mGroup.replace(0, len, destination);
+
+ KEntry entry = entryMap[ entryMapIt.key() ];
+ dirtied = entry.bDirty = flags & KConfigBase::Persistent;
+
+ if (flags & KConfigBase::Global) {
+ entry.bGlobal = true;
+ }
+
+ otherMap[newKey] = entry;
+ }
+
+ if (dirtied) {
+ otherGroup->config()->d_ptr->bDirty = true;
+ }
+}
+
+QString KConfigPrivate::expandString(const QString& value)
+{
+ QString aValue = value;
+
+ // check for environment variables and make necessary translations
+ int nDollarPos = aValue.indexOf( QLatin1Char('$') );
+ while( nDollarPos != -1 && nDollarPos+1 < aValue.length()) {
+ // there is at least one $
+ if( aValue[nDollarPos+1] == QLatin1Char('(') ) {
+ int nEndPos = nDollarPos+1;
+ // the next character is not $
+ while ( (nEndPos <= aValue.length()) && (aValue[nEndPos]!=QLatin1Char(')')) )
+ nEndPos++;
+ nEndPos++;
+ QString cmd = aValue.mid( nDollarPos+2, nEndPos-nDollarPos-3 );
+
+ QString result;
+#if 0 // Removed in KDE Frameworks 5. No such concept anymore. Just set your PATH.
+ QByteArray oldpath = qgetenv( "PATH" );
+ QByteArray newpath;
+ if (KComponentData::hasMainComponent()) {
+ newpath = QFile::encodeName(KGlobal::dirs()->resourceDirs("exe").join(QChar::fromLatin1(KPATH_SEPARATOR)));
+ if (!newpath.isEmpty() && !oldpath.isEmpty())
+ newpath += KPATH_SEPARATOR;
+ }
+ newpath += oldpath;
+ qputenv( "PATH", newpath);
+#endif
+
+// FIXME: wince does not have pipes
+#ifndef _WIN32_WCE
+ FILE *fs = popen(QFile::encodeName(cmd).data(), "r");
+ if (fs) {
+ QTextStream ts(fs, QIODevice::ReadOnly);
+ result = ts.readAll().trimmed();
+ pclose(fs);
+ }
+#endif
+#if 0 // Removed in KDE Frameworks 5, see above.
+ qputenv( "PATH", oldpath);
+#endif
+ aValue.replace( nDollarPos, nEndPos-nDollarPos, result );
+ nDollarPos += result.length();
+ } else if( aValue[nDollarPos+1] != QLatin1Char('$') ) {
+ int nEndPos = nDollarPos+1;
+ // the next character is not $
+ QString aVarName;
+ if ( aValue[nEndPos] == QLatin1Char('{') ) {
+ while ( (nEndPos <= aValue.length()) && (aValue[nEndPos] != QLatin1Char('}')) )
+ nEndPos++;
+ nEndPos++;
+ aVarName = aValue.mid( nDollarPos+2, nEndPos-nDollarPos-3 );
+ } else {
+ while ( nEndPos <= aValue.length() &&
+ (aValue[nEndPos].isNumber() ||
+ aValue[nEndPos].isLetter() ||
+ aValue[nEndPos] == QLatin1Char('_') ) )
+ nEndPos++;
+ aVarName = aValue.mid( nDollarPos+1, nEndPos-nDollarPos-1 );
+ }
+ QString env;
+ if (!aVarName.isEmpty()) {
+#ifdef Q_OS_WIN
+ if (aVarName == QLatin1String("HOME"))
+ env = QDir::homePath();
+ else
+#endif
+ {
+ QByteArray pEnv = qgetenv(aVarName.toLatin1().constData());
+ if( !pEnv.isEmpty() )
+ env = QString::fromLocal8Bit(pEnv.constData());
+ }
+ aValue.replace(nDollarPos, nEndPos-nDollarPos, env);
+ nDollarPos += env.length();
+ } else
+ aValue.remove( nDollarPos, nEndPos-nDollarPos );
+ } else {
+ // remove one of the dollar signs
+ aValue.remove( nDollarPos, 1 );
+ nDollarPos++;
+ }
+ nDollarPos = aValue.indexOf( QLatin1Char('$'), nDollarPos );
+ }
+
+ return aValue;
+}
+
+
+KConfig::KConfig(const QString& file, OpenFlags mode,
+ QStandardPaths::StandardLocation resourceType)
+ : d_ptr(new KConfigPrivate(mode, resourceType))
+{
+ d_ptr->changeFileName(file); // set the local file name
+
+ // read initial information off disk
+ reparseConfiguration();
+}
+
+KConfig::KConfig(const QString& file, const QString& backend, QStandardPaths::StandardLocation resourceType)
+ : d_ptr(new KConfigPrivate(SimpleConfig, resourceType))
+{
+ d_ptr->mBackend = KConfigBackend::create(file, backend);
+ d_ptr->bDynamicBackend = false;
+ d_ptr->changeFileName(file); // set the local file name
+
+ // read initial information off disk
+ reparseConfiguration();
+}
+
+KConfig::KConfig(KConfigPrivate &d)
+ : d_ptr(&d)
+{
+}
+
+KConfig::~KConfig()
+{
+ Q_D(KConfig);
+ if (d->bDirty && (d->mBackend && d->mBackend->ref.load() == 1))
+ sync();
+ delete d;
+}
+
+QStringList KConfig::groupList() const
+{
+ Q_D(const KConfig);
+ QSet<QString> groups;
+
+ for (KEntryMap::ConstIterator entryMapIt( d->entryMap.constBegin() ); entryMapIt != d->entryMap.constEnd(); ++entryMapIt) {
+ const KEntryKey& key = entryMapIt.key();
+ const QByteArray group = key.mGroup;
+ if (key.mKey.isNull() && !group.isEmpty() && group != "<default>" && group != "$Version") {
+ const QString groupname = QString::fromUtf8(group);
+ groups << groupname.left(groupname.indexOf(QLatin1Char('\x1d')));
+ }
+ }
+
+ return groups.toList();
+}
+
+QStringList KConfigPrivate::groupList(const QByteArray& group) const
+{
+ QByteArray theGroup = group + '\x1d';
+ QSet<QString> groups;
+
+ for (KEntryMap::ConstIterator entryMapIt( entryMap.constBegin() ); entryMapIt != entryMap.constEnd(); ++entryMapIt) {
+ const KEntryKey& key = entryMapIt.key();
+ if (key.mKey.isNull() && key.mGroup.startsWith(theGroup)) {
+ const QString groupname = QString::fromUtf8(key.mGroup.mid(theGroup.length()));
+ groups << groupname.left(groupname.indexOf(QLatin1Char('\x1d')));
+ }
+ }
+
+ return groups.toList();
+}
+
+// List all sub groups, including subsubgroups
+QSet<QByteArray> KConfigPrivate::allSubGroups(const QByteArray& parentGroup) const
+{
+ QSet<QByteArray> groups;
+ QByteArray theGroup = parentGroup + '\x1d';
+ groups << parentGroup;
+
+ for (KEntryMap::const_iterator entryMapIt = entryMap.begin(); entryMapIt != entryMap.end(); ++entryMapIt) {
+ const KEntryKey& key = entryMapIt.key();
+ if (key.mKey.isNull() && key.mGroup.startsWith(theGroup)) {
+ groups << key.mGroup;
+ }
+ }
+ return groups;
+}
+
+bool KConfigPrivate::hasNonDeletedEntries(const QByteArray& group) const
+{
+ const QSet<QByteArray> allGroups = allSubGroups(group);
+
+ Q_FOREACH(const QByteArray& aGroup, allGroups) {
+ // Could be optimized, let's use the slow way for now
+ // Check for any non-deleted entry
+ if (!keyListImpl(aGroup).isEmpty())
+ return true;
+ }
+ return false;
+}
+
+
+QStringList KConfigPrivate::keyListImpl(const QByteArray& theGroup) const
+{
+ QStringList keys;
+
+ const KEntryMapConstIterator theEnd = entryMap.constEnd();
+ KEntryMapConstIterator it = entryMap.findEntry(theGroup);
+ if (it != theEnd) {
+ ++it; // advance past the special group entry marker
+
+ QSet<QString> tmp;
+ for (; it != theEnd && it.key().mGroup == theGroup; ++it) {
+ const KEntryKey& key = it.key();
+ if (key.mGroup == theGroup && !key.mKey.isNull() && !it->bDeleted)
+ tmp << QString::fromUtf8(key.mKey);
+ }
+ keys = tmp.toList();
+ }
+
+ return keys;
+}
+
+QStringList KConfig::keyList(const QString& aGroup) const
+{
+ Q_D(const KConfig);
+ const QByteArray theGroup(aGroup.isEmpty() ? "<default>" : aGroup.toUtf8());
+ return d->keyListImpl(theGroup);
+}
+
+QMap<QString,QString> KConfig::entryMap(const QString& aGroup) const
+{
+ Q_D(const KConfig);
+ QMap<QString, QString> theMap;
+ const QByteArray theGroup(aGroup.isEmpty() ? "<default>" : aGroup.toUtf8());
+
+ const KEntryMapConstIterator theEnd = d->entryMap.constEnd();
+ KEntryMapConstIterator it = d->entryMap.findEntry(theGroup, 0, 0);
+ if (it != theEnd) {
+ ++it; // advance past the special group entry marker
+
+ for (; it != theEnd && it.key().mGroup == theGroup; ++it) {
+ // leave the default values and deleted entries out
+ if (!it->bDeleted && !it.key().bDefault) {
+ const QString key = QString::fromUtf8(it.key().mKey.constData());
+ // the localized entry should come first, so don't overwrite it
+ // with the non-localized entry
+ if (!theMap.contains(key)) {
+ if (it->bExpand) {
+ theMap.insert(key,KConfigPrivate::expandString(QString::fromUtf8(it->mValue.constData())));
+ } else {
+ theMap.insert(key,QString::fromUtf8(it->mValue.constData()));
+ }
+ }
+ }
+ }
+ }
+
+ return theMap;
+}
+
+bool KConfig::sync()
+{
+ Q_D(KConfig);
+
+ if (isImmutable() || name().isEmpty()) {
+ // can't write to an immutable or anonymous file.
+ return false;
+ }
+
+ if (d->bDirty && d->mBackend) {
+ const QByteArray utf8Locale(locale().toUtf8());
+
+ // Create the containing dir, maybe it wasn't there
+ d->mBackend->createEnclosing();
+
+ // lock the local file
+ if (d->configState == ReadWrite && !d->lockLocal()) {
+ qWarning() << "couldn't lock local file";
+ return false;
+ }
+
+ // Rewrite global/local config only if there is a dirty entry in it.
+ bool writeGlobals = false;
+ bool writeLocals = false;
+ Q_FOREACH (const KEntry& e, d->entryMap) {
+ if (e.bDirty) {
+ if (e.bGlobal) {
+ writeGlobals = true;
+ } else {
+ writeLocals = true;
+ }
+
+ if (writeGlobals && writeLocals) {
+ break;
+ }
+ }
+ }
+
+ d->bDirty = false; // will revert to true if a config write fails
+
+ if (d->wantGlobals() && writeGlobals) {
+ QExplicitlySharedDataPointer<KConfigBackend> tmp = KConfigBackend::create(d->sGlobalFileName);
+ if (d->configState == ReadWrite && !tmp->lock()) {
+ qWarning() << "couldn't lock global file";
+ d->bDirty = true;
+ return false;
+ }
+ if (!tmp->writeConfig(utf8Locale, d->entryMap, KConfigBackend::WriteGlobal)) {
+ d->bDirty = true;
+ }
+ if (tmp->isLocked()) {
+ tmp->unlock();
+ }
+ }
+
+ if (writeLocals) {
+ if (!d->mBackend->writeConfig(utf8Locale, d->entryMap, KConfigBackend::WriteOptions())) {
+ d->bDirty = true;
+ }
+ }
+ if (d->mBackend->isLocked()) {
+ d->mBackend->unlock();
+ }
+ }
+ return !d->bDirty;
+}
+
+void KConfig::markAsClean()
+{
+ Q_D(KConfig);
+ d->bDirty = false;
+
+ // clear any dirty flags that entries might have set
+ const KEntryMapIterator theEnd = d->entryMap.end();
+ for (KEntryMapIterator it = d->entryMap.begin(); it != theEnd; ++it)
+ it->bDirty = false;
+}
+
+bool KConfig::isDirty() const
+{
+ Q_D(const KConfig);
+ return d->bDirty;
+}
+
+void KConfig::checkUpdate(const QString &id, const QString &updateFile)
+{
+ const KConfigGroup cg(this, "$Version");
+ const QString cfg_id = updateFile+QLatin1Char(':')+id;
+ const QStringList ids = cg.readEntry("update_info", QStringList());
+ if (!ids.contains(cfg_id)) {
+#if 0
+ KToolInvocation::kdeinitExecWait(QString::fromLatin1("kconf_update"), QStringList() << QString::fromLatin1("--check") << updateFile);
+#else
+ QProcess::execute(QString::fromLatin1("kconf_update"), QStringList() << QString::fromLatin1("--check") << updateFile);
+#endif
+ reparseConfiguration();
+ }
+}
+
+KConfig* KConfig::copyTo(const QString &file, KConfig *config) const
+{
+ Q_D(const KConfig);
+ if (!config)
+ config = new KConfig(QString(), SimpleConfig, d->resourceType);
+ config->d_func()->changeFileName(file);
+ config->d_func()->entryMap = d->entryMap;
+ config->d_func()->bFileImmutable = false;
+
+ const KEntryMapIterator theEnd = config->d_func()->entryMap.end();
+ for (KEntryMapIterator it = config->d_func()->entryMap.begin(); it != theEnd; ++it)
+ it->bDirty = true;
+ config->d_ptr->bDirty = true;
+
+ return config;
+}
+
+QString KConfig::name() const
+{
+ Q_D(const KConfig);
+ return d->fileName;
+}
+
+Q_GLOBAL_STATIC(QString, globalMainConfigName)
+
+void KConfig::setMainConfigName(const QString& str)
+{
+ *globalMainConfigName() = str;
+}
+
+QString KConfig::mainConfigName()
+{
+ // --config on the command line overrides everything else
+ const QStringList args = QCoreApplication::arguments();
+ for (int i = 1; i < args.count() ; ++i) {
+ if (args.at(i) == QLatin1String("--config") && i < args.count()-1) {
+ return args.at(i+1);
+ }
+ }
+ const QString globalName = *globalMainConfigName();
+ if (!globalName.isEmpty())
+ return globalName;
+
+ QString appName = QCoreApplication::applicationName();
+ return appName + QLatin1String("rc");
+}
+
+void KConfigPrivate::changeFileName(const QString& name)
+{
+ fileName = name;
+
+ QString file;
+ if (name.isEmpty()) {
+ if (wantDefaults()) { // accessing default app-specific config "appnamerc"
+ fileName = KConfig::mainConfigName();
+ file = QStandardPaths::writableLocation(resourceType) + QLatin1Char('/') + fileName;
+ } else if (wantGlobals()) { // accessing "kdeglobals" - XXX used anywhere?
+ resourceType = QStandardPaths::GenericConfigLocation;
+ fileName = QLatin1String("kdeglobals");
+ file = sGlobalFileName;
+ } else {
+ // anonymous config
+ openFlags = KConfig::SimpleConfig;
+ return;
+ }
+ } else if (QDir::isAbsolutePath(fileName)) {
+ fileName = QFileInfo(fileName).canonicalFilePath();
+ if (fileName.isEmpty()) // file doesn't exist (yet)
+ fileName = name;
+ file = fileName;
+ } else {
+ file = QStandardPaths::writableLocation(resourceType) + QLatin1Char('/') + fileName;
+ }
+
+ Q_ASSERT(!file.isEmpty());
+
+#ifndef Q_OS_WIN
+ bSuppressGlobal = (file == sGlobalFileName);
+#else
+ bSuppressGlobal = (file.compare(sGlobalFileName, Qt::CaseInsensitive) == 0);
+#endif
+
+ if (bDynamicBackend || !mBackend) // allow dynamic changing of backend
+ mBackend = KConfigBackend::create(file);
+ else
+ mBackend->setFilePath(file);
+
+ configState = mBackend->accessMode();
+}
+
+void KConfig::reparseConfiguration()
+{
+ Q_D(KConfig);
+ if (d->fileName.isEmpty()) {
+ return;
+ }
+
+ // Don't lose pending changes
+ if (!d->isReadOnly() && d->bDirty)
+ sync();
+
+ d->entryMap.clear();
+
+ d->bFileImmutable = false;
+
+ // Parse all desired files from the least to the most specific.
+ if (d->wantGlobals())
+ d->parseGlobalFiles();
+
+ d->parseConfigFiles();
+}
+
+
+QStringList KConfigPrivate::getGlobalFiles() const
+{
+ QStringList globalFiles;
+ Q_FOREACH (const QString& dir1, QStandardPaths::locateAll(QStandardPaths::GenericConfigLocation, QLatin1String("kdeglobals")))
+ globalFiles.push_front(dir1);
+ Q_FOREACH (const QString& dir2, QStandardPaths::locateAll(QStandardPaths::GenericConfigLocation, QLatin1String("system.kdeglobals")))
+ globalFiles.push_front(dir2);
+ if (!etc_kderc.isEmpty())
+ globalFiles.push_front(etc_kderc);
+ return globalFiles;
+}
+
+void KConfigPrivate::parseGlobalFiles()
+{
+ const QStringList globalFiles = getGlobalFiles();
+// qDebug() << "parsing global files" << globalFiles;
+
+ // TODO: can we cache the values in etc_kderc / other global files
+ // on a per-application basis?
+ const QByteArray utf8Locale = locale.toUtf8();
+ Q_FOREACH(const QString& file, globalFiles) {
+ KConfigBackend::ParseOptions parseOpts = KConfigBackend::ParseGlobal|KConfigBackend::ParseExpansions;
+#ifndef Q_OS_WIN
+ if (file != sGlobalFileName)
+#else
+ if (file.compare(sGlobalFileName, Qt::CaseInsensitive) != 0)
+#endif
+ parseOpts |= KConfigBackend::ParseDefaults;
+
+ QExplicitlySharedDataPointer<KConfigBackend> backend = KConfigBackend::create(file);
+ if ( backend->parseConfig( utf8Locale, entryMap, parseOpts) == KConfigBackend::ParseImmutable)
+ break;
+ }
+}
+
+void KConfigPrivate::parseConfigFiles()
+{
+ // can only read the file if there is a backend and a file name
+ if (mBackend && !fileName.isEmpty()) {
+
+ bFileImmutable = false;
+
+ QList<QString> files;
+ if (wantDefaults()) {
+ if (bSuppressGlobal) {
+ files = getGlobalFiles();
+ } else {
+ if (QDir::isAbsolutePath(fileName)) {
+ files << fileName;
+ } else {
+ Q_FOREACH (const QString& f, QStandardPaths::locateAll(resourceType, fileName))
+ files.prepend(f);
+ }
+ }
+ } else {
+ files << mBackend->filePath();
+ }
+ if (!isSimple())
+ files = extraFiles.toList() + files;
+
+// qDebug() << "parsing local files" << files;
+
+ const QByteArray utf8Locale = locale.toUtf8();
+ foreach(const QString& file, files) {
+#ifndef Q_OS_WIN
+ if (file == mBackend->filePath()) {
+#else
+ if (file.compare(mBackend->filePath(), Qt::CaseInsensitive) == 0) {
+#endif
+ switch (mBackend->parseConfig(utf8Locale, entryMap, KConfigBackend::ParseExpansions)) {
+ case KConfigBackend::ParseOk:
+ break;
+ case KConfigBackend::ParseImmutable:
+ bFileImmutable = true;
+ break;
+ case KConfigBackend::ParseOpenError:
+ configState = KConfigBase::NoAccess;
+ break;
+ }
+ } else {
+ QExplicitlySharedDataPointer<KConfigBackend> backend = KConfigBackend::create(file);
+ bFileImmutable = (backend->parseConfig(utf8Locale, entryMap,
+ KConfigBackend::ParseDefaults|KConfigBackend::ParseExpansions)
+ == KConfigBackend::ParseImmutable);
+ }
+
+ if (bFileImmutable)
+ break;
+ }
+#pragma message("TODO: enable kiosk feature again (resource restrictions), but without KStandardDirs... Needs a class in the kconfig framework.")
+#if 0
+ if (componentData.dirs()->isRestrictedResource(resourceType, fileName))
+ bFileImmutable = true;
+#endif
+ }
+}
+
+KConfig::AccessMode KConfig::accessMode() const
+{
+ Q_D(const KConfig);
+ return d->configState;
+}
+
+void KConfig::addConfigSources(const QStringList& files)
+{
+ Q_D(KConfig);
+ Q_FOREACH(const QString& file, files) {
+ d->extraFiles.push(file);
+ }
+
+ if (!files.isEmpty()) {
+ reparseConfiguration();
+ }
+}
+
+QString KConfig::locale() const
+{
+ Q_D(const KConfig);
+ return d->locale;
+}
+
+bool KConfigPrivate::setLocale(const QString& aLocale)
+{
+ if (aLocale != locale) {
+ locale = aLocale;
+ return true;
+ }
+ return false;
+}
+
+bool KConfig::setLocale(const QString& locale)
+{
+ Q_D(KConfig);
+ if (d->setLocale(locale)) {
+ reparseConfiguration();
+ return true;
+ }
+ return false;
+}
+
+void KConfig::setReadDefaults(bool b)
+{
+ Q_D(KConfig);
+ d->bReadDefaults = b;
+}
+
+bool KConfig::readDefaults() const
+{
+ Q_D(const KConfig);
+ return d->bReadDefaults;
+}
+
+bool KConfig::isImmutable() const
+{
+ Q_D(const KConfig);
+ return d->bFileImmutable;
+}
+
+bool KConfig::isGroupImmutableImpl(const QByteArray& aGroup) const
+{
+ Q_D(const KConfig);
+ return isImmutable() || d->entryMap.getEntryOption(aGroup, 0, 0, KEntryMap::EntryImmutable);
+}
+
+#ifndef KDE_NO_DEPRECATED
+void KConfig::setForceGlobal(bool b)
+{
+ Q_D(KConfig);
+ d->bForceGlobal = b;
+}
+#endif
+
+#ifndef KDE_NO_DEPRECATED
+bool KConfig::forceGlobal() const
+{
+ Q_D(const KConfig);
+ return d->bForceGlobal;
+}
+#endif
+
+KConfigGroup KConfig::groupImpl(const QByteArray &group)
+{
+ return KConfigGroup(this, group.constData());
+}
+
+const KConfigGroup KConfig::groupImpl(const QByteArray &group) const
+{
+ return KConfigGroup(this, group.constData());
+}
+
+KEntryMap::EntryOptions convertToOptions(KConfig::WriteConfigFlags flags)
+{
+ KEntryMap::EntryOptions options=0;
+
+ if (flags&KConfig::Persistent)
+ options |= KEntryMap::EntryDirty;
+ if (flags&KConfig::Global)
+ options |= KEntryMap::EntryGlobal;
+ if (flags&KConfig::Localized)
+ options |= KEntryMap::EntryLocalized;
+ return options;
+}
+
+void KConfig::deleteGroupImpl(const QByteArray &aGroup, WriteConfigFlags flags)
+{
+ Q_D(KConfig);
+ KEntryMap::EntryOptions options = convertToOptions(flags)|KEntryMap::EntryDeleted;
+
+ const QSet<QByteArray> groups = d->allSubGroups(aGroup);
+ Q_FOREACH (const QByteArray& group, groups) {
+ const QStringList keys = d->keyListImpl(group);
+ Q_FOREACH (const QString& _key, keys) {
+ const QByteArray &key = _key.toUtf8();
+ if (d->canWriteEntry(group, key.constData())) {
+ d->entryMap.setEntry(group, key, QByteArray(), options);
+ d->bDirty = true;
+ }
+ }
+ }
+}
+
+bool KConfig::isConfigWritable(bool warnUser)
+{
+ Q_D(KConfig);
+ bool allWritable = (d->mBackend ? d->mBackend->isWritable() : false);
+
+ if (warnUser && !allWritable) {
+ QString errorMsg;
+ if (d->mBackend) // TODO how can be it be null? Set errorMsg appropriately
+ errorMsg = d->mBackend->nonWritableErrorMessage();
+
+ // Note: We don't ask the user if we should not ask this question again because we can't save the answer.
+ errorMsg += QCoreApplication::translate("KConfig", "Please contact your system administrator.");
+ QString cmdToExec = QStandardPaths::findExecutable(QString::fromLatin1("kdialog"));
+ if (!cmdToExec.isEmpty())
+ {
+ QProcess::execute(cmdToExec, QStringList()
+ << QString::fromLatin1("--title") << QCoreApplication::applicationName()
+ << QString::fromLatin1("--msgbox") << errorMsg);
+ }
+ }
+
+ d->configState = allWritable ? ReadWrite : ReadOnly; // update the read/write status
+
+ return allWritable;
+}
+
+bool KConfig::hasGroupImpl(const QByteArray& aGroup) const
+{
+ Q_D(const KConfig);
+
+ // No need to look for the actual group entry anymore, or for subgroups:
+ // a group exists if it contains any non-deleted entry.
+
+ return d->hasNonDeletedEntries(aGroup);
+}
+
+bool KConfigPrivate::canWriteEntry(const QByteArray& group, const char* key, bool isDefault) const
+{
+ if (bFileImmutable ||
+ entryMap.getEntryOption(group, key, KEntryMap::SearchLocalized, KEntryMap::EntryImmutable))
+ return isDefault;
+ return true;
+}
+
+void KConfigPrivate::putData( const QByteArray& group, const char* key,
+ const QByteArray& value, KConfigBase::WriteConfigFlags flags, bool expand)
+{
+ KEntryMap::EntryOptions options = convertToOptions(flags);
+
+ if (bForceGlobal)
+ options |= KEntryMap::EntryGlobal;
+ if (expand)
+ options |= KEntryMap::EntryExpansion;
+
+ if (value.isNull()) // deleting entry
+ options |= KEntryMap::EntryDeleted;
+
+ bool dirtied = entryMap.setEntry(group, key, value, options);
+ if (dirtied && (flags & KConfigBase::Persistent))
+ bDirty = true;
+}
+
+void KConfigPrivate::revertEntry(const QByteArray& group, const char* key)
+{
+ bool dirtied = entryMap.revertEntry(group, key);
+ if (dirtied)
+ bDirty = true;
+}
+
+QByteArray KConfigPrivate::lookupData(const QByteArray& group, const char* key,
+ KEntryMap::SearchFlags flags) const
+{
+ if (bReadDefaults)
+ flags |= KEntryMap::SearchDefaults;
+ const KEntryMapConstIterator it = entryMap.findEntry(group, key, flags);
+ if (it == entryMap.constEnd())
+ return QByteArray();
+ return it->mValue;
+}
+
+QString KConfigPrivate::lookupData(const QByteArray& group, const char* key,
+ KEntryMap::SearchFlags flags, bool *expand) const
+{
+ if (bReadDefaults)
+ flags |= KEntryMap::SearchDefaults;
+ return entryMap.getEntry(group, key, QString(), flags, expand);
+}
+
+QStandardPaths::StandardLocation KConfig::locationType() const
+{
+ Q_D(const KConfig);
+ return d->resourceType;
+}
+
+void KConfig::virtual_hook(int /*id*/, void* /*data*/)
+{
+ /* nothing */
+}
diff --git a/tier1/kconfig/src/core/kconfig.h b/tier1/kconfig/src/core/kconfig.h
new file mode 100644
index 00000000..6dbf1d26
--- /dev/null
+++ b/tier1/kconfig/src/core/kconfig.h
@@ -0,0 +1,397 @@
+/*
+ This file is part of the KDE libraries
+ Copyright (c) 2006, 2007 Thomas Braxton <kde.braxton@gmail.com>
+ Copyright (c) 2001 Waldo Bastian <bastian@kde.org>
+ Copyright (c) 1999 Preston Brown <pbrown@kde.org>
+ Copyright (c) 1997 Matthias Kalle Dalheimer <kalle@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KCONFIG_H
+#define KCONFIG_H
+
+#include "kconfigbase.h"
+
+#include <kconfigcore_export.h>
+
+#include <QtCore/QString>
+#include <QtCore/QVariant>
+#include <QtCore/QByteArray>
+#include <QtCore/QList>
+#include <qstandardpaths.h>
+
+class KConfigGroup;
+class KEntryMap;
+class KConfigPrivate;
+
+/**
+ * \class KConfig kconfig.h <KConfig>
+ *
+ * \brief The central class of the KDE configuration data system.
+ *
+ * Quickstart:
+ *
+ * Get the default application config object via KSharedConfig::openConfig().
+ *
+ * Load a specific configuration file:
+ * \code
+ * KConfig config( "/etc/kderc", KConfig::SimpleConfig );
+ * \endcode
+ *
+ * Load the configuration of a specific component:
+ * \code
+ * KConfig config( "pluginrc" );
+ * \endcode
+ *
+ * In general it is recommended to use KSharedConfig instead of
+ * creating multiple instances of KConfig to avoid the overhead of
+ * separate objects or concerns about synchronizing writes to disk
+ * even if the configuration object is updated from multiple code paths.
+ * KSharedConfig provides a set of open methods as counterparts for the
+ * KConfig constructors.
+ *
+ * \sa KSharedConfig, KConfigGroup, <a href="http://techbase.kde.org/index.php?title=Development/Tutorials/KConfig">the techbase HOWTO on KConfig</a>.
+ */
+class KCONFIGCORE_EXPORT KConfig : public KConfigBase
+{
+public:
+ /**
+ * Determines how the system-wide and user's global settings will affect
+ * the reading of the configuration.
+ *
+ * If CascadeConfig is selected, system-wide configuration sources are used
+ * to provide defaults for the settings accessed through this object, or
+ * possibly to override those settings in certain cases.
+ *
+ * IncludeGlobals does the same, but with the global settings sources.
+ *
+ * Note that the main configuration source overrides the cascaded sources,
+ * which override those provided to addConfigSources(), which override the
+ * global sources. The exception is that if a key or group is marked as
+ * being immutable, it will not be overridden.
+ *
+ * Note that all values other than IncludeGlobals and CascadeConfig are
+ * convenience definitions for the basic mode.
+ * Do @em not combine them with anything.
+ */
+ enum OpenFlag {
+ IncludeGlobals = 0x01, ///< Blend kdeglobals into the config object.
+ CascadeConfig = 0x02, ///< Cascade to system-wide config files.
+
+ SimpleConfig = 0x00, ///< Just a single config file.
+ NoCascade = IncludeGlobals, ///< Include user's globals, but omit system settings.
+ NoGlobals = CascadeConfig, ///< Cascade to system settings, but omit user's globals.
+ FullConfig = IncludeGlobals|CascadeConfig ///< Fully-fledged config, including globals and cascading to system settings
+ };
+ Q_DECLARE_FLAGS(OpenFlags, OpenFlag)
+
+ /**
+ * Creates a KConfig object to manipulate a configuration file for the
+ * current application.
+ *
+ * If an absolute path is specified for @p file, that file will be used
+ * as the store for the configuration settings. If a non-absolute path
+ * is provided, the file will be looked for in the standard directory
+ * specified by type. If no path is provided, a default
+ * configuration file will be used based on the name of the main
+ * application component.
+ *
+ * @p mode determines whether the user or global settings will be allowed
+ * to influence the values returned by this object. See OpenFlags for
+ * more details.
+ *
+ * @note You probably want to use KSharedConfig::openConfig instead.
+ *
+ * @param file the name of the file. If an empty string is passed in
+ * and SimpleConfig is passed in for the OpenFlags, then an in-memory
+ * KConfig object is created which will not write out to file nor which
+ * requires any file in the filesystem at all.
+ * @param mode how global settings should affect the configuration
+ * options exposed by this KConfig object
+ * @param type The standard directory to look for the configuration
+ * file in
+ *
+ * @sa KSharedConfig::openConfig(const QString&, OpenFlags, const char*)
+ */
+ explicit KConfig(const QString& file = QString(), OpenFlags mode = FullConfig,
+ QStandardPaths::StandardLocation type = QStandardPaths::GenericConfigLocation);
+
+ /**
+ * @internal
+ *
+ * Creates a KConfig object using the specified backend. If the backend can not
+ * be found or loaded, then the standard configuration parser is used as a fallback.
+ *
+ * @param file the file to be parsed
+ * @param backend the backend to load
+ * @param type where to look for the file if an absolute path is not provided
+ *
+ * @since 4.1
+ */
+ KConfig(const QString& file, const QString& backend, QStandardPaths::StandardLocation type = QStandardPaths::GenericConfigLocation);
+
+ virtual ~KConfig();
+
+ /**
+ * Returns the standard location enum passed to the constructor.
+ * Used by KSharedConfig.
+ * @since 5.0
+ */
+ QStandardPaths::StandardLocation locationType() const;
+
+ /**
+ * Returns the filename used to store the configuration.
+ */
+ QString name() const;
+
+ /// @reimp
+ bool sync() Q_DECL_OVERRIDE;
+
+ /// Returns true if sync has any changes to write out.
+ /// @since 4.12
+ bool isDirty() const;
+
+ /// @reimp
+ void markAsClean();
+
+ /// @{ configuration object state
+ /// @reimp
+ AccessMode accessMode() const;
+
+ /**
+ * Whether the configuration can be written to.
+ *
+ * If @p warnUser is true and the configuration cannot be
+ * written to (ie: this method returns @c false), a warning
+ * message box will be shown to the user telling them to
+ * contact their system administrator to get the problem fixed.
+ *
+ * The most likely cause for this method returning @c false
+ * is that the user does not have write permission for the
+ * configuration file.
+ *
+ * @param warnUser whether to show a warning message to the user
+ * if the configuration cannot be written to
+ *
+ * @returns true if the configuration can be written to, false
+ * if the configuration cannot be written to
+ */
+ bool isConfigWritable(bool warnUser);
+ /// @}
+
+ /**
+ * Copies all entries from this config object to a new config
+ * object that will save itself to @p file.
+ *
+ * The configuration will not actually be saved to @p file
+ * until the returned object is destroyed, or sync() is called
+ * on it.
+ *
+ * Do not forget to delete the returned KConfig object if
+ * @p config was 0.
+ *
+ * @param file the new config object will save itself to
+ * @param config if not 0, copy to the given KConfig object rather
+ * than creating a new one
+ *
+ * @return @p config if it was set, otherwise a new KConfig object
+ */
+ KConfig* copyTo(const QString &file, KConfig *config = 0) const;
+
+ /**
+ * Ensures that the configuration file contains a certain update.
+ *
+ * If the configuration file does not contain the update @p id
+ * as contained in @p updateFile, kconf_update is run to update
+ * the configuration file.
+ *
+ * If you install config update files with critical fixes
+ * you may wish to use this method to verify that a critical
+ * update has indeed been performed to catch the case where
+ * a user restores an old config file from backup that has
+ * not been updated yet.
+ *
+ * @param id the update to check
+ * @param updateFile the file containing the update
+ */
+ void checkUpdate(const QString &id, const QString &updateFile);
+
+ /**
+ * Updates the state of this object to match the persistent storage.
+ */
+ void reparseConfiguration();
+
+ /// @{ extra config files
+ /**
+ * Adds the list of configuration sources to the merge stack.
+ *
+ * Currently only files are accepted as configuration sources.
+ *
+ * The first entry in @p sources is treated as the most general and will
+ * be overridden by the second entry. The settings in the final entry
+ * in @p sources will override all the other sources provided in the list.
+ *
+ * The settings in @p sources will also be overridden by the sources
+ * provided by any previous calls to addConfigSources().
+ *
+ * The settings in the global configuration sources will be overridden by
+ * the sources provided to this method (@see IncludeGlobals).
+ * All the sources provided to any call to this method will be overridden
+ * by any files that cascade from the source provided to the constructor
+ * (@see CascadeConfig), which will in turn be
+ * overridden by the source provided to the constructor.
+ *
+ * Note that only the most specific file, ie: the file provided to the
+ * constructor, will be written to by this object.
+ *
+ * The state is automatically updated by this method, so there is no need to call
+ * reparseConfiguration().
+ *
+ * @param sources A list of extra config sources.
+ */
+ void addConfigSources(const QStringList &sources);
+
+ /// @}
+ /// @{ locales
+ /**
+ * Returns the current locale.
+ */
+ QString locale() const;
+ /**
+ * Sets the locale to @p aLocale.
+ *
+ * The global locale is used by default.
+ *
+ * @note If set to the empty string, @b no locale will be matched. This effectively disables
+ * reading translated entries.
+ *
+ * @return @c true if locale was changed, @c false if the call had no
+ * effect (eg: @p aLocale was already the current locale for this
+ * object)
+ */
+ bool setLocale(const QString& aLocale);
+ /// @}
+
+ /// @{ defaults
+ /**
+ * When set, all readEntry calls return the system-wide (default) values
+ * instead of the user's settings.
+ *
+ * This is off by default.
+ *
+ * @param b whether to read the system-wide defaults instead of the
+ * user's settings
+ */
+ void setReadDefaults(bool b);
+ /**
+ * @returns @c true if the system-wide defaults will be read instead of the
+ * user's settings
+ */
+ bool readDefaults() const;
+ /// @}
+
+ /// @{ immutability
+ /// @reimp
+ bool isImmutable() const;
+ /// @}
+
+ /// @{ global
+ /**
+ * @deprecated
+ *
+ * Forces all following write-operations to be performed on @c kdeglobals,
+ * independent of the @c Global flag in writeEntry().
+ *
+ * @param force true to force writing to kdeglobals
+ * @see forceGlobal
+ */
+#ifndef KDE_NO_DEPRECATED
+ KCONFIGCORE_DEPRECATED void setForceGlobal(bool force);
+#endif
+ /**
+ * @deprecated
+ *
+ * Returns whether all entries are being written to @c kdeglobals.
+ *
+ * @return @c true if all entries are being written to @c kdeglobals
+ * @see setForceGlobal
+ * @deprecated
+ */
+#ifndef KDE_NO_DEPRECATED
+ KCONFIGCORE_DEPRECATED bool forceGlobal() const;
+#endif
+ /// @}
+
+ /// @reimp
+ QStringList groupList() const;
+
+ /**
+ * Returns a map (tree) of entries in a particular group.
+ *
+ * The entries are all returned as strings.
+ *
+ * @param aGroup The group to get entries from.
+ *
+ * @return A map of entries in the group specified, indexed by key.
+ * The returned map may be empty if the group is empty, or not found.
+ * @see QMap
+ */
+ QMap<QString, QString> entryMap(const QString &aGroup=QString()) const;
+
+ /**
+ * Sets the name of the application config file.
+ * @since 5.0
+ */
+ static void setMainConfigName(const QString& str);
+
+protected:
+ virtual bool hasGroupImpl(const QByteArray &group) const;
+ virtual KConfigGroup groupImpl( const QByteArray &b);
+ virtual const KConfigGroup groupImpl(const QByteArray &b) const;
+ virtual void deleteGroupImpl(const QByteArray &group, WriteConfigFlags flags = Normal);
+ virtual bool isGroupImmutableImpl(const QByteArray& aGroup) const;
+
+ friend class KConfigGroup;
+ friend class KConfigGroupPrivate;
+ friend class KSharedConfig;
+
+ /** Virtual hook, used to add new "virtual" functions while maintaining
+ * binary compatibility. Unused in this class.
+ */
+ virtual void virtual_hook( int id, void* data );
+
+ KConfigPrivate *const d_ptr;
+
+ KConfig(KConfigPrivate &d);
+
+private:
+ friend class KConfigTest;
+
+ QStringList keyList(const QString& aGroup=QString()) const;
+
+ /**
+ * @internal for KSharedConfig. Could be made public if needed, though.
+ */
+ static QString mainConfigName();
+
+ Q_DISABLE_COPY(KConfig)
+
+ Q_DECLARE_PRIVATE(KConfig)
+};
+Q_DECLARE_OPERATORS_FOR_FLAGS( KConfig::OpenFlags )
+
+#endif // KCONFIG_H
diff --git a/tier1/kconfig/src/core/kconfig_p.h b/tier1/kconfig/src/core/kconfig_p.h
new file mode 100644
index 00000000..e6fb1ca0
--- /dev/null
+++ b/tier1/kconfig/src/core/kconfig_p.h
@@ -0,0 +1,110 @@
+/*
+ This file is part of the KDE libraries
+ Copyright (c) 2006, 2007 Thomas Braxton <kde.braxton@gmail.com>
+ Copyright (c) 2001 Waldo Bastian <bastian@kde.org>
+ Copyright (c) 1999 Preston Brown <pbrown@kde.org>
+ Copyright (c) 1997 Matthias Kalle Dalheimer <kalle@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KCONFIG_P_H
+#define KCONFIG_P_H
+
+#include "kconfigdata.h"
+#include "kconfigbackend.h"
+#include "kconfiggroup.h"
+
+#include <QtCore/QStringList>
+#include <QtCore/QStack>
+#include <QtCore/QFile>
+#include <QtCore/QDir>
+
+class KConfigPrivate
+{
+ friend class KConfig;
+public:
+ KConfig::OpenFlags openFlags;
+ QStandardPaths::StandardLocation resourceType;
+
+ void changeFileName(const QString& fileName);
+
+ // functions for KConfigGroup
+ bool canWriteEntry(const QByteArray& group, const char* key, bool isDefault=false) const;
+ QString lookupData(const QByteArray& group, const char* key, KEntryMap::SearchFlags flags,
+ bool* expand) const;
+ QByteArray lookupData(const QByteArray& group, const char* key, KEntryMap::SearchFlags flags) const;
+
+ void putData(const QByteArray& group, const char* key, const QByteArray& value,
+ KConfigBase::WriteConfigFlags flags, bool expand=false);
+ void revertEntry(const QByteArray& group, const char* key);
+ QStringList groupList(const QByteArray& group) const;
+ // copies the entries from @p source to @p otherGroup changing all occurrences
+ // of @p source with @p destination
+ void copyGroup(const QByteArray& source, const QByteArray& destination,
+ KConfigGroup *otherGroup, KConfigBase::WriteConfigFlags flags) const;
+ QStringList keyListImpl(const QByteArray& theGroup) const;
+ QSet<QByteArray> allSubGroups(const QByteArray& parentGroup) const;
+ bool hasNonDeletedEntries(const QByteArray& group) const;
+
+ static QString expandString(const QString& value);
+
+protected:
+ QExplicitlySharedDataPointer<KConfigBackend> mBackend;
+
+ KConfigPrivate(KConfig::OpenFlags flags,
+ QStandardPaths::StandardLocation type);
+
+ virtual ~KConfigPrivate()
+ {
+ }
+
+ bool bDynamicBackend:1; // do we own the backend?
+private:
+ bool bDirty:1;
+ bool bLocaleInitialized:1;
+ bool bReadDefaults:1;
+ bool bFileImmutable:1;
+ bool bForceGlobal:1;
+ bool bSuppressGlobal:1;
+
+ QString sGlobalFileName;
+ static bool mappingsRegistered;
+
+
+ KEntryMap entryMap;
+ QString backendType;
+ QStack<QString> extraFiles;
+
+ QString locale;
+ QString fileName;
+ QString etc_kderc;
+ KConfigBase::AccessMode configState;
+
+ bool wantGlobals() const { return openFlags&KConfig::IncludeGlobals && !bSuppressGlobal; }
+ bool wantDefaults() const { return openFlags&KConfig::CascadeConfig; }
+ bool isSimple() const { return openFlags == KConfig::SimpleConfig; }
+ bool isReadOnly() const { return configState == KConfig::ReadOnly; }
+
+ bool setLocale(const QString& aLocale);
+ QStringList getGlobalFiles() const;
+ void parseGlobalFiles();
+ void parseConfigFiles();
+ void initCustomized(KConfig*);
+ bool lockLocal();
+};
+
+#endif // KCONFIG_P_H
diff --git a/tier1/kconfig/src/core/kconfigbackend.cpp b/tier1/kconfig/src/core/kconfigbackend.cpp
new file mode 100644
index 00000000..eb92a964
--- /dev/null
+++ b/tier1/kconfig/src/core/kconfigbackend.cpp
@@ -0,0 +1,123 @@
+/*
+ This file is part of the KDE libraries
+ Copyright (c) 2006 Thomas Braxton <brax108@cox.net>
+ Copyright (c) 1999 Preston Brown <pbrown@kde.org>
+ Copyright (c) 1997-1999 Matthias Kalle Dalheimer <kalle@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "kconfigbackend.h"
+
+#include <QtCore/QDateTime>
+#include <QtCore/QStringList>
+#include <QtCore/QDir>
+#include <QtCore/QFileInfo>
+#include <QtCore/QHash>
+#include <QtCore/QDebug>
+
+#include "kconfig.h"
+#include "kconfigini_p.h"
+#include "kconfigdata.h"
+
+typedef QExplicitlySharedDataPointer<KConfigBackend> BackendPtr;
+
+class KConfigBackend::Private
+{
+public:
+ qint64 size;
+ QDateTime lastModified;
+ QString localFileName;
+
+ static QString whatSystem(const QString& /*fileName*/)
+ {
+ return QLatin1String("INI");
+ }
+};
+
+
+void KConfigBackend::registerMappings(const KEntryMap& /*entryMap*/)
+{
+}
+
+BackendPtr KConfigBackend::create(const QString& file, const QString& sys)
+{
+ //qDebug() << "creating a backend for file" << file << "with system" << sys;
+ const QString system = (sys.isEmpty() ? Private::whatSystem(file) : sys);
+ KConfigBackend* backend = 0;
+
+#if 0 // TODO port to Qt5 plugin loading
+ if (system.compare(QLatin1String("INI"), Qt::CaseInsensitive) != 0) {
+ const QString constraint = QString::fromLatin1("[X-KDE-PluginInfo-Name] ~~ '%1'").arg(system);
+ KService::List offers = KServiceTypeTrader::self()->query(QLatin1String("KConfigBackend"), constraint);
+
+ //qDebug() << "found" << offers.count() << "offers for KConfigBackend plugins with name" << system;
+ foreach (const KService::Ptr& offer, offers) {
+ backend = offer->createInstance<KConfigBackend>(0);
+ if (backend) {
+ //qDebug() << "successfully created a backend for" << system;
+ backend->setFilePath(file);
+ return BackendPtr(backend);
+ }
+ } // foreach offers
+ }
+#endif
+
+ //qDebug() << "default creation of the Ini backend";
+ backend = new KConfigIniBackend;
+ backend->setFilePath(file);
+ return BackendPtr(backend);
+}
+
+KConfigBackend::KConfigBackend()
+ : d(new Private)
+{
+}
+
+KConfigBackend::~KConfigBackend()
+{
+ delete d;
+}
+
+QDateTime KConfigBackend::lastModified() const
+{
+ return d->lastModified;
+}
+
+void KConfigBackend::setLastModified(const QDateTime& dt)
+{
+ d->lastModified = dt;
+}
+
+qint64 KConfigBackend::size() const
+{
+ return d->size;
+}
+
+void KConfigBackend::setSize(qint64 sz)
+{
+ d->size = sz;
+}
+
+QString KConfigBackend::filePath() const
+{
+ return d->localFileName;
+}
+
+void KConfigBackend::setLocalFilePath(const QString& file)
+{
+ d->localFileName = file;
+}
diff --git a/tier1/kconfig/src/core/kconfigbackend.desktop b/tier1/kconfig/src/core/kconfigbackend.desktop
new file mode 100644
index 00000000..bebcbff6
--- /dev/null
+++ b/tier1/kconfig/src/core/kconfigbackend.desktop
@@ -0,0 +1,86 @@
+[Desktop Entry]
+Type=ServiceType
+X-KDE-ServiceType=KConfigBackend
+
+Comment=Storage backend for KConfig
+Comment[ar]=خلفية الحفظ لـ KConfig
+Comment[as]=KConfig ৰ বাবে ভঁৰালৰ বেকএন্ড
+Comment[ast]=Infraestructura d'atroxamientu pa KConfig
+Comment[be@latin]=Słužba schovišča dla systemy „KConfig”
+Comment[bg]=Storage backend for KConfig
+Comment[bn]=KConfig-এর স্টোরেজ ব্যাকেন্ড
+Comment[bn_IN]=KConfig-র জন্য ব্যবহৃত ব্যাক-এন্ড সংগ্রহস্থল
+Comment[bs]=Skladišna pozadina za K‑konfig
+Comment[ca]=Dorsal d'emmagatzematge per al KConfig
+Comment[ca@valencia]=Dorsal d'emmagatzematge per al KConfig
+Comment[cs]=Úložiště pro KConfig
+Comment[csb]=Zôpisownô zbiérnica dlô KConfig
+Comment[da]=Lagringsmotor til KConfig
+Comment[de]=Speicher-Unterstützung für KConfig
+Comment[el]=Σύστημα υποστήριξης αποθήκευσης για το KConfig
+Comment[en_GB]=Storage backend for KConfig
+Comment[es]=Motor de almacenamiento para KConfig
+Comment[et]=KConfigi salvestamise taustaprogramm
+Comment[eu]=KConfig-en biltegiratze euskarria
+Comment[fi]=Asetusvaraston taustaosa
+Comment[fr]=Module de stockage pour KConfig
+Comment[fy]=Opslach efterein foar KConfig
+Comment[ga]=Inneall stórais KConfig
+Comment[gl]=Infraestrutura de almacenaxe para KConfig
+Comment[gu]=KConfig માટે સંગ્રહ પાશ્ર્વભાગ
+Comment[he]=מנוע שמירה עבור KConfig
+Comment[hne]=के-कानफिग बर भंडार बैकएण्ड
+Comment[hr]=Skladišna pozadina za KConfig
+Comment[hsb]=składowanski backend za KConfig
+Comment[hu]=Tároló a KConfighoz
+Comment[hy]=Բահեստի հետևի մասը KConfig-ի համար
+Comment[ia]=Retro-administration de immagazinage (storage) pro Kconfig
+Comment[id]=Backend penyimpanan untuk KConfig
+Comment[is]=Geymslubakendi fyrir KConfig
+Comment[it]=Backend di archiviazione per KConfig
+Comment[ja]=KConfig のストレージバックエンド
+Comment[kk]=KConfig үшін сақтау тетігі
+Comment[km]=កម្មវិធី​ខាងក្រោយ​ការ​ផ្ទុក​សម្រាប់ KConfig
+Comment[kn]=ಕೆಕಾನ್ಫಿಗ್ ಗೆ ಸಂಗ್ರಹಣಾ ಹಿಂಬದಿ (ಬಾಕೆಂಡ್)
+Comment[ko]=KConfig의 저장소 백엔드
+Comment[ku]=Embara ser-dawî ji bo KVeavakirin
+Comment[lt]=KConfig saugojimo sąsaja
+Comment[lv]=KConfig glabāšanas aizmugure
+Comment[mai]=KConfig क' लेल भंडारक बैकेंड
+Comment[ml]=കെകോണ്‍ഫിഗിനുളള സ്റ്റോറേജ് ബാക്കെന്‍ഡ്
+Comment[mr]=के-कॉन्फिग करिता संचयन बॅकएन्ड
+Comment[ms]=Storan belakang untuk KConfig
+Comment[nb]=Bakgrunnslagring for KConfig
+Comment[nds]=Spieker-Hülpprogramm för KConfig
+Comment[nl]=Opslagbackend voor KConfig
+Comment[nn]=Lagringsmotor for KConfig
+Comment[or]=KConfig ପାଇଁ ଭଣ୍ଡାର ପଛ ପାଖ
+Comment[pa]=KConfig ਲਈ ਸਟੋਰੇਜ਼ ਬੈਕਐਂਡ
+Comment[pl]=Przechowywanie danych dla KConfig
+Comment[pt]=Armazenamento da infra-estrutura do KConfig
+Comment[pt_BR]=Infraestrutura de armazenamento para o KConfig
+Comment[ro]=Suport de stocare pentru KConfig
+Comment[ru]=Модуль хранения параметров KConfig
+Comment[se]=KConfig vurkenduogáš
+Comment[si]=KConfig සඳහා ගබඩා පසුඈදුම
+Comment[sk]=Úložisko pre KConfig
+Comment[sl]=Zaledje za shranjevanje v KConfig
+Comment[sq]=Mbështetëse Ruajtëse për KConfig
+Comment[sr]=Складишна позадина за К‑конфиг
+Comment[sr@ijekavian]=Складишна позадина за К‑конфиг
+Comment[sr@ijekavianlatin]=Skladišna pozadina za KConfig
+Comment[sr@latin]=Skladišna pozadina za KConfig
+Comment[sv]=Lagringsgränssnitt för KConfig
+Comment[ta]=கேவடிவமைப்பிற்கான பின்னணி சேமிப்பகம்
+Comment[tg]=Пуштибонии захирагоҳ барои KConfig
+Comment[th]=โปรแกรมเบื้องหลังพื้นที่จัดเก็บข้อมูลสำหรับ KConfig
+Comment[tr]=KConfig için Depolama Arka Ucu
+Comment[tt]=KConfig өчен саклау бэкенды
+Comment[ug]=KConfig نىڭ ساقلاش ئارقا ئۇچى
+Comment[uk]=Засіб збереження для KConfig
+Comment[vi]=Hậu trường lưu trữ cho KConfig
+Comment[wa]=Bouye di fond di stocaedje po KConfig
+Comment[x-test]=xxStorage backend for KConfigxx
+Comment[zh_CN]=KConfig 存储后端
+Comment[zh_TW]=KConfig 儲存後端介面
+
diff --git a/tier1/kconfig/src/core/kconfigbackend.h b/tier1/kconfig/src/core/kconfigbackend.h
new file mode 100644
index 00000000..49239e66
--- /dev/null
+++ b/tier1/kconfig/src/core/kconfigbackend.h
@@ -0,0 +1,211 @@
+/*
+ This file is part of the KDE libraries
+ Copyright (c) 2006, 2007 Thomas Braxton <kde.braxton@gmail.com>
+ Copyright (c) 1999 Preston Brown <pbrown@kde.org>
+ Portions copyright (c) 1997 Matthias Kalle Dalheimer <kalle@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KCONFIGBACKEND_H
+#define KCONFIGBACKEND_H
+
+#include <QtCore/QObject>
+#include <QtCore/QString>
+#include <QExplicitlySharedDataPointer>
+
+#include <kconfigcore_export.h>
+#include <kconfigbase.h>
+
+class KEntryMap;
+class QFile;
+class QByteArray;
+class QDateTime;
+
+/**
+ * \class KConfigBackend kconfigbackend.h <KConfigBackend>
+ *
+ * Provides the implementation for accessing configuration sources.
+ *
+ * KDELibs only provides an INI backend, but this class can be used
+ * to create plugins that allow access to other file formats and
+ * configuration systems.
+ */
+class KCONFIGCORE_EXPORT KConfigBackend : public QObject, public QSharedData
+{
+ Q_OBJECT
+ Q_FLAGS(ParseOption)
+ Q_FLAGS(WriteOption)
+
+public:
+ /**
+ * Creates a new KConfig backend.
+ *
+ * If no @p system is given, or the given @p system is unknown, this method tries
+ * to determine the correct backend to use.
+ *
+ * @param fileName the absolute file name of the configuration file
+ * @param system the configuration system to use
+ * @return a KConfigBackend object to be used with KConfig
+ */
+ static QExplicitlySharedDataPointer<KConfigBackend> create(const QString& fileName = QString(),
+ const QString& system = QString());
+
+ /**
+ * Registers mappings from directories/files to configuration systems
+ *
+ * Allows you to tell KConfigBackend that create() should use a particular
+ * backend for a particular file or directory.
+ *
+ * @warning currently does nothing
+ *
+ * @param entryMap the KEntryMap to build the mappings from
+ */
+ static void registerMappings(const KEntryMap& entryMap);
+
+ /** Destroys the backend */
+ virtual ~KConfigBackend();
+
+ /** Allows the behaviour of parseConfig() to be tuned */
+ enum ParseOption {
+ ParseGlobal = 1, /// entries should be marked as @em global
+ ParseDefaults = 2, /// entries should be marked as @em default
+ ParseExpansions = 4 /// entries are allowed to be marked as @em expandable
+ };
+ /// @typedef typedef QFlags<ParseOption> ParseOptions
+ Q_DECLARE_FLAGS(ParseOptions, ParseOption)
+
+ /** Allows the behaviour of writeConfig() to be tuned */
+ enum WriteOption {
+ WriteGlobal = 1 /// only write entries marked as "global"
+ };
+ /// @typedef typedef QFlags<WriteOption> WriteOptions
+ Q_DECLARE_FLAGS(WriteOptions, WriteOption)
+
+ /** Return value from parseConfig() */
+ enum ParseInfo {
+ ParseOk, /// the configuration was opened read/write
+ ParseImmutable, /// the configuration is @em immutable
+ ParseOpenError /// the configuration could not be opened
+ };
+
+ /**
+ * Read persistent storage
+ *
+ * @param locale the locale to read entries for (if the backend supports localized entries)
+ * @param pWriteBackMap the KEntryMap where the entries are placed
+ * @param options @see ParseOptions
+ * @return @see ParseInfo
+ */
+ virtual ParseInfo parseConfig(const QByteArray& locale,
+ KEntryMap& pWriteBackMap,
+ ParseOptions options = ParseOptions()) = 0;
+
+ /**
+ * Write the @em dirty entries to permanent storage
+ *
+ * @param locale the locale to write entries for (if the backend supports localized entries)
+ * @param entryMap the KEntryMap containing the config object's entries.
+ * @param options @see WriteOptions
+ *
+ * @return @c true if the write was successful, @c false if writing the configuration failed
+ */
+ virtual bool writeConfig(const QByteArray& locale, KEntryMap& entryMap,
+ WriteOptions options) = 0;
+
+ /**
+ * If isWritable() returns false, writeConfig() will always fail.
+ *
+ * @return @c true if the configuration is writable, @c false if it is immutable
+ */
+ virtual bool isWritable() const = 0;
+ /**
+ * When isWritable() returns @c false, return an error message to
+ * explain to the user why saving configuration will not work.
+ *
+ * The return value when isWritable() returns @c true is undefined.
+ *
+ * @returns a translated user-visible explanation for the configuration
+ * object not being writable
+ */
+ virtual QString nonWritableErrorMessage() const = 0;
+ /**
+ * @return the read/write status of the configuration object
+ *
+ * @see KConfigBase::AccessMode
+ */
+ virtual KConfigBase::AccessMode accessMode() const = 0;
+ /**
+ * Create the enclosing object of the configuration object
+ *
+ * For example, if the configuration object is a file, this should create
+ * the parent directory.
+ */
+ virtual void createEnclosing() = 0;
+
+ /**
+ * Set the file path.
+ *
+ * @note @p path @b MUST be @em absolute.
+ *
+ * @param path the absolute file path
+ */
+ virtual void setFilePath(const QString& path) = 0;
+
+ /**
+ * Lock the file
+ */
+ virtual bool lock() = 0;
+ /**
+ * Release the lock on the file
+ */
+ virtual void unlock() = 0;
+ /**
+ * @return @c true if the file is locked, @c false if it is not locked
+ */
+ virtual bool isLocked() const = 0;
+
+ /**
+ * @return the date and time when the object was last modified
+ */
+ QDateTime lastModified() const;
+ /** @return the absolute path to the object */
+ QString filePath() const;
+ /** @return the size of the object */
+ qint64 size() const;
+
+protected:
+ KConfigBackend();
+ void setLastModified(const QDateTime& dt);
+ void setSize(qint64 sz);
+ void setLocalFilePath(const QString& file);
+
+private:
+ class Private;
+ Private *const d;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(KConfigBackend::ParseOptions)
+Q_DECLARE_OPERATORS_FOR_FLAGS(KConfigBackend::WriteOptions)
+
+/**
+ * Register a KConfig backend when it is contained in a loadable module
+ */
+#define K_EXPORT_KCONFIGBACKEND(libname, classname) \
+K_PLUGIN_FACTORY(factory, registerPlugin<classname>();)
+
+
+#endif // KCONFIGBACKEND_H
diff --git a/tier1/kconfig/src/core/kconfigbase.cpp b/tier1/kconfig/src/core/kconfigbase.cpp
new file mode 100644
index 00000000..4be7ac23
--- /dev/null
+++ b/tier1/kconfig/src/core/kconfigbase.cpp
@@ -0,0 +1,112 @@
+/*
+ This file is part of the KDE libraries
+ Copyright (c) 2006, 2007 Thomas Braxton <kde.braxton@gmail.com>
+ Copyright (c) 1999 Preston Brown <pbrown@kde.org>
+ Copyright (c) 1997-1999 Matthias Kalle Dalheimer <kalle@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "kconfigbase.h"
+
+#include "kconfiggroup.h"
+
+#include <QtCore/QString>
+
+bool KConfigBase::hasGroup(const QString &group) const
+{
+ return hasGroupImpl(group.toUtf8());
+}
+
+bool KConfigBase::hasGroup(const char *group) const
+{
+ return hasGroupImpl(QByteArray(group));
+}
+
+bool KConfigBase::hasGroup(const QByteArray &group) const
+{
+ return hasGroupImpl(group);
+}
+
+KConfigGroup KConfigBase::group( const QByteArray &b)
+{
+ return groupImpl(b);
+}
+
+KConfigGroup KConfigBase::group( const QString &str)
+{
+ return groupImpl(str.toUtf8());
+}
+
+KConfigGroup KConfigBase::group( const char *str)
+{
+ return groupImpl(QByteArray(str));
+}
+
+const KConfigGroup KConfigBase::group( const QByteArray &b ) const
+{
+ return groupImpl(b);
+}
+
+const KConfigGroup KConfigBase::group( const QString &s ) const
+{
+ return groupImpl(s.toUtf8());
+}
+
+const KConfigGroup KConfigBase::group( const char *s ) const
+{
+ return groupImpl(QByteArray(s));
+}
+
+void KConfigBase::deleteGroup(const QByteArray &group, WriteConfigFlags flags)
+{
+ deleteGroupImpl(group, flags);
+}
+
+void KConfigBase::deleteGroup(const QString &group, WriteConfigFlags flags)
+{
+ deleteGroupImpl(group.toUtf8(), flags);
+}
+
+void KConfigBase::deleteGroup(const char *group, WriteConfigFlags flags)
+{
+ deleteGroupImpl(QByteArray(group), flags);
+}
+
+bool KConfigBase::isGroupImmutable(const QByteArray& aGroup) const
+{
+ return isGroupImmutableImpl(aGroup);
+}
+
+bool KConfigBase::isGroupImmutable(const QString& aGroup) const
+{
+ return isGroupImmutableImpl(aGroup.toUtf8());
+}
+
+
+bool KConfigBase::isGroupImmutable(const char *aGroup) const
+{
+ return isGroupImmutableImpl(QByteArray(aGroup));
+}
+
+KConfigBase::~KConfigBase()
+{}
+
+KConfigBase::KConfigBase()
+{}
+
+void KConfigBase::virtual_hook(int , void *)
+{}
diff --git a/tier1/kconfig/src/core/kconfigbase.h b/tier1/kconfig/src/core/kconfigbase.h
new file mode 100644
index 00000000..782ff4b6
--- /dev/null
+++ b/tier1/kconfig/src/core/kconfigbase.h
@@ -0,0 +1,184 @@
+/*
+ This file is part of the KDE libraries
+ Copyright (c) 2006, 2007 Thomas Braxton <kde.braxton@gmail.com>
+ Copyright (c) 2001 Waldo Bastian <bastian@kde.org>
+ Copyright (c) 1999 Preston Brown <pbrown@kde.org>
+ Copyright (c) 1997 Matthias Kalle Dalheimer <kalle@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KCONFIGBASE_H
+#define KCONFIGBASE_H
+
+#include <kconfigcore_export.h>
+
+#include <QtCore/QtGlobal>
+
+class QStringList;
+class KConfigGroup;
+class KConfigBasePrivate;
+
+/**
+ * \class KConfigBase kconfigbase.h <KConfigBase>
+ */
+class KCONFIGCORE_EXPORT KConfigBase
+{
+public:
+ /**
+ * Flags to control write entry
+ */
+ enum WriteConfigFlag
+ {
+ Persistent = 0x01,
+ /**<
+ * Save this entry when saving the config object.
+ */
+ Global = 0x02,
+ /**<
+ * Save the entry to the global %KDE config file instead of the
+ * application specific config file.
+ */
+ Localized = 0x04,
+ /**<
+ * Add the locale tag to the key when writing it.
+ */
+ Normal=Persistent
+ /**<
+ * Save the entry to the application specific config file without
+ * a locale tag. This is the default.
+ */
+
+ };
+ Q_DECLARE_FLAGS(WriteConfigFlags, WriteConfigFlag)
+
+ /**
+ * Destructs the KConfigBase object.
+ */
+ virtual ~KConfigBase();
+
+ /**
+ * Returns a list of groups that are known about.
+ *
+ * @return The list of groups.
+ **/
+ virtual QStringList groupList() const = 0;
+
+ /**
+ * Returns true if the specified group is known about.
+ *
+ * @param group The group to search for.
+ * @return true if the group exists.
+ */
+ bool hasGroup(const QString &group) const;
+ bool hasGroup(const char *group) const;
+ bool hasGroup(const QByteArray &group) const;
+
+ /**
+ * Returns an object for the named subgroup.
+ *
+ * @param group the group to open. Pass a null string on to the KConfig
+ * object to obtain a handle on the root group.
+ * @return The list of groups.
+ **/
+ KConfigGroup group(const QByteArray &group);
+ KConfigGroup group(const QString &group);
+ KConfigGroup group(const char *group);
+
+ /**
+ * @overload
+ **/
+ const KConfigGroup group(const QByteArray &group) const;
+ const KConfigGroup group(const QString &group) const;
+ const KConfigGroup group(const char *group) const;
+
+ /**
+ * Delete @p aGroup. This marks @p aGroup as @em deleted in the config object. This effectively
+ * removes any cascaded values from config files earlier in the stack.
+ */
+ void deleteGroup(const QByteArray &group, WriteConfigFlags flags = Normal);
+ void deleteGroup(const QString &group, WriteConfigFlags flags = Normal);
+ void deleteGroup(const char *group, WriteConfigFlags flags = Normal);
+
+ /**
+ * Syncs the configuration object that this group belongs to.
+ * Unrelated concurrent changes to the same file are merged and thus
+ * not overwritten. Note however, that this object is @em not automatically
+ * updated with those changes.
+ */
+ virtual bool sync() = 0;
+
+ /**
+ * Reset the dirty flags of all entries in the entry map, so the
+ * values will not be written to disk on a later call to sync().
+ */
+ virtual void markAsClean() = 0;
+
+ /**
+ * Possible return values for accessMode().
+ */
+ enum AccessMode { NoAccess, ReadOnly, ReadWrite };
+
+ /**
+ * Returns the access mode of the app-config object.
+ *
+ * Possible return values
+ * are NoAccess (the application-specific config file could not be
+ * opened neither read-write nor read-only), ReadOnly (the
+ * application-specific config file is opened read-only, but not
+ * read-write) and ReadWrite (the application-specific config
+ * file is opened read-write).
+ *
+ * @return the access mode of the app-config object
+ */
+ virtual AccessMode accessMode() const = 0;
+
+ /**
+ * Checks whether this configuration object can be modified.
+ * @return whether changes may be made to this configuration object.
+ */
+ virtual bool isImmutable() const = 0;
+
+ /**
+ * Can changes be made to the entries in @p aGroup?
+ *
+ * @param aGroup The group to check for immutability.
+ * @return @c false if the entries in @p aGroup can be modified.
+ */
+ bool isGroupImmutable(const QByteArray& aGroup) const;
+ bool isGroupImmutable(const QString& aGroup) const;
+ bool isGroupImmutable(const char *aGroup) const;
+
+protected:
+ KConfigBase();
+
+ virtual bool hasGroupImpl(const QByteArray &group) const = 0;
+ virtual KConfigGroup groupImpl( const QByteArray &b) = 0;
+ virtual const KConfigGroup groupImpl(const QByteArray &b) const = 0;
+ virtual void deleteGroupImpl(const QByteArray &group, WriteConfigFlags flags = Normal) = 0;
+ virtual bool isGroupImmutableImpl(const QByteArray& aGroup) const = 0;
+
+ /** Virtual hook, used to add new "virtual" functions while maintaining
+ * binary compatibility. Unused in this class.
+ */
+ virtual void virtual_hook( int id, void* data );
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(KConfigBase::WriteConfigFlags)
+
+
+
+#endif // KCONFIG_H
diff --git a/tier1/kconfig/src/core/kconfigbase_p.h b/tier1/kconfig/src/core/kconfigbase_p.h
new file mode 100644
index 00000000..c1066267
--- /dev/null
+++ b/tier1/kconfig/src/core/kconfigbase_p.h
@@ -0,0 +1,30 @@
+/*
+ This file is part of the KDE libraries
+ Copyright (c) 1999 Preston Brown <pbrown@kde.org>
+ Copyright (C) 1997 Matthias Kalle Dalheimer <kalle@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KCONFIGBASE_P_H
+#define KCONFIGBASE_P_H
+
+#include <QtCore/QSharedData>
+
+class KConfigBasePrivate : public QSharedData
+{
+};
+#endif
diff --git a/tier1/kconfig/src/core/kconfigdata.cpp b/tier1/kconfig/src/core/kconfigdata.cpp
new file mode 100644
index 00000000..74a068be
--- /dev/null
+++ b/tier1/kconfig/src/core/kconfigdata.cpp
@@ -0,0 +1,317 @@
+/*
+ This file is part of the KDE libraries
+ Copyright (c) 2006, 2007 Thomas Braxton <kde.braxton@gmail.com>
+ Copyright (c) 1999-2000 Preston Brown <pbrown@kde.org>
+ Copyright (C) 1996-2000 Matthias Kalle Dalheimer <kalle@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <kconfigdata.h>
+
+QDebug operator<<(QDebug dbg, const KEntryKey& key)
+{
+ dbg.nospace() << "[" << key.mGroup << ", " << key.mKey << (key.bLocal?" localized":"") <<
+ (key.bDefault?" default":"") << (key.bRaw?" raw":"") << "]";
+ return dbg.space();
+}
+
+QDebug operator<<(QDebug dbg, const KEntry& entry)
+{
+ dbg.nospace() << "[" << entry.mValue << (entry.bDirty?" dirty":"") <<
+ (entry.bGlobal?" global":"") << (entry.bImmutable?" immutable":"") <<
+ (entry.bDeleted?" deleted":"") << (entry.bReverted?" reverted":"") <<
+ (entry.bExpand?" expand":"") << "]";
+
+ return dbg.space();
+}
+
+QMap< KEntryKey, KEntry >::Iterator KEntryMap::findExactEntry(const QByteArray& group, const QByteArray& key, KEntryMap::SearchFlags flags)
+{
+ KEntryKey theKey(group, key, bool(flags&SearchLocalized), bool(flags&SearchDefaults));
+ return find(theKey);
+}
+
+QMap< KEntryKey, KEntry >::Iterator KEntryMap::findEntry(const QByteArray& group, const QByteArray& key, KEntryMap::SearchFlags flags)
+{
+ KEntryKey theKey(group, key, false, bool(flags&SearchDefaults));
+
+ // try the localized key first
+ if (flags&SearchLocalized) {
+ theKey.bLocal = true;
+
+ Iterator it = find(theKey);
+ if (it != end())
+ return it;
+
+ theKey.bLocal = false;
+ }
+ return find(theKey);
+}
+
+QMap< KEntryKey, KEntry >::ConstIterator KEntryMap::findEntry(const QByteArray& group, const QByteArray& key, KEntryMap::SearchFlags flags) const
+{
+ KEntryKey theKey(group, key, false, bool(flags&SearchDefaults));
+
+ // try the localized key first
+ if (flags&SearchLocalized) {
+ theKey.bLocal = true;
+
+ ConstIterator it = find(theKey);
+ if (it != constEnd())
+ return it;
+
+ theKey.bLocal = false;
+ }
+ return find(theKey);
+}
+
+bool KEntryMap::setEntry(const QByteArray& group, const QByteArray& key, const QByteArray& value, KEntryMap::EntryOptions options)
+{
+ KEntryKey k;
+ KEntry e;
+ bool newKey = false;
+
+ const Iterator it = findExactEntry(group, key, SearchFlags(options>>16));
+
+ if (key.isEmpty()) { // inserting a group marker
+ k.mGroup = group;
+ e.bImmutable = (options&EntryImmutable);
+ if (options&EntryDeleted) {
+ qWarning("Internal KConfig error: cannot mark groups as deleted");
+ }
+ if(it == end()) {
+ insert(k, e);
+ return true;
+ } else if(it.value() == e) {
+ return false;
+ }
+
+ it.value() = e;
+ return true;
+ }
+
+
+ if (it != end()) {
+ if (it->bImmutable)
+ return false; // we cannot change this entry. Inherits group immutability.
+ k = it.key();
+ e = *it;
+ //qDebug() << "found existing entry for key" << k;
+ } else {
+ // make sure the group marker is in the map
+ KEntryMap const *that = this;
+ ConstIterator cit = that->findEntry(group);
+ if (cit == constEnd())
+ insert(KEntryKey(group), KEntry());
+ else if (cit->bImmutable)
+ return false; // this group is immutable, so we cannot change this entry.
+
+ k = KEntryKey(group, key);
+ newKey = true;
+ }
+
+ // set these here, since we may be changing the type of key from the one we found
+ k.bLocal = (options&EntryLocalized);
+ k.bDefault = (options&EntryDefault);
+ k.bRaw = (options&EntryRawKey);
+
+ e.mValue = value;
+ e.bDirty = e.bDirty || (options&EntryDirty);
+ e.bGlobal = (options&EntryGlobal); //we can't use || here, because changes to entries in
+ //kdeglobals would be written to kdeglobals instead
+ //of the local config file, regardless of the globals flag
+ e.bImmutable = e.bImmutable || (options&EntryImmutable);
+ if (value.isNull())
+ e.bDeleted = e.bDeleted || (options&EntryDeleted);
+ else
+ e.bDeleted = false; // setting a value to a previously deleted entry
+ e.bExpand = (options&EntryExpansion);
+ e.bReverted = false;
+
+ if(newKey)
+ {
+ //qDebug() << "inserting" << k << "=" << value;
+ insert(k, e);
+ if(k.bDefault)
+ {
+ k.bDefault = false;
+ //qDebug() << "also inserting" << k << "=" << value;
+ insert(k, e);
+ }
+ // TODO check for presence of unlocalized key
+ return true;
+ } else {
+// KEntry e2 = it.value();
+ if(it.value() != e)
+ {
+ //qDebug() << "changing" << k << "from" << e.mValue << "to" << value;
+ it.value() = e;
+ if(k.bDefault)
+ {
+ KEntryKey nonDefaultKey(k);
+ nonDefaultKey.bDefault = false;
+ insert(nonDefaultKey, e);
+ }
+ if (!(options & EntryLocalized)) {
+ KEntryKey theKey(group, key, true, false);
+ //qDebug() << "non-localized entry, remove localized one:" << theKey;
+ remove(theKey);
+ if (k.bDefault) {
+ theKey.bDefault = true;
+ remove(theKey);
+ }
+ }
+ return true;
+ } else {
+ //qDebug() << k << "was already set to" << e.mValue;
+ if (!(options & EntryLocalized)) {
+ //qDebug() << "unchanged non-localized entry, remove localized one.";
+ KEntryKey theKey(group, key, true, false);
+ bool ret = false;
+ Iterator cit = find(theKey);
+ if (cit != end()) {
+ erase(cit);
+ ret = true;
+ }
+ if (k.bDefault) {
+ theKey.bDefault = true;
+ Iterator cit = find(theKey);
+ if (cit != end()) {
+ erase(cit);
+ return true;
+ }
+ }
+ return ret;
+ }
+ //qDebug() << "localized entry, unchanged, return false";
+ // When we are writing a default, we know that the non-
+ // default is the same as the default, so we can simply
+ // use the same branch.
+ return false;
+ }
+ }
+}
+
+QString KEntryMap::getEntry(const QByteArray& group, const QByteArray& key, const QString& defaultValue, KEntryMap::SearchFlags flags, bool* expand) const
+{
+ const ConstIterator it = findEntry(group, key, flags);
+ QString theValue = defaultValue;
+
+ if (it != constEnd() && !it->bDeleted) {
+ if (!it->mValue.isNull()) {
+ const QByteArray data=it->mValue;
+ theValue = QString::fromUtf8(data.constData(), data.length());
+ if (expand)
+ *expand = it->bExpand;
+ }
+ }
+
+ return theValue;
+}
+
+bool KEntryMap::hasEntry(const QByteArray& group, const QByteArray& key, KEntryMap::SearchFlags flags) const
+{
+ const ConstIterator it = findEntry(group, key, flags);
+ if (it == constEnd())
+ return false;
+ if (it->bDeleted)
+ return false;
+ if (key.isNull()) { // looking for group marker
+ return it->mValue.isNull();
+ }
+ // if it->bReverted, we'll just return true; the real answer depends on lookup up with SearchDefaults, though.
+ return true;
+}
+
+bool KEntryMap::getEntryOption(const QMap< KEntryKey, KEntry >::ConstIterator& it, KEntryMap::EntryOption option) const
+{
+ if (it != constEnd()) {
+ switch (option) {
+ case EntryDirty:
+ return it->bDirty;
+ case EntryLocalized:
+ return it.key().bLocal;
+ case EntryGlobal:
+ return it->bGlobal;
+ case EntryImmutable:
+ return it->bImmutable;
+ case EntryDeleted:
+ return it->bDeleted;
+ case EntryExpansion:
+ return it->bExpand;
+ default:
+ break; // fall through
+ }
+ }
+
+ return false;
+}
+
+void KEntryMap::setEntryOption(QMap< KEntryKey, KEntry >::Iterator it, KEntryMap::EntryOption option, bool bf)
+{
+ if (it != end()) {
+ switch (option) {
+ case EntryDirty:
+ it->bDirty = bf;
+ break;
+ case EntryGlobal:
+ it->bGlobal = bf;
+ break;
+ case EntryImmutable:
+ it->bImmutable = bf;
+ break;
+ case EntryDeleted:
+ it->bDeleted = bf;
+ break;
+ case EntryExpansion:
+ it->bExpand = bf;
+ break;
+ default:
+ break; // fall through
+ }
+ }
+}
+
+bool KEntryMap::revertEntry(const QByteArray& group, const QByteArray& key, KEntryMap::SearchFlags flags)
+{
+ Q_ASSERT((flags & KEntryMap::SearchDefaults) == 0);
+ Iterator entry = findEntry(group, key, flags);
+ if (entry != end()) {
+ //qDebug() << "reverting" << entry.key() << " = " << entry->mValue;
+ if (entry->bReverted) { // already done before
+ return false;
+ }
+
+ KEntryKey defaultKey(entry.key());
+ defaultKey.bDefault = true;
+ //qDebug() << "looking up default entry with key=" << defaultKey;
+ const ConstIterator defaultEntry = constFind(defaultKey);
+ if (defaultEntry != constEnd()) {
+ Q_ASSERT(defaultEntry.key().bDefault);
+ //qDebug() << "found, update entry";
+ *entry = *defaultEntry; // copy default value, for subsequent lookups
+ } else {
+ entry->mValue = QByteArray();
+ }
+ entry->bDirty = true;
+ entry->bReverted = true; // skip it when writing out to disk
+
+ //qDebug() << "Here's what we have now:" << *this;
+ return true;
+ }
+ return false;
+}
diff --git a/tier1/kconfig/src/core/kconfigdata.h b/tier1/kconfig/src/core/kconfigdata.h
new file mode 100644
index 00000000..f7ad81b9
--- /dev/null
+++ b/tier1/kconfig/src/core/kconfigdata.h
@@ -0,0 +1,237 @@
+/*
+ This file is part of the KDE libraries
+ Copyright (c) 2006, 2007 Thomas Braxton <kde.braxton@gmail.com>
+ Copyright (c) 1999-2000 Preston Brown <pbrown@kde.org>
+ Copyright (C) 1996-2000 Matthias Kalle Dalheimer <kalle@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KCONFIGDATA_H
+#define KCONFIGDATA_H
+
+#include <QtCore/QByteArray>
+#include <QtCore/QString>
+#include <QtCore/QMap>
+#include <QtCore/QDebug>
+
+/**
+ * map/dict/list config node entry.
+ * @internal
+ */
+struct KEntry
+{
+ /** Constructor. @internal */
+ KEntry()
+ : mValue(), bDirty(false),
+ bGlobal(false), bImmutable(false), bDeleted(false), bExpand(false), bReverted(false) {}
+ /** @internal */
+ QByteArray mValue;
+ /**
+ * Must the entry be written back to disk?
+ */
+ bool bDirty :1;
+ /**
+ * Entry should be written to the global config file
+ */
+ bool bGlobal:1;
+ /**
+ * Entry can not be modified.
+ */
+ bool bImmutable:1;
+ /**
+ * Entry has been deleted.
+ */
+ bool bDeleted:1;
+ /**
+ * Whether to apply dollar expansion or not.
+ */
+ bool bExpand:1;
+ /**
+ * Entry has been reverted to its default value (from a more global file).
+ */
+ bool bReverted:1;
+};
+
+// These operators are used to check whether an entry which is about
+// to be written equals the previous value. As such, this intentionally
+// omits the dirty flag from the comparison.
+inline bool operator ==(const KEntry &k1, const KEntry &k2)
+{
+ return k1.bGlobal == k2.bGlobal && k1.bImmutable == k2.bImmutable
+ && k1.bDeleted == k2.bDeleted && k1.bExpand == k2.bExpand
+ && k1.mValue == k2.mValue;
+}
+
+inline bool operator !=(const KEntry &k1, const KEntry &k2)
+{
+ return !(k1 == k2);
+}
+
+/**
+ * key structure holding both the actual key and the group
+ * to which it belongs.
+ * @internal
+ */
+struct KEntryKey
+{
+ /** Constructor. @internal */
+ KEntryKey(const QByteArray& _group = QByteArray(),
+ const QByteArray& _key = QByteArray(), bool isLocalized=false, bool isDefault=false)
+ : mGroup(_group), mKey(_key), bLocal(isLocalized), bDefault(isDefault), bRaw(false)
+ { ; }
+ /**
+ * The "group" to which this EntryKey belongs
+ */
+ QByteArray mGroup;
+ /**
+ * The _actual_ key of the entry in question
+ */
+ QByteArray mKey;
+ /**
+ * Entry is localised or not
+ */
+ bool bLocal :1;
+ /**
+ * Entry indicates if this is a default value.
+ */
+ bool bDefault:1;
+ /** @internal
+ * Key is a raw unprocessed key.
+ * @warning this should only be set during merging, never for normal use.
+ */
+ bool bRaw:1;
+};
+
+/**
+ * Compares two KEntryKeys (needed for QMap). The order is localized, localized-default,
+ * non-localized, non-localized-default
+ * @internal
+ */
+inline bool operator <(const KEntryKey &k1, const KEntryKey &k2)
+{
+ int result = qstrcmp(k1.mGroup, k2.mGroup);
+ if (result != 0) {
+ return result < 0;
+ }
+
+ result = qstrcmp(k1.mKey, k2.mKey);
+ if (result != 0) {
+ return result < 0;
+ }
+
+ if (k1.bLocal != k2.bLocal)
+ return k1.bLocal;
+ return (!k1.bDefault && k2.bDefault);
+}
+
+
+QDebug operator<<(QDebug dbg, const KEntryKey& key);
+QDebug operator<<(QDebug dbg, const KEntry& entry);
+
+/**
+ * \relates KEntry
+ * type specifying a map of entries (key,value pairs).
+ * The keys are actually a key in a particular config file group together
+ * with the group name.
+ * @internal
+ */
+class KEntryMap : public QMap<KEntryKey, KEntry>
+{
+ public:
+ enum SearchFlag {
+ SearchDefaults=1,
+ SearchLocalized=2
+ };
+ Q_DECLARE_FLAGS(SearchFlags, SearchFlag)
+
+ enum EntryOption {
+ EntryDirty=1,
+ EntryGlobal=2,
+ EntryImmutable=4,
+ EntryDeleted=8,
+ EntryExpansion=16,
+ EntryRawKey=32,
+ EntryDefault=(SearchDefaults<<16),
+ EntryLocalized=(SearchLocalized<<16)
+ };
+ Q_DECLARE_FLAGS(EntryOptions, EntryOption)
+
+ Iterator findExactEntry(const QByteArray& group, const QByteArray& key = QByteArray(),
+ SearchFlags flags = SearchFlags());
+
+ Iterator findEntry(const QByteArray& group, const QByteArray& key = QByteArray(),
+ SearchFlags flags = SearchFlags());
+
+ ConstIterator findEntry(const QByteArray& group, const QByteArray& key = QByteArray(),
+ SearchFlags flags = SearchFlags()) const;
+
+ /**
+ * Returns true if the entry gets dirtied or false in other case
+ */
+ bool setEntry(const QByteArray& group, const QByteArray& key,
+ const QByteArray& value, EntryOptions options);
+
+ void setEntry(const QByteArray& group, const QByteArray& key,
+ const QString & value, EntryOptions options)
+ {
+ setEntry(group, key, value.toUtf8(), options);
+ }
+
+ QString getEntry(const QByteArray& group, const QByteArray& key,
+ const QString & defaultValue = QString(),
+ SearchFlags flags = SearchFlags(),
+ bool * expand=0) const;
+
+ bool hasEntry(const QByteArray& group, const QByteArray& key = QByteArray(),
+ SearchFlags flags = SearchFlags()) const;
+
+ bool getEntryOption(const ConstIterator& it, EntryOption option) const;
+ bool getEntryOption(const QByteArray& group, const QByteArray& key,
+ SearchFlags flags, EntryOption option) const
+ {
+ return getEntryOption(findEntry(group, key, flags), option);
+ }
+
+ void setEntryOption(Iterator it, EntryOption option, bool bf);
+ void setEntryOption(const QByteArray& group, const QByteArray& key, SearchFlags flags,
+ EntryOption option, bool bf)
+ {
+ setEntryOption(findEntry(group, key, flags), option, bf);
+ }
+
+ bool revertEntry(const QByteArray& group, const QByteArray& key, SearchFlags flags=SearchFlags());
+};
+Q_DECLARE_OPERATORS_FOR_FLAGS(KEntryMap::SearchFlags)
+Q_DECLARE_OPERATORS_FOR_FLAGS(KEntryMap::EntryOptions)
+
+/**
+ * \relates KEntry
+ * type for iterating over keys in a KEntryMap in sorted order.
+ * @internal
+ */
+typedef QMap<KEntryKey, KEntry>::Iterator KEntryMapIterator;
+
+/**
+ * \relates KEntry
+ * type for iterating over keys in a KEntryMap in sorted order.
+ * It is const, thus you cannot change the entries in the iterator,
+ * only examine them.
+ * @internal
+ */
+typedef QMap<KEntryKey, KEntry>::ConstIterator KEntryMapConstIterator;
+
+#endif
diff --git a/tier1/kconfig/src/core/kconfiggroup.cpp b/tier1/kconfig/src/core/kconfiggroup.cpp
new file mode 100644
index 00000000..ab7d494f
--- /dev/null
+++ b/tier1/kconfig/src/core/kconfiggroup.cpp
@@ -0,0 +1,1243 @@
+/*
+ This file is part of the KDE libraries
+ Copyright (c) 2006, 2007 Thomas Braxton <kde.braxton@gmail.com>
+ Copyright (c) 1999 Preston Brown <pbrown@kde.org>
+ Copyright (c) 1997 Matthias Kalle Dalheimer <kalle@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+// Qt5 TODO: re-enable. No point in doing it before, it breaks on QString::fromUtf8(QByteArray), which exists in qt5.
+#undef QT_NO_CAST_FROM_BYTEARRAY
+
+#include "kconfiggroup.h"
+#include "kconfiggroup_p.h"
+
+#include "kconfig.h"
+#include "kconfig_p.h"
+#include "ksharedconfig.h"
+#include "kconfigdata.h"
+
+#include <QtCore/QDate>
+#include <QtCore/QSharedData>
+#include <QtCore/QFile>
+#include <QtCore/QPoint>
+#include <QtCore/QRect>
+#include <QtCore/QString>
+#include <QtCore/QTextStream>
+#include <QtCore/QDir>
+#include <QtCore/QUrl>
+
+#include <stdlib.h>
+
+class KConfigGroupPrivate : public QSharedData
+{
+ public:
+ KConfigGroupPrivate(KConfig* owner, bool isImmutable, bool isConst, const QByteArray &name)
+ : mOwner(owner), mName(name), bImmutable(isImmutable), bConst(isConst)
+ {
+ }
+
+ KConfigGroupPrivate(const KSharedConfigPtr &owner, const QByteArray& name)
+ : sOwner(owner), mOwner(sOwner.data()), mName(name),
+ bImmutable(name.isEmpty()? owner->isImmutable(): owner->isGroupImmutable(name)), bConst(false)
+ {
+ }
+
+ KConfigGroupPrivate(KConfigGroup* parent, bool isImmutable, bool isConst, const QByteArray& name)
+ : sOwner(parent->d->sOwner), mOwner(parent->d->mOwner), mName(name),
+ bImmutable(isImmutable), bConst(isConst)
+ {
+ if (!parent->d->mName.isEmpty())
+ mParent = parent->d;
+ }
+
+ KConfigGroupPrivate(const KConfigGroupPrivate* other, bool isImmutable, const QByteArray &name)
+ : sOwner(other->sOwner), mOwner(other->mOwner), mName(name),
+ bImmutable(isImmutable), bConst(other->bConst)
+ {
+ if (!other->mName.isEmpty())
+ mParent = const_cast<KConfigGroupPrivate *>(other);
+ }
+
+ KSharedConfig::Ptr sOwner;
+ KConfig *mOwner;
+ QExplicitlySharedDataPointer<KConfigGroupPrivate> mParent;
+ QByteArray mName;
+
+ /* bitfield */
+ const bool bImmutable:1; // is this group immutable?
+ const bool bConst:1; // is this group read-only?
+
+ QByteArray fullName() const
+ {
+ if (!mParent) {
+ return name();
+ }
+ return mParent->fullName(mName);
+ }
+
+ QByteArray name() const
+ {
+ if (mName.isEmpty())
+ return "<default>";
+ return mName;
+ }
+
+ QByteArray fullName(const QByteArray& aGroup) const
+ {
+ if (mName.isEmpty())
+ return aGroup;
+ return fullName() + '\x1d' + aGroup;
+ }
+
+ static QExplicitlySharedDataPointer<KConfigGroupPrivate> create(KConfigBase *master,
+ const QByteArray &name,
+ bool isImmutable,
+ bool isConst)
+ {
+ QExplicitlySharedDataPointer<KConfigGroupPrivate> data;
+ if (dynamic_cast<KConfigGroup*>(master))
+ data = new KConfigGroupPrivate(dynamic_cast<KConfigGroup*>(master), isImmutable, isConst, name);
+ else
+ data = new KConfigGroupPrivate(dynamic_cast<KConfig*>(master), isImmutable, isConst, name);
+ return data;
+ }
+
+ static QByteArray serializeList(const QList<QByteArray> &list);
+ static QStringList deserializeList(const QString &data);
+};
+
+QByteArray KConfigGroupPrivate::serializeList(const QList<QByteArray> &list)
+{
+ QByteArray value = "";
+
+ if (!list.isEmpty()) {
+ QList<QByteArray>::ConstIterator it = list.constBegin();
+ const QList<QByteArray>::ConstIterator end = list.constEnd();
+
+ value = QByteArray(*it).replace('\\', "\\\\").replace(',', "\\,");
+
+ while (++it != end) {
+ // In the loop, so it is not done when there is only one element.
+ // Doing it repeatedly is a pretty cheap operation.
+ value.reserve(4096);
+
+ value += ',';
+ value += QByteArray(*it).replace('\\', "\\\\").replace(',', "\\,");
+ }
+
+ // To be able to distinguish an empty list from a list with one empty element.
+ if (value.isEmpty())
+ value = "\\0";
+ }
+
+ return value;
+}
+
+QStringList KConfigGroupPrivate::deserializeList(const QString &data)
+{
+ if (data.isEmpty())
+ return QStringList();
+ if (data == QLatin1String("\\0"))
+ return QStringList(QString());
+ QStringList value;
+ QString val;
+ val.reserve(data.size());
+ bool quoted = false;
+ for (int p = 0; p < data.length(); p++) {
+ if (quoted) {
+ val += data[p];
+ quoted = false;
+ } else if (data[p].unicode() == '\\') {
+ quoted = true;
+ } else if (data[p].unicode() == ',') {
+ val.squeeze(); // release any unused memory
+ value.append(val);
+ val.clear();
+ val.reserve(data.size() - p);
+ } else {
+ val += data[p];
+ }
+ }
+ value.append(val);
+ return value;
+}
+
+static QList<int> asIntList(const QByteArray& string)
+{
+ QList<int> list;
+ Q_FOREACH(const QByteArray& s, string.split(','))
+ list << s.toInt();
+ return list;
+}
+
+static QList<qreal> asRealList(const QByteArray& string)
+{
+ QList<qreal> list;
+ Q_FOREACH(const QByteArray& s, string.split(','))
+ list << s.toDouble();
+ return list;
+}
+
+static QString errString( const char * pKey, const QByteArray & value, const QVariant & aDefault ) {
+ return QString::fromLatin1("\"%1\" - conversion of \"%3\" to %2 failed")
+ .arg(QString::fromLatin1(pKey))
+ .arg(QString::fromLatin1(QVariant::typeToName(aDefault.type())))
+ .arg(QString::fromLatin1(value));
+}
+
+static QString formatError( int expected, int got ) {
+ return QString::fromLatin1(" (wrong format: expected %1 items, got %2)").arg( expected ).arg( got );
+}
+
+QVariant KConfigGroup::convertToQVariant(const char *pKey, const QByteArray& value, const QVariant& aDefault)
+{
+ // if a type handler is added here you must add a QVConversions definition
+ // to conversion_check.h, or ConversionCheck::to_QVariant will not allow
+ // readEntry<T> to convert to QVariant.
+ switch( aDefault.type() ) {
+ case QVariant::Invalid:
+ return QVariant();
+ case QVariant::String:
+ // this should return the raw string not the dollar expanded string.
+ // imho if processed string is wanted should call
+ // readEntry(key, QString) not readEntry(key, QVariant)
+ return QString::fromUtf8(value);
+ case QVariant::List:
+ case QVariant::StringList:
+ return KConfigGroupPrivate::deserializeList(QString::fromUtf8(value));
+ case QVariant::ByteArray:
+ return value;
+ case QVariant::Bool: {
+ const QByteArray lower(value.toLower());
+ if (lower == "false" || lower == "no" || lower == "off" || lower == "0")
+ return false;
+ return true;
+ }
+ case QVariant::Double:
+ case QMetaType::Float:
+ case QVariant::Int:
+ case QVariant::UInt:
+ case QVariant::LongLong:
+ case QVariant::ULongLong: {
+ QVariant tmp = value;
+ if ( !tmp.convert(aDefault.type()) )
+ tmp = aDefault;
+ return tmp;
+ }
+ case QVariant::Point: {
+ const QList<int> list = asIntList(value);
+
+ if ( list.count() != 2 ) {
+ qWarning() << errString( pKey, value, aDefault )
+ << formatError( 2, list.count() );
+ return aDefault;
+ }
+ return QPoint(list.at( 0 ), list.at( 1 ));
+ }
+ case QVariant::PointF: {
+ const QList<qreal> list = asRealList(value);
+
+ if ( list.count() != 2 ) {
+ qWarning() << errString( pKey, value, aDefault )
+ << formatError( 2, list.count() );
+ return aDefault;
+ }
+ return QPointF(list.at( 0 ), list.at( 1 ));
+ }
+ case QVariant::Rect: {
+ const QList<int> list = asIntList(value);
+
+ if ( list.count() != 4 ) {
+ qWarning() << errString( pKey, value, aDefault )
+ << formatError( 4, list.count() );
+ return aDefault;
+ }
+ const QRect rect(list.at( 0 ), list.at( 1 ), list.at( 2 ), list.at( 3 ));
+ if ( !rect.isValid() ) {
+ qWarning() << errString( pKey, value, aDefault );
+ return aDefault;
+ }
+ return rect;
+ }
+ case QVariant::RectF: {
+ const QList<qreal> list = asRealList(value);
+
+ if ( list.count() != 4 ) {
+ qWarning() << errString( pKey, value, aDefault )
+ << formatError( 4, list.count() );
+ return aDefault;
+ }
+ const QRectF rect(list.at( 0 ), list.at( 1 ), list.at( 2 ), list.at( 3 ));
+ if ( !rect.isValid() ) {
+ qWarning() << errString( pKey, value, aDefault );
+ return aDefault;
+ }
+ return rect;
+ }
+ case QVariant::Size: {
+ const QList<int> list = asIntList(value);
+
+ if ( list.count() != 2 ) {
+ qWarning() << errString( pKey, value, aDefault )
+ << formatError( 2, list.count() );
+ return aDefault;
+ }
+ const QSize size(list.at( 0 ), list.at( 1 ));
+ if ( !size.isValid() ) {
+ qWarning() << errString( pKey, value, aDefault );
+ return aDefault;
+ }
+ return size;
+ }
+ case QVariant::SizeF: {
+ const QList<qreal> list = asRealList(value);
+
+ if ( list.count() != 2 ) {
+ qWarning() << errString( pKey, value, aDefault )
+ << formatError( 2, list.count() );
+ return aDefault;
+ }
+ const QSizeF size(list.at( 0 ), list.at( 1 ));
+ if ( !size.isValid() ) {
+ qWarning() << errString( pKey, value, aDefault );
+ return aDefault;
+ }
+ return size;
+ }
+ case QVariant::DateTime: {
+ const QList<int> list = asIntList(value);
+ if ( list.count() != 6 ) {
+ qWarning() << errString( pKey, value, aDefault )
+ << formatError( 6, list.count() );
+ return aDefault;
+ }
+ const QDate date( list.at( 0 ), list.at( 1 ), list.at( 2 ) );
+ const QTime time( list.at( 3 ), list.at( 4 ), list.at( 5 ) );
+ const QDateTime dt( date, time );
+ if ( !dt.isValid() ) {
+ qWarning() << errString( pKey, value, aDefault );
+ return aDefault;
+ }
+ return dt;
+ }
+ case QVariant::Date: {
+ QList<int> list = asIntList(value);
+ if ( list.count() == 6 )
+ list = list.mid(0, 3); // don't break config files that stored QDate as QDateTime
+ if ( list.count() != 3 ) {
+ qWarning() << errString( pKey, value, aDefault )
+ << formatError( 3, list.count() );
+ return aDefault;
+ }
+ const QDate date( list.at( 0 ), list.at( 1 ), list.at( 2 ) );
+ if ( !date.isValid() ) {
+ qWarning() << errString( pKey, value, aDefault );
+ return aDefault;
+ }
+ return date;
+ }
+ case QVariant::Color:
+ case QVariant::Font:
+ qWarning() << "KConfigGroup::readEntry was passed GUI type '"
+ << aDefault.typeName()
+ << "' but kdeui isn't linked! If it is linked to your program, "
+ "this is a platform bug. Please inform the KDE developers";
+ break;
+ case QVariant::Url:
+ return QUrl(QString::fromUtf8(value));
+
+ default:
+ break;
+ }
+
+ qWarning() << "unhandled type " << aDefault.typeName();
+ return QVariant();
+}
+
+#ifdef Q_OS_WIN
+# include <QtCore/QDir>
+#endif
+
+static bool cleanHomeDirPath( QString &path, const QString &homeDir )
+{
+#ifdef Q_OS_WIN //safer
+ if (!QDir::toNativeSeparators(path).startsWith(QDir::toNativeSeparators(homeDir)))
+ return false;
+#else
+ if (!path.startsWith(homeDir))
+ return false;
+#endif
+
+ int len = homeDir.length();
+ // replace by "$HOME" if possible
+ if (len && (path.length() == len || path[len] == QLatin1Char('/'))) {
+ path.replace(0, len, QString::fromLatin1("$HOME"));
+ return true;
+ } else
+ return false;
+}
+
+static QString translatePath( QString path ) // krazy:exclude=passbyvalue
+{
+ if (path.isEmpty())
+ return path;
+
+ // only "our" $HOME should be interpreted
+ path.replace(QLatin1Char('$'), QLatin1String("$$"));
+
+ bool startsWithFile = path.startsWith(QLatin1String("file:"), Qt::CaseInsensitive);
+
+ // return original path, if it refers to another type of URL (e.g. http:/), or
+ // if the path is already relative to another directory
+ if ((!startsWithFile && QFileInfo(path).isRelative()) ||
+ (startsWithFile && QFileInfo(path.mid(5)).isRelative()))
+ return path;
+
+ if (startsWithFile)
+ path.remove(0,5); // strip leading "file:/" off the string
+
+ // keep only one single '/' at the beginning - needed for cleanHomeDirPath()
+ while (path[0] == QLatin1Char('/') && path[1] == QLatin1Char('/'))
+ path.remove(0,1);
+
+ // we can not use KGlobal::dirs()->relativeLocation("home", path) here,
+ // since it would not recognize paths without a trailing '/'.
+ // All of the 3 following functions to return the user's home directory
+ // can return different paths. We have to test all them.
+ const QString homeDir0 = QFile::decodeName(qgetenv("HOME"));
+ const QString homeDir1 = QDir::homePath();
+ const QString homeDir2 = QDir(homeDir1).canonicalPath();
+ if (cleanHomeDirPath(path, homeDir0) ||
+ cleanHomeDirPath(path, homeDir1) ||
+ cleanHomeDirPath(path, homeDir2) ) {
+ // qDebug() << "Path was replaced\n";
+ }
+
+ if (startsWithFile)
+ path.prepend(QString::fromLatin1("file://"));
+
+ return path;
+}
+
+
+KConfigGroup::KConfigGroup() : d(0)
+{
+}
+
+bool KConfigGroup::isValid() const
+{
+ return 0 != d.constData();
+}
+
+KConfigGroupGui _kde_internal_KConfigGroupGui;
+static inline bool readEntryGui(const QByteArray& data, const char* key, const QVariant &input,
+ QVariant &output)
+{
+ if (_kde_internal_KConfigGroupGui.readEntryGui)
+ return _kde_internal_KConfigGroupGui.readEntryGui(data, key, input, output);
+ return false;
+}
+
+static inline bool writeEntryGui(KConfigGroup *cg, const char* key, const QVariant &input,
+ KConfigGroup::WriteConfigFlags flags)
+{
+ if (_kde_internal_KConfigGroupGui.writeEntryGui)
+ return _kde_internal_KConfigGroupGui.writeEntryGui(cg, key, input, flags);
+ return false;
+}
+
+KConfigGroup::KConfigGroup(KConfigBase *master, const QString &_group)
+ : d(KConfigGroupPrivate::create(master, _group.toUtf8(), master->isGroupImmutable(_group), false))
+{
+}
+
+KConfigGroup::KConfigGroup(KConfigBase *master, const char *_group)
+ : d(KConfigGroupPrivate::create(master, _group, master->isGroupImmutable(_group), false))
+{
+}
+
+KConfigGroup::KConfigGroup(const KConfigBase *master, const QString &_group)
+ : d(KConfigGroupPrivate::create(const_cast<KConfigBase*>(master), _group.toUtf8(), master->isGroupImmutable(_group), true))
+{
+}
+
+KConfigGroup::KConfigGroup(const KConfigBase *master, const char * _group)
+ : d(KConfigGroupPrivate::create(const_cast<KConfigBase*>(master), _group, master->isGroupImmutable(_group), true))
+{
+}
+
+KConfigGroup::KConfigGroup(const KSharedConfigPtr &master, const QString &_group)
+ : d(new KConfigGroupPrivate(master, _group.toUtf8()))
+{
+}
+
+KConfigGroup::KConfigGroup(const KSharedConfigPtr &master, const char * _group)
+ : d(new KConfigGroupPrivate(master, _group))
+{
+}
+
+KConfigGroup &KConfigGroup::operator=(const KConfigGroup &rhs)
+{
+ d = rhs.d;
+ return *this;
+}
+
+KConfigGroup::KConfigGroup(const KConfigGroup &rhs)
+ : KConfigBase(), d(rhs.d)
+{
+}
+
+KConfigGroup::~KConfigGroup()
+{
+ d = 0;
+}
+
+KConfigGroup KConfigGroup::groupImpl(const QByteArray& aGroup)
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::groupImpl", "accessing an invalid group");
+ Q_ASSERT_X(!aGroup.isEmpty(), "KConfigGroup::groupImpl", "can not have an unnamed child group");
+
+ KConfigGroup newGroup;
+
+ newGroup.d = new KConfigGroupPrivate(this, isGroupImmutableImpl(aGroup), d->bConst, aGroup);
+
+ return newGroup;
+}
+
+const KConfigGroup KConfigGroup::groupImpl(const QByteArray& aGroup) const
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::groupImpl", "accessing an invalid group");
+ Q_ASSERT_X(!aGroup.isEmpty(), "KConfigGroup::groupImpl", "can not have an unnamed child group");
+
+ KConfigGroup newGroup;
+
+ newGroup.d = new KConfigGroupPrivate(const_cast<KConfigGroup*>(this), isGroupImmutableImpl(aGroup),
+ true, aGroup);
+
+ return newGroup;
+}
+
+KConfigGroup KConfigGroup::parent() const
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::parent", "accessing an invalid group");
+
+ KConfigGroup parentGroup;
+
+ if (d->mParent) {
+ parentGroup.d = d->mParent;
+ } else {
+ parentGroup.d = new KConfigGroupPrivate(d->mOwner, d->mOwner->isImmutable(), d->bConst, "");
+ // make sure we keep the refcount up on the KConfig object
+ parentGroup.d->sOwner = d->sOwner;
+ }
+
+ return parentGroup;
+}
+
+void KConfigGroup::deleteGroup(WriteConfigFlags flags)
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::deleteGroup", "accessing an invalid group");
+ Q_ASSERT_X(!d->bConst, "KConfigGroup::deleteGroup", "deleting a read-only group");
+
+ config()->deleteGroup(d->fullName(), flags);
+}
+
+#ifndef KDE_NO_DEPRECATED
+void KConfigGroup::changeGroup( const QString &group )
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::changeGroup", "accessing an invalid group");
+ d.detach();
+ d->mName = group.toUtf8();
+}
+#endif
+
+#ifndef KDE_NO_DEPRECATED
+void KConfigGroup::changeGroup( const char *group )
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::changeGroup", "accessing an invalid group");
+ d.detach();
+ d->mName = group;
+}
+#endif
+
+QString KConfigGroup::name() const
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::name", "accessing an invalid group");
+
+ return QString::fromUtf8(d->name());
+}
+
+bool KConfigGroup::exists() const
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::exists", "accessing an invalid group");
+
+ return config()->hasGroup( d->fullName() );
+}
+
+bool KConfigGroup::sync()
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::sync", "accessing an invalid group");
+
+ if (!d->bConst)
+ return config()->sync();
+
+ return false;
+}
+
+QMap<QString, QString> KConfigGroup::entryMap() const
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::entryMap", "accessing an invalid group");
+
+ return config()->entryMap(QString::fromUtf8(d->fullName()));
+}
+
+KConfig* KConfigGroup::config()
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::config", "accessing an invalid group");
+
+ return d->mOwner;
+}
+
+const KConfig* KConfigGroup::config() const
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::config", "accessing an invalid group");
+
+ return d->mOwner;
+}
+
+bool KConfigGroup::isEntryImmutable(const char* key) const
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::isEntryImmutable", "accessing an invalid group");
+
+ return (isImmutable() ||
+ !config()->d_func()->canWriteEntry(d->fullName(), key, config()->readDefaults()));
+}
+
+bool KConfigGroup::isEntryImmutable(const QString& key) const
+{
+ return isEntryImmutable(key.toUtf8().constData());
+}
+
+QString KConfigGroup::readEntryUntranslated(const QString& pKey, const QString& aDefault) const
+{
+ return readEntryUntranslated(pKey.toUtf8().constData(), aDefault);
+}
+
+QString KConfigGroup::readEntryUntranslated(const char *key, const QString& aDefault) const
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::readEntryUntranslated", "accessing an invalid group");
+
+ QString result = config()->d_func()->lookupData(d->fullName(), key, KEntryMap::SearchFlags(), 0);
+ if (result.isNull())
+ return aDefault;
+ return result;
+}
+
+QString KConfigGroup::readEntry(const char *key, const char* aDefault) const
+{
+ return readEntry(key, QString::fromUtf8(aDefault));
+}
+
+QString KConfigGroup::readEntry(const QString &key, const char* aDefault) const
+{
+ return readEntry(key.toUtf8().constData(), aDefault);
+}
+
+QString KConfigGroup::readEntry(const char* key, const QString& aDefault) const
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::readEntry", "accessing an invalid group");
+
+ bool expand = false;
+
+ // read value from the entry map
+ QString aValue = config()->d_func()->lookupData(d->fullName(), key, KEntryMap::SearchLocalized,
+ &expand);
+ if (aValue.isNull())
+ aValue = aDefault;
+
+ if (expand)
+ return KConfigPrivate::expandString(aValue);
+
+ return aValue;
+}
+
+QString KConfigGroup::readEntry(const QString &key, const QString& aDefault) const
+{
+ return readEntry(key.toUtf8().constData(), aDefault);
+}
+
+QStringList KConfigGroup::readEntry(const char* key, const QStringList& aDefault) const
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::readEntry", "accessing an invalid group");
+
+ const QString data = readEntry(key, QString());
+ if (data.isNull())
+ return aDefault;
+
+ return KConfigGroupPrivate::deserializeList(data);
+}
+
+QStringList KConfigGroup::readEntry( const QString& key, const QStringList& aDefault) const
+{
+ return readEntry( key.toUtf8().constData(), aDefault );
+}
+
+QVariant KConfigGroup::readEntry( const char* key, const QVariant &aDefault ) const
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::readEntry", "accessing an invalid group");
+
+ const QByteArray data = config()->d_func()->lookupData(d->fullName(), key, KEntryMap::SearchLocalized);
+ if (data.isNull())
+ return aDefault;
+
+ QVariant value;
+ if (!readEntryGui( data, key, aDefault, value ))
+ return convertToQVariant(key, data, aDefault);
+
+ return value;
+}
+
+QVariant KConfigGroup::readEntry( const QString& key, const QVariant& aDefault) const
+{
+ return readEntry( key.toUtf8().constData(), aDefault );
+}
+
+QVariantList KConfigGroup::readEntry( const char* key, const QVariantList& aDefault) const
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::readEntry", "accessing an invalid group");
+
+ const QString data = readEntry(key, QString());
+ if (data.isNull())
+ return aDefault;
+
+ QVariantList value;
+ Q_FOREACH(const QString& v, KConfigGroupPrivate::deserializeList(data))
+ value << v;
+
+ return value;
+}
+
+QVariantList KConfigGroup::readEntry( const QString& key, const QVariantList& aDefault) const
+{
+ return readEntry( key.toUtf8().constData(), aDefault );
+}
+
+QStringList KConfigGroup::readXdgListEntry(const QString& key, const QStringList& aDefault) const
+{
+ return readXdgListEntry(key.toUtf8().constData(), aDefault);
+}
+
+QStringList KConfigGroup::readXdgListEntry(const char *key, const QStringList& aDefault) const
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::readXdgListEntry", "accessing an invalid group");
+
+ const QString data = readEntry(key, QString());
+ if (data.isNull())
+ return aDefault;
+
+ QStringList value;
+ QString val;
+ val.reserve(data.size());
+ // XXX List serialization being a separate layer from low-level parsing is
+ // probably a bug. No affected entries are defined, though.
+ bool quoted = false;
+ for (int p = 0; p < data.length(); p++) {
+ if (quoted) {
+ val += data[p];
+ quoted = false;
+ } else if (data[p] == QLatin1Char('\\')) {
+ quoted = true;
+ } else if (data[p] == QLatin1Char(';')) {
+ value.append(val);
+ val.clear();
+ val.reserve(data.size() - p);
+ } else {
+ val += data[p];
+ }
+ }
+ if (!val.isEmpty()) {
+ qWarning() << "List entry" << key << "in" << config()->name() << "is not compliant with XDG standard (missing trailing semicolon).";
+ value.append(val);
+ }
+ return value;
+}
+
+QString KConfigGroup::readPathEntry(const QString& pKey, const QString & aDefault) const
+{
+ return readPathEntry(pKey.toUtf8().constData(), aDefault);
+}
+
+QString KConfigGroup::readPathEntry(const char *key, const QString & aDefault) const
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::readPathEntry", "accessing an invalid group");
+
+ bool expand = false;
+
+ QString aValue = config()->d_func()->lookupData(d->fullName(), key, KEntryMap::SearchLocalized,
+ &expand);
+ if (aValue.isNull())
+ aValue = aDefault;
+
+ return KConfigPrivate::expandString(aValue);
+}
+
+QStringList KConfigGroup::readPathEntry(const QString& pKey, const QStringList& aDefault) const
+{
+ return readPathEntry(pKey.toUtf8().constData(), aDefault);
+}
+
+QStringList KConfigGroup::readPathEntry(const char *key, const QStringList& aDefault) const
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::readPathEntry", "accessing an invalid group");
+
+ const QString data = readPathEntry(key, QString());
+ if (data.isNull())
+ return aDefault;
+
+ return KConfigGroupPrivate::deserializeList(data);
+}
+
+void KConfigGroup::writeEntry( const char* key, const QString& value, WriteConfigFlags flags )
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::writeEntry", "accessing an invalid group");
+ Q_ASSERT_X(!d->bConst, "KConfigGroup::writeEntry", "writing to a read-only group");
+
+ writeEntry(key, value.toUtf8(), flags);
+}
+
+void KConfigGroup::writeEntry( const QString& key, const QString& value, WriteConfigFlags flags )
+{
+ writeEntry(key.toUtf8().constData(), value, flags);
+}
+
+void KConfigGroup::writeEntry(const QString &key, const char *value, WriteConfigFlags pFlags)
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::writeEntry", "accessing an invalid group");
+ Q_ASSERT_X(!d->bConst, "KConfigGroup::writeEntry", "writing to a read-only group");
+
+ writeEntry(key.toUtf8().constData(), QVariant(QString::fromLatin1(value)), pFlags);
+}
+
+void KConfigGroup::writeEntry(const char *key, const char *value, WriteConfigFlags pFlags)
+{
+ writeEntry(key, QVariant(QString::fromLatin1(value)), pFlags);
+}
+
+void KConfigGroup::writeEntry( const char* key, const QByteArray& value,
+ WriteConfigFlags flags )
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::writeEntry", "accessing an invalid group");
+ Q_ASSERT_X(!d->bConst, "KConfigGroup::writeEntry", "writing to a read-only group");
+
+ config()->d_func()->putData(d->fullName(), key, value.isNull()? QByteArray(""): value, flags);
+}
+
+void KConfigGroup::writeEntry(const QString& key, const QByteArray& value,
+ WriteConfigFlags pFlags)
+{
+ writeEntry(key.toUtf8().constData(), value, pFlags);
+}
+
+void KConfigGroup::writeEntry(const char* key, const QStringList &list, WriteConfigFlags flags)
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::writeEntry", "accessing an invalid group");
+ Q_ASSERT_X(!d->bConst, "KConfigGroup::writeEntry", "writing to a read-only group");
+
+ QList<QByteArray> balist;
+
+ Q_FOREACH(const QString &entry, list)
+ balist.append(entry.toUtf8());
+
+ writeEntry(key, KConfigGroupPrivate::serializeList(balist), flags);
+}
+
+void KConfigGroup::writeEntry(const QString& key, const QStringList &list, WriteConfigFlags flags)
+{
+ writeEntry(key.toUtf8().constData(), list, flags);
+}
+
+void KConfigGroup::writeEntry( const char* key, const QVariantList& list, WriteConfigFlags flags )
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::writeEntry", "accessing an invalid group");
+ Q_ASSERT_X(!d->bConst, "KConfigGroup::writeEntry", "writing to a read-only group");
+
+ QList<QByteArray> data;
+
+ Q_FOREACH(const QVariant& v, list) {
+ if (v.type() == QVariant::ByteArray)
+ data << v.toByteArray();
+ else
+ data << v.toString().toUtf8();
+ }
+
+ writeEntry(key, KConfigGroupPrivate::serializeList(data), flags);
+}
+
+void KConfigGroup::writeEntry( const char* key, const QVariant &value,
+ WriteConfigFlags flags )
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::writeEntry", "accessing an invalid group");
+ Q_ASSERT_X(!d->bConst, "KConfigGroup::writeEntry", "writing to a read-only group");
+
+ if ( writeEntryGui( this, key, value, flags ) )
+ return; // GUI type that was handled
+
+ QByteArray data;
+ // if a type handler is added here you must add a QVConversions definition
+ // to conversion_check.h, or ConversionCheck::to_QVariant will not allow
+ // writeEntry<T> to convert to QVariant.
+ switch( value.type() ) {
+ case QVariant::Invalid:
+ data = "";
+ break;
+ case QVariant::ByteArray:
+ data = value.toByteArray();
+ break;
+ case QVariant::String:
+ case QVariant::Int:
+ case QVariant::UInt:
+ case QVariant::Double:
+ case QMetaType::Float:
+ case QVariant::Bool:
+ case QVariant::LongLong:
+ case QVariant::ULongLong:
+ data = value.toString().toUtf8();
+ break;
+ case QVariant::List:
+ if (!value.canConvert(QVariant::StringList))
+ qWarning() << "not all types in \"" << key << "\" can convert to QString,"
+ " information will be lost";
+ case QVariant::StringList:
+ writeEntry( key, value.toList(), flags );
+ return;
+ case QVariant::Point: {
+ QVariantList list;
+ const QPoint rPoint = value.toPoint();
+ list.insert( 0, rPoint.x() );
+ list.insert( 1, rPoint.y() );
+
+ writeEntry( key, list, flags );
+ return;
+ }
+ case QVariant::PointF: {
+ QVariantList list;
+ const QPointF point = value.toPointF();
+ list.insert( 0, point.x() );
+ list.insert( 1, point.y() );
+
+ writeEntry( key, list, flags );
+ return;
+ }
+ case QVariant::Rect:{
+ QVariantList list;
+ const QRect rRect = value.toRect();
+ list.insert( 0, rRect.left() );
+ list.insert( 1, rRect.top() );
+ list.insert( 2, rRect.width() );
+ list.insert( 3, rRect.height() );
+
+ writeEntry( key, list, flags );
+ return;
+ }
+ case QVariant::RectF:{
+ QVariantList list;
+ const QRectF rRectF = value.toRectF();
+ list.insert(0, rRectF.left());
+ list.insert(1, rRectF.top());
+ list.insert(2, rRectF.width());
+ list.insert(3, rRectF.height());
+
+ writeEntry(key, list, flags);
+ return;
+ }
+ case QVariant::Size:{
+ QVariantList list;
+ const QSize rSize = value.toSize();
+ list.insert( 0, rSize.width() );
+ list.insert( 1, rSize.height() );
+
+ writeEntry( key, list, flags );
+ return;
+ }
+ case QVariant::SizeF:{
+ QVariantList list;
+ const QSizeF rSizeF = value.toSizeF();
+ list.insert(0, rSizeF.width());
+ list.insert(1, rSizeF.height());
+
+ writeEntry(key, list, flags);
+ return;
+ }
+ case QVariant::Date: {
+ QVariantList list;
+ const QDate date = value.toDate();
+
+ list.insert( 0, date.year() );
+ list.insert( 1, date.month() );
+ list.insert( 2, date.day() );
+
+ writeEntry( key, list, flags );
+ return;
+ }
+ case QVariant::DateTime: {
+ QVariantList list;
+ const QDateTime rDateTime = value.toDateTime();
+
+ const QTime time = rDateTime.time();
+ const QDate date = rDateTime.date();
+
+ list.insert( 0, date.year() );
+ list.insert( 1, date.month() );
+ list.insert( 2, date.day() );
+
+ list.insert( 3, time.hour() );
+ list.insert( 4, time.minute() );
+ list.insert( 5, time.second() );
+
+ writeEntry( key, list, flags );
+ return;
+ }
+
+ case QVariant::Color:
+ case QVariant::Font:
+ qWarning() << "KConfigGroup::writeEntry was passed GUI type '"
+ << value.typeName()
+ << "' but kdeui isn't linked! If it is linked to your program, this is a platform bug. "
+ "Please inform the KDE developers";
+ break;
+ case QVariant::Url:
+ data = QUrl(value.toUrl()).toString().toUtf8();
+ break;
+ default:
+ qWarning() << "KConfigGroup::writeEntry - unhandled type" << value.typeName() << "in group" << name();
+ }
+
+ writeEntry(key, data, flags);
+}
+
+void KConfigGroup::writeEntry( const QString& key, const QVariant& value, WriteConfigFlags flags )
+{
+ writeEntry(key.toUtf8().constData(), value, flags);
+}
+
+void KConfigGroup::writeEntry(const QString& key, const QVariantList &list, WriteConfigFlags flags)
+{
+ writeEntry(key.toUtf8().constData(), list, flags);
+}
+
+void KConfigGroup::writeXdgListEntry(const QString& key, const QStringList &value, WriteConfigFlags pFlags)
+{
+ writeXdgListEntry(key.toUtf8().constData(), value, pFlags);
+}
+
+void KConfigGroup::writeXdgListEntry(const char *key, const QStringList &list, WriteConfigFlags flags)
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::writeXdgListEntry", "accessing an invalid group");
+ Q_ASSERT_X(!d->bConst, "KConfigGroup::writeXdgListEntry", "writing to a read-only group");
+
+ QString value;
+ value.reserve(4096);
+
+ // XXX List serialization being a separate layer from low-level escaping is
+ // probably a bug. No affected entries are defined, though.
+ QStringList::ConstIterator it = list.constBegin();
+ const QStringList::ConstIterator end = list.constEnd();
+ for (; it != end; ++it) {
+ QString val(*it);
+ val.replace(QLatin1Char('\\'), QLatin1String("\\\\")).replace(QLatin1Char(';'), QLatin1String("\\;"));
+ value += val;
+ value += QLatin1Char(';');
+ }
+
+ writeEntry(key, value, flags);
+}
+
+void KConfigGroup::writePathEntry(const QString& pKey, const QString & path, WriteConfigFlags pFlags)
+{
+ writePathEntry(pKey.toUtf8().constData(), path, pFlags);
+}
+
+void KConfigGroup::writePathEntry(const char *pKey, const QString & path, WriteConfigFlags pFlags)
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::writePathEntry", "accessing an invalid group");
+ Q_ASSERT_X(!d->bConst, "KConfigGroup::writePathEntry", "writing to a read-only group");
+
+ config()->d_func()->putData(d->fullName(), pKey, translatePath(path).toUtf8(), pFlags, true);
+}
+
+void KConfigGroup::writePathEntry(const QString& pKey, const QStringList &value, WriteConfigFlags pFlags)
+{
+ writePathEntry(pKey.toUtf8().constData(), value, pFlags);
+}
+
+void KConfigGroup::writePathEntry(const char *pKey, const QStringList &value, WriteConfigFlags pFlags)
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::writePathEntry", "accessing an invalid group");
+ Q_ASSERT_X(!d->bConst, "KConfigGroup::writePathEntry", "writing to a read-only group");
+
+ QList<QByteArray> list;
+ Q_FOREACH(const QString& path, value)
+ list << translatePath(path).toUtf8();
+
+ config()->d_func()->putData(d->fullName(), pKey, KConfigGroupPrivate::serializeList(list), pFlags, true);
+}
+
+void KConfigGroup::deleteEntry( const char *key, WriteConfigFlags flags)
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::deleteEntry", "accessing an invalid group");
+ Q_ASSERT_X(!d->bConst, "KConfigGroup::deleteEntry", "deleting from a read-only group");
+
+ config()->d_func()->putData(d->fullName(), key, QByteArray(), flags);
+}
+
+void KConfigGroup::deleteEntry( const QString& key, WriteConfigFlags flags)
+{
+ deleteEntry(key.toUtf8().constData(), flags);
+}
+
+void KConfigGroup::revertToDefault(const char *key)
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::revertToDefault", "accessing an invalid group");
+ Q_ASSERT_X(!d->bConst, "KConfigGroup::revertToDefault", "writing to a read-only group");
+
+ config()->d_func()->revertEntry(d->fullName(), key);
+}
+
+void KConfigGroup::revertToDefault(const QString &key)
+{
+ revertToDefault(key.toUtf8().constData());
+}
+
+bool KConfigGroup::hasDefault(const char *key) const
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::hasDefault", "accessing an invalid group");
+
+ KEntryMap::SearchFlags flags = KEntryMap::SearchDefaults|KEntryMap::SearchLocalized;
+
+ return !config()->d_func()->lookupData(d->fullName(), key, flags).isNull();
+}
+
+bool KConfigGroup::hasDefault(const QString &key) const
+{
+ return hasDefault(key.toUtf8().constData());
+}
+
+bool KConfigGroup::hasKey(const char *key) const
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::hasKey", "accessing an invalid group");
+
+ KEntryMap::SearchFlags flags = KEntryMap::SearchLocalized;
+ if ( config()->readDefaults() )
+ flags |= KEntryMap::SearchDefaults;
+
+ return !config()->d_func()->lookupData(d->fullName(), key, flags).isNull();
+}
+
+bool KConfigGroup::hasKey(const QString &key) const
+{
+ return hasKey(key.toUtf8().constData());
+}
+
+bool KConfigGroup::isImmutable() const
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::isImmutable", "accessing an invalid group");
+
+ return d->bImmutable;
+}
+
+QStringList KConfigGroup::groupList() const
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::groupList", "accessing an invalid group");
+
+ return config()->d_func()->groupList(d->fullName());
+}
+
+QStringList KConfigGroup::keyList() const
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::keyList", "accessing an invalid group");
+
+ return entryMap().keys();
+}
+
+void KConfigGroup::markAsClean()
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::markAsClean", "accessing an invalid group");
+
+ config()->markAsClean();
+}
+
+KConfigGroup::AccessMode KConfigGroup::accessMode() const
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::accessMode", "accessing an invalid group");
+
+ return config()->accessMode();
+}
+
+bool KConfigGroup::hasGroupImpl(const QByteArray & b) const
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::hasGroupImpl", "accessing an invalid group");
+
+ return config()->hasGroup(d->fullName(b));
+}
+
+void KConfigGroup::deleteGroupImpl(const QByteArray &b, WriteConfigFlags flags)
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::deleteGroupImpl", "accessing an invalid group");
+ Q_ASSERT_X(!d->bConst,"KConfigGroup::deleteGroupImpl", "deleting from a read-only group");
+
+ config()->deleteGroup(d->fullName(b), flags);
+}
+
+bool KConfigGroup::isGroupImmutableImpl(const QByteArray& b) const
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::isGroupImmutableImpl", "accessing an invalid group");
+
+ if (!hasGroupImpl(b)) // group doesn't exist yet
+ return d->bImmutable; // child groups are immutable if the parent is immutable.
+
+ return config()->isGroupImmutable(d->fullName(b));
+}
+
+void KConfigGroup::copyTo(KConfigBase* other, WriteConfigFlags pFlags) const
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::copyTo", "accessing an invalid group");
+ Q_ASSERT(other != 0);
+
+ if (KConfigGroup *otherGroup = dynamic_cast<KConfigGroup*>(other)) {
+ config()->d_func()->copyGroup(d->fullName(), otherGroup->d->fullName(), otherGroup, pFlags);
+ } else if (KConfig* otherConfig = dynamic_cast<KConfig*>(other)) {
+ KConfigGroup newGroup = otherConfig->group(d->fullName());
+ otherConfig->d_func()->copyGroup(d->fullName(), d->fullName(), &newGroup, pFlags);
+ } else {
+ Q_ASSERT_X(false, "KConfigGroup::copyTo", "unknown type of KConfigBase");
+ }
+}
+
+void KConfigGroup::reparent(KConfigBase* parent, WriteConfigFlags pFlags)
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::reparent", "accessing an invalid group");
+ Q_ASSERT_X(!d->bConst, "KConfigGroup::reparent", "reparenting a read-only group");
+ Q_ASSERT_X(!d->bImmutable, "KConfigGroup::reparent", "reparenting an immutable group");
+ Q_ASSERT(parent != 0);
+
+ KConfigGroup oldGroup(*this);
+
+ d = KConfigGroupPrivate::create(parent, d->mName, false, false);
+ oldGroup.copyTo(this, pFlags);
+ oldGroup.deleteGroup(); // so that the entries with the old group name are deleted on sync
+}
diff --git a/tier1/kconfig/src/core/kconfiggroup.h b/tier1/kconfig/src/core/kconfiggroup.h
new file mode 100644
index 00000000..ce0330be
--- /dev/null
+++ b/tier1/kconfig/src/core/kconfiggroup.h
@@ -0,0 +1,767 @@
+/*
+ This file is part of the KDE libraries
+ Copyright (c) 2006, 2007 Thomas Braxton <kde.braxton@gmail.com>
+ Copyright (c) 1999 Preston Brown <pbrown@kde.org>
+ Copyright (c) 1997 Matthias Kalle Dalheimer <kalle@kde.org>
+ Copyright (c) 2001 Waldo Bastian <bastian@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KCONFIGGROUP_H
+#define KCONFIGGROUP_H
+
+#include "kconfigbase.h"
+
+#include <kconfigcore_export.h>
+
+#include <QtCore/QExplicitlySharedDataPointer>
+#include <QtCore/QVariant>
+#include <QtCore/QStringList>
+
+class KConfig;
+class KConfigGroupPrivate;
+class KSharedConfig;
+typedef QExplicitlySharedDataPointer<KSharedConfig> KSharedConfigPtr;
+/**
+ * \class KConfigGroup kconfiggroup.h <KConfigGroup>
+ *
+ * A class for one specific group in a KConfig object.
+ *
+ * If you want to access the top-level entries of a KConfig
+ * object, which are not associated with any group, use an
+ * empty group name.
+ *
+ * A KConfigGroup will be read-only if it is constructed from a
+ * const config object or from another read-only group.
+ */
+class KCONFIGCORE_EXPORT KConfigGroup : public KConfigBase
+{
+public:
+ /**
+ * Constructs an invalid group.
+ *
+ * \see isValid
+ */
+ KConfigGroup();
+
+ /**
+ * Construct a config group corresponding to @p group in @p master.
+ *
+ * This allows the creation of subgroups by passing another
+ * group as @p master.
+ *
+ * @p group is the group name encoded in UTF-8.
+ */
+ KConfigGroup(KConfigBase *master, const QString &group);
+ /** Overload for KConfigGroup(KConfigBase*,const QString&) */
+ KConfigGroup(KConfigBase *master, const char *group);
+
+ /**
+ * Construct a read-only config group.
+ *
+ * A read-only group will silently ignore any attempts to write to it.
+ *
+ * This allows the creation of subgroups by passing an existing group
+ * as @p master.
+ */
+ KConfigGroup(const KConfigBase *master, const QString &group);
+ /** Overload for KConfigGroup(const KConfigBase*,const QString&) */
+ KConfigGroup(const KConfigBase *master, const char *group);
+
+ /** Overload for KConfigGroup(const KConfigBase*,const QString&) */
+ KConfigGroup(const KSharedConfigPtr &master, const QString &group);
+ /** Overload for KConfigGroup(const KConfigBase*,const QString&) */
+ KConfigGroup(const KSharedConfigPtr &master, const char *group);
+
+ /**
+ * Creates a read-only copy of a read-only group.
+ */
+ KConfigGroup(const KConfigGroup &);
+ KConfigGroup &operator=(const KConfigGroup &);
+
+ ~KConfigGroup();
+
+ /**
+ * Whether the group is valid.
+ *
+ * A group is invalid if it was constructed without arguments.
+ *
+ * You should not call any functions on an invalid group.
+ *
+ * @return @c true if the group is valid, @c false if it is invalid.
+ */
+ bool isValid() const;
+
+ /**
+ * The name of this group.
+ *
+ * The root group is named "<default>".
+ */
+ QString name() const;
+
+ /**
+ * Check whether the containing KConfig object acutally contains a
+ * group with this name.
+ */
+ bool exists() const;
+
+ /**
+ * @reimp
+ *
+ * Syncs the parent config.
+ */
+ bool sync() Q_DECL_OVERRIDE;
+
+ /// @reimp
+ void markAsClean();
+
+ /// @reimp
+ AccessMode accessMode() const;
+
+ /**
+ * Return the config object that this group belongs to
+ */
+ KConfig* config();
+ /**
+ * Return the config object that this group belongs to
+ */
+ const KConfig* config() const;
+
+ /**
+ * Changes the group of the object
+ *
+ * @deprecated
+ * Create another KConfigGroup from the parent of this group instead.
+ */
+#ifndef KDE_NO_DEPRECATED
+ KCONFIGCORE_DEPRECATED void changeGroup(const QString &group);
+#endif
+ /**
+ * Overload for changeGroup(const QString&)
+ *
+ * @deprecated
+ * Create another KConfigGroup from the parent of this group instead.
+ */
+#ifndef KDE_NO_DEPRECATED
+ KCONFIGCORE_DEPRECATED void changeGroup(const char *group);
+#endif
+
+ /**
+ * Copies the entries in this group to another configuration object
+ *
+ * @note @p other can be either another group or a different file.
+ *
+ * @param other the configuration object to copy this group's entries to
+ * @param pFlags the flags to use when writing the entries to the
+ * other configuration object
+ *
+ * @since 4.1
+ */
+ void copyTo(KConfigBase *other, WriteConfigFlags pFlags = Normal) const;
+
+ /**
+ * Changes the configuration object that this group belongs to
+ *
+ * @note @p other can be another group, the top-level KConfig object or
+ * a different KConfig object entirely.
+ *
+ * If @p parent is already the parent of this group, this method will have
+ * no effect.
+ *
+ * @param parent the config object to place this group under
+ * @param pFlags the flags to use in determining which storage source to
+ * write the data to
+ *
+ * @since 4.1
+ */
+ void reparent(KConfigBase *parent, WriteConfigFlags pFlags = Normal);
+
+ /**
+ * Returns the group that this group belongs to
+ *
+ * @return the parent group, or an invalid group if this is a top-level
+ * group
+ *
+ * @since 4.1
+ */
+ KConfigGroup parent() const;
+
+ /**
+ * @reimp
+ */
+ QStringList groupList() const;
+
+ /**
+ * Returns a list of keys this group contains
+ */
+ QStringList keyList() const;
+
+ /**
+ * Delete all entries in the entire group
+ *
+ * @param pFlags flags passed to KConfig::deleteGroup
+ *
+ * @see deleteEntry()
+ */
+ void deleteGroup(WriteConfigFlags pFlags = Normal);
+ using KConfigBase::deleteGroup;
+
+ /**
+ * Reads the value of an entry specified by @p pKey in the current group
+ *
+ * This template method makes it possible to write
+ * QString foo = readEntry("...", QString("default"));
+ * and the same with all other types supported by QVariant.
+ *
+ * The return type of the method is simply the same as the type of the default value.
+ *
+ * @note readEntry("...", Qt::white) will not compile because Qt::white is an enum.
+ * You must turn it into readEntry("...", QColor(Qt::white)).
+ *
+ * @note Only the following QVariant types are allowed : String,
+ * StringList, List, Font, Point, Rect, Size, Color, Int, UInt, Bool,
+ * Double, LongLong, ULongLong, DateTime and Date.
+ *
+ * @param key The key to search for
+ * @param aDefault A default value returned if the key was not found
+ * @return The value for this key, or @p aDefault.
+ *
+ * @see writeEntry(), deleteEntry(), hasKey()
+ */
+ template <typename T>
+ inline T readEntry(const QString &key, const T &aDefault) const
+ { return readCheck(key.toUtf8().constData(), aDefault); }
+ /** Overload for readEntry(const QString&, const T&) const */
+ template <typename T>
+ inline T readEntry(const char *key, const T &aDefault) const
+ { return readCheck(key, aDefault); }
+
+ /**
+ * Reads the value of an entry specified by @p key in the current group
+ *
+ * @param key the key to search for
+ * @param aDefault a default value returned if the key was not found
+ * @return the value for this key, or @p aDefault if the key was not found
+ *
+ * @see writeEntry(), deleteEntry(), hasKey()
+ */
+ QVariant readEntry(const QString &key, const QVariant &aDefault) const;
+ /** Overload for readEntry(const QString&, const QVariant&) */
+ QVariant readEntry(const char *key, const QVariant &aDefault) const;
+
+ /**
+ * Reads the string value of an entry specified by @p key in the current group
+ *
+ * If you want to read a path, please use readPathEntry().
+ *
+ * @param key the key to search for
+ * @param aDefault a default value returned if the key was not found
+ * @return the value for this key, or @p aDefault if the key was not found
+ *
+ * @see readPathEntry(), writeEntry(), deleteEntry(), hasKey()
+ */
+ QString readEntry(const QString &key, const QString &aDefault) const;
+ /** Overload for readEntry(const QString&, const QString&) */
+ QString readEntry(const char *key, const QString &aDefault) const;
+
+ /** Overload for readEntry(const QString&, const QString&) */
+ QString readEntry(const QString &key, const char *aDefault = 0) const;
+ /** Overload for readEntry(const QString&, const QString&) */
+ QString readEntry(const char *key, const char *aDefault = 0) const;
+
+ /**
+ * @copydoc readEntry(const char*, const QStringList&) const
+ *
+ * @warning This function doesn't convert the items returned
+ * to any type. It's actually a list of QVariant::String's. If you
+ * want the items converted to a specific type use
+ * readEntry(const char*, const QList<T>&) const
+ */
+ QVariantList readEntry(const QString &key, const QVariantList &aDefault) const;
+ /** Overload for readEntry(const QString&, const QVariantList&) */
+ QVariantList readEntry(const char *key, const QVariantList &aDefault) const;
+
+ /**
+ * Reads a list of strings from the config object
+ *
+ * @param key The key to search for
+ * @param aDefault The default value to use if the key does not exist
+ * @return The list, or @p aDefault if @p key does not exist
+ *
+ * @see readXdgListEntry(), writeEntry(), deleteEntry(), hasKey()
+ */
+ QStringList readEntry(const QString &key, const QStringList &aDefault) const;
+ /** Overload for readEntry(const QString&, const QStringList&) */
+ QStringList readEntry(const char *key, const QStringList &aDefault) const;
+
+ /**
+ * Reads a list of values from the config object
+ *
+ * @param key the key to search for
+ * @param aDefault the default value to use if the key does not exist
+ * @return the list, or @p aDefault if @p key does not exist
+ *
+ * @see readXdgListEntry(), writeEntry(), deleteEntry(), hasKey()
+ */
+ template<typename T>
+ inline QList<T> readEntry(const QString &key, const QList<T> &aDefault) const
+ { return readListCheck(key.toUtf8().constData(), aDefault); }
+ /** Overload for readEntry(const QString&, const QList<T>&) */
+ template<typename T>
+ inline QList<T> readEntry(const char *key, const QList<T> &aDefault) const
+ { return readListCheck(key, aDefault); }
+
+ /**
+ * Reads a list of strings from the config object, following XDG
+ * desktop entry spec separator semantics
+ *
+ * @param pKey the key to search for
+ * @param aDefault the default value to use if the key does not exist
+ * @return the list, or @p aDefault if @p pKey does not exist
+ *
+ * @see readEntry(const QString&, const QStringList&) const
+ */
+ QStringList readXdgListEntry(const QString &pKey, const QStringList &aDefault = QStringList()) const;
+ /** Overload for readXdgListEntry(const QString&, const QStringList&) */
+ QStringList readXdgListEntry(const char *pKey, const QStringList &aDefault = QStringList()) const;
+
+ /**
+ * Reads a path
+ *
+ * Read the value of an entry specified by @p pKey in the current group
+ * and interpret it as a path. This means, dollar expansion is activated
+ * for this value, so that e.g. $HOME gets expanded.
+ *
+ * @param pKey The key to search for.
+ * @param aDefault A default value returned if the key was not found.
+ * @return The value for this key. Can be QString() if @p aDefault is null.
+ */
+ QString readPathEntry(const QString &pKey, const QString &aDefault) const;
+ /** Overload for readPathEntry(const QString&, const QString&) */
+ QString readPathEntry(const char *key, const QString &aDefault) const;
+
+ /**
+ * Reads a list of paths
+ *
+ * Read the value of an entry specified by @p pKey in the current group
+ * and interpret it as a list of paths. This means, dollar expansion is activated
+ * for this value, so that e.g. $HOME gets expanded.
+ *
+ * @param pKey the key to search for
+ * @param aDefault a default value returned if the key was not found
+ * @return the list, or @p aDefault if the key does not exist
+ */
+ QStringList readPathEntry(const QString &pKey, const QStringList &aDefault) const;
+ /** Overload for readPathEntry(const QString&, const QStringList&) */
+ QStringList readPathEntry(const char *key, const QStringList &aDefault) const;
+
+ /**
+ * Reads an untranslated string entry
+ *
+ * You should not normally need to use this.
+ *
+ * @param pKey the key to search for
+ * @param aDefault a default value returned if the key was not found
+ * @return the value for this key, or @p aDefault if the key does not exist
+ */
+ QString readEntryUntranslated(const QString &pKey,
+ const QString &aDefault = QString()) const;
+ /** Overload for readEntryUntranslated(const QString&, const QString&) */
+ QString readEntryUntranslated(const char *key,
+ const QString &aDefault = QString()) const;
+
+ /**
+ * Writes a value to the configuration object.
+ *
+ * @param key the key to write to
+ * @param value the value to write
+ * @param pFlags the flags to use when writing this entry
+ *
+ * @see readEntry(), writeXdgListEntry(), deleteEntry()
+ */
+ void writeEntry(const QString &key, const QVariant &value,
+ WriteConfigFlags pFlags = Normal);
+ /** Overload for writeEntry(const QString&, const QVariant&, WriteConfigFlags) */
+ void writeEntry(const char *key, const QVariant &value,
+ WriteConfigFlags pFlags = Normal);
+
+ /** Overload for writeEntry(const QString&, const QVariant&, WriteConfigFlags) */
+ void writeEntry(const QString &key, const QString &value,
+ WriteConfigFlags pFlags = Normal);
+ /** Overload for writeEntry(const QString&, const QVariant&, WriteConfigFlags) */
+ void writeEntry(const char *key, const QString &value,
+ WriteConfigFlags pFlags = Normal);
+
+ /** Overload for writeEntry(const QString&, const QVariant&, WriteConfigFlags) */
+ void writeEntry(const QString &key, const QByteArray &value,
+ WriteConfigFlags pFlags = Normal);
+ /** Overload for writeEntry(const QString&, const QVariant&, WriteConfigFlags) */
+ void writeEntry(const char *key, const QByteArray &value,
+ WriteConfigFlags pFlags = Normal);
+
+ /** Overload for writeEntry(const QString&, const QVariant&, WriteConfigFlags) */
+ void writeEntry(const QString &key, const char *value, WriteConfigFlags pFlags = Normal);
+ /** Overload for writeEntry(const QString&, const QVariant&, WriteConfigFlags) */
+ void writeEntry(const char *key, const char *value, WriteConfigFlags pFlags = Normal);
+
+ /** Overload for writeEntry(const QString&, const QVariant&, WriteConfigFlags) */
+ template <typename T>
+ inline void writeEntry(const char *key, const T &value, WriteConfigFlags pFlags = Normal)
+ { writeCheck( key, value, pFlags ); }
+ /** Overload for writeEntry(const QString&, const QVariant&, WriteConfigFlags) */
+ template <typename T>
+ inline void writeEntry(const QString &key, const T &value, WriteConfigFlags pFlags = Normal)
+ { writeCheck( key.toUtf8().constData(), value, pFlags ); }
+
+ /** Overload for writeEntry(const QString&, const QVariant&, WriteConfigFlags) */
+ void writeEntry(const QString &key, const QStringList &value,
+ WriteConfigFlags pFlags = Normal);
+ /** Overload for writeEntry(const QString&, const QVariant&, WriteConfigFlags) */
+ void writeEntry(const char *key, const QStringList &value,
+ WriteConfigFlags pFlags = Normal);
+
+ /** Overload for writeEntry(const QString&, const QVariant&, WriteConfigFlags) */
+ void writeEntry(const QString &key, const QVariantList &value,
+ WriteConfigFlags pFlags = Normal);
+ /** Overload for writeEntry(const QString&, const QVariant&, WriteConfigFlags) */
+ void writeEntry(const char *key, const QVariantList &value,
+ WriteConfigFlags pFlags = Normal);
+
+ /** Overload for writeEntry(const QString&, const QVariant&, WriteConfigFlags) */
+ template <typename T>
+ inline void writeEntry(const QString &key, const QList<T> &value, WriteConfigFlags pFlags = Normal)
+ { writeListCheck( key.toUtf8().constData(), value, pFlags ); }
+ /** Overload for writeEntry(const QString&, const QVariant&, WriteConfigFlags) */
+ template <typename T>
+ inline void writeEntry(const char *key, const QList<T> &value, WriteConfigFlags pFlags = Normal)
+ { writeListCheck( key, value, pFlags ); }
+
+ /**
+ * Writes a list of strings to the config object, following XDG
+ * desktop entry spec separator semantics
+ *
+ * @param pKey the key to write to
+ * @param value the list to write
+ * @param pFlags the flags to use when writing this entry
+ *
+ * @see writeEntry(), readXdgListEntry()
+ */
+ void writeXdgListEntry(const QString &pKey, const QStringList &value,
+ WriteConfigFlags pFlags = Normal);
+ /** Overload for writeXdgListEntry(const QString&, const QStringList&, WriteConfigFlags) */
+ void writeXdgListEntry(const char *pKey, const QStringList &value,
+ WriteConfigFlags pFlags = Normal);
+
+ /**
+ * Writes a file path to the configuration
+ *
+ * If the path is located under $HOME, the user's home directory
+ * is replaced with $HOME in the persistent storage.
+ * The path should therefore be read back with readPathEntry()
+ *
+ * @param pKey the key to write to
+ * @param path the path to write
+ * @param pFlags the flags to use when writing this entry
+ *
+ * @see writeEntry(), readPathEntry()
+ */
+ void writePathEntry(const QString &pKey, const QString &path,
+ WriteConfigFlags pFlags = Normal);
+ /** Overload for writePathEntry(const QString&, const QString&, WriteConfigFlags) */
+ void writePathEntry(const char *pKey, const QString &path,
+ WriteConfigFlags pFlags = Normal);
+
+ /**
+ * Writes a list of paths to the configuration
+ *
+ * If any of the paths are located under $HOME, the user's home directory
+ * is replaced with $HOME in the persistent storage.
+ * The paths should therefore be read back with readPathEntry()
+ *
+ * @param pKey the key to write to
+ * @param value the list to write
+ * @param pFlags the flags to use when writing this entry
+ *
+ * @see writeEntry(), readPathEntry()
+ */
+ void writePathEntry(const QString &pKey, const QStringList &value,
+ WriteConfigFlags pFlags = Normal);
+ /** Overload for writePathEntry(const QString&, const QStringList&, WriteConfigFlags) */
+ void writePathEntry(const char *pKey, const QStringList &value,
+ WriteConfigFlags pFlags = Normal);
+
+ /**
+ * Deletes the entry specified by @p pKey in the current group
+ *
+ * This also hides system wide defaults.
+ *
+ * @param pKey the key to delete
+ * @param pFlags the flags to use when deleting this entry
+ *
+ * @see deleteGroup(), readEntry(), writeEntry()
+ */
+ void deleteEntry(const QString &pKey, WriteConfigFlags pFlags = Normal);
+ /** Overload for deleteEntry(const QString&, WriteConfigFlags) */
+ void deleteEntry(const char *pKey, WriteConfigFlags pFlags = Normal);
+
+ /**
+ * Checks whether the key has an entry in this group
+ *
+ * Use this to determine if a key is not specified for the current
+ * group (hasKey() returns false).
+ *
+ * If this returns @c false for a key, readEntry() (and its variants)
+ * will return the default value passed to them.
+ *
+ * @param key the key to search for
+ * @return @c true if the key is defined in this group by any of the
+ * configuration sources, @c false otherwise
+ *
+ * @see readEntry()
+ */
+ bool hasKey(const QString &key) const;
+ /** Overload for hasKey(const QString&) const */
+ bool hasKey(const char *key) const;
+
+ /**
+ * Whether this group may be changed
+ *
+ * @return @c false if the group may be changed, @c true otherwise
+ */
+ bool isImmutable() const;
+
+ /**
+ * Checks if it is possible to change the given entry
+ *
+ * If isImmutable() returns @c true, then this method will return
+ * @c true for all inputs.
+ *
+ * @param key the key to check
+ * @return @c false if the key may be changed using this configuration
+ * group object, @c true otherwise
+ */
+ bool isEntryImmutable(const QString &key) const;
+ /** Overload for isEntryImmutable(const QString&) const */
+ bool isEntryImmutable(const char *key) const;
+
+ /**
+ * Reverts an entry to the default settings.
+ *
+ * Reverts the entry with key @p key in the current group in the
+ * application specific config file to either the system wide (default)
+ * value or the value specified in the global KDE config file.
+ *
+ * To revert entries in the global KDE config file, the global KDE config
+ * file should be opened explicitly in a separate config object.
+ *
+ * @note This is @em not the same as deleting the key, as instead the
+ * global setting will be copied to the configuration file that this
+ * object manipulates.
+ *
+ * @param key The key of the entry to revert.
+ */
+ void revertToDefault(const QString &key);
+ /** Overload for revertToDefault(const QString&) */
+ void revertToDefault(const char* key);
+
+ /**
+ * Whether a default is specified for an entry in either the
+ * system wide configuration file or the global KDE config file
+ *
+ * If an application computes a default value at runtime for
+ * a certain entry, e.g. like:
+ * \code
+ * QColor computedDefault = qApp->palette().color(QPalette::Active, QPalette::Text);
+ * QColor color = group.readEntry(key, computedDefault);
+ * \endcode
+ * then it may wish to make the following check before
+ * writing back changes:
+ * \code
+ * if ( (value == computedDefault) && !group.hasDefault(key) )
+ * group.revertToDefault(key);
+ * else
+ * group.writeEntry(key, value);
+ * \endcode
+ *
+ * This ensures that as long as the entry is not modified to differ from
+ * the computed default, the application will keep using the computed default
+ * and will follow changes the computed default makes over time.
+ *
+ * @param key the key of the entry to check
+ * @return @c true if the global or system settings files specify a default
+ * for @p key in this group, @c false otherwise
+ */
+ bool hasDefault(const QString &key) const;
+ /** Overload for hasDefault(const QString&) const */
+ bool hasDefault(const char *key) const;
+
+ /**
+ * Returns a map (tree) of entries for all entries in this group
+ *
+ * Only the actual entry string is returned, none of the
+ * other internal data should be included.
+ *
+ * @return a map of entries in this group, indexed by key
+ */
+ QMap<QString, QString> entryMap() const;
+
+protected:
+ bool hasGroupImpl(const QByteArray &group) const;
+ KConfigGroup groupImpl(const QByteArray &b);
+ const KConfigGroup groupImpl(const QByteArray &b) const;
+ void deleteGroupImpl(const QByteArray &group, WriteConfigFlags flags);
+ bool isGroupImmutableImpl(const QByteArray &aGroup) const;
+
+private:
+ QExplicitlySharedDataPointer<KConfigGroupPrivate> d;
+
+ template<typename T>
+ inline T readCheck(const char *key, const T &defaultValue) const;
+
+ template<typename T>
+ inline QList<T> readListCheck(const char *key, const QList<T> &defaultValue) const;
+
+ template<typename T>
+ inline void writeCheck(const char *key, const T &value, WriteConfigFlags pFlags);
+
+ template<typename T>
+ inline void writeListCheck(const char *key, const QList<T> &value, WriteConfigFlags pFlags);
+
+ friend class KConfigGroupPrivate;
+
+ /**
+ * Return the data in @p value converted to a QVariant
+ *
+ * @param pKey the name of the entry being converted, this is only used for error
+ * reporting
+ * @param value the UTF-8 data to be converted
+ * @param aDefault the default value if @p pKey is not found
+ * @return @p value converted to QVariant, or @p aDefault if @p value is invalid or cannot be converted.
+ */
+ static QVariant convertToQVariant(const char *pKey, const QByteArray &value, const QVariant &aDefault);
+ friend class KServicePrivate; // XXX yeah, ugly^5
+};
+
+#define KCONFIGGROUP_ENUMERATOR_ERROR(ENUM) \
+"The Qt MetaObject system does not seem to know about \"" ENUM \
+"\" please use Q_ENUMS or Q_FLAGS to register it."
+
+/**
+ * To add support for your own enums in KConfig, you can declare them with Q_ENUMS()
+ * in a QObject subclass (which will make moc generate the code to turn the
+ * enum into a string and vice-versa), and then (in the cpp code)
+ * use the macro
+ * <code>KCONFIGGROUP_DECLARE_ENUM_QOBJECT(MyClass, MyEnum)</code>
+ *
+ * After that, you can use readEntry(group, key, value) and writeEntry(group, key, value[, flags]).
+ * Note that those are global functions, NOT member functions of KConfigGroup.
+ *
+ */
+#define KCONFIGGROUP_DECLARE_ENUM_QOBJECT(Class, Enum) \
+inline Class::Enum readEntry(const KConfigGroup& group, const char* key, const Class::Enum& def) \
+{ \
+const QMetaObject* M_obj = &Class::staticMetaObject; \
+const int M_index = M_obj->indexOfEnumerator(#Enum); \
+if(M_index == -1) qFatal(KCONFIGGROUP_ENUMERATOR_ERROR(#Enum)); \
+const QMetaEnum M_enum = M_obj->enumerator(M_index); \
+const QByteArray M_data = group.readEntry(key, QByteArray(M_enum.valueToKey(def)));\
+return static_cast<Class::Enum>(M_enum.keyToValue(M_data.constData())); \
+} \
+inline void writeEntry(KConfigGroup& group, const char* key, const Class::Enum& value, KConfigBase::WriteConfigFlags flags = KConfigBase::Normal)\
+{ \
+const QMetaObject* M_obj = &Class::staticMetaObject; \
+const int M_index = M_obj->indexOfEnumerator(#Enum); \
+if(M_index == -1) qFatal(KCONFIGGROUP_ENUMERATOR_ERROR(#Enum)); \
+const QMetaEnum M_enum = M_obj->enumerator(M_index); \
+group.writeEntry(key, QByteArray(M_enum.valueToKey(value)), flags); \
+}
+
+/**
+ * Similar to KCONFIGGROUP_DECLARE_ENUM_QOBJECT but for flags declared with Q_FLAGS()
+ * (where multiple values can be set at the same time)
+ */
+#define KCONFIGGROUP_DECLARE_FLAGS_QOBJECT(Class, Flags) \
+inline Class::Flags readEntry(const KConfigGroup& group, const char* key, const Class::Flags& def) \
+{ \
+const QMetaObject* M_obj = &Class::staticMetaObject; \
+const int M_index = M_obj->indexOfEnumerator(#Flags); \
+if(M_index == -1) qFatal(KCONFIGGROUP_ENUMERATOR_ERROR(#Flags)); \
+const QMetaEnum M_enum = M_obj->enumerator(M_index); \
+const QByteArray M_data = group.readEntry(key, QByteArray(M_enum.valueToKeys(def)));\
+return static_cast<Class::Flags>(M_enum.keysToValue(M_data.constData())); \
+} \
+inline void writeEntry(KConfigGroup& group, const char* key, const Class::Flags& value, KConfigBase::WriteConfigFlags flags = KConfigBase::Normal)\
+{ \
+const QMetaObject* M_obj = &Class::staticMetaObject; \
+const int M_index = M_obj->indexOfEnumerator(#Flags); \
+if(M_index == -1) qFatal(KCONFIGGROUP_ENUMERATOR_ERROR(#Flags)); \
+const QMetaEnum M_enum = M_obj->enumerator(M_index); \
+group.writeEntry(key, QByteArray(M_enum.valueToKeys(value)), flags); \
+}
+
+#include "conversion_check.h"
+
+template <typename T>
+T KConfigGroup::readCheck(const char *key, const T &defaultValue) const
+{
+ ConversionCheck::to_QVariant<T>();
+ return qvariant_cast<T>(readEntry(key, qVariantFromValue(defaultValue)));
+}
+
+template <typename T>
+QList<T> KConfigGroup::readListCheck(const char *key, const QList<T> &defaultValue) const
+{
+ ConversionCheck::to_QVariant<T>();
+ ConversionCheck::to_QString<T>();
+
+ QVariantList data;
+
+ Q_FOREACH(const T& value, defaultValue)
+ data.append(qVariantFromValue(value));
+
+ QList<T> list;
+ Q_FOREACH (const QVariant &value, readEntry<QVariantList>(key, data)) {
+ Q_ASSERT(value.canConvert<T>());
+ list.append(qvariant_cast<T>(value));
+ }
+
+ return list;
+}
+
+template <typename T>
+void KConfigGroup::writeCheck(const char *key, const T &value,
+ WriteConfigFlags pFlags)
+{
+ ConversionCheck::to_QVariant<T>();
+ writeEntry(key, qVariantFromValue(value), pFlags);
+}
+
+template <typename T>
+void KConfigGroup::writeListCheck(const char *key, const QList<T> &list,
+ WriteConfigFlags pFlags)
+{
+ ConversionCheck::to_QVariant<T>();
+ ConversionCheck::to_QString<T>();
+ QVariantList data;
+ Q_FOREACH(const T &value, list) {
+ data.append(qVariantFromValue(value));
+ }
+
+ writeEntry(key, data, pFlags);
+}
+
+#endif // KCONFIGGROUP_H
diff --git a/tier1/kconfig/src/core/kconfiggroup_p.h b/tier1/kconfig/src/core/kconfiggroup_p.h
new file mode 100644
index 00000000..c5d4f150
--- /dev/null
+++ b/tier1/kconfig/src/core/kconfiggroup_p.h
@@ -0,0 +1,42 @@
+/*
+ This file is part of the KDE libraries
+ Copyright (c) 2007 Thiago Macieira <thiago@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KCONFIGGROUP_P_H
+#define KCONFIGGROUP_P_H
+
+#include <QtCore/QVariant>
+#include "kconfiggroup.h"
+
+class KConfigGroup;
+
+struct KConfigGroupGui
+{
+ typedef bool (*kReadEntryGui)(const QByteArray& data, const char* key, const QVariant &input,
+ QVariant &output);
+ typedef bool (*kWriteEntryGui)(KConfigGroup *, const char* key, const QVariant &input,
+ KConfigGroup::WriteConfigFlags flags);
+
+ kReadEntryGui readEntryGui;
+ kWriteEntryGui writeEntryGui;
+};
+
+extern KCONFIGCORE_EXPORT KConfigGroupGui _kde_internal_KConfigGroupGui;
+
+#endif
diff --git a/tier1/kconfig/src/core/kconfigini.cpp b/tier1/kconfig/src/core/kconfigini.cpp
new file mode 100644
index 00000000..f44b2c39
--- /dev/null
+++ b/tier1/kconfig/src/core/kconfigini.cpp
@@ -0,0 +1,770 @@
+/*
+ This file is part of the KDE libraries
+ Copyright (c) 2006, 2007 Thomas Braxton <kde.braxton@gmail.com>
+ Copyright (c) 1999 Preston Brown <pbrown@kde.org>
+ Copyright (C) 1997-1999 Matthias Kalle Dalheimer (kalle@kde.org)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "kconfigini_p.h"
+
+#include "kconfig.h"
+#include "kconfigbackend.h"
+#include "bufferfragment_p.h"
+#include "kconfigdata.h"
+
+#include <qsavefile.h>
+#include <qlockfile.h>
+#include <qdatetime.h>
+#include <qdir.h>
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qdebug.h>
+#include <qplatformdefs.h>
+
+#ifndef Q_OS_WIN
+#include <unistd.h> // getuid, close
+#endif
+#include <sys/types.h> // uid_t
+#include <fcntl.h> // open
+
+KCONFIGCORE_EXPORT bool kde_kiosk_exception = false; // flag to disable kiosk restrictions
+
+QString KConfigIniBackend::warningProlog(const QFile &file, int line)
+{
+ return QString::fromLatin1("KConfigIni: In file %2, line %1: ")
+ .arg(line).arg(file.fileName());
+}
+
+KConfigIniBackend::KConfigIniBackend()
+ : KConfigBackend(), lockFile(NULL)
+{
+}
+
+KConfigIniBackend::~KConfigIniBackend()
+{
+}
+
+KConfigBackend::ParseInfo
+ KConfigIniBackend::parseConfig(const QByteArray& currentLocale, KEntryMap& entryMap,
+ ParseOptions options)
+{
+ return parseConfig(currentLocale, entryMap, options, false);
+}
+
+// merging==true is the merging that happens at the beginning of writeConfig:
+// merge changes in the on-disk file with the changes in the KConfig object.
+KConfigBackend::ParseInfo
+KConfigIniBackend::parseConfig(const QByteArray& currentLocale, KEntryMap& entryMap,
+ ParseOptions options, bool merging)
+{
+ if (filePath().isEmpty() || !QFile::exists(filePath()))
+ return ParseOk;
+
+ bool bDefault = options&ParseDefaults;
+ bool allowExecutableValues = options&ParseExpansions;
+
+ QByteArray currentGroup("<default>");
+
+ QFile file(filePath());
+ if (!file.open(QIODevice::ReadOnly|QIODevice::Text))
+ return ParseOpenError;
+
+ QList<QByteArray> immutableGroups;
+
+ bool fileOptionImmutable = false;
+ bool groupOptionImmutable = false;
+ bool groupSkip = false;
+
+ int lineNo = 0;
+ // on systems using \r\n as end of line, \r will be taken care of by
+ // trim() below
+ QByteArray buffer = file.readAll();
+ BufferFragment contents(buffer.data(), buffer.size());
+ unsigned int len = contents.length();
+ unsigned int startOfLine = 0;
+
+ while (startOfLine < len) {
+ BufferFragment line = contents.split('\n', &startOfLine);
+ line.trim();
+ lineNo++;
+
+ // skip empty lines and lines beginning with '#'
+ if (line.isEmpty() || line.at(0) == '#')
+ continue;
+
+ if (line.at(0) == '[') { // found a group
+ groupOptionImmutable = fileOptionImmutable;
+
+ QByteArray newGroup;
+ int start = 1, end;
+ do {
+ end = start;
+ for (;;) {
+ if (end == line.length()) {
+ qWarning() << warningProlog(file, lineNo) << "Invalid group header.";
+ // XXX maybe reset the current group here?
+ goto next_line;
+ }
+ if (line.at(end) == ']')
+ break;
+ end++;
+ }
+ if (end + 1 == line.length() && start + 2 == end &&
+ line.at(start) == '$' && line.at(start + 1) == 'i')
+ {
+ if (newGroup.isEmpty())
+ fileOptionImmutable = !kde_kiosk_exception;
+ else
+ groupOptionImmutable = !kde_kiosk_exception;
+ }
+ else {
+ if (!newGroup.isEmpty())
+ newGroup += '\x1d';
+ BufferFragment namePart=line.mid(start, end - start);
+ printableToString(&namePart, file, lineNo);
+ newGroup += namePart.toByteArray();
+ }
+ } while ((start = end + 2) <= line.length() && line.at(end + 1) == '[');
+ currentGroup = newGroup;
+
+ groupSkip = entryMap.getEntryOption(currentGroup, 0, 0, KEntryMap::EntryImmutable);
+
+ if (groupSkip && !bDefault)
+ continue;
+
+ if (groupOptionImmutable)
+ // Do not make the groups immutable until the entries from
+ // this file have been added.
+ immutableGroups.append(currentGroup);
+ } else {
+ if (groupSkip && !bDefault)
+ continue; // skip entry
+
+ BufferFragment aKey;
+ int eqpos = line.indexOf('=');
+ if (eqpos < 0) {
+ aKey = line;
+ line.clear();
+ } else {
+ BufferFragment temp = line.left(eqpos);
+ temp.trim();
+ aKey = temp;
+ line.truncateLeft(eqpos + 1);
+ }
+ if (aKey.isEmpty()) {
+ qWarning() << warningProlog(file, lineNo) << "Invalid entry (empty key)";
+ continue;
+ }
+
+ KEntryMap::EntryOptions entryOptions=0;
+ if (groupOptionImmutable)
+ entryOptions |= KEntryMap::EntryImmutable;
+
+ BufferFragment locale;
+ int start;
+ while ((start = aKey.lastIndexOf('[')) >= 0) {
+ int end = aKey.indexOf(']', start);
+ if (end < 0) {
+ qWarning() << warningProlog(file, lineNo)
+ << "Invalid entry (missing ']')";
+ goto next_line;
+ } else if (end > start + 1 && aKey.at(start + 1) == '$') { // found option(s)
+ int i = start + 2;
+ while (i < end) {
+ switch (aKey.at(i)) {
+ case 'i':
+ if (!kde_kiosk_exception)
+ entryOptions |= KEntryMap::EntryImmutable;
+ break;
+ case 'e':
+ if (allowExecutableValues)
+ entryOptions |= KEntryMap::EntryExpansion;
+ break;
+ case 'd':
+ entryOptions |= KEntryMap::EntryDeleted;
+ aKey = aKey.left(start);
+ printableToString(&aKey, file, lineNo);
+ entryMap.setEntry(currentGroup, aKey.toByteArray(), QByteArray(), entryOptions);
+ goto next_line;
+ default:
+ break;
+ }
+ i++;
+ }
+ } else { // found a locale
+ if (!locale.isNull()) {
+ qWarning() << warningProlog(file, lineNo)
+ << "Invalid entry (second locale!?)";
+ goto next_line;
+ }
+
+ locale = aKey.mid(start + 1,end - start - 1);
+ }
+ aKey.truncate(start);
+ }
+ if (eqpos < 0) { // Do this here after [$d] was checked
+ qWarning() << warningProlog(file, lineNo) << "Invalid entry (missing '=')";
+ continue;
+ }
+ printableToString(&aKey, file, lineNo);
+ if (!locale.isEmpty()) {
+ if (locale != currentLocale) {
+ // backward compatibility. C == en_US
+ if (locale.at(0) != 'C' || currentLocale != "en_US") {
+ if (merging)
+ entryOptions |= KEntryMap::EntryRawKey;
+ else
+ goto next_line; // skip this entry if we're not merging
+ }
+ }
+ }
+
+ if (!(entryOptions & KEntryMap::EntryRawKey))
+ printableToString(&aKey, file, lineNo);
+
+ if (options&ParseGlobal)
+ entryOptions |= KEntryMap::EntryGlobal;
+ if (bDefault)
+ entryOptions |= KEntryMap::EntryDefault;
+ if (!locale.isNull())
+ entryOptions |= KEntryMap::EntryLocalized;
+ printableToString(&line, file, lineNo);
+ if (entryOptions & KEntryMap::EntryRawKey) {
+ QByteArray rawKey;
+ rawKey.reserve(aKey.length() + locale.length() + 2);
+ rawKey.append(aKey.toVolatileByteArray());
+ rawKey.append('[').append(locale.toVolatileByteArray()).append(']');
+ entryMap.setEntry(currentGroup, rawKey, line.toByteArray(), entryOptions);
+ } else {
+ entryMap.setEntry(currentGroup, aKey.toByteArray(), line.toByteArray(), entryOptions);
+ }
+ }
+next_line:
+ continue;
+ }
+
+ // now make sure immutable groups are marked immutable
+ Q_FOREACH(const QByteArray& group, immutableGroups) {
+ entryMap.setEntry(group, QByteArray(), QByteArray(), KEntryMap::EntryImmutable);
+ }
+
+ return fileOptionImmutable ? ParseImmutable : ParseOk;
+}
+
+void KConfigIniBackend::writeEntries(const QByteArray& locale, QIODevice& file,
+ const KEntryMap& map, bool defaultGroup, bool &firstEntry)
+{
+ QByteArray currentGroup;
+ bool groupIsImmutable = false;
+ const KEntryMapConstIterator end = map.constEnd();
+ for (KEntryMapConstIterator it = map.constBegin(); it != end; ++it) {
+ const KEntryKey& key = it.key();
+
+ // Either process the default group or all others
+ if ((key.mGroup != "<default>") == defaultGroup)
+ continue; // skip
+
+ // the only thing we care about groups is, is it immutable?
+ if (key.mKey.isNull()) {
+ groupIsImmutable = it->bImmutable;
+ continue; // skip
+ }
+
+ const KEntry& currentEntry = *it;
+ if (!defaultGroup && currentGroup != key.mGroup) {
+ if (!firstEntry)
+ file.putChar('\n');
+ currentGroup = key.mGroup;
+ for (int start = 0, end;; start = end + 1) {
+ file.putChar('[');
+ end = currentGroup.indexOf('\x1d', start);
+ if (end < 0) {
+ int cgl = currentGroup.length();
+ if (currentGroup.at(start) == '$' && cgl - start <= 10) {
+ for (int i = start + 1; i < cgl; i++) {
+ char c = currentGroup.at(i);
+ if (c < 'a' || c > 'z')
+ goto nope;
+ }
+ file.write("\\x24");
+ start++;
+ }
+ nope:
+ file.write(stringToPrintable(currentGroup.mid(start), GroupString));
+ file.putChar(']');
+ if (groupIsImmutable) {
+ file.write("[$i]", 4);
+ }
+ file.putChar('\n');
+ break;
+ } else {
+ file.write(stringToPrintable(currentGroup.mid(start, end - start), GroupString));
+ file.putChar(']');
+ }
+ }
+ }
+
+ firstEntry = false;
+ // it is data for a group
+
+ if (key.bRaw) // unprocessed key with attached locale from merge
+ file.write(key.mKey);
+ else {
+ file.write(stringToPrintable(key.mKey, KeyString)); // Key
+ if (key.bLocal && locale != "C") { // 'C' locale == untranslated
+ file.putChar('[');
+ file.write(locale); // locale tag
+ file.putChar(']');
+ }
+ }
+ if (currentEntry.bDeleted) {
+ if (currentEntry.bImmutable)
+ file.write("[$di]", 5); // Deleted + immutable
+ else
+ file.write("[$d]", 4); // Deleted
+ } else {
+ if (currentEntry.bImmutable || currentEntry.bExpand) {
+ file.write("[$", 2);
+ if (currentEntry.bImmutable)
+ file.putChar('i');
+ if (currentEntry.bExpand)
+ file.putChar('e');
+ file.putChar(']');
+ }
+ file.putChar('=');
+ file.write(stringToPrintable(currentEntry.mValue, ValueString));
+ }
+ file.putChar('\n');
+ }
+}
+
+void KConfigIniBackend::writeEntries(const QByteArray& locale, QIODevice& file, const KEntryMap& map)
+{
+ bool firstEntry = true;
+
+ // write default group
+ writeEntries(locale, file, map, true, firstEntry);
+
+ // write all other groups
+ writeEntries(locale, file, map, false, firstEntry);
+}
+
+bool KConfigIniBackend::writeConfig(const QByteArray& locale, KEntryMap& entryMap,
+ WriteOptions options)
+{
+ Q_ASSERT(!filePath().isEmpty());
+
+ KEntryMap writeMap;
+ const bool bGlobal = options & WriteGlobal;
+
+ // First, reparse the file on disk, to merge our changes with the ones done by other apps
+ // Store the result into writeMap.
+ {
+ ParseOptions opts = ParseExpansions;
+ if (bGlobal)
+ opts |= ParseGlobal;
+ ParseInfo info = parseConfig(locale, writeMap, opts, true);
+ if (info != ParseOk) // either there was an error or the file became immutable
+ return false;
+ }
+
+ const KEntryMapIterator end = entryMap.end();
+ for (KEntryMapIterator it=entryMap.begin(); it != end; ++it) {
+ if (!it.key().mKey.isEmpty() && !it->bDirty) // not dirty, doesn't overwrite entry in writeMap. skips default entries, too.
+ continue;
+
+ const KEntryKey& key = it.key();
+
+ // only write entries that have the same "globality" as the file
+ if (it->bGlobal == bGlobal) {
+ if (it->bReverted) {
+ writeMap.remove(key);
+ } else if (!it->bDeleted) {
+ writeMap[key] = *it;
+ } else {
+ KEntryKey defaultKey = key;
+ defaultKey.bDefault = true;
+ if (!entryMap.contains(defaultKey)) {
+ writeMap.remove(key); // remove the deleted entry if there is no default
+ //qDebug() << "Detected as deleted=>removed:" << key.mGroup << key.mKey << "global=" << bGlobal;
+ } else {
+ writeMap[key] = *it; // otherwise write an explicitly deleted entry
+ //qDebug() << "Detected as deleted=>[$d]:" << key.mGroup << key.mKey << "global=" << bGlobal;
+ }
+ }
+ it->bDirty = false;
+ }
+ }
+
+ // now writeMap should contain only entries to be written
+ // so write it out to disk
+
+ // check if file exists
+ QFile::Permissions fileMode = QFile::ReadUser | QFile::WriteUser;
+ bool createNew = true;
+
+ QFileInfo fi(filePath());
+ if (fi.exists())
+ {
+#ifdef Q_OS_WIN
+ //TODO: getuid does not exist on windows, use GetSecurityInfo and GetTokenInformation instead
+ createNew = false;
+#else
+ if (fi.ownerId() == ::getuid())
+ {
+ // Preserve file mode if file exists and is owned by user.
+ fileMode = fi.permissions();
+ }
+ else
+ {
+ // File is not owned by user:
+ // Don't create new file but write to existing file instead.
+ createNew = false;
+ }
+#endif
+ }
+
+ if (createNew) {
+ QSaveFile file(filePath());
+ if (!file.open(QIODevice::WriteOnly)) {
+ return false;
+ }
+
+ file.setTextModeEnabled(true); // to get eol translation
+ writeEntries(locale, file, writeMap);
+
+ if (!file.size() && (fileMode == (QFile::ReadUser | QFile::WriteUser))) {
+ // File is empty and doesn't have special permissions: delete it.
+ file.cancelWriting();
+
+ if (fi.exists()) {
+ // also remove the old file in case it existed. this can happen
+ // when we delete all the entries in an existing config file.
+ // if we don't do this, then deletions and revertToDefault's
+ // will mysteriously fail
+ QFile::remove(filePath());
+ }
+ } else {
+ // Normal case: Close the file
+ if (file.commit()) {
+ QFile::setPermissions(filePath(), fileMode);
+ return true;
+ }
+ // Couldn't write. Disk full?
+ qWarning() << "Couldn't write" << filePath() << ". Disk full?";
+ return false;
+ }
+ } else {
+ // Open existing file. *DON'T* create it if it suddenly does not exist!
+#ifdef Q_OS_UNIX
+ int fd = QT_OPEN(QFile::encodeName(filePath()).constData(), O_WRONLY | O_TRUNC);
+ if (fd < 0) {
+ return false;
+ }
+ FILE *fp = ::fdopen(fd, "w");
+ if (!fp) {
+ QT_CLOSE(fd);
+ return false;
+ }
+ QFile f;
+ if (!f.open(fp, QIODevice::WriteOnly)) {
+ fclose(fp);
+ return false;
+ }
+ writeEntries(locale, f, writeMap);
+ f.close();
+ fclose(fp);
+#else
+ QFile f( filePath() );
+ // XXX This is broken - it DOES create the file if it is suddenly gone.
+ if (!f.open( QIODevice::WriteOnly | QIODevice::Truncate )) {
+ return false;
+ }
+ f.setTextModeEnabled(true);
+ writeEntries(locale, f, writeMap);
+#endif
+ }
+ return true;
+}
+
+
+bool KConfigIniBackend::isWritable() const
+{
+ const QString filePath = this->filePath();
+ if (!filePath.isEmpty()) {
+ QFileInfo file(filePath);
+ if (!file.exists()) {
+ // If the file does not exist, check if the deepest
+ // existing dir is writable.
+ QFileInfo dir(file.absolutePath());
+ while (!dir.exists()) {
+ QString parent = dir.absolutePath(); // Go up. Can't use cdUp() on non-existing dirs.
+ if (parent == dir.filePath()) {
+ // no parent
+ return false;
+ }
+ dir.setFile(parent);
+ }
+ return dir.isDir() && dir.isWritable();
+ } else {
+ return file.isWritable();
+ }
+ }
+
+ return false;
+}
+
+QString KConfigIniBackend::nonWritableErrorMessage() const
+{
+ return tr("Configuration file \"%1\" not writable.\n").arg(filePath());
+}
+
+void KConfigIniBackend::createEnclosing()
+{
+ const QString file = filePath();
+ if (file.isEmpty())
+ return; // nothing to do
+
+ // Create the containing dir, maybe it wasn't there
+ QDir dir;
+ dir.mkpath(QFileInfo(file).absolutePath());
+}
+
+void KConfigIniBackend::setFilePath(const QString& file)
+{
+ if (file.isEmpty())
+ return;
+
+ Q_ASSERT(QDir::isAbsolutePath(file));
+
+ const QFileInfo info(file);
+ if (info.exists()) {
+ setLocalFilePath(info.canonicalFilePath());
+ setLastModified(info.lastModified());
+ setSize(info.size());
+ } else {
+ setLocalFilePath(file);
+ setSize(0);
+ QDateTime dummy;
+ dummy.setTime_t(0);
+ setLastModified(dummy);
+ }
+}
+
+KConfigBase::AccessMode KConfigIniBackend::accessMode() const
+{
+ if (filePath().isEmpty())
+ return KConfigBase::NoAccess;
+
+ if (isWritable())
+ return KConfigBase::ReadWrite;
+
+ return KConfigBase::ReadOnly;
+}
+
+bool KConfigIniBackend::lock()
+{
+ Q_ASSERT(!filePath().isEmpty());
+
+ if (!lockFile) {
+ lockFile = new QLockFile(filePath() + QLatin1String(".lock"));
+ }
+
+ // This is a workaround for current QLockFilePrivate::tryLock_sys
+ // which might crash calling qAppName() if sync() is called after
+ // the QCoreApplication instance is gone. It might be the case with
+ // KSharedConfig instances cleanup.
+ if (!lockFile->tryLock(lockFile->staleLockTime())) {
+ lockFile->removeStaleLockFile();
+ lockFile->lock();
+ }
+ return lockFile->isLocked();
+}
+
+void KConfigIniBackend::unlock()
+{
+ lockFile->unlock();
+ delete lockFile;
+ lockFile = NULL;
+}
+
+bool KConfigIniBackend::isLocked() const
+{
+ return lockFile && lockFile->isLocked();
+}
+
+QByteArray KConfigIniBackend::stringToPrintable(const QByteArray& aString, StringType type)
+{
+ static const char nibbleLookup[] = {
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
+ };
+
+ if (aString.isEmpty())
+ return aString;
+ const int l = aString.length();
+
+ QByteArray result; // Guesstimated that it's good to avoid data() initialization for a length of l*4
+ result.resize(l * 4); // Maximum 4x as long as source string due to \x<ab> escape sequences
+ register const char *s = aString.constData();
+ int i = 0;
+ char *data = result.data();
+ char *start = data;
+
+ // Protect leading space
+ if (s[0] == ' ' && type != GroupString) {
+ *data++ = '\\';
+ *data++ = 's';
+ i++;
+ }
+
+ for (; i < l; ++i/*, r++*/) {
+ switch (s[i]) {
+ default:
+ // The \n, \t, \r cases (all < 32) are handled below; we can ignore them here
+ if (((unsigned char)s[i]) < 32)
+ goto doEscape;
+ *data++ = s[i];
+ break;
+ case '\n':
+ *data++ = '\\';
+ *data++ = 'n';
+ break;
+ case '\t':
+ *data++ = '\\';
+ *data++ = 't';
+ break;
+ case '\r':
+ *data++ = '\\';
+ *data++ = 'r';
+ break;
+ case '\\':
+ *data++ = '\\';
+ *data++ = '\\';
+ break;
+ case '=':
+ if (type != KeyString) {
+ *data++ = s[i];
+ break;
+ }
+ goto doEscape;
+ case '[':
+ case ']':
+ // Above chars are OK to put in *value* strings as plaintext
+ if (type == ValueString) {
+ *data++ = s[i];
+ break;
+ }
+ doEscape:
+ *data++ = '\\';
+ *data++ = 'x';
+ *data++ = nibbleLookup[((unsigned char)s[i]) >> 4];
+ *data++ = nibbleLookup[((unsigned char)s[i]) & 0x0f];
+ break;
+ }
+ }
+ *data = 0;
+ result.resize(data - start);
+
+ // Protect trailing space
+ if (result.endsWith(' ') && type != GroupString) {
+ result.replace(result.length() - 1, 1, "\\s");
+ }
+ result.squeeze();
+
+ return result;
+}
+
+char KConfigIniBackend::charFromHex(const char *str, const QFile& file, int line)
+{
+ unsigned char ret = 0;
+ for (int i = 0; i < 2; i++) {
+ ret <<= 4;
+ quint8 c = quint8(str[i]);
+
+ if (c >= '0' && c <= '9') {
+ ret |= c - '0';
+ } else if (c >= 'a' && c <= 'f') {
+ ret |= c - 'a' + 0x0a;
+ } else if (c >= 'A' && c <= 'F') {
+ ret |= c - 'A' + 0x0a;
+ } else {
+ QByteArray e(str, 2);
+ e.prepend("\\x");
+ qWarning() << warningProlog(file, line) << "Invalid hex character " << c
+ << " in \\x<nn>-type escape sequence \"" << e.constData() << "\".";
+ return 'x';
+ }
+ }
+ return char(ret);
+}
+
+void KConfigIniBackend::printableToString(BufferFragment* aString, const QFile& file, int line)
+{
+ if (aString->isEmpty() || aString->indexOf('\\')==-1)
+ return;
+ aString->trim();
+ int l = aString->length();
+ char *r = aString->data();
+ char *str=r;
+
+ for(int i = 0; i < l; i++, r++) {
+ if (str[i]!= '\\') {
+ *r=str[i];
+ } else {
+ // Probable escape sequence
+ i++;
+ if (i >= l) { // Line ends after backslash - stop.
+ *r = '\\';
+ break;
+ }
+
+ switch(str[i]) {
+ case 's':
+ *r = ' ';
+ break;
+ case 't':
+ *r = '\t';
+ break;
+ case 'n':
+ *r = '\n';
+ break;
+ case 'r':
+ *r = '\r';
+ break;
+ case '\\':
+ *r = '\\';
+ break;
+ case 'x':
+ if (i + 2 < l) {
+ *r = charFromHex(str + i + 1, file, line);
+ i += 2;
+ } else {
+ *r = 'x';
+ i = l - 1;
+ }
+ break;
+ default:
+ *r = '\\';
+ qWarning() << warningProlog(file, line)
+ << QString::fromLatin1("Invalid escape sequence \"\\%1\".").arg(str[i]);
+ }
+ }
+ }
+ aString->truncate(r - aString->constData());
+}
diff --git a/tier1/kconfig/src/core/kconfigini_p.h b/tier1/kconfig/src/core/kconfigini_p.h
new file mode 100644
index 00000000..368a78fb
--- /dev/null
+++ b/tier1/kconfig/src/core/kconfigini_p.h
@@ -0,0 +1,81 @@
+/*
+ This file is part of the KDE libraries
+ Copyright (c) 2006, 2007 Thomas Braxton <kde.braxton@gmail.com>
+ Copyright (c) 1999 Preston Brown <pbrown@kde.org>
+ Portions copyright (c) 1997 Matthias Kalle Dalheimer <kalle@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KCONFIGINI_P_H
+#define KCONFIGINI_P_H
+
+#include <kconfigcore_export.h>
+#include <kconfigbackend.h>
+
+class QLockFile;
+class QIODevice;
+
+class KConfigIniBackend : public KConfigBackend
+{
+private:
+ class BufferFragment;
+
+ QLockFile *lockFile;
+public:
+
+ KConfigIniBackend();
+ ~KConfigIniBackend();
+
+ ParseInfo parseConfig(const QByteArray& locale,
+ KEntryMap& entryMap,
+ ParseOptions options);
+ ParseInfo parseConfig(const QByteArray& locale,
+ KEntryMap& entryMap,
+ ParseOptions options,
+ bool merging);
+ bool writeConfig(const QByteArray& locale, KEntryMap& entryMap,
+ WriteOptions options);
+
+ bool isWritable() const;
+ QString nonWritableErrorMessage() const;
+ KConfigBase::AccessMode accessMode() const;
+ void createEnclosing();
+ void setFilePath(const QString& path);
+ bool lock();
+ void unlock();
+ bool isLocked() const;
+
+protected:
+
+ enum StringType {
+ GroupString = 0,
+ KeyString = 1,
+ ValueString = 2
+ };
+ // Warning: this modifies data in-place. Other BufferFragment objects referencing the same buffer
+ // fragment will get their data modified too.
+ static void printableToString(BufferFragment* aString, const QFile& file, int line);
+ static QByteArray stringToPrintable(const QByteArray& aString, StringType type);
+ static char charFromHex(const char *str, const QFile& file, int line);
+ static QString warningProlog(const QFile& file, int line);
+
+ void writeEntries(const QByteArray& locale, QIODevice& file, const KEntryMap& map);
+ void writeEntries(const QByteArray& locale, QIODevice& file, const KEntryMap& map,
+ bool defaultGroup, bool &firstEntry);
+};
+
+#endif // KCONFIGINI_P_H
diff --git a/tier1/kconfig/src/core/kcoreconfigskeleton.cpp b/tier1/kconfig/src/core/kcoreconfigskeleton.cpp
new file mode 100644
index 00000000..691e0b54
--- /dev/null
+++ b/tier1/kconfig/src/core/kcoreconfigskeleton.cpp
@@ -0,0 +1,1343 @@
+/*
+ This file is part of KOrganizer.
+ Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org>
+ Copyright (c) 2003 Waldo Bastian <bastian@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "kcoreconfigskeleton.h"
+#include "kcoreconfigskeleton_p.h"
+
+#include <QUrl>
+
+
+static QString obscuredString(const QString &str)
+{
+ QString result;
+ const QChar *unicode = str.unicode();
+ for ( int i = 0; i < str.length(); ++i )
+ // yes, no typo. can't encode ' ' or '!' because
+ // they're the unicode BOM. stupid scrambling. stupid.
+ result += ( unicode[ i ].unicode() <= 0x21 ) ? unicode[ i ]
+ : QChar( 0x1001F - unicode[ i ].unicode() );
+
+ return result;
+}
+
+KConfigSkeletonItem::KConfigSkeletonItem(const QString & _group,
+ const QString & _key)
+ : mGroup(_group)
+ , mKey(_key)
+ , d( new KConfigSkeletonItemPrivate )
+{
+}
+
+KConfigSkeletonItem::~KConfigSkeletonItem()
+{
+ delete d;
+}
+
+void KConfigSkeletonItem::setGroup( const QString &_group )
+{
+ mGroup = _group;
+}
+
+QString KConfigSkeletonItem::group() const
+{
+ return mGroup;
+}
+
+void KConfigSkeletonItem::setKey( const QString &_key )
+{
+ mKey = _key;
+}
+
+QString KConfigSkeletonItem::key() const
+{
+ return mKey;
+}
+
+void KConfigSkeletonItem::setName(const QString &_name)
+{
+ mName = _name;
+}
+
+QString KConfigSkeletonItem::name() const
+{
+ return mName;
+}
+
+void KConfigSkeletonItem::setLabel( const QString &l )
+{
+ d->mLabel = l;
+}
+
+QString KConfigSkeletonItem::label() const
+{
+ return d->mLabel;
+}
+
+void KConfigSkeletonItem::setToolTip( const QString &t )
+{
+ d->mToolTip = t;
+}
+
+QString KConfigSkeletonItem::toolTip() const
+{
+ return d->mToolTip;
+}
+
+void KConfigSkeletonItem::setWhatsThis( const QString &w )
+{
+ d->mWhatsThis = w;
+}
+
+QString KConfigSkeletonItem::whatsThis() const
+{
+ return d->mWhatsThis;
+}
+
+QVariant KConfigSkeletonItem::minValue() const
+{
+ return QVariant();
+}
+
+QVariant KConfigSkeletonItem::maxValue() const
+{
+ return QVariant();
+}
+
+bool KConfigSkeletonItem::isImmutable() const
+{
+ return d->mIsImmutable;
+}
+
+void KConfigSkeletonItem::readImmutability( const KConfigGroup &group )
+{
+ d->mIsImmutable = group.isEntryImmutable( mKey );
+}
+
+
+KCoreConfigSkeleton::ItemString::ItemString( const QString &_group, const QString &_key,
+ QString &reference,
+ const QString &defaultValue,
+ Type type )
+ : KConfigSkeletonGenericItem<QString>( _group, _key, reference, defaultValue ),
+ mType( type )
+{
+}
+
+void KCoreConfigSkeleton::ItemString::writeConfig( KConfig *config )
+{
+ if ( mReference != mLoadedValue ) // WABA: Is this test needed?
+ {
+ KConfigGroup cg(config, mGroup );
+ if ((mDefault == mReference) && !cg.hasDefault( mKey))
+ cg.revertToDefault( mKey );
+ else if ( mType == Path )
+ cg.writePathEntry( mKey, mReference );
+ else if ( mType == Password )
+ cg.writeEntry( mKey, obscuredString( mReference ) );
+ else
+ cg.writeEntry( mKey, mReference );
+ }
+}
+
+
+void KCoreConfigSkeleton::ItemString::readConfig( KConfig *config )
+{
+ KConfigGroup cg(config, mGroup );
+
+ if ( mType == Path )
+ {
+ mReference = cg.readPathEntry( mKey, mDefault );
+ }
+ else if ( mType == Password )
+ {
+ QString val = cg.readEntry( mKey, obscuredString( mDefault ) );
+ mReference = obscuredString( val );
+ }
+ else
+ {
+ mReference = cg.readEntry( mKey, mDefault );
+ }
+
+ mLoadedValue = mReference;
+
+ readImmutability( cg );
+}
+
+void KCoreConfigSkeleton::ItemString::setProperty(const QVariant & p)
+{
+ mReference = p.toString();
+}
+
+bool KCoreConfigSkeleton::ItemString::isEqual(const QVariant &v) const
+{
+ return mReference == v.toString();
+}
+
+QVariant KCoreConfigSkeleton::ItemString::property() const
+{
+ return QVariant(mReference);
+}
+
+KCoreConfigSkeleton::ItemPassword::ItemPassword( const QString &_group, const QString &_key,
+ QString &reference,
+ const QString &defaultValue)
+ : ItemString( _group, _key, reference, defaultValue, Password )
+{
+}
+
+KCoreConfigSkeleton::ItemPath::ItemPath( const QString &_group, const QString &_key,
+ QString &reference,
+ const QString &defaultValue)
+ : ItemString( _group, _key, reference, defaultValue, Path )
+{
+}
+
+KCoreConfigSkeleton::ItemUrl::ItemUrl( const QString &_group, const QString &_key,
+ QUrl &reference,
+ const QUrl &defaultValue )
+ : KConfigSkeletonGenericItem<QUrl>( _group, _key, reference, defaultValue )
+{
+}
+
+void KCoreConfigSkeleton::ItemUrl::writeConfig( KConfig *config )
+{
+ if ( mReference != mLoadedValue ) // WABA: Is this test needed?
+ {
+ KConfigGroup cg(config, mGroup );
+ if ((mDefault == mReference) && !cg.hasDefault( mKey))
+ cg.revertToDefault( mKey );
+ else
+ cg.writeEntry<QString>( mKey, mReference.toString() );
+ }
+}
+
+void KCoreConfigSkeleton::ItemUrl::readConfig( KConfig *config )
+{
+ KConfigGroup cg(config, mGroup );
+
+ mReference = QUrl( cg.readEntry<QString>( mKey, mDefault.toString() ) );
+ mLoadedValue = mReference;
+
+ readImmutability( cg );
+}
+
+void KCoreConfigSkeleton::ItemUrl::setProperty(const QVariant & p)
+{
+ mReference = qvariant_cast<QUrl>(p);
+}
+
+bool KCoreConfigSkeleton::ItemUrl::isEqual(const QVariant &v) const
+{
+ return mReference == qvariant_cast<QUrl>(v);
+}
+
+QVariant KCoreConfigSkeleton::ItemUrl::property() const
+{
+ return qVariantFromValue<QUrl>(mReference);
+}
+
+KCoreConfigSkeleton::ItemProperty::ItemProperty( const QString &_group,
+ const QString &_key,
+ QVariant &reference,
+ const QVariant &defaultValue )
+ : KConfigSkeletonGenericItem<QVariant>( _group, _key, reference, defaultValue )
+{
+}
+
+void KCoreConfigSkeleton::ItemProperty::readConfig( KConfig *config )
+{
+ KConfigGroup cg(config, mGroup );
+ mReference = cg.readEntry( mKey, mDefault );
+ mLoadedValue = mReference;
+
+ readImmutability( cg );
+}
+
+void KCoreConfigSkeleton::ItemProperty::setProperty(const QVariant & p)
+{
+ mReference = p;
+}
+
+bool KCoreConfigSkeleton::ItemProperty::isEqual(const QVariant &v) const
+{
+ //this might cause problems if the QVariants are not of default types
+ return mReference == v;
+}
+
+QVariant KCoreConfigSkeleton::ItemProperty::property() const
+{
+ return mReference;
+}
+
+KCoreConfigSkeleton::ItemBool::ItemBool( const QString &_group, const QString &_key,
+ bool &reference, bool defaultValue )
+ : KConfigSkeletonGenericItem<bool>( _group, _key, reference, defaultValue )
+{
+}
+
+void KCoreConfigSkeleton::ItemBool::readConfig( KConfig *config )
+{
+ KConfigGroup cg(config, mGroup );
+ mReference = cg.readEntry( mKey, mDefault );
+ mLoadedValue = mReference;
+
+ readImmutability( cg );
+}
+
+void KCoreConfigSkeleton::ItemBool::setProperty(const QVariant & p)
+{
+ mReference = p.toBool();
+}
+
+bool KCoreConfigSkeleton::ItemBool::isEqual(const QVariant &v) const
+{
+ return mReference == v.toBool();
+}
+
+QVariant KCoreConfigSkeleton::ItemBool::property() const
+{
+ return QVariant( mReference );
+}
+
+
+KCoreConfigSkeleton::ItemInt::ItemInt( const QString &_group, const QString &_key,
+ qint32 &reference, qint32 defaultValue )
+ : KConfigSkeletonGenericItem<qint32>( _group, _key, reference, defaultValue )
+ ,mHasMin(false), mHasMax(false)
+{
+}
+
+void KCoreConfigSkeleton::ItemInt::readConfig( KConfig *config )
+{
+ KConfigGroup cg(config, mGroup );
+ mReference = cg.readEntry( mKey, mDefault );
+ if (mHasMin)
+ mReference = qMax(mReference, mMin);
+ if (mHasMax)
+ mReference = qMin(mReference, mMax);
+ mLoadedValue = mReference;
+
+ readImmutability( cg );
+}
+
+void KCoreConfigSkeleton::ItemInt::setProperty(const QVariant & p)
+{
+ mReference = p.toInt();
+}
+
+bool KCoreConfigSkeleton::ItemInt::isEqual(const QVariant &v) const
+{
+ return mReference == v.toInt();
+}
+
+QVariant KCoreConfigSkeleton::ItemInt::property() const
+{
+ return QVariant(mReference);
+}
+
+QVariant KCoreConfigSkeleton::ItemInt::minValue() const
+{
+ if (mHasMin)
+ return QVariant(mMin);
+ return QVariant();
+}
+
+QVariant KCoreConfigSkeleton::ItemInt::maxValue() const
+{
+ if (mHasMax)
+ return QVariant(mMax);
+ return QVariant();
+}
+
+void KCoreConfigSkeleton::ItemInt::setMinValue(qint32 v)
+{
+ mHasMin = true;
+ mMin = v;
+}
+
+void KCoreConfigSkeleton::ItemInt::setMaxValue(qint32 v)
+{
+ mHasMax = true;
+ mMax = v;
+}
+
+
+KCoreConfigSkeleton::ItemLongLong::ItemLongLong( const QString &_group, const QString &_key,
+ qint64 &reference, qint64 defaultValue )
+ : KConfigSkeletonGenericItem<qint64>( _group, _key, reference, defaultValue )
+ ,mHasMin(false), mHasMax(false)
+{
+}
+
+void KCoreConfigSkeleton::ItemLongLong::readConfig( KConfig *config )
+{
+ KConfigGroup cg(config, mGroup );
+ mReference = cg.readEntry( mKey, mDefault );
+ if (mHasMin)
+ mReference = qMax(mReference, mMin);
+ if (mHasMax)
+ mReference = qMin(mReference, mMax);
+ mLoadedValue = mReference;
+
+ readImmutability( cg );
+}
+
+void KCoreConfigSkeleton::ItemLongLong::setProperty(const QVariant & p)
+{
+ mReference = p.toLongLong();
+}
+
+bool KCoreConfigSkeleton::ItemLongLong::isEqual(const QVariant &v) const
+{
+ return mReference == v.toLongLong();
+}
+
+QVariant KCoreConfigSkeleton::ItemLongLong::property() const
+{
+ return QVariant(mReference);
+}
+
+QVariant KCoreConfigSkeleton::ItemLongLong::minValue() const
+{
+ if (mHasMin)
+ return QVariant(mMin);
+ return QVariant();
+}
+
+QVariant KCoreConfigSkeleton::ItemLongLong::maxValue() const
+{
+ if (mHasMax)
+ return QVariant(mMax);
+ return QVariant();
+}
+
+void KCoreConfigSkeleton::ItemLongLong::setMinValue(qint64 v)
+{
+ mHasMin = true;
+ mMin = v;
+}
+
+void KCoreConfigSkeleton::ItemLongLong::setMaxValue(qint64 v)
+{
+ mHasMax = true;
+ mMax = v;
+}
+
+KCoreConfigSkeleton::ItemEnum::ItemEnum( const QString &_group, const QString &_key,
+ qint32 &reference,
+ const QList<Choice> &choices,
+ qint32 defaultValue )
+ : ItemInt( _group, _key, reference, defaultValue ), mChoices(choices)
+{
+}
+
+void KCoreConfigSkeleton::ItemEnum::readConfig( KConfig *config )
+{
+ KConfigGroup cg(config, mGroup );
+ if (!cg.hasKey(mKey))
+ {
+ mReference = mDefault;
+ }
+ else
+ {
+ int i = 0;
+ mReference = -1;
+ QString tmp = cg.readEntry( mKey, QString() ).toLower();
+ for(QList<Choice>::ConstIterator it = mChoices.constBegin();
+ it != mChoices.constEnd(); ++it, ++i)
+ {
+ if ((*it).name.toLower() == tmp)
+ {
+ mReference = i;
+ break;
+ }
+ }
+ if (mReference == -1)
+ mReference = cg.readEntry( mKey, mDefault );
+ }
+ mLoadedValue = mReference;
+
+ readImmutability( cg );
+}
+
+void KCoreConfigSkeleton::ItemEnum::writeConfig( KConfig *config )
+{
+ if ( mReference != mLoadedValue ) // WABA: Is this test needed?
+ {
+ KConfigGroup cg(config, mGroup );
+ if ((mDefault == mReference) && !cg.hasDefault( mKey))
+ cg.revertToDefault( mKey );
+ else if ((mReference >= 0) && (mReference < (int) mChoices.count()))
+ cg.writeEntry( mKey, mChoices[mReference].name );
+ else
+ cg.writeEntry( mKey, mReference );
+ }
+}
+
+QList<KCoreConfigSkeleton::ItemEnum::Choice> KCoreConfigSkeleton::ItemEnum::choices() const
+{
+ return mChoices;
+}
+
+QList<KCoreConfigSkeleton::ItemEnum::Choice> KCoreConfigSkeleton::ItemEnum::choices2() const
+{
+ return mChoices;
+}
+
+KCoreConfigSkeleton::ItemUInt::ItemUInt( const QString &_group, const QString &_key,
+ quint32 &reference,
+ quint32 defaultValue )
+ : KConfigSkeletonGenericItem<quint32>( _group, _key, reference, defaultValue )
+ ,mHasMin(false), mHasMax(false)
+{
+}
+
+void KCoreConfigSkeleton::ItemUInt::readConfig( KConfig *config )
+{
+ KConfigGroup cg(config, mGroup );
+ mReference = cg.readEntry( mKey, mDefault );
+ if (mHasMin)
+ mReference = qMax(mReference, mMin);
+ if (mHasMax)
+ mReference = qMin(mReference, mMax);
+ mLoadedValue = mReference;
+
+ readImmutability( cg );
+}
+
+void KCoreConfigSkeleton::ItemUInt::setProperty(const QVariant & p)
+{
+ mReference = p.toUInt();
+}
+
+bool KCoreConfigSkeleton::ItemUInt::isEqual(const QVariant &v) const
+{
+ return mReference == v.toUInt();
+}
+
+QVariant KCoreConfigSkeleton::ItemUInt::property() const
+{
+ return QVariant(mReference);
+}
+
+QVariant KCoreConfigSkeleton::ItemUInt::minValue() const
+{
+ if (mHasMin)
+ return QVariant(mMin);
+ return QVariant();
+}
+
+QVariant KCoreConfigSkeleton::ItemUInt::maxValue() const
+{
+ if (mHasMax)
+ return QVariant(mMax);
+ return QVariant();
+}
+
+void KCoreConfigSkeleton::ItemUInt::setMinValue(quint32 v)
+{
+ mHasMin = true;
+ mMin = v;
+}
+
+void KCoreConfigSkeleton::ItemUInt::setMaxValue(quint32 v)
+{
+ mHasMax = true;
+ mMax = v;
+}
+
+
+KCoreConfigSkeleton::ItemULongLong::ItemULongLong( const QString &_group, const QString &_key,
+ quint64 &reference, quint64 defaultValue )
+ : KConfigSkeletonGenericItem<quint64>( _group, _key, reference, defaultValue )
+ ,mHasMin(false), mHasMax(false)
+{
+}
+
+void KCoreConfigSkeleton::ItemULongLong::readConfig( KConfig *config )
+{
+ KConfigGroup cg(config, mGroup );
+ mReference = cg.readEntry( mKey, mDefault );
+ if (mHasMin)
+ mReference = qMax(mReference, mMin);
+ if (mHasMax)
+ mReference = qMin(mReference, mMax);
+ mLoadedValue = mReference;
+
+ readImmutability( cg );
+}
+
+void KCoreConfigSkeleton::ItemULongLong::setProperty(const QVariant & p)
+{
+ mReference = p.toULongLong();
+}
+
+bool KCoreConfigSkeleton::ItemULongLong::isEqual(const QVariant &v) const
+{
+ return mReference == v.toULongLong();
+}
+
+QVariant KCoreConfigSkeleton::ItemULongLong::property() const
+{
+ return QVariant(mReference);
+}
+
+QVariant KCoreConfigSkeleton::ItemULongLong::minValue() const
+{
+ if (mHasMin)
+ return QVariant(mMin);
+ return QVariant();
+}
+
+QVariant KCoreConfigSkeleton::ItemULongLong::maxValue() const
+{
+ if (mHasMax)
+ return QVariant(mMax);
+ return QVariant();
+}
+
+void KCoreConfigSkeleton::ItemULongLong::setMinValue(quint64 v)
+{
+ mHasMin = true;
+ mMin = v;
+}
+
+void KCoreConfigSkeleton::ItemULongLong::setMaxValue(quint64 v)
+{
+ mHasMax = true;
+ mMax = v;
+}
+
+KCoreConfigSkeleton::ItemDouble::ItemDouble( const QString &_group, const QString &_key,
+ double &reference, double defaultValue )
+ : KConfigSkeletonGenericItem<double>( _group, _key, reference, defaultValue )
+ ,mHasMin(false), mHasMax(false)
+{
+}
+
+void KCoreConfigSkeleton::ItemDouble::readConfig( KConfig *config )
+{
+ KConfigGroup cg(config, mGroup );
+ mReference = cg.readEntry( mKey, mDefault );
+ if (mHasMin)
+ mReference = qMax(mReference, mMin);
+ if (mHasMax)
+ mReference = qMin(mReference, mMax);
+ mLoadedValue = mReference;
+
+ readImmutability( cg );
+}
+
+void KCoreConfigSkeleton::ItemDouble::setProperty(const QVariant & p)
+{
+ mReference = p.toDouble();
+}
+
+bool KCoreConfigSkeleton::ItemDouble::isEqual(const QVariant &v) const
+{
+ return mReference == v.toDouble();
+}
+
+QVariant KCoreConfigSkeleton::ItemDouble::property() const
+{
+ return QVariant(mReference);
+}
+
+QVariant KCoreConfigSkeleton::ItemDouble::minValue() const
+{
+ if (mHasMin)
+ return QVariant(mMin);
+ return QVariant();
+}
+
+QVariant KCoreConfigSkeleton::ItemDouble::maxValue() const
+{
+ if (mHasMax)
+ return QVariant(mMax);
+ return QVariant();
+}
+
+void KCoreConfigSkeleton::ItemDouble::setMinValue(double v)
+{
+ mHasMin = true;
+ mMin = v;
+}
+
+void KCoreConfigSkeleton::ItemDouble::setMaxValue(double v)
+{
+ mHasMax = true;
+ mMax = v;
+}
+
+
+KCoreConfigSkeleton::ItemRect::ItemRect( const QString &_group, const QString &_key,
+ QRect &reference,
+ const QRect &defaultValue )
+ : KConfigSkeletonGenericItem<QRect>( _group, _key, reference, defaultValue )
+{
+}
+
+void KCoreConfigSkeleton::ItemRect::readConfig( KConfig *config )
+{
+ KConfigGroup cg(config, mGroup );
+ mReference = cg.readEntry( mKey, mDefault );
+ mLoadedValue = mReference;
+
+ readImmutability( cg );
+}
+
+void KCoreConfigSkeleton::ItemRect::setProperty(const QVariant & p)
+{
+ mReference = p.toRect();
+}
+
+bool KCoreConfigSkeleton::ItemRect::isEqual(const QVariant &v) const
+{
+ return mReference == v.toRect();
+}
+
+QVariant KCoreConfigSkeleton::ItemRect::property() const
+{
+ return QVariant(mReference);
+}
+
+
+KCoreConfigSkeleton::ItemPoint::ItemPoint( const QString &_group, const QString &_key,
+ QPoint &reference,
+ const QPoint &defaultValue )
+ : KConfigSkeletonGenericItem<QPoint>( _group, _key, reference, defaultValue )
+{
+}
+
+void KCoreConfigSkeleton::ItemPoint::readConfig( KConfig *config )
+{
+ KConfigGroup cg(config, mGroup );
+ mReference = cg.readEntry( mKey, mDefault );
+ mLoadedValue = mReference;
+
+ readImmutability( cg );
+}
+
+void KCoreConfigSkeleton::ItemPoint::setProperty(const QVariant & p)
+{
+ mReference = p.toPoint();
+}
+
+bool KCoreConfigSkeleton::ItemPoint::isEqual(const QVariant &v) const
+{
+ return mReference == v.toPoint();
+}
+
+QVariant KCoreConfigSkeleton::ItemPoint::property() const
+{
+ return QVariant(mReference);
+}
+
+
+KCoreConfigSkeleton::ItemSize::ItemSize( const QString &_group, const QString &_key,
+ QSize &reference,
+ const QSize &defaultValue )
+ : KConfigSkeletonGenericItem<QSize>( _group, _key, reference, defaultValue )
+{
+}
+
+void KCoreConfigSkeleton::ItemSize::readConfig( KConfig *config )
+{
+ KConfigGroup cg(config, mGroup );
+ mReference = cg.readEntry( mKey, mDefault );
+ mLoadedValue = mReference;
+
+ readImmutability( cg );
+}
+
+void KCoreConfigSkeleton::ItemSize::setProperty(const QVariant & p)
+{
+ mReference = p.toSize();
+}
+
+bool KCoreConfigSkeleton::ItemSize::isEqual(const QVariant &v) const
+{
+ return mReference == v.toSize();
+}
+
+QVariant KCoreConfigSkeleton::ItemSize::property() const
+{
+ return QVariant(mReference);
+}
+
+
+KCoreConfigSkeleton::ItemDateTime::ItemDateTime( const QString &_group, const QString &_key,
+ QDateTime &reference,
+ const QDateTime &defaultValue )
+ : KConfigSkeletonGenericItem<QDateTime>( _group, _key, reference, defaultValue )
+{
+}
+
+void KCoreConfigSkeleton::ItemDateTime::readConfig( KConfig *config )
+{
+ KConfigGroup cg(config, mGroup );
+ mReference = cg.readEntry( mKey, mDefault );
+ mLoadedValue = mReference;
+
+ readImmutability( cg );
+}
+
+void KCoreConfigSkeleton::ItemDateTime::setProperty(const QVariant & p)
+{
+ mReference = p.toDateTime();
+}
+
+bool KCoreConfigSkeleton::ItemDateTime::isEqual(const QVariant &v) const
+{
+ return mReference == v.toDateTime();
+}
+
+QVariant KCoreConfigSkeleton::ItemDateTime::property() const
+{
+ return QVariant(mReference);
+}
+
+
+KCoreConfigSkeleton::ItemStringList::ItemStringList( const QString &_group, const QString &_key,
+ QStringList &reference,
+ const QStringList &defaultValue )
+ : KConfigSkeletonGenericItem<QStringList>( _group, _key, reference, defaultValue )
+{
+}
+
+void KCoreConfigSkeleton::ItemStringList::readConfig( KConfig *config )
+{
+ KConfigGroup cg(config, mGroup );
+ if ( !cg.hasKey( mKey ) )
+ mReference = mDefault;
+ else
+ mReference = cg.readEntry( mKey, mDefault );
+ mLoadedValue = mReference;
+
+ readImmutability( cg );
+}
+
+void KCoreConfigSkeleton::ItemStringList::setProperty(const QVariant & p)
+{
+ mReference = p.toStringList();
+}
+
+bool KCoreConfigSkeleton::ItemStringList::isEqual(const QVariant &v) const
+{
+ return mReference == v.toStringList();
+}
+
+QVariant KCoreConfigSkeleton::ItemStringList::property() const
+{
+ return QVariant(mReference);
+}
+
+
+KCoreConfigSkeleton::ItemPathList::ItemPathList( const QString &_group, const QString &_key,
+ QStringList &reference,
+ const QStringList &defaultValue )
+ : ItemStringList( _group, _key, reference, defaultValue )
+{
+}
+
+void KCoreConfigSkeleton::ItemPathList::readConfig( KConfig *config )
+{
+ KConfigGroup cg(config, mGroup );
+ if ( !cg.hasKey( mKey ) )
+ mReference = mDefault;
+ else
+ mReference = cg.readPathEntry( mKey, QStringList() );
+ mLoadedValue = mReference;
+
+ readImmutability( cg );
+}
+
+void KCoreConfigSkeleton::ItemPathList::writeConfig( KConfig *config )
+{
+ if ( mReference != mLoadedValue ) // WABA: Is this test needed?
+ {
+ KConfigGroup cg(config, mGroup );
+ if ((mDefault == mReference) && !cg.hasDefault( mKey))
+ cg.revertToDefault( mKey );
+ else {
+ QStringList sl = mReference;
+ cg.writePathEntry( mKey, sl );
+ }
+ }
+}
+
+KCoreConfigSkeleton::ItemUrlList::ItemUrlList( const QString &_group, const QString &_key,
+ QList<QUrl> &reference,
+ const QList<QUrl> &defaultValue )
+ : KConfigSkeletonGenericItem<QList<QUrl> >( _group, _key, reference, defaultValue )
+{
+}
+
+void KCoreConfigSkeleton::ItemUrlList::readConfig( KConfig *config )
+{
+ KConfigGroup cg(config, mGroup );
+ if ( !cg.hasKey( mKey ) )
+ mReference = mDefault;
+ else {
+ QStringList strList;
+ Q_FOREACH (const QUrl& url, mDefault) {
+ strList.append(url.toString());
+ }
+ mReference.clear();
+ const QStringList readList = cg.readEntry<QStringList>(mKey, strList);
+ Q_FOREACH (const QString& str, readList) {
+ mReference.append(QUrl(str));
+ }
+ }
+ mLoadedValue = mReference;
+
+ readImmutability( cg );
+}
+
+void KCoreConfigSkeleton::ItemUrlList::writeConfig( KConfig *config )
+{
+ if ( mReference != mLoadedValue ) // WABA: Is this test needed?
+ {
+ KConfigGroup cg(config, mGroup );
+ if ((mDefault == mReference) && !cg.hasDefault( mKey))
+ cg.revertToDefault( mKey );
+ else {
+ QStringList strList;
+ Q_FOREACH (const QUrl& url, mReference) {
+ strList.append(url.toString());
+ }
+ cg.writeEntry<QStringList>(mKey, strList);
+ }
+ }
+}
+
+void KCoreConfigSkeleton::ItemUrlList::setProperty(const QVariant & p)
+{
+ mReference = qvariant_cast<QList<QUrl> >(p);
+}
+
+bool KCoreConfigSkeleton::ItemUrlList::isEqual(const QVariant &v) const
+{
+ return mReference == qvariant_cast<QList<QUrl> >(v);
+}
+
+QVariant KCoreConfigSkeleton::ItemUrlList::property() const
+{
+ return qVariantFromValue<QList<QUrl> >(mReference);
+}
+
+
+KCoreConfigSkeleton::ItemIntList::ItemIntList( const QString &_group, const QString &_key,
+ QList<int> &reference,
+ const QList<int> &defaultValue )
+ : KConfigSkeletonGenericItem<QList<int> >( _group, _key, reference, defaultValue )
+{
+}
+
+void KCoreConfigSkeleton::ItemIntList::readConfig( KConfig *config )
+{
+ KConfigGroup cg(config, mGroup );
+ if ( !cg.hasKey( mKey ) )
+ mReference = mDefault;
+ else
+ mReference = cg.readEntry( mKey , mDefault );
+ mLoadedValue = mReference;
+
+ readImmutability( cg );
+}
+
+void KCoreConfigSkeleton::ItemIntList::setProperty(const QVariant &p)
+{
+ mReference = qvariant_cast< QList<int> >(p);
+}
+
+bool KCoreConfigSkeleton::ItemIntList::isEqual(const QVariant &v) const
+{
+ return mReference == qvariant_cast< QList<int> >(v);
+}
+
+QVariant KCoreConfigSkeleton::ItemIntList::property() const
+{
+ return qVariantFromValue< QList<int> >(mReference);
+}
+
+//static int kCoreConfigSkeletionDebugArea() { static int s_area = KDebug::registerArea("kdecore (KConfigSkeleton)"); return s_area; }
+
+KCoreConfigSkeleton::KCoreConfigSkeleton(const QString &configname, QObject* parent)
+ : QObject(parent),
+ d( new Private )
+{
+ //qDebug() << "Creating KCoreConfigSkeleton (" << (void *)this << ")";
+
+ d->mConfig = KSharedConfig::openConfig( configname );
+}
+
+KCoreConfigSkeleton::KCoreConfigSkeleton(KSharedConfig::Ptr pConfig, QObject* parent)
+ : QObject(parent),
+ d( new Private )
+{
+ //qDebug() << "Creating KCoreConfigSkeleton (" << (void *)this << ")";
+ d->mConfig = pConfig;
+}
+
+
+KCoreConfigSkeleton::~KCoreConfigSkeleton()
+{
+ delete d;
+}
+
+void KCoreConfigSkeleton::setCurrentGroup( const QString &group )
+{
+ d->mCurrentGroup = group;
+}
+
+QString KCoreConfigSkeleton::currentGroup() const
+{
+ return d->mCurrentGroup;
+}
+
+KConfig *KCoreConfigSkeleton::config()
+{
+ return d->mConfig.data();
+}
+
+const KConfig *KCoreConfigSkeleton::config() const
+{
+ return d->mConfig.data();
+}
+
+void KCoreConfigSkeleton::setSharedConfig(KSharedConfig::Ptr pConfig)
+{
+ d->mConfig = pConfig;
+}
+
+KConfigSkeletonItem::List KCoreConfigSkeleton::items() const
+{
+ return d->mItems;
+}
+
+bool KCoreConfigSkeleton::useDefaults(bool b)
+{
+ if (b == d->mUseDefaults)
+ return d->mUseDefaults;
+
+ d->mUseDefaults = b;
+ KConfigSkeletonItem::List::ConstIterator it;
+ for( it = d->mItems.constBegin(); it != d->mItems.constEnd(); ++it )
+ {
+ (*it)->swapDefault();
+ }
+ usrUseDefaults(b);
+ return !d->mUseDefaults;
+}
+
+void KCoreConfigSkeleton::setDefaults()
+{
+ KConfigSkeletonItem::List::ConstIterator it;
+ for( it = d->mItems.constBegin(); it != d->mItems.constEnd(); ++it ) {
+ (*it)->setDefault();
+ }
+ usrSetDefaults();
+}
+
+void KCoreConfigSkeleton::readConfig()
+{
+ // qDebug();
+ d->mConfig->reparseConfiguration();
+ KConfigSkeletonItem::List::ConstIterator it;
+ for( it = d->mItems.constBegin(); it != d->mItems.constEnd(); ++it )
+ {
+ (*it)->readConfig( d->mConfig.data() );
+ }
+ usrReadConfig();
+}
+
+bool KCoreConfigSkeleton::writeConfig()
+{
+ //qDebug();
+ KConfigSkeletonItem::List::ConstIterator it;
+ for( it = d->mItems.constBegin(); it != d->mItems.constEnd(); ++it )
+ {
+ (*it)->writeConfig( d->mConfig.data() );
+ }
+ if (!usrWriteConfig())
+ return false;
+
+ if (d->mConfig->isDirty()) {
+ if (!d->mConfig->sync())
+ return false;
+ readConfig();
+ emit configChanged();
+ }
+ return true;
+}
+
+bool KCoreConfigSkeleton::usrUseDefaults(bool)
+{
+ return false;
+}
+
+void KCoreConfigSkeleton::usrSetDefaults()
+{
+}
+
+void KCoreConfigSkeleton::usrReadConfig()
+{
+}
+
+bool KCoreConfigSkeleton::usrWriteConfig()
+{
+ return true;
+}
+
+void KCoreConfigSkeleton::addItem( KConfigSkeletonItem *item, const QString &name )
+{
+ if (d->mItems.contains(item)) {
+ if (item->name() == name ||
+ (name.isEmpty() && item->name() == item->key())) {
+ // nothing to do -> it is already in our collection
+ // and the name isn't changing
+ return;
+ }
+
+ d->mItemDict.remove(item->name());
+ } else {
+ d->mItems.append( item );
+ }
+
+ item->setName(name.isEmpty() ? item->key() : name);
+ d->mItemDict.insert(item->name(), item);
+ item->readDefault(d->mConfig.data());
+ item->readConfig(d->mConfig.data());
+}
+
+void KCoreConfigSkeleton::removeItem(const QString &name)
+{
+ KConfigSkeletonItem *item = d->mItemDict.value(name);
+ if (item) {
+ d->mItems.removeAll(item);
+ d->mItemDict.remove(item->name());
+ delete item;
+ }
+}
+
+void KCoreConfigSkeleton::clearItems()
+{
+ KConfigSkeletonItem::List items = d->mItems;
+ d->mItems.clear();
+ d->mItemDict.clear();
+ qDeleteAll(items);
+}
+
+KCoreConfigSkeleton::ItemString *KCoreConfigSkeleton::addItemString( const QString &name, QString &reference,
+ const QString &defaultValue, const QString &key )
+{
+ KCoreConfigSkeleton::ItemString *item;
+ item = new KCoreConfigSkeleton::ItemString( d->mCurrentGroup, key.isEmpty() ? name : key,
+ reference, defaultValue,
+ KCoreConfigSkeleton::ItemString::Normal );
+ addItem( item, name );
+ return item;
+}
+
+KCoreConfigSkeleton::ItemPassword *KCoreConfigSkeleton::addItemPassword( const QString &name, QString &reference,
+ const QString &defaultValue, const QString &key )
+{
+ KCoreConfigSkeleton::ItemPassword *item;
+ item = new KCoreConfigSkeleton::ItemPassword( d->mCurrentGroup, key.isNull() ? name : key,
+ reference, defaultValue );
+ addItem( item, name );
+ return item;
+}
+
+KCoreConfigSkeleton::ItemPath *KCoreConfigSkeleton::addItemPath( const QString &name, QString &reference,
+ const QString &defaultValue, const QString &key )
+{
+ KCoreConfigSkeleton::ItemPath *item;
+ item = new KCoreConfigSkeleton::ItemPath( d->mCurrentGroup, key.isNull() ? name : key,
+ reference, defaultValue );
+ addItem( item, name );
+ return item;
+}
+
+KCoreConfigSkeleton::ItemProperty *KCoreConfigSkeleton::addItemProperty( const QString &name, QVariant &reference,
+ const QVariant &defaultValue, const QString &key )
+{
+ KCoreConfigSkeleton::ItemProperty *item;
+ item = new KCoreConfigSkeleton::ItemProperty( d->mCurrentGroup, key.isNull() ? name : key,
+ reference, defaultValue );
+ addItem( item, name );
+ return item;
+}
+
+KCoreConfigSkeleton::ItemBool *KCoreConfigSkeleton::addItemBool( const QString &name, bool &reference,
+ bool defaultValue, const QString &key )
+{
+ KCoreConfigSkeleton::ItemBool *item;
+ item = new KCoreConfigSkeleton::ItemBool( d->mCurrentGroup, key.isNull() ? name : key,
+ reference, defaultValue );
+ addItem( item, name );
+ return item;
+}
+
+KCoreConfigSkeleton::ItemInt *KCoreConfigSkeleton::addItemInt( const QString &name, qint32 &reference,
+ qint32 defaultValue, const QString &key )
+{
+ KCoreConfigSkeleton::ItemInt *item;
+ item = new KCoreConfigSkeleton::ItemInt( d->mCurrentGroup, key.isNull() ? name : key,
+ reference, defaultValue );
+ addItem( item, name );
+ return item;
+}
+
+KCoreConfigSkeleton::ItemUInt *KCoreConfigSkeleton::addItemUInt( const QString &name, quint32 &reference,
+ quint32 defaultValue, const QString &key )
+{
+ KCoreConfigSkeleton::ItemUInt *item;
+ item = new KCoreConfigSkeleton::ItemUInt( d->mCurrentGroup, key.isNull() ? name : key,
+ reference, defaultValue );
+ addItem( item, name );
+ return item;
+}
+
+KCoreConfigSkeleton::ItemLongLong *KCoreConfigSkeleton::addItemLongLong( const QString &name, qint64 &reference,
+ qint64 defaultValue, const QString &key )
+{
+ KCoreConfigSkeleton::ItemLongLong *item;
+ item = new KCoreConfigSkeleton::ItemLongLong( d->mCurrentGroup, key.isNull() ? name : key,
+ reference, defaultValue );
+ addItem( item, name );
+ return item;
+}
+
+#ifndef KDE_NO_DEPRECATED
+KCoreConfigSkeleton::ItemLongLong *KCoreConfigSkeleton::addItemInt64(
+ const QString& name,
+ qint64 &reference,
+ qint64 defaultValue,
+ const QString & key)
+{
+ return addItemLongLong(name, reference, defaultValue, key);
+}
+#endif
+
+KCoreConfigSkeleton::ItemULongLong *KCoreConfigSkeleton::addItemULongLong( const QString &name, quint64 &reference,
+ quint64 defaultValue, const QString &key )
+{
+ KCoreConfigSkeleton::ItemULongLong *item;
+ item = new KCoreConfigSkeleton::ItemULongLong( d->mCurrentGroup, key.isNull() ? name : key,
+ reference, defaultValue );
+ addItem( item, name );
+ return item;
+}
+
+#ifndef KDE_NO_DEPRECATED
+KCoreConfigSkeleton::ItemULongLong *KCoreConfigSkeleton::addItemUInt64(
+ const QString & name,
+ quint64 &reference,
+ quint64 defaultValue,
+ const QString & key)
+{
+ return addItemULongLong(name, reference, defaultValue, key);
+}
+#endif
+
+KCoreConfigSkeleton::ItemDouble *KCoreConfigSkeleton::addItemDouble( const QString &name, double &reference,
+ double defaultValue, const QString &key )
+{
+ KCoreConfigSkeleton::ItemDouble *item;
+ item = new KCoreConfigSkeleton::ItemDouble( d->mCurrentGroup, key.isNull() ? name : key,
+ reference, defaultValue );
+ addItem( item, name );
+ return item;
+}
+
+KCoreConfigSkeleton::ItemRect *KCoreConfigSkeleton::addItemRect( const QString &name, QRect &reference,
+ const QRect &defaultValue, const QString &key )
+{
+ KCoreConfigSkeleton::ItemRect *item;
+ item = new KCoreConfigSkeleton::ItemRect( d->mCurrentGroup, key.isNull() ? name : key,
+ reference, defaultValue );
+ addItem( item, name );
+ return item;
+}
+
+KCoreConfigSkeleton::ItemPoint *KCoreConfigSkeleton::addItemPoint( const QString &name, QPoint &reference,
+ const QPoint &defaultValue, const QString &key )
+{
+ KCoreConfigSkeleton::ItemPoint *item;
+ item = new KCoreConfigSkeleton::ItemPoint( d->mCurrentGroup, key.isNull() ? name : key,
+ reference, defaultValue );
+ addItem( item, name );
+ return item;
+}
+
+KCoreConfigSkeleton::ItemSize *KCoreConfigSkeleton::addItemSize( const QString &name, QSize &reference,
+ const QSize &defaultValue, const QString &key )
+{
+ KCoreConfigSkeleton::ItemSize *item;
+ item = new KCoreConfigSkeleton::ItemSize( d->mCurrentGroup, key.isNull() ? name : key,
+ reference, defaultValue );
+ addItem( item, name );
+ return item;
+}
+
+KCoreConfigSkeleton::ItemDateTime *KCoreConfigSkeleton::addItemDateTime( const QString &name, QDateTime &reference,
+ const QDateTime &defaultValue, const QString &key )
+{
+ KCoreConfigSkeleton::ItemDateTime *item;
+ item = new KCoreConfigSkeleton::ItemDateTime( d->mCurrentGroup, key.isNull() ? name : key,
+ reference, defaultValue );
+ addItem( item, name );
+ return item;
+}
+
+KCoreConfigSkeleton::ItemStringList *KCoreConfigSkeleton::addItemStringList( const QString &name, QStringList &reference,
+ const QStringList &defaultValue, const QString &key )
+{
+ KCoreConfigSkeleton::ItemStringList *item;
+ item = new KCoreConfigSkeleton::ItemStringList( d->mCurrentGroup, key.isNull() ? name : key,
+ reference, defaultValue );
+ addItem( item, name );
+ return item;
+}
+
+KCoreConfigSkeleton::ItemIntList *KCoreConfigSkeleton::addItemIntList( const QString &name, QList<int> &reference,
+ const QList<int> &defaultValue, const QString &key )
+{
+ KCoreConfigSkeleton::ItemIntList *item;
+ item = new KCoreConfigSkeleton::ItemIntList( d->mCurrentGroup, key.isNull() ? name : key,
+ reference, defaultValue );
+ addItem( item, name );
+ return item;
+}
+
+bool KCoreConfigSkeleton::isImmutable(const QString &name) const
+{
+ KConfigSkeletonItem *item = findItem(name);
+ return !item || item->isImmutable();
+}
+
+KConfigSkeletonItem *KCoreConfigSkeleton::findItem(const QString &name) const
+{
+ return d->mItemDict.value(name);
+}
+
diff --git a/tier1/kconfig/src/core/kcoreconfigskeleton.h b/tier1/kconfig/src/core/kcoreconfigskeleton.h
new file mode 100644
index 00000000..75f6fa28
--- /dev/null
+++ b/tier1/kconfig/src/core/kcoreconfigskeleton.h
@@ -0,0 +1,1407 @@
+/*
+ * This file is part of KDE.
+ *
+ * Copyright (c) 2001,2002,2003 Cornelius Schumacher <schumacher@kde.org>
+ * Copyright (c) 2003 Waldo Bastian <bastian@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef KCORECONFIGSKELETON_H
+#define KCORECONFIGSKELETON_H
+
+#include <kconfigcore_export.h>
+
+#include <ksharedconfig.h>
+#include <kconfiggroup.h>
+
+#include <QtCore/QDate>
+#include <QtCore/QHash>
+#include <QtCore/QRect>
+#include <QtCore/QStringList>
+#include <QtCore/QVariant>
+#include <QtCore/QUrl>
+
+ class KConfigSkeletonItemPrivate;
+ /**
+ * \class KConfigSkeletonItem kcoreconfigskeleton.h <KConfigSkeletonItem>
+ *
+ * @short Class for storing a preferences setting
+ * @author Cornelius Schumacher
+ * @see KCoreConfigSkeleton
+ *
+ * This class represents one preferences setting as used by @ref KCoreConfigSkeleton.
+ * Subclasses of KConfigSkeletonItem implement storage functions for a certain type of
+ * setting. Normally you don't have to use this class directly. Use the special
+ * addItem() functions of KCoreConfigSkeleton instead. If you subclass this class you will
+ * have to register instances with the function KCoreConfigSkeleton::addItem().
+ */
+ class KCONFIGCORE_EXPORT KConfigSkeletonItem
+ {
+ public:
+ typedef QList < KConfigSkeletonItem * >List;
+ typedef QHash < QString, KConfigSkeletonItem* > Dict;
+ typedef QHash < QString, KConfigSkeletonItem* >::Iterator DictIterator;
+
+ /**
+ * Constructor.
+ *
+ * @param _group Config file group.
+ * @param _key Config file key.
+ */
+ KConfigSkeletonItem(const QString & _group, const QString & _key);
+
+ /**
+ * Destructor.
+ */
+ virtual ~KConfigSkeletonItem();
+
+ /**
+ * Set config file group.
+ */
+ void setGroup( const QString &_group );
+
+ /**
+ * Return config file group.
+ */
+ QString group() const;
+
+ /**
+ * Set config file key.
+ */
+ void setKey( const QString &_key );
+
+ /**
+ * Return config file key.
+ */
+ QString key() const;
+
+ /**
+ * Set internal name of entry.
+ */
+ void setName(const QString &_name);
+
+ /**
+ * Return internal name of entry.
+ */
+ QString name() const;
+
+ /**
+ Set label providing a translated one-line description of the item.
+ */
+ void setLabel( const QString &l );
+
+ /**
+ Return label of item. See setLabel().
+ */
+ QString label() const;
+
+ /**
+ Set ToolTip description of item.
+ @since 4.2
+ */
+ void setToolTip( const QString &t );
+
+ /**
+ Return ToolTip description of item. See setToolTip().
+ @since 4.2
+ */
+ QString toolTip() const;
+
+ /**
+ Set WhatsThis description of item.
+ */
+ void setWhatsThis( const QString &w );
+
+ /**
+ Return WhatsThis description of item. See setWhatsThis().
+ */
+ QString whatsThis() const;
+
+ /**
+ * This function is called by @ref KCoreConfigSkeleton to read the value for this setting
+ * from a config file.
+ */
+ virtual void readConfig(KConfig *) = 0;
+
+ /**
+ * This function is called by @ref KCoreConfigSkeleton to write the value of this setting
+ * to a config file.
+ */
+ virtual void writeConfig(KConfig *) = 0;
+
+ /**
+ * Read global default value.
+ */
+ virtual void readDefault(KConfig *) = 0;
+
+ /**
+ * Set item to @p p
+ */
+ virtual void setProperty(const QVariant &p) = 0;
+
+ /**
+ * Check whether the item is equal to p.
+ *
+ * Use this function to compare items that use custom types,
+ * because QVariant::operator== will not work for those.
+ *
+ * @param p QVariant to compare to
+ * @return true if the item is equal to p, false otherwise
+ */
+ virtual bool isEqual(const QVariant &p) const = 0;
+
+ /**
+ * Return item as property
+ */
+ virtual QVariant property() const = 0;
+
+ /**
+ * Return minimum value of item or invalid if not specified
+ */
+ virtual QVariant minValue() const;
+
+ /**
+ * Return maximum value of item or invalid if not specified
+ */
+ virtual QVariant maxValue() const;
+
+ /**
+ * Sets the current value to the default value.
+ */
+ virtual void setDefault() = 0;
+
+ /**
+ * Exchanges the current value with the default value
+ * Used by KCoreConfigSkeleton::useDefaults(bool);
+ */
+ virtual void swapDefault() = 0;
+
+ /**
+ * Return if the entry can be modified.
+ */
+ bool isImmutable() const;
+
+ protected:
+ /**
+ * sets mIsImmutable to true if mKey in config is immutable
+ * @param group KConfigGroup to check if mKey is immutable in
+ */
+ void readImmutability(const KConfigGroup &group);
+
+ QString mGroup; ///< The group name for this item
+ QString mKey; ///< The config key for this item
+ QString mName; ///< The name of this item
+
+ private:
+ KConfigSkeletonItemPrivate * const d;
+ };
+
+
+/**
+ * \class KConfigSkeletonGenericItem kcoreconfigskeleton.h <KConfigSkeletonGenericItem>
+ */
+template < typename T > class KConfigSkeletonGenericItem:public KConfigSkeletonItem
+ {
+ public:
+ /** @copydoc KConfigSkeletonItem(const QString&, const QString&)
+ @param reference The initial value to hold in the item
+ @param defaultValue The default value for the item
+ */
+ KConfigSkeletonGenericItem(const QString & _group, const QString & _key, T & reference,
+ T defaultValue)
+ : KConfigSkeletonItem(_group, _key), mReference(reference),
+ mDefault(defaultValue), mLoadedValue(defaultValue)
+ {
+ }
+
+ /**
+ * Set value of this KConfigSkeletonItem.
+ */
+ void setValue(const T & v)
+ {
+ mReference = v;
+ }
+
+ /**
+ * Return value of this KConfigSkeletonItem.
+ */
+ T & value()
+ {
+ return mReference;
+ }
+
+ /**
+ * Return const value of this KConfigSkeletonItem.
+ */
+ const T & value() const
+ {
+ return mReference;
+ }
+
+ /**
+ Set default value for this item.
+ */
+ virtual void setDefaultValue( const T &v )
+ {
+ mDefault = v;
+ }
+
+ /**
+ Set the value for this item to the default value
+ */
+ virtual void setDefault()
+ {
+ mReference = mDefault;
+ }
+
+ /** @copydoc KConfigSkeletonItem::writeConfig(KConfig *) */
+ virtual void writeConfig(KConfig * config)
+ {
+ if ( mReference != mLoadedValue ) // Is this needed?
+ {
+ KConfigGroup cg(config, mGroup);
+ if ((mDefault == mReference) && !cg.hasDefault( mKey))
+ cg.revertToDefault( mKey );
+ else
+ cg.writeEntry(mKey, mReference);
+ }
+ }
+
+ /** @copydoc KConfigSkeletonItem::readDefault(KConfig*) */
+ void readDefault(KConfig * config)
+ {
+ config->setReadDefaults(true);
+ readConfig(config);
+ config->setReadDefaults(false);
+ mDefault = mReference;
+ }
+
+ /** @copydoc KConfigSkeletonItem::swapDefault() */
+ void swapDefault()
+ {
+ T tmp = mReference;
+ mReference = mDefault;
+ mDefault = tmp;
+ }
+
+ protected:
+ T & mReference; ///< Stores the value for this item
+ T mDefault; ///< The default value for this item
+ T mLoadedValue;
+ };
+
+ /**
+ * \class KCoreConfigSkeleton kcoreconfigskeleton.h <KCoreConfigSkeleton>
+ *
+ * @short Class for handling preferences settings for an application.
+ * @author Cornelius Schumacher
+ * @see KConfigSkeletonItem
+ *
+ * This class provides an interface to preferences settings. Preferences items
+ * can be registered by the addItem() function corresponding to the data type of
+ * the setting. KCoreConfigSkeleton then handles reading and writing of config files and
+ * setting of default values.
+ *
+ * Normally you will subclass KCoreConfigSkeleton, add data members for the preferences
+ * settings and register the members in the constructor of the subclass.
+ *
+ * Example:
+ * \code
+ * class MyPrefs : public KCoreConfigSkeleton
+ * {
+ * public:
+ * MyPrefs()
+ * {
+ * setCurrentGroup("MyGroup");
+ * addItemBool("MySetting1", mMyBool, false);
+ * addItemPoint("MySetting2", mMyPoint, QPoint(100, 200));
+ *
+ * setCurrentGroup("MyOtherGroup");
+ * addItemDouble("MySetting3", mMyDouble, 3.14);
+ * }
+ *
+ * bool mMyBool;
+ * QPoint mMyPoint;
+ * double mMyDouble;
+ * }
+ * \endcode
+ *
+ * It might be convenient in many cases to make this subclass of KCoreConfigSkeleton a
+ * singleton for global access from all over the application without passing
+ * references to the KCoreConfigSkeleton object around.
+ *
+ * You can write the data to the configuration file by calling @ref writeConfig()
+ * and read the data from the configuration file by calling @ref readConfig().
+ * If you want to watch for config changes, use @ref configChanged() signal.
+ *
+ * If you have items, which are not covered by the existing addItem() functions
+ * you can add customized code for reading, writing and default setting by
+ * implementing the functions @ref usrUseDefaults(), @ref usrReadConfig() and
+ * @ref usrWriteConfig().
+ *
+ * Internally preferences settings are stored in instances of subclasses of
+ * @ref KConfigSkeletonItem. You can also add KConfigSkeletonItem subclasses
+ * for your own types and call the generic @ref addItem() to register them.
+ *
+ * In many cases you don't have to write the specific KCoreConfigSkeleton
+ * subclasses yourself, but you can use \ref kconfig_compiler to automatically
+ * generate the C++ code from an XML description of the configuration options.
+ *
+ * Use KConfigSkeleton if you need GUI types as well.
+ */
+class KCONFIGCORE_EXPORT KCoreConfigSkeleton : public QObject
+{
+ Q_OBJECT
+public:
+ /**
+ * Class for handling a string preferences item.
+ */
+ class KCONFIGCORE_EXPORT ItemString:public KConfigSkeletonGenericItem < QString >
+ {
+ public:
+ enum Type { Normal, Password, Path };
+
+ /** @enum Type
+ The type of string that is held in this item
+
+ @var ItemString::Type ItemString::Normal
+ A normal string
+
+ @var ItemString::Type ItemString::Password
+ A password string
+
+ @var ItemString::Type ItemString::Path
+ A path to a file or directory
+ */
+
+
+ /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem
+ @param type The type of string held by the item
+ */
+ ItemString(const QString & _group, const QString & _key,
+ QString & reference,
+ const QString & defaultValue = QLatin1String(""), // NOT QString() !!
+ Type type = Normal);
+
+ /** @copydoc KConfigSkeletonItem::writeConfig(KConfig*) */
+ void writeConfig(KConfig * config);
+
+ /** @copydoc KConfigSkeletonItem::readConfig(KConfig*) */
+ void readConfig(KConfig * config);
+
+ /** @copydoc KConfigSkeletonItem::setProperty(const QVariant&) */
+ void setProperty(const QVariant & p);
+
+ /** @copydoc KConfigSkeletonItem::isEqual(const QVariant &) const */
+ bool isEqual(const QVariant &p) const;
+
+ /** @copydoc KConfigSkeletonItem::property() const */
+ QVariant property() const;
+
+ private:
+ Type mType;
+ };
+
+ /**
+ * Class for handling a password preferences item.
+ */
+ class KCONFIGCORE_EXPORT ItemPassword:public ItemString
+ {
+ public:
+ /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem */
+ ItemPassword(const QString & _group, const QString & _key,
+ QString & reference,
+ const QString & defaultValue = QLatin1String("")); // NOT QString() !!
+ };
+
+ /**
+ * Class for handling a path preferences item.
+ */
+ class KCONFIGCORE_EXPORT ItemPath:public ItemString
+ {
+ public:
+ /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem */
+ ItemPath(const QString & _group, const QString & _key,
+ QString & reference,
+ const QString & defaultValue = QString());
+ };
+
+ /**
+ * Class for handling a url preferences item.
+ */
+ class KCONFIGCORE_EXPORT ItemUrl:public KConfigSkeletonGenericItem < QUrl >
+ {
+ public:
+
+ /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem
+ */
+ ItemUrl(const QString & _group, const QString & _key,
+ QUrl & reference,
+ const QUrl & defaultValue = QUrl());
+
+ /** @copydoc KConfigSkeletonItem::writeConfig(KConfig*) */
+ void writeConfig(KConfig * config);
+
+ /** @copydoc KConfigSkeletonItem::readConfig(KConfig*) */
+ void readConfig(KConfig * config);
+
+ /** @copydoc KConfigSkeletonItem::setProperty(const QVariant&) */
+ void setProperty(const QVariant & p);
+
+ /** @copydoc KConfigSkeletonItem::isEqual(const QVariant &) const */
+ bool isEqual(const QVariant &p) const;
+
+ /** @copydoc KConfigSkeletonItem::property() const */
+ QVariant property() const;
+ };
+
+ /**
+ * Class for handling a QVariant preferences item.
+ */
+ class KCONFIGCORE_EXPORT ItemProperty:public KConfigSkeletonGenericItem < QVariant >
+ {
+ public:
+ /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem */
+ ItemProperty(const QString & _group, const QString & _key,
+ QVariant & reference, const QVariant & defaultValue = 0);
+
+ void readConfig(KConfig * config);
+ void setProperty(const QVariant & p);
+
+ /** @copydoc KConfigSkeletonItem::isEqual(const QVariant &) const */
+ bool isEqual(const QVariant &p) const;
+
+ /** @copydoc KConfigSkeletonItem::property() const */
+ QVariant property() const;
+ };
+
+
+ /**
+ * Class for handling a bool preferences item.
+ */
+ class KCONFIGCORE_EXPORT ItemBool:public KConfigSkeletonGenericItem < bool >
+ {
+ public:
+ /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem */
+ ItemBool(const QString & _group, const QString & _key, bool & reference,
+ bool defaultValue = true);
+
+ /** @copydoc KConfigSkeletonItem::readConfig(KConfig*) */
+ void readConfig(KConfig * config);
+
+ /** @copydoc KConfigSkeletonItem::setProperty(const QVariant&) */
+ void setProperty(const QVariant & p);
+
+ /** @copydoc KConfigSkeletonItem::isEqual(const QVariant &) const */
+ bool isEqual(const QVariant &p) const;
+
+ /** @copydoc KConfigSkeletonItem::property() const */
+ QVariant property() const;
+ };
+
+
+ /**
+ * Class for handling a 32-bit integer preferences item.
+ */
+ class KCONFIGCORE_EXPORT ItemInt:public KConfigSkeletonGenericItem < qint32 >
+ {
+ public:
+ /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem */
+ ItemInt(const QString & _group, const QString & _key, qint32 &reference,
+ qint32 defaultValue = 0);
+
+ /** @copydoc KConfigSkeletonItem::readConfig(KConfig*) */
+ void readConfig(KConfig * config);
+
+ /** @copydoc KConfigSkeletonItem::setProperty(const QVariant&) */
+ void setProperty(const QVariant & p);
+
+ /** @copydoc KConfigSkeletonItem::isEqual(const QVariant &) const */
+ bool isEqual(const QVariant &p) const;
+
+ /** @copydoc KConfigSkeletonItem::property() */
+ QVariant property() const;
+
+ /** Get the minimum value that is allowed to be stored in this item */
+ QVariant minValue() const;
+
+ /** Get the maximum value this is allowed to be stored in this item */
+ QVariant maxValue() const;
+
+ /** Set the minimum value for the item
+ @sa minValue()
+ */
+ void setMinValue(qint32);
+
+ /** Set the maximum value for the item
+ @sa maxValue
+ */
+ void setMaxValue(qint32);
+
+ private:
+ bool mHasMin : 1;
+ bool mHasMax : 1;
+ qint32 mMin;
+ qint32 mMax;
+ };
+
+ /**
+ * Class for handling a 64-bit integer preferences item.
+ */
+ class KCONFIGCORE_EXPORT ItemLongLong:public KConfigSkeletonGenericItem < qint64 >
+ {
+ public:
+ /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem */
+ ItemLongLong(const QString & _group, const QString & _key, qint64 &reference,
+ qint64 defaultValue = 0);
+
+ /** @copydoc KConfigSkeletonItem::readConfig(KConfig*) */
+ void readConfig(KConfig * config);
+
+ /** @copydoc KConfigSkeletonItem::setProperty(const QVariant&) */
+ void setProperty(const QVariant & p);
+
+ /** @copydoc KConfigSkeletonItem::isEqual(const QVariant &) const */
+ bool isEqual(const QVariant &p) const;
+
+ /** @copydoc KConfigSkeletonItem::property() */
+ QVariant property() const;
+
+ /** @copydoc ItemInt::minValue() */
+ QVariant minValue() const;
+
+ /** @copydoc ItemInt::maxValue() */
+ QVariant maxValue() const;
+
+ /** @copydoc ItemInt::setMinValue(qint32) */
+ void setMinValue(qint64);
+
+ /** @copydoc ItemInt::setMaxValue(qint32) */
+ void setMaxValue(qint64);
+
+ private:
+ bool mHasMin : 1;
+ bool mHasMax : 1;
+ qint64 mMin;
+ qint64 mMax;
+ };
+#ifndef KDE_NO_DEPRECATED
+ typedef KCONFIGCORE_DEPRECATED ItemLongLong ItemInt64;
+#endif
+
+ /**
+ * Class for handling enums.
+ */
+ class KCONFIGCORE_EXPORT ItemEnum:public ItemInt
+ {
+ public:
+ struct Choice
+ {
+ QString name;
+ QString label;
+ QString toolTip;
+ QString whatsThis;
+ };
+
+ /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem
+ @param choices The list of enums that can be stored in this item
+ */
+ ItemEnum(const QString & _group, const QString & _key, qint32 &reference,
+ const QList<Choice> &choices, qint32 defaultValue = 0);
+
+ QList<Choice> choices() const;
+
+ /** @copydoc KConfigSkeletonItem::readConfig(KConfig*) */
+ void readConfig(KConfig * config);
+
+ /** @copydoc KConfigSkeletonItem::writeConfig(KConfig*) */
+ void writeConfig(KConfig * config);
+
+ // Source compatibility with 4.x
+ typedef Choice Choice2;
+ QList<Choice> choices2() const;
+
+ private:
+ QList<Choice> mChoices;
+ };
+
+
+ /**
+ * Class for handling an unsigned 32-bit integer preferences item.
+ */
+ class KCONFIGCORE_EXPORT ItemUInt:public KConfigSkeletonGenericItem < quint32 >
+ {
+ public:
+ /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem */
+ ItemUInt(const QString & _group, const QString & _key,
+ quint32 &reference, quint32 defaultValue = 0);
+
+ /** @copydoc KConfigSkeletonItem::readConfig(KConfig*) */
+ void readConfig(KConfig * config);
+
+ /** @copydoc KConfigSkeletonItem::setProperty(const QVariant&) */
+ void setProperty(const QVariant & p);
+
+ /** @copydoc KConfigSkeletonItem::isEqual(const QVariant &) const */
+ bool isEqual(const QVariant &p) const;
+
+ /** @copydoc KConfigSkeletonItem::property() */
+ QVariant property() const;
+
+ /** @copydoc ItemInt::minValue() */
+ QVariant minValue() const;
+
+ /** @copydoc ItemInt::maxValue() */
+ QVariant maxValue() const;
+
+ /** @copydoc ItemInt::setMinValue(qint32) */
+ void setMinValue(quint32);
+
+ /** @copydoc ItemInt::setMaxValue(qint32) */
+ void setMaxValue(quint32);
+
+ private:
+ bool mHasMin : 1;
+ bool mHasMax : 1;
+ quint32 mMin;
+ quint32 mMax;
+ };
+
+ /**
+ * Class for handling unsigned 64-bit integer preferences item.
+ */
+ class KCONFIGCORE_EXPORT ItemULongLong:public KConfigSkeletonGenericItem < quint64 >
+ {
+ public:
+ /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem */
+ ItemULongLong(const QString & _group, const QString & _key, quint64 &reference,
+ quint64 defaultValue = 0);
+
+ /** @copydoc KConfigSkeletonItem::readConfig(KConfig*) */
+ void readConfig(KConfig * config);
+
+ /** @copydoc KConfigSkeletonItem::setProperty(const QVariant&) */
+ void setProperty(const QVariant & p);
+
+ /** @copydoc KConfigSkeletonItem::isEqual(const QVariant &) const */
+ bool isEqual(const QVariant &p) const;
+
+ /** @copydoc KConfigSkeletonItem::property() */
+ QVariant property() const;
+
+ /** @copydoc ItemInt::minValue() */
+ QVariant minValue() const;
+
+ /** @copydoc ItemInt::maxValue() */
+ QVariant maxValue() const;
+
+ /** @copydoc ItemInt::setMinValue(qint32) */
+ void setMinValue(quint64);
+
+ /** @copydoc ItemInt::setMaxValue(qint32) */
+ void setMaxValue(quint64);
+
+ private:
+ bool mHasMin : 1;
+ bool mHasMax : 1;
+ quint64 mMin;
+ quint64 mMax;
+ };
+#ifndef KDE_NO_DEPRECATED
+ typedef KCONFIGCORE_DEPRECATED ItemULongLong ItemUInt64;
+#endif
+
+ /**
+ * Class for handling a floating point preference item.
+ */
+ class KCONFIGCORE_EXPORT ItemDouble:public KConfigSkeletonGenericItem < double >
+ {
+ public:
+ /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem */
+ ItemDouble(const QString & _group, const QString & _key,
+ double &reference, double defaultValue = 0);
+
+ /** @copydoc KConfigSkeletonItem::readConfig(KConfig*) */
+ void readConfig(KConfig * config);
+
+ /** @copydoc KConfigSkeletonItem::setProperty(const QVariant&) */
+ void setProperty(const QVariant & p);
+
+ /** @copydoc KConfigSkeletonItem::isEqual(const QVariant &) const */
+ bool isEqual(const QVariant &p) const;
+
+ /** @copydoc KConfigSkeletonItem::property() */
+ QVariant property() const;
+
+ /** @copydoc ItemInt::minValue() */
+ QVariant minValue() const;
+
+ /** @copydoc ItemInt::maxValue() */
+ QVariant maxValue() const;
+
+ /** @copydoc ItemInt::setMinValue() */
+ void setMinValue(double);
+
+ /** @copydoc ItemInt::setMaxValue() */
+ void setMaxValue(double);
+
+ private:
+ bool mHasMin : 1;
+ bool mHasMax : 1;
+ double mMin;
+ double mMax;
+ };
+
+
+ /**
+ * Class for handling a QRect preferences item.
+ */
+ class KCONFIGCORE_EXPORT ItemRect:public KConfigSkeletonGenericItem < QRect >
+ {
+ public:
+ /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem */
+ ItemRect(const QString & _group, const QString & _key, QRect & reference,
+ const QRect & defaultValue = QRect());
+
+ /** @copydoc KConfigSkeletonItem::readConfig(KConfig*) */
+ void readConfig(KConfig * config);
+
+ /** @copydoc KConfigSkeletonItem::setProperty(const QVariant&) */
+ void setProperty(const QVariant & p);
+
+ /** @copydoc KConfigSkeletonItem::isEqual(const QVariant &) const */
+ bool isEqual(const QVariant &p) const;
+
+ /** @copydoc KConfigSkeletonItem::property() */
+ QVariant property() const;
+ };
+
+
+ /**
+ * Class for handling a QPoint preferences item.
+ */
+ class KCONFIGCORE_EXPORT ItemPoint:public KConfigSkeletonGenericItem < QPoint >
+ {
+ public:
+ /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem */
+ ItemPoint(const QString & _group, const QString & _key, QPoint & reference,
+ const QPoint & defaultValue = QPoint());
+
+ /** @copydoc KConfigSkeletonItem::readConfig(KConfig*) */
+ void readConfig(KConfig * config);
+
+ /** @copydoc KConfigSkeletonItem::setProperty(const QVariant&) */
+ void setProperty(const QVariant & p);
+
+ /** @copydoc KConfigSkeletonItem::isEqual(const QVariant &) const */
+ bool isEqual(const QVariant &p) const;
+
+ /** @copydoc KConfigSkeletonItem::property() */
+ QVariant property() const;
+ };
+
+
+ /**
+ * Class for handling a QSize preferences item.
+ */
+ class KCONFIGCORE_EXPORT ItemSize:public KConfigSkeletonGenericItem < QSize >
+ {
+ public:
+ /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem */
+ ItemSize(const QString & _group, const QString & _key, QSize & reference,
+ const QSize & defaultValue = QSize());
+
+ /** @copydoc KConfigSkeletonItem::readConfig(KConfig*) */
+ void readConfig(KConfig * config);
+
+ /** @copydoc KConfigSkeletonItem::setProperty(const QVariant&) */
+ void setProperty(const QVariant & p);
+
+ /** @copydoc KConfigSkeletonItem::isEqual(const QVariant &) const */
+ bool isEqual(const QVariant &p) const;
+
+ /** @copydoc KConfigSkeletonItem::property() */
+ QVariant property() const;
+ };
+
+
+ /**
+ * Class for handling a QDateTime preferences item.
+ */
+ class KCONFIGCORE_EXPORT ItemDateTime:public KConfigSkeletonGenericItem < QDateTime >
+ {
+ public:
+ /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem */
+ ItemDateTime(const QString & _group, const QString & _key,
+ QDateTime & reference,
+ const QDateTime & defaultValue = QDateTime());
+
+ /** @copydoc KConfigSkeletonItem::readConfig(KConfig*) */
+ void readConfig(KConfig * config);
+
+ /** @copydoc KConfigSkeletonItem::setProperty(const QVariant&) */
+ void setProperty(const QVariant & p);
+
+ /** @copydoc KConfigSkeletonItem::isEqual(const QVariant &) const */
+ bool isEqual(const QVariant &p) const;
+
+ /** @copydoc KConfigSkeletonItem::property() */
+ QVariant property() const;
+ };
+
+
+ /**
+ * Class for handling a string list preferences item.
+ */
+ class KCONFIGCORE_EXPORT ItemStringList:public KConfigSkeletonGenericItem < QStringList >
+ {
+ public:
+ /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem */
+ ItemStringList(const QString & _group, const QString & _key,
+ QStringList & reference,
+ const QStringList & defaultValue = QStringList());
+
+ /** @copydoc KConfigSkeletonItem::readConfig(KConfig*) */
+ void readConfig(KConfig * config);
+
+ /** @copydoc KConfigSkeletonItem::setProperty(const QVariant&) */
+ void setProperty(const QVariant & p);
+
+ /** @copydoc KConfigSkeletonItem::isEqual(const QVariant &) const */
+ bool isEqual(const QVariant &p) const;
+
+ /** @copydoc KConfigSkeletonItem::property() */
+ QVariant property() const;
+ };
+
+
+ /**
+ * Class for handling a path list preferences item.
+ */
+ class KCONFIGCORE_EXPORT ItemPathList:public ItemStringList
+ {
+ public:
+ /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem */
+ ItemPathList(const QString & _group, const QString & _key,
+ QStringList & reference,
+ const QStringList & defaultValue = QStringList());
+
+ /** @copydoc KConfigSkeletonItem::readConfig */
+ void readConfig(KConfig * config);
+ /** @copydoc KConfigSkeletonItem::writeConfig */
+ void writeConfig(KConfig * config);
+ };
+
+ /**
+ * Class for handling a url list preferences item.
+ */
+ class KCONFIGCORE_EXPORT ItemUrlList:public KConfigSkeletonGenericItem < QList<QUrl> >
+ {
+ public:
+ /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem */
+ ItemUrlList(const QString & _group, const QString & _key,
+ QList<QUrl> & reference,
+ const QList<QUrl> & defaultValue = QList<QUrl>());
+
+ /** @copydoc KConfigSkeletonItem::readConfig(KConfig*) */
+ void readConfig(KConfig * config);
+
+ /** @copydoc KConfigSkeletonItem::writeConfig(KConfig*) */
+ void writeConfig(KConfig * config);
+
+ /** @copydoc KConfigSkeletonItem::setProperty(const QVariant&) */
+ void setProperty(const QVariant & p);
+
+ /** @copydoc KConfigSkeletonItem::isEqual(const QVariant &) const */
+ bool isEqual(const QVariant &p) const;
+
+ /** @copydoc KConfigSkeletonItem::property() */
+ QVariant property() const;
+ };
+
+ /**
+ * Class for handling an integer list preferences item.
+ */
+ class KCONFIGCORE_EXPORT ItemIntList:public KConfigSkeletonGenericItem < QList < int > >
+ {
+ public:
+ /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem */
+ ItemIntList(const QString & _group, const QString & _key,
+ QList < int >&reference,
+ const QList < int >&defaultValue = QList < int >());
+
+ /** @copydoc KConfigSkeletonItem::readConfig(KConfig*) */
+ void readConfig(KConfig * config);
+
+ /** @copydoc KConfigSkeletonItem::setProperty(const QVariant&) */
+ void setProperty(const QVariant & p);
+
+ /** @copydoc KConfigSkeletonItem::isEqual(const QVariant &) const */
+ bool isEqual(const QVariant &p) const;
+
+ /** @copydoc KConfigSkeletonItem::property() */
+ QVariant property() const;
+ };
+
+
+public:
+ /**
+ * Constructor.
+ *
+ * @param configname name of config file. If no name is given, the default
+ * config file as returned by KSharedConfig::openConfig() is used
+ * @param parent the parent object (see QObject documentation)
+ */
+ explicit KCoreConfigSkeleton(const QString & configname = QString(), QObject* parent = 0);
+
+ /**
+ * Constructor.
+ *
+ * @param config configuration object to use
+ * @param parent the parent object (see QObject documentation)
+ */
+ explicit KCoreConfigSkeleton(KSharedConfig::Ptr config, QObject* parent = 0);
+
+ /**
+ * Destructor
+ */
+ virtual ~KCoreConfigSkeleton();
+
+ /**
+ * Set all registered items to their default values.
+ * This method calls usrSetDefaults() after setting the defaults for the
+ * registered items. You can overridde usrSetDefaults() in derived classes
+ * if you have special requirements.
+ * If you need more fine-grained control of setting the default values of
+ * the registered items you can override setDefaults() in a derived class.
+ */
+ virtual void setDefaults();
+
+ /**
+ * Read preferences from config file. All registered items are set to the
+ * values read from disk.
+ * This method calls usrReadConfig() after reading the settings of the
+ * registered items from the KConfig. You can overridde usrReadConfig()
+ * in derived classes if you have special requirements.
+ * If you need more fine-grained control of storing the settings from
+ * the registered items you can override readConfig() in a derived class.
+ */
+ virtual void readConfig();
+
+ /**
+ * Set the config file group for subsequent addItem() calls. It is valid
+ * until setCurrentGroup() is called with a new argument. Call this before
+ * you add any items. The default value is "No Group".
+ */
+ void setCurrentGroup(const QString & group);
+
+ /**
+ * Returns the current group used for addItem() calls.
+ */
+ QString currentGroup() const;
+
+ /**
+ * Register a custom @ref KConfigSkeletonItem with a given name.
+ *
+ * If the name parameter is null, take the name from KConfigSkeletonItem::key().
+ * Note that all names must be unique but that multiple entries can have
+ * the same key if they reside in different groups.
+ *
+ * KCoreConfigSkeleton takes ownership of the KConfigSkeletonItem.
+ */
+ void addItem(KConfigSkeletonItem *, const QString & name = QString() );
+
+ /**
+ * Register an item of type QString.
+ *
+ * @param name Name used to identify this setting. Names must be unique.
+ * @param reference Pointer to the variable, which is set by readConfig()
+ * calls and read by writeConfig() calls.
+ * @param defaultValue Default value, which is used when the config file
+ * does not yet contain the key of this item.
+ * @param key Key used in config file. If key is null, name is used as key.
+ * @return The created item
+ */
+ ItemString *addItemString(const QString & name, QString & reference,
+ const QString & defaultValue = QLatin1String(""), // NOT QString() !!
+ const QString & key = QString());
+
+ /**
+ * Register a password item of type QString. The string value is written
+ * encrypted to the config file. Note that the current encryption scheme
+ * is very weak.
+ *
+ * @param name Name used to identify this setting. Names must be unique.
+ * @param reference Pointer to the variable, which is set by readConfig()
+ * calls and read by writeConfig() calls.
+ * @param defaultValue Default value, which is used when the config file
+ * does not yet contain the key of this item.
+ * @param key Key used in config file. If key is null, name is used as key.
+ * @return The created item
+ */
+ ItemPassword *addItemPassword(const QString & name, QString & reference,
+ const QString & defaultValue = QLatin1String(""),
+ const QString & key = QString());
+
+ /**
+ * Register a path item of type QString. The string value is interpreted
+ * as a path. This means, dollar expension is activated for this value, so
+ * that e.g. $HOME gets expanded.
+ *
+ * @param name Name used to identify this setting. Names must be unique.
+ * @param reference Pointer to the variable, which is set by readConfig()
+ * calls and read by writeConfig() calls.
+ * @param defaultValue Default value, which is used when the config file
+ * does not yet contain the key of this item.
+ * @param key Key used in config file. If key is null, name is used as key.
+ * @return The created item
+ */
+ ItemPath *addItemPath(const QString & name, QString & reference,
+ const QString & defaultValue = QLatin1String(""),
+ const QString & key = QString());
+
+ /**
+ * Register a property item of type QVariant. Note that only the following
+ * QVariant types are allowed: String, StringList, Font, Point, Rect, Size,
+ * Color, Int, UInt, Bool, Double, DateTime and Date.
+ *
+ * @param name Name used to identify this setting. Names must be unique.
+ * @param reference Pointer to the variable, which is set by readConfig()
+ * calls and read by writeConfig() calls.
+ * @param defaultValue Default value, which is used when the config file
+ * does not yet contain the key of this item.
+ * @param key Key used in config file. If key is null, name is used as key.
+ * @return The created item
+ */
+ ItemProperty *addItemProperty(const QString & name, QVariant & reference,
+ const QVariant & defaultValue = QVariant(),
+ const QString & key = QString());
+ /**
+ * Register an item of type bool.
+ *
+ * @param name Name used to identify this setting. Names must be unique.
+ * @param reference Pointer to the variable, which is set by readConfig()
+ * calls and read by writeConfig() calls.
+ * @param defaultValue Default value, which is used when the config file
+ * does not yet contain the key of this item.
+ * @param key Key used in config file. If key is null, name is used as key.
+ * @return The created item
+ */
+ ItemBool *addItemBool(const QString & name, bool & reference,
+ bool defaultValue = false,
+ const QString & key = QString());
+
+ /**
+ * Register an item of type qint32.
+ *
+ * @param name Name used to identify this setting. Names must be unique.
+ * @param reference Pointer to the variable, which is set by readConfig()
+ * calls and read by writeConfig() calls.
+ * @param defaultValue Default value, which is used when the config file
+ * does not yet contain the key of this item.
+ * @param key Key used in config file. If key is null, name is used as key.
+ * @return The created item
+ */
+ ItemInt *addItemInt(const QString & name, qint32 &reference, qint32 defaultValue = 0,
+ const QString & key = QString());
+
+ /**
+ * Register an item of type quint32.
+ *
+ * @param name Name used to identify this setting. Names must be unique.
+ * @param reference Pointer to the variable, which is set by readConfig()
+ * calls and read by writeConfig() calls.
+ * @param defaultValue Default value, which is used when the config file
+ * does not yet contain the key of this item.
+ * @param key Key used in config file. If key is null, name is used as key.
+ * @return The created item
+ */
+ ItemUInt *addItemUInt(const QString & name, quint32 &reference,
+ quint32 defaultValue = 0,
+ const QString & key = QString());
+
+ /**
+ * Register an item of type qint64.
+ *
+ * @param name Name used to identify this setting. Names must be unique.
+ * @param reference Pointer to the variable, which is set by readConfig()
+ * calls and read by writeConfig() calls.
+ * @param defaultValue Default value, which is used when the config file
+ * does not yet contain the key of this item.
+ * @param key Key used in config file. If key is null, name is used as key.
+ * @return The created item
+ */
+ ItemLongLong *addItemLongLong(const QString & name, qint64 &reference,
+ qint64 defaultValue = 0,
+ const QString & key = QString());
+
+ /**
+ * @deprecated
+ * Use addItemLongLong().
+ */
+#ifndef KDE_NO_DEPRECATED
+ KCONFIGCORE_DEPRECATED ItemLongLong *addItemInt64( const QString& name, qint64 &reference,
+ qint64 defaultValue = 0,
+ const QString & key = QString());
+#endif
+
+ /**
+ * Register an item of type quint64
+ *
+ * @param name Name used to identify this setting. Names must be unique.
+ * @param reference Pointer to the variable, which is set by readConfig()
+ * calls and read by writeConfig() calls.
+ * @param defaultValue Default value, which is used when the config file
+ * does not yet contain the key of this item.
+ * @param key Key used in config file. If key is null, name is used as key.
+ * @return The created item
+ */
+ ItemULongLong *addItemULongLong(const QString & name, quint64 &reference,
+ quint64 defaultValue = 0,
+ const QString & key = QString());
+
+ /**
+ * @deprecated
+ * Use addItemULongLong().
+ */
+#ifndef KDE_NO_DEPRECATED
+ KCONFIGCORE_DEPRECATED ItemULongLong *addItemUInt64(const QString & name, quint64 &reference,
+ quint64 defaultValue = 0,
+ const QString & key = QString());
+#endif
+
+ /**
+ * Register an item of type double.
+ *
+ * @param name Name used to identify this setting. Names must be unique.
+ * @param reference Pointer to the variable, which is set by readConfig()
+ * calls and read by writeConfig() calls.
+ * @param defaultValue Default value, which is used when the config file
+ * does not yet contain the key of this item.
+ * @param key Key used in config file. If key is null, name is used as key.
+ * @return The created item
+ */
+ ItemDouble *addItemDouble(const QString & name, double &reference,
+ double defaultValue = 0.0,
+ const QString & key = QString());
+
+ /**
+ * Register an item of type QRect.
+ *
+ * @param name Name used to identify this setting. Names must be unique.
+ * @param reference Pointer to the variable, which is set by readConfig()
+ * calls and read by writeConfig() calls.
+ * @param defaultValue Default value, which is used when the config file
+ * does not yet contain the key of this item.
+ * @param key Key used in config file. If key is null, name is used as key.
+ * @return The created item
+ */
+ ItemRect *addItemRect(const QString & name, QRect & reference,
+ const QRect & defaultValue = QRect(),
+ const QString & key = QString());
+
+ /**
+ * Register an item of type QPoint.
+ *
+ * @param name Name used to identify this setting. Names must be unique.
+ * @param reference Pointer to the variable, which is set by readConfig()
+ * calls and read by writeConfig() calls.
+ * @param defaultValue Default value, which is used when the config file
+ * does not yet contain the key of this item.
+ * @param key Key used in config file. If key is null, name is used as key.
+ * @return The created item
+ */
+ ItemPoint *addItemPoint(const QString & name, QPoint & reference,
+ const QPoint & defaultValue = QPoint(),
+ const QString & key = QString());
+
+ /**
+ * Register an item of type QSize.
+ *
+ * @param name Name used to identify this setting. Names must be unique.
+ * @param reference Pointer to the variable, which is set by readConfig()
+ * calls and read by writeConfig() calls.
+ * @param defaultValue Default value, which is used when the config file
+ * does not yet contain the key of this item.
+ * @param key Key used in config file. If key is null, name is used as key.
+ * @return The created item
+ */
+ ItemSize *addItemSize(const QString & name, QSize & reference,
+ const QSize & defaultValue = QSize(),
+ const QString & key = QString());
+
+ /**
+ * Register an item of type QDateTime.
+ *
+ * @param name Name used to identify this setting. Names must be unique.
+ * @param reference Pointer to the variable, which is set by readConfig()
+ * calls and read by writeConfig() calls.
+ * @param defaultValue Default value, which is used when the config file
+ * does not yet contain the key of this item.
+ * @param key Key used in config file. If key is null, name is used as key.
+ * @return The created item
+ */
+ ItemDateTime *addItemDateTime(const QString & name, QDateTime & reference,
+ const QDateTime & defaultValue = QDateTime(),
+ const QString & key = QString());
+
+ /**
+ * Register an item of type QStringList.
+ *
+ * @param name Name used to identify this setting. Names must be unique.
+ * @param reference Pointer to the variable, which is set by readConfig()
+ * calls and read by writeConfig() calls.
+ * @param defaultValue Default value, which is used when the config file
+ * does not yet contain the key of this item.
+ * @param key Key used in config file. If key is null, name is used as key.
+ * @return The created item
+ */
+ ItemStringList *addItemStringList(const QString & name, QStringList & reference,
+ const QStringList & defaultValue = QStringList(),
+ const QString & key = QString());
+
+ /**
+ * Register an item of type QList<int>.
+ *
+ * @param name Name used to identify this setting. Names must be unique.
+ * @param reference Pointer to the variable, which is set by readConfig()
+ * calls and read by writeConfig() calls.
+ * @param defaultValue Default value, which is used when the config file
+ * does not yet contain the key of this item.
+ * @param key Key used in config file. If key is null, name is used as key.
+ * @return The created item
+ */
+ ItemIntList *addItemIntList(const QString & name, QList < int >&reference,
+ const QList < int >&defaultValue =
+ QList < int >(),
+ const QString & key = QString());
+
+ /**
+ * Return the @ref KConfig object used for reading and writing the settings.
+ */
+ KConfig *config();
+
+ /**
+ * Return the @ref KConfig object used for reading and writing the settings.
+ */
+ const KConfig *config() const;
+
+ /**
+ * Set the @ref KSharedConfig object used for reading and writing the settings.
+ */
+ void setSharedConfig(KSharedConfig::Ptr pConfig);
+
+ /**
+ * Return list of items managed by this KCoreConfigSkeleton object.
+ */
+ KConfigSkeletonItem::List items() const;
+
+ /**
+ * Removes and deletes an item by name
+ * @arg name the name of the item to remove
+ */
+ void removeItem(const QString &name);
+
+ /**
+ * Removes and deletes all items
+ */
+ void clearItems();
+
+ /**
+ * Return whether a certain item is immutable
+ * @since 4.4
+ */
+ bool isImmutable(const QString & name) const;
+
+ /**
+ * Lookup item by name
+ * @since 4.4
+ */
+ KConfigSkeletonItem * findItem(const QString & name) const;
+
+ /**
+ * Specify whether this object should reflect the actual values or the
+ * default values.
+ * This method is implemented by usrUseDefaults(), which can be overridden
+ * in derived classes if you have special requirements and can call
+ * usrUseDefaults() directly.
+ * If you don't have control whether useDefaults() or usrUseDefaults() is
+ * called override useDefaults() directly.
+ * @param b true to make this object reflect the default values,
+ * false to make it reflect the actual values.
+ * @return The state prior to this call
+ */
+ virtual bool useDefaults(bool b);
+
+public Q_SLOTS:
+ /**
+ * Write preferences to config file. The values of all registered items are
+ * written to disk.
+ * This method calls usrWriteConfig() after writing the settings from the
+ * registered items to the KConfig. You can overridde usrWriteConfig()
+ * in derived classes if you have special requirements.
+ * If you need more fine-grained control of storing the settings from
+ * the registered items you can override writeConfig() in a derived class.
+ */
+ virtual bool writeConfig();
+
+Q_SIGNALS:
+ /**
+ * This signal is emitted when the configuration change.
+ */
+ void configChanged();
+
+protected:
+ /**
+ * Implemented by subclasses that use special defaults.
+ * It replaces the default values with the actual values and
+ * vice versa. Called from @ref useDefaults()
+ * @param b true to make this object reflect the default values,
+ * false to make it reflect the actual values.
+ * @return The state prior to this call
+ */
+ virtual bool usrUseDefaults(bool b);
+
+ /**
+ * Perform the actual setting of default values.
+ * Override in derived classes to set special default values.
+ * Called from @ref setDefaults()
+ */
+ virtual void usrSetDefaults();
+
+ /**
+ * Perform the actual reading of the configuration file.
+ * Override in derived classes to read special config values.
+ * Called from @ref readConfig()
+ */
+ virtual void usrReadConfig();
+
+ /**
+ * Perform the actual writing of the configuration file.
+ * Override in derived classes to write special config values.
+ * Called from @ref writeConfig()
+ */
+ virtual bool usrWriteConfig();
+
+private:
+ class Private;
+ Private * const d;
+ friend class KConfigSkeleton;
+
+};
+
+#endif
diff --git a/tier1/kconfig/src/core/kcoreconfigskeleton_p.h b/tier1/kconfig/src/core/kcoreconfigskeleton_p.h
new file mode 100644
index 00000000..0912019c
--- /dev/null
+++ b/tier1/kconfig/src/core/kcoreconfigskeleton_p.h
@@ -0,0 +1,64 @@
+/*
+ This file is part of KOrganizer.
+ Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org>
+ Copyright (c) 2003 Waldo Bastian <bastian@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KCORECONFIGSKELETON_P_H
+#define KCORECONFIGSKELETON_P_H
+
+#include "kcoreconfigskeleton.h"
+
+class KCoreConfigSkeleton::Private
+{
+public:
+ Private()
+ : mCurrentGroup( QLatin1String("No Group") ), mUseDefaults( false )
+ {}
+ ~Private()
+ {
+ KConfigSkeletonItem::List::ConstIterator it;
+ for( it = mItems.constBegin(); it != mItems.constEnd(); ++it )
+ {
+ delete *it;
+ }
+ }
+ QString mCurrentGroup;
+
+ KSharedConfig::Ptr mConfig; // pointer to KConfig object
+
+ KConfigSkeletonItem::List mItems;
+ KConfigSkeletonItem::Dict mItemDict;
+
+ bool mUseDefaults;
+};
+
+class KConfigSkeletonItemPrivate
+{
+public:
+ KConfigSkeletonItemPrivate()
+ : mIsImmutable(true)
+ {}
+ bool mIsImmutable; ///< Indicates this item is immutable
+
+ QString mLabel; ///< The label for this item
+ QString mToolTip; ///< The ToolTip text for this item
+ QString mWhatsThis; ///< The What's This text for this item
+};
+
+#endif
diff --git a/tier1/kconfig/src/core/kdesktopfile.cpp b/tier1/kconfig/src/core/kdesktopfile.cpp
new file mode 100644
index 00000000..0ebbb4b0
--- /dev/null
+++ b/tier1/kconfig/src/core/kdesktopfile.cpp
@@ -0,0 +1,366 @@
+/*
+ This file is part of the KDE libraries
+ Copyright (c) 1999 Pietro Iglio <iglio@kde.org>
+ Copyright (c) 1999 Preston Brown <pbrown@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+// Qt5 TODO: re-enable. No point in doing it before, it breaks on QString::fromUtf8(QByteArray), which exists in qt5.
+#undef QT_NO_CAST_FROM_BYTEARRAY
+
+#include "kdesktopfile.h"
+
+#ifndef Q_OS_WIN
+#include <unistd.h>
+#endif
+
+#include <QtCore/QDir>
+#include <QtCore/QFileInfo>
+#include <QUrl>
+#include <qstandardpaths.h>
+
+#include "kauthorized.h"
+#include "kconfig_p.h"
+#include "kconfiggroup.h"
+#include "kconfigini_p.h"
+
+class KDesktopFilePrivate : public KConfigPrivate
+{
+ public:
+ KDesktopFilePrivate(QStandardPaths::StandardLocation resourceType, const QString &fileName);
+ KConfigGroup desktopGroup;
+};
+
+KDesktopFilePrivate::KDesktopFilePrivate(QStandardPaths::StandardLocation resourceType, const QString &fileName)
+ : KConfigPrivate(KConfig::NoGlobals, resourceType)
+{
+ mBackend = new KConfigIniBackend();
+ bDynamicBackend = false;
+ changeFileName(fileName);
+}
+
+KDesktopFile::KDesktopFile(QStandardPaths::StandardLocation resourceType, const QString &fileName)
+ : KConfig(*new KDesktopFilePrivate(resourceType, fileName))
+{
+ Q_D(KDesktopFile);
+ reparseConfiguration();
+ d->desktopGroup = KConfigGroup(this, "Desktop Entry");
+}
+
+KDesktopFile::KDesktopFile(const QString &fileName)
+ : KConfig(*new KDesktopFilePrivate(QStandardPaths::ApplicationsLocation, fileName))
+{
+ Q_D(KDesktopFile);
+ reparseConfiguration();
+ d->desktopGroup = KConfigGroup(this, "Desktop Entry");
+}
+
+KDesktopFile::~KDesktopFile()
+{
+}
+
+KConfigGroup KDesktopFile::desktopGroup() const
+{
+ Q_D(const KDesktopFile);
+ return d->desktopGroup;
+}
+
+QString KDesktopFile::locateLocal(const QString &path)
+{
+ QString relativePath;
+ // Relative to config? (e.g. for autostart)
+ Q_FOREACH(const QString& dir, QStandardPaths::standardLocations(QStandardPaths::GenericConfigLocation)) {
+ if (path.startsWith(dir) + '/') {
+ relativePath = dir.mid(path.length() + 1);
+ return QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + QLatin1Char('/') + relativePath;
+ }
+ }
+ // Relative to xdg data dir? (much more common)
+ Q_FOREACH(const QString& dir, QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation)) {
+ if (path.startsWith(dir) + '/')
+ relativePath = dir.mid(path.length() + 1);
+ }
+ if (relativePath.isEmpty()) {
+ // What now? The desktop file doesn't come from XDG_DATA_DIRS. Use filename only and hope for the best.
+ relativePath = path.mid(path.lastIndexOf(QLatin1Char('/'))+1);
+ }
+ return QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1Char('/') + relativePath;
+}
+
+bool KDesktopFile::isDesktopFile(const QString& path)
+{
+ return (path.length() > 8
+ && path.endsWith(QLatin1String(".desktop")));
+}
+
+bool KDesktopFile::isAuthorizedDesktopFile(const QString& path)
+{
+ if (path.isEmpty())
+ return false; // Empty paths are not ok.
+
+ if (QDir::isRelativePath(path))
+ return true; // Relative paths are ok.
+
+ const QString realPath = QFileInfo(path).canonicalFilePath();
+ if (realPath.isEmpty())
+ return false; // File doesn't exist.
+
+#ifndef Q_OS_WIN
+ const Qt::CaseSensitivity sensitivity = Qt::CaseSensitive;
+#else
+ const Qt::CaseSensitivity sensitivity = Qt::CaseInsensitive;
+#endif
+
+ // Check if the .desktop file is installed as part of KDE or XDG.
+ const QStringList appsDirs = QStandardPaths::standardLocations(QStandardPaths::ApplicationsLocation);
+ Q_FOREACH (const QString &prefix, appsDirs) {
+ if (QDir(prefix).exists() && realPath.startsWith(QFileInfo(prefix).canonicalFilePath(), sensitivity))
+ return true;
+ }
+ const QString servicesDir = QLatin1String("kde5/services/"); // KGlobal::dirs()->xdgDataRelativePath("services")
+ Q_FOREACH (const QString &xdgDataPrefix, QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation)) {
+ if (QDir(xdgDataPrefix).exists()) {
+ const QString prefix = QFileInfo(xdgDataPrefix).canonicalFilePath();
+ if (realPath.startsWith(prefix + QLatin1Char('/') + servicesDir, sensitivity))
+ return true;
+ }
+ }
+ const QString autostartDir = QLatin1String("autostart/");
+ Q_FOREACH (const QString &xdgDataPrefix, QStandardPaths::standardLocations(QStandardPaths::GenericConfigLocation)) {
+ if (QDir(xdgDataPrefix).exists()) {
+ const QString prefix = QFileInfo(xdgDataPrefix).canonicalFilePath();
+ if (realPath.startsWith(prefix + QLatin1Char('/') + autostartDir, sensitivity))
+ return true;
+ }
+ }
+
+ // Forbid desktop files outside of standard locations if kiosk is set so
+ if (!KAuthorized::authorize(QLatin1String("run_desktop_files"))) {
+ qWarning() << "Access to '" << path << "' denied because of 'run_desktop_files' restriction." << endl;
+ return false;
+ }
+
+ // Not otherwise permitted, so only allow if the file is executable, or if
+ // owned by root (uid == 0)
+ QFileInfo entryInfo( path );
+ if (entryInfo.isExecutable() || entryInfo.ownerId() == 0)
+ return true;
+
+ qWarning() << "Access to '" << path << "' denied, not owned by root, executable flag not set." << endl;
+ return false;
+}
+
+QString KDesktopFile::readType() const
+{
+ Q_D(const KDesktopFile);
+ return d->desktopGroup.readEntry("Type", QString());
+}
+
+QString KDesktopFile::readIcon() const
+{
+ Q_D(const KDesktopFile);
+ return d->desktopGroup.readEntry("Icon", QString());
+}
+
+QString KDesktopFile::readName() const
+{
+ Q_D(const KDesktopFile);
+ return d->desktopGroup.readEntry("Name", QString());
+}
+
+QString KDesktopFile::readComment() const
+{
+ Q_D(const KDesktopFile);
+ return d->desktopGroup.readEntry("Comment", QString());
+}
+
+QString KDesktopFile::readGenericName() const
+{
+ Q_D(const KDesktopFile);
+ return d->desktopGroup.readEntry("GenericName", QString());
+}
+
+QString KDesktopFile::readPath() const
+{
+ Q_D(const KDesktopFile);
+ // NOT readPathEntry, it is not XDG-compliant. Path entries written by
+ // KDE4 will be still treated as such, though.
+ return d->desktopGroup.readEntry("Path", QString());
+}
+
+QString KDesktopFile::readDevice() const
+{
+ Q_D(const KDesktopFile);
+ return d->desktopGroup.readEntry("Dev", QString());
+}
+
+QString KDesktopFile::readUrl() const
+{
+ Q_D(const KDesktopFile);
+ if (hasDeviceType()) {
+ return d->desktopGroup.readEntry("MountPoint", QString());
+ } else {
+ // NOT readPathEntry (see readPath())
+ QString url = d->desktopGroup.readEntry("URL", QString());
+ if ( !url.isEmpty() && !QDir::isRelativePath(url) )
+ {
+ // Handle absolute paths as such (i.e. we need to escape them)
+ return QUrl::fromLocalFile(url).toString();
+ }
+ return url;
+ }
+}
+
+QStringList KDesktopFile::readActions() const
+{
+ Q_D(const KDesktopFile);
+ return d->desktopGroup.readXdgListEntry("Actions");
+}
+
+KConfigGroup KDesktopFile::actionGroup(const QString &group)
+{
+ return KConfigGroup(this, QLatin1String("Desktop Action ") + group);
+}
+
+const KConfigGroup KDesktopFile::actionGroup(const QString& group) const
+{
+ return const_cast<KDesktopFile*>(this)->actionGroup(group);
+}
+
+bool KDesktopFile::hasActionGroup(const QString &group) const
+{
+ return hasGroup(QString(QLatin1String("Desktop Action ") + group).toUtf8().constData());
+}
+
+bool KDesktopFile::hasLinkType() const
+{
+ return readType() == QLatin1String("Link");
+}
+
+bool KDesktopFile::hasApplicationType() const
+{
+ return readType() == QLatin1String("Application");
+}
+
+bool KDesktopFile::hasDeviceType() const
+{
+ return readType() == QLatin1String("FSDevice");
+}
+
+bool KDesktopFile::tryExec() const
+{
+ Q_D(const KDesktopFile);
+ // Test for TryExec and "X-KDE-AuthorizeAction"
+ // NOT readPathEntry (see readPath())
+ QString te = d->desktopGroup.readEntry("TryExec", QString());
+
+ if (!te.isEmpty()) {
+ return !QStandardPaths::findExecutable(te).isEmpty();
+ }
+ const QStringList list = d->desktopGroup.readEntry("X-KDE-AuthorizeAction", QStringList());
+ if (!list.isEmpty())
+ {
+ for(QStringList::ConstIterator it = list.begin();
+ it != list.end();
+ ++it)
+ {
+ if (!KAuthorized::authorize((*it).trimmed()))
+ return false;
+ }
+ }
+
+ // See also KService::username()
+ bool su = d->desktopGroup.readEntry("X-KDE-SubstituteUID", false);
+ if (su)
+ {
+ QString user = d->desktopGroup.readEntry("X-KDE-Username", QString());
+ if (user.isEmpty())
+ user = QString::fromLocal8Bit(qgetenv("ADMIN_ACCOUNT"));
+ if (user.isEmpty())
+ user = QString::fromLatin1("root");
+ if (!KAuthorized::authorize(QString::fromLatin1("user/")+user))
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * @return the filename as passed to the constructor.
+ */
+//QString KDesktopFile::fileName() const { return backEnd->fileName(); }
+
+/**
+ * @return the resource type as passed to the constructor.
+ */
+//QString
+//KDesktopFile::resource() const { return backEnd->resource(); }
+
+QStringList
+KDesktopFile::sortOrder() const
+{
+ Q_D(const KDesktopFile);
+ return d->desktopGroup.readEntry("SortOrder", QStringList());
+}
+
+//void KDesktopFile::virtual_hook( int id, void* data )
+//{ KConfig::virtual_hook( id, data ); }
+
+QString KDesktopFile::readDocPath() const
+{
+ Q_D(const KDesktopFile);
+ //legacy entry in kde3 apps
+ if(d->desktopGroup.hasKey( "DocPath" ))
+ return d->desktopGroup.readPathEntry( "DocPath", QString() );
+ return d->desktopGroup.readPathEntry( "X-DocPath", QString() );
+}
+
+KDesktopFile* KDesktopFile::copyTo(const QString &file) const
+{
+ KDesktopFile *config = new KDesktopFile(QString());
+ this->KConfig::copyTo(file, config);
+// config->setDesktopGroup();
+ return config;
+}
+
+QStandardPaths::StandardLocation KDesktopFile::resource() const
+{
+ Q_D(const KDesktopFile);
+ return d->resourceType;
+}
+
+QString KDesktopFile::fileName() const
+{
+ return name();
+}
+
+bool KDesktopFile::noDisplay() const
+{
+ Q_D(const KDesktopFile);
+ if (d->desktopGroup.readEntry("NoDisplay", false)) {
+ return true;
+ }
+ if (d->desktopGroup.hasKey("OnlyShowIn")) {
+ if (!d->desktopGroup.readXdgListEntry("OnlyShowIn").contains(QLatin1String("KDE")))
+ return true;
+ }
+ if (d->desktopGroup.hasKey("NotShowIn")) {
+ if (d->desktopGroup.readXdgListEntry("NotShowIn").contains(QLatin1String("KDE")))
+ return true;
+ }
+ return false;
+}
diff --git a/tier1/kconfig/src/core/kdesktopfile.h b/tier1/kconfig/src/core/kdesktopfile.h
new file mode 100644
index 00000000..f3c5fe8f
--- /dev/null
+++ b/tier1/kconfig/src/core/kdesktopfile.h
@@ -0,0 +1,252 @@
+/* This file is part of the KDE libraries
+ Copyright (c) 1999 Pietro Iglio <iglio@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#ifndef KDESKTOPFILE_H
+#define KDESKTOPFILE_H
+
+#include <kconfig.h>
+
+class KConfigGroup;
+class KDesktopFilePrivate;
+
+/**
+ * \class KDesktopFile kdesktopfile.h <KDesktopFile>
+ *
+ * %KDE Desktop File Management.
+ * This class implements %KDE's support for the freedesktop.org
+ * <em>Desktop Entry Spec</em>.
+ *
+ * @author Pietro Iglio <iglio@kde.org>
+ * @see KConfigBase KConfig
+ * @see <a href="http://standards.freedesktop.org/desktop-entry-spec/latest/">Desktop Entry Spec</a>
+ */
+class KCONFIGCORE_EXPORT KDesktopFile : public KConfig
+{
+public:
+ /**
+ * Constructs a KDesktopFile object.
+ *
+ * See QStandardPaths for more information on resources.
+ *
+ * @param resourceType Allows you to change what sort of resource
+ * to search for if @p fileName is not absolute.
+ * For instance, you might want to specify GenericConfigLocation.
+ * @param fileName The name or path of the desktop file. If it
+ * is not absolute, it will be located
+ * using the resource type @p resType.
+ */
+ explicit KDesktopFile(QStandardPaths::StandardLocation resourceType, const QString &fileName);
+
+ /**
+ * Constructs a KDesktopFile object.
+ *
+ * See QStandardPaths for more information on resources.
+ *
+ * @param fileName The name or path of the desktop file. If it
+ * is not absolute, it will be located
+ * using the resource type ApplicationsLocation
+ */
+ explicit KDesktopFile(const QString &fileName);
+
+ /**
+ * Destructs the KDesktopFile object.
+ *
+ * Writes back any dirty configuration entries.
+ */
+ virtual ~KDesktopFile();
+
+ /**
+ * Checks whether this is really a desktop file.
+ *
+ * The check is performed looking at the file extension (the file is not
+ * opened).
+ * Currently, the only valid extension is ".desktop".
+ * @param path the path of the file to check
+ * @return true if the file appears to be a desktop file.
+ */
+ static bool isDesktopFile(const QString& path);
+
+ /**
+ * Checks whether the user is authorized to run this desktop file.
+ * By default users are authorized to run all desktop files but
+ * the KIOSK framework can be used to activate certain restrictions.
+ * See README.kiosk for more information.
+ *
+ * Note: Since KDE 4.3, there are more restrictions on authorized
+ * desktop files to prevent users from inadvertently running trojan
+ * desktop files. Your application launchers should have the executable
+ * bit set to prevent issues. To see if a restriction is due to
+ * KIOSK, see KAuthorized.
+ *
+ * @param path the file to check
+ * @return true if the user is authorized to run the file
+ */
+ static bool isAuthorizedDesktopFile(const QString& path);
+
+ /**
+ * Returns the location where changes for the .desktop file @p path
+ * should be written to.
+ */
+ static QString locateLocal(const QString &path);
+
+ KConfigGroup desktopGroup() const;
+
+ /**
+ * Returns the value of the "Type=" entry.
+ * @return the type or QString() if not specified
+ */
+ QString readType() const;
+
+ /**
+ * Returns the value of the "Icon=" entry.
+ * @return the icon or QString() if not specified
+ */
+ QString readIcon() const;
+
+ /**
+ * Returns the value of the "Name=" entry.
+ * @return the name or QString() if not specified
+ */
+ QString readName() const;
+
+ /**
+ * Returns the value of the "Comment=" entry.
+ * @return the comment or QString() if not specified
+ */
+ QString readComment() const;
+
+ /**
+ * Returns the value of the "GenericName=" entry.
+ * @return the generic name or QString() if not specified
+ */
+ QString readGenericName() const;
+
+ /**
+ * Returns the value of the "Path=" entry.
+ * @return the path or QString() if not specified
+ */
+ QString readPath() const;
+
+ /**
+ * Returns the value of the "Dev=" entry.
+ * @return the device or QString() if not specified
+ */
+ QString readDevice() const;
+
+ /**
+ * Returns the value of the "URL=" entry.
+ * @return the URL or QString() if not specified
+ */
+ QString readUrl() const;
+
+ /**
+ * Returns a list of the "Actions=" entries.
+ * @return the list of actions
+ */
+ QStringList readActions() const;
+
+ /**
+ * Sets the desktop action group.
+ * @param group the new action group
+ */
+ KConfigGroup actionGroup(const QString &group);
+
+ const KConfigGroup actionGroup(const QString &group) const;
+
+ /**
+ * Returns true if the action group exists, false otherwise
+ * @param group the action group to test
+ * @return true if the action group exists
+ */
+ bool hasActionGroup(const QString &group) const;
+
+ /**
+ * Checks whether there is a "Type=Link" entry.
+ *
+ * The link points to the "URL=" entry.
+ * @return true if there is a "Type=Link" entry
+ */
+ bool hasLinkType() const;
+
+ /**
+ * Checks whether there is an entry "Type=Application".
+ * @return true if there is a "Type=Application" entry
+ */
+ bool hasApplicationType() const;
+
+ /**
+ * Checks whether there is an entry "Type=FSDevice".
+ * @return true if there is a "Type=FSDevice" entry
+ */
+ bool hasDeviceType() const;
+
+ /**
+ * Checks whether the TryExec field contains a binary
+ * which is found on the local system.
+ * @return true if TryExec contains an existing binary
+ */
+ bool tryExec() const;
+
+ /**
+ * Returns the value of the "X-DocPath=" Or "DocPath=" entry.
+ * @return The value of the "X-DocPath=" Or "DocPath=" entry.
+ */
+ QString readDocPath() const;
+
+ /**
+ * Returns the entry of the "SortOrder=" entry.
+ * @return the value of the "SortOrder=" entry.
+ */
+ QStringList sortOrder() const;
+
+ /**
+ * Whether the entry should be suppressed in menus.
+ * This handles the NoDisplay key, but also OnlyShowIn / NotShowIn.
+ * @return true to suppress this service
+ * @since 4.1
+ */
+ bool noDisplay() const;
+
+ /**
+ * Copies all entries from this config object to a new
+ * KDesktopFile object that will save itself to @p file.
+ *
+ * Actual saving to @p file happens when the returned object is
+ * destructed or when sync() is called upon it.
+ *
+ * @param file the new KDesktopFile object it will save itself to.
+ */
+ KDesktopFile* copyTo(const QString &file) const;
+
+ QString fileName() const;
+
+ QStandardPaths::StandardLocation resource() const;
+
+protected:
+ /** Virtual hook, used to add new "virtual" functions while maintaining
+ binary compatibility. Unused in this class.
+ */
+// virtual void virtual_hook( int id, void* data );
+private:
+
+ Q_DISABLE_COPY(KDesktopFile)
+
+ Q_DECLARE_PRIVATE(KDesktopFile)
+};
+
+#endif
diff --git a/tier1/kconfig/src/core/kemailsettings.cpp b/tier1/kconfig/src/core/kemailsettings.cpp
new file mode 100644
index 00000000..6a1f9448
--- /dev/null
+++ b/tier1/kconfig/src/core/kemailsettings.cpp
@@ -0,0 +1,269 @@
+/*
+ * Copyright (c) 2000 Alex Zepeda <zipzippy@sonic.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "kemailsettings.h"
+
+#include <kconfig.h>
+#include <kconfiggroup.h>
+
+class KEMailSettingsPrivate {
+public:
+ KEMailSettingsPrivate() : m_pConfig( 0 ) {}
+ ~KEMailSettingsPrivate() { delete m_pConfig; }
+ KConfig *m_pConfig;
+ QStringList profiles;
+ QString m_sDefaultProfile, m_sCurrentProfile;
+};
+
+QString KEMailSettings::defaultProfileName() const
+{
+ return p->m_sDefaultProfile;
+}
+
+QString KEMailSettings::getSetting(KEMailSettings::Setting s) const
+{
+ KConfigGroup cg(p->m_pConfig, QStringLiteral("PROFILE_") + p->m_sCurrentProfile);
+ switch (s) {
+ case ClientProgram: {
+ return cg.readEntry("EmailClient");
+ break;
+ }
+ case ClientTerminal: {
+ return cg.readEntry("TerminalClient", QVariant(false)).toString();
+ break;
+ }
+ case RealName: {
+ return cg.readEntry("FullName");
+ break;
+ }
+ case EmailAddress: {
+ return cg.readEntry("EmailAddress");
+ break;
+ }
+ case ReplyToAddress: {
+ return cg.readEntry("ReplyAddr");
+ break;
+ }
+ case Organization: {
+ return cg.readEntry("Organization");
+ break;
+ }
+ case OutServer: {
+ return cg.readEntry("OutgoingServer");
+ break;
+ }
+ case OutServerLogin: {
+ return cg.readEntry("OutgoingUserName");
+ break;
+ }
+ case OutServerPass: {
+ return cg.readEntry("OutgoingPassword");
+ break;
+ }
+ case OutServerType: {
+ return cg.readEntry("OutgoingServerType");
+ break;
+ }
+ case OutServerCommand: {
+ return cg.readEntry("OutgoingCommand");
+ break;
+ }
+ case OutServerTLS: {
+ return cg.readEntry("OutgoingServerTLS", QVariant(false)).toString();
+ break;
+ }
+ case InServer: {
+ return cg.readEntry("IncomingServer");
+ break;
+ }
+ case InServerLogin: {
+ return cg.readEntry("IncomingUserName");
+ break;
+ }
+ case InServerPass: {
+ return cg.readEntry("IncomingPassword");
+ break;
+ }
+ case InServerType: {
+ return cg.readEntry("IncomingServerType");
+ break;
+ }
+ case InServerMBXType: {
+ return cg.readEntry("IncomingServerMBXType");
+ break;
+ }
+ case InServerTLS: {
+ return cg.readEntry("IncomingServerTLS", QVariant(false)).toString();
+ break;
+ }
+ };
+ return QString();
+}
+void KEMailSettings::setSetting(KEMailSettings::Setting s, const QString &v)
+{
+ KConfigGroup cg(p->m_pConfig, QStringLiteral("PROFILE_") + p->m_sCurrentProfile);
+ switch (s) {
+ case ClientProgram: {
+ cg.writePathEntry("EmailClient", v);
+ break;
+ }
+ case ClientTerminal: {
+ cg.writeEntry("TerminalClient", (v == QLatin1String("true")));
+ break;
+ }
+ case RealName: {
+ cg.writeEntry("FullName", v);
+ break;
+ }
+ case EmailAddress: {
+ cg.writeEntry("EmailAddress", v);
+ break;
+ }
+ case ReplyToAddress: {
+ cg.writeEntry("ReplyAddr", v);
+ break;
+ }
+ case Organization: {
+ cg.writeEntry("Organization", v);
+ break;
+ }
+ case OutServer: {
+ cg.writeEntry("OutgoingServer", v);
+ break;
+ }
+ case OutServerLogin: {
+ cg.writeEntry("OutgoingUserName", v);
+ break;
+ }
+ case OutServerPass: {
+ cg.writeEntry("OutgoingPassword", v);
+ break;
+ }
+ case OutServerType: {
+ cg.writeEntry("OutgoingServerType", v);
+ break;
+ }
+ case OutServerCommand: {
+ cg.writeEntry("OutgoingCommand", v);
+ break;
+ }
+ case OutServerTLS: {
+ cg.writeEntry("OutgoingServerTLS", (v == QLatin1String("true")));
+ break;
+ }
+ case InServer: {
+ cg.writeEntry("IncomingServer", v);
+ break;
+ }
+ case InServerLogin: {
+ cg.writeEntry("IncomingUserName", v);
+ break;
+ }
+ case InServerPass: {
+ cg.writeEntry("IncomingPassword", v);
+ break;
+ }
+ case InServerType: {
+ cg.writeEntry("IncomingServerType", v);
+ break;
+ }
+ case InServerMBXType: {
+ cg.writeEntry("IncomingServerMBXType", v);
+ break;
+ }
+ case InServerTLS: {
+ cg.writeEntry("IncomingServerTLS", (v == QLatin1String("true")));
+ break;
+ }
+ };
+ cg.sync();
+}
+
+void KEMailSettings::setDefault(const QString &s)
+{
+ p->m_pConfig->group("Defaults").writeEntry("Profile", s);
+ p->m_pConfig->sync();
+ p->m_sDefaultProfile=s;
+
+}
+
+void KEMailSettings::setProfile (const QString &s)
+{
+ QString groupname = QStringLiteral("PROFILE_");
+ groupname.append(s);
+ p->m_sCurrentProfile=s;
+ if (!p->m_pConfig->hasGroup(groupname)) { // Create a group if it doesn't exist
+ KConfigGroup cg(p->m_pConfig, groupname);
+ cg.writeEntry("ServerType", QString());
+ p->profiles+=s;
+ }
+}
+
+#ifndef KDE_NO_DEPRECATED
+QString KEMailSettings::currentProfileName() const
+{
+ return p->m_sCurrentProfile;
+}
+#endif
+
+QStringList KEMailSettings::profiles() const
+{
+ return p->profiles;
+}
+
+KEMailSettings::KEMailSettings()
+ :p(new KEMailSettingsPrivate())
+{
+ p->m_sCurrentProfile.clear();
+
+ p->m_pConfig = new KConfig(QStringLiteral("emaildefaults"));
+
+ const QStringList groups = p->m_pConfig->groupList();
+ for (QStringList::ConstIterator it = groups.begin(); it != groups.end(); ++it) {
+ if ( (*it).startsWith( QLatin1String( "PROFILE_" ) ) )
+ p->profiles+= (*it).mid(8, (*it).length());
+ }
+
+ KConfigGroup cg( p->m_pConfig, "Defaults");
+ p->m_sDefaultProfile = cg.readEntry("Profile", tr("Default"));
+ if (!p->m_sDefaultProfile.isNull()) {
+ if (!p->m_pConfig->hasGroup(QStringLiteral("PROFILE_") + p->m_sDefaultProfile))
+ setDefault(tr("Default"));
+ else
+ setDefault(p->m_sDefaultProfile);
+ } else {
+ if (p->profiles.count()) {
+ setDefault(p->profiles[0]);
+ } else
+ setDefault(tr("Default"));
+ }
+ setProfile(defaultProfileName());
+}
+
+KEMailSettings::~KEMailSettings()
+{
+ delete p;
+}
diff --git a/tier1/kconfig/src/core/kemailsettings.h b/tier1/kconfig/src/core/kemailsettings.h
new file mode 100644
index 00000000..32610d61
--- /dev/null
+++ b/tier1/kconfig/src/core/kemailsettings.h
@@ -0,0 +1,176 @@
+/*-
+ * Copyright (c) 2000 Alex Zepeda <zipzippy@sonic.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef _KEMAILSETTINGS_H
+#define _KEMAILSETTINGS_H
+
+#include <QtCore/QCoreApplication> // Q_DECLARE_TR_FUNCTIONS
+#include <QtCore/QStringList>
+
+#include <kconfigcore_export.h>
+
+class KEMailSettingsPrivate;
+
+
+/**
+ * This is just a small class to facilitate accessing e-mail settings in
+ * a sane way, and allowing any program to manage multiple e-mail
+ * profiles effortlessly
+ *
+ * The default profile is automatically selected in the constructor.
+ *
+ * @author Alex Zepeda zipzippy@sonic.net
+ **/
+class KCONFIGCORE_EXPORT KEMailSettings {
+ Q_DECLARE_TR_FUNCTIONS(KEMailSettings)
+public:
+ /**
+ * The list of settings that I thought of when I wrote this
+ * class. Any extra settings thought of later can be accessed
+ * easily with getExtendedSetting and setExtendedSetting.
+ * @see getSetting()
+ * @see setSetting()
+ * @see getExtendedSetting()
+ * @see setExtendedSetting()
+ **/
+ enum Setting {
+ ClientProgram,
+ ClientTerminal,
+ RealName,
+ EmailAddress,
+ ReplyToAddress,
+ Organization,
+ OutServer,
+ OutServerLogin,
+ OutServerPass,
+#ifndef KDE_NO_DEPRECATED
+ /**
+ * @deprecated since Frameworks 5.0
+ */
+ OutServerType,
+ /**
+ * @deprecated since Frameworks 5.0
+ */
+ OutServerCommand,
+ /**
+ * @deprecated since Frameworks 5.0
+ */
+ OutServerTLS,
+#endif
+ InServer,
+ InServerLogin,
+ InServerPass,
+#ifndef KDE_NO_DEPRECATED
+ /**
+ * @deprecated since Frameworks 5.0
+ */
+ InServerType,
+ /**
+ * @deprecated since Frameworks 5.0
+ */
+ InServerMBXType,
+ /**
+ * @deprecated since Frameworks 5.0
+ */
+ InServerTLS
+#endif
+ };
+
+ /**
+ * The various extensions allowed.
+ **/
+ enum Extension {
+ POP3,
+ SMTP,
+ OTHER
+ };
+
+ /**
+ * Default constructor, just sets things up and sets the default profile
+ * as the current profile
+ **/
+ KEMailSettings();
+
+ /**
+ * Default destructor, nothing to see here.
+ **/
+ ~KEMailSettings();
+
+ /**
+ * List of profiles available.
+ * @return the list of profiles
+ **/
+ QStringList profiles() const;
+
+#ifndef KDE_NO_DEPRECATED
+ /**
+ * @deprecated since Frameworks 5.0
+ * Returns the name of the current profile.
+ * @returns what profile we're currently using
+ **/
+ KCONFIGCORE_DEPRECATED QString currentProfileName() const;
+#endif
+
+ /**
+ * Change the current profile.
+ * @param s the name of the new profile
+ **/
+ void setProfile (const QString &s);
+
+ /**
+ * Returns the name of the default profile.
+ * @returns the name of the one that's currently default QString() if none
+ **/
+ QString defaultProfileName() const;
+
+ /**
+ * Sets a new default.
+ * @param def the new default
+ **/
+ void setDefault(const QString &def);
+
+ /**
+ * Get one of the predefined "basic" settings.
+ * @param s the setting to get
+ * @return the value of the setting, or QString() if not
+ * set
+ **/
+ QString getSetting(KEMailSettings::Setting s) const;
+
+ /**
+ * Set one of the predefined "basic" settings.
+ * @param s the setting to set
+ * @param v the new value of the setting, or QString() to
+ * unset
+ **/
+ void setSetting(KEMailSettings::Setting s, const QString &v);
+
+private:
+ KEMailSettingsPrivate* const p;
+};
+
+#endif
diff --git a/tier1/kconfig/src/core/ksharedconfig.cpp b/tier1/kconfig/src/core/ksharedconfig.cpp
new file mode 100644
index 00000000..0e5d1959
--- /dev/null
+++ b/tier1/kconfig/src/core/ksharedconfig.cpp
@@ -0,0 +1,122 @@
+/*
+ This file is part of the KDE libraries
+ Copyright (c) 1999 Preston Brown <pbrown@kde.org>
+ Copyright (C) 1997-1999 Matthias Kalle Dalheimer (kalle@kde.org)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "ksharedconfig.h"
+#include "kconfigbackend.h"
+#include "kconfiggroup.h"
+#include "kconfig_p.h"
+#include <QCoreApplication>
+
+void _k_globalMainConfigSync();
+
+class GlobalSharedConfigList : public QList<KSharedConfig*>
+{
+public:
+ GlobalSharedConfigList()
+ {
+ // We want to force the sync() before the QCoreApplication
+ // instance is gone. Otherwise we trigger a QLockFile::lock()
+ // after QCoreApplication is gone, calling qAppName() for a non
+ // existent app...
+ qAddPostRoutine(&_k_globalMainConfigSync);
+ }
+
+ // in addition to the list, we need to hold the main config,
+ // so that it's not created and destroyed all the time.
+ KSharedConfigPtr mainConfig;
+};
+
+
+Q_GLOBAL_STATIC(GlobalSharedConfigList, globalSharedConfigList)
+
+void _k_globalMainConfigSync()
+{
+ if (globalSharedConfigList->mainConfig)
+ globalSharedConfigList->mainConfig->sync();
+}
+
+
+KSharedConfigPtr KSharedConfig::openConfig(const QString& _fileName,
+ OpenFlags flags,
+ QStandardPaths::StandardLocation resType)
+{
+ QString fileName(_fileName);
+ GlobalSharedConfigList *list = globalSharedConfigList();
+ if (fileName.isEmpty() && !flags.testFlag(KConfig::SimpleConfig)) {
+ // Determine the config file name that KConfig will make up (see KConfigPrivate::changeFileName)
+ fileName = KConfig::mainConfigName();
+ }
+
+ if (list) {
+ for(QList<KSharedConfig*>::ConstIterator it = list->constBegin(); it != list->constEnd(); ++it) {
+ if ( (*it)->name() == fileName &&
+ (*it)->d_ptr->openFlags == flags &&
+ (*it)->locationType() == resType
+// (*it)->backEnd()->type() == backEnd
+ ) {
+ return KSharedConfigPtr(*it);
+ }
+ }
+ }
+ KSharedConfigPtr ptr(new KSharedConfig(fileName, flags, resType));
+ if (_fileName.isEmpty() && flags == FullConfig && resType == QStandardPaths::GenericConfigLocation) {
+ list->mainConfig = ptr;
+
+ static bool userWarned = false;
+ if (!userWarned) {
+ userWarned = true;
+ QByteArray readOnly = qgetenv("KDE_HOME_READONLY");
+ if (readOnly.isEmpty() && QCoreApplication::applicationName() != QLatin1String("kdialog")) {
+ if (ptr->group("General").readEntry(QLatin1String("warn_unwritable_config"), true))
+ ptr->isConfigWritable(true);
+ }
+ }
+ }
+
+ return ptr;
+}
+
+
+KSharedConfig::KSharedConfig(const QString &fileName,
+ OpenFlags flags,
+ QStandardPaths::StandardLocation resType)
+ : KConfig(fileName, flags, resType)
+{
+ globalSharedConfigList()->append(this);
+}
+
+KSharedConfig::~KSharedConfig()
+{
+ if (!globalSharedConfigList.isDestroyed())
+ globalSharedConfigList()->removeAll(this);
+}
+
+KConfigGroup KSharedConfig::groupImpl(const QByteArray &groupName)
+{
+ KSharedConfigPtr ptr(this);
+ return KConfigGroup( ptr, groupName.constData());
+}
+
+const KConfigGroup KSharedConfig::groupImpl(const QByteArray &groupName) const
+{
+ const KSharedConfigPtr ptr(const_cast<KSharedConfig*>(this));
+ return KConfigGroup( ptr, groupName.constData());
+}
diff --git a/tier1/kconfig/src/core/ksharedconfig.h b/tier1/kconfig/src/core/ksharedconfig.h
new file mode 100644
index 00000000..42f7440e
--- /dev/null
+++ b/tier1/kconfig/src/core/ksharedconfig.h
@@ -0,0 +1,88 @@
+/*
+ This file is part of the KDE libraries
+ Copyright (c) 1999 Preston Brown <pbrown@kde.org>
+ Copyright (C) 1997-1999 Matthias Kalle Dalheimer (kalle@kde.org)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KSHAREDCONFIG_H
+#define KSHAREDCONFIG_H
+
+#include <kconfig.h>
+#include <QExplicitlySharedDataPointer>
+
+/**
+ * \class KSharedConfig ksharedconfig.h <KSharedConfig>
+ *
+ * KConfig variant using shared memory
+ *
+ * KSharedConfig provides a reference counted, shared memory variant
+ * of KConfig. This allows you to use manipulate the same configuration
+ * files from different places in your code without worrying about
+ * accidentally overwriting changes.
+ *
+ * Note that, as with most of kdelibs, this is @b NOT threadsafe.
+ */
+class KCONFIGCORE_EXPORT KSharedConfig : public KConfig, public QSharedData //krazy:exclude=dpointer (only for refcounting)
+{
+public:
+ typedef QExplicitlySharedDataPointer<KSharedConfig> Ptr;
+
+public:
+ /**
+ * Creates a KSharedConfig object to manipulate a configuration file
+ *
+ * If an absolute path is specified for @p fileName, that file will be used
+ * as the store for the configuration settings. If a non-absolute path
+ * is provided, the file will be looked for in the standard directory
+ * specified by resourceType. If no path is provided, a default
+ * configuration file will be used based on the name of the main
+ * application component.
+ *
+ * @p mode determines whether the user or global settings will be allowed
+ * to influence the values returned by this object. See KConfig::OpenFlags for
+ * more details.
+ *
+ * @param fileName the configuration file to open. If empty, it will be determined
+ * automatically (from --config on the command line, otherwise
+ * from the application name + "rc")
+ * @param mode how global settings should affect the configuration
+ * options exposed by this KConfig object
+ * @param resourceType The standard directory to look for the configuration
+ * file in (see KStandardDirs)
+ *
+ * @sa KConfig
+ */
+ static KSharedConfig::Ptr openConfig(const QString& fileName = QString(),
+ OpenFlags mode = FullConfig,
+ QStandardPaths::StandardLocation type = QStandardPaths::GenericConfigLocation);
+
+ virtual ~KSharedConfig();
+
+private:
+ Q_DISABLE_COPY(KSharedConfig)
+ virtual KConfigGroup groupImpl(const QByteArray& aGroup);
+ virtual const KConfigGroup groupImpl(const QByteArray& aGroup) const;
+
+ KSharedConfig(const QString& file, OpenFlags mode,
+ QStandardPaths::StandardLocation resourceType);
+
+};
+
+typedef KSharedConfig::Ptr KSharedConfigPtr;
+
+#endif // multiple inclusion guard
diff --git a/tier1/kconfig/src/gui/CMakeLists.txt b/tier1/kconfig/src/gui/CMakeLists.txt
new file mode 100644
index 00000000..974b05cc
--- /dev/null
+++ b/tier1/kconfig/src/gui/CMakeLists.txt
@@ -0,0 +1,41 @@
+
+find_package(Qt5Widgets 5.2.0 REQUIRED NO_MODULE)
+find_package(Qt5Xml 5.2.0 REQUIRED NO_MODULE)
+
+set(libkconfiggui_SRCS
+ kconfiggui.cpp
+ kconfiggroupgui.cpp
+ kconfigloader.cpp
+ kconfigskeleton.cpp
+ kstandardshortcut.cpp
+ kwindowconfig.cpp
+)
+
+add_library(KF5ConfigGui ${libkconfiggui_SRCS})
+generate_export_header(KF5ConfigGui BASE_NAME KConfigGui)
+add_library(KF5::ConfigGui ALIAS KF5ConfigGui)
+
+target_link_libraries(KF5ConfigGui PUBLIC Qt5::Gui Qt5::Xml KF5::ConfigCore)
+
+if(IS_ABSOLUTE "${INCLUDE_INSTALL_DIR}")
+ target_include_directories(KF5ConfigGui INTERFACE "$<INSTALL_INTERFACE:${INCLUDE_INSTALL_DIR}>" )
+else()
+ target_include_directories(KF5ConfigGui INTERFACE "$<INSTALL_INTERFACE:${CMAKE_INSTALL_PREFIX}/${INCLUDE_INSTALL_DIR}>" )
+endif()
+
+set_target_properties(KF5ConfigGui PROPERTIES VERSION ${KCONFIG_VERSION_STRING}
+ SOVERSION ${KCONFIG_SOVERSION}
+ EXPORT_NAME ConfigGui
+)
+
+install(TARGETS KF5ConfigGui EXPORT KF5ConfigTargets ${INSTALL_TARGETS_DEFAULT_ARGS})
+
+install( FILES
+ ${CMAKE_CURRENT_BINARY_DIR}/kconfiggui_export.h
+ kconfiggui.h
+ kconfigloader.h
+ kconfigskeleton.h
+ kstandardshortcut.h
+ kwindowconfig.h
+ DESTINATION ${INCLUDE_INSTALL_DIR} COMPONENT Devel
+)
diff --git a/tier1/kconfig/src/gui/kconfiggroupgui.cpp b/tier1/kconfig/src/gui/kconfiggroupgui.cpp
new file mode 100644
index 00000000..22706e77
--- /dev/null
+++ b/tier1/kconfig/src/gui/kconfiggroupgui.cpp
@@ -0,0 +1,197 @@
+/*
+ This file is part of the KDE libraries
+ Copyright (c) 2007 Thiago Macieira <thiago@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <kconfiggroup.h>
+
+#include <QtCore/QMutableStringListIterator>
+#include <QColor>
+#include <QDebug>
+#include <QFont>
+
+#include <kconfiggroup_p.h>
+
+/**
+ * Try to read a GUI type from config group @p cg at key @p key.
+ * @p input is the default value and also indicates the type to be read.
+ * @p output is to be set with the value that has been read.
+ *
+ * @returns true if something was handled (even if output was set to clear or default)
+ * or false if nothing was handled (e.g., Core type)
+ */
+static bool readEntryGui(const QByteArray& data, const char* key, const QVariant &input,
+ QVariant &output)
+{
+ const QString errString = QString::fromLatin1("\"%1\" - conversion from \"%3\" to %2 failed")
+ .arg(QLatin1String(key))
+ .arg(QLatin1String(QVariant::typeToName(input.type())))
+ .arg(QLatin1String(data.constData()));
+ const QString formatError = QString::fromLatin1(" (wrong format: expected '%1' items, read '%2')");
+
+ // set in case of failure
+ output = input;
+
+ switch (input.type()) {
+ case QVariant::Color: {
+ if (data.isEmpty() || data == "invalid") {
+ output = QColor(); // return what was stored
+ return true;
+ } else if (data.at(0) == '#') {
+ QColor col;
+ col.setNamedColor(QString::fromUtf8(data.constData(), data.length()));
+ output = col;
+ return true;
+ } else if (!data.contains(',')) {
+ QColor col;
+ col.setNamedColor(QString::fromUtf8(data.constData(), data.length()));
+ if (!col.isValid())
+ qCritical() << qPrintable(errString);
+ output = col;
+ return true;
+ } else {
+ const QList<QByteArray> list = data.split(',');
+ const int count = list.count();
+
+ if (count != 3 && count != 4) {
+ qCritical() << qPrintable(errString) << qPrintable(formatError.arg(QLatin1String("3' or '4")).arg(count));
+ return true; // return default
+ }
+
+ int temp[4];
+ // bounds check components
+ for(int i = 0; i < count; i++) {
+ bool ok;
+ const int j = temp[i] = list.at(i).toInt(&ok);
+ if (!ok) { // failed to convert to int
+ qCritical() << qPrintable(errString) << " (integer conversion failed)";
+ return true; // return default
+ }
+ if (j < 0 || j > 255) {
+ static const char *const components[6] = {
+ "red", "green", "blue", "alpha"
+ };
+ const QString boundsError = QLatin1String(" (bounds error: %1 component %2)");
+ qCritical() << qPrintable(errString)
+ << qPrintable(boundsError.arg(QLatin1String(components[i])).arg(j < 0? QLatin1String("< 0"): QLatin1String("> 255")));
+ return true; // return default
+ }
+ }
+ QColor aColor(temp[0], temp[1], temp[2]);
+ if (count == 4)
+ aColor.setAlpha(temp[3]);
+
+ if (aColor.isValid())
+ output = aColor;
+ else
+ qCritical() << qPrintable(errString);
+ return true;
+ }
+ }
+
+ case QVariant::Font: {
+ QVariant tmp = QString::fromUtf8(data.constData(), data.length());
+ if (tmp.convert(QVariant::Font))
+ output = tmp;
+ else
+ qCritical() << qPrintable(errString);
+ return true;
+ }
+ case QVariant::Pixmap:
+ case QVariant::Image:
+ case QVariant::Brush:
+ case QVariant::Palette:
+ case QVariant::Icon:
+ case QVariant::Region:
+ case QVariant::Bitmap:
+ case QVariant::Cursor:
+ case QVariant::SizePolicy:
+ case QVariant::Pen:
+ // we may want to handle these in the future
+
+ default:
+ break;
+ }
+
+ return false; // not handled
+}
+
+/**
+ * Try to write a GUI type @p prop to config group @p cg at key @p key.
+ *
+ * @returns true if something was handled (even if an empty value was written)
+ * or false if nothing was handled (e.g., Core type)
+ */
+static bool writeEntryGui(KConfigGroup *cg, const char* key, const QVariant &prop,
+ KConfigGroup::WriteConfigFlags pFlags)
+{
+ switch (prop.type()) {
+ case QVariant::Color: {
+ const QColor rColor = prop.value<QColor>();
+
+ if (!rColor.isValid()) {
+ cg->writeEntry(key, "invalid", pFlags);
+ return true;
+ }
+
+ QList<int> list;
+ list.insert(0, rColor.red());
+ list.insert(1, rColor.green());
+ list.insert(2, rColor.blue());
+ if (rColor.alpha() != 255)
+ list.insert(3, rColor.alpha());
+
+ cg->writeEntry( key, list, pFlags );
+ return true;
+ }
+ case QVariant::Font:
+ cg->writeEntry( key, prop.toString().toUtf8(), pFlags );
+ return true;
+
+ case QVariant::Pixmap:
+ case QVariant::Image:
+ case QVariant::Brush:
+ case QVariant::Palette:
+ case QVariant::Icon:
+ case QVariant::Region:
+ case QVariant::Bitmap:
+ case QVariant::Cursor:
+ case QVariant::SizePolicy:
+ case QVariant::Pen:
+ // we may want to handle one of these in the future
+ break;
+
+ default:
+ break;
+ }
+
+ return false;
+}
+
+static int initKConfigGroupGui()
+{
+ _kde_internal_KConfigGroupGui.readEntryGui = readEntryGui;
+ _kde_internal_KConfigGroupGui.writeEntryGui = writeEntryGui;
+ return 42; // because 42 is nicer than 1 or 0
+}
+
+#ifdef Q_CONSTRUCTOR_FUNCTION
+Q_CONSTRUCTOR_FUNCTION(initKConfigGroupGui)
+#else
+static int dummyKConfigGroupGui = initKConfigGroupGui();
+#endif
diff --git a/tier1/kconfig/src/gui/kconfiggui.cpp b/tier1/kconfig/src/gui/kconfiggui.cpp
new file mode 100644
index 00000000..88da6b56
--- /dev/null
+++ b/tier1/kconfig/src/gui/kconfiggui.cpp
@@ -0,0 +1,51 @@
+/*
+ This file is part of the KDE libraries
+ Copyright (c) 1999 Matthias Ettrich <ettrich@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "kconfiggui.h"
+
+#include <QGuiApplication>
+
+#include <kconfig.h>
+
+static KConfig* s_sessionConfig = 0;
+
+KConfig* KConfigGui::sessionConfig()
+{
+ if (!s_sessionConfig) // create an instance specific config object
+ s_sessionConfig = new KConfig( sessionConfigName(), KConfig::SimpleConfig );
+ return s_sessionConfig;
+}
+
+bool KConfigGui::hasSessionConfig()
+{
+ return s_sessionConfig != 0;
+}
+
+QString KConfigGui::sessionConfigName()
+{
+#ifdef QT_NO_SESSIONMANAGER
+#error QT_NO_SESSIONMANAGER was set, this will not compile. Reconfigure Qt with Session management support.
+#endif
+ const QString sessionKey = qApp->sessionKey();
+ const QString sessionId = qApp->sessionId();
+ return QString(QLatin1String("session/%1_%2_%3")).arg(QGuiApplication::applicationName()).arg(sessionId).arg(sessionKey);
+}
+
diff --git a/tier1/kconfig/src/gui/kconfiggui.h b/tier1/kconfig/src/gui/kconfiggui.h
new file mode 100644
index 00000000..4e2313f3
--- /dev/null
+++ b/tier1/kconfig/src/gui/kconfiggui.h
@@ -0,0 +1,58 @@
+/*
+ This file is part of the KDE libraries
+ Copyright (c) 1999 Matthias Ettrich <ettrich@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef KCONFIGGUI_H
+#define KCONFIGGUI_H
+
+#include <kconfiggui_export.h>
+
+#include <QString>
+
+class KConfig;
+
+namespace KConfigGui
+{
+ /**
+ * Returns the application session config object.
+ *
+ * @return A pointer to the application's instance specific
+ * KConfig object.
+ * @see KConfig
+ */
+ KCONFIGGUI_EXPORT KConfig* sessionConfig();
+
+ /**
+ * Indicates if a session config has been created for that application
+ * (ie. if sessionConfig() got called at least once)
+ *
+ * @return true if a sessionConfig object was created, false otherwise
+ */
+ KCONFIGGUI_EXPORT bool hasSessionConfig();
+
+ /**
+ * Returns the name of the application session
+ *
+ * @return the application session name
+ */
+ KCONFIGGUI_EXPORT QString sessionConfigName();
+}
+
+#endif // KCONFIGGUI_H
diff --git a/tier1/kconfig/src/gui/kconfigloader.cpp b/tier1/kconfig/src/gui/kconfigloader.cpp
new file mode 100644
index 00000000..150c6b69
--- /dev/null
+++ b/tier1/kconfig/src/gui/kconfigloader.cpp
@@ -0,0 +1,442 @@
+/*
+ * Copyright 2007 Aaron Seigo <aseigo@kde.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "kconfigloader.h"
+#include "kconfigloader_p.h"
+#include "kconfigloaderhandler_p.h"
+
+#include <QColor>
+#include <QFont>
+#include <QHash>
+#include <QXmlContentHandler>
+#include <QXmlInputSource>
+#include <QXmlSimpleReader>
+#include <QUrl>
+
+#include <QDebug>
+
+void ConfigLoaderPrivate::parse(KConfigLoader *loader, QIODevice *xml)
+{
+ clearData();
+ loader->clearItems();
+
+ if (xml) {
+ QXmlInputSource source(xml);
+ QXmlSimpleReader reader;
+ ConfigLoaderHandler handler(loader, this);
+ reader.setContentHandler(&handler);
+ reader.parse(&source, false);
+ }
+}
+
+ConfigLoaderHandler::ConfigLoaderHandler(KConfigLoader *config, ConfigLoaderPrivate *d)
+ : QXmlDefaultHandler(),
+ m_config(config),
+ d(d)
+{
+ resetState();
+}
+
+bool ConfigLoaderHandler::startElement(const QString &namespaceURI, const QString &localName,
+ const QString &qName, const QXmlAttributes &attrs)
+{
+ Q_UNUSED(namespaceURI)
+ Q_UNUSED(qName)
+
+// qDebug() << "ConfigLoaderHandler::startElement(" << localName << qName;
+ int numAttrs = attrs.count();
+ QString tag = localName.toLower();
+ if (tag == QStringLiteral("group")) {
+ QString group;
+ for (int i = 0; i < numAttrs; ++i) {
+ QString name = attrs.localName(i).toLower();
+ if (name == QStringLiteral("name")) {
+ //qDebug() << "set group to" << attrs.value(i);
+ group = attrs.value(i);
+ }
+ }
+ if (group.isEmpty()) {
+ group = d->baseGroup;
+ } else {
+ d->groups.append(group);
+ if (!d->baseGroup.isEmpty()) {
+ group = d->baseGroup + QStringLiteral("\x1d") + group;
+ }
+ }
+ m_currentGroup = group;
+ if (m_config) {
+ m_config->setCurrentGroup(group);
+ }
+ } else if (tag == QStringLiteral("entry")) {
+ for (int i = 0; i < numAttrs; ++i) {
+ QString name = attrs.localName(i).toLower();
+ if (name == QStringLiteral("name")) {
+ m_name = attrs.value(i).trimmed();
+ } else if (name == QStringLiteral("type")) {
+ m_type = attrs.value(i).toLower();
+ } else if (name == QStringLiteral("key")) {
+ m_key = attrs.value(i).trimmed();
+ }
+ }
+ } else if (tag == QStringLiteral("choice")) {
+ m_choice.name.clear();
+ m_choice.label.clear();
+ m_choice.whatsThis.clear();
+ for (int i = 0; i < numAttrs; ++i) {
+ QString name = attrs.localName(i).toLower();
+ if (name == QStringLiteral("name")) {
+ m_choice.name = attrs.value(i);
+ }
+ }
+ m_inChoice = true;
+ }
+
+ return true;
+}
+
+bool ConfigLoaderHandler::characters(const QString &ch)
+{
+ m_cdata.append(ch);
+ return true;
+}
+
+QString ConfigLoaderHandler::name() const
+{
+ return m_name;
+}
+
+void ConfigLoaderHandler::setName(const QString &name)
+{
+ m_name = name;
+}
+
+QString ConfigLoaderHandler::key() const
+{
+ return m_key;
+}
+
+void ConfigLoaderHandler::setKey(const QString &key)
+{
+ m_key = key;
+}
+
+QString ConfigLoaderHandler::type() const
+{
+ return m_type;
+}
+
+QString ConfigLoaderHandler::currentGroup() const
+{
+ return m_currentGroup;
+}
+
+QString ConfigLoaderHandler::defaultValue() const
+{
+ return m_default;
+}
+
+bool ConfigLoaderHandler::endElement(const QString &namespaceURI,
+ const QString &localName, const QString &qName)
+{
+ Q_UNUSED(namespaceURI)
+ Q_UNUSED(qName)
+
+// qDebug() << "ConfigLoaderHandler::endElement(" << localName << qName;
+ const QString tag = localName.toLower();
+ if (tag == QStringLiteral("entry")) {
+ addItem();
+ resetState();
+ } else if (tag == QStringLiteral("label")) {
+ if (m_inChoice) {
+ m_choice.label = m_cdata.trimmed();
+ } else {
+ m_label = m_cdata.trimmed();
+ }
+ } else if (tag == QStringLiteral("whatsthis")) {
+ if (m_inChoice) {
+ m_choice.whatsThis = m_cdata.trimmed();
+ } else {
+ m_whatsThis = m_cdata.trimmed();
+ }
+ } else if (tag == QStringLiteral("default")) {
+ m_default = m_cdata.trimmed();
+ } else if (tag == QStringLiteral("min")) {
+ m_min = m_cdata.toInt(&m_haveMin);
+ } else if (tag == QStringLiteral("max")) {
+ m_max = m_cdata.toInt(&m_haveMax);
+ } else if (tag == QStringLiteral("choice")) {
+ m_enumChoices.append(m_choice);
+ m_inChoice = false;
+ }
+
+ m_cdata.clear();
+ return true;
+}
+
+void ConfigLoaderHandler::addItem()
+{
+ if (m_name.isEmpty()) {
+ if (m_key.isEmpty()) {
+ return;
+ }
+
+ m_name = m_key;
+ }
+
+ m_name.remove(QStringLiteral(" "));
+
+ KConfigSkeletonItem *item = 0;
+
+ if (m_type == QStringLiteral("bool")) {
+ bool defaultValue = m_default.toLower() == QStringLiteral("true");
+ item = m_config->addItemBool(m_name, *d->newBool(), defaultValue, m_key);
+ } else if (m_type == QStringLiteral("color")) {
+ item = m_config->addItemColor(m_name, *d->newColor(), QColor(m_default), m_key);
+ } else if (m_type == QStringLiteral("datetime")) {
+ item = m_config->addItemDateTime(m_name, *d->newDateTime(),
+ QDateTime::fromString(m_default), m_key);
+ } else if (m_type == QStringLiteral("enum")) {
+ m_key = (m_key.isEmpty()) ? m_name : m_key;
+ KConfigSkeleton::ItemEnum *enumItem =
+ new KConfigSkeleton::ItemEnum(m_config->currentGroup(),
+ m_key, *d->newInt(),
+ m_enumChoices,
+ m_default.toUInt());
+ m_config->addItem(enumItem, m_name);
+ item = enumItem;
+ } else if (m_type == QStringLiteral("font")) {
+ item = m_config->addItemFont(m_name, *d->newFont(), QFont(m_default), m_key);
+ } else if (m_type == QStringLiteral("int")) {
+ KConfigSkeleton::ItemInt *intItem = m_config->addItemInt(m_name, *d->newInt(),
+ m_default.toInt(), m_key);
+
+ if (m_haveMin) {
+ intItem->setMinValue(m_min);
+ }
+
+ if (m_haveMax) {
+ intItem->setMaxValue(m_max);
+ }
+
+ item = intItem;
+ } else if (m_type == QStringLiteral("password")) {
+ item = m_config->addItemPassword(m_name, *d->newString(), m_default, m_key);
+ } else if (m_type == QStringLiteral("path")) {
+ item = m_config->addItemPath(m_name, *d->newString(), m_default, m_key);
+ } else if (m_type == QStringLiteral("string")) {
+ item = m_config->addItemString(m_name, *d->newString(), m_default, m_key);
+ } else if (m_type == QStringLiteral("stringlist")) {
+ //FIXME: the split() is naive and will break on lists with ,'s in them
+ item = m_config->addItemStringList(m_name, *d->newStringList(),
+ m_default.split(QStringLiteral(",")), m_key);
+ } else if (m_type == QStringLiteral("uint")) {
+ KConfigSkeleton::ItemUInt *uintItem =
+ m_config->addItemUInt(m_name, *d->newUint(), m_default.toUInt(), m_key);
+ if (m_haveMin) {
+ uintItem->setMinValue(m_min);
+ }
+ if (m_haveMax) {
+ uintItem->setMaxValue(m_max);
+ }
+ item = uintItem;
+ } else if (m_type == QStringLiteral("url")) {
+ m_key = (m_key.isEmpty()) ? m_name : m_key;
+ KConfigSkeleton::ItemUrl *urlItem =
+ new KConfigSkeleton::ItemUrl(m_config->currentGroup(),
+ m_key, *d->newUrl(),
+ QUrl::fromUserInput(m_default));
+ m_config->addItem(urlItem, m_name);
+ item = urlItem;
+ } else if (m_type == QStringLiteral("double")) {
+ KConfigSkeleton::ItemDouble *doubleItem = m_config->addItemDouble(m_name,
+ *d->newDouble(), m_default.toDouble(), m_key);
+ if (m_haveMin) {
+ doubleItem->setMinValue(m_min);
+ }
+ if (m_haveMax) {
+ doubleItem->setMaxValue(m_max);
+ }
+ item = doubleItem;
+ } else if (m_type == QStringLiteral("intlist")) {
+ QStringList tmpList = m_default.split(QStringLiteral(","));
+ QList<int> defaultList;
+ foreach (const QString &tmp, tmpList) {
+ defaultList.append(tmp.toInt());
+ }
+ item = m_config->addItemIntList(m_name, *d->newIntList(), defaultList, m_key);
+ } else if (m_type == QStringLiteral("longlong")) {
+ KConfigSkeleton::ItemLongLong *longlongItem = m_config->addItemLongLong(m_name,
+ *d->newLongLong(), m_default.toLongLong(), m_key);
+ if (m_haveMin) {
+ longlongItem->setMinValue(m_min);
+ }
+ if (m_haveMax) {
+ longlongItem->setMaxValue(m_max);
+ }
+ item = longlongItem;
+ /* No addItemPathList in KConfigSkeleton ?
+ } else if (m_type == "PathList") {
+ //FIXME: the split() is naive and will break on lists with ,'s in them
+ item = m_config->addItemPathList(m_name, *d->newStringList(), m_default.split(","), m_key);
+ */
+ } else if (m_type == QStringLiteral("point")) {
+ QPoint defaultPoint;
+ QStringList tmpList = m_default.split(QStringLiteral(","));
+ if (tmpList.size() >= 2) {
+ defaultPoint.setX(tmpList[0].toInt());
+ defaultPoint.setY(tmpList[1].toInt());
+ }
+ item = m_config->addItemPoint(m_name, *d->newPoint(), defaultPoint, m_key);
+ } else if (m_type == QStringLiteral("rect")) {
+ QRect defaultRect;
+ QStringList tmpList = m_default.split(QStringLiteral(","));
+ if (tmpList.size() >= 4) {
+ defaultRect.setCoords(tmpList[0].toInt(), tmpList[1].toInt(),
+ tmpList[2].toInt(), tmpList[3].toInt());
+ }
+ item = m_config->addItemRect(m_name, *d->newRect(), defaultRect, m_key);
+ } else if (m_type == QStringLiteral("size")) {
+ QSize defaultSize;
+ QStringList tmpList = m_default.split(QStringLiteral(","));
+ if (tmpList.size() >= 2) {
+ defaultSize.setWidth(tmpList[0].toInt());
+ defaultSize.setHeight(tmpList[1].toInt());
+ }
+ item = m_config->addItemSize(m_name, *d->newSize(), defaultSize, m_key);
+ } else if (m_type == QStringLiteral("ulonglong")) {
+ KConfigSkeleton::ItemULongLong *ulonglongItem =
+ m_config->addItemULongLong(m_name, *d->newULongLong(), m_default.toULongLong(), m_key);
+ if (m_haveMin) {
+ ulonglongItem->setMinValue(m_min);
+ }
+ if (m_haveMax) {
+ ulonglongItem->setMaxValue(m_max);
+ }
+ item = ulonglongItem;
+ /* No addItemUrlList in KConfigSkeleton ?
+ } else if (m_type == "urllist") {
+ //FIXME: the split() is naive and will break on lists with ,'s in them
+ QStringList tmpList = m_default.split(",");
+ QList<QUrl> defaultList;
+ foreach (const QString& tmp, tmpList) {
+ defaultList.append(QUrl(tmp));
+ }
+ item = m_config->addItemUrlList(m_name, *d->newUrlList(), defaultList, m_key);*/
+ }
+
+ if (item) {
+ item->setLabel(m_label);
+ item->setWhatsThis(m_whatsThis);
+ d->keysToNames.insert(item->group() + item->key(), item->name());
+ }
+}
+
+void ConfigLoaderHandler::resetState()
+{
+ m_haveMin = false;
+ m_min = 0;
+ m_haveMax = false;
+ m_max = 0;
+ m_name.clear();
+ m_type.clear();
+ m_label.clear();
+ m_default.clear();
+ m_key.clear();
+ m_whatsThis.clear();
+ m_enumChoices.clear();
+ m_inChoice = false;
+}
+
+KConfigLoader::KConfigLoader(const QString &configFile, QIODevice *xml, QObject *parent)
+ : KConfigSkeleton(configFile, parent),
+ d(new ConfigLoaderPrivate)
+{
+ d->parse(this, xml);
+}
+
+KConfigLoader::KConfigLoader(KSharedConfigPtr config, QIODevice *xml, QObject *parent)
+ : KConfigSkeleton(config, parent),
+ d(new ConfigLoaderPrivate)
+{
+ d->parse(this, xml);
+}
+
+//FIXME: obviously this is broken and should be using the group as the root,
+// but KConfigSkeleton does not currently support this. it will eventually though,
+// at which point this can be addressed properly
+KConfigLoader::KConfigLoader(const KConfigGroup &config, QIODevice *xml, QObject *parent)
+ : KConfigSkeleton(KSharedConfig::openConfig(config.config()->name()), parent),
+ d(new ConfigLoaderPrivate)
+{
+ KConfigGroup group = config.parent();
+ d->baseGroup = config.name();
+ while (group.isValid() && group.name() != QStringLiteral("<default>")) {
+ d->baseGroup = group.name() + QStringLiteral("\x1d") + d->baseGroup;
+ group = group.parent();
+ }
+ d->parse(this, xml);
+}
+
+KConfigLoader::~KConfigLoader()
+{
+ delete d;
+}
+
+KConfigSkeletonItem *KConfigLoader::findItem(const QString &group, const QString &key) const
+{
+ return KConfigSkeleton::findItem(d->keysToNames[group + key]);
+}
+
+KConfigSkeletonItem *KConfigLoader::findItemByName(const QString &name) const
+{
+ return KConfigSkeleton::findItem(name);
+}
+
+QVariant KConfigLoader::property(const QString &name) const
+{
+ KConfigSkeletonItem *item = KConfigSkeleton::findItem(name);
+
+ if (item) {
+ return item->property();
+ }
+
+ return QVariant();
+}
+
+bool KConfigLoader::hasGroup(const QString &group) const
+{
+ return d->groups.contains(group);
+}
+
+QStringList KConfigLoader::groupList() const
+{
+ return d->groups;
+}
+
+bool KConfigLoader::usrWriteConfig()
+{
+ if (d->saveDefaults) {
+ KConfigSkeletonItem::List itemList = items();
+ for(int i = 0; i < itemList.size(); i++) {
+ KConfigGroup cg(config(), itemList.at(i)->group());
+ cg.writeEntry(itemList.at(i)->key(), "");
+ }
+ }
+ return true;
+}
diff --git a/tier1/kconfig/src/gui/kconfigloader.h b/tier1/kconfig/src/gui/kconfigloader.h
new file mode 100644
index 00000000..df38ce79
--- /dev/null
+++ b/tier1/kconfig/src/gui/kconfigloader.h
@@ -0,0 +1,176 @@
+/*
+ * Copyright 2007 Aaron Seigo <aseigo@kde.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef KCONFIGLOADER_H
+#define KCONFIGLOADER_H
+
+#include <kconfiggroup.h>
+#include <kconfigskeleton.h>
+#include <ksharedconfig.h>
+
+#include <kconfiggui_export.h>
+
+class ConfigLoaderPrivate;
+
+/**
+ * @class KConfigLoader kconfigloader.h <KConfigLoader>
+ *
+ * @short A KConfigSkeleton that populates itself based on KConfigXT XML
+ *
+ * This class allows one to ship an XML file and reconstitute it into a
+ * KConfigSkeleton object at runtime. Common usage might look like this:
+ *
+ * \code
+ * QFile file(xmlFilePath);
+ * KConfigLoader appletConfig(configFilePath, &file);
+ * \endcode
+ *
+ * Alternatively, any QIODevice may be used in place of QFile in the
+ * example above.
+ *
+ * KConfigLoader is useful if it is not possible to use compiled code
+ * and by that the kconfig compiler cannot be used. Common examples are
+ * scripted plugins which want to provide a configuration interface.
+ * With the help of KConfigLoader a dynamically loaded ui file can be
+ * populated with the stored values and also stored back to the config
+ * file.
+ *
+ * An example for populating a QDialog with a dynamically populated UI
+ * with the help of a KConfigDialogManager:
+ * \code
+ * QDialog *dialog = new QDialog();
+ * QFile xmlFile("path/to/kconfigxt.xml");
+ * KConfigGroup cg = KSharedConfig::openConfig()->group(QString());
+ * KConfigLoader *configLoader = new KConfigLoader(cg, &xmlFile, this);
+ *
+ * // load the ui file
+ * QUiLoader *loader = new QUiLoader(this);
+ * QFile uiFile("path/to/userinterface.ui");
+ * uiFile.open(QFile::ReadOnly);
+ * QWidget *customConfigForm = loader->load(&uiFile, dialog);
+ * uiFile.close();
+ *
+ * KConfigDialogManager *manager = new KConfigDialogManager(customConfigForm, configLoader);
+ * if (dialog->exec() == QDialog::Accepted) {
+ * manager->updateSettings();
+ * }
+ * \endcode
+ *
+ * Currently the following data types are supported:
+ *
+ * @li bools
+ * @li colors
+ * @li datetimes
+ * @li enumerations
+ * @li fonts
+ * @li ints
+ * @li passwords
+ * @li paths
+ * @li strings
+ * @li stringlists
+ * @li uints
+ * @li urls
+ * @li doubles
+ * @li int lists
+ * @li longlongs
+ * @li path lists
+ * @li points
+ * @li rects
+ * @li sizes
+ * @li ulonglongs
+ * @li url lists
+ **/
+class KCONFIGGUI_EXPORT KConfigLoader : public KConfigSkeleton
+{
+public:
+ /**
+ * Creates a KConfigSkeleton populated using the definition found in
+ * the XML data passed in.
+ *
+ * @param configFile path to the configuration file to use
+ * @param xml the xml data; must be valid KConfigXT data
+ * @param parent optional QObject parent
+ **/
+ KConfigLoader(const QString &configFile, QIODevice *xml, QObject *parent = 0);
+
+ /**
+ * Creates a KConfigSkeleton populated using the definition found in
+ * the XML data passed in.
+ *
+ * @param config the configuration object to use
+ * @param xml the xml data; must be valid KConfigXT data
+ * @param parent optional QObject parent
+ **/
+ KConfigLoader(KSharedConfigPtr config, QIODevice *xml, QObject *parent = 0);
+
+ /**
+ * Creates a KConfigSkeleton populated using the definition found in
+ * the XML data passed in.
+ *
+ * @param config the group to use as the root for configuration items
+ * @param xml the xml data; must be valid KConfigXT data
+ * @param parent optional QObject parent
+ **/
+ KConfigLoader(const KConfigGroup &config, QIODevice *xml, QObject *parent = 0);
+
+ ~KConfigLoader();
+
+ /**
+ * Finds the item for the given group and key.
+ *
+ * @param group the group in the config file to look in
+ * @param key the configuration key to find
+ * @return the associated KConfigSkeletonItem, or 0 if none
+ */
+ KConfigSkeletonItem *findItem(const QString &group, const QString &key) const;
+
+ /**
+ * Finds an item by its name
+ */
+ KConfigSkeletonItem *findItemByName(const QString &name) const;
+
+ /**
+ * Returns the property (variantized value) of the named item
+ */
+ QVariant property(const QString &name) const;
+
+ /**
+ * Check to see if a group exists
+ *
+ * @param group the name of the group to check for
+ * @return true if the group exists, or false if it does not
+ */
+ bool hasGroup(const QString &group) const;
+
+ /**
+ * @return the list of groups defined by the XML
+ */
+ QStringList groupList() const;
+
+protected:
+ /**
+ * Hack used to force writing when no default exists in config file.
+ */
+ bool usrWriteConfig();
+
+private:
+ ConfigLoaderPrivate * const d;
+};
+
+#endif //multiple inclusion guard
diff --git a/tier1/kconfig/src/gui/kconfigloader_p.h b/tier1/kconfig/src/gui/kconfigloader_p.h
new file mode 100644
index 00000000..f9aa9191
--- /dev/null
+++ b/tier1/kconfig/src/gui/kconfigloader_p.h
@@ -0,0 +1,222 @@
+/*
+ * Copyright 2007-2008 Aaron Seigo <aseigo@kde.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef KCONFIGLOADER_P_H
+#define KCONFIGLOADER_P_H
+
+#include <QUrl>
+
+class ConfigLoaderPrivate
+{
+ public:
+ ConfigLoaderPrivate()
+ : saveDefaults(false)
+ {
+ }
+
+ ~ConfigLoaderPrivate()
+ {
+ clearData();
+ }
+
+ void clearData()
+ {
+ qDeleteAll(bools);
+ qDeleteAll(strings);
+ qDeleteAll(stringlists);
+ qDeleteAll(colors);
+ qDeleteAll(fonts);
+ qDeleteAll(ints);
+ qDeleteAll(uints);
+ qDeleteAll(urls);
+ qDeleteAll(dateTimes);
+ qDeleteAll(doubles);
+ qDeleteAll(intlists);
+ qDeleteAll(longlongs);
+ qDeleteAll(points);
+ qDeleteAll(rects);
+ qDeleteAll(sizes);
+ qDeleteAll(ulonglongs);
+ qDeleteAll(urllists);
+ }
+
+ bool *newBool()
+ {
+ bool *v = new bool;
+ bools.append(v);
+ return v;
+ }
+
+ QString *newString()
+ {
+ QString *v = new QString;
+ strings.append(v);
+ return v;
+ }
+
+ QStringList *newStringList()
+ {
+ QStringList *v = new QStringList;
+ stringlists.append(v);
+ return v;
+ }
+
+ QColor *newColor()
+ {
+ QColor *v = new QColor;
+ colors.append(v);
+ return v;
+ }
+
+ QFont *newFont()
+ {
+ QFont *v = new QFont;
+ fonts.append(v);
+ return v;
+ }
+
+ qint32 *newInt()
+ {
+ qint32 *v = new qint32;
+ ints.append(v);
+ return v;
+ }
+
+ quint32 *newUint()
+ {
+ quint32 *v = new quint32;
+ uints.append(v);
+ return v;
+ }
+
+ QUrl *newUrl()
+ {
+ QUrl *v = new QUrl;
+ urls.append(v);
+ return v;
+ }
+
+ QDateTime *newDateTime()
+ {
+ QDateTime *v = new QDateTime;
+ dateTimes.append(v);
+ return v;
+ }
+
+ double *newDouble()
+ {
+ double *v = new double;
+ doubles.append(v);
+ return v;
+ }
+
+ QList<qint32>* newIntList()
+ {
+ QList<qint32> *v = new QList<qint32>;
+ intlists.append(v);
+ return v;
+ }
+
+ qint64 *newLongLong()
+ {
+ qint64 *v = new qint64;
+ longlongs.append(v);
+ return v;
+ }
+
+ QPoint *newPoint()
+ {
+ QPoint *v = new QPoint;
+ points.append(v);
+ return v;
+ }
+
+ QRect *newRect()
+ {
+ QRect *v = new QRect;
+ rects.append(v);
+ return v;
+ }
+
+ QSize *newSize()
+ {
+ QSize *v = new QSize;
+ sizes.append(v);
+ return v;
+ }
+
+ quint64 *newULongLong()
+ {
+ quint64 *v = new quint64;
+ ulonglongs.append(v);
+ return v;
+ }
+
+ QList<QUrl> *newUrlList()
+ {
+ QList<QUrl> *v = new QList<QUrl>();
+ urllists.append(v);
+ return v;
+ }
+
+ void parse(KConfigLoader *loader, QIODevice *xml);
+
+ /**
+ * Whether or not to write out default values.
+ *
+ * @param writeDefaults true if defaults should be written out
+ */
+ void setWriteDefaults(bool writeDefaults)
+ {
+ saveDefaults = writeDefaults;
+ }
+
+ /**
+ * @return true if default values will also be written out
+ */
+ bool writeDefaults() const
+ {
+ return saveDefaults;
+ }
+
+
+ QList<bool *> bools;
+ QList<QString *> strings;
+ QList<QStringList *> stringlists;
+ QList<QColor *> colors;
+ QList<QFont *> fonts;
+ QList<qint32 *> ints;
+ QList<quint32 *> uints;
+ QList<QUrl *> urls;
+ QList<QDateTime *> dateTimes;
+ QList<double *> doubles;
+ QList<QList<qint32> *> intlists;
+ QList<qint64 *> longlongs;
+ QList<QPoint *> points;
+ QList<QRect *> rects;
+ QList<QSize *> sizes;
+ QList<quint64 *> ulonglongs;
+ QList<QList<QUrl> *> urllists;
+ QString baseGroup;
+ QStringList groups;
+ QHash<QString, QString> keysToNames;
+ bool saveDefaults;
+};
+
+#endif
diff --git a/tier1/kconfig/src/gui/kconfigloaderhandler_p.h b/tier1/kconfig/src/gui/kconfigloaderhandler_p.h
new file mode 100644
index 00000000..f0766346
--- /dev/null
+++ b/tier1/kconfig/src/gui/kconfigloaderhandler_p.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2007-2008 Aaron Seigo <aseigo@kde.org>
+ * Copyright 2013 Marco Martin <mart@kde.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef KCONFIGLOADERHANDLER_P_H
+#define KCONFIGLOADERHANDLER_P_H
+
+#include <QXmlDefaultHandler>
+
+class ConfigLoaderHandler : public QXmlDefaultHandler
+{
+public:
+ ConfigLoaderHandler(KConfigLoader *config, ConfigLoaderPrivate *d);
+ bool startElement(const QString &namespaceURI, const QString &localName,
+ const QString &qName, const QXmlAttributes &atts);
+ bool endElement(const QString &namespaceURI, const QString &localName,
+ const QString &qName);
+ bool characters(const QString &ch);
+
+ QString name() const;
+ void setName(const QString &name);
+ QString key() const;
+ void setKey(const QString &name);
+ QString type() const;
+ QString currentGroup() const;
+ QString defaultValue() const;
+
+private:
+ virtual void addItem();
+ void resetState();
+
+ KConfigLoader *m_config;
+ ConfigLoaderPrivate *d;
+ int m_min;
+ int m_max;
+ QString m_currentGroup;
+ QString m_name;
+ QString m_key;
+ QString m_type;
+ QString m_label;
+ QString m_default;
+ QString m_cdata;
+ QString m_whatsThis;
+ KConfigSkeleton::ItemEnum::Choice m_choice;
+ QList<KConfigSkeleton::ItemEnum::Choice> m_enumChoices;
+ bool m_haveMin;
+ bool m_haveMax;
+ bool m_inChoice;
+};
+
+#endif
+
diff --git a/tier1/kconfig/src/gui/kconfigskeleton.cpp b/tier1/kconfig/src/gui/kconfigskeleton.cpp
new file mode 100644
index 00000000..7704d36e
--- /dev/null
+++ b/tier1/kconfig/src/gui/kconfigskeleton.cpp
@@ -0,0 +1,121 @@
+/*
+ This file is part of KOrganizer.
+ Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org>
+ Copyright (c) 2003 Waldo Bastian <bastian@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "kconfigskeleton.h"
+
+#include <kcoreconfigskeleton_p.h>
+
+KConfigSkeleton::KConfigSkeleton(const QString &configname, QObject* parent)
+ : KCoreConfigSkeleton(configname, parent)
+{
+}
+
+KConfigSkeleton::KConfigSkeleton(KSharedConfig::Ptr pConfig, QObject* parent)
+ : KCoreConfigSkeleton(pConfig, parent)
+{
+}
+
+
+KConfigSkeleton::ItemColor::ItemColor( const QString &_group, const QString &_key,
+ QColor &reference,
+ const QColor &defaultValue )
+ : KConfigSkeletonGenericItem<QColor>( _group, _key, reference, defaultValue )
+{
+}
+
+void KConfigSkeleton::ItemColor::readConfig( KConfig *config )
+{
+ KConfigGroup cg(config, mGroup );
+ mReference = cg.readEntry( mKey, mDefault );
+ mLoadedValue = mReference;
+
+ readImmutability( cg );
+}
+
+void KConfigSkeleton::ItemColor::setProperty(const QVariant & p)
+{
+ mReference = qvariant_cast<QColor>(p);
+}
+
+bool KConfigSkeleton::ItemColor::isEqual(const QVariant &v) const
+{
+ return mReference == qvariant_cast<QColor>(v);
+}
+
+QVariant KConfigSkeleton::ItemColor::property() const
+{
+ return QVariant(mReference);
+}
+
+
+KConfigSkeleton::ItemFont::ItemFont( const QString &_group, const QString &_key,
+ QFont &reference,
+ const QFont &defaultValue )
+ : KConfigSkeletonGenericItem<QFont>( _group, _key, reference, defaultValue )
+{
+}
+
+void KConfigSkeleton::ItemFont::readConfig( KConfig *config )
+{
+ KConfigGroup cg(config, mGroup );
+ mReference = cg.readEntry( mKey, mDefault );
+ mLoadedValue = mReference;
+
+ readImmutability( cg );
+}
+
+void KConfigSkeleton::ItemFont::setProperty(const QVariant & p)
+{
+ mReference = qvariant_cast<QFont>(p);
+}
+
+bool KConfigSkeleton::ItemFont::isEqual(const QVariant &v) const
+{
+ return mReference == qvariant_cast<QFont>(v);
+}
+
+QVariant KConfigSkeleton::ItemFont::property() const
+{
+ return QVariant(mReference);
+}
+
+
+KConfigSkeleton::ItemColor *KConfigSkeleton::addItemColor( const QString &name, QColor &reference,
+ const QColor &defaultValue, const QString &key )
+{
+ KConfigSkeleton::ItemColor *item;
+ item = new KConfigSkeleton::ItemColor( d->mCurrentGroup, key.isNull() ? name : key,
+ reference, defaultValue );
+ addItem( item, name );
+ return item;
+}
+
+KConfigSkeleton::ItemFont *KConfigSkeleton::addItemFont( const QString &name, QFont &reference,
+ const QFont &defaultValue, const QString &key )
+{
+ KConfigSkeleton::ItemFont *item;
+ item = new KConfigSkeleton::ItemFont( d->mCurrentGroup, key.isNull() ? name : key,
+ reference, defaultValue );
+ addItem( item, name );
+ return item;
+}
+
+
diff --git a/tier1/kconfig/src/gui/kconfigskeleton.h b/tier1/kconfig/src/gui/kconfigskeleton.h
new file mode 100644
index 00000000..e62e60b4
--- /dev/null
+++ b/tier1/kconfig/src/gui/kconfigskeleton.h
@@ -0,0 +1,140 @@
+/*
+ * This file is part of KDE.
+ *
+ * Copyright (c) 2001,2002,2003 Cornelius Schumacher <schumacher@kde.org>
+ * Copyright (c) 2003 Waldo Bastian <bastian@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef KCONFIGSKELETON_H
+#define KCONFIGSKELETON_H
+
+#include <kconfiggui_export.h>
+
+#include <kcoreconfigskeleton.h>
+
+#include <QColor>
+#include <QFont>
+
+/**
+ * @short Class for handling preferences settings for an application.
+ * @author Cornelius Schumacher
+ *
+ * This class extends KCoreConfigSkeleton by support for GUI types.
+ *
+ */
+class KCONFIGGUI_EXPORT KConfigSkeleton : public KCoreConfigSkeleton
+{
+ Q_OBJECT
+public:
+ /**
+ * Class for handling a color preferences item.
+ */
+ class KCONFIGGUI_EXPORT ItemColor:public KConfigSkeletonGenericItem < QColor >
+ {
+ public:
+ /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem */
+ ItemColor(const QString & _group, const QString & _key,
+ QColor & reference,
+ const QColor & defaultValue = QColor(128, 128, 128));
+
+ /** @copydoc KConfigSkeletonItem::readConfig(KConfig*) */
+ void readConfig(KConfig * config);
+
+ /** @copydoc KConfigSkeletonItem::setProperty(const QVariant&) */
+ void setProperty(const QVariant & p);
+
+ /** @copydoc KConfigSkeletonItem::isEqual(const QVariant &) */
+ bool isEqual(const QVariant &p) const;
+
+ /** @copydoc KConfigSkeletonItem::property() */
+ QVariant property() const;
+ };
+
+
+ /**
+ * Class for handling a font preferences item.
+ */
+ class KCONFIGGUI_EXPORT ItemFont:public KConfigSkeletonGenericItem < QFont >
+ {
+ public:
+ /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem */
+ ItemFont(const QString & _group, const QString & _key, QFont & reference,
+ const QFont & defaultValue = QFont());
+
+ /** @copydoc KConfigSkeletonItem::readConfig(KConfig*) */
+ void readConfig(KConfig * config);
+
+ /** @copydoc KConfigSkeletonItem::setProperty(const QVariant&) */
+ void setProperty(const QVariant & p);
+
+ /** @copydoc KConfigSkeletonItem::isEqual(const QVariant &) */
+ bool isEqual(const QVariant &p) const;
+
+ /** @copydoc KConfigSkeletonItem::property() */
+ QVariant property() const;
+ };
+
+public:
+ /**
+ * Constructor.
+ *
+ * @param configname name of config file. If no name is given, the default
+ * config file as returned by KSharedConfig::openConfig() is used.
+ */
+ explicit KConfigSkeleton(const QString & configname = QString(), QObject* parent = 0);
+
+ /**
+ * Constructor.
+ *
+ * @param config configuration object to use.
+ */
+ explicit KConfigSkeleton(KSharedConfig::Ptr config, QObject* parent = 0);
+
+ /**
+ * Register an item of type QColor.
+ *
+ * @param name Name used to identify this setting. Names must be unique.
+ * @param reference Pointer to the variable, which is set by readConfig()
+ * calls and read by writeConfig() calls.
+ * @param defaultValue Default value, which is used when the config file
+ * does not yet contain the key of this item.
+ * @param key Key used in config file. If key is null, name is used as key.
+ * @return The created item
+ */
+ ItemColor *addItemColor(const QString & name, QColor & reference,
+ const QColor & defaultValue = QColor(128, 128, 128),
+ const QString & key = QString());
+
+ /**
+ * Register an item of type QFont.
+ *
+ * @param name Name used to identify this setting. Names must be unique.
+ * @param reference Pointer to the variable, which is set by readConfig()
+ * calls and read by writeConfig() calls.
+ * @param defaultValue Default value, which is used when the config file
+ * does not yet contain the key of this item.
+ * @param key Key used in config file. If key is null, name is used as key.
+ * @return The created item
+ */
+ ItemFont *addItemFont(const QString & name, QFont & reference,
+ const QFont & defaultValue = QFont(),
+ const QString & key = QString());
+
+};
+
+#endif
diff --git a/tier1/kconfig/src/gui/kstandardshortcut.cpp b/tier1/kconfig/src/gui/kstandardshortcut.cpp
new file mode 100644
index 00000000..a377ff0f
--- /dev/null
+++ b/tier1/kconfig/src/gui/kstandardshortcut.cpp
@@ -0,0 +1,377 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1997 Stefan Taferner (taferner@alpin.or.at)
+ Copyright (C) 2000 Nicolas Hadacek (haadcek@kde.org)
+ Copyright (C) 2001,2002 Ellis Whitehead (ellis@kde.org)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "kstandardshortcut.h"
+
+#include "kconfig.h"
+#include "ksharedconfig.h"
+#include <kconfiggroup.h>
+
+#include <QCoreApplication>
+#include <QDebug>
+#include <QKeySequence>
+
+namespace KStandardShortcut
+{
+
+struct KStandardShortcutInfo
+{
+ //! The standard shortcut id. @see StandardShortcut
+ StandardShortcut id;
+
+ /**
+ * Unique name for the given accel. The name is used to save the user
+ * settings. It's not representable. Use description for that.
+ * @warning NEVER EVER CHANGE IT OR TRANSLATE IT!
+ */
+ const char* name;
+
+ //! Context for the translation
+ const char* translation_context;
+
+ //! Localized label for user-visible display
+ const char* description;
+
+ //! The keys for this shortcut
+ int cutDefault, cutDefault2;
+
+ //! A shortcut that is created with @a cutDefault and @cutDefault2
+ QList<QKeySequence> cut;
+
+ //! If this struct is initialized. If not initialized @cut is not valid
+ bool isInitialized;
+};
+
+//! We need to remember the context to get the correct translation.
+#undef I18N_NOOP2
+#define I18N_NOOP2(comment,x) comment, x
+
+#define CTRL(x) Qt::CTRL+Qt::Key_##x
+#define SHIFT(x) Qt::SHIFT+Qt::Key_##x
+#define CTRLSHIFT(x) Qt::CTRL+Qt::SHIFT+Qt::Key_##x
+#define ALT(x) Qt::ALT+Qt::Key_##x
+#define ALTSHIFT(x) Qt::ALT+Qt::SHIFT+Qt::Key_##x
+
+/** Array of predefined KStandardShortcutInfo objects, which cover all
+ the "standard" accelerators. Each enum value from StandardShortcut
+ should appear in this table.
+*/
+// STUFF WILL BREAK IF YOU DON'T READ THIS!!!
+// Read the comments of the big enum in kstandardshortcut.h before you change anything!
+static KStandardShortcutInfo g_infoStandardShortcut[] =
+{
+//Group File,
+ {AccelNone, 0 , 0 , 0 , 0 , 0 , QList<QKeySequence>(), false },
+ { Open , "Open" , I18N_NOOP2("@action", "Open") , CTRL(O), 0 , QList<QKeySequence>(), false } ,
+ { New , "New" , I18N_NOOP2("@action", "New") , CTRL(N), 0 , QList<QKeySequence>(), false } ,
+ { Close , "Close", I18N_NOOP2("@action", "Close"), CTRL(W), CTRL(Escape), QList<QKeySequence>(), false } ,
+ { Save , "Save" , I18N_NOOP2("@action", "Save") , CTRL(S), 0 , QList<QKeySequence>(), false } ,
+ { Print , "Print", I18N_NOOP2("@action", "Print"), CTRL(P), 0 , QList<QKeySequence>(), false } ,
+ { Quit , "Quit" , I18N_NOOP2("@action", "Quit") , CTRL(Q), 0 , QList<QKeySequence>(), false } ,
+
+//Group Edit
+ { Undo , "Undo" , I18N_NOOP2("@action", "Undo") , CTRL(Z) , 0 , QList<QKeySequence>(), false },
+ { Redo , "Redo" , I18N_NOOP2("@action", "Redo") , CTRLSHIFT(Z) , 0 , QList<QKeySequence>(), false },
+ { Cut , "Cut" , I18N_NOOP2("@action", "Cut") , CTRL(X) , SHIFT(Delete), QList<QKeySequence>(), false },
+ { Copy , "Copy" , I18N_NOOP2("@action", "Copy") , CTRL(C) , CTRL(Insert) , QList<QKeySequence>(), false },
+ { Paste , "Paste" , I18N_NOOP2("@action", "Paste") , CTRL(V) , SHIFT(Insert), QList<QKeySequence>(), false },
+ { PasteSelection , "Paste Selection" , I18N_NOOP2("@action", "Paste Selection") , CTRLSHIFT(Insert), 0 , QList<QKeySequence>(), false },
+
+ { SelectAll , "SelectAll" , I18N_NOOP2("@action", "Select All") , CTRL(A) , 0 , QList<QKeySequence>(), false },
+ { Deselect , "Deselect" , I18N_NOOP2("@action", "Deselect") , CTRLSHIFT(A) , 0 , QList<QKeySequence>(), false },
+ { DeleteWordBack , "DeleteWordBack" , I18N_NOOP2("@action", "Delete Word Backwards"), CTRL(Backspace) , 0 , QList<QKeySequence>(), false },
+ { DeleteWordForward, "DeleteWordForward", I18N_NOOP2("@action", "Delete Word Forward") , CTRL(Delete) , 0 , QList<QKeySequence>(), false },
+
+ { Find , "Find" , I18N_NOOP2("@action", "Find") , CTRL(F) , 0 , QList<QKeySequence>(), false },
+ { FindNext , "FindNext" , I18N_NOOP2("@action", "Find Next") , Qt::Key_F3 , 0 , QList<QKeySequence>(), false },
+ { FindPrev , "FindPrev" , I18N_NOOP2("@action", "Find Prev") , SHIFT(F3) , 0 , QList<QKeySequence>(), false },
+ { Replace , "Replace" , I18N_NOOP2("@action", "Replace") , CTRL(R) , 0 , QList<QKeySequence>(), false },
+
+//Group Navigation
+ { Home , "Home" , I18N_NOOP2("@action Go to main page" , "Home") , ALT(Home) , Qt::Key_HomePage , QList<QKeySequence>(), false },
+ { Begin , "Begin" , I18N_NOOP2("@action Beginning of document", "Begin") , CTRL(Home) , 0 , QList<QKeySequence>(), false },
+ { End , "End" , I18N_NOOP2("@action End of document" , "End") , CTRL(End) , 0 , QList<QKeySequence>(), false },
+ { Prior , "Prior" , I18N_NOOP2("@action" , "Prior") , Qt::Key_PageUp , 0 , QList<QKeySequence>(), false },
+ { Next , "Next" , I18N_NOOP2("@action Opposite to Prior" , "Next") , Qt::Key_PageDown, 0 , QList<QKeySequence>(), false },
+
+ { Up , "Up" , I18N_NOOP2("@action" , "Up") , ALT(Up) , 0 , QList<QKeySequence>(), false },
+ { Back , "Back" , I18N_NOOP2("@action" , "Back") , ALT(Left) , Qt::Key_Back , QList<QKeySequence>(), false },
+ { Forward , "Forward" , I18N_NOOP2("@action" , "Forward") , ALT(Right) , Qt::Key_Forward , QList<QKeySequence>(), false },
+ { Reload , "Reload" , I18N_NOOP2("@action" , "Reload") , Qt::Key_F5 , Qt::Key_Refresh , QList<QKeySequence>(), false },
+
+ { BeginningOfLine, "BeginningOfLine" , I18N_NOOP2("@action" , "Beginning of Line") , Qt::Key_Home , 0 , QList<QKeySequence>(), false },
+ { EndOfLine , "EndOfLine" , I18N_NOOP2("@action" , "End of Line") , Qt::Key_End , 0 , QList<QKeySequence>(), false },
+ { GotoLine , "GotoLine" , I18N_NOOP2("@action" , "Go to Line") , CTRL(G) , 0 , QList<QKeySequence>(), false },
+ { BackwardWord , "BackwardWord" , I18N_NOOP2("@action" , "Backward Word") , CTRL(Left) , 0 , QList<QKeySequence>(), false },
+ { ForwardWord , "ForwardWord" , I18N_NOOP2("@action" , "Forward Word") , CTRL(Right) , 0 , QList<QKeySequence>(), false },
+
+ { AddBookmark , "AddBookmark" , I18N_NOOP2("@action" , "Add Bookmark") , CTRL(B) , 0 , QList<QKeySequence>(), false },
+ { ZoomIn , "ZoomIn" , I18N_NOOP2("@action" , "Zoom In") , CTRL(Plus) , CTRL(Equal) , QList<QKeySequence>(), false },
+ { ZoomOut , "ZoomOut" , I18N_NOOP2("@action" , "Zoom Out") , CTRL(Minus) , 0 , QList<QKeySequence>(), false },
+ { FullScreen , "FullScreen" , I18N_NOOP2("@action" , "Full Screen Mode") , CTRLSHIFT(F) , 0 , QList<QKeySequence>(), false },
+
+ { ShowMenubar , "ShowMenubar" , I18N_NOOP2("@action" , "Show Menu Bar") , CTRL(M) , 0 , QList<QKeySequence>(), false },
+ { TabNext , "Activate Next Tab" , I18N_NOOP2("@action" , "Activate Next Tab") , CTRL(Period) , CTRL(BracketRight), QList<QKeySequence>(), false },
+ { TabPrev , "Activate Previous Tab", I18N_NOOP2("@action" , "Activate Previous Tab"), CTRL(Comma) , CTRL(BracketLeft) , QList<QKeySequence>(), false },
+
+ //Group Help
+ { Help , "Help" , I18N_NOOP2("@action" , "Help") , Qt::Key_F1 , 0 , QList<QKeySequence>(), false },
+ { WhatsThis , "WhatsThis" , I18N_NOOP2("@action" , "What's This") , SHIFT(F1) , 0 , QList<QKeySequence>(), false },
+
+//Group TextCompletion
+ { TextCompletion , "TextCompletion" , I18N_NOOP2("@action", "Text Completion") , CTRL(E) , 0, QList<QKeySequence>(), false },
+ { PrevCompletion , "PrevCompletion" , I18N_NOOP2("@action", "Previous Completion Match"), CTRL(Up) , 0, QList<QKeySequence>(), false },
+ { NextCompletion , "NextCompletion" , I18N_NOOP2("@action", "Next Completion Match") , CTRL(Down) , 0, QList<QKeySequence>(), false },
+ { SubstringCompletion , "SubstringCompletion" , I18N_NOOP2("@action", "Substring Completion") , CTRL(T) , 0, QList<QKeySequence>(), false },
+
+ { RotateUp , "RotateUp" , I18N_NOOP2("@action", "Previous Item in List") , Qt::Key_Up , 0, QList<QKeySequence>(), false },
+ { RotateDown , "RotateDown" , I18N_NOOP2("@action", "Next Item in List") , Qt::Key_Down, 0, QList<QKeySequence>(), false },
+
+ { OpenRecent , "OpenRecent" , I18N_NOOP2("@action", "Open Recent") , 0 , 0, QList<QKeySequence>(), false },
+ { SaveAs , "SaveAs" , I18N_NOOP2("@action", "Save As") , CTRLSHIFT(S), 0, QList<QKeySequence>(), false },
+ { Revert , "Revert" , I18N_NOOP2("@action", "Revert") , 0 , 0, QList<QKeySequence>(), false },
+ { PrintPreview , "PrintPreview" , I18N_NOOP2("@action", "Print Preview") , 0 , 0, QList<QKeySequence>(), false },
+ { Mail , "Mail" , I18N_NOOP2("@action", "Mail") , 0 , 0, QList<QKeySequence>(), false },
+ { Clear , "Clear" , I18N_NOOP2("@action", "Clear") , 0 , 0, QList<QKeySequence>(), false },
+ { ActualSize , "ActualSize" , I18N_NOOP2("@action", "Actual Size") , 0 , 0, QList<QKeySequence>(), false },
+ { FitToPage , "FitToPage" , I18N_NOOP2("@action", "Fit To Page") , 0 , 0, QList<QKeySequence>(), false },
+ { FitToWidth , "FitToWidth" , I18N_NOOP2("@action", "Fit To Width") , 0 , 0, QList<QKeySequence>(), false },
+ { FitToHeight , "FitToHeight" , I18N_NOOP2("@action", "Fit To Height") , 0 , 0, QList<QKeySequence>(), false },
+ { Zoom , "Zoom" , I18N_NOOP2("@action", "Zoom") , 0 , 0, QList<QKeySequence>(), false },
+ { Goto , "Goto" , I18N_NOOP2("@action", "Goto") , 0 , 0, QList<QKeySequence>(), false },
+ { GotoPage , "GotoPage" , I18N_NOOP2("@action", "Goto Page") , 0 , 0, QList<QKeySequence>(), false },
+ { DocumentBack , "DocumentBack" , I18N_NOOP2("@action", "Document Back") , ALTSHIFT(Left), 0, QList<QKeySequence>(), false },
+ { DocumentForward , "DocumentForward" , I18N_NOOP2("@action", "Document Forward") , ALTSHIFT(Right), 0, QList<QKeySequence>(), false },
+ { EditBookmarks , "EditBookmarks" , I18N_NOOP2("@action", "Edit Bookmarks") , 0 , 0, QList<QKeySequence>(), false },
+ { Spelling , "Spelling" , I18N_NOOP2("@action", "Spelling") , 0 , 0, QList<QKeySequence>(), false },
+ { ShowToolbar , "ShowToolbar" , I18N_NOOP2("@action", "Show Toolbar") , 0 , 0, QList<QKeySequence>(), false },
+ { ShowStatusbar , "ShowStatusbar" , I18N_NOOP2("@action", "Show Statusbar") , 0 , 0, QList<QKeySequence>(), false },
+ { SaveOptions , "SaveOptions" , I18N_NOOP2("@action", "Save Options") , 0 , 0, QList<QKeySequence>(), false },
+ { KeyBindings , "KeyBindings" , I18N_NOOP2("@action", "Key Bindings") , 0 , 0, QList<QKeySequence>(), false },
+ { Preferences , "Preferences" , I18N_NOOP2("@action", "Preferences") , 0 , 0, QList<QKeySequence>(), false },
+ { ConfigureToolbars , "ConfigureToolbars" , I18N_NOOP2("@action", "Configure Toolbars") , 0 , 0, QList<QKeySequence>(), false },
+ { ConfigureNotifications , "ConfigureNotifications" , I18N_NOOP2("@action", "Configure Notifications") , 0 , 0, QList<QKeySequence>(), false },
+ { TipofDay , "TipofDay" , I18N_NOOP2("@action", "Tip Of Day") , 0 , 0, QList<QKeySequence>(), false },
+ { ReportBug , "ReportBug" , I18N_NOOP2("@action", "Report Bug") , 0 , 0, QList<QKeySequence>(), false },
+ { SwitchApplicationLanguage, "SwitchApplicationLanguage", I18N_NOOP2("@action", "Switch Application Language"), 0 , 0, QList<QKeySequence>(), false },
+ { AboutApp , "AboutApp" , I18N_NOOP2("@action", "About Application") , 0 , 0, QList<QKeySequence>(), false },
+ { AboutKDE , "AboutKDE" , I18N_NOOP2("@action", "About KDE") , 0 , 0, QList<QKeySequence>(), false },
+
+ //dummy entry to catch simple off-by-one errors. Insert new entries before this line.
+ { AccelNone , 0 , 0 , 0 , 0, 0, QList<QKeySequence>(), false }
+};
+
+
+/** Search for the KStandardShortcutInfo object associated with the given @p id.
+ Return a dummy entry with no name and an empty shortcut if @p id is invalid.
+*/
+static KStandardShortcutInfo *guardedStandardShortcutInfo(StandardShortcut id)
+{
+ if (id >= static_cast<int>(sizeof(g_infoStandardShortcut) / sizeof(KStandardShortcutInfo)) ||
+ id < 0) {
+ qWarning() << "KStandardShortcut: id not found!";
+ return &g_infoStandardShortcut[AccelNone];
+ } else
+ return &g_infoStandardShortcut[id];
+}
+
+/** Initialize the accelerator @p id by checking if it is overridden
+ in the configuration file (and if it isn't, use the default).
+ On X11, if QApplication was initialized with GUI disabled,
+ the default will always be used.
+*/
+static void initialize(StandardShortcut id)
+{
+ KStandardShortcutInfo *info = guardedStandardShortcutInfo(id);
+
+ // All three are needed.
+ if (info->id!=AccelNone) {
+ Q_ASSERT(info->description);
+ Q_ASSERT(info->translation_context);
+ Q_ASSERT(info->name);
+ }
+
+ KConfigGroup cg(KSharedConfig::openConfig(), "Shortcuts");
+
+ if (cg.hasKey(info->name)) {
+ QString s = cg.readEntry(info->name);
+ if (s != QLatin1String("none"))
+ info->cut = QKeySequence::listFromString(s);
+ else
+ info->cut = QList<QKeySequence>();
+ } else {
+ info->cut = hardcodedDefaultShortcut(id);
+ }
+
+ info->isInitialized = true;
+}
+
+void saveShortcut(StandardShortcut id, const QList<QKeySequence> &newShortcut)
+{
+ KStandardShortcutInfo *info = guardedStandardShortcutInfo(id);
+ // If the action has no standard shortcut associated there is nothing to
+ // save
+ if(info->id == AccelNone)
+ return;
+
+ KConfigGroup cg(KSharedConfig::openConfig(), "Shortcuts");
+
+ info->cut = newShortcut;
+ bool sameAsDefault = (newShortcut == hardcodedDefaultShortcut(id));
+
+ if (sameAsDefault) {
+ // If the shortcut is the equal to the hardcoded one we remove it from
+ // kdeglobal if necessary and return.
+ if(cg.hasKey(info->name))
+ cg.deleteEntry(info->name, KConfig::Global|KConfig::Persistent);
+
+ return;
+ }
+
+ // Write the changed shortcut to kdeglobals
+ cg.writeEntry(info->name, QKeySequence::listToString(info->cut), KConfig::Global|KConfig::Persistent);
+}
+
+QString name(StandardShortcut id)
+{
+ return QString::fromLatin1(guardedStandardShortcutInfo(id)->name);
+}
+
+QString label(StandardShortcut id)
+{
+ KStandardShortcutInfo *info = guardedStandardShortcutInfo( id );
+ return QCoreApplication::translate("KStandardShortcut",
+ info->description,
+ info->translation_context);
+}
+
+// TODO: Add psWhatsThis entry to KStandardShortcutInfo
+QString whatsThis( StandardShortcut /*id*/ )
+{
+// KStandardShortcutInfo* info = guardedStandardShortcutInfo( id );
+// if( info && info->whatsThis )
+// return i18n(info->whatsThis);
+// else
+ return QString();
+}
+
+const QList<QKeySequence> &shortcut(StandardShortcut id)
+{
+ KStandardShortcutInfo *info = guardedStandardShortcutInfo(id);
+
+ if(!info->isInitialized)
+ initialize(id);
+
+ return info->cut;
+}
+
+StandardShortcut find(const QKeySequence &seq)
+{
+ if( !seq.isEmpty() ) {
+ for(uint i = 0; i < sizeof(g_infoStandardShortcut) / sizeof(KStandardShortcutInfo); i++) {
+ StandardShortcut id = g_infoStandardShortcut[i].id;
+ if( id != AccelNone ) {
+ if(!g_infoStandardShortcut[i].isInitialized)
+ initialize(id);
+ if(g_infoStandardShortcut[i].cut.contains(seq))
+ return id;
+ }
+ }
+ }
+ return AccelNone;
+}
+
+StandardShortcut find(const char *keyName)
+{
+ for(uint i = 0; i < sizeof(g_infoStandardShortcut) / sizeof(KStandardShortcutInfo); i++)
+ if (qstrcmp(g_infoStandardShortcut[i].name, keyName))
+ return g_infoStandardShortcut[i].id;
+
+ return AccelNone;
+}
+
+QList<QKeySequence> hardcodedDefaultShortcut(StandardShortcut id)
+{
+ QList<QKeySequence> cut;
+ KStandardShortcutInfo *info = guardedStandardShortcutInfo(id);
+
+ if (info->cutDefault != 0)
+ cut << info->cutDefault;
+
+ if (info->cutDefault2 != 0) {
+ if (cut.isEmpty())
+ cut << QKeySequence();
+
+ cut << info->cutDefault2;
+ }
+
+ return cut;
+}
+
+const QList<QKeySequence> &open() { return shortcut( Open ); }
+const QList<QKeySequence> &openNew() { return shortcut( New ); }
+const QList<QKeySequence> &close() { return shortcut( Close ); }
+const QList<QKeySequence> &save() { return shortcut( Save ); }
+const QList<QKeySequence> &print() { return shortcut( Print ); }
+const QList<QKeySequence> &quit() { return shortcut( Quit ); }
+const QList<QKeySequence> &cut() { return shortcut( Cut ); }
+const QList<QKeySequence> &copy() { return shortcut( Copy ); }
+const QList<QKeySequence> &paste() { return shortcut( Paste ); }
+const QList<QKeySequence> &pasteSelection() { return shortcut( PasteSelection ); }
+const QList<QKeySequence> &deleteWordBack() { return shortcut( DeleteWordBack ); }
+const QList<QKeySequence> &deleteWordForward() { return shortcut( DeleteWordForward ); }
+const QList<QKeySequence> &undo() { return shortcut( Undo ); }
+const QList<QKeySequence> &redo() { return shortcut( Redo ); }
+const QList<QKeySequence> &find() { return shortcut( Find ); }
+const QList<QKeySequence> &findNext() { return shortcut( FindNext ); }
+const QList<QKeySequence> &findPrev() { return shortcut( FindPrev ); }
+const QList<QKeySequence> &replace() { return shortcut( Replace ); }
+const QList<QKeySequence> &home() { return shortcut( Home ); }
+const QList<QKeySequence> &begin() { return shortcut( Begin ); }
+const QList<QKeySequence> &end() { return shortcut( End ); }
+const QList<QKeySequence> &beginningOfLine() { return shortcut( BeginningOfLine ); }
+const QList<QKeySequence> &endOfLine() { return shortcut( EndOfLine ); }
+const QList<QKeySequence> &prior() { return shortcut( Prior ); }
+const QList<QKeySequence> &next() { return shortcut( Next ); }
+const QList<QKeySequence> &backwardWord() { return shortcut( BackwardWord ); }
+const QList<QKeySequence> &forwardWord() { return shortcut( ForwardWord ); }
+const QList<QKeySequence> &gotoLine() { return shortcut( GotoLine ); }
+const QList<QKeySequence> &addBookmark() { return shortcut( AddBookmark ); }
+const QList<QKeySequence> &tabNext() { return shortcut( TabNext ); }
+const QList<QKeySequence> &tabPrev() { return shortcut( TabPrev ); }
+const QList<QKeySequence> &fullScreen() { return shortcut( FullScreen ); }
+const QList<QKeySequence> &zoomIn() { return shortcut( ZoomIn ); }
+const QList<QKeySequence> &zoomOut() { return shortcut( ZoomOut ); }
+const QList<QKeySequence> &help() { return shortcut( Help ); }
+const QList<QKeySequence> &completion() { return shortcut( TextCompletion ); }
+const QList<QKeySequence> &prevCompletion() { return shortcut( PrevCompletion ); }
+const QList<QKeySequence> &nextCompletion() { return shortcut( NextCompletion ); }
+const QList<QKeySequence> &rotateUp() { return shortcut( RotateUp ); }
+const QList<QKeySequence> &rotateDown() { return shortcut( RotateDown ); }
+const QList<QKeySequence> &substringCompletion() { return shortcut( SubstringCompletion ); }
+const QList<QKeySequence> &whatsThis() { return shortcut( WhatsThis ); }
+const QList<QKeySequence> &reload() { return shortcut( Reload ); }
+const QList<QKeySequence> &selectAll() { return shortcut( SelectAll ); }
+const QList<QKeySequence> &up() { return shortcut( Up ); }
+const QList<QKeySequence> &back() { return shortcut( Back ); }
+const QList<QKeySequence> &forward() { return shortcut( Forward ); }
+const QList<QKeySequence> &showMenubar() { return shortcut( ShowMenubar ); }
+
+}
diff --git a/tier1/kconfig/src/gui/kstandardshortcut.h b/tier1/kconfig/src/gui/kstandardshortcut.h
new file mode 100644
index 00000000..b02a6ebf
--- /dev/null
+++ b/tier1/kconfig/src/gui/kstandardshortcut.h
@@ -0,0 +1,482 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1997 Stefan Taferner (taferner@kde.org)
+ Copyright (C) 2000 Nicolas Hadacek (hadacek@kde.org)
+ Copyright (C) 2001,2002 Ellis Whitehead (ellis@kde.org)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#ifndef KSTANDARDSHORTCUT_H
+#define KSTANDARDSHORTCUT_H
+
+#include <QtCore/QString>
+#include <QKeySequence>
+
+#include <kconfiggui_export.h>
+
+/**
+ * \namespace KStandardShortcut
+ * Convenient methods for access to the common accelerator keys in
+ * the key configuration. These are the standard keybindings that should
+ * be used in all KDE applications. They will be configurable,
+ * so do not hardcode the default behavior.
+ */
+namespace KStandardShortcut
+{ // STUFF WILL BREAK IF YOU DON'T READ THIS!!!
+ /*
+ *Always add new std-accels to the end of this enum, never in the middle!
+ *Don't forget to add the corresponding entries in g_infoStandardShortcut[] in kstandardshortcut.cpp, too.
+ *Values of elements here and positions of the corresponding entries in
+ *the big array g_infoStandardShortcut[] ABSOLUTELY MUST BE THE SAME.
+ * !!! !!!! !!!!! !!!!
+ * !!!! !!! !!!! !!!!
+ * Remember to also update kdoctools/genshortcutents.cpp.
+ *
+ * Other Rules:
+ *
+ * - Never change the name of an existing shortcut
+ * - Never translate the name of a shortcut
+ */
+
+ /**
+ * Defines the identifier of all standard accelerators.
+ */
+ enum StandardShortcut {
+ //C++ requires that the value of an enum symbol be one more than the previous one.
+ //This means that everything will be well-ordered from here on.
+ AccelNone=0,
+ // File menu
+ Open, New, Close, Save,
+ // The Print item
+ Print,
+ Quit,
+ // Edit menu
+ Undo, Redo, Cut, Copy, Paste, PasteSelection,
+ SelectAll, Deselect, DeleteWordBack, DeleteWordForward,
+ Find, FindNext, FindPrev, Replace,
+ // Navigation
+ Home, Begin, End, Prior, Next,
+ Up, Back, Forward, Reload,
+ // Text Navigation
+ BeginningOfLine, EndOfLine, GotoLine,
+ BackwardWord, ForwardWord,
+ // View parameters
+ AddBookmark, ZoomIn, ZoomOut, FullScreen,
+ ShowMenubar,
+ // Tabular navigation
+ TabNext, TabPrev,
+ // Help menu
+ Help, WhatsThis,
+ // Text completion
+ TextCompletion, PrevCompletion, NextCompletion, SubstringCompletion,
+
+ RotateUp, RotateDown,
+
+ OpenRecent,
+ SaveAs,
+ Revert,
+ PrintPreview,
+ Mail,
+ Clear,
+ ActualSize,
+ FitToPage,
+ FitToWidth,
+ FitToHeight,
+ Zoom,
+ Goto,
+ GotoPage,
+ DocumentBack,
+ DocumentForward,
+ EditBookmarks,
+ Spelling,
+ ShowToolbar,
+ ShowStatusbar,
+ SaveOptions,
+ KeyBindings,
+ Preferences,
+ ConfigureToolbars,
+ ConfigureNotifications,
+ TipofDay,
+ ReportBug,
+ SwitchApplicationLanguage,
+ AboutApp,
+ AboutKDE,
+
+ // Insert new items here!
+
+ StandardShortcutCount // number of standard shortcuts
+ };
+
+ /**
+ * Returns the keybinding for @p accel.
+ * On X11, if QApplication was initialized with GUI disabled, the
+ * default keybinding will always be returned.
+ * @param id the id of the accelerator
+ */
+ KCONFIGGUI_EXPORT const QList<QKeySequence> &shortcut(StandardShortcut id);
+
+ /**
+ * Returns a unique name for the given accel.
+ * @param id the id of the accelerator
+ * @return the unique name of the accelerator
+ */
+ KCONFIGGUI_EXPORT QString name(StandardShortcut id);
+
+ /**
+ * Returns a localized label for user-visible display.
+ * @param id the id of the accelerator
+ * @return a localized label for the accelerator
+ */
+ KCONFIGGUI_EXPORT QString label(StandardShortcut id);
+
+ /**
+ * Returns an extended WhatsThis description for the given accelerator.
+ * @param id the id of the accelerator
+ * @return a localized description of the accelerator
+ */
+ KCONFIGGUI_EXPORT QString whatsThis(StandardShortcut id);
+
+ /**
+ * Return the StandardShortcut id of the standard accel action which
+ * uses this key sequence, or AccelNone if none of them do.
+ * This is used by class KKeyChooser.
+ * @param keySeq the key sequence to search
+ * @return the id of the standard accelerator, or AccelNone if there
+ * is none
+ */
+ KCONFIGGUI_EXPORT StandardShortcut find(const QKeySequence &keySeq);
+
+ /**
+ * Return the StandardShortcut id of the standard accel action which
+ * has \a keyName as its name, or AccelNone if none of them do.
+ * This is used by class KKeyChooser.
+ * @param keyName the key sequence to search
+ * @return the id of the standard accelerator, or AccelNone if there
+ * is none
+ */
+ KCONFIGGUI_EXPORT StandardShortcut find(const char *keyName);
+
+ /**
+ * Returns the hardcoded default shortcut for @p id.
+ * This does not take into account the user's configuration.
+ * @param id the id of the accelerator
+ * @return the default shortcut of the accelerator
+ */
+ KCONFIGGUI_EXPORT QList<QKeySequence> hardcodedDefaultShortcut(StandardShortcut id);
+
+ /**
+ * Saves the new shortcut \a cut for standard accel \a id.
+ */
+ KCONFIGGUI_EXPORT void saveShortcut(StandardShortcut id, const QList<QKeySequence> &newShortcut);
+
+ /**
+ * Open file. Default: Ctrl-o
+ * @return the shortcut of the standard accelerator
+ */
+ KCONFIGGUI_EXPORT const QList<QKeySequence> &open();
+
+ /**
+ * Create a new document (or whatever). Default: Ctrl-n
+ * @return the shortcut of the standard accelerator
+ */
+ KCONFIGGUI_EXPORT const QList<QKeySequence> &openNew();
+
+ /**
+ * Close current document. Default: Ctrl-w
+ * @return the shortcut of the standard accelerator
+ */
+ KCONFIGGUI_EXPORT const QList<QKeySequence> &close();
+
+ /**
+ * Save current document. Default: Ctrl-s
+ * @return the shortcut of the standard accelerator
+ */
+ KCONFIGGUI_EXPORT const QList<QKeySequence> &save();
+
+ /**
+ * Print current document. Default: Ctrl-p
+ * @return the shortcut of the standard accelerator
+ */
+ KCONFIGGUI_EXPORT const QList<QKeySequence> &print();
+
+ /**
+ * Quit the program. Default: Ctrl-q
+ * @return the shortcut of the standard accelerator
+ */
+ KCONFIGGUI_EXPORT const QList<QKeySequence> &quit();
+
+ /**
+ * Undo last operation. Default: Ctrl-z
+ * @return the shortcut of the standard accelerator
+ */
+ KCONFIGGUI_EXPORT const QList<QKeySequence> &undo();
+
+ /**
+ * Redo. Default: Shift-Ctrl-z
+ * @return the shortcut of the standard accelerator
+ */
+ KCONFIGGUI_EXPORT const QList<QKeySequence> &redo();
+
+ /**
+ * Cut selected area and store it in the clipboard. Default: Ctrl-x
+ * @return the shortcut of the standard accelerator
+ */
+ KCONFIGGUI_EXPORT const QList<QKeySequence> &cut();
+
+ /**
+ * Copy selected area into the clipboard. Default: Ctrl-c
+ * @return the shortcut of the standard accelerator
+ */
+ KCONFIGGUI_EXPORT const QList<QKeySequence> &copy();
+
+ /**
+ * Paste contents of clipboard at mouse/cursor position. Default: Ctrl-v
+ * @return the shortcut of the standard accelerator
+ */
+ KCONFIGGUI_EXPORT const QList<QKeySequence> &paste();
+
+ /**
+ * Paste the selection at mouse/cursor position. Default: Ctrl-Shift-Insert
+ * @return the shortcut of the standard accelerator
+ */
+ KCONFIGGUI_EXPORT const QList<QKeySequence> &pasteSelection();
+
+ /**
+ * Select all. Default: Ctrl-A
+ * @return the shortcut of the standard accelerator
+ **/
+ KCONFIGGUI_EXPORT const QList<QKeySequence> &selectAll();
+
+ /**
+ * Delete a word back from mouse/cursor position. Default: Ctrl-Backspace
+ * @return the shortcut of the standard accelerator
+ */
+ KCONFIGGUI_EXPORT const QList<QKeySequence> &deleteWordBack();
+
+ /**
+ * Delete a word forward from mouse/cursor position. Default: Ctrl-Delete
+ * @return the shortcut of the standard accelerator
+ */
+ KCONFIGGUI_EXPORT const QList<QKeySequence> &deleteWordForward();
+
+ /**
+ * Find, search. Default: Ctrl-f
+ * @return the shortcut of the standard accelerator
+ */
+ KCONFIGGUI_EXPORT const QList<QKeySequence> &find();
+
+ /**
+ * Find/search next. Default: F3
+ * @return the shortcut of the standard accelerator
+ */
+ KCONFIGGUI_EXPORT const QList<QKeySequence> &findNext();
+
+ /**
+ * Find/search previous. Default: Shift-F3
+ * @return the shortcut of the standard accelerator
+ */
+ KCONFIGGUI_EXPORT const QList<QKeySequence> &findPrev();
+
+ /**
+ * Find and replace matches. Default: Ctrl-r
+ * @return the shortcut of the standard accelerator
+ */
+ KCONFIGGUI_EXPORT const QList<QKeySequence> &replace();
+
+ /**
+ * Zoom in. Default: Ctrl-Plus
+ * @return the shortcut of the standard accelerator
+ */
+ KCONFIGGUI_EXPORT const QList<QKeySequence> &zoomIn();
+
+ /**
+ * Zoom out. Default: Ctrl-Minus
+ * @return the shortcut of the standard accelerator
+ */
+ KCONFIGGUI_EXPORT const QList<QKeySequence> &zoomOut();
+
+ /**
+ * Toggle insert/overwrite (with visual feedback, e.g. in the statusbar). Default: Insert
+ * @return the shortcut of the standard accelerator
+ */
+ KCONFIGGUI_EXPORT const QList<QKeySequence> &insert();
+
+ /**
+ * Goto home page. Default: Alt-Home
+ * @return the shortcut of the standard accelerator
+ */
+ KCONFIGGUI_EXPORT const QList<QKeySequence> &home();
+
+ /**
+ * Goto beginning of the document. Default: Ctrl-Home
+ * @return the shortcut of the standard accelerator
+ */
+ KCONFIGGUI_EXPORT const QList<QKeySequence> &begin();
+
+ /**
+ * Goto end of the document. Default: Ctrl-End
+ * @return the shortcut of the standard accelerator
+ */
+ KCONFIGGUI_EXPORT const QList<QKeySequence> &end();
+
+ /**
+ * Goto beginning of current line. Default: Home
+ * @return the shortcut of the standard accelerator
+ */
+ KCONFIGGUI_EXPORT const QList<QKeySequence> &beginningOfLine();
+
+ /**
+ * Goto end of current line. Default: End
+ * @return the shortcut of the standard accelerator
+ */
+ KCONFIGGUI_EXPORT const QList<QKeySequence> &endOfLine();
+
+ /**
+ * Scroll up one page. Default: Prior
+ * @return the shortcut of the standard accelerator
+ */
+ KCONFIGGUI_EXPORT const QList<QKeySequence> &prior();
+
+ /**
+ * Scroll down one page. Default: Next
+ * @return the shortcut of the standard accelerator
+ */
+ KCONFIGGUI_EXPORT const QList<QKeySequence> &next();
+
+ /**
+ * Go to line. Default: Ctrl+G
+ * @return the shortcut of the standard accelerator
+ */
+ KCONFIGGUI_EXPORT const QList<QKeySequence> &gotoLine();
+
+ /**
+ * Add current page to bookmarks. Default: Ctrl+B
+ * @return the shortcut of the standard accelerator
+ */
+ KCONFIGGUI_EXPORT const QList<QKeySequence> &addBookmark();
+
+ /**
+ * Next Tab. Default: Ctrl-<
+ * @return the shortcut of the standard accelerator
+ */
+ KCONFIGGUI_EXPORT const QList<QKeySequence> &tabNext();
+
+ /**
+ * Previous Tab. Default: Ctrl->
+ * @return the shortcut of the standard accelerator
+ */
+ KCONFIGGUI_EXPORT const QList<QKeySequence> &tabPrev();
+
+ /**
+ * Full Screen Mode. Default: Ctrl+Shift+F
+ * @return the shortcut of the standard accelerator
+ */
+ KCONFIGGUI_EXPORT const QList<QKeySequence> &fullScreen();
+
+ /**
+ * Help the user in the current situation. Default: F1
+ * @return the shortcut of the standard accelerator
+ */
+ KCONFIGGUI_EXPORT const QList<QKeySequence> &help();
+
+ /**
+ * Complete text in input widgets. Default Ctrl+E
+ * @return the shortcut of the standard accelerator
+ **/
+ KCONFIGGUI_EXPORT const QList<QKeySequence> &completion();
+
+ /**
+ * Iterate through a list when completion returns
+ * multiple items. Default: Ctrl+Up
+ * @return the shortcut of the standard accelerator
+ */
+ KCONFIGGUI_EXPORT const QList<QKeySequence> &prevCompletion();
+
+ /**
+ * Iterate through a list when completion returns
+ * multiple items. Default: Ctrl+Down
+ * @return the shortcut of the standard accelerator
+ */
+ KCONFIGGUI_EXPORT const QList<QKeySequence> &nextCompletion();
+
+ /**
+ * Find a string within another string or list of strings.
+ * Default: Ctrl-T
+ * @return the shortcut of the standard accelerator
+ */
+ KCONFIGGUI_EXPORT const QList<QKeySequence> &substringCompletion();
+
+ /**
+ * Help users iterate through a list of entries. Default: Up
+ * @return the shortcut of the standard accelerator
+ */
+ KCONFIGGUI_EXPORT const QList<QKeySequence> &rotateUp();
+
+ /**
+ * Help users iterate through a list of entries. Default: Down
+ * @return the shortcut of the standard accelerator
+ */
+ KCONFIGGUI_EXPORT const QList<QKeySequence> &rotateDown();
+
+ /**
+ * What's This button. Default: Shift+F1
+ * @return the shortcut of the standard accelerator
+ */
+ KCONFIGGUI_EXPORT const QList<QKeySequence> &whatsThis();
+
+ /**
+ * Reload. Default: F5
+ * @return the shortcut of the standard accelerator
+ */
+ KCONFIGGUI_EXPORT const QList<QKeySequence> &reload();
+
+ /**
+ * Up. Default: Alt+Up
+ * @return the shortcut of the standard accelerator
+ */
+ KCONFIGGUI_EXPORT const QList<QKeySequence> &up();
+
+ /**
+ * Back. Default: Alt+Left
+ * @return the shortcut of the standard accelerator
+ */
+ KCONFIGGUI_EXPORT const QList<QKeySequence> &back();
+
+ /**
+ * Forward. Default: ALT+Right
+ * @return the shortcut of the standard accelerator
+ */
+ KCONFIGGUI_EXPORT const QList<QKeySequence> &forward();
+
+ /**
+ * BackwardWord. Default: Ctrl+Left
+ * @return the shortcut of the standard accelerator
+ */
+ KCONFIGGUI_EXPORT const QList<QKeySequence> &backwardWord();
+
+ /**
+ * ForwardWord. Default: Ctrl+Right
+ * @return the shortcut of the standard accelerator
+ */
+ KCONFIGGUI_EXPORT const QList<QKeySequence> &forwardWord();
+
+ /**
+ * Show Menu Bar. Default: Ctrl-M
+ * @return the shortcut of the standard accelerator
+ */
+ KCONFIGGUI_EXPORT const QList<QKeySequence> &showMenubar();
+
+}
+
+#endif // KSTANDARDSHORTCUT_H
diff --git a/tier1/kconfig/src/gui/kwindowconfig.cpp b/tier1/kconfig/src/gui/kwindowconfig.cpp
new file mode 100644
index 00000000..6b7ae5f0
--- /dev/null
+++ b/tier1/kconfig/src/gui/kwindowconfig.cpp
@@ -0,0 +1,83 @@
+/*
+ This file is part of the KDE libraries
+ Copyright (c) 2012 Benjamin Port <benjamin.port@ben2367.fr>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "kwindowconfig.h"
+
+#include <QScreen>
+#include <QWindow>
+
+static const char* s_initialSizePropertyName = "_kconfig_initial_size";
+static const char* s_initialScreenSizePropertyName = "_kconfig_initial_screen_size";
+
+void KWindowConfig::saveWindowSize(const QWindow *window, KConfigGroup &config, KConfigGroup::WriteConfigFlags options)
+{
+ if (!window)
+ return;
+ const QRect desk = window->screen()->geometry();
+
+ const QSize sizeToSave = window->size();
+ const bool isMaximized = window->windowState() & Qt::WindowMaximized;
+
+ const QString screenMaximizedString(QString::fromLatin1("Window-Maximized %1x%2").arg(desk.height()).arg(desk.width()));
+ // Save size only if window is not maximized
+ if (!isMaximized) {
+ const QSize defaultSize(window->property(s_initialSizePropertyName).toSize());
+ const QSize defaultScreenSize(window->property(s_initialScreenSizePropertyName).toSize());
+ const bool sizeValid = defaultSize.isValid() && defaultScreenSize.isValid();
+ if (!sizeValid || (sizeValid && (defaultSize != sizeToSave || defaultScreenSize != desk.size()))) {
+ const QString wString(QString::fromLatin1("Width %1").arg(desk.width()));
+ const QString hString(QString::fromLatin1("Height %1").arg(desk.height()));
+ config.writeEntry(wString, sizeToSave.width(), options);
+ config.writeEntry(hString, sizeToSave.height(), options);
+ }
+ }
+ if ( (isMaximized == false) && !config.hasDefault(screenMaximizedString) )
+ config.revertToDefault(screenMaximizedString);
+ else
+ config.writeEntry(screenMaximizedString, isMaximized, options);
+
+}
+
+void KWindowConfig::restoreWindowSize(QWindow* window, const KConfigGroup& config)
+{
+ if (!window)
+ return;
+
+ const QRect desk = window->screen()->geometry();
+
+ const int width = config.readEntry(QString::fromLatin1("Width %1").arg(desk.width()), window->size().width());
+ const int height = config.readEntry(QString::fromLatin1("Height %1").arg(desk.height()), window->size().height());
+ const bool isMaximized = config.readEntry(QString::fromLatin1("Window-Maximized %1x%2").arg(desk.height()).arg(desk.width()), false);
+
+ // Check default size
+ const QSize defaultSize(window->property(s_initialSizePropertyName).toSize());
+ const QSize defaultScreenSize(window->property(s_initialScreenSizePropertyName).toSize());
+ if (!defaultSize.isValid() || !defaultScreenSize.isValid()) {
+ window->setProperty(s_initialSizePropertyName, window->size());
+ window->setProperty(s_initialScreenSizePropertyName, desk.size());
+ }
+
+ // If window is maximized set maximized state and in all case set the size
+ window->resize(width, height);
+ if (isMaximized) {
+ window->setWindowState(Qt::WindowMaximized);
+ }
+}
diff --git a/tier1/kconfig/src/gui/kwindowconfig.h b/tier1/kconfig/src/gui/kwindowconfig.h
new file mode 100644
index 00000000..2c70571d
--- /dev/null
+++ b/tier1/kconfig/src/gui/kwindowconfig.h
@@ -0,0 +1,58 @@
+/*
+ This file is part of the KDE libraries
+ Copyright (c) 2012 Benjamin Port <benjamin.port@ben2367.fr>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef KWINDOWCONFIG_H
+#define KWINDOWCONFIG_H
+
+#include <kconfiggroup.h>
+#include <kconfiggui_export.h>
+
+class QWindow;
+
+namespace KWindowConfig
+{
+ /**
+ * Saves the window's size dependent on the screen dimension either to the
+ * global or application config file.
+ *
+ * @note the group must be set before calling
+ *
+ * @param window The window to save size.
+ * @param config The config group to read from.
+ * @param options passed to KConfigGroup::writeEntry()
+ * @since 5.0
+ */
+ KCONFIGGUI_EXPORT void saveWindowSize( const QWindow* window, KConfigGroup& config, KConfigGroup::WriteConfigFlags options = KConfigGroup::Normal );
+
+ /**
+ * Restores the dialog's size from the configuration according to
+ * the screen size.
+ *
+ * @note the group must be set before calling
+ *
+ * @param dialog The dialog to restore size.
+ * @param config The config group to read from.
+ * @since 5.0.
+ */
+ KCONFIGGUI_EXPORT void restoreWindowSize( QWindow* window, const KConfigGroup& config );
+}
+
+#endif // KWINDOWCONFIG_H
diff --git a/tier1/kconfig/src/kconf_update/CMakeLists.txt b/tier1/kconfig/src/kconf_update/CMakeLists.txt
new file mode 100644
index 00000000..e4e37ba9
--- /dev/null
+++ b/tier1/kconfig/src/kconf_update/CMakeLists.txt
@@ -0,0 +1,17 @@
+find_package(Qt5Core 5.2.0 REQUIRED NO_MODULE)
+
+remove_definitions(-DQT_NO_CAST_FROM_ASCII)
+
+configure_file(config-kconf.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-kconf.h )
+
+########### next target ###############
+
+set(kconf_update_SRCS
+ kconf_update.cpp
+ kconfigutils.cpp
+ )
+
+add_executable(kconf_update ${kconf_update_SRCS})
+target_link_libraries(kconf_update Qt5::Core KF5::ConfigCore)
+
+install(TARGETS kconf_update DESTINATION ${LIBEXEC_INSTALL_DIR})
diff --git a/tier1/kconfig/src/kconf_update/Mainpage.dox b/tier1/kconfig/src/kconf_update/Mainpage.dox
new file mode 100644
index 00000000..77d486ce
--- /dev/null
+++ b/tier1/kconfig/src/kconf_update/Mainpage.dox
@@ -0,0 +1,31 @@
+/** @mainpage ./kconf_update
+
+kconf_update is a tool designed to update config files. 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.
+
+What used to happen is that the application looks up both the old and the
+new configuration option and then decides which one to use. This method has
+several drawbacks:
+- The application may need to read more configuration files than strictly
+ needed, resulting in a slower startup.
+- The application becomes bigger with code that will only be used once.
+
+kconf_update addresses these problems by offering a framework to update
+configuration files without adding code to the application itself.
+
+See the <a href="http://websvn.kde.org/trunk/KDE/kdelibs/kconf_update/README.kconf_update?view=markup">README file</a> for more information.
+
+@authors
+Waldo Bastian \<bastian@kde.org\>
+
+@maintainers
+[Unknown/None]
+
+@licenses
+@lgpl
+
+*/
+// vim:ts=4:sw=4:expandtab:filetype=doxygen
diff --git a/tier1/kconfig/src/kconf_update/README.kconf_update b/tier1/kconfig/src/kconf_update/README.kconf_update
new file mode 100644
index 00000000..281fb9e5
--- /dev/null
+++ b/tier1/kconfig/src/kconf_update/README.kconf_update
@@ -0,0 +1,248 @@
+README kconf_update
+
+Version: 1.1
+Author: Waldo Bastian <bastian@kde.org>, <bastian@suse.com>
+
+What it does
+============
+
+kconf_update is a tool designed to update config files. 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.
+
+What used to happen is that the application looks up both the old and the
+new configuration option and then decides which one to use. This method has
+several drawbacks:
+* The application may need to read more configuration files than strictly
+needed, resulting in a slower startup.
+* The application becomes bigger with code that will only be used once.
+
+kconf_update addresses these problems by offering a framework to update
+configuration files without adding code to the application itself.
+
+
+How it works
+============
+
+Applications can install so called "update files" under
+$KDEDIR/share/apps/kconf_update. An update file has ".upd" as extension and
+contains instructions for transferring/converting configuration information
+from one place to another.
+
+Updating the configuration happens automatically, either when KDE gets started
+or when kded detects a new update file in the above mentioned location.
+
+Update files are separated into sections. Each section has an Id. When a
+section describing a configuration change has been applied, the Id will be
+stored in the file "kconf_updaterc". This information is used to make sure
+that a configuration update is only performed once.
+
+If you overwrite an existing update file with a new version that contains a
+new section, only the update instructions from this extra section will be
+performed.
+
+File format of the update file
+==============================
+
+Empty lines or lines that start with '#' are considered comments.
+Commas (,) are used to seperate fields and may not occur as part
+of any field and all of the keywords are case-sensitive, i.e. you
+cannot say "key" instead of "Key" for example.
+
+For the rest the file is parsed and executed sequentially from top to bottom.
+Each line can contain one entry. The following entries are recognized:
+
+
+Id=<id>
+
+With <id> identifying the group of update entries that follows. Once a group
+of entries have been applied, their <id> is stored and this group of entries
+will not be applied again.
+
+
+File=<oldfile>,<newfile>
+File=<oldfile>
+
+Specifies that configuration information is read from <oldfile> and written
+to <newfile>. If you only specify <oldfile>, the information is read from
+as well as written to <oldfile>. Note that if the file does not exist
+at the time kconf_update first checks, no related update will be performed
+(script won't be run at all, etc.).
+
+
+Script=<script>[,<interpreter>]
+
+All entries from <oldfile> are piped into <script>. The output of script
+is used as new entries for <newfile>. Existing entries can be deleted by
+adding lines with "# DELETE [group]key" in the output of the script.
+To delete a whole group use "# DELETEGROUP [group]".
+
+<script> should be installed into $(kde_datadir)/kconf_update, or
+kconf_update will not be able to find it. It's also possible to install
+kconf_update applications in $(kde_bindir)/kconf_update_bin, which opens the
+door to kconf_update applications that are written in C++ and use Qt's
+powerful string API instead.
+
+If Script was issued after a "Group" command the behavior is slightly
+different:
+All entries from <oldfile>/<oldgroup> are piped into <script>. The output
+of script is used as new entries for <newfile>/<newgroup>, unless a different
+group is specified with "[group]". Existing entries can be deleted from
+<oldgroup> by adding lines with "# DELETE key" in the output of the script.
+To delete <oldgroup> use "# DELETEGROUP".
+
+<interpreter> can be something like "perl".
+
+It is also possible to have a Script without specifying <oldfile> or
+<newfile>. In that case the script is run but it will not be fed any input
+and its output will simply be discarded.
+
+ScriptArguments=<arguments>
+
+If specified, the arguments will be passed to <script>.
+IMPORTANT: It has to be specified before Script=.
+
+Group=<oldgroup>,<newgroup>
+Group=<oldgroup>
+
+Specifies that configuration information is read from the group <oldgroup>
+and written to <newgroup>. If you only specify <oldgroup>, the information
+is read from as well as written to <oldgroup>. You can use <default> to
+specify keys that are not under any group.
+A group may be written either as "group" or as "[group]". The latter syntax
+makes it possible to specify subgroups: "[group][subgroup]".
+
+RemoveGroup=<oldgroup>
+
+Specifies that <oldgroup> is removed entirely. This can be used
+to remove obsolete entries or to force a revert to default values.
+
+Options=<option1>, <option2>, ....
+
+With this entry you can specify options that apply to the next "Script",
+"Key" or "AllKeys" entry (only to the first!). Possible options are:
+
+- "copy" Copy the configuration item instead of moving it. This means that
+ the configuration item will not be deleted from <oldfile>/<oldgroup>.
+
+- "overwrite" Normally, a configuration item is not moved if an item with the
+ new name already exists. When this option is specified the old
+ configuration item will overwrite any existing item.
+
+
+Key=<oldkey>,<newkey>
+Key=<oldkey>
+
+Specifies that configuration information is read from the key <oldkey>
+and written to <newkey>. If you only specify <oldkey>, the information
+is read from as well as written to <oldkey>.
+
+
+AllKeys
+
+Specifies that all configuration information in the selected group should
+be moved (All keys).
+
+AllGroups
+
+Specifies that all configuration information from all keys in ALL
+groups should be moved.
+
+
+RemoveKey=<oldkey>
+
+Specifies that <oldkey> is removed from the selected group. This can be used
+to remove obsolete entries or to force a revert to default values.
+
+
+Example update file
+===================
+
+# This is comment
+Id=kde2.2
+File=kioslaverc,kio_httprc
+Group=Proxy Settings
+Key=NoProxyFor
+Key=UseProxy
+Key=httpProxy,Proxy
+Group=Cache Settings,Cache
+Key=MaxCacheSize
+Key=UseCache
+Group=UserAgent
+AllKeys
+RemoveGroup=KDE
+# End of file
+
+
+The above update file extracts config information from the file "kioslaverc"
+and stores it into the file "kio_httprc".
+
+It reads the keys "NoProxyFor", "UseProxy" and "httpProxy" from the group
+"Proxy Settings" in the "kioslaverc" file. If any of these options are present
+they are written to the keys "NoProxyFor", "UseProxy" and "Proxy" (!) in
+the group "Proxy Settings" in the "kio_httprc" file.
+
+It also reads the keys "MaxCacheSize" and "UseCache" from the group
+"Cache Settings" in the "kioslaverc" file and writes this information to the
+keys "MaxCacheSize" and "UseCache" in the group "Cache" (!) in the
+"kio_httprc" file.
+
+Then it takes all keys in the "UserAgent" group of the file "kioslaverc"
+and moves then to the "UserAgent" group in the "kio_httprc" file.
+
+Finally it removes the entire "KDE" group in the kioslaverc file.
+
+
+Debugging and testing
+=====================
+
+If you are developing a kconf_update script and want to test or debug it you
+need to make sure kconf_update runs again after each of your changes. There
+are a number of ways to achieve this.
+
+The easiest is to not install the kconf_update script in the first place, but
+manually call it through a pipe. If you want to test the update script for
+your application KHello's config file khellorc, you can test by using
+
+ cat ~/.kde/share/config/khellorc | khello_conf_update.sh
+
+(assuming khello_conf_update.sh is the kconf_update script and ~/.kde is your
+$KDEHOME). This is easier than making install every time, but has the obvious
+downside that you need to 'parse' your script's output yourself instead of
+letting kconf_update do it and check the resulting output file.
+
+After 'make install' the kconf_update script is run by kded, but it does so
+only once. This is of course the idea behind it, but while developing it can
+be a problem. You can increase the revision number for each subsequent run
+of 'make install' to force a new kconf_update run, but there's a better
+approach that doesn't skyrocket the version number for a mediocre debug
+session.
+
+kded doesn't really ignore scripts that it has already run right away.
+Instead it checks the affected config file every time a .upd file is added
+or changed. The reason it still doesn't run again on your config file lies
+in the traces kconf_update leaves behind: it adds a special config group
+'[$Version]' with a key 'update_info'. This key lists all kconf_update
+scripts that have already been run on this config file. It also adds a group
+for the script to $KDEHOME/share/config/kconf_updaterc. Just remove your
+script entries from both your rcfile and kconf_updaterc, 'make install',
+and kconf_update will happily run your script again, without you having to
+increase the version number.
+
+If you want to know what kconf_update has been up to lately, have a look
+at $KDEHOME/share/apps/kconf_update/log/update.log
+
+
+Common Problems
+===============
+
+* kconf_update refuses to update an entry
+If you change the value of an entry without changing the key or file,
+make sure to tell kconf_update that it should overwrite the old entry
+by adding "Options=overwrite".
+
+
+Have fun,
+Waldo
diff --git a/tier1/kconfig/src/kconf_update/config-kconf.h.cmake b/tier1/kconfig/src/kconf_update/config-kconf.h.cmake
new file mode 100644
index 00000000..0f70f8c8
--- /dev/null
+++ b/tier1/kconfig/src/kconf_update/config-kconf.h.cmake
@@ -0,0 +1,4 @@
+#define CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}"
+#define LIBEXEC_INSTALL_DIR "${LIBEXEC_INSTALL_DIR}"
+#define LIB_INSTALL_DIR "${LIB_INSTALL_DIR}"
+#define KCONF_UPDATE_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}"
diff --git a/tier1/kconfig/src/kconf_update/kconf_update.cpp b/tier1/kconfig/src/kconf_update/kconf_update.cpp
new file mode 100644
index 00000000..60a61db3
--- /dev/null
+++ b/tier1/kconfig/src/kconf_update/kconf_update.cpp
@@ -0,0 +1,967 @@
+/*
+ *
+ * This file is part of the KDE libraries
+ * Copyright (c) 2001 Waldo Bastian <bastian@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ **/
+
+#include <config-kconf.h> // CMAKE_INSTALL_PREFIX
+
+#include <QtCore/QDate>
+#include <QtCore/QFile>
+#include <QtCore/QTextStream>
+#include <QtCore/QTextCodec>
+#include <QUrl>
+#include <QTemporaryFile>
+#include <QCoreApplication>
+#include <QtCore/QDir>
+
+#include <kconfig.h>
+#include <kconfiggroup.h>
+
+#include <qstandardpaths.h>
+#include <qcommandlineparser.h>
+#include <qcommandlineoption.h>
+
+#include "kconfigutils.h"
+
+class KonfUpdate
+{
+public:
+ KonfUpdate(QCommandLineParser *parser);
+ ~KonfUpdate();
+ QStringList findUpdateFiles(bool dirtyOnly);
+
+ QTextStream &log();
+ QTextStream &logFileError();
+
+ bool checkFile(const QString &filename);
+ void checkGotFile(const QString &_file, const QString &id);
+
+ bool updateFile(const QString &filename);
+
+ void gotId(const QString &_id);
+ void gotFile(const QString &_file);
+ void gotGroup(const QString &_group);
+ void gotRemoveGroup(const QString &_group);
+ void gotKey(const QString &_key);
+ void gotRemoveKey(const QString &_key);
+ void gotAllKeys();
+ void gotAllGroups();
+ void gotOptions(const QString &_options);
+ void gotScript(const QString &_script);
+ void gotScriptArguments(const QString &_arguments);
+ void resetOptions();
+
+ void copyGroup(const KConfigBase *cfg1, const QString &group1,
+ KConfigBase *cfg2, const QString &group2);
+ void copyGroup(const KConfigGroup &cg1, KConfigGroup &cg2);
+ void copyOrMoveKey(const QStringList &srcGroupPath, const QString &srcKey, const QStringList &dstGroupPath, const QString &dstKey);
+ void copyOrMoveGroup(const QStringList &srcGroupPath, const QStringList &dstGroupPath);
+
+ QStringList parseGroupString(const QString &_str);
+
+protected:
+ KConfig *m_config;
+ QString m_currentFilename;
+ bool m_skip;
+ bool m_skipFile;
+ bool m_debug;
+ QString m_id;
+
+ QString m_oldFile;
+ QString m_newFile;
+ QString m_newFileName;
+ KConfig *m_oldConfig1; // Config to read keys from.
+ KConfig *m_oldConfig2; // Config to delete keys from.
+ KConfig *m_newConfig;
+
+ QStringList m_oldGroup;
+ QStringList m_newGroup;
+
+ bool m_bCopy;
+ bool m_bOverwrite;
+ bool m_bUseConfigInfo;
+ QString m_arguments;
+ QTextStream *m_textStream;
+ QFile *m_file;
+ QString m_line;
+ int m_lineCount;
+};
+
+KonfUpdate::KonfUpdate(QCommandLineParser * parser)
+ : m_textStream(0), m_file(0)
+{
+ bool updateAll = false;
+ m_oldConfig1 = 0;
+ m_oldConfig2 = 0;
+ m_newConfig = 0;
+
+ m_config = new KConfig("kconf_updaterc");
+ KConfigGroup cg(m_config, QString());
+
+ QStringList updateFiles;
+
+ m_debug = parser->isSet("debug");
+
+ m_bUseConfigInfo = false;
+ if (parser->isSet("check")) {
+ m_bUseConfigInfo = true;
+ QString file = QStandardPaths::locate(QStandardPaths::GenericDataLocation, "kconf_update/" + parser->value("check"));
+ if (file.isEmpty()) {
+ qWarning("File '%s' not found.", parser->value("check").toLocal8Bit().data());
+ log() << "File '" << parser->value("check") << "' passed on command line not found" << endl;
+ return;
+ }
+ updateFiles.append(file);
+ } else if (parser->positionalArguments().count()) {
+ updateFiles += parser->positionalArguments();
+ } else {
+ if (cg.readEntry("autoUpdateDisabled", false))
+ return;
+ updateFiles = findUpdateFiles(true);
+ updateAll = true;
+ }
+
+ for (QStringList::ConstIterator it = updateFiles.constBegin();
+ it != updateFiles.constEnd();
+ ++it) {
+ updateFile(*it);
+ }
+
+ if (updateAll && !cg.readEntry("updateInfoAdded", false)) {
+ cg.writeEntry("updateInfoAdded", true);
+ updateFiles = findUpdateFiles(false);
+
+ for (QStringList::ConstIterator it = updateFiles.constBegin();
+ it != updateFiles.constEnd();
+ ++it) {
+ checkFile(*it);
+ }
+ updateFiles.clear();
+ }
+}
+
+KonfUpdate::~KonfUpdate()
+{
+ delete m_config;
+ delete m_file;
+ delete m_textStream;
+}
+
+QTextStream & operator<<(QTextStream & stream, const QStringList & lst)
+{
+ stream << lst.join(", ");
+ return stream;
+}
+
+QTextStream &
+KonfUpdate::log()
+{
+ if (!m_textStream) {
+ QString dir = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1Char('/') + "kconf_update/log";
+ QDir().mkpath(dir);
+ QString file = dir + "/update.log";
+ m_file = new QFile(file);
+ if (m_file->open(QIODevice::WriteOnly | QIODevice::Append)) {
+ m_textStream = new QTextStream(m_file);
+ } else {
+ // Error
+ m_textStream = new QTextStream(stderr, QIODevice::WriteOnly);
+ }
+ }
+
+ (*m_textStream) << QDateTime::currentDateTime().toString(Qt::ISODate) << " ";
+
+ return *m_textStream;
+}
+
+QTextStream &
+KonfUpdate::logFileError()
+{
+ return log() << m_currentFilename << ':' << m_lineCount << ":'" << m_line << "': ";
+}
+
+QStringList KonfUpdate::findUpdateFiles(bool dirtyOnly)
+{
+ QStringList result;
+
+ const QStringList dirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, "kconf_update", QStandardPaths::LocateDirectory);
+ Q_FOREACH(const QString& dir, dirs) {
+ const QStringList fileNames = QDir(dir).entryList(QStringList() << QStringLiteral("*.upd"));
+ Q_FOREACH(const QString& fileName, fileNames) {
+ const QString file = dir + '/' + fileName;
+ QFileInfo info(file);
+
+ KConfigGroup cg(m_config, fileName);
+ const QDateTime ctime = QDateTime::fromTime_t(cg.readEntry("ctime", 0));
+ const QDateTime mtime = QDateTime::fromTime_t(cg.readEntry("mtime", 0));
+ if (!dirtyOnly ||
+ (ctime != info.created()) || (mtime != info.lastModified())) {
+ result.append(file);
+ }
+ }
+ }
+ return result;
+}
+
+bool KonfUpdate::checkFile(const QString &filename)
+{
+ m_currentFilename = filename;
+ int i = m_currentFilename.lastIndexOf('/');
+ if (i != -1) {
+ m_currentFilename = m_currentFilename.mid(i + 1);
+ }
+ m_skip = true;
+ QFile file(filename);
+ if (!file.open(QIODevice::ReadOnly)) {
+ return false;
+ }
+
+ QTextStream ts(&file);
+ ts.setCodec(QTextCodec::codecForName("ISO-8859-1"));
+ int lineCount = 0;
+ resetOptions();
+ QString id;
+ while (!ts.atEnd()) {
+ QString line = ts.readLine().trimmed();
+ lineCount++;
+ if (line.isEmpty() || (line[0] == '#')) {
+ continue;
+ }
+ if (line.startsWith("Id=")) {
+ id = m_currentFilename + ':' + line.mid(3);
+ } else if (line.startsWith("File=")) {
+ checkGotFile(line.mid(5), id);
+ }
+ }
+
+ return true;
+}
+
+void KonfUpdate::checkGotFile(const QString &_file, const QString &id)
+{
+ QString file;
+ int i = _file.indexOf(',');
+ if (i == -1) {
+ file = _file.trimmed();
+ } else {
+ file = _file.mid(i + 1).trimmed();
+ }
+
+// qDebug("File %s, id %s", file.toLatin1().constData(), id.toLatin1().constData());
+
+ KConfig cfg(file, KConfig::SimpleConfig);
+ KConfigGroup cg(&cfg, "$Version");
+ QStringList ids = cg.readEntry("update_info", QStringList());
+ if (ids.contains(id)) {
+ return;
+ }
+ ids.append(id);
+ cg.writeEntry("update_info", ids);
+}
+
+/**
+ * Syntax:
+ * # Comment
+ * Id=id
+ * File=oldfile[,newfile]
+ * AllGroups
+ * Group=oldgroup[,newgroup]
+ * RemoveGroup=oldgroup
+ * Options=[copy,][overwrite,]
+ * Key=oldkey[,newkey]
+ * RemoveKey=ldkey
+ * AllKeys
+ * Keys= [Options](AllKeys|(Key|RemoveKey)*)
+ * ScriptArguments=arguments
+ * Script=scriptfile[,interpreter]
+ *
+ * Sequence:
+ * (Id,(File(Group,Keys)*)*)*
+ **/
+bool KonfUpdate::updateFile(const QString &filename)
+{
+ m_currentFilename = filename;
+ int i = m_currentFilename.lastIndexOf('/');
+ if (i != -1) {
+ m_currentFilename = m_currentFilename.mid(i + 1);
+ }
+ m_skip = true;
+ QFile file(filename);
+ if (!file.open(QIODevice::ReadOnly)) {
+ return false;
+ }
+
+ log() << "Checking update-file '" << filename << "' for new updates" << endl;
+
+ QTextStream ts(&file);
+ ts.setCodec(QTextCodec::codecForName("ISO-8859-1"));
+ m_lineCount = 0;
+ resetOptions();
+ while (!ts.atEnd()) {
+ m_line = ts.readLine().trimmed();
+ m_lineCount++;
+ if (m_line.isEmpty() || (m_line[0] == '#')) {
+ continue;
+ }
+ if (m_line.startsWith(QLatin1String("Id="))) {
+ gotId(m_line.mid(3));
+ } else if (m_skip) {
+ continue;
+ } else if (m_line.startsWith(QLatin1String("Options="))) {
+ gotOptions(m_line.mid(8));
+ } else if (m_line.startsWith(QLatin1String("File="))) {
+ gotFile(m_line.mid(5));
+ } else if (m_skipFile) {
+ continue;
+ } else if (m_line.startsWith(QLatin1String("Group="))) {
+ gotGroup(m_line.mid(6));
+ } else if (m_line.startsWith(QLatin1String("RemoveGroup="))) {
+ gotRemoveGroup(m_line.mid(12));
+ resetOptions();
+ } else if (m_line.startsWith(QLatin1String("Script="))) {
+ gotScript(m_line.mid(7));
+ resetOptions();
+ } else if (m_line.startsWith(QLatin1String("ScriptArguments="))) {
+ gotScriptArguments(m_line.mid(16));
+ } else if (m_line.startsWith(QLatin1String("Key="))) {
+ gotKey(m_line.mid(4));
+ resetOptions();
+ } else if (m_line.startsWith(QLatin1String("RemoveKey="))) {
+ gotRemoveKey(m_line.mid(10));
+ resetOptions();
+ } else if (m_line == "AllKeys") {
+ gotAllKeys();
+ resetOptions();
+ } else if (m_line == "AllGroups") {
+ gotAllGroups();
+ resetOptions();
+ } else {
+ logFileError() << "Parse error" << endl;
+ }
+ }
+ // Flush.
+ gotId(QString());
+
+ QFileInfo info(filename);
+ KConfigGroup cg(m_config, m_currentFilename);
+ cg.writeEntry("ctime", info.created().toTime_t());
+ cg.writeEntry("mtime", info.lastModified().toTime_t());
+ cg.sync();
+ return true;
+}
+
+
+
+void KonfUpdate::gotId(const QString &_id)
+{
+ if (!m_id.isEmpty() && !m_skip) {
+ KConfigGroup cg(m_config, m_currentFilename);
+
+ QStringList ids = cg.readEntry("done", QStringList());
+ if (!ids.contains(m_id)) {
+ ids.append(m_id);
+ cg.writeEntry("done", ids);
+ cg.sync();
+ }
+ }
+
+ // Flush pending changes
+ gotFile(QString());
+ KConfigGroup cg(m_config, m_currentFilename);
+
+ QStringList ids = cg.readEntry("done", QStringList());
+ if (!_id.isEmpty()) {
+ if (ids.contains(_id)) {
+ //qDebug("Id '%s' was already in done-list", _id.toLatin1().constData());
+ if (!m_bUseConfigInfo) {
+ m_skip = true;
+ return;
+ }
+ }
+ m_skip = false;
+ m_skipFile = false;
+ m_id = _id;
+ if (m_bUseConfigInfo) {
+ log() << m_currentFilename << ": Checking update '" << _id << "'" << endl;
+ } else {
+ log() << m_currentFilename << ": Found new update '" << _id << "'" << endl;
+ }
+ }
+}
+
+void KonfUpdate::gotFile(const QString &_file)
+{
+ // Reset group
+ gotGroup(QString());
+
+ if (!m_oldFile.isEmpty()) {
+ // Close old file.
+ delete m_oldConfig1;
+ m_oldConfig1 = 0;
+
+ KConfigGroup cg(m_oldConfig2, "$Version");
+ QStringList ids = cg.readEntry("update_info", QStringList());
+ QString cfg_id = m_currentFilename + ':' + m_id;
+ if (!ids.contains(cfg_id) && !m_skip) {
+ ids.append(cfg_id);
+ cg.writeEntry("update_info", ids);
+ }
+ cg.sync();
+ delete m_oldConfig2;
+ m_oldConfig2 = 0;
+
+ QString file = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + QLatin1Char('/') + m_oldFile;
+ QFileInfo info(file);
+ if (info.exists() && info.size() == 0) {
+ // Delete empty file.
+ QFile::remove(file);
+ }
+
+ m_oldFile.clear();
+ }
+ if (!m_newFile.isEmpty()) {
+ // Close new file.
+ KConfigGroup cg(m_newConfig, "$Version");
+ QStringList ids = cg.readEntry("update_info", QStringList());
+ QString cfg_id = m_currentFilename + ':' + m_id;
+ if (!ids.contains(cfg_id) && !m_skip) {
+ ids.append(cfg_id);
+ cg.writeEntry("update_info", ids);
+ }
+ m_newConfig->sync();
+ delete m_newConfig;
+ m_newConfig = 0;
+
+ m_newFile.clear();
+ }
+ m_newConfig = 0;
+
+ int i = _file.indexOf(',');
+ if (i == -1) {
+ m_oldFile = _file.trimmed();
+ } else {
+ m_oldFile = _file.left(i).trimmed();
+ m_newFile = _file.mid(i + 1).trimmed();
+ if (m_oldFile == m_newFile) {
+ m_newFile.clear();
+ }
+ }
+
+ if (!m_oldFile.isEmpty()) {
+ m_oldConfig2 = new KConfig(m_oldFile, KConfig::NoGlobals);
+ QString cfg_id = m_currentFilename + ':' + m_id;
+ KConfigGroup cg(m_oldConfig2, "$Version");
+ QStringList ids = cg.readEntry("update_info", QStringList());
+ if (ids.contains(cfg_id)) {
+ m_skip = true;
+ m_newFile.clear();
+ log() << m_currentFilename << ": Skipping update '" << m_id << "'" << endl;
+ }
+
+ if (!m_newFile.isEmpty()) {
+ m_newConfig = new KConfig(m_newFile, KConfig::NoGlobals);
+ KConfigGroup cg(m_newConfig, "$Version");
+ ids = cg.readEntry("update_info", QStringList());
+ if (ids.contains(cfg_id)) {
+ m_skip = true;
+ log() << m_currentFilename << ": Skipping update '" << m_id << "'" << endl;
+ }
+ } else {
+ m_newConfig = m_oldConfig2;
+ }
+
+ m_oldConfig1 = new KConfig(m_oldFile, KConfig::NoGlobals);
+ } else {
+ m_newFile.clear();
+ }
+ m_newFileName = m_newFile;
+ if (m_newFileName.isEmpty()) {
+ m_newFileName = m_oldFile;
+ }
+
+ m_skipFile = false;
+ if (!m_oldFile.isEmpty()) { // if File= is specified, it doesn't exist, is empty or contains only kconf_update's [$Version] group, skip
+ if (m_oldConfig1 != NULL
+ && (m_oldConfig1->groupList().isEmpty()
+ || (m_oldConfig1->groupList().count() == 1 && m_oldConfig1->groupList().first() == "$Version"))) {
+ log() << m_currentFilename << ": File '" << m_oldFile << "' does not exist or empty, skipping" << endl;
+ m_skipFile = true;
+ }
+ }
+}
+
+QStringList KonfUpdate::parseGroupString(const QString &str)
+{
+ bool ok;
+ QString error;
+ QStringList lst = KConfigUtils::parseGroupString(str, &ok, &error);
+ if (!ok) {
+ logFileError() << error;
+ }
+ return lst;
+}
+
+void KonfUpdate::gotGroup(const QString &_group)
+{
+ QString group = _group.trimmed();
+ if (group.isEmpty()) {
+ m_oldGroup = m_newGroup = QStringList();
+ return;
+ }
+
+ QStringList tokens = group.split(',');
+ m_oldGroup = parseGroupString(tokens.at(0));
+ if (tokens.count() == 1) {
+ m_newGroup = m_oldGroup;
+ } else {
+ m_newGroup = parseGroupString(tokens.at(1));
+ }
+}
+
+void KonfUpdate::gotRemoveGroup(const QString &_group)
+{
+ m_oldGroup = parseGroupString(_group);
+
+ if (!m_oldConfig1) {
+ logFileError() << "RemoveGroup without previous File specification" << endl;
+ return;
+ }
+
+ KConfigGroup cg = KConfigUtils::openGroup(m_oldConfig2, m_oldGroup);
+ if (!cg.exists()) {
+ return;
+ }
+ // Delete group.
+ cg.deleteGroup();
+ log() << m_currentFilename << ": RemoveGroup removes group " << m_oldFile << ":" << m_oldGroup << endl;
+}
+
+
+void KonfUpdate::gotKey(const QString &_key)
+{
+ QString oldKey, newKey;
+ int i = _key.indexOf(',');
+ if (i == -1) {
+ oldKey = _key.trimmed();
+ newKey = oldKey;
+ } else {
+ oldKey = _key.left(i).trimmed();
+ newKey = _key.mid(i + 1).trimmed();
+ }
+
+ if (oldKey.isEmpty() || newKey.isEmpty()) {
+ logFileError() << "Key specifies invalid key" << endl;
+ return;
+ }
+ if (!m_oldConfig1) {
+ logFileError() << "Key without previous File specification" << endl;
+ return;
+ }
+ copyOrMoveKey(m_oldGroup, oldKey, m_newGroup, newKey);
+}
+
+void KonfUpdate::copyOrMoveKey(const QStringList &srcGroupPath, const QString &srcKey, const QStringList &dstGroupPath, const QString &dstKey)
+{
+ KConfigGroup dstCg = KConfigUtils::openGroup(m_newConfig, dstGroupPath);
+ if (!m_bOverwrite && dstCg.hasKey(dstKey)) {
+ log() << m_currentFilename << ": Skipping " << m_newFileName << ":" << dstCg.name() << ":" << dstKey << ", already exists." << endl;
+ return;
+ }
+
+ KConfigGroup srcCg = KConfigUtils::openGroup(m_oldConfig1, srcGroupPath);
+ if (!srcCg.hasKey(srcKey))
+ return;
+ QString value = srcCg.readEntry(srcKey, QString());
+ log() << m_currentFilename << ": Updating " << m_newFileName << ":" << dstCg.name() << ":" << dstKey << " to '" << value << "'" << endl;
+ dstCg.writeEntry(dstKey, value);
+
+ if (m_bCopy) {
+ return; // Done.
+ }
+
+ // Delete old entry
+ if (m_oldConfig2 == m_newConfig
+ && srcGroupPath == dstGroupPath
+ && srcKey == dstKey) {
+ return; // Don't delete!
+ }
+ KConfigGroup srcCg2 = KConfigUtils::openGroup(m_oldConfig2, srcGroupPath);
+ srcCg2.deleteEntry(srcKey);
+ log() << m_currentFilename << ": Removing " << m_oldFile << ":" << srcCg2.name() << ":" << srcKey << ", moved." << endl;
+}
+
+void KonfUpdate::copyOrMoveGroup(const QStringList &srcGroupPath, const QStringList &dstGroupPath)
+{
+ KConfigGroup cg = KConfigUtils::openGroup(m_oldConfig1, srcGroupPath);
+
+ // Keys
+ Q_FOREACH(const QString &key, cg.keyList()) {
+ copyOrMoveKey(srcGroupPath, key, dstGroupPath, key);
+ }
+
+ // Subgroups
+ Q_FOREACH(const QString &group, cg.groupList()) {
+ QStringList groupPath = QStringList() << group;
+ copyOrMoveGroup(srcGroupPath + groupPath, dstGroupPath + groupPath);
+ }
+}
+
+void KonfUpdate::gotRemoveKey(const QString &_key)
+{
+ QString key = _key.trimmed();
+
+ if (key.isEmpty()) {
+ logFileError() << "RemoveKey specifies invalid key" << endl;
+ return;
+ }
+
+ if (!m_oldConfig1) {
+ logFileError() << "Key without previous File specification" << endl;
+ return;
+ }
+
+ KConfigGroup cg1 = KConfigUtils::openGroup(m_oldConfig1, m_oldGroup);
+ if (!cg1.hasKey(key)) {
+ return;
+ }
+ log() << m_currentFilename << ": RemoveKey removes " << m_oldFile << ":" << m_oldGroup << ":" << key << endl;
+
+ // Delete old entry
+ KConfigGroup cg2 = KConfigUtils::openGroup(m_oldConfig2, m_oldGroup);
+ cg2.deleteEntry(key);
+ /*if (m_oldConfig2->deleteGroup(m_oldGroup, KConfig::Normal)) { // Delete group if empty.
+ log() << m_currentFilename << ": Removing empty group " << m_oldFile << ":" << m_oldGroup << endl;
+ } (this should be automatic)*/
+}
+
+void KonfUpdate::gotAllKeys()
+{
+ if (!m_oldConfig1) {
+ logFileError() << "AllKeys without previous File specification" << endl;
+ return;
+ }
+
+ copyOrMoveGroup(m_oldGroup, m_newGroup);
+}
+
+void KonfUpdate::gotAllGroups()
+{
+ if (!m_oldConfig1) {
+ logFileError() << "AllGroups without previous File specification" << endl;
+ return;
+ }
+
+ const QStringList allGroups = m_oldConfig1->groupList();
+ for (QStringList::ConstIterator it = allGroups.begin();
+ it != allGroups.end(); ++it) {
+ m_oldGroup = QStringList() << *it;
+ m_newGroup = m_oldGroup;
+ gotAllKeys();
+ }
+}
+
+void KonfUpdate::gotOptions(const QString &_options)
+{
+ const QStringList options = _options.split(',');
+ for (QStringList::ConstIterator it = options.begin();
+ it != options.end();
+ ++it) {
+ if ((*it).toLower().trimmed() == "copy") {
+ m_bCopy = true;
+ }
+
+ if ((*it).toLower().trimmed() == "overwrite") {
+ m_bOverwrite = true;
+ }
+ }
+}
+
+void KonfUpdate::copyGroup(const KConfigBase *cfg1, const QString &group1,
+ KConfigBase *cfg2, const QString &group2)
+{
+ KConfigGroup cg1(cfg1, group1);
+ KConfigGroup cg2(cfg2, group2);
+ copyGroup(cg1, cg2);
+}
+
+void KonfUpdate::copyGroup(const KConfigGroup &cg1, KConfigGroup &cg2)
+{
+ // Copy keys
+ QMap<QString, QString> list = cg1.entryMap();
+ for (QMap<QString, QString>::ConstIterator it = list.constBegin();
+ it != list.constEnd(); ++it) {
+ if (m_bOverwrite || !cg2.hasKey(it.key())) {
+ cg2.writeEntry(it.key(), it.value());
+ }
+ }
+
+ // Copy subgroups
+ Q_FOREACH(const QString &group, cg1.groupList()) {
+ copyGroup(&cg1, group, &cg2, group);
+ }
+}
+
+void KonfUpdate::gotScriptArguments(const QString &_arguments)
+{
+ m_arguments = _arguments;
+}
+
+void KonfUpdate::gotScript(const QString &_script)
+{
+ QString script, interpreter;
+ int i = _script.indexOf(',');
+ if (i == -1) {
+ script = _script.trimmed();
+ } else {
+ script = _script.left(i).trimmed();
+ interpreter = _script.mid(i + 1).trimmed();
+ }
+
+
+ if (script.isEmpty()) {
+ logFileError() << "Script fails to specify filename";
+ m_skip = true;
+ return;
+ }
+
+
+
+ QString path = QStandardPaths::locate(QStandardPaths::GenericDataLocation, "kconf_update/" + script);
+ if (path.isEmpty()) {
+ if (interpreter.isEmpty()) {
+ // KDE4: this was looking into locate("lib", "kconf_update_bin/"). But QStandardPaths doesn't know the lib dirs.
+ // Let's look in the install prefix and in PATH.
+ path = CMAKE_INSTALL_PREFIX "/" LIB_INSTALL_DIR "/kconf_update_bin/" + script;
+ if (QFile::exists(path))
+ path = QStandardPaths::findExecutable(script);
+ }
+
+ if (path.isEmpty()) {
+ logFileError() << "Script '" << script << "' not found" << endl;
+ m_skip = true;
+ return;
+ }
+ }
+
+ if (!m_arguments.isNull()) {
+ log() << m_currentFilename << ": Running script '" << script << "' with arguments '" << m_arguments << "'" << endl;
+ } else {
+ log() << m_currentFilename << ": Running script '" << script << "'" << endl;
+ }
+
+ QString cmd;
+ if (interpreter.isEmpty()) {
+ cmd = path;
+ } else {
+ cmd = interpreter + ' ' + path;
+ }
+
+ if (!m_arguments.isNull()) {
+ cmd += ' ';
+ cmd += m_arguments;
+ }
+
+ QTemporaryFile scriptIn;
+ scriptIn.open();
+ QTemporaryFile scriptOut;
+ scriptOut.open();
+ QTemporaryFile scriptErr;
+ scriptErr.open();
+
+ int result;
+ if (m_oldConfig1) {
+ if (m_debug) {
+ scriptIn.setAutoRemove(false);
+ log() << "Script input stored in " << scriptIn.fileName() << endl;
+ }
+ KConfig cfg(scriptIn.fileName(), KConfig::SimpleConfig);
+
+ if (m_oldGroup.isEmpty()) {
+ // Write all entries to tmpFile;
+ const QStringList grpList = m_oldConfig1->groupList();
+ for (QStringList::ConstIterator it = grpList.begin();
+ it != grpList.end();
+ ++it) {
+ copyGroup(m_oldConfig1, *it, &cfg, *it);
+ }
+ } else {
+ KConfigGroup cg1 = KConfigUtils::openGroup(m_oldConfig1, m_oldGroup);
+ KConfigGroup cg2(&cfg, QString());
+ copyGroup(cg1, cg2);
+ }
+ cfg.sync();
+#ifndef _WIN32_WCE
+ result = system(QFile::encodeName(QString("%1 < %2 > %3 2> %4").arg(cmd, scriptIn.fileName(), scriptOut.fileName(), scriptErr.fileName())).constData());
+#else
+ QString path_ = QDir::convertSeparators ( QFileInfo ( cmd ).absoluteFilePath() );
+ QString file_ = QFileInfo ( cmd ).fileName();
+ SHELLEXECUTEINFO execInfo;
+ memset ( &execInfo,0,sizeof ( execInfo ) );
+ execInfo.cbSize = sizeof ( execInfo );
+ execInfo.fMask = SEE_MASK_FLAG_NO_UI;
+ execInfo.lpVerb = L"open";
+ execInfo.lpFile = (LPCWSTR) path_.utf16();
+ execInfo.lpDirectory = (LPCWSTR) file_.utf16();
+ execInfo.lpParameters = (LPCWSTR) QString(" < %1 > %2 2> %3").arg( scriptIn.fileName(), scriptOut.fileName(), scriptErr.fileName()).utf16();
+ result = ShellExecuteEx ( &execInfo );
+ if (result != 0)
+ {
+ result = 0;
+ }
+ else
+ {
+ result = -1;
+ }
+#endif
+ } else {
+ // No config file
+#ifndef _WIN32_WCE
+ result = system(QFile::encodeName(QString("%1 2> %2").arg(cmd, scriptErr.fileName())).constData());
+#else
+ QString path_ = QDir::convertSeparators ( QFileInfo ( cmd ).absoluteFilePath() );
+ QString file_ = QFileInfo ( cmd ).fileName();
+ SHELLEXECUTEINFO execInfo;
+ memset ( &execInfo,0,sizeof ( execInfo ) );
+ execInfo.cbSize = sizeof ( execInfo );
+ execInfo.fMask = SEE_MASK_FLAG_NO_UI;
+ execInfo.lpVerb = L"open";
+ execInfo.lpFile = (LPCWSTR) path_.utf16();
+ execInfo.lpDirectory = (LPCWSTR) file_.utf16();
+ execInfo.lpParameters = (LPCWSTR) QString(" 2> %1").arg( scriptErr.fileName()).utf16();
+ result = ShellExecuteEx ( &execInfo );
+ if (result != 0)
+ {
+ result = 0;
+ }
+ else
+ {
+ result = -1;
+ }
+#endif
+ }
+
+ // Copy script stderr to log file
+ {
+ QFile output(scriptErr.fileName());
+ if (output.open(QIODevice::ReadOnly)) {
+ QTextStream ts(&output);
+ ts.setCodec(QTextCodec::codecForName("UTF-8"));
+ while (!ts.atEnd()) {
+ QString line = ts.readLine();
+ log() << "[Script] " << line << endl;
+ }
+ }
+ }
+
+ if (result) {
+ log() << m_currentFilename << ": !! An error occurred while running '" << cmd << "'" << endl;
+ return;
+ }
+
+ if (!m_oldConfig1) {
+ return; // Nothing to merge
+ }
+
+ if (m_debug) {
+ scriptOut.setAutoRemove(false);
+ log() << "Script output stored in " << scriptOut.fileName() << endl;
+ }
+
+ // Deleting old entries
+ {
+ QStringList group = m_oldGroup;
+ QFile output(scriptOut.fileName());
+ if (output.open(QIODevice::ReadOnly)) {
+ QTextStream ts(&output);
+ ts.setCodec(QTextCodec::codecForName("UTF-8"));
+ while (!ts.atEnd()) {
+ QString line = ts.readLine();
+ if (line.startsWith('[')) {
+ group = parseGroupString(line);
+ } else if (line.startsWith(QLatin1String("# DELETE "))) {
+ QString key = line.mid(9);
+ if (key[0] == '[') {
+ int j = key.lastIndexOf(']') + 1;
+ if (j > 0) {
+ group = parseGroupString(key.left(j));
+ key = key.mid(j);
+ }
+ }
+ KConfigGroup cg = KConfigUtils::openGroup(m_oldConfig2, group);
+ cg.deleteEntry(key);
+ log() << m_currentFilename << ": Script removes " << m_oldFile << ":" << group << ":" << key << endl;
+ /*if (m_oldConfig2->deleteGroup(group, KConfig::Normal)) { // Delete group if empty.
+ log() << m_currentFilename << ": Removing empty group " << m_oldFile << ":" << group << endl;
+ } (this should be automatic)*/
+ } else if (line.startsWith(QLatin1String("# DELETEGROUP"))) {
+ QString str = line.mid(13).trimmed();
+ if (!str.isEmpty()) {
+ group = parseGroupString(str);
+ }
+ KConfigGroup cg = KConfigUtils::openGroup(m_oldConfig2, group);
+ cg.deleteGroup();
+ log() << m_currentFilename << ": Script removes group " << m_oldFile << ":" << group << endl;
+ }
+ }
+ }
+ }
+
+ // Merging in new entries.
+ KConfig scriptOutConfig(scriptOut.fileName(), KConfig::NoGlobals);
+ if (m_newGroup.isEmpty()) {
+ // Copy "default" keys as members of "default" keys
+ copyGroup(&scriptOutConfig, QString(), m_newConfig, QString());
+ } else {
+ // Copy default keys as members of m_newGroup
+ KConfigGroup srcCg = KConfigUtils::openGroup(&scriptOutConfig, QStringList());
+ KConfigGroup dstCg = KConfigUtils::openGroup(m_newConfig, m_newGroup);
+ copyGroup(srcCg, dstCg);
+ }
+ Q_FOREACH(const QString &group, scriptOutConfig.groupList()) {
+ copyGroup(&scriptOutConfig, group, m_newConfig, group);
+ }
+}
+
+void KonfUpdate::resetOptions()
+{
+ m_bCopy = false;
+ m_bOverwrite = false;
+ m_arguments.clear();
+}
+
+
+int main(int argc, char **argv)
+{
+ QCoreApplication app(argc, argv);
+ app.setApplicationVersion("1.1");
+
+ QCommandLineParser parser;
+ parser.addVersionOption();
+ parser.setApplicationDescription(QCoreApplication::translate("main", "KDE Tool for updating user configuration files"));
+ parser.addHelpOption();
+ parser.addOption(QCommandLineOption(QStringList() << "debug", QCoreApplication::translate("main", "Keep output results from scripts")));
+ parser.addOption(QCommandLineOption(QStringList() << "check", QCoreApplication::translate("main", "Check whether config file itself requires updating"), "update-file"));
+ //parser.addOption(QCommandLineOption(QStringList() << "+[file]", QCoreApplication::translate("main", "File to read update instructions from")));
+
+ // TODO aboutData.addAuthor(ki18n("Waldo Bastian"), KLocalizedString(), "bastian@kde.org");
+
+ parser.process(app);
+ KonfUpdate konfUpdate(&parser);
+
+ return 0;
+}
diff --git a/tier1/kconfig/src/kconf_update/kconfigutils.cpp b/tier1/kconfig/src/kconf_update/kconfigutils.cpp
new file mode 100644
index 00000000..f2663e13
--- /dev/null
+++ b/tier1/kconfig/src/kconf_update/kconfigutils.cpp
@@ -0,0 +1,127 @@
+/* This file is part of the KDE libraries
+ Copyright 2010 Canonical Ltd
+ Author: Aurélien Gâteau <aurelien.gateau@canonical.com>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License (LGPL) as published by the Free Software Foundation;
+ either version 2 of the License, or (at your option) any later
+ version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#include "kconfigutils.h"
+
+// KDE
+#include <kconfig.h>
+#include <kconfiggroup.h>
+
+namespace KConfigUtils
+{
+
+bool hasGroup(KConfig *config, const QStringList &lst)
+{
+ KConfigGroup group = openGroup(config, lst);
+ return group.exists();
+}
+
+KConfigGroup openGroup(KConfig *config, const QStringList &_lst)
+{
+ if (_lst.isEmpty()) {
+ return KConfigGroup(config, QString());
+ }
+
+ QStringList lst = _lst;
+
+ KConfigGroup cg;
+ for (cg = KConfigGroup(config, lst.takeFirst()); !lst.isEmpty(); cg = KConfigGroup(&cg, lst.takeFirst())) {}
+ return cg;
+}
+
+QStringList parseGroupString(const QString &_str, bool *ok, QString *error)
+{
+ QString str = unescapeString(_str.trimmed(), ok, error);
+ if (!ok) {
+ return QStringList();
+ }
+
+ *ok = true;
+ if (str[0] != '[') {
+ // Simplified notation, no '['
+ return QStringList() << str;
+ }
+
+ if (!str.endsWith(']')) {
+ *ok = false;
+ *error = QString("Missing closing ']' in %1").arg(_str);
+ return QStringList();
+ }
+ // trim outer brackets
+ str.chop(1);
+ str.remove(0, 1);
+
+ return str.split("][");
+}
+
+QString unescapeString(const QString &src, bool *ok, QString *error)
+{
+ QString dst;
+ int length = src.length();
+ for (int pos = 0; pos < length; ++pos) {
+ QChar ch = src.at(pos);
+ if (ch != '\\') {
+ dst += ch;
+ } else {
+ ++pos;
+ if (pos == length) {
+ *ok = false;
+ *error = QString("Unfinished escape sequence in %1").arg(src);
+ return QString();
+ }
+ ch = src.at(pos);
+ if (ch == 's') {
+ dst += ' ';
+ } else if (ch == 't') {
+ dst += '\t';
+ } else if (ch == 'n') {
+ dst += '\n';
+ } else if (ch == 'r') {
+ dst += '\r';
+ } else if (ch == '\\') {
+ dst += '\\';
+ } else if (ch == 'x') {
+ if (pos + 2 < length) {
+ char value = src.mid(pos + 1, 2).toInt(ok, 16);
+ if (*ok) {
+ dst += QChar::fromLatin1(value);
+ pos += 2;
+ } else {
+ *error = QString("Invalid hex escape sequence at column %1 in %2").arg(pos).arg(src);
+ return QString();
+ }
+ } else {
+ *ok = false;
+ *error = QString("Unfinished hex escape sequence at column %1 in %2").arg(pos).arg(src);
+ return QString();
+ }
+ } else {
+ *ok = false;
+ *error = QString("Invalid escape sequence at column %1 in %2").arg(pos).arg(src);
+ return QString();
+ }
+ }
+ }
+
+ *ok = true;
+ return dst;
+}
+
+} // namespace
diff --git a/tier1/kconfig/src/kconf_update/kconfigutils.h b/tier1/kconfig/src/kconf_update/kconfigutils.h
new file mode 100644
index 00000000..606495e6
--- /dev/null
+++ b/tier1/kconfig/src/kconf_update/kconfigutils.h
@@ -0,0 +1,43 @@
+/* This file is part of the KDE libraries
+ Copyright 2010 Canonical Ltd
+ Author: Aurélien Gâteau <aurelien.gateau@canonical.com>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License (LGPL) as published by the Free Software Foundation;
+ either version 2 of the License, or (at your option) any later
+ version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#ifndef KCONFIGUTILS_H
+#define KCONFIGUTILS_H
+
+class QString;
+class QStringList;
+
+class KConfig;
+class KConfigGroup;
+
+namespace KConfigUtils
+{
+
+bool hasGroup(KConfig *, const QStringList &);
+
+KConfigGroup openGroup(KConfig *, const QStringList &);
+
+QStringList parseGroupString(const QString &str, bool *ok, QString *error);
+
+QString unescapeString(const QString &str, bool *ok, QString *error);
+
+} // namespace
+
+#endif /* KCONFIGUTILS_H */
diff --git a/tier1/kconfig/src/kconfig_compiler/CMakeLists.txt b/tier1/kconfig/src/kconfig_compiler/CMakeLists.txt
new file mode 100644
index 00000000..31726df1
--- /dev/null
+++ b/tier1/kconfig/src/kconfig_compiler/CMakeLists.txt
@@ -0,0 +1,15 @@
+
+
+set(kconfig_compiler_SRCS kconfig_compiler.cpp)
+
+
+add_executable(kconfig_compiler ${kconfig_compiler_SRCS})
+add_executable(KF5::kconfig_compiler ALIAS kconfig_compiler)
+
+find_package(Qt5Xml 5.2.0 REQUIRED NO_MODULE)
+
+target_link_libraries(kconfig_compiler Qt5::Xml)
+
+# "export" this target too so we can use the LOCATION property of the imported target in
+# FindKDE4Internal.cmake to get the full path to the installed executable instead of using FIND_PROGRAM(), Alex
+install(TARGETS kconfig_compiler EXPORT KF5ConfigTargets ${INSTALL_TARGETS_DEFAULT_ARGS} )
diff --git a/tier1/kconfig/src/kconfig_compiler/README.dox b/tier1/kconfig/src/kconfig_compiler/README.dox
new file mode 100644
index 00000000..b9606f1d
--- /dev/null
+++ b/tier1/kconfig/src/kconfig_compiler/README.dox
@@ -0,0 +1,446 @@
+/**
+\page kconfig_compiler The KDE Configuration Compiler
+
+kconfig_compiler generates C++ source code from an XML file containing
+information about configuration options (.kcfg) and a file that provides
+the code generation options (.kcfgc) The generated class is based on
+KConfigSkeleton and provides an API for the application to access its
+configuration data.
+
+The generated C++ source code is output to a .h and a .cpp file, whose base
+name is the same as that of the .kcfgc file.
+
+<h2>XML description of the configuration options</h2>
+
+The structure of the .kcfg file is described by its DTD kcfg.xsd.
+
+The \<kcfgfile\> tag may contain either the "name" attribute, which should be the name
+of the configuration file described, or the "arg" attribute, which, if set to
+"true", will allow you to pass the KSharedConfig::Ptr object to use.
+
+If neither "name" nor "arg" is set, the default configuration file
+("\<appname\>rc") will be used.
+
+The \<include\> tags are optional and may contain C++ header files that
+are needed to compile the code needed to compute default values. To generate
+a \#include "..." statement instead of \#include \<...\>, enclose the header
+file name in double quotes (e.g. \<include\>"header.h"\</include\>).
+
+The remaining entries in the XML file are grouped by the tag \<group\>
+which describes the corresponding group in the configuration file.
+
+The individual entries must have at least a name or a key. The key is used
+as the key in the config file, while the name is used to create accessor and
+modifier functions. If \<key\> is given, but not \<name\>, the name is
+constructed by removing all spaces from \<key\>. If \<name\> is given, but
+not \<key\>, the key is the same as \<name\>.
+
+An entry must also have a type. The list of allowable types is
+specified in the DTD and loosely follows the list of types supported
+by the QVariant with exception of the clearly binary types
+(e.g. Pixmap, Image...) which are not supported. Besides those basic
+types the following special types are supported:
+
+- Path This is a string that is specially treated as a file-path.
+ In particular paths in the home directory are prefixed with $HOME in
+ when being stored in the configuration file.
+
+- Enum This indicates an enumeration. The possible enum values and optional
+ enum name should be provided via the \<choices\> tag. Enum values are
+ accessed as integers by the application but stored as strings in the
+ configuration file. This makes it possible to add more values at a later
+ date without breaking compatibility.
+
+- IntList This indicates a list of integers. This information is provided
+ to the application as QValueList<int>. Useful for storing QSplitter
+ geometries.
+
+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 \<default\> tag
+should contain the code="true" attribute. The contents of the \<default\>
+tag is then considered to be a C++ expression. Note that in this case you
+might have to add an \<include\> tag as described above, or a
+SourceIncludeFiles entry in the .kcfgc file as described below, so that the
+code which computes the default value can be compiled.
+
+Additional code for computing default values can be provided outside any
+entry definition via the \<code\> tag. The contents of the \<code\> 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.
+
+<h2>Code generation options</h2>
+
+The options for generating the C++ sources are read from the file with the
+extension .kcfgc. To generate a class add the corresponding kcfgc file to the
+SOURCES line in the Makefile.am.
+
+The following options are read from the kcfgc file:
+
+<table>
+<tr>
+ <td><b><i>Name</i></b></td>
+ <td><b><i>Type</i></b></td>
+ <td><b><i>Default</i></b></td>
+ <td><b><i>Description</i></b></td>
+</tr>
+<tr>
+ <td><b>File</b></td>
+ <td>string</td>
+ <td>programname.kcfg</td>
+ <td>Name of kcfg file containing the options the class is generated for</td>
+</tr>
+<tr>
+ <td><b>NameSpace</b></td>
+ <td>string</td>
+ <td>-</td>
+ <td>Optional namespace for generated class</td>
+</tr>
+<tr>
+ <td><b>ClassName</b></td>
+ <td>string</td>
+ <td>-</td>
+ <td>Name of generated class (required)</td>
+</tr>
+<tr>
+ <td><b>Inherits</b></td>
+ <td>string</td>
+ <td>KConfigSkeleton</td>
+ <td>Class the generated class inherits from. This class must inherit
+ KConfigSkeleton.</td>
+</tr>
+<tr>
+ <td><b>Visibility</b></td>
+ <td>string</td>
+ <td>-</td>
+ <td>Inserts visibility directive (for example KDE_EXPORT) between "class" keyword and class
+ name in header file</td>
+</tr>
+<tr>
+ <td><b>Singleton</b></td>
+ <td>bool</td>
+ <td>false</td>
+ <td>Generated class is a singleton.</td>
+</tr>
+<tr>
+ <td><b>CustomAdditions</b></td>
+ <td>bool</td>
+ <td>-</td>
+ <td></td>
+</tr>
+<tr>
+ <td><b>MemberVariables</b></td>
+ <td>string: public|protected|private|dpointer</td>
+ <td>private</td>
+ <td>C++ access modifier used for member variables holding the configuration
+ values</td>
+</tr>
+<tr>
+ <td><b>IncludeFiles</b></td>
+ <td>comma separated list of strings</td>
+ <td>-</td>
+ <td>Names of files to be included in the header of the generated class. Enclose a
+ file name in (escaped) double quotes to generate \#include "..." instead of
+ \#include \<...\>.</td>
+</tr>
+<tr>
+ <td><b>SourceIncludeFiles</b></td>
+ <td>comma separated list of strings</td>
+ <td>-</td>
+ <td>Names of files to be included in the source file of the generated class. Enclose
+ a file name in (escaped) double quotes to generate \#include "..." instead of
+ \#include \<...\>.</td>
+</tr>
+<tr>
+ <td><b>Mutators</b></td>
+ <td>true, false or a comma separated list of options</td>
+ <td>false</td>
+ <td>If true, mutator functions for all configuration options are generated.
+ If false, no mutator functions are generated. If a list is provided,
+ mutator functions are generated for the options that are listed.</td>
+</tr>
+<tr>
+ <td><b>DefaultValueGetters</b></td>
+ <td>true, false or a comma separated list of options</td>
+ <td>false</td>
+ <td>If true, functions to return the default value of all configuration options
+ are generated. If false, no default value functions are generated. If a list
+ is provided, default value functions are generated for the options that are listed.</td>
+</tr>
+<tr>
+ <td><b>ItemAccessors</b></td>
+ <td>bool</td>
+ <td>false</td>
+ <td>Generate accessor functions for the KConfigSkeletonItem objects
+ corresponding to the configuration options. If <b>SetUserTexts</b> is set,
+ <b>ItemAccessors</b> also has to be set.</td>
+</tr>
+<tr>
+ <td><b>SetUserTexts</b></td>
+ <td>bool</td>
+ <td>false</td>
+ <td>Set the label and whatthis texts of the items from the kcfg file.If
+ <b>SetUserTexts</b> is set, <b>ItemAccessors</b> also has to be set.</td>
+</tr>
+<tr>
+ <td><b>GlobalEnums</b></td>
+ <td>bool</td>
+ <td>false</td>
+ <td>If set to true all choices of Enum items will be created in the global
+ scope of the generated class. If set to false, each Enum item whose enum is not
+ explicitly named will get its own namespace for its choices.</td>
+</tr>
+<tr>
+ <td><b>UseEnumTypes</b></td>
+ <td>bool</td>
+ <td>false</td>
+ <td>If set to true, all Enum items whose enums are named will use enum types for
+ the return value of accessor functions and for the parameter of mutator
+ functions. This eliminates the need to cast accessor return values to the enum
+ type if you want to use the enum type in your own code. If set to false,
+ accessor return values and mutator parameters will be of type int.</td>
+</tr>
+<tr>
+ <td><b>ForceStringFilename</b></td>
+ <td>bool</td>
+ <td>false</td>
+ <td>If set to true, forces the first parameter of the generated class to be a QString when using an argument for the filename. This is useful to specify at runtime the filename of the configuration class.</td>
+</table>
+
+
+<h2>Advanced options</h2>
+
+There are several possibilities to parameterize entries.
+
+- Parameterized entries
+
+An entry can be parameterized using a fixed range parameter specified with
+the \<parameter\> tag. Such parameter can either be an Enum or an int. An Enum
+parameter should specify the possible enumeration values with the \<choices\>
+tag. An int parameter should specify its maximum value. Its minimum value
+is always 0.
+
+A parameterized entry is expanded to a number of entries, one for each
+value in the parameter range. The name and key should contain a reference
+to the parameter in the form of $(parameter-name). When expanding the entries
+the $(parameter-name) part is replaced with the value of the parameter.
+In the case of an Enum parameter it is replaced with the name of the
+enumuration value. In the case of an int parameter it is replaced with
+the numeric value of the parameter.
+
+Parameterized entries all share the same default value unless different
+default values have been specified for specific parameter values.
+This can be done with the param= attribute of the \<default\>. When a
+param attribute is specified the default value only applies to that
+particular parameter value.
+
+Example 1:
+\verbatim
+ <entry name="Color$(ColorIndex)" type="Color" key="color_$(ColorIndex)">
+ <parameter name="ColorIndex" type="Int" max="3"/>
+ <default param="0">#ff0000</default>
+ <default param="1">#00ff00</default>
+ <default param="2">#0000ff</default>
+ <default param="3">#ffff00</default>
+ </entry>
+\endverbatim
+
+The above describes 4 color configuration entries with the following defaults:
+
+\verbatim
+color_0=#ff0000
+color_1=#00ff00
+color_2=#0000ff
+color_3=#ffff00
+\endverbatim
+
+The configuration options will be accessible to the application via
+a QColor color(int ColorIndex) and a
+void setColor(int ColorIndex, const QColor &v) function.
+
+Example 2:
+\verbatim
+ <entry name="Sound$(SoundEvent)" type="String" key="sound_$(SoundEvent)">
+ <parameter name="SoundEvent" type="Enum">
+ <values>
+ <value>Explosion</value>
+ <value>Crash</value>
+ <value>Missile</value>
+ </values>
+ </parameter>
+ <default param="Explosion">boom.wav</default>
+ <default param="Crash">crash.wav</default>
+ <default param="Missile">missile.wav</default>
+ </entry>
+\endverbatim
+
+The above describes 3 string configuration entries with the following defaults:
+
+sound_Explosion=boom.wav
+sound_Crash=crash.wav
+sound_Missile=missile.wav
+
+The configuration options will be accessible to the application via
+a QString sound(int SoundEvent) and a
+void setSound(int SoundEvent, const QString &v) function.
+
+- Parameterized groups
+
+A group name can be parametrized using a parameter given to the KConfigSkeleton
+instance (which means this feature cannot be used with singleton classes).
+
+Example 1:
+\verbatim
+ <kcfgfile name="testrc">
+ <parameter name="groupname"/>
+ </kcfgfile>
+ <group name="$(groupname)">
+ <entry key="Text" type="string">
+ </entry>
+ </group>
+\endverbatim
+
+In this case passing "Group2" as the 'groupname' parameter to the generated class
+will make it use group "Group2" for the entry "Text".
+
+- Enums
+
+By default, if <b>GlobalEnums</b> is set to false, a separate named enum will be generated
+for each Enum entry. Since each enum is defined in a little enclosing class of its own,
+this allows the same Enum value names to be used in different enums. For example, the
+.kcfg entry
+
+\verbatim
+<entry name="KeepData" type="Enum">
+ <choices>
+ <choice name="Do">
+ <choice name="Dont">
+ </choices>
+</entry>
+\endverbatim
+
+will generate this public class containing the enum definition, inside the generated class:
+
+\verbatim
+ class EnumKeepData
+ {
+ public:
+ enum type { Do, Dont, COUNT };
+ };
+\endverbatim
+
+Alternatively, if <b>GlobalEnums</b> is set to true, all Enum items are defined as
+unnamed enums in the global scope of the generated class. In this case, all Enum values
+must have different names to avoid clashes. However, you can use a 'prefix' argument
+in \<choices\> to prevent duplicate enum member names clashing. Using this, the Enum value
+names are prefixed in code with the string you specify. For example, if <b>GlobalEnums</b>
+is set to true, the .kcfg entry
+
+\verbatim
+<entry name="KeepData" type="Enum">
+ <choices prefix="Keep_">
+ <choice name="Do">
+ <choice name="Dont">
+ </choices>
+</entry>
+\endverbatim
+
+will generate config file entries of "KeepData=Do" and "KeepData=Dont", but the enum
+will be declared
+
+\verbatim
+ enum { Keep_Do, Keep_Dont };
+\endverbatim
+
+It is possible to specify your own name for a generated enum, by including a
+'name' parameter in \<choices\>. Just like unnamed enums, this enum will be defined in
+the global scope of the generated class (without any enclosing class of its own).
+Therefore the names of Enum values must be unique across both unnamed enums (if
+<b>GlobalEnums</b> is set to true) and all specifically named enums.
+
+An example of a specifically named enum:
+
+\verbatim
+<entry name="KeepData" type="Enum">
+ <choices name="Types">
+ <choice name="Do">
+ <choice name="Dont">
+ </choices>
+</entry>
+\endverbatim
+
+which results in the following enum declaration, inside the generated class:
+
+\verbatim
+ enum Types { Do, Dont };
+\endverbatim
+
+It is also possible to specify the use of enums external to the generated class, by
+including the string "::" in the enum name - just ensure that it is sufficiently
+qualified to be unambiguous in use. To specify use of an unnamed enum, append a
+trailing "::". For example, to use the enum 'myEnum' defined in class ClassA, use
+either of
+
+\verbatim
+<choices name="ClassA::myEnum">
+<choices name="::ClassA::myEnum">
+\endverbatim
+
+To specify an unnamed enum in namespace ProgSpace, use
+
+\verbatim
+<choices name="ProgSpace::">
+\endverbatim
+
+To specify a top-level unnamed enum, use
+
+\verbatim
+<choices name="::">
+\endverbatim
+
+To specify the top-level enum 'anotherEnum', use
+
+\verbatim
+<choices name="::anotherEnum">
+\endverbatim
+
+
+- Signal support.
+
+An entry can emit a signal when it gets changed. First of all, you must
+define a list of signals for the configuration class. The signal's name may be
+any legal identifier you wish. The \<argument\> tag allows you to specify arguments
+for the emitted signal. It supports all types as defined in
+the KConfigXT DTD. The argument value must specify the name, without spaces, of one
+of the entries defined in the .kcfg file.
+A signal definition can also contain a \<label\> tag which will be
+the documentation line in the generated file.
+
+\verbatim
+<signal name="emoticonSettingsChanged" />
+
+<signal name="styleChanged">
+ <label>Tell when a complete style change.</label>
+ <argument type="String">stylePath</argument>
+ <argument type="String">StyleCSSVariant</argument>
+</signal>
+\endverbatim
+
+After defining the signals, you must tell which signal to emit for the entry.
+A signal can be emitted by multiple entries. Also, you don't need to specify the arguments
+for a signal, the signal name will suffice.
+
+\verbatim
+<entry key="stylePath" type="String">
+ <label>Absolute path to a directory containing a Adium/Kopete chat window style.</label>
+ <emit signal="styleChanged" />
+</entry>
+\endverbatim
+
+You can also use the generic configChanged() signal from KConfigSkeleton to notify your application
+about configuration changes.
+
+If you have questions or comments please contact Cornelius Schumacher
+<schumacher@kde.org> or Waldo Bastian <bastian@kde.org>
+*/
diff --git a/tier1/kconfig/src/kconfig_compiler/TODO b/tier1/kconfig/src/kconfig_compiler/TODO
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/tier1/kconfig/src/kconfig_compiler/TODO
diff --git a/tier1/kconfig/src/kconfig_compiler/checkkcfg.pl b/tier1/kconfig/src/kconfig_compiler/checkkcfg.pl
new file mode 100755
index 00000000..2eddbeee
--- /dev/null
+++ b/tier1/kconfig/src/kconfig_compiler/checkkcfg.pl
@@ -0,0 +1,83 @@
+#!/usr/bin/perl
+
+if ( @ARGV != 1 ) {
+ print STDERR "Missing arg: filename\n";
+ exit 1;
+}
+
+$file = $ARGV[0];
+
+$file =~ /^(.*)\.[^\.]*$/;
+$filebase = $1;
+
+$file_h = "$filebase.h";
+$file_cpp = "$filebase.cpp";
+
+$kcfgc = $file . "c";
+
+$cmd = "./kconfig_compiler $file $kcfgc";
+
+#print "CMD $cmd\n";
+
+if ( system( $cmd ) != 0 ) {
+ print STDERR "Unable to run kconfig_compiler\n";
+ exit 1;
+}
+
+checkfile( $file_h );
+checkfile( $file_cpp );
+
+exit 0;
+
+sub checkfile()
+{
+ my $file = shift;
+
+ $file =~ /\/([^\/]*)$/;
+ my $filename = $1;
+
+ print "Checking '$filename':\n";
+
+ my @ref;
+ if ( !open( REF, "$file.ref" ) ) {
+ print STDERR "Unable to open $file.ref\n";
+ exit 1;
+ }
+ while( <REF> ) {
+ push @ref, $_;
+ }
+ close REF;
+
+ if ( !open( READ, $filename ) ) {
+ print STDERR "Unable to open $filename\n";
+ exit 1;
+ }
+
+ $error = 0;
+ $i = 0;
+ $line = 1;
+ while( <READ> ) {
+ $out = $_;
+ $ref = @ref[$i++];
+
+ if ( $out ne $ref ) {
+ $error++;
+ print " Line $line: Expected : $ref";
+ print " Line $line: Compiler output : $out";
+ }
+
+ $line++;
+ }
+
+ close READ;
+
+ if ( $error > 0 ) {
+ print "\n FAILED: $error errors found.\n";
+ if ( $error > 5 ) {
+ system( "diff -u $file.ref $filename" );
+ }
+ exit 1;
+ } else {
+ print " OK\n";
+ }
+}
diff --git a/tier1/kconfig/src/kconfig_compiler/kcfg.xsd b/tier1/kconfig/src/kconfig_compiler/kcfg.xsd
new file mode 100644
index 00000000..4926fb19
--- /dev/null
+++ b/tier1/kconfig/src/kconfig_compiler/kcfg.xsd
@@ -0,0 +1,234 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- kcfg XSD v1.0 -->
+<xsd:schema
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns="http://www.kde.org/standards/kcfg/1.0"
+ xmlns:kcfg="http://www.kde.org/standards/kcfg/1.0"
+ targetNamespace="http://www.kde.org/standards/kcfg/1.0"
+ version="1.0"
+ elementFormDefault="qualified" >
+
+ <xsd:annotation>
+ <xsd:documentation>
+
+ Copyright (c) 2003 Cornelius Schumacher &lt;schumacher@kde.org&gt;
+ Copyright (c) 2003 Waldo Bastian &lt;bastian@kde.org&gt;
+ Copyright (c) 2003 Zack Rusin &lt;zack@kde.org&gt;
+ Copyright (c) 2004 Frans Englich &lt;frans.englich@telia.com&gt;
+ Copyright (c) 2006 Michaël Larouche &lt;michael.larouche@kdemail.net&gt;
+
+ Permission to use, copy, modify and distribute this DTD
+ and its accompanying documentation for any purpose and without fee
+ is hereby granted in perpetuity, provided that the above copyright
+ notice and this paragraph appear in all copies. The copyright
+ holders make no representation about the suitability of the DTD for
+ any purpose. It is provided "as is" without expressed or implied
+ warranty.
+
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:annotation>
+ <xsd:documentation>
+
+ A Schema for KDE's KConfigXT XML format. It is similar to the DTD
+ found at:
+
+ http://www.kde.org/standards/kcfg/1.0/kcfg.dtd
+
+ Documents valid against the Schema version are backwards compatible
+ to the DTD. Validating against the Schema instead of the DTD is
+ recommended, since the former provides better validation.
+
+ A document instance of this Schema should have a declaration
+ looking like this:
+
+ <![CDATA[
+
+ <?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" >
+ <!-- the content -->
+ </kcfg>
+
+ ]]>
+
+ </xsd:documentation>
+ </xsd:annotation>
+
+ <xsd:element name="kcfg">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="include" minOccurs="0" maxOccurs="unbounded" type="xsd:string"/>
+ <xsd:element name="kcfgfile" >
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="parameter" type="kcfg:parameter" minOccurs="0" maxOccurs="unbounded" />
+ <!-- FIXME: Are really unbounded occurances of parameter allowed? -->
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="optional"/>
+ <xsd:attribute name="arg" type="xsd:boolean" use="optional"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="signal" type="kcfg:signal" minOccurs="0" maxOccurs="unbounded" />
+ <xsd:element name="group" maxOccurs="unbounded" >
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="entry" maxOccurs="unbounded">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="parameter" minOccurs="0" type="kcfg:parameter"/>
+ <xsd:element name="label" minOccurs="0" type="kcfg:translatableString"/>
+ <xsd:element name="whatsthis" minOccurs="0" type="kcfg:translatableString"/>
+ <xsd:element name="tooltip" minOccurs="0" type="kcfg:translatableString"/>
+ <xsd:element name="choices" minOccurs="0">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="choice" maxOccurs="unbounded">
+ <xsd:complexType>
+ <xsd:all>
+ <xsd:element minOccurs="0" name="label" type="kcfg:translatableString"/>
+ <xsd:element minOccurs="0" name="whatsthis" type="kcfg:translatableString"/>
+ <xsd:element minOccurs="0" name="tooltip" type="kcfg:translatableString"/>
+ </xsd:all>
+ <xsd:attribute name="name" use="required" type="xsd:string"/>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute name="name" use="optional" type="xsd:string"/>
+ <xsd:attribute name="prefix" use="optional" type="xsd:string"/>
+
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="code" minOccurs="0" type="kcfg:code"/>
+
+ <xsd:element name="default" maxOccurs="unbounded" minOccurs="0" >
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:string">
+ <xsd:attribute use="optional" name="code" type="xsd:boolean"/>
+ <xsd:attribute use="optional" name="param" type="xsd:string"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="min" minOccurs="0" >
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:string">
+ <xsd:attribute name="code" type="xsd:boolean"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="max" minOccurs="0">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:string">
+ <xsd:attribute name="code" type="xsd:boolean"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="emit" minOccurs="0">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:string">
+ <xsd:attribute name="signal" use="required" type="xsd:string"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+
+ </xsd:choice>
+ <xsd:attribute name="name" use="optional" type="xsd:string"/>
+ <xsd:attribute name="key" use="optional" type="xsd:string"/>
+ <xsd:attribute name="hidden" use="optional" type="xsd:boolean"/>
+ <xsd:attribute name="type" type="kcfg:datatype"/>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string"/>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:simpleType name="datatype">
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="String"/>
+ <xsd:enumeration value="StringList"/>
+ <xsd:enumeration value="Font"/>
+ <xsd:enumeration value="Rect"/>
+ <xsd:enumeration value="Size"/>
+ <xsd:enumeration value="Color"/>
+ <xsd:enumeration value="Point"/>
+ <xsd:enumeration value="Int"/>
+ <xsd:enumeration value="UInt"/>
+ <xsd:enumeration value="Bool"/>
+ <xsd:enumeration value="Double"/>
+ <xsd:enumeration value="DateTime"/>
+ <xsd:enumeration value="LongLong"/>
+ <xsd:enumeration value="ULongLong"/>
+ <xsd:enumeration value="IntList"/>
+ <xsd:enumeration value="Enum"/>
+ <xsd:enumeration value="Path"/>
+ <xsd:enumeration value="PathList"/>
+ <xsd:enumeration value="Password"/>
+ <xsd:enumeration value="Url"/>
+ <xsd:enumeration value="UrlList"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+
+ <xsd:complexType name="parameter">
+ <xsd:sequence>
+ <xsd:element minOccurs="0" name="values">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" maxOccurs="unbounded" type="xsd:string"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string"/>
+ <xsd:attribute name="type" use="optional" type="kcfg:datatype" />
+ <xsd:attribute name="max" use="optional" type="xsd:positiveInteger"/>
+ </xsd:complexType>
+
+ <xsd:complexType name="code">
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:string"/>
+ </xsd:simpleContent>
+ </xsd:complexType>
+
+ <xsd:complexType name="signal">
+ <xsd:sequence>
+ <xsd:element name="label" minOccurs="0" type="xsd:string"/>
+ <xsd:element name="argument" maxOccurs="unbounded" minOccurs="0" >
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:string">
+ <xsd:attribute use="required" name="type" type="kcfg:datatype"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ </xsd:complexType>
+
+ <xsd:complexType name="translatableString">
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:string">
+ <xsd:attribute use="optional" name="context" type="xsd:string"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+</xsd:schema>
+
diff --git a/tier1/kconfig/src/kconfig_compiler/kconfig_compiler.cpp b/tier1/kconfig/src/kconfig_compiler/kconfig_compiler.cpp
new file mode 100644
index 00000000..ae192eec
--- /dev/null
+++ b/tier1/kconfig/src/kconfig_compiler/kconfig_compiler.cpp
@@ -0,0 +1,2338 @@
+// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
+/*
+ This file is part of KDE.
+
+ Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org>
+ Copyright (c) 2003 Waldo Bastian <bastian@kde.org>
+ Copyright (c) 2003 Zack Rusin <zack@kde.org>
+ Copyright (c) 2006 Michaël Larouche <michael.larouche@kdemail.net>
+ Copyright (c) 2008 Allen Winter <winter@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+// Compiling this file with this flag is just crazy
+#undef QT_NO_CAST_FROM_ASCII
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QFile>
+#include <QtCore/QFileInfo>
+#include <QtCore/QSettings>
+#include <QtCore/QTextStream>
+#include <QtXml/QDomAttr>
+#include <QtCore/QRegExp>
+#include <QtCore/QStringList>
+
+#include <ostream>
+#include <iostream>
+#include <stdlib.h>
+
+namespace
+{
+ QTextStream cout(stdout);
+ QTextStream cerr(stderr);
+}
+
+static void parseArgs(const QStringList &args, QString &directory, QString &file1, QString &file2)
+{
+ int fileCount = 0;
+ directory = QChar::fromLatin1('.');
+
+ for (int i = 1; i < args.count(); ++i) {
+ if (args.at(i) == QLatin1String("-d") || args.at(i) == QLatin1String("--directory")) {
+ if (i + 1 > args.count()) {
+ cerr << args.at(i) << " needs an argument" << endl;
+ exit(1);
+ }
+ directory = args.at(++i);
+ } else if (args.at(i).startsWith(QLatin1String("-d"))) {
+ directory = args.at(i).mid(2);
+ } else if (args.at(i) == QLatin1String("--help") || args.at(i) == QLatin1String("-h")) {
+ cout << "Options:" << endl;
+ cout << " -L --license Display software license" << endl;
+ cout << " -d, --directory <dir> Directory to generate files in [.]" << endl;
+ cout << " -h, --help Display this help" << endl;
+ cout << endl;
+ cout << "Arguments:" << endl;
+ cout << " file.kcfg Input kcfg XML file" << endl;
+ cout << " file.kcfgc Code generation options file" << endl;
+ exit(0);
+ } else if (args.at(i) == QLatin1String("--license") || args.at(i) == QLatin1String("-L")) {
+ cout << "Copyright 2003 Cornelius Schumacher, Waldo Bastian, Zack Rusin," << endl;
+ cout << " Reinhold Kainhofer, Duncan Mac-Vicar P., Harald Fernengel" << endl;
+ cout << "This program comes with ABSOLUTELY NO WARRANTY." << endl;
+ cout << "You may redistribute copies of this program" << endl;
+ cout << "under the terms of the GNU Library Public License." << endl;
+ cout << "For more information about these matters, see the file named COPYING." << endl;
+ exit(0);
+ } else if (args.at(i).startsWith(QLatin1Char('-'))) {
+ cerr << "Unknown option: " << args.at(i) << endl;
+ exit(1);
+ } else if (fileCount == 0) {
+ file1 = args.at(i);
+ ++fileCount;
+ } else if (fileCount == 1) {
+ file2 = args.at(i);
+ ++fileCount;
+ } else {
+ cerr << "Too many arguments" << endl;
+ exit(1);
+ }
+ }
+ if (fileCount < 2) {
+ cerr << "Too few arguments" << endl;
+ exit(1);
+ }
+}
+
+QStringList allNames;
+QRegExp *validNameRegexp;
+QString This;
+QString Const;
+
+/**
+ Configuration Compiler Configuration
+*/
+class CfgConfig
+{
+public:
+ CfgConfig( const QString &codegenFilename )
+ {
+ // Configure the compiler with some settings
+ QSettings codegenConfig(codegenFilename, QSettings::IniFormat);
+
+ nameSpace = codegenConfig.value("NameSpace").toString();
+ className = codegenConfig.value("ClassName").toString();
+ if ( className.isEmpty() ) {
+ cerr << "Class name missing" << endl;
+ exit(1);
+ }
+ inherits = codegenConfig.value("Inherits").toString();
+ if ( inherits.isEmpty() ) inherits = "KConfigSkeleton";
+ visibility = codegenConfig.value("Visibility").toString();
+ if ( !visibility.isEmpty() ) visibility += ' ';
+ forceStringFilename = codegenConfig.value("ForceStringFilename", false).toBool();
+ singleton = codegenConfig.value("Singleton", false).toBool();
+ staticAccessors = singleton;
+ customAddons = codegenConfig.value("CustomAdditions", false).toBool();
+ memberVariables = codegenConfig.value("MemberVariables").toString();
+ dpointer = (memberVariables == "dpointer");
+ headerIncludes = codegenConfig.value("IncludeFiles", QStringList()).toStringList();
+ sourceIncludes = codegenConfig.value("SourceIncludeFiles", QStringList()).toStringList();
+ mutators = codegenConfig.value("Mutators", QStringList()).toStringList();
+ allMutators = ((mutators.count() == 1) && (mutators.at(0).toLower() == "true"));
+ itemAccessors = codegenConfig.value("ItemAccessors", false).toBool();
+ setUserTexts = codegenConfig.value("SetUserTexts", false).toBool();
+ defaultGetters = codegenConfig.value("DefaultValueGetters", QStringList()).toStringList();
+ allDefaultGetters = (defaultGetters.count() == 1) && (defaultGetters.at(0).toLower() == "true");
+ globalEnums = codegenConfig.value("GlobalEnums", false).toBool();
+ useEnumTypes = codegenConfig.value("UseEnumTypes", false).toBool();
+
+ const QString trString = codegenConfig.value("TranslationSystem").toString().toLower();
+ if ( trString == "kde" ) {
+ translationSystem = KdeTranslation;
+ } else {
+ if ( !trString.isEmpty() && trString != "qt" ) {
+ cerr << "Unknown translation system, falling back to Qt tr()" << endl;
+ }
+ translationSystem = QtTranslation;
+ }
+ }
+
+public:
+ enum TranslationSystem {
+ QtTranslation,
+ KdeTranslation
+ };
+
+ // These are read from the .kcfgc configuration file
+ QString nameSpace; // The namespace for the class to be generated
+ QString className; // The class name to be generated
+ QString inherits; // The class the generated class inherits (if empty, from KConfigSkeleton)
+ QString visibility;
+ bool forceStringFilename;
+ bool singleton; // The class will be a singleton
+ bool staticAccessors; // provide or not static accessors
+ bool customAddons;
+ QString memberVariables;
+ QStringList headerIncludes;
+ QStringList sourceIncludes;
+ QStringList mutators;
+ QStringList defaultGetters;
+ bool allMutators;
+ bool setUserTexts;
+ bool allDefaultGetters;
+ bool dpointer;
+ bool globalEnums;
+ bool useEnumTypes;
+ bool itemAccessors;
+ TranslationSystem translationSystem;
+};
+
+
+struct SignalArguments
+{
+ QString type;
+ QString variableName;
+};
+
+class Signal {
+public:
+ QString name;
+ QString label;
+ QList<SignalArguments> arguments;
+};
+
+
+
+
+class CfgEntry
+{
+ public:
+ struct Choice
+ {
+ QString name;
+ QString context;
+ QString label;
+ QString toolTip;
+ QString whatsThis;
+ };
+ class Choices
+ {
+ public:
+ Choices() {}
+ Choices( const QList<Choice> &d, const QString &n, const QString &p )
+ : prefix(p), choices(d), mName(n)
+ {
+ int i = n.indexOf(QLatin1String("::"));
+ if (i >= 0)
+ mExternalQual = n.left(i + 2);
+ }
+ QString prefix;
+ QList<Choice> choices;
+ const QString& name() const { return mName; }
+ const QString& externalQualifier() const { return mExternalQual; }
+ bool external() const { return !mExternalQual.isEmpty(); }
+ private:
+ QString mName;
+ QString mExternalQual;
+ };
+
+ CfgEntry( const QString &group, const QString &type, const QString &key,
+ const QString &name, const QString &labelContext, const QString &label,
+ const QString &toolTipContext, const QString &toolTip, const QString &whatsThisContext, const QString &whatsThis, const QString &code,
+ const QString &defaultValue, const Choices &choices, const QList<Signal> signalList,
+ bool hidden )
+ : mGroup( group ), mType( type ), mKey( key ), mName( name ),
+ mLabelContext( labelContext ), mLabel( label ), mToolTipContext( toolTipContext ), mToolTip( toolTip ),
+ mWhatsThisContext( whatsThisContext ), mWhatsThis( whatsThis ),
+ mCode( code ), mDefaultValue( defaultValue ), mChoices( choices ),
+ mSignalList(signalList), mHidden( hidden )
+ {
+ }
+
+ void setGroup( const QString &group ) { mGroup = group; }
+ QString group() const { return mGroup; }
+
+ void setType( const QString &type ) { mType = type; }
+ QString type() const { return mType; }
+
+ void setKey( const QString &key ) { mKey = key; }
+ QString key() const { return mKey; }
+
+ void setName( const QString &name ) { mName = name; }
+ QString name() const { return mName; }
+
+ void setLabelContext( const QString &labelContext ) { mLabelContext = labelContext; }
+ QString labelContext() const { return mLabelContext; }
+
+ void setLabel( const QString &label ) { mLabel = label; }
+ QString label() const { return mLabel; }
+
+ void setToolTipContext( const QString &toolTipContext ) { mToolTipContext = toolTipContext; }
+ QString toolTipContext() const { return mToolTipContext; }
+
+ void setToolTip( const QString &toolTip ) { mToolTip = toolTip; }
+ QString toolTip() const { return mToolTip; }
+
+ void setWhatsThisContext( const QString &whatsThisContext ) { mWhatsThisContext = whatsThisContext; }
+ QString whatsThisContext() const { return mWhatsThisContext; }
+
+ void setWhatsThis( const QString &whatsThis ) { mWhatsThis = whatsThis; }
+ QString whatsThis() const { return mWhatsThis; }
+
+ void setDefaultValue( const QString &d ) { mDefaultValue = d; }
+ QString defaultValue() const { return mDefaultValue; }
+
+ void setCode( const QString &d ) { mCode = d; }
+ QString code() const { return mCode; }
+
+ void setMinValue( const QString &d ) { mMin = d; }
+ QString minValue() const { return mMin; }
+
+ void setMaxValue( const QString &d ) { mMax = d; }
+ QString maxValue() const { return mMax; }
+
+ void setParam( const QString &d ) { mParam = d; }
+ QString param() const { return mParam; }
+
+ void setParamName( const QString &d ) { mParamName = d; }
+ QString paramName() const { return mParamName; }
+
+ void setParamType( const QString &d ) { mParamType = d; }
+ QString paramType() const { return mParamType; }
+
+ void setChoices( const QList<Choice> &d, const QString &n, const QString &p ) { mChoices = Choices( d, n, p ); }
+ Choices choices() const { return mChoices; }
+
+ void setParamValues( const QStringList &d ) { mParamValues = d; }
+ QStringList paramValues() const { return mParamValues; }
+
+ void setParamDefaultValues( const QStringList &d ) { mParamDefaultValues = d; }
+ QString paramDefaultValue(int i) const { return mParamDefaultValues[i]; }
+
+ void setParamMax( int d ) { mParamMax = d; }
+ int paramMax() const { return mParamMax; }
+
+ void setSignalList( const QList<Signal> &value ) { mSignalList = value; }
+ QList<Signal> signalList() const { return mSignalList; }
+
+ bool hidden() const { return mHidden; }
+
+ void dump() const
+ {
+ cerr << "<entry>" << endl;
+ cerr << " group: " << mGroup << endl;
+ cerr << " type: " << mType << endl;
+ cerr << " key: " << mKey << endl;
+ cerr << " name: " << mName << endl;
+ cerr << " label context: " << mLabelContext << endl;
+ cerr << " label: " << mLabel << endl;
+// whatsthis
+ cerr << " code: " << mCode << endl;
+// cerr << " values: " << mValues.join(":") << endl;
+
+ if (!param().isEmpty())
+ {
+ cerr << " param name: "<< mParamName << endl;
+ cerr << " param type: "<< mParamType << endl;
+ cerr << " paramvalues: " << mParamValues.join(QChar::fromLatin1(':')) << endl;
+ }
+ cerr << " default: " << mDefaultValue << endl;
+ cerr << " hidden: " << mHidden << endl;
+ cerr << " min: " << mMin << endl;
+ cerr << " max: " << mMax << endl;
+ cerr << "</entry>" << endl;
+ }
+
+ private:
+ QString mGroup;
+ QString mType;
+ QString mKey;
+ QString mName;
+ QString mLabelContext;
+ QString mLabel;
+ QString mToolTipContext;
+ QString mToolTip;
+ QString mWhatsThisContext;
+ QString mWhatsThis;
+ QString mCode;
+ QString mDefaultValue;
+ QString mParam;
+ QString mParamName;
+ QString mParamType;
+ Choices mChoices;
+ QList<Signal> mSignalList;
+ QStringList mParamValues;
+ QStringList mParamDefaultValues;
+ int mParamMax;
+ bool mHidden;
+ QString mMin;
+ QString mMax;
+};
+
+class Param {
+public:
+ QString name;
+ QString type;
+};
+
+// returns the name of an member variable
+// use itemPath to know the full path
+// like using d-> in case of dpointer
+static QString varName(const QString &n, const CfgConfig &cfg)
+{
+ QString result;
+ if ( !cfg.dpointer ) {
+ result = QChar::fromLatin1('m') + n;
+ result[1] = result[1].toUpper();
+ }
+ else {
+ result = n;
+ result[0] = result[0].toLower();
+ }
+ return result;
+}
+
+static QString varPath(const QString &n, const CfgConfig &cfg)
+{
+ QString result;
+ if ( cfg.dpointer ) {
+ result = "d->"+varName(n, cfg);
+ }
+ else {
+ result = varName(n, cfg);
+ }
+ return result;
+}
+
+static QString enumName(const QString &n)
+{
+ QString result = QString::fromLatin1("Enum") + n;
+ result[4] = result[4].toUpper();
+ return result;
+}
+
+static QString enumName(const QString &n, const CfgEntry::Choices &c)
+{
+ QString result = c.name();
+ if ( result.isEmpty() )
+ {
+ result = QString::fromLatin1("Enum") + n;
+ result[4] = result[4].toUpper();
+ }
+ return result;
+}
+
+static QString enumType(const CfgEntry *e, bool globalEnums)
+{
+ QString result = e->choices().name();
+ if ( result.isEmpty() )
+ {
+ result = QString::fromLatin1("Enum") + e->name();
+ if( !globalEnums )
+ result += QString::fromLatin1("::type");
+ result[4] = result[4].toUpper();
+ }
+ return result;
+}
+
+static QString enumTypeQualifier(const QString &n, const CfgEntry::Choices &c)
+{
+ QString result = c.name();
+ if ( result.isEmpty() )
+ {
+ result = QString::fromLatin1("Enum") + n + QString::fromLatin1("::");
+ result[4] = result[4].toUpper();
+ }
+ else if ( c.external() )
+ result = c.externalQualifier();
+ else
+ result.clear();
+ return result;
+}
+
+static QString setFunction(const QString &n, const QString &className = QString())
+{
+ QString result = QString::fromLatin1("set") + n;
+ result[3] = result[3].toUpper();
+
+ if ( !className.isEmpty() )
+ result = className + QString::fromLatin1("::") + result;
+ return result;
+}
+
+static QString getDefaultFunction(const QString &n, const QString &className = QString())
+{
+ QString result = QString::fromLatin1("default") + n + QString::fromLatin1("Value");
+ result[7] = result[7].toUpper();
+
+ if ( !className.isEmpty() )
+ result = className + QString::fromLatin1("::") + result;
+ return result;
+}
+
+static QString getFunction(const QString &n, const QString &className = QString())
+{
+ QString result = n;
+ result[0] = result[0].toLower();
+
+ if ( !className.isEmpty() )
+ result = className + QString::fromLatin1("::") + result;
+ return result;
+}
+
+
+static void addQuotes( QString &s )
+{
+ if ( !s.startsWith( QLatin1Char('"') ) )
+ s.prepend( QLatin1Char('"') );
+ if ( !s.endsWith( QLatin1Char('"') ) )
+ s.append( QLatin1Char('"') );
+}
+
+static QString quoteString( const QString &s )
+{
+ QString r = s;
+ r.replace( QLatin1Char('\\'), QLatin1String("\\\\") );
+ r.replace( QLatin1Char('\"'), QLatin1String("\\\"") );
+ r.remove( QLatin1Char('\r') );
+ r.replace( QLatin1Char('\n'), QLatin1String("\\n\"\n\"") );
+ return QLatin1Char('\"') + r + QLatin1Char('\"');
+}
+
+static QString literalString( const QString &s )
+{
+ bool isAscii = true;
+ for(int i = s.length(); i--;)
+ if (s[i].unicode() > 127) isAscii = false;
+
+ if (isAscii)
+ return QString::fromLatin1("QLatin1String( ") + quoteString(s) + QString::fromLatin1(" )");
+ else
+ return QString::fromLatin1("QString::fromUtf8( ") + quoteString(s) + QString::fromLatin1(" )");
+}
+
+static QString dumpNode(const QDomNode &node)
+{
+ QString msg;
+ QTextStream s(&msg, QIODevice::WriteOnly );
+ node.save(s, 0);
+
+ msg = msg.simplified();
+ if (msg.length() > 40)
+ return msg.left(37) + QString::fromLatin1("...");
+ return msg;
+}
+
+static QString filenameOnly(const QString& path)
+{
+ int i = path.lastIndexOf(QRegExp(QLatin1String("[/\\]")));
+ if (i >= 0)
+ return path.mid(i+1);
+ return path;
+}
+
+static QString signalEnumName(const QString &signalName)
+{
+ QString result;
+ result = QString::fromLatin1("signal") + signalName;
+ result[6] = result[6].toUpper();
+
+ return result;
+}
+
+static void preProcessDefault( QString &defaultValue, const QString &name,
+ const QString &type,
+ const CfgEntry::Choices &choices,
+ QString &code, const CfgConfig &cfg )
+{
+ if ( type == QLatin1String("String") && !defaultValue.isEmpty() ) {
+ defaultValue = literalString(defaultValue);
+
+ } else if ( type == QLatin1String("Path") && !defaultValue.isEmpty() ) {
+ defaultValue = literalString( defaultValue );
+ } else if ( type == QLatin1String("Url") && !defaultValue.isEmpty() ) {
+ // Use fromUserInput in order to support absolute paths and absolute urls, like KDE4's KUrl(QString) did.
+ defaultValue = QString::fromLatin1("QUrl::fromUserInput( ") + literalString(defaultValue) + QLatin1Char(')');
+ } else if ( ( type == QLatin1String("UrlList") || type == QLatin1String("StringList") || type == QLatin1String("PathList")) && !defaultValue.isEmpty() ) {
+ QTextStream cpp( &code, QIODevice::WriteOnly | QIODevice::Append );
+ if (!code.isEmpty())
+ cpp << endl;
+
+ if( type == "UrlList" ) {
+ cpp << " QList<QUrl> default" << name << ";" << endl;
+ } else {
+ cpp << " QStringList default" << name << ";" << endl;
+ }
+ const QStringList defaults = defaultValue.split(QLatin1Char(','));
+ QStringList::ConstIterator it;
+ for( it = defaults.constBegin(); it != defaults.constEnd(); ++it ) {
+ cpp << " default" << name << ".append( ";
+ if( type == QLatin1String("UrlList") ) {
+ cpp << "QUrl::fromUserInput(";
+ }
+ cpp << "QString::fromUtf8( \"" << *it << "\" ) ";
+ if( type == QLatin1String("UrlList") ) {
+ cpp << ") ";
+ }
+ cpp << ");" << endl;
+ }
+ defaultValue = QString::fromLatin1("default") + name;
+
+ } else if ( type == QLatin1String("Color") && !defaultValue.isEmpty() ) {
+ QRegExp colorRe(QLatin1String("\\d+,\\s*\\d+,\\s*\\d+(,\\s*\\d+)?"));
+ if (colorRe.exactMatch(defaultValue))
+ {
+ defaultValue = QLatin1String("QColor( ") + defaultValue + QLatin1String(" )");
+ }
+ else
+ {
+ defaultValue = QLatin1String("QColor( \"") + defaultValue + QLatin1String("\" )");
+ }
+
+ } else if ( type == QLatin1String("Enum") ) {
+ QList<CfgEntry::Choice>::ConstIterator it;
+ for( it = choices.choices.constBegin(); it != choices.choices.constEnd(); ++it ) {
+ if ( (*it).name == defaultValue ) {
+ if ( cfg.globalEnums && choices.name().isEmpty() )
+ defaultValue.prepend( choices.prefix );
+ else
+ defaultValue.prepend( enumTypeQualifier(name, choices) + choices.prefix );
+ break;
+ }
+ }
+
+ } else if ( type == QLatin1String("IntList") ) {
+ QTextStream cpp( &code, QIODevice::WriteOnly | QIODevice::Append );
+ if (!code.isEmpty())
+ cpp << endl;
+
+ cpp << " QList<int> default" << name << ";" << endl;
+ if (!defaultValue.isEmpty())
+ {
+ const QStringList defaults = defaultValue.split( QLatin1Char(',') );
+ QStringList::ConstIterator it;
+ for( it = defaults.constBegin(); it != defaults.constEnd(); ++it ) {
+ cpp << " default" << name << ".append( " << *it << " );"
+ << endl;
+ }
+ }
+ defaultValue = QString::fromLatin1("default") + name;
+ }
+}
+
+
+CfgEntry *parseEntry( const QString &group, const QDomElement &element, const CfgConfig &cfg )
+{
+ bool defaultCode = false;
+ QString type = element.attribute( "type" );
+ QString name = element.attribute( "name" );
+ QString key = element.attribute( "key" );
+ QString hidden = element.attribute( "hidden" );
+ QString labelContext;
+ QString label;
+ QString toolTipContext;
+ QString toolTip;
+ QString whatsThisContext;
+ QString whatsThis;
+ QString defaultValue;
+ QString code;
+ QString param;
+ QString paramName;
+ QString paramType;
+ CfgEntry::Choices choices;
+ QList<Signal> signalList;
+ QStringList paramValues;
+ QStringList paramDefaultValues;
+ QString minValue;
+ QString maxValue;
+ int paramMax = 0;
+
+ for ( QDomElement e = element.firstChildElement(); !e.isNull(); e = e.nextSiblingElement() ) {
+ QString tag = e.tagName();
+ if ( tag == "label" ) {
+ label = e.text();
+ labelContext = e.attribute( "context" );
+ }
+ else if ( tag == "tooltip" ) {
+ toolTip = e.text();
+ toolTipContext = e.attribute( "context" );
+ }
+ else if ( tag == "whatsthis" ) {
+ whatsThis = e.text();
+ whatsThisContext = e.attribute( "context" );
+ }
+ else if ( tag == "min" ) minValue = e.text();
+ else if ( tag == "max" ) maxValue = e.text();
+ else if ( tag == "code" ) code = e.text();
+ else if ( tag == "parameter" )
+ {
+ param = e.attribute( "name" );
+ paramType = e.attribute( "type" );
+ if ( param.isEmpty() ) {
+ cerr << "Parameter must have a name: " << dumpNode(e) << endl;
+ return 0;
+ }
+ if ( paramType.isEmpty() ) {
+ cerr << "Parameter must have a type: " << dumpNode(e) << endl;
+ return 0;
+ }
+ if ((paramType == "Int") || (paramType == "UInt"))
+ {
+ bool ok;
+ paramMax = e.attribute("max").toInt(&ok);
+ if (!ok)
+ {
+ cerr << "Integer parameter must have a maximum (e.g. max=\"0\"): "
+ << dumpNode(e) << endl;
+ return 0;
+ }
+ }
+ else if (paramType == "Enum")
+ {
+ for ( QDomElement e2 = e.firstChildElement(); !e2.isNull(); e2 = e2.nextSiblingElement() ) {
+ if (e2.tagName() == "values")
+ {
+ for ( QDomElement e3 = e2.firstChildElement(); !e3.isNull(); e3 = e3.nextSiblingElement() ) {
+ if (e3.tagName() == "value")
+ {
+ paramValues.append( e3.text() );
+ }
+ }
+ break;
+ }
+ }
+ if (paramValues.isEmpty())
+ {
+ cerr << "No values specified for parameter '" << param
+ << "'." << endl;
+ return 0;
+ }
+ paramMax = paramValues.count()-1;
+ }
+ else
+ {
+ cerr << "Parameter '" << param << "' has type " << paramType
+ << " but must be of type int, uint or Enum." << endl;
+ return 0;
+ }
+ }
+ else if ( tag == "default" )
+ {
+ if (e.attribute("param").isEmpty())
+ {
+ defaultValue = e.text();
+ if (e.attribute( "code" ) == "true")
+ defaultCode = true;
+ }
+ }
+ else if ( tag == "choices" ) {
+ QString name = e.attribute( "name" );
+ QString prefix = e.attribute( "prefix" );
+ QList<CfgEntry::Choice> chlist;
+ for( QDomElement e2 = e.firstChildElement(); !e2.isNull(); e2 = e2.nextSiblingElement() ) {
+ if ( e2.tagName() == "choice" ) {
+ CfgEntry::Choice choice;
+ choice.name = e2.attribute( "name" );
+ if ( choice.name.isEmpty() ) {
+ cerr << "Tag <choice> requires attribute 'name'." << endl;
+ }
+ for( QDomElement e3 = e2.firstChildElement(); !e3.isNull(); e3 = e3.nextSiblingElement() ) {
+ if ( e3.tagName() == "label" ) {
+ choice.label = e3.text();
+ choice.context = e3.attribute( "context" );
+ }
+ if ( e3.tagName() == "tooltip" ) {
+ choice.toolTip = e3.text();
+ choice.context = e3.attribute( "context" );
+ }
+ if ( e3.tagName() == "whatsthis" ) {
+ choice.whatsThis = e3.text();
+ choice.context = e3.attribute( "context" );
+ }
+ }
+ chlist.append( choice );
+ }
+ }
+ choices = CfgEntry::Choices( chlist, name, prefix );
+ }
+ else if ( tag == "emit" ) {
+ QDomNode signalNode;
+ Signal signal;
+ signal.name = e.attribute( "signal" );
+ signalList.append( signal);
+ }
+ }
+
+
+ bool nameIsEmpty = name.isEmpty();
+ if ( nameIsEmpty && key.isEmpty() ) {
+ cerr << "Entry must have a name or a key: " << dumpNode(element) << endl;
+ return 0;
+ }
+
+ if ( key.isEmpty() ) {
+ key = name;
+ }
+
+ if ( nameIsEmpty ) {
+ name = key;
+ name.remove( ' ' );
+ } else if ( name.contains( ' ' ) ) {
+ cout<<"Entry '"<<name<<"' contains spaces! <name> elements can not contain spaces!"<<endl;
+ name.remove( ' ' );
+ }
+
+ if (name.contains("$("))
+ {
+ if (param.isEmpty())
+ {
+ cerr << "Name may not be parameterized: " << name << endl;
+ return 0;
+ }
+ }
+ else
+ {
+ if (!param.isEmpty())
+ {
+ cerr << "Name must contain '$(" << param << ")': " << name << endl;
+ return 0;
+ }
+ }
+
+ if ( label.isEmpty() ) {
+ label = key;
+ }
+
+ if ( type.isEmpty() ) type = "String"; // XXX : implicit type might be bad
+
+ if (!param.isEmpty())
+ {
+ // Adjust name
+ paramName = name;
+ name.remove("$("+param+')');
+ // Lookup defaults for indexed entries
+ for(int i = 0; i <= paramMax; i++)
+ {
+ paramDefaultValues.append(QString());
+ }
+
+ for ( QDomElement e = element.firstChildElement(); !e.isNull(); e = e.nextSiblingElement() ) {
+ QString tag = e.tagName();
+ if ( tag == "default" )
+ {
+ QString index = e.attribute("param");
+ if (index.isEmpty())
+ continue;
+
+ bool ok;
+ int i = index.toInt(&ok);
+ if (!ok)
+ {
+ i = paramValues.indexOf(index);
+ if (i == -1)
+ {
+ cerr << "Index '" << index << "' for default value is unknown." << endl;
+ return 0;
+ }
+ }
+
+ if ((i < 0) || (i > paramMax))
+ {
+ cerr << "Index '" << i << "' for default value is out of range [0, "<< paramMax<<"]." << endl;
+ return 0;
+ }
+
+ QString tmpDefaultValue = e.text();
+
+ if (e.attribute( "code" ) != "true")
+ preProcessDefault(tmpDefaultValue, name, type, choices, code, cfg);
+
+ paramDefaultValues[i] = tmpDefaultValue;
+ }
+ }
+ }
+
+ if (!validNameRegexp->exactMatch(name))
+ {
+ if (nameIsEmpty)
+ cerr << "The key '" << key << "' can not be used as name for the entry because "
+ "it is not a valid name. You need to specify a valid name for this entry." << endl;
+ else
+ cerr << "The name '" << name << "' is not a valid name for an entry." << endl;
+ return 0;
+ }
+
+ if (allNames.contains(name))
+ {
+ if (nameIsEmpty)
+ cerr << "The key '" << key << "' can not be used as name for the entry because "
+ "it does not result in a unique name. You need to specify a unique name for this entry." << endl;
+ else
+ cerr << "The name '" << name << "' is not unique." << endl;
+ return 0;
+ }
+ allNames.append(name);
+
+ if (!defaultCode)
+ {
+ preProcessDefault(defaultValue, name, type, choices, code, cfg);
+ }
+
+ CfgEntry *result = new CfgEntry( group, type, key, name, labelContext, label, toolTipContext, toolTip, whatsThisContext, whatsThis,
+ code, defaultValue, choices, signalList,
+ hidden == "true" );
+ if (!param.isEmpty())
+ {
+ result->setParam(param);
+ result->setParamName(paramName);
+ result->setParamType(paramType);
+ result->setParamValues(paramValues);
+ result->setParamDefaultValues(paramDefaultValues);
+ result->setParamMax(paramMax);
+ }
+ result->setMinValue(minValue);
+ result->setMaxValue(maxValue);
+
+ return result;
+}
+
+static bool isUnsigned(const QString& type)
+{
+ if ( type == "UInt" ) return true;
+ if ( type == "ULongLong" ) return true;
+ return false;
+}
+
+/**
+ Return parameter declaration for given type.
+*/
+QString param( const QString &t )
+{
+ const QString type = t.toLower();
+ if ( type == "string" ) return "const QString &";
+ else if ( type == "stringlist" ) return "const QStringList &";
+ else if ( type == "font" ) return "const QFont &";
+ else if ( type == "rect" ) return "const QRect &";
+ else if ( type == "size" ) return "const QSize &";
+ else if ( type == "color" ) return "const QColor &";
+ else if ( type == "point" ) return "const QPoint &";
+ else if ( type == "int" ) return "int";
+ else if ( type == "uint" ) return "uint";
+ else if ( type == "bool" ) return "bool";
+ else if ( type == "double" ) return "double";
+ else if ( type == "datetime" ) return "const QDateTime &";
+ else if ( type == "longlong" ) return "qint64";
+ else if ( type == "ulonglong" ) return "quint64";
+ else if ( type == "intlist" ) return "const QList<int> &";
+ else if ( type == "enum" ) return "int";
+ else if ( type == "path" ) return "const QString &";
+ else if ( type == "pathlist" ) return "const QStringList &";
+ else if ( type == "password" ) return "const QString &";
+ else if ( type == "url" ) return "const QUrl &";
+ else if ( type == "urllist" ) return "const QList<QUrl> &";
+ else {
+ cerr <<"kconfig_compiler does not support type \""<< type <<"\""<<endl;
+ return "QString"; //For now, but an assert would be better
+ }
+}
+
+/**
+ Actual C++ storage type for given type.
+*/
+QString cppType( const QString &t )
+{
+ const QString type = t.toLower();
+ if ( type == "string" ) return "QString";
+ else if ( type == "stringlist" ) return "QStringList";
+ else if ( type == "font" ) return "QFont";
+ else if ( type == "rect" ) return "QRect";
+ else if ( type == "size" ) return "QSize";
+ else if ( type == "color" ) return "QColor";
+ else if ( type == "point" ) return "QPoint";
+ else if ( type == "int" ) return "int";
+ else if ( type == "uint" ) return "uint";
+ else if ( type == "bool" ) return "bool";
+ else if ( type == "double" ) return "double";
+ else if ( type == "datetime" ) return "QDateTime";
+ else if ( type == "longlong" ) return "qint64";
+ else if ( type == "ulonglong" ) return "quint64";
+ else if ( type == "intlist" ) return "QList<int>";
+ else if ( type == "enum" ) return "int";
+ else if ( type == "path" ) return "QString";
+ else if ( type == "pathlist" ) return "QStringList";
+ else if ( type == "password" ) return "QString";
+ else if ( type == "url" ) return "QUrl";
+ else if ( type == "urllist" ) return "QList<QUrl>";
+ else {
+ cerr<<"kconfig_compiler does not support type \""<< type <<"\""<<endl;
+ return "QString"; //For now, but an assert would be better
+ }
+}
+
+QString defaultValue( const QString &t )
+{
+ const QString type = t.toLower();
+ if ( type == "string" ) return "\"\""; // Use empty string, not null string!
+ else if ( type == "stringlist" ) return "QStringList()";
+ else if ( type == "font" ) return "QFont()";
+ else if ( type == "rect" ) return "QRect()";
+ else if ( type == "size" ) return "QSize()";
+ else if ( type == "color" ) return "QColor(128, 128, 128)";
+ else if ( type == "point" ) return "QPoint()";
+ else if ( type == "int" ) return "0";
+ else if ( type == "uint" ) return "0";
+ else if ( type == "bool" ) return "false";
+ else if ( type == "double" ) return "0.0";
+ else if ( type == "datedime" ) return "QDateTime()";
+ else if ( type == "longlong" ) return "0";
+ else if ( type == "ulonglong" ) return "0";
+ else if ( type == "intlist" ) return "QList<int>()";
+ else if ( type == "enum" ) return "0";
+ else if ( type == "path" ) return "\"\""; // Use empty string, not null string!
+ else if ( type == "pathlist" ) return "QStringList()";
+ else if ( type == "password" ) return "\"\""; // Use empty string, not null string!
+ else if ( type == "url" ) return "QUrl()";
+ else if ( type == "urllist" ) return "QList<QUrl>()";
+ else {
+ cerr<<"Error, kconfig_compiler does not support the \""<< type <<"\" type!"<<endl;
+ return "QString"; //For now, but an assert would be better
+ }
+}
+
+QString itemType( const QString &type )
+{
+ QString t;
+
+ t = type;
+ t.replace( 0, 1, t.left( 1 ).toUpper() );
+
+ return t;
+}
+
+static QString itemDeclaration(const CfgEntry *e, const CfgConfig &cfg)
+{
+ if (cfg.itemAccessors)
+ return QString();
+
+ QString fCap = e->name();
+ fCap[0] = fCap[0].toUpper();
+ return " "+cfg.inherits+"::Item"+itemType( e->type() ) +
+ " *item" + fCap +
+ ( (!e->param().isEmpty())?(QString("[%1]").arg(e->paramMax()+1)) : QString()) +
+ ";\n";
+}
+
+// returns the name of an item variable
+// use itemPath to know the full path
+// like using d-> in case of dpointer
+static QString itemVar(const CfgEntry *e, const CfgConfig &cfg)
+{
+ QString result;
+ if (cfg.itemAccessors)
+ {
+ if ( !cfg.dpointer )
+ {
+ result = 'm' + e->name() + "Item";
+ result[1] = result[1].toUpper();
+ }
+ else
+ {
+ result = e->name() + "Item";
+ result[0] = result[0].toLower();
+ }
+ }
+ else
+ {
+ result = "item" + e->name();
+ result[4] = result[4].toUpper();
+ }
+ return result;
+}
+
+static QString itemPath(const CfgEntry *e, const CfgConfig &cfg)
+{
+ QString result;
+ if ( cfg.dpointer ) {
+ result = "d->"+itemVar(e, cfg);
+ }
+ else {
+ result = itemVar(e, cfg);
+ }
+ return result;
+}
+
+QString newItem( const QString &type, const QString &name, const QString &key,
+ const QString &defaultValue, const CfgConfig &cfg, const QString &param = QString())
+{
+ QString t = "new "+cfg.inherits+"::Item" + itemType( type ) +
+ "( currentGroup(), " + key + ", " + varPath( name, cfg ) + param;
+ if ( type == "Enum" ) t += ", values" + name;
+ if ( !defaultValue.isEmpty() ) {
+ t += ", ";
+ if ( type == "String" ) t += defaultValue;
+ else t+= defaultValue;
+ }
+ t += " );";
+
+ return t;
+}
+
+QString paramString(const QString &s, const CfgEntry *e, int i)
+{
+ QString result = s;
+ QString needle = "$("+e->param()+')';
+ if (result.contains(needle))
+ {
+ QString tmp;
+ if (e->paramType() == "Enum")
+ {
+ tmp = e->paramValues()[i];
+ }
+ else
+ {
+ tmp = QString::number(i);
+ }
+
+ result.replace(needle, tmp);
+ }
+ return result;
+}
+
+QString paramString(const QString &group, const QList<Param> &parameters)
+{
+ QString paramString = group;
+ QString arguments;
+ int i = 1;
+ for (QList<Param>::ConstIterator it = parameters.constBegin();
+ it != parameters.constEnd(); ++it)
+ {
+ if (paramString.contains("$("+(*it).name+')'))
+ {
+ QString tmp;
+ tmp.sprintf("%%%d", i++);
+ paramString.replace("$("+(*it).name+')', tmp);
+ arguments += ".arg( mParam"+(*it).name+" )";
+ }
+ }
+ if (arguments.isEmpty())
+ return "QLatin1String( \""+group+"\" )";
+
+ return "QString( QLatin1String( \""+paramString+"\" ) )"+arguments;
+}
+
+QString translatedString(const CfgConfig &cfg, const QString &string, const QString &context = QString(), const QString &param = QString(), const QString &paramValue = QString())
+{
+ QString result;
+
+ switch (cfg.translationSystem) {
+ case CfgConfig::QtTranslation:
+ if (!context.isEmpty()) {
+ result+= "/*: " + context + " */ QCoreApplication::translate(\"";
+ } else {
+ result+= "QCoreApplication::translate(\"";
+ }
+ result+= cfg.className + "\", ";
+ break;
+
+ case CfgConfig::KdeTranslation:
+ if (!context.isEmpty()) {
+ result+= "i18nc(" + quoteString(context) + ", ";
+ } else {
+ result+= "i18n(";
+ }
+ break;
+ }
+
+ if (!param.isEmpty()) {
+ QString resolvedString = string;
+ resolvedString.replace("$("+param+')', paramValue);
+ result+= quoteString(resolvedString);
+ } else {
+ result+= quoteString(string);
+ }
+
+ result+= ')';
+
+ return result;
+}
+
+/* int i is the value of the parameter */
+QString userTextsFunctions( CfgEntry *e, const CfgConfig &cfg, QString itemVarStr=QString(), QString i=QString() )
+{
+ QString txt;
+ if (itemVarStr.isNull()) itemVarStr=itemPath(e, cfg);
+ if ( !e->label().isEmpty() ) {
+ txt += " " + itemVarStr + "->setLabel( ";
+ txt += translatedString(cfg, e->label(), e->labelContext(), e->param(), i);
+ txt += " );\n";
+ }
+ if ( !e->toolTip().isEmpty() ) {
+ txt += " " + itemVarStr + "->setToolTip( ";
+ txt += translatedString(cfg, e->toolTip(), e->toolTipContext(), e->param(), i);
+ txt += " );\n";
+ }
+ if ( !e->whatsThis().isEmpty() ) {
+ txt += " " + itemVarStr + "->setWhatsThis( ";
+ txt += translatedString(cfg, e->whatsThis(), e->whatsThisContext(), e->param(), i);
+ txt += " );\n";
+ }
+ return txt;
+}
+
+// returns the member accesor implementation
+// which should go in the h file if inline
+// or the cpp file if not inline
+QString memberAccessorBody( CfgEntry *e, bool globalEnums, const CfgConfig &cfg )
+{
+ QString result;
+ QTextStream out(&result, QIODevice::WriteOnly);
+ QString n = e->name();
+ QString t = e->type();
+ bool useEnumType = cfg.useEnumTypes && t == "Enum";
+
+ out << "return ";
+ if (useEnumType)
+ out << "static_cast<" << enumType(e, globalEnums) << ">(";
+ out << This << varPath(n, cfg);
+ if (!e->param().isEmpty())
+ out << "[i]";
+ if (useEnumType)
+ out << ")";
+ out << ";" << endl;
+
+ return result;
+}
+
+// returns the member mutator implementation
+// which should go in the h file if inline
+// or the cpp file if not inline
+QString memberMutatorBody( CfgEntry *e, const CfgConfig &cfg )
+{
+ QString result;
+ QTextStream out(&result, QIODevice::WriteOnly);
+ QString n = e->name();
+ QString t = e->type();
+
+ if (!e->minValue().isEmpty())
+ {
+ if (e->minValue() != "0" || !isUnsigned(t)) { // skip writing "if uint<0" (#187579)
+ out << "if (v < " << e->minValue() << ")" << endl;
+ out << "{" << endl;
+ out << " qDebug() << \"" << setFunction(n);
+ out << ": value \" << v << \" is less than the minimum value of ";
+ out << e->minValue()<< "\";" << endl;
+ out << " v = " << e->minValue() << ";" << endl;
+ out << "}" << endl;
+ }
+ }
+
+ if (!e->maxValue().isEmpty())
+ {
+ out << endl << "if (v > " << e->maxValue() << ")" << endl;
+ out << "{" << endl;
+ out << " qDebug() << \"" << setFunction(n);
+ out << ": value \" << v << \" is greater than the maximum value of ";
+ out << e->maxValue()<< "\";" << endl;
+ out << " v = " << e->maxValue() << ";" << endl;
+ out << "}" << endl << endl;
+ }
+
+ out << "if (!" << This << "isImmutable( QString::fromLatin1( \"";
+ if (!e->param().isEmpty())
+ {
+ out << e->paramName().replace("$("+e->param()+")", "%1") << "\" ).arg( ";
+ if ( e->paramType() == "Enum" ) {
+ out << "QLatin1String( ";
+
+ if (cfg.globalEnums)
+ out << enumName(e->param()) << "ToString[i]";
+ else
+ out << enumName(e->param()) << "::enumToString[i]";
+
+ out << " )";
+ }
+ else
+ {
+ out << "i";
+ }
+ out << " )";
+ }
+ else
+ {
+ out << n << "\" )";
+ }
+ out << " ))" << (!e->signalList().empty() ? " {" : "") << endl;
+ out << " " << This << varPath(n, cfg);
+ if (!e->param().isEmpty())
+ out << "[i]";
+ out << " = v;" << endl;
+
+ if ( !e->signalList().empty() ) {
+ Q_FOREACH(const Signal &signal, e->signalList()) {
+ out << " " << This << varPath("settingsChanged", cfg) << " |= " << signalEnumName(signal.name) << ";" << endl;
+ }
+ out << "}" << endl;
+ }
+
+ return result;
+}
+
+// returns the member get default implementation
+// which should go in the h file if inline
+// or the cpp file if not inline
+QString memberGetDefaultBody( CfgEntry *e )
+{
+ QString result = e->code();
+ QTextStream out(&result, QIODevice::WriteOnly);
+ out << endl;
+
+ if (!e->param().isEmpty()) {
+ out << " switch (i) {" << endl;
+ for (int i = 0; i <= e->paramMax(); ++i) {
+ if (!e->paramDefaultValue(i).isEmpty()) {
+ out << " case " << i << ": return " << e->paramDefaultValue(i) << ';' << endl;
+ }
+ }
+ out << " default:" << endl;
+ out << " return " << e->defaultValue().replace("$("+e->param()+')', "i") << ';' << endl;
+ out << " }" << endl;
+ } else {
+ out << " return " << e->defaultValue() << ';';
+ }
+
+ return result;
+}
+
+// returns the item accesor implementation
+// which should go in the h file if inline
+// or the cpp file if not inline
+QString itemAccessorBody( CfgEntry *e, const CfgConfig &cfg )
+{
+ QString result;
+ QTextStream out(&result, QIODevice::WriteOnly);
+
+ out << "return " << itemPath(e, cfg);
+ if (!e->param().isEmpty()) out << "[i]";
+ out << ";" << endl;
+
+ return result;
+}
+
+//indents text adding X spaces per line
+QString indent(QString text, int spaces)
+{
+ QString result;
+ QTextStream out(&result, QIODevice::WriteOnly);
+ QTextStream in(&text, QIODevice::ReadOnly);
+ QString currLine;
+ while ( !in.atEnd() )
+ {
+ currLine = in.readLine();
+ if (!currLine.isEmpty())
+ for (int i=0; i < spaces; i++)
+ out << " ";
+ out << currLine << endl;
+ }
+ return result;
+}
+
+// adds as many 'namespace foo {' lines to p_out as
+// there are namespaces in p_ns
+void beginNamespaces(const QString &p_ns, QTextStream &p_out)
+{
+ if ( !p_ns.isEmpty() ) {
+ const QStringList nameSpaces = p_ns.split( "::" );
+ foreach (const QString &ns, nameSpaces )
+ p_out << "namespace " << ns << " {" << endl;
+ p_out << endl;
+ }
+}
+
+// adds as many '}' lines to p_out as
+// there are namespaces in p_ns
+void endNamespaces(const QString &p_ns, QTextStream &p_out)
+{
+ if ( !p_ns.isEmpty() ) {
+ const int namespaceCount = p_ns.count( "::" ) + 1;
+ for ( int i = 0; i < namespaceCount; ++i )
+ p_out << "}" << endl;
+ p_out << endl;
+ }
+}
+
+
+int main( int argc, char **argv )
+{
+ QCoreApplication app(argc, argv);
+
+ validNameRegexp = new QRegExp("[a-zA-Z_][a-zA-Z0-9_]*");
+
+ QString directoryName, inputFilename, codegenFilename;
+ parseArgs(app.arguments(), directoryName, inputFilename, codegenFilename);
+
+ QString baseDir = directoryName;
+#ifdef Q_OS_WIN
+ if (!baseDir.endsWith('/') && !baseDir.endsWith('\\'))
+#else
+ if (!baseDir.endsWith('/'))
+#endif
+ baseDir.append("/");
+
+ if (!codegenFilename.endsWith(QLatin1String(".kcfgc")))
+ {
+ cerr << "Codegen options file must have extension .kcfgc" << endl;
+ return 1;
+ }
+ QString baseName = QFileInfo(codegenFilename).fileName();
+ baseName = baseName.left(baseName.length() - 6);
+
+ CfgConfig cfg = CfgConfig( codegenFilename );
+
+ QFile input( inputFilename );
+
+ QDomDocument doc;
+ QString errorMsg;
+ int errorRow;
+ int errorCol;
+ if ( !doc.setContent( &input, &errorMsg, &errorRow, &errorCol ) ) {
+ cerr << "Unable to load document." << endl;
+ cerr << "Parse error in " << inputFilename << ", line " << errorRow << ", col " << errorCol << ": " << errorMsg << endl;
+ return 1;
+ }
+
+ QDomElement cfgElement = doc.documentElement();
+
+ if ( cfgElement.isNull() ) {
+ cerr << "No document in kcfg file" << endl;
+ return 1;
+ }
+
+ QString cfgFileName;
+ bool cfgFileNameArg = false;
+ QList<Param> parameters;
+ QList<Signal> signalList;
+ QStringList includes;
+ bool hasSignals = false;
+
+ QList<CfgEntry*> entries;
+
+ for ( QDomElement e = cfgElement.firstChildElement(); !e.isNull(); e = e.nextSiblingElement() ) {
+ QString tag = e.tagName();
+
+ if ( tag == "include" ) {
+ QString includeFile = e.text();
+ if (!includeFile.isEmpty())
+ includes.append(includeFile);
+
+ } else if ( tag == "kcfgfile" ) {
+ cfgFileName = e.attribute( "name" );
+ cfgFileNameArg = e.attribute( "arg" ).toLower() == "true";
+ for( QDomElement e2 = e.firstChildElement(); !e2.isNull(); e2 = e2.nextSiblingElement() ) {
+ if ( e2.tagName() == "parameter" ) {
+ Param p;
+ p.name = e2.attribute( "name" );
+ p.type = e2.attribute( "type" );
+ if (p.type.isEmpty())
+ p.type = "String";
+ parameters.append( p );
+ }
+ }
+
+ } else if ( tag == "group" ) {
+ QString group = e.attribute( "name" );
+ if ( group.isEmpty() ) {
+ cerr << "Group without name" << endl;
+ return 1;
+ }
+ for( QDomElement e2 = e.firstChildElement(); !e2.isNull(); e2 = e2.nextSiblingElement() ) {
+ if ( e2.tagName() != "entry" ) continue;
+ CfgEntry *entry = parseEntry( group, e2, cfg );
+ if ( entry ) entries.append( entry );
+ else {
+ cerr << "Can not parse entry." << endl;
+ return 1;
+ }
+ }
+ }
+ else if ( tag == "signal" ) {
+ QString signalName = e.attribute( "name" );
+ if ( signalName.isEmpty() ) {
+ cerr << "Signal without name." << endl;
+ return 1;
+ }
+ Signal theSignal;
+ theSignal.name = signalName;
+
+ for( QDomElement e2 = e.firstChildElement(); !e2.isNull(); e2 = e2.nextSiblingElement() ) {
+ if ( e2.tagName() == "argument") {
+ SignalArguments argument;
+ argument.type = e2.attribute("type");
+ if ( argument.type.isEmpty() ) {
+ cerr << "Signal argument without type." << endl;
+ return 1;
+ }
+ argument.variableName = e2.text();
+ theSignal.arguments.append(argument);
+ }
+ else if( e2.tagName() == "label") {
+ theSignal.label = e2.text();
+ }
+ }
+ signalList.append(theSignal);
+ }
+ }
+
+ if ( cfg.className.isEmpty() ) {
+ cerr << "Class name missing" << endl;
+ return 1;
+ }
+
+ if ( cfg.singleton && !parameters.isEmpty() ) {
+ cerr << "Singleton class can not have parameters" << endl;
+ return 1;
+ }
+
+ if ( !cfgFileName.isEmpty() && cfgFileNameArg)
+ {
+ cerr << "Having both a fixed filename and a filename as argument is not possible." << endl;
+ return 1;
+ }
+
+ if ( entries.isEmpty() ) {
+ cerr << "No entries." << endl;
+ }
+
+#if 0
+ CfgEntry *cfg;
+ for( cfg = entries.first(); cfg; cfg = entries.next() ) {
+ cfg->dump();
+ }
+#endif
+
+ hasSignals = !signalList.empty();
+ QString headerFileName = baseName + ".h";
+ QString implementationFileName = baseName + ".cpp";
+ QString mocFileName = baseName + ".moc";
+ QString cppPreamble; // code to be inserted at the beginnin of the cpp file, e.g. initialization of static values
+
+ QFile header( baseDir + headerFileName );
+ if ( !header.open( QIODevice::WriteOnly ) ) {
+ cerr << "Can not open '" << baseDir << headerFileName << "for writing." << endl;
+ return 1;
+ }
+
+ QTextStream h( &header );
+
+ h << "// This file is generated by kconfig_compiler from " << QFileInfo(inputFilename).fileName() << "." << endl;
+ h << "// All changes you do to this file will be lost." << endl;
+
+ h << "#ifndef " << ( !cfg.nameSpace.isEmpty() ? QString (QString(cfg.nameSpace).replace( "::", "_" ).toUpper() + '_') : "" )
+ << cfg.className.toUpper() << "_H" << endl;
+ h << "#define " << ( !cfg.nameSpace.isEmpty() ? QString (QString(cfg.nameSpace).replace( "::", "_" ).toUpper() + '_') : "" )
+ << cfg.className.toUpper() << "_H" << endl << endl;
+
+ // Includes
+ QStringList::ConstIterator it;
+ for( it = cfg.headerIncludes.constBegin(); it != cfg.headerIncludes.constEnd(); ++it ) {
+ if ( (*it).startsWith('"') )
+ h << "#include " << *it << endl;
+ else
+ h << "#include <" << *it << ">" << endl;
+ }
+
+ if ( cfg.headerIncludes.count() > 0 ) h << endl;
+
+ if ( !cfg.singleton && parameters.isEmpty() )
+ h << "#include <qglobal.h>" << endl;
+
+ if ( cfg.inherits=="KCoreConfigSkeleton" ) {
+ h << "#include <kcoreconfigskeleton.h>" << endl;
+ } else {
+ h << "#include <kconfigskeleton.h>" << endl;
+ }
+
+ h << "#include <QCoreApplication>" << endl;
+ h << "#include <QDebug>" << endl << endl;
+
+ // Includes
+ for( it = includes.constBegin(); it != includes.constEnd(); ++it ) {
+ if ( (*it).startsWith('"') )
+ h << "#include " << *it << endl;
+ else
+ h << "#include <" << *it << ">" << endl;
+ }
+
+ beginNamespaces(cfg.nameSpace, h);
+
+ // Private class declaration
+ if ( cfg.dpointer )
+ h << "class " << cfg.className << "Private;" << endl << endl;
+
+ // Class declaration header
+ h << "class " << cfg.visibility << cfg.className << " : public " << cfg.inherits << endl;
+
+ h << "{" << endl;
+ // Add Q_OBJECT macro if the config need signals.
+ if( hasSignals )
+ h << " Q_OBJECT" << endl;
+ h << " public:" << endl;
+
+ // enums
+ QList<CfgEntry*>::ConstIterator itEntry;
+ for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry ) {
+ const CfgEntry::Choices &choices = (*itEntry)->choices();
+ const QList<CfgEntry::Choice> chlist = choices.choices;
+ if ( !chlist.isEmpty() ) {
+ QStringList values;
+ QList<CfgEntry::Choice>::ConstIterator itChoice;
+ for( itChoice = chlist.constBegin(); itChoice != chlist.constEnd(); ++itChoice ) {
+ values.append( choices.prefix + (*itChoice).name );
+ }
+ if ( choices.name().isEmpty() ) {
+ if ( cfg.globalEnums ) {
+ h << " enum " << enumName( (*itEntry)->name(), (*itEntry)->choices() ) << " { " << values.join( ", " ) << " };" << endl;
+ } else {
+ // Create an automatically named enum
+ h << " class " << enumName( (*itEntry)->name(), (*itEntry)->choices() ) << endl;
+ h << " {" << endl;
+ h << " public:" << endl;
+ h << " enum type { " << values.join( ", " ) << ", COUNT };" << endl;
+ h << " };" << endl;
+ }
+ } else if ( !choices.external() ) {
+ // Create a named enum
+ h << " enum " << enumName( (*itEntry)->name(), (*itEntry)->choices() ) << " { " << values.join( ", " ) << " };" << endl;
+ }
+ }
+ const QStringList values = (*itEntry)->paramValues();
+ if ( !values.isEmpty() ) {
+ if ( cfg.globalEnums ) {
+ // ### FIXME!!
+ // make the following string table an index-based string search!
+ // ###
+ h << " enum " << enumName( (*itEntry)->param() ) << " { " << values.join( ", " ) << " };" << endl;
+ h << " static const char* const " << enumName( (*itEntry)->param() ) << "ToString[];" << endl;
+ cppPreamble += "const char* const " + cfg.className + "::" + enumName( (*itEntry)->param() ) +
+ "ToString[] = { \"" + values.join( "\", \"" ) + "\" };\n";
+ } else {
+ h << " class " << enumName( (*itEntry)->param() ) << endl;
+ h << " {" << endl;
+ h << " public:" << endl;
+ h << " enum type { " << values.join( ", " ) << ", COUNT };" << endl;
+ h << " static const char* const enumToString[];" << endl;
+ h << " };" << endl;
+ cppPreamble += "const char* const " + cfg.className + "::" + enumName( (*itEntry)->param() ) +
+ "::enumToString[] = { \"" + values.join( "\", \"" ) + "\" };\n";
+ }
+ }
+ }
+ if ( hasSignals ) {
+ h << "\n enum {" << endl;
+ unsigned val = 1;
+ QList<Signal>::ConstIterator it, itEnd = signalList.constEnd();
+ for ( it = signalList.constBegin(); it != itEnd; val <<= 1) {
+ if ( !val ) {
+ cerr << "Too many signals to create unique bit masks" << endl;
+ exit(1);
+ }
+ Signal signal = *it;
+ h << " " << signalEnumName(signal.name) << " = 0x" << hex << val;
+ if ( ++it != itEnd )
+ h << ",";
+ h << endl;
+ }
+ h << " };" << dec << endl;
+ }
+ h << endl;
+ // Constructor or singleton accessor
+ if ( !cfg.singleton ) {
+ h << " " << cfg.className << "(";
+ if (cfgFileNameArg)
+ {
+ if(cfg.forceStringFilename)
+ h << " const QString &cfgfilename"
+ << (parameters.isEmpty() ? " = QString()" : ", ");
+ else
+ h << " KSharedConfig::Ptr config"
+ << (parameters.isEmpty() ? " = KSharedConfig::openConfig()" : ", ");
+ }
+ for (QList<Param>::ConstIterator it = parameters.constBegin();
+ it != parameters.constEnd(); ++it)
+ {
+ if (it != parameters.constBegin())
+ h << ",";
+ h << " " << param((*it).type) << " " << (*it).name;
+ }
+ h << " );" << endl;
+ } else {
+ h << " static " << cfg.className << " *self();" << endl;
+ if (cfgFileNameArg)
+ {
+ h << " static void instance(const QString& cfgfilename);" << endl;
+ }
+ }
+
+ // Destructor
+ h << " ~" << cfg.className << "();" << endl << endl;
+
+ // global variables
+ if (cfg.staticAccessors)
+ This = "self()->";
+ else
+ Const = " const";
+
+ for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry ) {
+ QString n = (*itEntry)->name();
+ QString t = (*itEntry)->type();
+
+ // Manipulator
+ if (cfg.allMutators || cfg.mutators.contains(n))
+ {
+ h << " /**" << endl;
+ h << " Set " << (*itEntry)->label() << endl;
+ h << " */" << endl;
+ if (cfg.staticAccessors)
+ h << " static" << endl;
+ h << " void " << setFunction(n) << "( ";
+ if (!(*itEntry)->param().isEmpty())
+ h << cppType((*itEntry)->paramType()) << " i, ";
+ if (cfg.useEnumTypes && t == "Enum")
+ h << enumType(*itEntry, cfg.globalEnums);
+ else
+ h << param( t );
+ h << " v )";
+ // function body inline only if not using dpointer
+ // for BC mode
+ if ( !cfg.dpointer )
+ {
+ h << endl << " {" << endl;
+ h << indent(memberMutatorBody(*itEntry, cfg), 6 );
+ h << " }" << endl;
+ }
+ else
+ {
+ h << ";" << endl;
+ }
+ }
+ h << endl;
+ // Accessor
+ h << " /**" << endl;
+ h << " Get " << (*itEntry)->label() << endl;
+ h << " */" << endl;
+ if (cfg.staticAccessors)
+ h << " static" << endl;
+ h << " ";
+ if (cfg.useEnumTypes && t == "Enum")
+ h << enumType(*itEntry, cfg.globalEnums);
+ else
+ h << cppType(t);
+ h << " " << getFunction(n) << "(";
+ if (!(*itEntry)->param().isEmpty())
+ h << " " << cppType((*itEntry)->paramType()) <<" i ";
+ h << ")" << Const;
+ // function body inline only if not using dpointer
+ // for BC mode
+ if ( !cfg.dpointer )
+ {
+ h << endl << " {" << endl;
+ h << indent(memberAccessorBody(*itEntry, cfg.globalEnums, cfg), 6 );
+ h << " }" << endl;
+ }
+ else
+ {
+ h << ";" << endl;
+ }
+
+ // Default value Accessor
+ if ((cfg.allDefaultGetters || cfg.defaultGetters.contains(n)) && !(*itEntry)->defaultValue().isEmpty()) {
+ h << endl;
+ h << " /**" << endl;
+ h << " Get " << (*itEntry)->label() << " default value" << endl;
+ h << " */" << endl;
+ if (cfg.staticAccessors)
+ h << " static" << endl;
+ h << " ";
+ if (cfg.useEnumTypes && t == "Enum")
+ h << enumType(*itEntry, cfg.globalEnums);
+ else
+ h << cppType(t);
+ h << " " << getDefaultFunction(n) << "(";
+ if ( !(*itEntry)->param().isEmpty() )
+ h << " " << cppType( (*itEntry)->paramType() ) <<" i ";
+ h << ")" << Const << endl;
+ h << " {" << endl;
+ h << " return ";
+ if (cfg.useEnumTypes && t == "Enum")
+ h << "static_cast<" << enumType(*itEntry, cfg.globalEnums) << ">(";
+ h << getDefaultFunction(n) << "_helper(";
+ if ( !(*itEntry)->param().isEmpty() )
+ h << " i ";
+ h << ")";
+ if (cfg.useEnumTypes && t == "Enum")
+ h << ")";
+ h << ";" << endl;
+ h << " }" << endl;
+ }
+
+ // Item accessor
+ if ( cfg.itemAccessors ) {
+ h << endl;
+ h << " /**" << endl;
+ h << " Get Item object corresponding to " << n << "()"
+ << endl;
+ h << " */" << endl;
+ h << " Item" << itemType( (*itEntry)->type() ) << " *"
+ << getFunction( n ) << "Item(";
+ if (!(*itEntry)->param().isEmpty()) {
+ h << " " << cppType((*itEntry)->paramType()) << " i ";
+ }
+ h << ")";
+ if ( !cfg.dpointer )
+ {
+ h << endl << " {" << endl;
+ h << indent( itemAccessorBody((*itEntry), cfg), 6);
+ h << " }" << endl;
+ }
+ else
+ {
+ h << ";" << endl;
+ }
+ }
+
+ h << endl;
+ }
+
+
+ // Signal definition.
+ if( hasSignals ) {
+ h << endl;
+ h << " Q_SIGNALS:";
+ Q_FOREACH(const Signal &signal, signalList) {
+ h << endl;
+ if ( !signal.label.isEmpty() ) {
+ h << " /**" << endl;
+ h << " " << signal.label << endl;
+ h << " */" << endl;
+ }
+ h << " void " << signal.name << "(";
+ QList<SignalArguments>::ConstIterator it, itEnd = signal.arguments.constEnd();
+ for ( it = signal.arguments.constBegin(); it != itEnd; ) {
+ SignalArguments argument = *it;
+ QString type = param(argument.type);
+ if ( cfg.useEnumTypes && argument.type == "Enum" ) {
+ for ( int i = 0, end = entries.count(); i < end; ++i ) {
+ if ( entries[i]->name() == argument.variableName ) {
+ type = enumType(entries[i], cfg.globalEnums);
+ break;
+ }
+ }
+ }
+ h << type << " " << argument.variableName;
+ if ( ++it != itEnd ) {
+ h << ", ";
+ }
+ }
+ h << ");" << endl;
+ }
+ h << endl;
+ }
+
+ h << " protected:" << endl;
+
+ // Private constructor for singleton
+ if ( cfg.singleton ) {
+ h << " " << cfg.className << "(";
+ if ( cfgFileNameArg )
+ h << "const QString& arg";
+ h << ");" << endl;
+ h << " friend class " << cfg.className << "Helper;" << endl << endl;
+ }
+
+ if ( hasSignals ) {
+ h << " virtual bool usrWriteConfig();" << endl;
+ }
+
+ // Member variables
+ if ( !cfg.memberVariables.isEmpty() && cfg.memberVariables != "private" && cfg.memberVariables != "dpointer") {
+ h << " " << cfg.memberVariables << ":" << endl;
+ }
+
+ // Class Parameters
+ for (QList<Param>::ConstIterator it = parameters.constBegin();
+ it != parameters.constEnd(); ++it)
+ {
+ h << " " << cppType((*it).type) << " mParam" << (*it).name << ";" << endl;
+ }
+
+ if ( cfg.memberVariables != "dpointer" )
+ {
+ QString group;
+ for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry ) {
+ if ( (*itEntry)->group() != group ) {
+ group = (*itEntry)->group();
+ h << endl;
+ h << " // " << group << endl;
+ }
+ h << " " << cppType( (*itEntry)->type() ) << " " << varName( (*itEntry)->name(), cfg );
+ if ( !(*itEntry)->param().isEmpty() )
+ {
+ h << QString("[%1]").arg( (*itEntry)->paramMax()+1 );
+ }
+ h << ";" << endl;
+
+ if ( cfg.allDefaultGetters || cfg.defaultGetters.contains((*itEntry)->name()) )
+ {
+ h << " ";
+ if (cfg.staticAccessors)
+ h << "static ";
+ h << cppType((*itEntry)->type()) << " " << getDefaultFunction((*itEntry)->name()) << "_helper(";
+ if ( !(*itEntry)->param().isEmpty() )
+ h << " " << cppType( (*itEntry)->paramType() ) <<" i ";
+ h << ")" << Const << ";" << endl;
+ }
+ }
+
+ h << endl << " private:" << endl;
+ if ( cfg.itemAccessors ) {
+ for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry ) {
+ h << " Item" << itemType( (*itEntry)->type() ) << " *" << itemVar( *itEntry, cfg );
+ if ( !(*itEntry)->param().isEmpty() ) h << QString("[%1]").arg( (*itEntry)->paramMax()+1 );
+ h << ";" << endl;
+ }
+ }
+ if ( hasSignals )
+ h << " uint " << varName("settingsChanged", cfg) << ";" << endl;
+
+ }
+ else
+ {
+ // use a private class for both member variables and items
+ h << " private:" << endl;
+ for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry ) {
+ if ( cfg.allDefaultGetters || cfg.defaultGetters.contains((*itEntry)->name()) ) {
+ h << " ";
+ if (cfg.staticAccessors)
+ h << "static ";
+ h << cppType((*itEntry)->type()) << " " << getDefaultFunction((*itEntry)->name()) << "_helper(";
+ if ( !(*itEntry)->param().isEmpty() )
+ h << " " << cppType( (*itEntry)->paramType() ) <<" i ";
+ h << ")" << Const << ";" << endl;
+ }
+ }
+ h << " " + cfg.className + "Private *d;" << endl;
+ }
+
+ if (cfg.customAddons)
+ {
+ h << " // Include custom additions" << endl;
+ h << " #include \"" << filenameOnly(baseName) << "_addons.h\"" <<endl;
+ }
+
+ h << "};" << endl << endl;
+
+ endNamespaces(cfg.nameSpace, h);
+
+ h << "#endif" << endl << endl;
+
+
+ header.close();
+
+ QFile implementation( baseDir + implementationFileName );
+ if ( !implementation.open( QIODevice::WriteOnly ) ) {
+ cerr << "Can not open '" << implementationFileName << "for writing."
+ << endl;
+ return 1;
+ }
+
+ QTextStream cpp( &implementation );
+
+
+ cpp << "// This file is generated by kconfig_compiler from " << QFileInfo(inputFilename).fileName() << "." << endl;
+ cpp << "// All changes you do to this file will be lost." << endl << endl;
+
+ cpp << "#include \"" << headerFileName << "\"" << endl << endl;
+
+ for( it = cfg.sourceIncludes.constBegin(); it != cfg.sourceIncludes.constEnd(); ++it ) {
+ if ( (*it).startsWith('"') )
+ cpp << "#include " << *it << endl;
+ else
+ cpp << "#include <" << *it << ">" << endl;
+ }
+
+ if ( cfg.sourceIncludes.count() > 0 ) cpp << endl;
+
+ if ( cfg.setUserTexts && cfg.translationSystem==CfgConfig::KdeTranslation)
+ cpp << "#include <klocalizedstring.h>" << endl << endl;
+
+ // Header required by singleton implementation
+ if ( cfg.singleton )
+ cpp << "#include <qglobal.h>" << endl << "#include <QtCore/QFile>" << endl << endl;
+ if ( cfg.singleton && cfgFileNameArg )
+ cpp << "#include <QDebug>" << endl << endl;
+
+ if ( !cfg.nameSpace.isEmpty() )
+ cpp << "using namespace " << cfg.nameSpace << ";" << endl << endl;
+
+ QString group;
+
+ // private class implementation
+ if ( cfg.dpointer )
+ {
+ beginNamespaces(cfg.nameSpace, cpp);
+ cpp << "class " << cfg.className << "Private" << endl;
+ cpp << "{" << endl;
+ cpp << " public:" << endl;
+ for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry ) {
+ if ( (*itEntry)->group() != group ) {
+ group = (*itEntry)->group();
+ cpp << endl;
+ cpp << " // " << group << endl;
+ }
+ cpp << " " << cppType( (*itEntry)->type() ) << " " << varName( (*itEntry)->name(), cfg );
+ if ( !(*itEntry)->param().isEmpty() )
+ {
+ cpp << QString("[%1]").arg( (*itEntry)->paramMax()+1 );
+ }
+ cpp << ";" << endl;
+ }
+ cpp << endl << " // items" << endl;
+ for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry ) {
+ cpp << " "+cfg.inherits+"::Item" << itemType( (*itEntry)->type() ) << " *" << itemVar( *itEntry, cfg );
+ if ( !(*itEntry)->param().isEmpty() ) cpp << QString("[%1]").arg( (*itEntry)->paramMax()+1 );
+ cpp << ";" << endl;
+ }
+ if ( hasSignals ) {
+ cpp << " uint " << varName("settingsChanged", cfg) << ";" << endl;
+ }
+
+ cpp << "};" << endl << endl;
+ endNamespaces(cfg.nameSpace, cpp);
+ }
+
+ // Singleton implementation
+ if ( cfg.singleton ) {
+ beginNamespaces(cfg.nameSpace, cpp);
+ cpp << "class " << cfg.className << "Helper" << endl;
+ cpp << '{' << endl;
+ cpp << " public:" << endl;
+ cpp << " " << cfg.className << "Helper() : q(0) {}" << endl;
+ cpp << " ~" << cfg.className << "Helper() { delete q; }" << endl;
+ cpp << " " << cfg.className << " *q;" << endl;
+ cpp << "};" << endl;
+ endNamespaces(cfg.nameSpace, cpp);
+ cpp << "Q_GLOBAL_STATIC(" << cfg.className << "Helper, s_global" << cfg.className << ")" << endl;
+
+ cpp << cfg.className << " *" << cfg.className << "::self()" << endl;
+ cpp << "{" << endl;
+ if ( cfgFileNameArg ) {
+ cpp << " if (!s_global" << cfg.className << "()->q)" << endl;
+ cpp << " qFatal(\"you need to call " << cfg.className << "::instance before using\");" << endl;
+ } else {
+ cpp << " if (!s_global" << cfg.className << "()->q) {" << endl;
+ cpp << " new " << cfg.className << ';' << endl;
+ cpp << " s_global" << cfg.className << "()->q->readConfig();" << endl;
+ cpp << " }" << endl << endl;
+ }
+ cpp << " return s_global" << cfg.className << "()->q;" << endl;
+ cpp << "}" << endl << endl;
+
+ if ( cfgFileNameArg ) {
+ cpp << "void " << cfg.className << "::instance(const QString& cfgfilename)" << endl;
+ cpp << "{" << endl;
+ cpp << " if (s_global" << cfg.className << "()->q) {" << endl;
+ cpp << " qDebug() << \"" << cfg.className << "::instance called after the first use - ignoring\";" << endl;
+ cpp << " return;" << endl;
+ cpp << " }" << endl;
+ cpp << " new " << cfg.className << "(cfgfilename);" << endl;
+ cpp << " s_global" << cfg.className << "()->q->readConfig();" << endl;
+ cpp << "}" << endl << endl;
+ }
+ }
+
+ if ( !cppPreamble.isEmpty() )
+ cpp << cppPreamble << endl;
+
+ // Constructor
+ cpp << cfg.className << "::" << cfg.className << "( ";
+ if ( cfgFileNameArg ) {
+ if ( !cfg.singleton && ! cfg.forceStringFilename)
+ cpp << " KSharedConfig::Ptr config";
+ else
+ cpp << " const QString& config";
+ cpp << (parameters.isEmpty() ? " " : ", ");
+ }
+
+ for (QList<Param>::ConstIterator it = parameters.constBegin();
+ it != parameters.constEnd(); ++it)
+ {
+ if (it != parameters.constBegin())
+ cpp << ",";
+ cpp << " " << param((*it).type) << " " << (*it).name;
+ }
+ cpp << " )" << endl;
+
+ cpp << " : " << cfg.inherits << "(";
+ if ( !cfgFileName.isEmpty() ) cpp << " QLatin1String( \"" << cfgFileName << "\" ";
+ if ( cfgFileNameArg ) cpp << " config ";
+ if ( !cfgFileName.isEmpty() ) cpp << ") ";
+ cpp << ")" << endl;
+
+ // Store parameters
+ for (QList<Param>::ConstIterator it = parameters.constBegin();
+ it != parameters.constEnd(); ++it)
+ {
+ cpp << " , mParam" << (*it).name << "(" << (*it).name << ")" << endl;
+ }
+
+ if ( hasSignals && !cfg.dpointer )
+ cpp << " , " << varName("settingsChanged", cfg) << "(0)" << endl;
+
+ cpp << "{" << endl;
+
+ if (cfg.dpointer)
+ {
+ cpp << " d = new " + cfg.className + "Private;" << endl;
+ if (hasSignals)
+ cpp << " " << varPath("settingsChanged", cfg) << " = 0;" << endl;
+ }
+ // Needed in case the singleton class is used as baseclass for
+ // another singleton.
+ if (cfg.singleton) {
+ cpp << " Q_ASSERT(!s_global" << cfg.className << "()->q);" << endl;
+ cpp << " s_global" << cfg.className << "()->q = this;" << endl;
+ }
+
+ group.clear();
+
+ for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry ) {
+ if ( (*itEntry)->group() != group ) {
+ if ( !group.isEmpty() ) cpp << endl;
+ group = (*itEntry)->group();
+ cpp << " setCurrentGroup( " << paramString(group, parameters) << " );" << endl << endl;
+ }
+
+ QString key = paramString( (*itEntry)->key(), parameters );
+ if ( !(*itEntry)->code().isEmpty() ) {
+ cpp << (*itEntry)->code() << endl;
+ }
+ if ( (*itEntry)->type() == "Enum" ) {
+ cpp << " QList<"+cfg.inherits+"::ItemEnum::Choice> values"
+ << (*itEntry)->name() << ";" << endl;
+ const QList<CfgEntry::Choice> choices = (*itEntry)->choices().choices;
+ QList<CfgEntry::Choice>::ConstIterator it;
+ for( it = choices.constBegin(); it != choices.constEnd(); ++it ) {
+ cpp << " {" << endl;
+ cpp << " "+cfg.inherits+"::ItemEnum::Choice choice;" << endl;
+ cpp << " choice.name = QLatin1String(\"" << (*it).name << "\");" << endl;
+ if ( cfg.setUserTexts ) {
+ if ( !(*it).label.isEmpty() ) {
+ cpp << " choice.label = "
+ << translatedString(cfg, (*it).label, (*it).context)
+ << ";" << endl;
+ }
+ if ( !(*it).toolTip.isEmpty() ) {
+ cpp << " choice.toolTip = "
+ << translatedString(cfg, (*it).toolTip, (*it).context)
+ << ";" << endl;
+ }
+ if ( !(*it).whatsThis.isEmpty() ) {
+ cpp << " choice.whatsThis = "
+ << translatedString(cfg, (*it).whatsThis, (*it).context)
+ << ";" << endl;
+ }
+ }
+ cpp << " values" << (*itEntry)->name() << ".append( choice );" << endl;
+ cpp << " }" << endl;
+ }
+ }
+
+ if (!cfg.dpointer)
+ cpp << itemDeclaration( *itEntry, cfg );
+
+ if ( (*itEntry)->param().isEmpty() )
+ {
+ // Normal case
+ cpp << " " << itemPath( *itEntry, cfg ) << " = "
+ << newItem( (*itEntry)->type(), (*itEntry)->name(), key, (*itEntry)->defaultValue(), cfg ) << endl;
+
+ if ( !(*itEntry)->minValue().isEmpty() )
+ cpp << " " << itemPath( *itEntry, cfg ) << "->setMinValue(" << (*itEntry)->minValue() << ");" << endl;
+ if ( !(*itEntry)->maxValue().isEmpty() )
+ cpp << " " << itemPath( *itEntry, cfg ) << "->setMaxValue(" << (*itEntry)->maxValue() << ");" << endl;
+
+ if ( cfg.setUserTexts )
+ cpp << userTextsFunctions( (*itEntry), cfg );
+
+ cpp << " addItem( " << itemPath( *itEntry, cfg );
+ QString quotedName = (*itEntry)->name();
+ addQuotes( quotedName );
+ if ( quotedName != key ) cpp << ", QLatin1String( \"" << (*itEntry)->name() << "\" )";
+ cpp << " );" << endl;
+ }
+ else
+ {
+ // Indexed
+ for(int i = 0; i <= (*itEntry)->paramMax(); i++)
+ {
+ QString defaultStr;
+ QString itemVarStr(itemPath( *itEntry, cfg )+QString("[%1]").arg(i));
+
+ if ( !(*itEntry)->paramDefaultValue(i).isEmpty() )
+ defaultStr = (*itEntry)->paramDefaultValue(i);
+ else if ( !(*itEntry)->defaultValue().isEmpty() )
+ defaultStr = paramString( (*itEntry)->defaultValue(), (*itEntry), i );
+ else
+ defaultStr = defaultValue( (*itEntry)->type() );
+
+ cpp << " " << itemVarStr << " = "
+ << newItem( (*itEntry)->type(), (*itEntry)->name(), paramString(key, *itEntry, i), defaultStr,cfg, QString("[%1]").arg(i) )
+ << endl;
+
+ if ( cfg.setUserTexts )
+ cpp << userTextsFunctions( *itEntry, cfg, itemVarStr, (*itEntry)->paramName() );
+
+ // Make mutators for enum parameters work by adding them with $(..) replaced by the
+ // param name. The check for isImmutable in the set* functions doesn't have the param
+ // name available, just the corresponding enum value (int), so we need to store the
+ // param names in a separate static list!.
+ cpp << " addItem( " << itemVarStr << ", QLatin1String( \"";
+ if ( (*itEntry)->paramType()=="Enum" )
+ cpp << (*itEntry)->paramName().replace( "$("+(*itEntry)->param()+')', "%1").arg((*itEntry)->paramValues()[i] );
+ else
+ cpp << (*itEntry)->paramName().replace( "$("+(*itEntry)->param()+')', "%1").arg(i);
+ cpp << "\" ) );" << endl;
+ }
+ }
+ }
+
+ cpp << "}" << endl << endl;
+
+ if (cfg.dpointer)
+ {
+ // setters and getters go in Cpp if in dpointer mode
+ for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry ) {
+ QString n = (*itEntry)->name();
+ QString t = (*itEntry)->type();
+
+ // Manipulator
+ if (cfg.allMutators || cfg.mutators.contains(n))
+ {
+ cpp << "void " << setFunction(n, cfg.className) << "( ";
+ if ( !(*itEntry)->param().isEmpty() )
+ cpp << cppType( (*itEntry)->paramType() ) << " i, ";
+ if (cfg.useEnumTypes && t == "Enum")
+ cpp << enumType(*itEntry, cfg.globalEnums);
+ else
+ cpp << param( t );
+ cpp << " v )" << endl;
+ // function body inline only if not using dpointer
+ // for BC mode
+ cpp << "{" << endl;
+ cpp << indent(memberMutatorBody( *itEntry, cfg ), 6);
+ cpp << "}" << endl << endl;
+ }
+
+ // Accessor
+ if (cfg.useEnumTypes && t == "Enum")
+ cpp << enumType(*itEntry, cfg.globalEnums);
+ else
+ cpp << cppType(t);
+ cpp << " " << getFunction(n, cfg.className) << "(";
+ if ( !(*itEntry)->param().isEmpty() )
+ cpp << " " << cppType( (*itEntry)->paramType() ) <<" i ";
+ cpp << ")" << Const << endl;
+ // function body inline only if not using dpointer
+ // for BC mode
+ cpp << "{" << endl;
+ cpp << indent(memberAccessorBody( *itEntry, cfg.globalEnums, cfg ), 2);
+ cpp << "}" << endl << endl;
+
+ // Default value Accessor -- written by the loop below
+
+ // Item accessor
+ if ( cfg.itemAccessors )
+ {
+ cpp << endl;
+ cpp << cfg.inherits+"::Item" << itemType( (*itEntry)->type() ) << " *"
+ << getFunction( n, cfg.className ) << "Item(";
+ if ( !(*itEntry)->param().isEmpty() ) {
+ cpp << " " << cppType( (*itEntry)->paramType() ) << " i ";
+ }
+ cpp << ")" << endl;
+ cpp << "{" << endl;
+ cpp << indent(itemAccessorBody( *itEntry, cfg ), 2);
+ cpp << "}" << endl;
+ }
+
+ cpp << endl;
+ }
+ }
+
+ // default value getters always go in Cpp
+ for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry ) {
+ QString n = (*itEntry)->name();
+ QString t = (*itEntry)->type();
+
+ // Default value Accessor, as "helper" function
+ if (( cfg.allDefaultGetters || cfg.defaultGetters.contains(n) ) && !(*itEntry)->defaultValue().isEmpty() ) {
+ cpp << cppType(t) << " " << getDefaultFunction(n, cfg.className) << "_helper(";
+ if ( !(*itEntry)->param().isEmpty() )
+ cpp << " " << cppType( (*itEntry)->paramType() ) <<" i ";
+ cpp << ")" << Const << endl;
+ cpp << "{" << endl;
+ cpp << memberGetDefaultBody(*itEntry) << endl;
+ cpp << "}" << endl << endl;
+ }
+ }
+
+ // Destructor
+ cpp << cfg.className << "::~" << cfg.className << "()" << endl;
+ cpp << "{" << endl;
+ if ( cfg.singleton ) {
+ if ( cfg.dpointer )
+ cpp << " delete d;" << endl;
+ cpp << " s_global" << cfg.className << "()->q = 0;" << endl;
+ }
+ cpp << "}" << endl << endl;
+
+ if ( hasSignals ) {
+ cpp << "bool " << cfg.className << "::" << "usrWriteConfig()" << endl;
+ cpp << "{" << endl;
+ cpp << " const bool res = " << cfg.inherits << "::usrWriteConfig();" << endl;
+ cpp << " if (!res) return false;" << endl << endl;
+ Q_FOREACH(const Signal &signal, signalList) {
+ cpp << " if ( " << varPath("settingsChanged", cfg) << " & " << signalEnumName(signal.name) << " ) " << endl;
+ cpp << " emit " << signal.name << "(";
+ QList<SignalArguments>::ConstIterator it, itEnd = signal.arguments.constEnd();
+ for ( it = signal.arguments.constBegin(); it != itEnd; ) {
+ SignalArguments argument = *it;
+ bool cast = false;
+ if ( cfg.useEnumTypes && argument.type == "Enum" ) {
+ for ( int i = 0, end = entries.count(); i < end; ++i ) {
+ if ( entries[i]->name() == argument.variableName ) {
+ cpp << "static_cast<" << enumType(entries[i], cfg.globalEnums) << ">(";
+ cast = true;
+ break;
+ }
+ }
+ }
+ cpp << varPath(argument.variableName, cfg);
+ if ( cast )
+ cpp << ")";
+ if ( ++it != itEnd )
+ cpp << ", ";
+ }
+ cpp << ");" << endl << endl;
+ }
+ cpp << " " << varPath("settingsChanged", cfg) << " = 0;" << endl;
+ cpp << " return true;" << endl;
+ cpp << "}" << endl;
+ }
+
+ // Add includemoc if they are signals defined.
+ if( hasSignals ) {
+ cpp << endl;
+ cpp << "#include \"" << mocFileName << "\"" << endl;
+ cpp << endl;
+ }
+
+ // clear entries list
+ qDeleteAll( entries );
+
+ implementation.close();
+}