24 changed files with 1286 additions and 50 deletions
			
			
		@ -0,0 +1,244 @@ | 
				
			|||
<?xml version="1.0" encoding="utf-8"?> | 
				
			|||
<!DOCTYPE TS> | 
				
			|||
<TS version="2.1" language="de_DE"> | 
				
			|||
<context> | 
				
			|||
    <name>DrawerViewModel</name> | 
				
			|||
    <message> | 
				
			|||
        <location filename="drawerviewmodel.cpp" line="+11"/> | 
				
			|||
        <source>Main Sample</source> | 
				
			|||
        <translation type="unfinished"></translation> | 
				
			|||
    </message> | 
				
			|||
    <message> | 
				
			|||
        <location line="+1"/> | 
				
			|||
        <source>Tab Sample</source> | 
				
			|||
        <translation type="unfinished"></translation> | 
				
			|||
    </message> | 
				
			|||
    <message> | 
				
			|||
        <location line="+1"/> | 
				
			|||
        <source>Settings</source> | 
				
			|||
        <translation type="unfinished"></translation> | 
				
			|||
    </message> | 
				
			|||
</context> | 
				
			|||
<context> | 
				
			|||
    <name>SampleViewModel</name> | 
				
			|||
    <message> | 
				
			|||
        <location filename="sampleviewmodel.cpp" line="+81"/> | 
				
			|||
        <source>Random input</source> | 
				
			|||
        <translation type="unfinished"></translation> | 
				
			|||
    </message> | 
				
			|||
    <message> | 
				
			|||
        <location line="+1"/> | 
				
			|||
        <source>Enter a number:</source> | 
				
			|||
        <translation type="unfinished"></translation> | 
				
			|||
    </message> | 
				
			|||
    <message> | 
				
			|||
        <location line="+12"/> | 
				
			|||
        <source>Open Files:</source> | 
				
			|||
        <translation type="unfinished"></translation> | 
				
			|||
    </message> | 
				
			|||
    <message> | 
				
			|||
        <location line="+12"/> | 
				
			|||
        <source>Clear Eventlist</source> | 
				
			|||
        <translation type="unfinished"></translation> | 
				
			|||
    </message> | 
				
			|||
    <message> | 
				
			|||
        <location line="+1"/> | 
				
			|||
        <source>Do you really want to clear the eventlist?</source> | 
				
			|||
        <translation type="unfinished"></translation> | 
				
			|||
    </message> | 
				
			|||
    <message> | 
				
			|||
        <location line="+9"/> | 
				
			|||
        <source>QtMvvm sample application</source> | 
				
			|||
        <translation type="unfinished"></translation> | 
				
			|||
    </message> | 
				
			|||
    <message> | 
				
			|||
        <location line="+2"/> | 
				
			|||
        <source>BSD 3 Clause</source> | 
				
			|||
        <translation type="unfinished"></translation> | 
				
			|||
    </message> | 
				
			|||
</context> | 
				
			|||
<context> | 
				
			|||
    <name>TabItemViewModel</name> | 
				
			|||
    <message> | 
				
			|||
        <location filename="tabviewmodel.cpp" line="+28"/> | 
				
			|||
        <source>No Title</source> | 
				
			|||
        <translation type="unfinished"></translation> | 
				
			|||
    </message> | 
				
			|||
</context> | 
				
			|||
<context> | 
				
			|||
    <name>TabViewModel</name> | 
				
			|||
    <message> | 
				
			|||
        <location line="-13"/> | 
				
			|||
        <source>New Tab</source> | 
				
			|||
        <translation type="unfinished"></translation> | 
				
			|||
    </message> | 
				
			|||
    <message> | 
				
			|||
        <location line="+0"/> | 
				
			|||
        <source>Enter a tab title:</source> | 
				
			|||
        <translation type="unfinished"></translation> | 
				
			|||
    </message> | 
				
			|||
</context> | 
				
			|||
