Browse Source

wip doc

pull/2/head
Skycoder42 6 years ago
parent
commit
99a2df8025
No known key found for this signature in database GPG Key ID: 8E01AD9EF0578D2B
  1. 10
      README.md
  2. 70
      doc/coreapp.dox
  3. 125
      doc/isettingsaccessor.dox
  4. 1
      src/mvvmcore/binding.h
  5. 12
      src/mvvmcore/coreapp.h
  6. 15
      src/mvvmcore/isettingsaccessor.h
  7. 4
      src/mvvmcore/mvvmcore.pro
  8. 7
      src/mvvmdatasynccore/datasyncsettingsentry.cpp

10
README.md

@ -17,10 +17,14 @@ The main feature of QtMvvm is the seperation between ui and logic. With this lib
The key features are:
- Create ViewModels in the core application to prepare data for presentation without binding to any concret GUI
- Supports singleton ViewModels
- Supports automatic presentation of container ViewModels
- Functions to show messageboxes (info, warning, error, etc.) from your core app
- Asynchronous, with result handling
- Supports input dialogs and native file dialogs out of the box
- Supports native file pickers on Android
- Supports color picker dialog
- Supports progress and busy indicator dialogs
- custom dialog types can be created
- Methods to create Two-Way Bindings from C++ and QML
- Macros and a ServiceRegistry to make Dependency Injection possible for Services and ViewModels
@ -136,8 +140,8 @@ The most important part is to know how to add new ViewModels and Views.
```qml
import QtQuick 2.10
import QtQuick.Controls 2.3
import de.skycoder42.QtMvvm.Core 1.0
import de.skycoder42.QtMvvm.Quick 1.0
import de.skycoder42.QtMvvm.Core 1.1
import de.skycoder42.QtMvvm.Quick 1.1
import com.example.mvvmexample 1.0 //adjust to the module defined in your main.cpp
```
- Add a property named viewmodel to the root element: `property MyCustomViewModel viewmodel: null` (If you did not register the viewmodel, use `var` instead of `MyCustomViewModel` as property type)
@ -169,7 +173,7 @@ To create a presenter, the `QtMvvm::IPresenter` must be implemented and provided
- The `QtMvvmApp` qml types automatically register themselves as presenter and perform the presentations
- Supports Items as new fullscreen pages inside a stack view, as drawer or as tabs
- Supports Popups as modal dialogs
-
## Icons
In many of the UI projects default icons are used for the views (if no icon theme is present). They are taken from:

70
doc/coreapp.dox

