Skycoder42
6 years ago
8 changed files with 459 additions and 18 deletions
@ -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} |
|||
<Settings name="Settings"> |
|||
<Node key="my"> |
|||
<Entry key="key" type="int" default="42"/> |
|||
</Node> |
|||
</Settings> |
|||
@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} |
|||
<?xml version="1.0" encoding="UTF-8" ?> |
|||
<Settings name="MySettings"> |
|||
<Node key="my"> |
|||
<Entry key="key" type="int" default="42"/> |
|||
</Node> |
|||
</Settings> |
|||
@endcode |
|||
|
|||
Finally, adjust you main to look like this: |
|||
@code{.cpp} |
|||
#include <QCoreApplication> |
|||
#include <QDebug> |
|||
#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} |
|||
<?xml version="1.0" encoding="UTF-8" ?> |
|||
<Settings name="MySettings"> |
|||
<Qml uri="com.example.settings" |
|||
major="1" |
|||
minor="0"/> |
|||
<!-- ... --> |
|||
</Settings> |
|||
@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 <header>) |
|||
and local includes (#include "header") are supported.<br/> |
|||
|
|||
@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} |
|||
<Param type="int">-1</Param> |
|||
<Param type="int">10 + 20</Param> |
|||
<Param type="int">qRand()</Param> |
|||
@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 |
|||
`<Param type="QDate" asStr="true">2018-05-09</Param>`.<br/> |
|||
|
|||
@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 `<Code>` 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 | `<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 |
|||
|
|||
@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 |
|||
*/ |
@ -0,0 +1,86 @@ |
|||
<?xml version="1.0" encoding="UTF-8" ?> |
|||
<Settings name="TestSettings" |
|||
prefix="SOME_EXPORT" |
|||
baseKey="tests" |
|||
scope="DestroyOnAppQuit"> |
|||
<Include>QtCore/QDateTime</Include> |
|||
<Include local="false">QtCore/QUrl</Include> |
|||
<Include local="true">testbackend.h</Include> |
|||
|
|||
<Backend class="TestBackend"> |
|||
<Param type="QString" asStr="true">Test Backend</Param> |
|||
<Param type="int">42</Param> |
|||
</Backend> |
|||
|
|||
<TypeMapping key="range" type="int"/> |
|||
|
|||
<Node key="emptyNode"/> |
|||
<Entry key="emptyEntry" |
|||
type="bool"/> |
|||
<Entry key="advancedEntry" |
|||
type="QString" |
|||
qmlGroupKey="qmlAdvancedEntry" |
|||
default="Hello World" |
|||
tr="true" |
|||
trContext="some_context"/> |
|||
<Entry key="codeEntry" |
|||
type="QUrl"> |
|||
<Code>QUrl::fromLocalFile(QStringLiteral("/path/to/something"))</Code> |
|||
</Entry> |
|||
|
|||
<Node key="parentNode"> |
|||
<Node key="emptyChildNode"/> |
|||
<Node key="fullChildNode"> |
|||
<Entry key="replaceEntry" |
|||
type="range" |
|||
default="42"/> |
|||
</Node> |
|||
<Entry key="parentEntry" |
|||
type="bool" |
|||
default="true"> |
|||
<Node key="subNode"/> |
|||
<Entry key="nodeWithCodeEntry" |
|||
type="int"> |
|||
<Node key="someNode"/> |
|||
<Code> |
|||
qRound(42.8) |
|||
</Code> |
|||
</Entry> |
|||
<Entry key="leafEntry" |
|||
type="QString" |
|||
default="translate me" |
|||
tr="true"/> |
|||
</Entry> |
|||
</Node> |
|||
|
|||
<Entry key="voidEntry" |
|||
type="void"/> |
|||
<Entry key="variantEntry" |
|||
type="QVariant"/> |
|||
<Entry key="simpleListEntry" |
|||
type="QList<int>"> |
|||
<Code>{42}</Code> |
|||
</Entry> |
|||
|
|||
<ListNode key="listNode"> |
|||
<Entry key="simpleChild" |
|||
type="bool"/> |
|||
<Node key="someNode"> |
|||
<Entry key="deepChild" |
|||
type="int" |
|||
default="22"/> |
|||
<Entry key="deepParent" |
|||
type="QString" |
|||
default="___"> |
|||
<Entry key="simpleChild" |
|||
type="bool" |
|||
default="true"/> |
|||
</Entry> |
|||
</Node> |
|||
<ListNode key="childList"> |
|||
<Entry key="valueEntry" |
|||
type="double" |
|||
default="4.2"/> |
|||
</ListNode> |
|||
</ListNode> |
|||
</Settings> |
Loading…
Reference in new issue