<context> | 
				
			|||
    <name>qtmvvm_settings_xml</name> | 
				
			|||
    <message> | 
				
			|||
        <location filename=".ts-dummy/settings.tsdummy.cpp" line="+4"/> | 
				
			|||
        <source>property</source> | 
				
			|||
        <translation type="unfinished"></translation> | 
				
			|||
    </message> | 
				
			|||
    <message> | 
				
			|||
        <location line="+1"/> | 
				
			|||
        <source>Text 1</source> | 
				
			|||
        <translation type="unfinished"></translation> | 
				
			|||
    </message> | 
				
			|||
    <message> | 
				
			|||
        <location line="+1"/> | 
				
			|||
        <source>Value C</source> | 
				
			|||
        <translation type="unfinished"></translation> | 
				
			|||
    </message> | 
				
			|||
    <message> | 
				
			|||
        <location line="+1"/> | 
				
			|||
        <source>Value A</source> | 
				
			|||
        <translation type="unfinished"></translation> | 
				
			|||
    </message> | 
				
			|||
    <message> | 
				
			|||
        <location line="+1"/> | 
				
			|||
        <source>Another Section</source> | 
				
			|||
        <translation type="unfinished"></translation> | 
				
			|||
    </message> | 
				
			|||
    <message> | 
				
			|||
        <location line="+1"/> | 
				
			|||
        <source>Value B</source> | 
				
			|||
        <translation type="unfinished"></translation> | 
				
			|||
    </message> | 
				
			|||
    <message> | 
				
			|||
        <location line="+1"/> | 
				
			|||
        <source>Enter a nice name</source> | 
				
			|||
        <translation type="unfinished"></translation> | 
				
			|||
    </message> | 
				
			|||
    <message> | 
				
			|||
        <location line="+1"/> | 
				
			|||
        <source>Value B+C</source> | 
				
			|||
        <translation type="unfinished"></translation> | 
				
			|||
    </message> | 
				
			|||
    <message> | 
				
			|||
        <location line="+1"/> | 
				
			|||
        <source>Variant A</source> | 
				
			|||
        <translation type="unfinished"></translation> | 
				
			|||
    </message> | 
				
			|||
    <message> | 
				
			|||
        <location line="+1"/> | 
				
			|||
        <source>This is a tooltip</source> | 
				
			|||
        <translation type="unfinished"></translation> | 
				
			|||
    </message> | 
				
			|||
    <message> | 
				
			|||
        <location line="+1"/> | 
				
			|||
        <source>Variant C</source> | 
				
			|||
        <translation type="unfinished"></translation> | 
				
			|||
    </message> | 
				
			|||
    <message> | 
				
			|||
        <location line="+1"/> | 
				
			|||
        <source>Value A+B</source> | 
				
			|||
        <translation type="unfinished"></translation> | 
				
			|||
    </message> | 
				
			|||
    <message> | 
				
			|||
        <location line="+1"/> | 
				
			|||
        <source>Sub-Group</source> | 
				
			|||
        <translation type="unfinished"></translation> | 
				
			|||
    </message> | 
				
			|||
    <message> | 
				
			|||
        <location line="+1"/> | 
				
			|||
        <source>&Check me</source> | 
				
			|||
        <translation type="unfinished"></translation> | 
				
			|||
    </message> | 
				
			|||
    <message> | 
				
			|||
        <location line="+1"/> | 
				
			|||
        <source>Enter a &value</source> | 
				
			|||
        <translation type="unfinished"></translation> | 
				
			|||
    </message> | 
				
			|||
    <message> | 
				
			|||
        <location line="+1"/> | 
				
			|||
        <source>The value must be between 0 and 1</source> | 
				
			|||
        <translation type="unfinished"></translation> | 
				
			|||
    </message> | 
				
			|||
    <message> | 
				
			|||
        <location line="+1"/> | 
				
			|||
        <source>Open &system settings</source> | 
				
			|||
        <translation type="unfinished"></translation> | 
				
			|||
    </message> | 
				
			|||
    <message> | 
				
			|||
        <location line="+1"/> | 
				
			|||
        <source>Another main category</source> | 
				
			|||
        <translation type="unfinished"></translation> | 
				
			|||
    </message> | 
				
			|||
    <message> | 
				
			|||
        <location line="+1"/> | 
				
			|||
        <source>Value A+C</source> | 
				
			|||
        <translation type="unfinished"></translation> | 
				
			|||
    </message> | 
				
			|||
    <message> | 
				
			|||
        <location line="+1"/> | 
				
			|||
        <source>Variant B</source> | 
				
			|||
        <translation type="unfinished"></translation> | 
				
			|||
    </message> | 
				
			|||
    <message> | 
				
			|||
        <location line="+1"/> | 
				
			|||
        <source>Choose a &font</source> | 
				
			|||
        <translation type="unfinished"></translation> | 
				
			|||
    </message> | 
				
			|||
    <message> | 
				
			|||
        <location line="+1"/> | 
				
			|||
        <source>This is another section</source> | 
				
			|||
        <translation type="unfinished"></translation> | 
				
			|||
    </message> | 
				
			|||
    <message> | 
				
			|||
        <location line="+1"/> | 
				
			|||
        <source>bool</source> | 
				
			|||
        <translation type="unfinished"></translation> | 
				
			|||
    </message> | 
				
			|||
    <message> | 
				
			|||
        <location line="+1"/> | 
				
			|||
        <source>Select a &mode</source> | 
				
			|||
        <translation type="unfinished"></translation> | 
				
			|||
    </message> | 
				
			|||
    <message> | 
				
			|||
        <location line="+1"/> | 
				
			|||
        <source>I am a checkbox!</source> | 
				
			|||
        <translation type="unfinished"></translation> | 
				
			|||
    </message> | 
				
			|||
    <message> | 
				
			|||
        <location line="+1"/> | 
				
			|||
        <source>Value A+B+C</source> | 
				
			|||
        <translation type="unfinished"></translation> | 
				
			|||
    </message> | 
				
			|||
    <message> | 
				
			|||
        <location line="+1"/> | 
				
			|||
        <source>Enter a &number</source> | 
				
			|||
        <translation type="unfinished"></translation> | 
				
			|||
    </message> | 
				
			|||
    <message> | 
				
			|||
        <location line="+1"/> | 
				
			|||
        <source>You can use this to trigger whatever kind of action you need</source> | 
				
			|||
        <translation type="unfinished"></translation> | 
				
			|||
    </message> | 
				
			|||
    <message> | 
				
			|||
        <location line="+1"/> | 
				
			|||
        <source>Text 2</source> | 
				
			|||
        <translation type="unfinished"></translation> | 
				
			|||
    </message> | 
				
			|||
    <message> | 
				
			|||
        <location line="+1"/> | 
				
			|||
        <source>Enter a &website</source> | 
				
			|||
        <translation type="unfinished"></translation> | 
				
			|||
    </message> | 
				
			|||
    <message> | 
				
			|||
        <location line="+1"/> | 
				
			|||
        <source>Enter a &name</source> | 
				
			|||
        <translation type="unfinished"></translation> | 
				
			|||
    </message> | 
				
			|||
    <message> | 
				
			|||
        <location line="+1"/> | 
				
			|||
        <source>https://example.org/test</source>
 | 
				
			|||
        <translation type="unfinished"></translation> | 
				
			|||
    </message> | 
				
			|||
