device;
+ //TODO add support for android content device
+ if(url.isLocalFile())
+ device.reset(new QFile(url.toLocalFile()));
+ else {
+ critical(tr("Import failed"), tr("Unsupported URL Scheme: %1").arg(url.scheme()));
+ return;
+ }
+
+ if(!device->open(QIODevice::ReadOnly | QIODevice::Text)) {
+ critical(tr("Import failed"),
+ tr("Failed to open URL \"%1\" with error: %1")
+ .arg(url.toString())
+ .arg(device->errorString()));
+ return;
+ }
+ auto data = device->readAll();
+ device->close();
+
+ if(AccountManager::isTrustedImport(data)) {
+ MessageConfig config{MessageConfig::TypeInputDialog, QMetaType::typeName(QMetaType::QString)};
+ config.setTitle(tr("Import account data"))
+ .setText(tr("Enter the password to decrypt the account data. "
+ "Then choose whether you want to keep you local data or not:"))
+ .setButtons(MessageConfig::YesToAll | MessageConfig::Yes | MessageConfig::Cancel) //TODO adjust to get ideal placement
+ .setButtonText(MessageConfig::YesToAll, tr("Reset data"))
+ .setButtonText(MessageConfig::Yes, tr("Keep data"))
+ .setViewProperties({
+ {QStringLiteral("echoMode"), 2} //QLineEdit::Password
+ });
+ auto res = CoreApp::showDialog(config);
+ connect(res, &MessageResult::dialogDone, this, [this, res, data](MessageConfig::StandardButton btn) {
+ switch (btn) {
+ case MessageConfig::YesToAll:
+ d->performImport(true, res->result().toString(), data, false);
+ break;
+ case MessageConfig::Yes:
+ d->performImport(true, res->result().toString(), data, true);
+ break;
+ default:
+ break;
+ }
+ });
+ } else {
+ MessageConfig config{MessageConfig::TypeMessageBox, MessageConfig::SubTypeQuestion};
+ config.setTitle(tr("Import account data"))
+ .setText(tr("Keep the local data after changing the account?"))
+ .setButtons(MessageConfig::YesToAll | MessageConfig::Yes | MessageConfig::Cancel) //TODO adjust to get ideal placement
+ .setButtonText(MessageConfig::YesToAll, tr("Reset data"))
+ .setButtonText(MessageConfig::Yes, tr("Keep data"));
+ auto res = CoreApp::showDialog(config);
+ connect(res, &MessageResult::dialogDone, this, [this, res, data](MessageConfig::StandardButton btn) {
+ switch (btn) {
+ case MessageConfig::YesToAll:
+ d->performImport(false, {}, data, false);
+ break;
+ case MessageConfig::Yes:
+ d->performImport(false, {}, data, true);
+ break;
+ default:
+ break;
+ }
+ });
+ }
+ }
+ }, tr("Import account data"),
+ {QStringLiteral("application/x-datasync-account-data"), QStringLiteral("application/octet-stream")},
+ QUrl::fromLocalFile(home));
+}
+
+void DataSyncViewModel::performReset()
+{
+ MessageConfig config {MessageConfig::TypeMessageBox, MessageConfig::SubTypeQuestion};
+ config.setTitle(tr("Reset Account?"))
+ .setText(tr("Do you want to reset your account? "
+ "You will loose the connection to all other devices and get a new identity."
+ "You can either keep your data or reset it as well."
+ "This cannot be undone!"))
+ .setButtons(MessageConfig::YesToAll | MessageConfig::Yes | MessageConfig::Cancel) //TODO adjust to get ideal placement
+ .setButtonText(MessageConfig::YesToAll, tr("Reset data"))
+ .setButtonText(MessageConfig::Yes, tr("Keep data"));
+ auto res = CoreApp::showDialog(config);
+ connect(res, &MessageResult::dialogDone, this, [this](MessageConfig::StandardButton btn) {
+ switch (btn) {
+ case MessageConfig::YesToAll:
+ d->accountManager->resetAccount(false);
+ break;
+ case MessageConfig::Yes:
+ d->accountManager->resetAccount(true);
+ break;
+ default:
+ break;
+ }
+ });
+}
+
+void DataSyncViewModel::changeRemote()
+{
+ Q_UNIMPLEMENTED();
+}
+
+void DataSyncViewModel::startNetworkExchange()
+{
+ Q_UNIMPLEMENTED();
+}
+
+void DataSyncViewModel::setColorMap(DataSyncViewModel::ColorMap colorMap)
+{
+ if (d->colorMap == colorMap)
+ return;
+
+ d->colorMap = colorMap;
+ emit colorMapChanged(d->colorMap);
+}
+
+void DataSyncViewModel::resetColorMap()
+{
+ d->colorMap.clear();
+ d->colorMap.insert(SyncManager::Initializing, Qt::darkCyan);
+ d->colorMap.insert(SyncManager::Downloading, Qt::darkCyan);
+ d->colorMap.insert(SyncManager::Uploading, Qt::darkCyan);
+ d->colorMap.insert(SyncManager::Synchronized, Qt::darkGreen);
+ d->colorMap.insert(SyncManager::Error, Qt::darkRed);
+ d->colorMap.insert(SyncManager::Disconnected, Qt::darkYellow);
+ emit colorMapChanged(d->colorMap);
+}
+
+void DataSyncViewModel::showImportDialog(LoginRequest request)
+{
+ if(request.handled())
+ return;
+ question(tr("Login requested!"),
+ tr("A device wants to log into your account:
"
+ "Name: %1
"
+ "Fingerprint: %2
"
+ "Do you want accept the request?
")
+ .arg(request.device().name())
+ .arg(formatFingerPrint(request.device().fingerprint())),
+ this, [this, request](bool ok) {
+ auto req = request;
+ if(!req.handled()) {
+ if(ok)
+ req.accept();
+ else
+ req.reject();
+ }
+ });
+}
+
+void DataSyncViewModel::showImportAccepted()
+{
+ information(tr("Import accepted"),
+ tr("The partner has accepted the import. You are now logged in."));
+}
+
+void DataSyncViewModel::showAccessGranted(const QUuid &id)
+{
+ d->pendingGrants.insert(id);
+ //no need to call list devices, is done by the model
+}
+
+void DataSyncViewModel::triggerGranted(const QList &devices)
+{
+ for(auto device : devices) {
+ if(d->pendingGrants.remove(device.deviceId())) {
+ information(tr("Account access granted"),
+ tr("Account access has been granted to device:
"
+ "Name: %1
"
+ "Fingerprint: %2
")
+ .arg(device.name())
+ .arg(formatFingerPrint(device.fingerprint())));
+ }
+ }
+}
+
+void DataSyncViewModel::onInit(const QVariantHash ¶ms)
+{
+ try {
+ if(params.contains(paramReplicaNode)) {
+ auto node = params.value(paramReplicaNode).value();
+ d->syncManager = new SyncManager(node, this);
+ d->accountManager = new AccountManager(node, this);
+ } else {
+ auto setup = params.value(paramSetup, QtDataSync::DefaultSetup).toString();
+ d->syncManager = new SyncManager(setup, this);
+ d->accountManager = new AccountManager(setup, this);
+ }
+
+ //sync manager
+ connect(d->syncManager, &SyncManager::syncStateChanged,
+ this, &DataSyncViewModel::statusStringChanged);
+ connect(d->syncManager, &SyncManager::lastErrorChanged,
+ this, &DataSyncViewModel::statusStringChanged);
+
+ //account manager
+ connect(d->accountManager, &AccountManager::loginRequested,
+ this, &DataSyncViewModel::showImportDialog);
+ connect(d->accountManager, &AccountManager::importAccepted,
+ this, &DataSyncViewModel::showImportAccepted);
+ connect(d->accountManager, &AccountManager::accountAccessGranted,
+ this, &DataSyncViewModel::showAccessGranted);
+ connect(d->accountManager, &AccountManager::accountDevices,
+ this, &DataSyncViewModel::triggerGranted);
+ d->accountModel->setup(d->accountManager);
+
+ emit syncManagerChanged(d->syncManager);
+ emit accountManagerChanged(d->accountManager);
+ } catch(SetupDoesNotExistException &e) {
+ logCritical() << "Failed to init DataSyncViewModel with error:"
+ << e.what();
+ }
+}
+
+void DataSyncViewModel::onResult(quint32 requestCode, const QVariant &result)
+{
+ switch (requestCode) {
+ case DataSyncViewModelPrivate::ExportRequestCode:
+ if(result.isValid()) {
+ auto res = ExportSetupViewModel::result(result);
+ d->performExport(std::get<0>(res), std::get<1>(res), std::get<2>(res));
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+// ------------- Private Implementation -------------
+
+QtMvvm::DataSyncViewModelPrivate::DataSyncViewModelPrivate(DataSyncViewModel *q_ptr) :
+ q(q_ptr),
+ syncManager(nullptr),
+ accountManager(nullptr),
+ colorMap(),
+ accountModel(new AccountModel(q_ptr))
+{}
+
+void DataSyncViewModelPrivate::performExport(bool trusted, bool includeServer, const QString &password)
+{
+ auto home = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
+ getSaveFile(q, [this, trusted, includeServer, password](QUrl url) {
+ if(url.isValid()) {
+ QSharedPointer device;
+ //TODO add support for android content device
+ if(url.isLocalFile())
+ device.reset(new QFile(url.toLocalFile()));
+ else {
+ critical(DataSyncViewModel::tr("Export failed"),
+ DataSyncViewModel::tr("Unsupported URL Scheme: %1").arg(url.scheme()));
+ return;
+ }
+
+ if(!device->open(QIODevice::WriteOnly | QIODevice::Text)) {
+ critical(DataSyncViewModel::tr("Export failed"),
+ DataSyncViewModel::tr("Failed to open URL \"%1\" with error: %1")
+ .arg(url.toString())
+ .arg(device->errorString()));
+ return;
+ }
+
+ QPointer qPtr(q);
+ auto resFn = [this, qPtr, device](QByteArray data) {
+ if(!qPtr)
+ return;
+ device->write(data);
+ device->close();
+ information(DataSyncViewModel::tr("Export completed"),
+ DataSyncViewModel::tr("Data was successfully exported."));
+ };
+ auto errFn = [this, qPtr, device](QString error){
+ if(!qPtr)
+ return;
+ critical(DataSyncViewModel::tr("Export failed"), error);
+ };
+
+ if(trusted)
+ accountManager->exportAccountTrusted(includeServer, password, resFn, errFn);
+ else
+ accountManager->exportAccount(includeServer, resFn, errFn);
+ }
+ }, DataSyncViewModel::tr("Export account data"),
+ {QStringLiteral("application/x-datasync-account-data"), QStringLiteral("application/octet-stream")},
+ QUrl::fromLocalFile(home));
+}
+
+void DataSyncViewModelPrivate::performImport(bool trusted, const QString &password, const QByteArray &data, bool keepData)
+{
+ QPointer qPtr(q);
+ auto resFn = [this, qPtr](bool ok, QString error) {
+ if(!qPtr)
+ return;
+ if(ok) {
+ information(DataSyncViewModel::tr("Import completed"),
+ DataSyncViewModel::tr("Data was successfully imported."));
+ } else
+ critical(DataSyncViewModel::tr("Import failed"), error);
+ };
+
+ if(trusted)
+ accountManager->importAccountTrusted(data, password, resFn, keepData);
+ else
+ accountManager->importAccount(data, resFn, keepData);
+}
diff --git a/src/mvvmdatasynccore/datasyncviewmodel.h b/src/mvvmdatasynccore/datasyncviewmodel.h
new file mode 100644
index 0000000..8bd1651
--- /dev/null
+++ b/src/mvvmdatasynccore/datasyncviewmodel.h
@@ -0,0 +1,86 @@
+#ifndef QTMVVM_DATASYNCVIEWMODEL_H
+#define QTMVVM_DATASYNCVIEWMODEL_H
+
+#include
+#include
+
+#include
+
+#include
+
+#include
+#include
+
+#include "QtMvvmDataSyncCore/qtmvvmdatasynccore_global.h"
+#include "QtMvvmDataSyncCore/accountmodel.h"
+
+namespace QtMvvm {
+
+class DataSyncViewModelPrivate;
+class Q_MVVMDATASYNCCORE_EXPORT DataSyncViewModel : public ViewModel
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QtDataSync::SyncManager* syncManager READ syncManager NOTIFY syncManagerChanged)
+ Q_PROPERTY(QtDataSync::AccountManager* accountManager READ accountManager NOTIFY accountManagerChanged)
+
+ Q_PROPERTY(ColorMap colorMap READ colorMap WRITE setColorMap RESET resetColorMap NOTIFY colorMapChanged)
+ Q_PROPERTY(QString statusString READ statusString NOTIFY statusStringChanged)
+
+ Q_PROPERTY(QtMvvm::AccountModel* accountModel READ accountModel CONSTANT)
+
+public:
+ typedef QMap ColorMap;
+
+ static const QString paramSetup;
+ static const QString paramReplicaNode;
+
+ static QVariantHash showParams(const QString &setup);
+ static QVariantHash showParams(QRemoteObjectNode *node);
+
+ Q_INVOKABLE explicit DataSyncViewModel(QObject *parent = nullptr);
+ ~DataSyncViewModel();
+
+ QtDataSync::SyncManager* syncManager() const;
+ QtDataSync::AccountManager* accountManager() const;
+ ColorMap colorMap() const;
+ QString statusString() const;
+
+ AccountModel *accountModel() const;
+
+ Q_INVOKABLE static QString formatFingerPrint(const QByteArray &fingerPrint);
+
+public Q_SLOTS:
+ void showDeviceInfo();
+ void startExport();
+ void startImport();
+ void performReset();
+ void changeRemote();
+ void startNetworkExchange();
+
+ void setColorMap(ColorMap colorMap);
+ void resetColorMap();
+
+private Q_SLOTS:
+ void showImportDialog(QtDataSync::LoginRequest request);
+ void showImportAccepted();
+ void showAccessGranted(const QUuid &id);
+ void triggerGranted(const QList &devices);
+
+Q_SIGNALS:
+ void syncManagerChanged(QtDataSync::SyncManager* syncManager);
+ void accountManagerChanged(QtDataSync::AccountManager* accountManager);
+ void colorMapChanged(ColorMap colorMap);
+ void statusStringChanged();
+
+protected:
+ void onInit(const QVariantHash ¶ms) override;
+ void onResult(quint32 requestCode, const QVariant &result) override;
+
+private:
+ QScopedPointer d;
+};
+
+}
+
+#endif // QTMVVM_DATASYNCVIEWMODEL_H
diff --git a/src/mvvmdatasynccore/datasyncviewmodel_p.h b/src/mvvmdatasynccore/datasyncviewmodel_p.h
new file mode 100644
index 0000000..09dc792
--- /dev/null
+++ b/src/mvvmdatasynccore/datasyncviewmodel_p.h
@@ -0,0 +1,32 @@
+#ifndef QTMVVM_DATASYNCVIEWMODEL_P_H
+#define QTMVVM_DATASYNCVIEWMODEL_P_H
+
+#include
+
+#include "qtmvvmdatasynccore_global.h"
+#include "datasyncviewmodel.h"
+
+namespace QtMvvm {
+
+class DataSyncViewModelPrivate
+{
+public:
+ static const quint32 ExportRequestCode = 0xb201;
+
+ DataSyncViewModelPrivate(DataSyncViewModel *q_ptr);
+
+ DataSyncViewModel *q;
+ QtDataSync::SyncManager *syncManager;
+ QtDataSync::AccountManager *accountManager;
+ DataSyncViewModel::ColorMap colorMap;
+ AccountModel *accountModel;
+
+ QSet pendingGrants;
+
+ void performExport(bool trusted, bool includeServer, const QString &password);
+ void performImport(bool trusted, const QString &password, const QByteArray &data, bool keepData);
+};
+
+}
+
+#endif // QTMVVM_DATASYNCVIEWMODEL_P_H
diff --git a/src/mvvmdatasynccore/exportsetupviewmodel.cpp b/src/mvvmdatasynccore/exportsetupviewmodel.cpp
new file mode 100644
index 0000000..7e877e0
--- /dev/null
+++ b/src/mvvmdatasynccore/exportsetupviewmodel.cpp
@@ -0,0 +1,82 @@
+#include "exportsetupviewmodel_p.h"
+using namespace QtMvvm;
+
+std::tuple ExportSetupViewModel::result(const QVariant &data)
+{
+ auto map = data.toHash();
+ return std::make_tuple(map.value(QStringLiteral("trusted")).toBool(),
+ map.value(QStringLiteral("includeServer")).toBool(),
+ map.value(QStringLiteral("password")).toString());
+}
+
+ExportSetupViewModel::ExportSetupViewModel(QObject *parent) :
+ ViewModel(parent),
+ _trusted(false),
+ _includeServer(false),
+ _password()
+{
+ connect(this, &ExportSetupViewModel::trustedChanged,
+ this, &ExportSetupViewModel::validChanged);
+ connect(this, &ExportSetupViewModel::passwordChanged,
+ this, &ExportSetupViewModel::validChanged);
+}
+
+bool ExportSetupViewModel::trusted() const
+{
+ return _trusted;
+}
+
+bool ExportSetupViewModel::includeServer() const
+{
+ return _includeServer;
+}
+
+QString ExportSetupViewModel::password() const
+{
+ return _password;
+}
+
+bool ExportSetupViewModel::isValid() const
+{
+ return !_trusted || !_password.isEmpty();
+}
+
+bool ExportSetupViewModel::completeSetup()
+{
+ if(!isValid())
+ return false;
+
+ QVariantHash hash;
+ hash[QStringLiteral("trusted")] = _trusted;
+ hash[QStringLiteral("includeServer")] = _includeServer;
+ hash[QStringLiteral("password")] = _trusted ? _password : QString();
+ emit resultReady(hash);
+ return true;
+}
+
+void ExportSetupViewModel::setTrusted(bool trusted)
+{
+ if (_trusted == trusted)
+ return;
+
+ _trusted = trusted;
+ emit trustedChanged(_trusted);
+}
+
+void ExportSetupViewModel::setIncludeServer(bool includeServer)
+{
+ if (_includeServer == includeServer)
+ return;
+
+ _includeServer = includeServer;
+ emit includeServerChanged(_includeServer);
+}
+
+void ExportSetupViewModel::setPassword(QString password)
+{
+ if (_password == password)
+ return;
+
+ _password = password;
+ emit passwordChanged(_password);
+}
diff --git a/src/mvvmdatasynccore/exportsetupviewmodel_p.h b/src/mvvmdatasynccore/exportsetupviewmodel_p.h
new file mode 100644
index 0000000..500753e
--- /dev/null
+++ b/src/mvvmdatasynccore/exportsetupviewmodel_p.h
@@ -0,0 +1,53 @@
+#ifndef QTMVVM_EXPORTSETUPVIEWMODEL_P_H
+#define QTMVVM_EXPORTSETUPVIEWMODEL_P_H
+
+#include
+
+#include
+
+#include "qtmvvmdatasynccore_global.h"
+
+namespace QtMvvm {
+
+class Q_MVVMDATASYNCCORE_EXPORT ExportSetupViewModel : public ViewModel
+{
+ Q_OBJECT
+
+ Q_PROPERTY(bool trusted READ trusted WRITE setTrusted NOTIFY trustedChanged)
+ Q_PROPERTY(bool includeServer READ includeServer WRITE setIncludeServer NOTIFY includeServerChanged)
+ Q_PROPERTY(QString password READ password WRITE setPassword NOTIFY passwordChanged)
+
+ Q_PROPERTY(bool valid READ isValid NOTIFY validChanged)
+
+public:
+ static std::tuple result(const QVariant &data);
+
+ Q_INVOKABLE explicit ExportSetupViewModel(QObject *parent = nullptr);
+
+ bool trusted() const;
+ bool includeServer() const;
+ QString password() const;
+ bool isValid() const;
+
+public Q_SLOTS:
+ bool completeSetup();
+
+ void setTrusted(bool trusted);
+ void setIncludeServer(bool includeServer);
+ void setPassword(QString password);
+
+Q_SIGNALS:
+ void trustedChanged(bool trusted);
+ void includeServerChanged(bool includeServer);
+ void passwordChanged(QString password);
+ void validChanged();
+
+private:
+ bool _trusted;
+ QString _password;
+ bool _includeServer;
+};
+
+}
+
+#endif // QTMVVM_EXPORTSETUPVIEWMODEL_P_H
diff --git a/src/mvvmdatasynccore/mvvmdatasynccore.pro b/src/mvvmdatasynccore/mvvmdatasynccore.pro
new file mode 100644
index 0000000..097f5a3
--- /dev/null
+++ b/src/mvvmdatasynccore/mvvmdatasynccore.pro
@@ -0,0 +1,43 @@
+TARGET = QtMvvmDataSyncCore
+
+QT = core gui mvvmcore datasync mvvmcore-private
+
+HEADERS += \
+ qtmvvmdatasynccore_global.h \
+ datasyncviewmodel.h \
+ datasyncviewmodel_p.h \
+ accountmodel.h \
+ accountmodel_p.h \
+ exportsetupviewmodel_p.h
+
+SOURCES += \
+ datasyncviewmodel.cpp \
+ accountmodel.cpp \
+ exportsetupviewmodel.cpp
+
+TRANSLATIONS += \
+ translations/qtmvvmdatasynccore_de.ts \
+ translations/qtmvvmdatasynccore_template.ts
+
+DISTFILES += $$TRANSLATIONS \
+ application-x-datasync-account-data.xml
+
+qpmx_ts_target.path = $$[QT_INSTALL_TRANSLATIONS]
+qpmx_ts_target.depends += lrelease
+
+load(qt_module)
+
+win32 {
+ QMAKE_TARGET_PRODUCT = "$$TARGET"
+ QMAKE_TARGET_COMPANY = "Skycoder42"
+ QMAKE_TARGET_COPYRIGHT = "Felix Barz"
+} else:mac {
+ QMAKE_TARGET_BUNDLE_PREFIX = "com.skycoder42."
+}
+
+!ReleaseBuild:!DebugBuild:!system(qpmx -d $$shell_quote($$_PRO_FILE_PWD_) --qmake-run init $$QPMX_EXTRA_OPTIONS $$shell_quote($$QMAKE_QMAKE) $$shell_quote($$OUT_PWD)): error(qpmx initialization failed. Check the compilation log for details.)
+else: include($$OUT_PWD/qpmx_generated.pri)
+
+qpmx_ts_target.files -= $$OUT_PWD/$$QPMX_WORKINGDIR/qtmvvmdatasynccore_template.qm
+qpmx_ts_target.files += translations/qtmvvmdatasynccore_template.ts
+
diff --git a/src/mvvmdatasynccore/qpmx.json b/src/mvvmdatasynccore/qpmx.json
new file mode 100644
index 0000000..461fe91
--- /dev/null
+++ b/src/mvvmdatasynccore/qpmx.json
@@ -0,0 +1,14 @@
+{
+ "dependencies": [],
+ "license": {
+ "file": "",
+ "name": ""
+ },
+ "prcFile": "",
+ "priFile": "",
+ "priIncludes": [
+ ],
+ "publishers": {
+ },
+ "source": false
+}
diff --git a/src/mvvmdatasynccore/qtmvvmdatasynccore_global.h b/src/mvvmdatasynccore/qtmvvmdatasynccore_global.h
new file mode 100644
index 0000000..55867c8
--- /dev/null
+++ b/src/mvvmdatasynccore/qtmvvmdatasynccore_global.h
@@ -0,0 +1,12 @@
+#ifndef QTMVVMDATASYNCCORE_GLOBAL_H
+#define QTMVVMDATASYNCCORE_GLOBAL_H
+
+#include
+
+#if defined(QT_BUILD_MVVMDATASYNCCORE_LIB)
+# define Q_MVVMDATASYNCCORE_EXPORT Q_DECL_EXPORT
+#else
+# define Q_MVVMDATASYNCCORE_EXPORT Q_DECL_IMPORT
+#endif
+
+#endif // QTMVVMDATASYNCCORE_GLOBAL_H
diff --git a/src/mvvmdatasynccore/translations/qtmvvmdatasynccore_de.ts b/src/mvvmdatasynccore/translations/qtmvvmdatasynccore_de.ts
new file mode 100644
index 0000000..1552582
--- /dev/null
+++ b/src/mvvmdatasynccore/translations/qtmvvmdatasynccore_de.ts
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/src/mvvmdatasynccore/translations/qtmvvmdatasynccore_template.ts b/src/mvvmdatasynccore/translations/qtmvvmdatasynccore_template.ts
new file mode 100644
index 0000000..6401616
--- /dev/null
+++ b/src/mvvmdatasynccore/translations/qtmvvmdatasynccore_template.ts
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/src/mvvmquick/quickpresenter.cpp b/src/mvvmquick/quickpresenter.cpp
index 1c75749..846e3c0 100644
--- a/src/mvvmquick/quickpresenter.cpp
+++ b/src/mvvmquick/quickpresenter.cpp
@@ -64,7 +64,7 @@ void QuickPresenter::present(QtMvvm::ViewModel *viewModel, const QVariantHash &p
Q_ARG(QtMvvm::ViewModel*, viewModel),
Q_ARG(QVariantHash, params),
Q_ARG(QUrl, url),
- Q_ARG(QPointer, parent));
+ Q_ARG(QPointer, parent)); //TODO invoke with result?
} else
throw PresenterException("QML presenter not ready - cannot present yet");
}
@@ -74,7 +74,7 @@ void QuickPresenter::showDialog(const QtMvvm::MessageConfig &config, QtMvvm::Mes
if(d->qmlPresenter) {
QMetaObject::invokeMethod(d->qmlPresenter, "showDialog",
Q_ARG(QtMvvm::MessageConfig, config),
- Q_ARG(QtMvvm::MessageResult*, result));
+ Q_ARG(QtMvvm::MessageResult*, result)); //TODO invoke with result?
} else
throw PresenterException("QML presenter not ready - cannot present yet");
}
diff --git a/src/mvvmwidgets/inputwidgetfactory.cpp b/src/mvvmwidgets/inputwidgetfactory.cpp
index 8ef4a6d..b9e20a8 100644
--- a/src/mvvmwidgets/inputwidgetfactory.cpp
+++ b/src/mvvmwidgets/inputwidgetfactory.cpp
@@ -66,7 +66,7 @@ QWidget *InputWidgetFactory::createInput(const QByteArray &type, QWidget *parent
widget = new SelectComboBox(parent);
else {
logCritical() << "Failed to find any input view for input type:" << type;
- return nullptr;
+ return nullptr; //TODO throw?
}
for(auto it = viewProperties.constBegin(); it != viewProperties.constEnd(); it++)
diff --git a/src/mvvmwidgets/widgetspresenter.cpp b/src/mvvmwidgets/widgetspresenter.cpp
index 348d0a9..59d3263 100644
--- a/src/mvvmwidgets/widgetspresenter.cpp
+++ b/src/mvvmwidgets/widgetspresenter.cpp
@@ -288,8 +288,10 @@ void WidgetsPresenter::presentMessageBox(const MessageConfig &config, QPointer result)
{
auto input = d->inputViewFactory->createInput(config.subType(), nullptr, config.viewProperties());
- if(!input)
- return;
+ if(!input) {
+ throw PresenterException(QByteArrayLiteral("Unable to find an input for type") +
+ config.subType());
+ }
QWidget *parent = nullptr;
if(!config.viewProperties().value(QStringLiteral("modal"), false).toBool())
diff --git a/src/src.pro b/src/src.pro
index e4a4ccb..ed84261 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -6,5 +6,9 @@ SUBDIRS += mvvmcore \
mvvmquick \
imports
+qtHaveModule(datasync) {
+ SUBDIRS += mvvmdatasynccore
+}
+
prepareRecursiveTarget(lrelease)
QMAKE_EXTRA_TARGETS += lrelease
diff --git a/sync.profile b/sync.profile
index e062f8d..caa885d 100644
--- a/sync.profile
+++ b/sync.profile
@@ -1,7 +1,8 @@
%modules = (
"QtMvvmCore" => "$basedir/src/mvvmcore",
"QtMvvmWidgets" => "$basedir/src/mvvmwidgets",
- "QtMvvmQuick" => "$basedir/src/mvvmquick"
+ "QtMvvmQuick" => "$basedir/src/mvvmquick",
+ "QtMvvmDataSyncCore" => "$basedir/src/mvvmdatasynccore"
);
# Force generation of camel case headers for classes inside QtDataSync namespaces