@ -92,10 +92,11 @@ CoreApp::disableAutoBoot
*/
/*!
@fn QtMvvm::CoreApp::show(const QVariantHash &)
@fn QtMvvm::CoreApp::show(const QVariantHash &, QPointer<ViewModel>)
@tparam TViewModel The type of the viewmodel to be presented
@param params A map of named parameters to be passed to the viewmodel
@param parentViewModel The viewmodel to be used as logical parent to the new one, for presenting
Creates a new instance of the Viewmodel class, creates to corresponding view and then shows it.
This is done via the IPresenter that is currently registered.
@ -104,25 +105,29 @@ This is done via the IPresenter that is currently registered.
*/
/*!
@fn QtMvvm::CoreApp::show(const char *, const QVariantHash &)
@fn QtMvvm::CoreApp::show(const char *, const QVariantHash &, QPointer<ViewModel>)
@param viewModelName The name of the viewmodel to be presented
@param params A map of named parameters to be passed to the viewmodel
@param parentViewModel The viewmodel to be used as logical parent to the new one, for presenting
Creates a new instance of the Viewmodel class, creates to corresponding view and then shows it.
This is done via the IPresenter that is currently registered.
This is done via the IPresenter that is currently registered, taking the parent viewmodel into
consideration where neccessary.
@sa ViewModel::show, CoreApp::showDialog
*/
/*!
@fn QtMvvm::CoreApp::show(const QMetaObject *, const QVariantHash &)
@fn QtMvvm::CoreApp::show(const QMetaObject *, const QVariantHash &, QPointer<ViewModel>)
@param viewModelMetaObject The metaobject of the viewmodel to be presented
@param params A map of named parameters to be passed to the viewmodel
@param parentViewModel The viewmodel to be used as logical parent to the new one, for presenting
Creates a new instance of the Viewmodel class, creates to corresponding view and then shows it.
This is done via the IPresenter that is currently registered.
This is done via the IPresenter that is currently registered, taking the parent viewmodel into
consideration where neccessary.
@sa ViewModel::show, CoreApp::showDialog
*/
@ -142,6 +147,61 @@ been closed.
@sa CoreApp::show, MessageConfig, MessageResult
*/
/*!
@fn QtMvvm::CoreApp::safeCastInputType
@param type The edit type the given value is supposed to be of
@param value The value to be cast to the type specified by the edit type
@returns A variant of the given value, cast to that type
The primary function of this method is to cast types like `url` to their respective C++ equivalent,
i.e. `QUrl`. The table below shows the default type conversion map, and custom entries can be
added via registerInputTypeMapping(). For all types not in that mapping, the function tries
to see `type` like a C++ typename, i.e. `int` and use that to convert the variant. If no type
can be determined, the value is returned without doing anything.
Edit-Type | C++-Type
------------|----------
switch | bool
string | QString
number | double
range | int
date | QDateTime
color | QColor
url | QUrl
var | QVariant
variant | QVariant
selection | QVariant
list | QVariant
radiolist | QVariant
@sa CoreApp::registerInputTypeMapping
*/
/*!
@fn QtMvvm::CoreApp::registerInputTypeMapping(const QByteArray &)
@tparam T The C++ type to be registered for the given edit type
@param type The edit type to register the C++ type for
Registeres the given type, so that whenever type is passed to safeCastInputType(), the given
variant will be converter to T
@sa CoreApp::safeCastInputType
*/
/*!
@fn QtMvvm::CoreApp::registerInputTypeMapping(const QByteArray &, int)
@param type The edit type to register the C++ type for
@param targetType The id of C++ type to be registered for the given edit type
Registeres the given type, so that whenever type is passed to safeCastInputType(), the given
variant will be converter to targetType
@sa CoreApp::safeCastInputType
*/
/*!
@fn QtMvvm::CoreApp::bootApp

125
doc/isettingsaccessor.dox

@ -0,0 +1,125 @@
/*!
@class QtMvvm::ISettingsAccessor
This class is used by the SettingsViewModel and the @ref settings_generator "qsettingsgenerator"
to access settings. The interface is meant to be used as proxy for some kind of settings
backend (like QSettings), so access is kept generic and you can decide to use a different
storage if needed. While this class can be used directly, it is dsigned to only be used
as backend for a settings viewmodel or a generated settings instance, and thus lacks many
"comfort" methods one would otherwise expect.
@note All the semantincs desribed below, except for the change signals, are exactly the same
as for QSettings, as this interface is modeled after QSettings, in other words, the same rules
for keys and values as for QSettings apply to the methods of this interface.
@section ISettingsAccessor_keys Semantics of keys
Keys follow the following semantics. All keys are of the format `group/subgroup/key`. Keys
may or may not be case sensitive, depending on the plattform. The best approach is to assume
keys are case insensitive when storing, but case sensitive when loading. While the keys are
seperated into groups and keys, all groups can also serve as keys, i.e. `group/subgroup` is a
valid key as well.
@section ISettingsAccessor_storing Storing data
You can assume that data passed to save() is serializable via QDataStream. In other words, to
convert the variant to binary data, you can simply use operator<< and operator>> of the
QVariant. Also, just like with QSettings, the saved data does not have to retain the type. The
only condition is, that whatever you load() for the same key as used for storing must be
convertible to the same type as the variant, that was passed to the save() method.
Finally, saving data via this method does not have to immediatly store it permanently. However,
calling load() with the same key right after save() must always return the same value as
passed to it. Permanent storing can be done asynchronously, but should happen automatically
without to much time passing after the save() (or remove()), and must always happen before
the destruction of this object. Furthermore, users can use the sync() method to immediatly store
data permanently and load all changes done externally.
@section ISettingsAccessor_signals Change signals
Another specialty of this class are the change signals. They must be emitted whenever save()
or remove() are called, to ensure at least changes done within the same instance trigger the
according change signals. Changes done externally should lead to change signals, but don't have
to, if not supported. For example, the DataSyncSettingsAccessor can indeed detect changes as
they occur on other instances or externally, and thus emits the signals. QSettings however does
not support change signals of any kind, and thus external changes do change the data that can
be loaded, but do not emit any signals.
@section ISettingsAccessor_impl Available implementations
Currently, the following backends are supported:
- QSettingsAccessor: Wraps QSettings
- DataSyncSettingsAccessor: Part of mvvm datasync core, allows to store and sync settings via datasync
- AndroidSettingsAccessor: Wraps the SharedPreferences of the android API
@sa #QtMvvm_ISettingsAccessorIID, QSettingsAccessor, DataSyncSettingsAccessor,
AndroidSettingsAccessor, SettingsViewModel, DataSyncSettingsViewModel, @ref settings_generator
*/
/*!
@fn QtMvvm::ISettingsAccessor::contains
@param key The key of the settings entry to be checked for existance
@returns true, if a value for that key was stored, false if not
This should only check for values, not for groups, i.e. if key referes to a group that has
child keys, but no value by itself, you should still return false.
@sa ISettingsAccessor::load
*/
/*!
@fn QtMvvm::ISettingsAccessor::load
@param key The key of the settings entry to be loaded
@param defaultValue A alternative value to be returned if there is no data stored for that key
@returns The data loaded for the key, or the default value
If the given value does exist, it should be loaded and returned. If the is on data stored for
that key, simply return whatever is passed as the default value.
@sa @ref ISettingsAccessor_storing, ISettingsAccessor::contains, ISettingsAccessor::save
*/
/*!
@fn QtMvvm::ISettingsAccessor::save
@param key The key of the settings entry to be saved
@param value The data to be stored under that key
Should simply store the passed data under the given key. You dont have to check if the variant
is actually serializable, as the meta system will automatically warn the user if thats not the
case. Permanent storing is done asynchronously, but can be forced via sync().
Any implementation of this method *must* emit the entryChanged() signal with the passed data and
key.
@sa @ref ISettingsAccessor_storing, ISettingsAccessor::entryChanged, ISettingsAccessor::load,
ISettingsAccessor::remove, ISettingsAccessor::sync
*/
/*!
@fn QtMvvm::ISettingsAccessor::remove
@param key The key of the settings entry to be removed
This method should remove the given key and all of its subkeys. If for example the settings
contained the values `group/subgroup` and `group/subgroup/key`, after this method, both must
have been removed. Permanent storing is done asynchronously, but can be forced via sync().
Any implementation of this method *must* emit the entryRemoved() signal for **all** the removed
entries. I.e. for the example above, it must be emitted for both, `group/subgroup` and
`group/subgroup/key`.
@sa @ref ISettingsAccessor_storing, ISettingsAccessor::entryRemoved, ISettingsAccessor::save,
ISettingsAccessor::sync
*/
/*!
@fn QtMvvm::ISettingsAccessor::sync
You can call this method to immediatly store any changed data to permanent store. This exists
because typically, calls to save() and remove() only "cache" the changes, and then later write
them to the permanent store in a single transaction, as this can be an expensive operation.
Normally, you don't have to care about this, as this happens automatically, but sometimes you
might want to manually perform this step. Thats what this method is for.
@sa ISettingsAccessor::save, ISettingsAccessor::remove, QSettings::sync
*/

