diff options
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"><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></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< 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 ); +        </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"><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></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< 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 ); +        </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")) << 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 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> ©()                  { 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> ©(); + +  /** +   * 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 <schumacher@kde.org> +            Copyright (c) 2003 Waldo Bastian <bastian@kde.org> +            Copyright (c) 2003 Zack Rusin <zack@kde.org> +            Copyright (c) 2004 Frans Englich <frans.englich@telia.com> +            Copyright (c) 2006 Michaël Larouche <michael.larouche@kdemail.net> + +            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 ¶m = 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> ¶meters) +{ +  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 ¶m = QString(), const QString ¶mValue = 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(); +}  | 
