A tool to generate static, typesafe settings access without having to type key strings
The general idea is that instead of this:
You create a settings file like this:
And can now access the data like this:
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.
.toType()
calls needed)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.
Create a pro file with and add the lines:
Create a file named mysettings.xml
and fill it:
Finally, adjust you main to look like this:
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
):
And also add some QML metadata using the Qml element in the settings
And with that, you can use the specified uri to access the settings from QML:
The following sections document the different elements and attributes in the XML format used by the generator.
The possible elements of such a file.
The root Element of the XML document. It defines meta-stuff and the actual nodes and entries.
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 | InstanceScope | DestroyOnAppDestroy | The destruction scope of the create service instance |
Name | XML-Type | Limits | Description |
---|---|---|---|
Include | Include | 0 - ∞ | A header file to be included |
Backend | Backend | 0 - 1 | The definition of the settings backend to use |
Qml | Qml | 0 - 1 | Special configuration parameters for the QML bindings |
TypeMapping | TypeMapping | 0 - ∞ | Type mappings to map abstract type names to C++ types |
<node> | NodeContent Elements | 0 - ∞ | General "node-like" elements, that can be inside any node-like element |
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 <header>) and local includes (#include "header") are supported.
Name | Type | Default/Required | Description |
---|---|---|---|
local | bool | false | Specifies whether the include is a global or a local include |
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.
The backend element can be used to select a different QtMvvm::ISettingsAccessor instead of the standard QtMvvm::QSettingsAccessor.
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 |
Name | XML-Type | Limits | Description |
---|---|---|---|
Param | Param | 0 - ∞ | A parameter to be passed to the backends constructor, before the QObject* parent |
A generic parameter to be passed to C++ method.
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 |
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:
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 <Param type="QDate" asStr="true">2018-05-09</Param>
.
The Qml element contains special properties that are only used for QML binding generation.
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 | 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 |
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 Settings-XML file.
Name | Type | Default/Required | Description |
---|---|---|---|
key | string | required | The fake type name |
type | string | required | The C++-type to replace it with |
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:
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 /
)
Name | Type | Default/Required | Description |
---|---|---|---|
key | string | required | The name (and group key) of the node |
Name | XML-Type | Limits | Description |
---|---|---|---|
<node> | NodeContent Elements | 0 - ∞ | General "node-like" elements, that can be inside any node-like element |
The Entry element is an extension of the 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 <Code>
child element, that contains actual C++-Code that evaluates to a default value.
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 TypeMapping |
qmlGroupKey | string | <key>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 |
Name | XML-Type | Limits | Description |
---|---|---|---|
Code | settings_generator_elements_Code | 0 - 1 | C++-Code to create a default value |
The ListNode element is an extension of the 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.
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 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.
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 |
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.
The XML-Types are not elements, but values of attributes etc. that have been defined for the file.
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 |
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 |
The following code block is a sample of a settings generator XML file. It's a little bigger to show of the capabilities
The following file is the XSD the parser operates on. You can use it to verify your settings xml files.