1
src/mvvmcore/binding.h

@ -33,6 +33,7 @@ public:
//! Specifies whether the binding is a valid and active binding
bool isValid() const;
//! @copydoc Binding::isValid
operator bool() const;
//! Remove the binding by disconnecting all change signals

12
src/mvvmcore/coreapp.h

@ -37,21 +37,27 @@ public:
//! Show a new ViewModel by its type
template <typename TViewModel>
static inline void show(const QVariantHash &params = {}, QPointer<ViewModel> parentViewModel = nullptr);
//! Show a new ViewModel by its name
//! @copydoc CoreApp::show(const char *, const QVariantHash &, QPointer<ViewModel>);
static void show(const char *viewModelName, const QVariantHash &params = {}); //MAJOR merge methods
//! Show a new ViewModel by its name
static void show(const char *viewModelName, const QVariantHash &params, QPointer<ViewModel> parentViewModel);
//! Show a new ViewModel by its metaobject
//! @copydoc CoreApp::show(const QMetaObject *, const QVariantHash &, QPointer<ViewModel>);
static void show(const QMetaObject *viewModelMetaObject, const QVariantHash &params = {}); //MAJOR merge methods
//! Show a new ViewModel by its metaobject
static void show(const QMetaObject *viewModelMetaObject, const QVariantHash &params, QPointer<ViewModel> parentViewModel);
//! Show a basic dialog
static MessageResult *showDialog(const MessageConfig &config);
//! Safely casts a value of the given edit type to the corresponding variant type
static QVariant safeCastInputType(const QByteArray &type, const QVariant &value);
static void registerInputTypeMapping(const QByteArray &type, int targetType);
//! Register a type to be used as variant type for the given edit type
template <typename T>
static void registerInputTypeMapping(const QByteArray &type);
//! @copybrief CoreApp::registerInputTypeMapping(const QByteArray &)
static void registerInputTypeMapping(const QByteArray &type, int targetType);
//! Returns the currently used presenter
static IPresenter *presenter();
public Q_SLOTS:

