diff --git a/deploy.json b/deploy.json
index fa7d357..bd3f8b3 100644
--- a/deploy.json
+++ b/deploy.json
@@ -20,5 +20,8 @@
"installs": {
"ProjectTemplate": "Tools/QtCreator/share/qtcreator/templates/wizards/projects/qtmvvm",
"qbs/Qt/settingsgenerator": "Tools/QtCreator/share/qtcreator/qbs/share/qbs/modules/Qt/settingsgenerator"
- }
+ },
+ "hostbuilds": [
+ "bin/qsettingsgenerator*"
+ ]
}
diff --git a/doc/Doxyfile b/doc/Doxyfile
index 23ba9f6..c99a0fa 100644
--- a/doc/Doxyfile
+++ b/doc/Doxyfile
@@ -999,7 +999,9 @@ EXCLUDE_SYMBOLS = QtMvvm::__helpertypes \
# command).
EXAMPLE_PATH = ../examples \
- ./snippets
+ ./snippets \
+ ../src/settingsconfig \
+ ../tools/settingsgenerator
# If the value of the EXAMPLE_PATH tag contains directories, you can use the
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
diff --git a/doc/qsettingsgenerator.dox b/doc/qsettingsgenerator.dox
new file mode 100644
index 0000000..e8d5d51
--- /dev/null
+++ b/doc/qsettingsgenerator.dox
@@ -0,0 +1,336 @@
+/*!
+@page settings_generator The qsettingsgenerator Tool
+@brief A tool to generate static, typesafe settings access without having to type key strings
+
+@tableofcontents
+
+The general idea is that instead of this:
+@code{.cpp}
+QSettins settings;
+int value = settings.value("my/key", 42).toInt();
+@endcode
+
+You create a settings file like this:
+@code{.xml}
+
+
+
+
+
+@endcode
+
+And can now access the data like this:
+@code{.cpp}
+int value = Settings::instance()->my.key;
+@endcode
+
+So in summary: First, using QSettings requires you to type in
+strings as keys - which cannot be checked by the compiler. With this tool you get a c++ member
+hirachie instead - which is checked by the compiler and thus typo free. Also, the values in
+the settings are made statically typed by using this generator. The second point was to support
+multiple backends, not only QSettings, without having to change the frontend code.
+
+@section settings_generator_features Features
+- Access settings via code - no more typos and redundant strings!
+- Static typing gives additionl saftey and is easier to use (no `.toType()` calls needed)
+- Default values in one single, central place - less error prone and easier to maintain
+ - Can be specified as strings in the xml
+ - Can be specified as C++ code in the xml
+- Use as a global single instance or create local instances
+- Support for custom settings backends instead of QSettings alone
+ - QtMvvm::QSettingsAccessor for usage with QSettings (the default)
+ - QtMvvm::DataSyncSettingsAccessor to sync settings via [QtDataSync](https://github.com/Skycoder42/QtDataSync)
+ - QtMvvm::AndroidSettingsAccessor (android only) to access the SharedPreferences
+- Can be used as an injectable service
+
+@section settings_generator_usage Usage
+Using QtMvvmCore adds a custom qmake compiler to you project. All you need to do is to create the settings xml
+definition and then add it to the pro file as `SETTINGS_DEFINITIONS += mysettings.xml`. This will create a header
+named "mysettings.h" you can include. That header contains the C++ generated settings class to access the settings.
+
+@subsection settings_generator_usage_example Example
+Create a pro file with and add the lines:
+@code{.pro}
+QT += mvvmcore
+
+SETTINGS_DEFINITIONS += mysettings.xml
+@endcode
+
+Create a file named `mysettings.xml` and fill it:
+@code{.xml}
+
+
+
+
+
+
+@endcode
+
+Finally, adjust you main to look like this:
+@code{.cpp}
+#include
+#include
+#include "mysettings.h"
+
+int main(int argc, char *argv[])
+{
+ QCoreApplication a(argc, argv);
+
+ int myKey = MySettings::instance()->my.key;
+ qDebug() << myKey;
+
+ return 0;
+}
+@endcode
+
+@section settings_generator_qml QML-Bindings
+The tool can also generate QML-Bindings, so you can access the settings in the same way from
+QML. To do so, add to your pro file (in addition to `SETTINGS_DEFINITIONS`):
+@code{.pro}
+QML_SETTINGS_DEFINITIONS += mysettings.xml
+@endcode
+
+And also add some QML metadata using the Qml element in the settings
+@code{.xml}
+
+
+
+
+
+@endcode
+
+And with that, you can use the specified uri to access the settings from QML:
+@code{.qml}
+import com.example.settings 1.0
+
+SomeItem {
+ someProperty: MySettings.my.key
+}
+@endcode
+
+@section settings_generator_format XML-Format Documentation
+The following sections document the different elements and attributes in the XML format used
+by the generator.
+
+@subsection settings_generator_elements Elements
+The possible elements of such a file.
+
+@subsubsection settings_generator_elements_Settings Settings
+The root Element of the XML document. It defines meta-stuff and the actual nodes and entries.
+
+@paragraph settings_generator_elements_Settings_attributes Attributes
+ Name | Type | Default/Required | Description
+------------|-----------------------------------------------|-----------------------|-------------
+ name | string | _filename_ | The C++ class name of the generated class
+ prefix | string | _empty_ | Specify an export macro. The value is put before the class definition, if you want to export the generated class from a dynamic library
+ baseKey | string | _empty_ | A base settings key that is prepended to all keys
+ scope | @ref settings_generator_values_InstanceScope | DestroyOnAppDestroy | The destruction scope of the create service instance
+
+@paragraph settings_generator_elements_Settings_children Child elements
+ Name | XML-Type | Limits | Description
+----------------|-----------------------------------------------|-----------|-------------
+ Include | @ref settings_generator_elements_Include | 0 - ∞ | A header file to be included
+ Backend | @ref settings_generator_elements_Backend | 0 - 1 | The definition of the settings backend to use
+ Qml | @ref settings_generator_elements_Qml | 0 - 1 | Special configuration parameters for the QML bindings
+ TypeMapping | @ref settings_generator_elements_TypeMapping | 0 - ∞ | Type mappings to map abstract type names to C++ types
+ <node> | @ref settings_generator_elements_NodeContent | 0 - ∞ | General "node-like" elements, that can be inside any node-like element
+
+@subsubsection settings_generator_elements_Include Include
+Describes a file to be included via a c++ include directive. You can use them if you want to
+make use of special classes in your generated classes. Both global includes (#include )
+and local includes (#include "header") are supported.
+
+@paragraph settings_generator_elements_Include_attributes Attributes
+ Name | Type | Default/Required | Description
+--------|-------|-------------------|-------------
+ local | bool | false | Specifies whether the include is a global or a local include
+
+@paragraph settings_generator_elements_Include_children Content
+The content of this element must be a string. More specific the header to be included. It
+becomes the content of the include directive. Specifiy it without the braces or quores, as thoes
+are added automatically.
+
+@subsubsection settings_generator_elements_Backend Backend
+The backend element can be used to select a different QtMvvm::ISettingsAccessor instead of the
+standard QtMvvm::QSettingsAccessor.
+
+@paragraph settings_generator_elements_Backend_attributes Attributes
+ Name | Type | Default/Required | Description
+--------|-----------|-------------------|-------------
+ class | string | _required_ | The C++ class name of the backend to be used. Must be a class that implements QtMvvm::ISettingsAccessor
+
+@paragraph settings_generator_elements_Backend_children Child elements
+ Name | XML-Type | Limits | Description
+--------|-------------------------------------------|-----------|-------------
+ Param | @ref settings_generator_elements_Param | 0 - ∞ | A parameter to be passed to the backends constructor, before the QObject* parent
+
+@subsubsection settings_generator_elements_Param Param
+A generic parameter to be passed to C++ method.
+
+@paragraph settings_generator_elements_Param_attributes Attributes
+ Name | Type | Default/Required | Description
+--------|-----------|-------------------|-------------
+ type | string | _required_ | The C++ class name of type of the parameter.
+ asStr | bool | false | Specify how the element content should be interpreted
+
+@paragraph settings_generator_elements_Param_children Content
+The content of a param represents the value of the parameter. How the content is interpreted
+depends on the asStr attribute.
+
+If it is set to false (the default), the content must be c++ code and is copied to the generated
+class as is. The code must be an expression that evalutes to a single value that is implicitly
+convertible to the given type. If type was for example int, valid expressions could be:
+
+@code{.xml}
+-1
+10 + 20
+qRand()
+@endcode
+
+If set to true, the content is assumed to be a string. You don't need to specify quotation
+marks around the string. That string is used to initialize a QVariant that is then converted to
+type - in other words, the type you use must be variant convertible from a string. This can be
+used to, for example, create a QDate from a string with the value of
+`2018-05-09`.
+
+@subsubsection settings_generator_elements_Qml Qml
+The Qml element contains special properties that are only used for QML binding generation.
+
+@paragraph settings_generator_elements_Qml_attributes Attributes
+ Name | Type | Default/Required | Description
+------------|-------------------------------------------------------|-------------------|-------------
+ uri | string | _required_ | The QML-Import URI for the QML module
+ major | int | 1 | The major version of the generated module
+ minor | int | 0 | The minor version of the generated module
+ type | @ref settings_generator_values_QmlRegistrationMode | Singleton | The mode on how to register the instance in QML
+ register | bool | true | Specify, if the type should be registered automatically
+ header | string | _empty_ | A custom path to the generate C++-Code of the settings generator, if it can't be the default path
+
+@subsubsection settings_generator_elements_TypeMapping TypeMapping
+Type mappings allow you to specify the C++-type of an arbitrary type to be replaced by in the
+generated code. This can be useful when importing a @ref settings_xml "Settings-XML" file.
+
+@paragraph settings_generator_elements_TypeMapping_attributes Attributes
+ Name | Type | Default/Required | Description
+--------|-----------|-------------------|-------------
+ key | string | _required_ | The fake type name
+ type | string | _required_ | The C++-type to replace it with
+
+@subsubsection settings_generator_elements_NodeContent NodeContent Elements
+Elements that have the NodeContent as child type can have a combination of the following
+actual child elements. Can can be unordered and mixed in any way:
+
+- @ref settings_generator_elements_Node
+- @ref settings_generator_elements_Entry
+- @ref settings_generator_elements_ListNode
+- @ref settings_generator_elements_Import
+
+@subsubsection settings_generator_elements_Node Node
+The node represents a sub-group within the settings. All elements within the node will have
+the node's key prepended to their key (seperated by a `/`)
+
+@paragraph settings_generator_elements_Node_attributes Attributes
+ Name | Type | Default/Required | Description
+--------|-----------|-------------------|-------------
+ key | string | _required_ | The name (and group key) of the node
+
+@paragraph settings_generator_elements_Node_children Child elements
+ Name | XML-Type | Limits | Description
+----------------|-----------------------------------------------|-----------|-------------
+ <node> | @ref settings_generator_elements_NodeContent | 0 - ∞ | General "node-like" elements, that can be inside any node-like element
+
+@subsubsection settings_generator_elements_Entry Entry
+The Entry element is an extension of the @ref settings_generator_elements_Node type. This
+means it's the same as a Node, but with additional properties.
+
+The entry represents a leaf entry in the settings, with a value that can be loaded and stored
+from the settings via the entry's key (within the node subgroups). Entries themselves can also
+be used as a node as well, and thus contain child elements, too.
+
+The default value can be specified in 2 ways. Either as a string (via the attribute) that is
+converted to the target type using QVariant, or via the `` child element, that contains
+actual C++-Code that evaluates to a default value.
+
+@sa QtMvvm::SettingsEntry
+
+@paragraph settings_generator_elements_Entry_attributes Attributes
+ Name | Type | Default/Required | Description
+------------|-----------|-------------------|-------------
+type | string | _required_ | The C++-type that this entry saves and loads. Can be a virtual type, that is resolved by a @ref settings_generator_elements_TypeMapping
+qmlGroupKey | string | `Group` | The name the property that holds the entries sub-nodes for the QML binding
+default | string | _empty_ | A default value (as string) to be returned if the entry is not stored in the settings
+tr | bool | false | Specify whether the default value should be translated
+trContext | string | _filename_ | A custom translation context to use instead of the filename
+
+@paragraph settings_generator_elements_Entry_children Additional Child elements
+ Name | XML-Type | Limits | Description
+--------|---------------------------------------|-----------|-------------
+ Code | @ref settings_generator_elements_Code | 0 - 1 | C++-Code to create a default value
+
+@subsubsection settings_generator_elements_ListNode ListNode
+The ListNode element is an extension of the @ref settings_generator_elements_Node type. This
+means it's the same as a Node, but with additional properties.
+
+The ListNode is a special node that allows you to easily store lists of elements. All children
+that are defined within a listnode are part of the "array elements", so you will access
+elements in a list node via `listNode[2].group.entry` and can append and remove elements from
+that list.
+
+@sa QtMvvm::SettingsListNode
+
+@subsubsection settings_generator_elements_ImportType ImportType
+The Imports allow you to include other files within this one as sub elements. You can include
+either a Settings-Generator-XML (this file) or a @ref settings_xml "Settings-XML". The
+imported file is then treated like it's contents where simply defined instead of the import
+element, allowing seemless combination of different files.
+
+You can use the rootNode to instead of importing the root element in the importet file, go
+down to the node that matches the key defined by rootNode and only import that part.
+
+@paragraph settings_generator_elements_ImportType_attributes Attributes
+ Name | Type | Default/Required | Description
+------------|-----------|-------------------|-------------
+ required | bool | true | Specify, if the import is required or optional
+ rootNode | string | _empty_ | A root node withing the imported file to use as a starting point
+
+@paragraph settings_generator_elements_ImportType_children Content
+The content of the element is a string - the path to the file to be imported. If the path is
+a relative path, it is resolved relative to the file that is importing it, aka "this" file.
+
+@subsection settings_generator_values XML-Types
+The XML-Types are not elements, but values of attributes etc. that have been defined for the
+file.
+
+@subsubsection settings_generator_values_InstanceScope InstanceScope
+InstanceScope is a simple enum with the following allowed values:
+
+ Name | Description
+----------------------------|-------------
+ DestroyOnAppQuit | Sets the scope of the created mvvm service to QtMvvm::ServiceRegistry::DestroyOnAppQuit
+ DestroyOnAppDestroy | Sets the scope of the created mvvm service to QtMvvm::ServiceRegistry::DestroyOnAppDestroy
+ DestroyOnRegistryDestroy | Sets the scope of the created mvvm service to QtMvvm::ServiceRegistry::DestroyOnRegistryDestroy
+ DestroyNever | Sets the scope of the created mvvm service to QtMvvm::ServiceRegistry::DestroyNever
+
+@subsubsection settings_generator_values_QmlRegistrationMode QmlRegistrationMode
+InstanceScope is a simple enum with the following allowed values:
+
+ Name | Description
+----------------|-------------
+ Singleton | Register the QML type as a singleton instance
+ Uncreatable | Register the QML type as a uncreatable type
+ Creatable | Register the QML type as a normal, constructable type
+
+@section settings_generator_sample Sample settings generator XML file
+The following code block is a sample of a settings generator XML file. It's a little bigger to
+show of the capabilities
+
+@include generatortest.xml
+
+@section settings_xml_xsd The XSD for the settings files
+The following file is the XSD the parser operates on. You can use it to verify your settings
+xml files.
+
+@include qsettingsgenerator.xsd
+*/
diff --git a/doc/settingsxml.dox b/doc/settingsxml.dox
index 3398a87..96deca8 100644
--- a/doc/settingsxml.dox
+++ b/doc/settingsxml.dox
@@ -9,18 +9,24 @@ QtMvvm::ISettingsSetupLoader. The files are read via that service and mapped to
QtMvvm::SettingsElements::Setup.
@section settings_xml_translator Translations
-All the settings files you have can be easily translated via a standard ts/qm file. In order for
-this to work, all you have to do is add the following lines to your pro file:
+All the settings files you have can be easily translated via a standard ts/qm file. The following
+explains how exactly.
+
+The mvvm core module comes with a special make taget, called `lupdate` that will automatically
+run lupdate when your sources change to update the TRANSLATIONS files. To not run this automatically,
+call qmake with `qmake CONFIG+=no_auto_lupdate ...`. In both cases, you can always run `make lupdate`
+to explicitly update the dependencies.
+
+With this step enabled, the only thing left to do is to add the settings xml file to the translation
+targets so it gets included as a source when running the lupdate target. To do so, simply add it
+to the `SETTINGS_TRANSLATIONS` qmake variable:
@code{.pro}
-QTMVVM_TS_SETTINGS += settings.xml
-_never_true_condition: SOURCES += $$files($$PWD/.ts-dummy/*)
-PRE_TARGETDEPS += qtmvvm-tsgen #optional
+SETTINGS_TRANSLATIONS += settings.xml
@endcode
-This will automatically generate a dummy cpp file in the `.ts-dummy` folder for each file
-added to the `QTMVVM_TS_SETTINGS` variable. These files contain dummy code that will then be
-read by lupdate automatically and added to all your ts files.
+This will internally generate a cpp file that is parsed and included in lupdate when running it
+via the builtin lupdate target.
@section settings_xml_elements Elements
The possible elements of such a file
@@ -162,6 +168,7 @@ long as for the last two their type is `object`
key | string | Required | no | The key of the property
type | @ref settings_xml_types_type | Required | no | The type of the properties value
tr | bool | `false` | no | Specify whether the properties value (content) should be translated. Does not apply to `list` or `object` types
+ ztr | bool | `false` | no | Like tr, but does not translate the text, only generate the translation in the ts file
@subsubsection settings_xml_elements_property_elements Content
@@ -185,6 +192,7 @@ same.
--------|-------------------------------|-------------------|---------------|-------------
type | @ref settings_xml_types_type | Required | no | The type of the list element
tr | bool | `false` | no | Specify whether the element value (content) should be translated. Does not apply to `list` or `object` types
+ ztr | bool | `false` | no | Like tr, but does not translate the text, only generate the translation in the ts file
@subsubsection settings_xml_elements_element_elements Content
The content depend on the `type` attribute. The following tables shows which type leads
@@ -206,9 +214,11 @@ element must be a `` element (Each element that support includes as one c
marked as primary). It is possible to specify an include element in another included document.
@subsubsection settings_xml_elements_include_attribs Attributes
- Name | Type | Default | Translated | Description
-------------|-------|-----------|---------------|-------------
- optional | bool | `false` | no | An optional include. If the file cannot be found it is skipped instead of aborting with an error
+ Name | Type | Default | Translated | Description
+------------|---------------------------------------|---------------|---------------|-------------
+ optional | bool | `false` | no | An optional include. If the file cannot be found it is skipped instead of aborting with an error
+ frontends | @ref settings_xml_types_descriptor | Empty | no | @copybrief QtMvvm::SettingsElements::Entry::frontends
+ selectors | @ref settings_xml_types_descriptor | Empty | no | @copybrief QtMvvm::SettingsElements::Entry::selectors
@subsubsection settings_xml_elements_include_elements Content
The content of the include element must be a path to an XML file to be read as include. If the
@@ -300,4 +310,10 @@ The following code block is a sample settings XML file. It is the same that is b
the example application.
@include settings.xml
+
+@section settings_xml_xsd The XSD for the settings files
+The following file is the XSD the parser operates on. You can use it to verify your settings
+xml files.
+
+@include settingsconfig.xsd
*/
diff --git a/doc/snippets/generatortest.xml b/doc/snippets/generatortest.xml
new file mode 100644
index 0000000..1c681f6
--- /dev/null
+++ b/doc/snippets/generatortest.xml
@@ -0,0 +1,86 @@
+
+
+ QtCore/QDateTime
+ QtCore/QUrl
+ testbackend.h
+
+
+ Test Backend
+ 42
+
+
+
+
+
+
+
+
+ QUrl::fromLocalFile(QStringLiteral("/path/to/something"))
+
+
+
+
+
+
+
+
+
+
+
+
+ qRound(42.8)
+
+
+
+
+
+
+
+
+
+ {42}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mkspecs/features/qsettingstranslator.prf b/mkspecs/features/qsettingstranslator.prf
index ce645a6..ba2d1f9 100644
--- a/mkspecs/features/qsettingstranslator.prf
+++ b/mkspecs/features/qsettingstranslator.prf
@@ -31,7 +31,7 @@ QSETTINGSTRANSLATOR_DIR = $$QSETTINGSTRANSLATOR_DIR$$SUFFIX
lupdate_trcond_c.variable_out = TRANSLATIONS_CONDITION
lupdate_trcond_c.commands = echo created > ${QMAKE_FILE_OUT}
lupdate_trcond_c.output = $$QSETTINGSTRANSLATOR_DIR/trcond.cpp
- lupdate_trcond_c.CONFIG += combine no_link
+ lupdate_trcond_c.CONFIG += combine no_link explicit_dependencies
QMAKE_EXTRA_COMPILERS += lupdate_trcond_c
lupdate_fakepri_c.name = fakepri ${QMAKE_FILE_IN}
diff --git a/src/mvvmcore/mvvmcore.pro b/src/mvvmcore/mvvmcore.pro
index c590548..a705e7e 100644
--- a/src/mvvmcore/mvvmcore.pro
+++ b/src/mvvmcore/mvvmcore.pro
@@ -42,7 +42,7 @@ SOURCES += \
settingsconfigloader.cpp
android {
- #QT += androidextras
+ QT += androidextras
HEADERS += \
androidsettingsaccessor.h \
diff --git a/tools/settingsgenerator/qsettingsgenerator.xsd b/tools/settingsgenerator/qsettingsgenerator.xsd
index 8d7ce02..deb35a2 100644
--- a/tools/settingsgenerator/qsettingsgenerator.xsd
+++ b/tools/settingsgenerator/qsettingsgenerator.xsd
@@ -100,9 +100,7 @@
-
-
-
+