</context> | 
				
			|||
</TS> | 
				
			|||
@ -0,0 +1,131 @@ | 
				
			|||
#include "accountmodel.h" | 
				
			|||
#include "accountmodel_p.h" | 
				
			|||
 | 
				
			|||
#include <QRemoteObjectReplica> | 
				
			|||
 | 
				
			|||
using namespace QtMvvm; | 
				
			|||
using namespace QtDataSync; | 
				
			|||
 | 
				
			|||
AccountModel::AccountModel(QObject *parent) : | 
				
			|||
	QAbstractListModel(parent), | 
				
			|||
	d(new AccountModelPrivate()) | 
				
			|||
{} | 
				
			|||
 | 
				
			|||
AccountModel::~AccountModel() {} | 
				
			|||
 | 
				
			|||
void AccountModel::setup(AccountManager *manager) | 
				
			|||
{ | 
				
			|||
	beginResetModel(); | 
				
			|||
	d->devices.clear(); | 
				
			|||
	if(d->manager) | 
				
			|||
		d->manager->disconnect(this); | 
				
			|||
	d->manager = manager; | 
				
			|||
	endResetModel(); | 
				
			|||
 | 
				
			|||
	connect(d->manager, &AccountManager::accountDevices, | 
				
			|||
			this, &AccountModel::accountDevices); | 
				
			|||
	connect(d->manager, &AccountManager::importAccepted, | 
				
			|||
			this, &AccountModel::reload); | 
				
			|||
	connect(d->manager, &AccountManager::accountAccessGranted, | 
				
			|||
			this, &AccountModel::reload); | 
				
			|||
 | 
				
			|||
	if(d->manager->replica()->isInitialized()) | 
				
			|||
		d->manager->listDevices(); | 
				
			|||
	else { | 
				
			|||
		connect(d->manager->replica(), &QRemoteObjectReplica::initialized, | 
				
			|||
				d->manager, &AccountManager::listDevices); | 
				
			|||
	} | 
				
			|||
 | 
				
			|||
} | 
				
			|||
 | 
				
			|||