15
src/mvvmcore/isettingsaccessor.h

@ -9,31 +9,42 @@
namespace QtMvvm {
//! An interface to provide a generic way to access settings of any origin
class Q_MVVMCORE_EXPORT ISettingsAccessor : public QObject
{
Q_OBJECT
Q_DISABLE_COPY(ISettingsAccessor)
public:
//! Constructor
ISettingsAccessor(QObject *parent = nullptr);
//! Checks if a value is stored for the given key
virtual bool contains(const QString &key) const = 0;
//! Loads the value for the given key from the settings
virtual QVariant load(const QString &key, const QVariant &defaultValue = {}) const = 0;
//! Stores the given value under the given key in the settings
virtual void save(const QString &key, const QVariant &value) = 0;
//! Removes the key and all its subkeys from the settings
virtual void remove(const QString &key) = 0;
public Q_SLOTS:
//! Synchronizes the settings to the disk or whatever is needed to permanently store them
virtual void sync() = 0;
Q_SIGNALS:
//! Is emitted whenever a settings value was changed, at least via this instance
void entryChanged(const QString &key, const QVariant &value);
//! Is emitted whenever a settings value was removed, at least via this instance
void entryRemoved(const QString &key);
};
}
#define ISettingsAccessorIid "de.skycoder42.qtmvvm.core.ISettingsAccessor"
Q_DECLARE_INTERFACE(QtMvvm::ISettingsAccessor, ISettingsAccessorIid)
//! The IID of the QtMvvm::IPresenter class
#define QtMvvm_ISettingsAccessorIID "de.skycoder42.qtmvvm.core.ISettingsAccessor"
Q_DECLARE_INTERFACE(QtMvvm::ISettingsAccessor, QtMvvm_ISettingsAccessorIID)
Q_DECLARE_METATYPE(QtMvvm::ISettingsAccessor*)
//! @file isettingsaccessor.h The ISettingsAccessor class header
#endif // QTMVVM_ISETTINGSACCESSOR_H

4
src/mvvmcore/mvvmcore.pro

@ -25,7 +25,7 @@ HEADERS += \
isettingsaccessor.h \
qsettingsaccessor.h \
settingsentry.h \
settingsconfigloader_p.h
settingsconfigloader_p.h
SOURCES += \
viewmodel.cpp \
@ -39,7 +39,7 @@ SOURCES += \
isettingsaccessor.cpp \
qsettingsaccessor.cpp \
settingsentry.cpp \
settingsconfigloader.cpp
settingsconfigloader.cpp
include(../settingsconfig/settingsconfig.pri)

7
src/mvvmdatasynccore/datasyncsettingsentry.cpp

@ -1,5 +1,6 @@
#include "datasyncsettingsentry.h"
#include <QtCore/QDataStream>
#include <QtMvvmCore/private/qtmvvm_logging_p.h>
#if QT_HAS_INCLUDE(<optional>) && __cplusplus >= 201703L
#include <optional>
#define QTMVVM_HAS_OPTIONAL
@ -65,14 +66,20 @@ QVariant DataSyncSettingsEntry::value() const
QDataStream stream{d->data};
stream.setVersion(d->version);
d->value = QVariant{};
stream.startTransaction();
stream >> d->value.value();
if(!stream.commitTransaction())
logWarning() << "Failed to read data of entry with key" << d->key;
}
return d->value.value_or(QVariant{});
#else
if(!d->data.isNull() && !d->value.isValid()) {
QDataStream stream{d->data};
stream.setVersion(d->version);
stream.startTransaction();
stream >> d->value;
if(!stream.commitTransaction())
logWarning() << "Failed to read data of entry with key" << d->key;
}
return d->value;
#endif

Loading…
Cancel
Save