aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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();
+}