QVariant AccountModel::headerData(int section, Qt::Orientation orientation, int role) const | 
				
			|||
{ | 
				
			|||
	if(orientation != Qt::Horizontal) | 
				
			|||
		return {}; | 
				
			|||
 | 
				
			|||
	switch (section) { | 
				
			|||
	case 0: | 
				
			|||
		switch(role) { | 
				
			|||
		case NameRole: | 
				
			|||
			return tr("Name"); | 
				
			|||
		case FingerPrintRole: | 
				
			|||
			return tr("Fingerprint"); | 
				
			|||
		default: | 
				
			|||
			break; | 
				
			|||
		} | 
				
			|||
		break; | 
				
			|||
	case 1: | 
				
			|||
		if(role == Qt::DisplayRole) | 
				
			|||
			return tr("Fingerprint"); | 
				
			|||
		break; | 
				
			|||
	default: | 
				
			|||
		break; | 
				
			|||
	} | 
				
			|||
 | 
				
			|||
	return {}; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
int AccountModel::rowCount(const QModelIndex &parent) const | 
				
			|||
{ | 
				
			|||
	if (parent.isValid()) | 
				
			|||
		return 0; | 
				
			|||
	else | 
				
			|||
		return d->devices.size(); | 
				
			|||
} | 
				
			|||
 | 
				
			|||
QVariant AccountModel::data(const QModelIndex &index, int role) const | 
				
			|||
{ | 
				
			|||
	if (!index.isValid()) | 
				
			|||
		return QVariant(); | 
				
			|||
 | 
				
			|||
	switch (index.column()) { | 
				
			|||
	case 0: | 
				
			|||
		switch(role) { | 
				
			|||
		case NameRole: | 
				
			|||
			return d->devices.value(index.row()).name(); | 
				
			|||
		case FingerPrintRole: | 
				
			|||
			return d->devices.value(index.row()).fingerprint(); | 
				
			|||
		default: | 
				
			|||
			break; | 
				
			|||
		} | 
				
			|||
		break; | 
				
			|||
	case 1: | 
				
			|||
		if(role == Qt::DisplayRole) | 
				
			|||
			return d->devices.value(index.row()).fingerprint(); | 
				
			|||
		break; | 
				
			|||
	default: | 
				
			|||
		break; | 
				
			|||
	} | 
				
			|||
 | 
				
			|||
	return {}; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
bool AccountModel::removeDevice(const QModelIndex &index) | 
				
			|||
{ | 
				
			|||
	if (!index.isValid()) | 
				
			|||
		return false; | 
				
			|||
	else { | 
				
			|||
		d->manager->removeDevice(d->devices.value(index.row())); | 
				
			|||
		return true; | 
				
			|||
	} | 
				
			|||
} | 
				
			|||
 | 
				
			|||
void AccountModel::reload() | 
				
			|||
{ | 
				
			|||
	if(d->manager) | 
				
			|||
		d->manager->listDevices(); | 
				
			|||
} | 
				
			|||
 | 
				
			|||
void AccountModel::accountDevices(const QList<DeviceInfo> &devices) | 
				
			|||
{ | 
				
			|||
	beginResetModel(); | 
				
			|||
	d->devices = devices; | 
				
			|||
	endResetModel(); | 
				
			|||
} | 
				
			|||
 | 
				
			|||
// ------------- Private Implementation -------------
 | 
				
			|||
 | 
				
			|||
AccountModelPrivate::AccountModelPrivate() : | 
				
			|||
	manager(nullptr), | 
				
			|||
	devices() | 
				
			|||
{} | 
				
			|||
@ -0,0 +1,51 @@ | 
				
			|||
#ifndef QTMVVM_ACCOUNTMODEL_H | 
				
			|||
#define QTMVVM_ACCOUNTMODEL_H | 
				
			|||
 | 
				
			|||
#include <QtCore/qabstractitemmodel.h> | 
				
			|||
#include <QtCore/qscopedpointer.h> | 
				
			|||
 | 
				
			|||
#include <QtDataSync/accountmanager.h> | 
				
			|||
 | 
				
			|||
#include "QtMvvmDataSyncCore/qtmvvmdatasynccore_global.h" | 
				
			|||
 | 
				
			|||
namespace QtMvvm { | 
				
			|||
 | 
				
			|||
class AccountModelPrivate; | 
				
			|||
class Q_MVVMDATASYNCCORE_EXPORT AccountModel : public QAbstractListModel | 
				
			|||
{ | 
				
			|||
	Q_OBJECT | 
				
			|||
 | 
				
			|||
public: | 
				
			|||
	enum Roles { | 
				
			|||
		NameRole = Qt::DisplayRole, | 
				
			|||
		FingerPrintRole = Qt::UserRole + 1 | 
				
			|||
	}; | 
				
			|||
	Q_ENUM(Roles) | 
				
			|||
 | 
				
			|||
	explicit AccountModel(QObject *parent = nullptr); | 
				
			|||
	~AccountModel(); | 
				
			|||
 | 
				
			|||
	Q_INVOKABLE void setup(QtDataSync::AccountManager *manager); | 
				
			|||
 | 
				
			|||
	QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; | 
				
			|||
	int rowCount(const QModelIndex &parent = QModelIndex()) const override; | 
				
			|||
	QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; | 
				
			|||
 | 
				
			|||
	Q_INVOKABLE bool removeDevice(const QModelIndex &index); | 
				
			|||
	Q_INVOKABLE inline bool removeDevice(int row) { | 
				
			|||
		return removeDevice(index(row)); | 
				
			|||
	} | 
				
			|||
 | 
				
			|||
public Q_SLOTS: | 
				
			|||
	void reload(); | 
				
			|||
 | 
				
			|||
private Q_SLOTS: | 
				
			|||
	void accountDevices(const QList<QtDataSync::DeviceInfo> &devices); | 
				
			|||
 | 
				
			|||
private: | 
				
			|||
	QScopedPointer<AccountModelPrivate> d; | 
				
			|||
}; | 
				
			|||
 | 
				
			|||
} | 
				
			|||
 | 
				
			|||
#endif // QTMVVM_ACCOUNTMODEL_H
 | 
				
			|||
@ -0,0 +1,20 @@ | 
				
			|||
#ifndef QTMVVM_ACCOUNTMODEL_P_H | 
				
			|||
#define QTMVVM_ACCOUNTMODEL_P_H | 
				
			|||
 | 
				
			|||
#include "qtmvvmdatasynccore_global.h" | 
				
			|||
#include "accountmodel.h" | 
				
			|||
 | 
				
			|||
namespace QtMvvm { | 
				
			|||
 | 
				
			|||
class AccountModelPrivate | 
				
			|||
{ | 
				
			|||
public: | 
				
			|||
	AccountModelPrivate(); | 
				
			|||
 | 
				
			|||
	QtDataSync::AccountManager *manager; | 
				
			|||
	QList<QtDataSync::DeviceInfo> devices; | 
				
			|||
}; | 
				
			|||
 | 
				
			|||
} | 
				
			|||
 | 
				
			|||
#endif // QTMVVM_ACCOUNTMODEL_P_H
 | 
				
			|||
@ -0,0 +1,11 @@ | 
				
			|||
<?xml version="1.0" encoding="UTF-8"?> | 
				
			|||
<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info"> | 
				
			|||
	<mime-type type="application/x-datasync-account-data"> | 
				
			|||
		<comment>Account data of a datasync account as file export</comment> | 
				
			|||
		<comment xml:lang="en">Account data of a datasync account as file export</comment> | 
				
			|||
		<comment xml:lang="de">Account-Daten eines Datasync-Accounts als Dateiexport</comment> | 
				
			|||
		<icon name="x-datasync-account-data"/> | 
				
			|||
		<glob-deleteall/> | 
				
			|||
		<glob pattern="*.dsad"/> | 
				
			|||
	</mime-type> | 
				
			|||
</mime-info> | 
				
			|||
@ -0,0 +1,422 @@ | 
				
			|||
#include "datasyncviewmodel.h" | 
				
			|||
#include "datasyncviewmodel_p.h" | 
				
			|||
#include "exportsetupviewmodel_p.h" | 
				
			|||
 | 
				
			|||
#include <QtCore/QStandardPaths> | 
				
			|||
#include <QtCore/QFile> | 
				
			|||
 | 
				
			|||
#include <QtRemoteObjects/QRemoteObjectNode> | 
				
			|||
 | 
				
			|||
#include <QtMvvmCore/CoreApp> | 
				
			|||
#include <QtMvvmCore/Messages> | 
				
			|||
 | 
				
			|||
#include <QtDataSync/SetupDoesNotExistException> | 
				
			|||
 | 
				
			|||
#undef logDebug | 
				
			|||
#undef logInfo | 
				
			|||
#undef logWarning | 
				
			|||
#undef logCritical | 
				
			|||
#include <QtMvvmCore/private/qtmvvm_logging_p.h> | 
				
			|||
 | 
				
			|||
using namespace QtMvvm; | 
				
			|||
using namespace QtDataSync; | 
				
			|||
 | 
				
			|||
const QString DataSyncViewModel::paramSetup(QStringLiteral("setup")); | 
				
			|||
const QString DataSyncViewModel::paramReplicaNode(QStringLiteral("node")); | 
				
			|||
 | 
				
			|||
QVariantHash DataSyncViewModel::showParams(const QString &setup) | 
				
			|||
{ | 
				
			|||
	return { | 
				
			|||
		{paramSetup, setup} | 
				
			|||
	}; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
QVariantHash DataSyncViewModel::showParams(QRemoteObjectNode *node) | 
				
			|||
{ | 
				
			|||
	return { | 
				
			|||
		{paramReplicaNode, QVariant::fromValue(node)} | 
				
			|||
	}; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
DataSyncViewModel::DataSyncViewModel(QObject *parent) : | 
				
			|||
	ViewModel(parent), | 
				
			|||
	d(new DataSyncViewModelPrivate(this)) | 
				
			|||
{ | 
				
			|||
	resetColorMap(); | 
				
			|||
} | 
				
			|||
 | 
				
			|||
DataSyncViewModel::~DataSyncViewModel() {} | 
				
			|||
 | 
				
			|||
SyncManager *DataSyncViewModel::syncManager() const | 
				
			|||
{ | 
				
			|||
	return d->syncManager; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
AccountManager *DataSyncViewModel::accountManager() const | 
				
			|||
{ | 
				
			|||
	return d->accountManager; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
DataSyncViewModel::ColorMap DataSyncViewModel::colorMap() const | 
				
			|||
{ | 
				
			|||
	return d->colorMap; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
QString DataSyncViewModel::statusString() const | 
				
			|||
{ | 
				
			|||
	if(!d->syncManager) | 
				
			|||
		return {}; | 
				
			|||
	auto state = d->syncManager->syncState(); | 
				
			|||
 | 
				
			|||
	QString baseText = QStringLiteral("<font color=\"%1\">%2</font>") | 
				
			|||
					   .arg(d->colorMap.value(state).name()); | 
				
			|||
	switch (state) { | 
				
			|||
	case SyncManager::Initializing: | 
				
			|||
		return baseText.arg(tr("Connecting…")); | 
				
			|||
	case SyncManager::Downloading: | 
				
			|||
		return baseText.arg(tr("Downloading…")); | 
				
			|||
	case SyncManager::Uploading: | 
				
			|||
		return baseText.arg(tr("Uploading…")); | 
				
			|||
	case SyncManager::Synchronized: | 
				
			|||
		return baseText.arg(tr("Synchronized")); | 
				
			|||
	case SyncManager::Error: | 
				
			|||
		return baseText.arg(tr("Error!")); | 
				
			|||
	case SyncManager::Disconnected: | 
				
			|||
		return baseText.arg(tr("Disconnected")); | 
				
			|||
	default: | 
				
			|||
		Q_UNREACHABLE(); | 
				
			|||
		return QString(); | 
				
			|||
	} | 
				
			|||
} | 
				
			|||
 | 
				
			|||
AccountModel *DataSyncViewModel::accountModel() const | 
				
			|||
{ | 
				
			|||
	return d->accountModel; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
QString DataSyncViewModel::formatFingerPrint(const QByteArray &fingerPrint) | 
				
			|||
{ | 
				
			|||
	QByteArrayList res; | 
				
			|||
	for(char c : fingerPrint) | 
				
			|||
		res.append(QByteArray(1, c).toHex().toUpper()); | 
				
			|||
	return QString::fromUtf8(res.join(':')); | 
				
			|||
} | 
				
			|||
 | 
				
			|||
void DataSyncViewModel::showDeviceInfo() | 
				
			|||
{ | 
				
			|||
	Q_UNIMPLEMENTED(); | 
				
			|||
} | 
				
			|||
 | 
				
			|||
void DataSyncViewModel::startExport() | 
				
			|||
{ | 
				
			|||
	showForResult<ExportSetupViewModel>(DataSyncViewModelPrivate::ExportRequestCode); | 
				
			|||
} | 
				
			|||
 | 
				
			|||
void DataSyncViewModel::startImport() | 
				
			|||
{ | 
				
			|||
	auto home = QStandardPaths::writableLocation(QStandardPaths::HomeLocation); | 
				
			|||
	getOpenFile(this, [this](QUrl url) { | 
				
			|||
		if(url.isValid()) { | 
				
			|||
			QSharedPointer<QIODevice> 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("<p>A device wants to log into your account:</p>" | 
				
			|||
				"<p>Name: %1<br/>" | 
				
			|||
				"Fingerprint: %2</p>" | 
				
			|||
				"<p>Do you want accept the request?</p>") | 
				
			|||
			 .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<DeviceInfo> &devices) | 
				
			|||
{ | 
				
			|||
	for(auto device : devices) { | 
				
			|||
		if(d->pendingGrants.remove(device.deviceId())) { | 
				
			|||
			information(tr("Account access granted"), | 
				
			|||
						tr("<p>Account access has been granted to device:</p>" | 
				
			|||
						   "<p>Name: %1<br/>" | 
				
			|||
						   "Fingerprint: %2</p>") | 
				
			|||
						.arg(device.name()) | 
				
			|||
						.arg(formatFingerPrint(device.fingerprint()))); | 
				
			|||
		} | 
				
			|||
	} | 
				
			|||
} | 
				
			|||
 | 
				
			|||
void DataSyncViewModel::onInit(const QVariantHash ¶ms) | 
				
			|||
{ | 
				
			|||
	try { | 
				
			|||
		if(params.contains(paramReplicaNode)) { | 
				
			|||
			auto node = params.value(paramReplicaNode).value<QRemoteObjectNode*>(); | 
				
			|||
			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<QIODevice> 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<DataSyncViewModel> 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<DataSyncViewModel> 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); | 
				
			|||
} | 
				
			|||
@ -0,0 +1,86 @@ | 
				
			|||
#ifndef QTMVVM_DATASYNCVIEWMODEL_H | 
				
			|||
#define QTMVVM_DATASYNCVIEWMODEL_H | 
				
			|||
 | 
				
			|||
#include <QtCore/qmap.h> | 
				
			|||
#include <QtCore/qscopedpointer.h> | 
				
			|||
 | 
				
			|||
#include <QtGui/qcolor.h> | 
				
			|||
 | 
				
			|||
#include <QtMvvmCore/viewmodel.h> | 
				
			|||
 | 
				
			|||
#include <QtDataSync/syncmanager.h> | 
				
			|||
#include <QtDataSync/accountmanager.h> | 
				
			|||
 | 
				
			|||
#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<QtDataSync::SyncManager::SyncState, QColor> 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<QtDataSync::DeviceInfo> &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<DataSyncViewModelPrivate> d; | 
				
			|||
}; | 
				
			|||
 | 
				
			|||
} | 
				
			|||
 | 
				
			|||
#endif // QTMVVM_DATASYNCVIEWMODEL_H
 | 
				
			|||
@ -0,0 +1,32 @@ | 
				
			|||
#ifndef QTMVVM_DATASYNCVIEWMODEL_P_H | 
				
			|||
#define QTMVVM_DATASYNCVIEWMODEL_P_H | 
				
			|||
 | 
				
			|||
#include <QtCore/QSet> | 
				
			|||
 | 
				
			|||
#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<QUuid> 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
 | 
				
			|||
@ -0,0 +1,82 @@ | 
				
			|||
#include "exportsetupviewmodel_p.h" | 
				
			|||
using namespace QtMvvm; | 
				
			|||
 | 
				
			|||
std::tuple<bool, bool, QString> 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); | 
				
			|||
} | 
				
			|||
@ -0,0 +1,53 @@ | 
				
			|||
#ifndef QTMVVM_EXPORTSETUPVIEWMODEL_P_H | 
				
			|||
#define QTMVVM_EXPORTSETUPVIEWMODEL_P_H | 
				
			|||
 | 
				
			|||
#include <tuple> | 
				
			|||
 | 
				
			|||
#include <QtMvvmCore/ViewModel> | 
				
			|||
 | 
				
			|||
#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<bool, bool, QString> 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
 | 
				
			|||
@ -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 | 
				
			|||
 | 
				
			|||
@ -0,0 +1,14 @@ | 
				
			|||
{ | 
				
			|||
    "dependencies": [], | 
				
			|||
    "license": { | 
				
			|||
        "file": "", | 
				
			|||
        "name": "" | 
				
			|||
    }, | 
				
			|||
    "prcFile": "", | 
				
			|||
    "priFile": "", | 
				
			|||
    "priIncludes": [ | 
				
			|||
    ], | 
				
			|||
    "publishers": { | 
				
			|||
    }, | 
				
			|||
    "source": false | 
				
			|||
} | 
				
			|||
@ -0,0 +1,12 @@ | 
				
			|||
#ifndef QTMVVMDATASYNCCORE_GLOBAL_H | 
				
			|||
#define QTMVVMDATASYNCCORE_GLOBAL_H | 
				
			|||
 | 
				
			|||
#include <QtCore/qglobal.h> | 
				
			|||
 | 
				
			|||
#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
 | 
				
			|||
@ -0,0 +1,4 @@ | 
				
			|||
<?xml version="1.0" encoding="utf-8"?> | 
				
			|||
<!DOCTYPE TS> | 
				
			|||
<TS version="2.1" language="de_DE"> | 
				
			|||
</TS> | 
				
			|||
@ -0,0 +1,4 @@ | 
				
			|||
<?xml version="1.0" encoding="utf-8"?> | 
				
			|||
<!DOCTYPE TS> | 
				
			|||
<TS version="2.1"> | 
				
			|||
</TS> | 
				
			|||
					Loading…
					
					
				
		Reference in new issue