├── modeling
├── .gitignore
├── server_db.dia
├── localstore_db.dia
├── modeling.pri
└── exchange.txt
├── src
├── 3rdparty
│ ├── cryptopp
│ │ ├── .gitignore
│ │ ├── cryptopp.pri
│ │ ├── travis.sh
│ │ └── appveyor.bat
│ └── 3rdparty.pro
├── plugins
│ ├── keystores
│ │ ├── plain
│ │ │ ├── plain.json
│ │ │ ├── plain.pro
│ │ │ ├── plainkeystoreplugin.h
│ │ │ ├── plainkeystoreplugin.cpp
│ │ │ ├── plainkeystore.h
│ │ │ └── plainkeystore.cpp
│ │ ├── android
│ │ │ ├── android.json
│ │ │ ├── android.pro
│ │ │ ├── androidkeystoreplugin.h
│ │ │ ├── androidkeystoreplugin.cpp
│ │ │ └── androidkeystore.h
│ │ ├── kwallet
│ │ │ ├── kwallet.json
│ │ │ ├── kwallet.pro
│ │ │ ├── kwalletkeystoreplugin.h
│ │ │ ├── kwalletkeystoreplugin.cpp
│ │ │ └── kwalletkeystore.h
│ │ ├── keychain
│ │ │ ├── keychain.json
│ │ │ ├── keychain.pro
│ │ │ ├── keychainkeystoreplugin.h
│ │ │ ├── keychainkeystoreplugin.cpp
│ │ │ └── keychainkeystore.h
│ │ ├── wincred
│ │ │ ├── wincred.json
│ │ │ ├── wincred.pro
│ │ │ ├── wincredkeystoreplugin.h
│ │ │ ├── wincredkeystoreplugin.cpp
│ │ │ └── wincredkeystore.h
│ │ ├── secretservice
│ │ │ ├── secretservice.json
│ │ │ ├── secretservice.pro
│ │ │ ├── secretservicekeystoreplugin.h
│ │ │ ├── secretservicekeystoreplugin.cpp
│ │ │ ├── secretservicekeystore.h
│ │ │ ├── libsecretwrapper.h
│ │ │ └── secretservicekeystore.cpp
│ │ └── keystores.pro
│ └── plugins.pro
├── imports
│ ├── imports.pro
│ └── datasync
│ │ ├── qmldir
│ │ ├── qqmliossyncsingleton.cpp
│ │ ├── qtdatasync_plugin.h
│ │ ├── qqmliossyncsingleton.h
│ │ ├── datasync.pro
│ │ ├── qqmleventcursor.h
│ │ ├── qqmleventcursor.cpp
│ │ └── qqmldatastoremodel.cpp
├── messages
│ ├── messages.pri
│ ├── syncmessage.cpp
│ ├── accountmessage.cpp
│ ├── keychangemessage.cpp
│ ├── devicesmessage.cpp
│ ├── loginmessage.cpp
│ ├── grantmessage.cpp
│ ├── syncmessage_p.h
│ ├── macupdatemessage.cpp
│ ├── removemessage.cpp
│ ├── devicekeysmessage.cpp
│ ├── changemessage.cpp
│ ├── welcomemessage.cpp
│ ├── keychangemessage_p.h
│ ├── devicechangemessage.cpp
│ ├── accountmessage_p.h
│ ├── newkeymessage.cpp
│ ├── loginmessage_p.h
│ ├── changedmessage.cpp
│ ├── grantmessage_p.h
│ ├── accessmessage.cpp
│ ├── macupdatemessage_p.h
│ ├── removemessage_p.h
│ ├── welcomemessage_p.h
│ ├── devicesmessage_p.h
│ ├── devicekeysmessage_p.h
│ ├── errormessage.cpp
│ ├── devicechangemessage_p.h
│ ├── changemessage_p.h
│ ├── proofmessage.cpp
│ ├── errormessage_p.h
│ ├── accessmessage_p.h
│ ├── newkeymessage_p.h
│ ├── registermessage.cpp
│ ├── messages.pro
│ ├── changedmessage_p.h
│ ├── identifymessage_p.h
│ ├── registermessage_p.h
│ └── identifymessage.cpp
├── datasyncios
│ ├── QIOSApplicationDelegate+QtDatasyncAppDelegate_p.h
│ ├── qtdatasyncappdelegate_capi_p.h
│ ├── qtdatasyncios_global.h
│ ├── datasyncios.pro
│ ├── iossyncdelegate_p.h
│ └── QIOSApplicationDelegate+QtDatasyncAppDelegate.mm
├── datasync
│ ├── datatypestore.cpp
│ ├── rothreadedbackend
│ │ ├── rothreadedbackend.pri
│ │ ├── exchangerotransport_p.h
│ │ ├── exchangerotransport.cpp
│ │ ├── exchangebufferserver_p.h
│ │ └── exchangebuffer_p.h
│ ├── conflictresolver_p.h
│ ├── logger_p.h
│ ├── changeemitter_p.rep
│ ├── syncmanager_p.rep
│ ├── signal_private_connect_p.h
│ ├── remoteconfig_p.h
│ ├── datastore_p.h
│ ├── qtdatasync_global.h
│ ├── synchelper_p.h
│ ├── synccontroller_p.h
│ ├── qtdatasync_global.cpp
│ ├── syncmanager_p.h
│ ├── qtdatasync_helpertypes.h
│ ├── conflictresolver.cpp
│ ├── eventcursor_p.h
│ ├── datastoremodel_p.h
│ ├── migrationhelper_p.h
│ ├── userexchangemanager_p.h
│ ├── logger.cpp
│ ├── accountmanager_p.rep
│ ├── controller_p.h
│ ├── changeemitter_p.h
│ ├── objectkey.h
│ ├── objectkey.cpp
│ ├── setup_p.h
│ ├── keystore.cpp
│ ├── emitteradapter_p.h
│ ├── accountmanager_p.h
│ ├── exception.cpp
│ ├── changeemitter.cpp
│ └── controller.cpp
├── datasyncandroid
│ ├── datasyncandroid.pro
│ ├── qtdatasyncandroid_global.h
│ ├── androidbackgroundservice_p.h
│ └── androidsynccontrol_p.h
├── java
│ └── java.pro
├── src.pro
└── translations
│ └── translations.pro
├── examples
├── examples.pro
└── datasync
│ ├── IosSync
│ ├── qml.qrc
│ ├── IosSync.pro
│ ├── syncdelegate.cpp
│ ├── syncdelegate.h
│ ├── main.qml
│ ├── main.cpp
│ └── Info.plist
│ ├── AndroidSync
│ ├── qml.qrc
│ ├── android
│ │ ├── res
│ │ │ ├── drawable-hdpi
│ │ │ │ └── icon.png
│ │ │ ├── drawable-ldpi
│ │ │ │ └── icon.png
│ │ │ ├── drawable-mdpi
│ │ │ │ └── icon.png
│ │ │ └── values
│ │ │ │ └── libs.xml
│ │ ├── build.gradle
│ │ └── src
│ │ │ └── de
│ │ │ └── skycoder42
│ │ │ └── qtdatasync
│ │ │ └── sample
│ │ │ └── androidsync
│ │ │ └── SvcHelper.java
│ ├── AndroidSync.pro
│ ├── syncservice.h
│ ├── main.qml
│ ├── syncservice.cpp
│ └── main.cpp
│ ├── datasync.pro
│ └── Sample
│ ├── sampledata.cpp
│ ├── sampledata.h
│ ├── docker-compose.yaml
│ ├── widget.h
│ ├── Sample.pro
│ ├── exchangedialog.h
│ └── accountdialog.h
├── doc
├── images
│ ├── demo.gif
│ └── GitHub_Logo.png
├── doc.pro
├── qtdatasync.dox
├── doxme.py
├── rothreaded.dox
├── migrationhelper.dox
├── makedoc.sh
└── logger.dox
├── tools
├── tools.pro
└── appserver
│ ├── docker_setup.conf
│ ├── qdsapp-install.bat.in
│ ├── qdsapp.socket.in
│ ├── dockerbuild
│ ├── env_start.sh
│ └── install.sh
│ ├── qdsapp.conf
│ ├── qdsapp.service.in
│ ├── de.skycoder42.qtdatasync.qdsapp.plist.in
│ ├── docker-compose.yaml
│ ├── clientconnector.h
│ ├── datasyncservice.h
│ └── singletaskqueue.h
├── tests
├── global
│ └── global.cfg
├── auto
│ ├── datasync
│ │ ├── TestSetup
│ │ │ └── TestSetup.pro
│ │ ├── TestMessages
│ │ │ └── TestMessages.pro
│ │ ├── TestDataStore
│ │ │ └── TestDataStore.pro
│ │ ├── TestEventCursor
│ │ │ └── TestEventCursor.pro
│ │ ├── TestDataTypeStore
│ │ │ └── TestDataTypeStore.pro
│ │ ├── TestChangeController
│ │ │ └── TestChangeController.pro
│ │ ├── TestMigrationHelper
│ │ │ └── TestMigrationHelper.pro
│ │ ├── TestRemoteConnector
│ │ │ └── TestRemoteConnector.pro
│ │ ├── TestRoThreadedBackend
│ │ │ ├── testclass.rep
│ │ │ └── TestRoThreadedBackend.pro
│ │ ├── TestLocalStore
│ │ │ └── TestLocalStore.pro
│ │ ├── IntegrationTest
│ │ │ ├── qdsapp.conf
│ │ │ └── IntegrationTest.pro
│ │ ├── TestKeystorePlugins
│ │ │ └── TestKeystorePlugins.pro
│ │ ├── TestSyncController
│ │ │ ├── TestSyncController.pro
│ │ │ ├── testresolver.h
│ │ │ └── testresolver.cpp
│ │ ├── TestCryptoController
│ │ │ └── TestCryptoController.pro
│ │ ├── TestAppServer
│ │ │ ├── qdsapp.conf
│ │ │ └── TestAppServer.pro
│ │ ├── TestLib
│ │ │ ├── testdata.cpp
│ │ │ ├── testobject.cpp
│ │ │ ├── mockclient.h
│ │ │ ├── testdata.h
│ │ │ ├── testobject.h
│ │ │ ├── mockserver.h
│ │ │ ├── mockclient.cpp
│ │ │ ├── TestLib.pro
│ │ │ ├── mockserver.cpp
│ │ │ ├── testlib.h
│ │ │ └── testlib.cpp
│ │ ├── datasync.pro
│ │ └── tests.pri
│ ├── cmake
│ │ ├── cmake.pro
│ │ └── CMakeLists.txt
│ ├── qml
│ │ ├── qml.pro
│ │ └── TestQmlDataSync
│ │ │ ├── TestQmlDataSync.pro
│ │ │ ├── tst_qmldatasync.cpp
│ │ │ └── tst_qmldatasync.qml
│ └── auto.pro
├── tests.pro
└── ci
│ ├── qdsapp.conf
│ └── setup.sh
├── .gitmodules
├── Dockerfile
├── .qmake.conf
├── deploy.json
├── qtdatasync.pro
├── sync.profile
├── .gitignore
├── mkspecs
└── features
│ └── masm.prf
├── appveyor.yml
└── LICENSE
/modeling/.gitignore:
--------------------------------------------------------------------------------
1 | *.dia~
2 |
--------------------------------------------------------------------------------
/src/3rdparty/cryptopp/.gitignore:
--------------------------------------------------------------------------------
1 | include
2 | lib
3 |
--------------------------------------------------------------------------------
/examples/examples.pro:
--------------------------------------------------------------------------------
1 | TEMPLATE = subdirs
2 |
3 | SUBDIRS = datasync
4 |
--------------------------------------------------------------------------------
/src/plugins/keystores/plain/plain.json:
--------------------------------------------------------------------------------
1 | {
2 | "Keys" : [ "plain" ]
3 | }
4 |
--------------------------------------------------------------------------------
/src/imports/imports.pro:
--------------------------------------------------------------------------------
1 | TEMPLATE = subdirs
2 |
3 | SUBDIRS += \
4 | datasync
5 |
--------------------------------------------------------------------------------
/src/plugins/keystores/android/android.json:
--------------------------------------------------------------------------------
1 | {
2 | "Keys" : [ "android" ]
3 | }
4 |
--------------------------------------------------------------------------------
/src/plugins/keystores/kwallet/kwallet.json:
--------------------------------------------------------------------------------
1 | {
2 | "Keys" : [ "kwallet" ]
3 | }
4 |
--------------------------------------------------------------------------------
/src/plugins/keystores/keychain/keychain.json:
--------------------------------------------------------------------------------
1 | {
2 | "Keys" : [ "keychain" ]
3 | }
4 |
--------------------------------------------------------------------------------
/src/plugins/keystores/wincred/wincred.json:
--------------------------------------------------------------------------------
1 | {
2 | "Keys" : [ "wincred" ]
3 | }
4 |
--------------------------------------------------------------------------------
/doc/images/demo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Skycoder42/QtDataSync/master/doc/images/demo.gif
--------------------------------------------------------------------------------
/modeling/server_db.dia:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Skycoder42/QtDataSync/master/modeling/server_db.dia
--------------------------------------------------------------------------------
/src/plugins/plugins.pro:
--------------------------------------------------------------------------------
1 | TEMPLATE = subdirs
2 |
3 | QT_FOR_CONFIG += core
4 | SUBDIRS += keystores
5 |
--------------------------------------------------------------------------------
/doc/images/GitHub_Logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Skycoder42/QtDataSync/master/doc/images/GitHub_Logo.png
--------------------------------------------------------------------------------
/modeling/localstore_db.dia:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Skycoder42/QtDataSync/master/modeling/localstore_db.dia
--------------------------------------------------------------------------------
/src/plugins/keystores/secretservice/secretservice.json:
--------------------------------------------------------------------------------
1 | {
2 | "Keys" : [ "secretservice", "gnome-keyring" ]
3 | }
4 |
--------------------------------------------------------------------------------
/src/messages/messages.pri:
--------------------------------------------------------------------------------
1 | QMAKE_USE_PRIVATE += datasync_messages
2 | include($$PWD/../3rdparty/cryptopp/cryptopp.pri)
3 |
--------------------------------------------------------------------------------
/tools/tools.pro:
--------------------------------------------------------------------------------
1 | TEMPLATE = subdirs
2 |
3 | !cross_compile: SUBDIRS += appserver
4 |
5 | QMAKE_EXTRA_TARGETS += run-tests
6 |
--------------------------------------------------------------------------------
/tests/global/global.cfg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/examples/datasync/IosSync/qml.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | main.qml
4 |
5 |
6 |
--------------------------------------------------------------------------------
/modeling/modeling.pri:
--------------------------------------------------------------------------------
1 | OTHER_FILES += $$PWD/*.qmodel \
2 | $$PWD/*.dia \
3 | $$PWD/*.txt \
4 | $$PWD/../src/datasync/connectormodel.scxml
5 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "src/3rdparty/cryptopp/src"]
2 | path = src/3rdparty/cryptopp/src
3 | url = https://github.com/weidai11/cryptopp.git
4 |
--------------------------------------------------------------------------------
/examples/datasync/AndroidSync/qml.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | main.qml
4 |
5 |
6 |
--------------------------------------------------------------------------------
/tests/auto/datasync/TestSetup/TestSetup.pro:
--------------------------------------------------------------------------------
1 | include(../tests.pri)
2 |
3 | TARGET = tst_setup
4 |
5 | SOURCES += \
6 | tst_setup.cpp
7 |
8 |
--------------------------------------------------------------------------------
/tests/auto/datasync/TestMessages/TestMessages.pro:
--------------------------------------------------------------------------------
1 | include(../tests.pri)
2 |
3 | TARGET = tst_messages
4 |
5 | SOURCES += \
6 | tst_messages.cpp
7 |
--------------------------------------------------------------------------------
/tests/auto/datasync/TestDataStore/TestDataStore.pro:
--------------------------------------------------------------------------------
1 | include(../tests.pri)
2 |
3 | TARGET = tst_datastore
4 |
5 | SOURCES += \
6 | tst_datastore.cpp
7 |
--------------------------------------------------------------------------------
/tests/auto/cmake/cmake.pro:
--------------------------------------------------------------------------------
1 |
2 | # Cause make to do nothing.
3 | TEMPLATE = subdirs
4 |
5 | CMAKE_QT_MODULES_UNDER_TEST = datasync
6 |
7 | CONFIG += ctest_testcase
8 |
--------------------------------------------------------------------------------
/tests/auto/datasync/TestEventCursor/TestEventCursor.pro:
--------------------------------------------------------------------------------
1 | include(../tests.pri)
2 |
3 | TARGET = tst_eventcursor
4 |
5 | SOURCES += \
6 | tst_eventcursor.cpp
7 |
--------------------------------------------------------------------------------
/tests/auto/qml/qml.pro:
--------------------------------------------------------------------------------
1 | TEMPLATE = subdirs
2 |
3 | SUBDIRS += \
4 | TestQmlDataSync
5 |
6 | prepareRecursiveTarget(run-tests)
7 | QMAKE_EXTRA_TARGETS += run-tests
8 |
--------------------------------------------------------------------------------
/src/3rdparty/3rdparty.pro:
--------------------------------------------------------------------------------
1 | TEMPLATE = subdirs
2 |
3 | system_cryptopp:unix: message("Not building cryptopp, using system provided version")
4 | else: SUBDIRS += cryptopp
5 |
--------------------------------------------------------------------------------
/tests/auto/datasync/TestDataTypeStore/TestDataTypeStore.pro:
--------------------------------------------------------------------------------
1 | include(../tests.pri)
2 |
3 | TARGET = tst_datatypestore
4 |
5 | SOURCES += \
6 | tst_datatypestore.cpp
7 |
--------------------------------------------------------------------------------
/src/3rdparty/cryptopp/cryptopp.pri:
--------------------------------------------------------------------------------
1 | system_cryptopp:unix {
2 | CONFIG += link_pkgconfig
3 | PKGCONFIG += libcrypto++
4 | } else {
5 | QMAKE_USE_PRIVATE += cryptopp
6 | }
7 |
--------------------------------------------------------------------------------
/tests/tests.pro:
--------------------------------------------------------------------------------
1 | TEMPLATE = subdirs
2 |
3 | CONFIG += no_docs_target
4 |
5 | SUBDIRS += auto
6 |
7 | prepareRecursiveTarget(run-tests)
8 | QMAKE_EXTRA_TARGETS += run-tests
9 |
--------------------------------------------------------------------------------
/examples/datasync/datasync.pro:
--------------------------------------------------------------------------------
1 | TEMPLATE = subdirs
2 | QT_FOR_CONFIG += core
3 |
4 | SUBDIRS += \
5 | Sample
6 |
7 | android: SUBDIRS += AndroidSync
8 | ios: SUBDIRS += IosSync
9 |
--------------------------------------------------------------------------------
/tests/auto/datasync/TestChangeController/TestChangeController.pro:
--------------------------------------------------------------------------------
1 | include(../tests.pri)
2 |
3 | TARGET = tst_changecontroller
4 |
5 | SOURCES += \
6 | tst_changecontroller.cpp
7 |
--------------------------------------------------------------------------------
/tests/auto/datasync/TestMigrationHelper/TestMigrationHelper.pro:
--------------------------------------------------------------------------------
1 | include(../tests.pri)
2 |
3 | TARGET = tst_migrationhelper
4 |
5 | SOURCES += \
6 | tst_migrationhelper.cpp
7 |
--------------------------------------------------------------------------------
/tests/auto/datasync/TestRemoteConnector/TestRemoteConnector.pro:
--------------------------------------------------------------------------------
1 | include(../tests.pri)
2 |
3 | TARGET = tst_remoteconnector
4 |
5 | SOURCES += \
6 | tst_remoteconnector.cpp
7 |
--------------------------------------------------------------------------------
/tests/auto/datasync/TestRoThreadedBackend/testclass.rep:
--------------------------------------------------------------------------------
1 | class TestClass
2 | {
3 | PROP(bool currState=false);
4 | SLOT(serverDo(int id));
5 | SIGNAL(serverDone(int id));
6 | };
7 |
--------------------------------------------------------------------------------
/examples/datasync/AndroidSync/android/res/drawable-hdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Skycoder42/QtDataSync/master/examples/datasync/AndroidSync/android/res/drawable-hdpi/icon.png
--------------------------------------------------------------------------------
/examples/datasync/AndroidSync/android/res/drawable-ldpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Skycoder42/QtDataSync/master/examples/datasync/AndroidSync/android/res/drawable-ldpi/icon.png
--------------------------------------------------------------------------------
/examples/datasync/AndroidSync/android/res/drawable-mdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Skycoder42/QtDataSync/master/examples/datasync/AndroidSync/android/res/drawable-mdpi/icon.png
--------------------------------------------------------------------------------
/tests/auto/datasync/TestLocalStore/TestLocalStore.pro:
--------------------------------------------------------------------------------
1 | include(../tests.pri)
2 |
3 | QT += concurrent
4 |
5 | TARGET = tst_localstore
6 |
7 | SOURCES += \
8 | tst_localstore.cpp
9 |
--------------------------------------------------------------------------------
/tests/ci/qdsapp.conf:
--------------------------------------------------------------------------------
1 | [server]
2 | host=localhost
3 | port=14242
4 |
5 | [database]
6 | name=postgres
7 | host=localhost
8 | port=5432
9 | username=postgres
10 | password=baum42
11 |
--------------------------------------------------------------------------------
/src/imports/datasync/qmldir:
--------------------------------------------------------------------------------
1 | module de.skycoder42.QtDataSync
2 | plugin declarative_datasync
3 | classname QtDataSyncDeclarativeModule
4 | typeinfo plugins.qmltypes
5 | depends QtQml 2.2
6 | depends QtQml.Models 2.2
7 |
--------------------------------------------------------------------------------
/tests/auto/datasync/IntegrationTest/qdsapp.conf:
--------------------------------------------------------------------------------
1 | [server]
2 | host=localhost
3 | port=14242
4 |
5 | [database]
6 | name=QtDataSync
7 | host=localhost
8 | port=15432
9 | username=qtdatasync
10 | password=baum42
11 |
--------------------------------------------------------------------------------
/tests/auto/datasync/TestKeystorePlugins/TestKeystorePlugins.pro:
--------------------------------------------------------------------------------
1 | include(../tests.pri)
2 |
3 | QT += gui widgets #required for kde
4 |
5 | TARGET = tst_keystoreplugins
6 |
7 | SOURCES += \
8 | tst_keystoreplugins.cpp
9 |
--------------------------------------------------------------------------------
/tools/appserver/docker_setup.conf:
--------------------------------------------------------------------------------
1 | [server]
2 | host=localhost
3 | port=4242
4 | loglevel=4
5 |
6 | [database]
7 | name=QtDataSync
8 | host=localhost
9 | port=15432
10 | username=qtdatasync
11 | password=baum42
12 |
--------------------------------------------------------------------------------
/src/messages/syncmessage.cpp:
--------------------------------------------------------------------------------
1 | #include "syncmessage_p.h"
2 |
3 | #include
4 |
5 | using namespace QtDataSync;
6 |
7 | const QMetaObject *SyncMessage::getMetaObject() const
8 | {
9 | return &staticMetaObject;
10 | }
11 |
--------------------------------------------------------------------------------
/tests/auto/datasync/TestSyncController/TestSyncController.pro:
--------------------------------------------------------------------------------
1 | include(../tests.pri)
2 |
3 | TARGET = tst_synccontroller
4 |
5 | SOURCES += \
6 | tst_synccontroller.cpp \
7 | testresolver.cpp
8 |
9 | HEADERS += \
10 | testresolver.h
11 |
--------------------------------------------------------------------------------
/src/datasyncios/QIOSApplicationDelegate+QtDatasyncAppDelegate_p.h:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | @interface QIOSApplicationDelegate : UIResponder
4 | @end
5 |
6 | @interface QIOSApplicationDelegate (QtDatasyncAppDelegate)
7 | @end
8 |
--------------------------------------------------------------------------------
/tests/auto/auto.pro:
--------------------------------------------------------------------------------
1 | TEMPLATE = subdirs
2 |
3 | SUBDIRS += cmake \
4 | datasync \
5 | qml
6 |
7 | qml.depends += datasync
8 |
9 | cmake.CONFIG += no_run-tests_target
10 | prepareRecursiveTarget(run-tests)
11 | QMAKE_EXTRA_TARGETS += run-tests
12 |
--------------------------------------------------------------------------------
/tests/auto/datasync/TestCryptoController/TestCryptoController.pro:
--------------------------------------------------------------------------------
1 | include(../tests.pri)
2 |
3 | TARGET = tst_cryptocontroller
4 |
5 | SOURCES += \
6 | tst_cryptocontroller.cpp
7 |
8 | DEFINES += PLUGIN_DIR=\\\"$$OUT_PWD/../../../../plugins/keystores/\\\"
9 |
--------------------------------------------------------------------------------
/tests/auto/datasync/TestAppServer/qdsapp.conf:
--------------------------------------------------------------------------------
1 | [general]
2 | logIpAddress=true
3 |
4 | [server]
5 | host=localhost
6 | port=14242
7 |
8 | [database]
9 | name=QtDataSync
10 | host=localhost
11 | port=15432
12 | username=qtdatasync
13 | password=baum42
14 |
--------------------------------------------------------------------------------
/tests/auto/datasync/TestRoThreadedBackend/TestRoThreadedBackend.pro:
--------------------------------------------------------------------------------
1 | include(../tests.pri)
2 |
3 | TARGET = tst_rothreadedbackend
4 |
5 | SOURCES += \
6 | tst_rothreadedbackend.cpp
7 |
8 | REPC_SOURCE += testclass.rep
9 | REPC_REPLICA += $$REPC_SOURCE
10 |
--------------------------------------------------------------------------------
/src/datasync/datatypestore.cpp:
--------------------------------------------------------------------------------
1 | #include "datatypestore.h"
2 | using namespace QtDataSync;
3 |
4 | DataTypeStoreBase::DataTypeStoreBase(QObject *parent) :
5 | QObject{parent}
6 | {}
7 |
8 | QString DataTypeStoreBase::setupName() const
9 | {
10 | return store()->setupName();
11 | }
12 |
--------------------------------------------------------------------------------
/tests/auto/cmake/CMakeLists.txt:
--------------------------------------------------------------------------------
1 |
2 | cmake_minimum_required(VERSION 2.8)
3 |
4 | project(qmake_cmake_files)
5 |
6 | enable_testing()
7 |
8 | find_package(Qt5Core REQUIRED)
9 |
10 | include("${_Qt5CTestMacros}")
11 |
12 | test_module_includes(
13 | DataSync QDataSync
14 | )
15 |
--------------------------------------------------------------------------------
/tests/auto/datasync/TestLib/testdata.cpp:
--------------------------------------------------------------------------------
1 | #include "testdata.h"
2 |
3 | TestData::TestData(int id, QString text) :
4 | id(id),
5 | text(text)
6 | {}
7 |
8 | bool TestData::operator ==(const TestData &other) const
9 | {
10 | return id == other.id &&
11 | text == other.text;
12 | }
13 |
--------------------------------------------------------------------------------
/tools/appserver/qdsapp-install.bat.in:
--------------------------------------------------------------------------------
1 | @echo off
2 | sc create qdsapp binPath= \\"$$system_path($$[QT_INSTALL_BINS]\\\\$${TARGET}) --backend windows\\" start= auto displayname= \\"$${QMAKE_TARGET_PRODUCT}\\" || exit /B 1
3 | sc description qdsapp \\"$${QMAKE_TARGET_PRODUCT} Service\\" || exit /B 1
4 |
--------------------------------------------------------------------------------
/tools/appserver/qdsapp.socket.in:
--------------------------------------------------------------------------------
1 | [Unit]
2 | Description=QtDataSync AppServer Socket
3 | Documentation=https://github.com/Skycoder42/QtDataSync
4 | After=network.target
5 | PartOf=$${APPNAME}.service
6 |
7 | [Socket]
8 | ListenStream=4242
9 |
10 | [Install]
11 | WantedBy=sockets.target
12 |
--------------------------------------------------------------------------------
/src/messages/accountmessage.cpp:
--------------------------------------------------------------------------------
1 | #include "accountmessage_p.h"
2 | using namespace QtDataSync;
3 |
4 | AccountMessage::AccountMessage(QUuid deviceId) :
5 | deviceId{deviceId}
6 | {}
7 |
8 | const QMetaObject *AccountMessage::getMetaObject() const
9 | {
10 | return &staticMetaObject;
11 | }
12 |
--------------------------------------------------------------------------------
/src/messages/keychangemessage.cpp:
--------------------------------------------------------------------------------
1 | #include "keychangemessage_p.h"
2 | using namespace QtDataSync;
3 |
4 | KeyChangeMessage::KeyChangeMessage(quint32 nextIndex) :
5 | nextIndex{nextIndex}
6 | {}
7 |
8 | const QMetaObject *KeyChangeMessage::getMetaObject() const
9 | {
10 | return &staticMetaObject;
11 | }
12 |
--------------------------------------------------------------------------------
/tests/auto/datasync/TestLib/testobject.cpp:
--------------------------------------------------------------------------------
1 | #include "testobject.h"
2 |
3 | TestObject::TestObject(QObject *parent) :
4 | QObject(parent),
5 | id(0),
6 | text()
7 | {}
8 |
9 | bool TestObject::equals(const TestObject *other) const
10 | {
11 | return id == other->id &&
12 | text == other->text;
13 | }
14 |
--------------------------------------------------------------------------------
/src/messages/devicesmessage.cpp:
--------------------------------------------------------------------------------
1 | #include "devicesmessage_p.h"
2 | using namespace QtDataSync;
3 |
4 | const QMetaObject *ListDevicesMessage::getMetaObject() const
5 | {
6 | return &staticMetaObject;
7 | }
8 |
9 |
10 |
11 | const QMetaObject *DevicesMessage::getMetaObject() const
12 | {
13 | return &staticMetaObject;
14 | }
15 |
--------------------------------------------------------------------------------
/src/imports/datasync/qqmliossyncsingleton.cpp:
--------------------------------------------------------------------------------
1 | #include "qqmliossyncsingleton.h"
2 | using namespace QtDataSync;
3 |
4 | QQmlIosSyncSingleton::QQmlIosSyncSingleton(QObject *parent) :
5 | QObject{parent}
6 | {}
7 |
8 | IosSyncDelegate *QQmlIosSyncSingleton::delegate() const
9 | {
10 | return IosSyncDelegate::currentDelegate();
11 | }
12 |
--------------------------------------------------------------------------------
/src/plugins/keystores/keystores.pro:
--------------------------------------------------------------------------------
1 | TEMPLATE = subdirs
2 |
3 | SUBDIRS += plain
4 | qtHaveModule(KWallet): SUBDIRS += kwallet
5 | unix:!android:!ios:packagesExist(libsecret-1): SUBDIRS += secretservice
6 | win32:!cross_compile: SUBDIRS += wincred
7 | mac|ios: SUBDIRS += keychain
8 | android:qtHaveModule(androidextras): SUBDIRS += android
9 |
--------------------------------------------------------------------------------
/src/datasync/rothreadedbackend/rothreadedbackend.pri:
--------------------------------------------------------------------------------
1 | HEADERS += \
2 | $$PWD/exchangebuffer_p.h \
3 | $$PWD/exchangebufferserver_p.h \
4 | $$PWD/exchangerotransport_p.h
5 |
6 | SOURCES += \
7 | $$PWD/exchangebuffer.cpp \
8 | $$PWD/exchangebufferserver.cpp \
9 | $$PWD/exchangerotransport.cpp
10 |
11 | INCLUDEPATH += $$PWD
12 |
--------------------------------------------------------------------------------
/src/datasyncios/qtdatasyncappdelegate_capi_p.h:
--------------------------------------------------------------------------------
1 | #ifndef QTDATASYNCAPPDELEGATE_CAPI_P_H
2 | #define QTDATASYNCAPPDELEGATE_CAPI_P_H
3 |
4 | #include
5 | #include
6 |
7 | #include "iossyncdelegate.h"
8 |
9 | // c -> mm
10 | void QtDatasyncAppDelegateInitialize();
11 | void setSyncInterval(double intervalSeconds);
12 |
13 | #endif // DATASYNCAPPDELEGATE_CAPI_P_H
14 |
--------------------------------------------------------------------------------
/src/messages/loginmessage.cpp:
--------------------------------------------------------------------------------
1 | #include "loginmessage_p.h"
2 | using namespace QtDataSync;
3 |
4 | LoginMessage::LoginMessage(QUuid deviceId, QString deviceName, QByteArray nonce) :
5 | InitMessage{std::move(nonce)},
6 | deviceId{deviceId},
7 | deviceName{std::move(deviceName)}
8 | {}
9 |
10 | const QMetaObject *LoginMessage::getMetaObject() const
11 | {
12 | return &staticMetaObject;
13 | }
14 |
--------------------------------------------------------------------------------
/examples/datasync/Sample/sampledata.cpp:
--------------------------------------------------------------------------------
1 | #include "sampledata.h"
2 |
3 | QDebug operator<<(QDebug debug, const SampleData &data)
4 | {
5 | QDebugStateSaver saver(debug);
6 | debug.nospace().noquote() << "SampleData{"
7 | << "id: " << data.id << ", "
8 | << "title: " << data.title << ", "
9 | << "description: " << data.description
10 | << '}';
11 | return debug;
12 | }
13 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | #LABEL maintainer="skycoder42.de@gmx.de"
2 | FROM alpine:latest
3 |
4 | COPY . /tmp/src
5 | RUN /tmp/src/tools/appserver/dockerbuild/install.sh
6 |
7 | ENV QDSAPP_CONFIG_FILE=/etc/qdsapp.conf \
8 | QDSAPP_DATABASE_HOST= \
9 | QDSAPP_DATABASE_PORT=5432 \
10 | QDSAPP_DATABASE_USER=postgres \
11 | QDSAPP_DATABASE_PASSWORD= \
12 | QDSAPP_DATABASE_NAME=postgres
13 | CMD ["/usr/bin/env_start.sh"]
14 |
--------------------------------------------------------------------------------
/src/plugins/keystores/plain/plain.pro:
--------------------------------------------------------------------------------
1 | TARGET = qplain
2 |
3 | QT += datasync
4 | QT -= gui
5 |
6 | HEADERS += \
7 | plainkeystoreplugin.h \
8 | plainkeystore.h
9 |
10 | SOURCES += \
11 | plainkeystoreplugin.cpp \
12 | plainkeystore.cpp
13 |
14 | DISTFILES += plain.json
15 |
16 | PLUGIN_TYPE = keystores
17 | PLUGIN_EXTENDS = datasync
18 | PLUGIN_CLASS_NAME = PlainKeyStorePlugin
19 | load(qt_plugin)
20 |
--------------------------------------------------------------------------------
/examples/datasync/IosSync/IosSync.pro:
--------------------------------------------------------------------------------
1 | TEMPLATE = app
2 |
3 | QT += quick datasync datasyncios
4 | CONFIG += c++14
5 |
6 | TARGET = IosSync
7 |
8 | HEADERS += \
9 | syncdelegate.h
10 |
11 | SOURCES += \
12 | main.cpp \
13 | syncdelegate.cpp
14 |
15 | RESOURCES += qml.qrc
16 |
17 | QMAKE_INFO_PLIST = Info.plist
18 |
19 | target.path = $$[QT_INSTALL_EXAMPLES]/datasync/$$TARGET
20 | !install_ok: INSTALLS += target
21 |
--------------------------------------------------------------------------------
/src/plugins/keystores/kwallet/kwallet.pro:
--------------------------------------------------------------------------------
1 | TARGET = qkwallet
2 |
3 | QT += datasync KWallet
4 | QT -= gui
5 |
6 | HEADERS += \
7 | kwalletkeystoreplugin.h \
8 | kwalletkeystore.h
9 |
10 | SOURCES += \
11 | kwalletkeystoreplugin.cpp \
12 | kwalletkeystore.cpp
13 |
14 | DISTFILES += kwallet.json
15 |
16 | PLUGIN_TYPE = keystores
17 | PLUGIN_EXTENDS = datasync
18 | PLUGIN_CLASS_NAME = KWalletKeyStorePlugin
19 | load(qt_plugin)
20 |
--------------------------------------------------------------------------------
/src/datasyncios/qtdatasyncios_global.h:
--------------------------------------------------------------------------------
1 | #ifndef QTDATASYNCIOS_GLOBAL_H
2 | #define QTDATASYNCIOS_GLOBAL_H
3 |
4 | #include
5 |
6 | #ifndef QT_STATIC
7 | # if defined(QT_BUILD_DATASYNCIOS_LIB)
8 | # define Q_DATASYNCIOS_EXPORT Q_DECL_EXPORT
9 | # else
10 | # define Q_DATASYNCIOS_EXPORT Q_DECL_IMPORT
11 | # endif
12 | #else
13 | # define Q_DATASYNCIOS_EXPORT
14 | #endif
15 |
16 | #endif // QTDATASYNCIOS_GLOBAL_H
17 |
--------------------------------------------------------------------------------
/src/plugins/keystores/android/android.pro:
--------------------------------------------------------------------------------
1 | TARGET = qandroid
2 |
3 | QT += datasync androidextras
4 | QT -= gui
5 |
6 | HEADERS += \
7 | androidkeystoreplugin.h \
8 | androidkeystore.h
9 |
10 | SOURCES += \
11 | androidkeystoreplugin.cpp \
12 | androidkeystore.cpp
13 |
14 | DISTFILES += android.json
15 |
16 | PLUGIN_TYPE = keystores
17 | PLUGIN_EXTENDS = datasync
18 | PLUGIN_CLASS_NAME = AndroidKeyStorePlugin
19 | load(qt_plugin)
20 |
--------------------------------------------------------------------------------
/tests/auto/datasync/TestLib/mockclient.h:
--------------------------------------------------------------------------------
1 | #ifndef MOCKCLIENT_H
2 | #define MOCKCLIENT_H
3 |
4 | #include
5 |
6 | #include "mockconnection.h"
7 |
8 | class MockClient : public MockConnection
9 | {
10 | Q_OBJECT
11 |
12 | public:
13 | explicit MockClient(QObject *parent = nullptr);
14 |
15 | bool waitForConnected(quint16 port = 14242);
16 |
17 | private:
18 | QSignalSpy _connectSpy;
19 | };
20 |
21 | #endif // MOCKCLIENT_H
22 |
--------------------------------------------------------------------------------
/src/datasyncandroid/datasyncandroid.pro:
--------------------------------------------------------------------------------
1 | TARGET = QtDataSyncAndroid
2 |
3 | QT = core service androidextras datasync datasync-private
4 |
5 | HEADERS += \
6 | androidbackgroundservice.h \
7 | qtdatasyncandroid_global.h \
8 | androidbackgroundservice_p.h \
9 | androidsynccontrol.h \
10 | androidsynccontrol_p.h
11 |
12 | SOURCES += \
13 | androidbackgroundservice.cpp \
14 | androidsynccontrol.cpp
15 |
16 | load(qt_module)
17 |
--------------------------------------------------------------------------------
/tests/auto/datasync/TestAppServer/TestAppServer.pro:
--------------------------------------------------------------------------------
1 | include(../tests.pri)
2 |
3 | QT += service
4 |
5 | TARGET = tst_appserver
6 |
7 | SOURCES += \
8 | tst_appserver.cpp
9 |
10 | BUILD_BIN_DIR = $$shadowed($$dirname(_QMAKE_CONF_))/bin
11 | DEFINES += BUILD_BIN_DIR=\\\"$$BUILD_BIN_DIR/\\\"
12 |
13 | !include(./setup.pri): SETUP_FILE = $$PWD/qdsapp.conf
14 |
15 | DISTFILES += $$SETUP_FILE
16 | DEFINES += SETUP_FILE=\\\"$$SETUP_FILE\\\"
17 |
--------------------------------------------------------------------------------
/src/messages/grantmessage.cpp:
--------------------------------------------------------------------------------
1 | #include "grantmessage_p.h"
2 | using namespace QtDataSync;
3 |
4 | GrantMessage::GrantMessage() = default;
5 |
6 | GrantMessage::GrantMessage(const AcceptMessage &message) :
7 | AccountMessage{message.deviceId},
8 | index{message.index},
9 | scheme{message.scheme},
10 | secret{message.secret}
11 | {}
12 |
13 | const QMetaObject *GrantMessage::getMetaObject() const
14 | {
15 | return &staticMetaObject;
16 | }
17 |
--------------------------------------------------------------------------------
/src/messages/syncmessage_p.h:
--------------------------------------------------------------------------------
1 | #ifndef QTDATASYNC_SYNCMESSAGE_P_H
2 | #define QTDATASYNC_SYNCMESSAGE_P_H
3 |
4 | #include "message_p.h"
5 |
6 | namespace QtDataSync {
7 |
8 | class Q_DATASYNC_EXPORT SyncMessage : public Message
9 | {
10 | Q_GADGET
11 |
12 | protected:
13 | const QMetaObject *getMetaObject() const override;
14 | };
15 |
16 | }
17 |
18 | Q_DECLARE_METATYPE(QtDataSync::SyncMessage)
19 |
20 | #endif // QTDATASYNC_SYNCMESSAGE_P_H
21 |
--------------------------------------------------------------------------------
/tests/auto/datasync/IntegrationTest/IntegrationTest.pro:
--------------------------------------------------------------------------------
1 | include(../tests.pri)
2 |
3 | QT += service
4 |
5 | TARGET = tst_integration
6 |
7 | SOURCES += \
8 | tst_integration.cpp
9 |
10 | BUILD_BIN_DIR = $$shadowed($$dirname(_QMAKE_CONF_))/bin
11 | DEFINES += BUILD_BIN_DIR=\\\"$$BUILD_BIN_DIR/\\\"
12 |
13 | !include(./setup.pri): SETUP_FILE = $$PWD/qdsapp.conf
14 |
15 | DISTFILES += $$SETUP_FILE
16 | DEFINES += SETUP_FILE=\\\"$$SETUP_FILE\\\"
17 |
--------------------------------------------------------------------------------
/src/3rdparty/cryptopp/travis.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -e
3 |
4 | version=7_0_0
5 |
6 | case "$PLATFORM" in
7 | gcc_64)
8 | pkgName=linux
9 | ;;
10 | clang_64)
11 | pkgName=macos
12 | ;;
13 | *)
14 | pkgName=$PLATFORM
15 | ;;
16 | esac
17 |
18 | curl -Lo /tmp/cryptopp.tar.xz https://github.com/Skycoder42/ci-builds/releases/download/cryptopp_${version}/cryptopp_${version}_${pkgName}.tar.xz
19 | tar -xf /tmp/cryptopp.tar.xz -C ./src/3rdparty/
20 |
--------------------------------------------------------------------------------
/.qmake.conf:
--------------------------------------------------------------------------------
1 | load(qt_build_config)
2 |
3 | CONFIG += warning_clean exceptions c++17
4 | #QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.12
5 |
6 | DEFINES += QT_DEPRECATED_WARNINGS QT_ASCII_CAST_WARNINGS
7 |
8 | MODULE_VERSION_MAJOR = 4
9 | MODULE_VERSION_MINOR = 3
10 | MODULE_VERSION_PATCH = 0
11 | MODULE_VERSION_IMPORT = $${MODULE_VERSION_MAJOR}.$${MODULE_VERSION_MINOR}
12 | MODULE_VERSION = $${MODULE_VERSION_MAJOR}.$${MODULE_VERSION_MINOR}.$${MODULE_VERSION_PATCH}
13 |
14 |
--------------------------------------------------------------------------------
/deploy.json:
--------------------------------------------------------------------------------
1 | {
2 | "title": "QtDataSync",
3 | "description": "A simple offline-first synchronisation framework, to synchronize data of Qt applications between devices.",
4 | "modules": [ "QtDataSync", "QtDataSyncAndroid", "QtDataSyncIos" ],
5 | "dependencies": [
6 | ".skycoder42.jsonserializer",
7 | ".skycoder42.service"
8 | ],
9 | "excludes": [ "wasm", "msvc2015" ],
10 | "license": {
11 | "name": "BSD-3-Clause",
12 | "path": "LICENSE"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/imports/datasync/qtdatasync_plugin.h:
--------------------------------------------------------------------------------
1 | #ifndef QTDATASYNC_PLUGIN_H
2 | #define QTDATASYNC_PLUGIN_H
3 |
4 | #include
5 |
6 | class QtDataSyncDeclarativeModule : public QQmlExtensionPlugin
7 | {
8 | Q_OBJECT
9 | Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
10 |
11 | public:
12 | QtDataSyncDeclarativeModule(QObject *parent = nullptr);
13 | void registerTypes(const char *uri) override;
14 | };
15 |
16 | #endif // QTDATASYNC_PLUGIN_H
17 |
--------------------------------------------------------------------------------
/src/datasync/conflictresolver_p.h:
--------------------------------------------------------------------------------
1 | #ifndef QTDATASYNC_CONFLICTRESOLVER_P_H
2 | #define QTDATASYNC_CONFLICTRESOLVER_P_H
3 |
4 | #include "qtdatasync_global.h"
5 | #include "conflictresolver.h"
6 |
7 | namespace QtDataSync {
8 |
9 | //no export needed
10 | class ConflictResolverPrivate
11 | {
12 | public:
13 | QString defaultsName;
14 | Logger *logger = nullptr;
15 | QSettings *settings = nullptr;
16 | };
17 |
18 | }
19 |
20 | #endif // QTDATASYNC_CONFLICTRESOLVER_P_H
21 |
--------------------------------------------------------------------------------
/src/datasync/logger_p.h:
--------------------------------------------------------------------------------
1 | #ifndef QTDATASYNC_LOGGER_P_H
2 | #define QTDATASYNC_LOGGER_P_H
3 |
4 | #include "qtdatasync_global.h"
5 | #include "logger.h"
6 |
7 | namespace QtDataSync {
8 |
9 | //no export needed
10 | class LoggerPrivate
11 | {
12 | public:
13 | LoggerPrivate(QString setupName, const QByteArray &subCategory);
14 |
15 | QString setupName;
16 | QByteArray catName;
17 | QLoggingCategory logCat;
18 | };
19 |
20 | }
21 |
22 | #endif // QTDATASYNC_LOGGER_P_H
23 |
--------------------------------------------------------------------------------
/src/plugins/keystores/wincred/wincred.pro:
--------------------------------------------------------------------------------
1 | TARGET = qwincred
2 |
3 | QT += datasync
4 | QT -= gui
5 |
6 | HEADERS += \
7 | wincredkeystoreplugin.h \
8 | wincredkeystore.h
9 |
10 | SOURCES += \
11 | wincredkeystoreplugin.cpp \
12 | wincredkeystore.cpp
13 |
14 | DISTFILES += wincred.json
15 |
16 | LIBS += -ladvapi32
17 |
18 | PLUGIN_TYPE = keystores
19 | PLUGIN_EXTENDS = datasync
20 | PLUGIN_CLASS_NAME = WinCredKeyStorePlugin
21 | load(qt_plugin)
22 |
--------------------------------------------------------------------------------
/src/datasyncandroid/qtdatasyncandroid_global.h:
--------------------------------------------------------------------------------
1 | #ifndef QTDATASYNCANDROID_GLOBAL_H
2 | #define QTDATASYNCANDROID_GLOBAL_H
3 |
4 | #include
5 |
6 | #ifndef QT_STATIC
7 | # if defined(QT_BUILD_DATASYNCANDROID_LIB)
8 | # define Q_DATASYNCANDROID_EXPORT Q_DECL_EXPORT
9 | # else
10 | # define Q_DATASYNCANDROID_EXPORT Q_DECL_IMPORT
11 | # endif
12 | #else
13 | # define Q_DATASYNCANDROID_EXPORT
14 | #endif
15 |
16 | #endif // QTDATASYNCANDROID_GLOBAL_H
17 |
--------------------------------------------------------------------------------
/src/messages/macupdatemessage.cpp:
--------------------------------------------------------------------------------
1 | #include "macupdatemessage_p.h"
2 | using namespace QtDataSync;
3 |
4 | MacUpdateMessage::MacUpdateMessage(quint32 keyIndex, QByteArray cmac) :
5 | keyIndex{keyIndex},
6 | cmac{std::move(cmac)}
7 | {}
8 |
9 | const QMetaObject *MacUpdateMessage::getMetaObject() const
10 | {
11 | return &staticMetaObject;
12 | }
13 |
14 |
15 |
16 | const QMetaObject *MacUpdateAckMessage::getMetaObject() const
17 | {
18 | return &staticMetaObject;
19 | }
20 |
--------------------------------------------------------------------------------
/examples/datasync/IosSync/syncdelegate.cpp:
--------------------------------------------------------------------------------
1 | #include "syncdelegate.h"
2 | #include
3 |
4 | SyncDelegate::SyncDelegate(QObject *parent) :
5 | IosSyncDelegate{parent}
6 | {}
7 |
8 | //! [delegate_src]
9 | QtDataSync::IosSyncDelegate::SyncResult SyncDelegate::onSyncCompleted(QtDataSync::SyncManager::SyncState state)
10 | {
11 | qInfo() << "Finished synchronization in state:" << state;
12 | return IosSyncDelegate::onSyncCompleted(state);
13 | }
14 | //! [delegate_src]
15 |
--------------------------------------------------------------------------------
/tests/auto/qml/TestQmlDataSync/TestQmlDataSync.pro:
--------------------------------------------------------------------------------
1 | TEMPLATE = app
2 | TARGET = tst_qmldatasync
3 | CONFIG += qmltestcase
4 | CONFIG += console
5 | SOURCES += tst_qmldatasync.cpp
6 |
7 | QT += datasync
8 |
9 | importFiles.path = .
10 | DEPLOYMENT += importFiles
11 |
12 | DISTFILES += \
13 | tst_qmldatasync.qml
14 |
15 | DEFINES += SRCDIR=\\\"$$_PRO_FILE_PWD_/\\\"
16 |
17 | win32:msvc:CONFIG(debug, debug|release): CONFIG += disable_testrun
18 | include($$PWD/../../testrun.pri)
19 |
--------------------------------------------------------------------------------
/tests/auto/datasync/TestLib/testdata.h:
--------------------------------------------------------------------------------
1 | #ifndef TESTDATA_H
2 | #define TESTDATA_H
3 |
4 | #include
5 |
6 | class TestData
7 | {
8 | Q_GADGET
9 |
10 | Q_PROPERTY(int id MEMBER id USER true)
11 | Q_PROPERTY(QString text MEMBER text)
12 |
13 | public:
14 | TestData(int id = -1, QString text = {});
15 |
16 | bool operator ==(const TestData &other) const;
17 |
18 | int id;
19 | QString text;
20 | };
21 |
22 | Q_DECLARE_METATYPE(TestData)
23 |
24 | #endif // TESTDATA_H
25 |
--------------------------------------------------------------------------------
/src/datasync/changeemitter_p.rep:
--------------------------------------------------------------------------------
1 | #include "qtdatasync_global.h"
2 | #include "objectkey.h"
3 |
4 | class ChangeEmitter {
5 | SLOT(void triggerRemoteChange(const QtDataSync::ObjectKey &key, bool deleted, bool changed));
6 | SLOT(void triggerRemoteClear(const QByteArray &typeName, const QStringList &ids));
7 | SLOT(void triggerRemoteReset());
8 | SLOT(void triggerUpload());
9 |
10 | SIGNAL(remoteDataChanged(const QtDataSync::ObjectKey &key, bool deleted));
11 | SIGNAL(remoteDataResetted());
12 | };
13 |
--------------------------------------------------------------------------------
/src/datasyncios/datasyncios.pro:
--------------------------------------------------------------------------------
1 | TARGET = QtDataSyncIos
2 |
3 | QT = core datasync datasync-private
4 | CONFIG += no_app_extension_api_only
5 |
6 | HEADERS += \
7 | qtdatasyncios_global.h \
8 | qtdatasyncappdelegate_capi_p.h \
9 | QIOSApplicationDelegate+QtDatasyncAppDelegate_p.h \
10 | iossyncdelegate.h \
11 | iossyncdelegate_p.h
12 |
13 | SOURCES += \
14 | iossyncdelegate.cpp
15 |
16 | OBJECTIVE_SOURCES += \
17 | QIOSApplicationDelegate+QtDatasyncAppDelegate.mm
18 |
19 | load(qt_module)
20 |
--------------------------------------------------------------------------------
/src/messages/removemessage.cpp:
--------------------------------------------------------------------------------
1 | #include "removemessage_p.h"
2 | using namespace QtDataSync;
3 |
4 | RemoveMessage::RemoveMessage(QUuid deviceId) :
5 | deviceId{deviceId}
6 | {}
7 |
8 | const QMetaObject *RemoveMessage::getMetaObject() const
9 | {
10 | return &staticMetaObject;
11 | }
12 |
13 |
14 |
15 | RemoveAckMessage::RemoveAckMessage(QUuid deviceId) :
16 | deviceId{deviceId}
17 | {}
18 |
19 | const QMetaObject *RemoveAckMessage::getMetaObject() const
20 | {
21 | return &staticMetaObject;
22 | }
23 |
--------------------------------------------------------------------------------
/qtdatasync.pro:
--------------------------------------------------------------------------------
1 | load(qt_parts)
2 |
3 | SUBDIRS += doc
4 |
5 | doxygen.target = doxygen
6 | doxygen.CONFIG = recursive
7 | doxygen.recurse_target = doxygen
8 | doxygen.recurse += doc
9 | QMAKE_EXTRA_TARGETS += doxygen
10 |
11 | runtests.target = run-tests
12 | runtests.CONFIG = recursive
13 | runtests.recurse_target = run-tests
14 | runtests.recurse += sub_tests sub_src sub_tools
15 | QMAKE_EXTRA_TARGETS += runtests
16 |
17 | include(modeling/modeling.pri)
18 |
19 | DISTFILES += .qmake.conf \
20 | sync.profile
21 |
--------------------------------------------------------------------------------
/examples/datasync/IosSync/syncdelegate.h:
--------------------------------------------------------------------------------
1 | #ifndef SYNCDELEGATE_H
2 | #define SYNCDELEGATE_H
3 |
4 | #include
5 | #include
6 |
7 | //! [delegate_hdr]
8 | class SyncDelegate : public QtDataSync::IosSyncDelegate
9 | {
10 | Q_OBJECT
11 |
12 | public:
13 | explicit SyncDelegate(QObject *parent = nullptr);
14 |
15 | protected:
16 | SyncResult onSyncCompleted(QtDataSync::SyncManager::SyncState state) override;
17 | };
18 | //! [delegate_hdr]
19 |
20 | #endif // SYNCDELEGATE_H
21 |
--------------------------------------------------------------------------------
/src/datasyncandroid/androidbackgroundservice_p.h:
--------------------------------------------------------------------------------
1 | #ifndef QTDATASYNC_ANDROIDBACKGROUNDSERVICE_P_H
2 | #define QTDATASYNC_ANDROIDBACKGROUNDSERVICE_P_H
3 |
4 | #include "androidbackgroundservice.h"
5 |
6 | #include
7 |
8 | namespace QtDataSync {
9 |
10 | class AndroidBackgroundServicePrivate
11 | {
12 | public:
13 | SyncManager *manager = nullptr;
14 | int startId = -1;
15 |
16 | bool waitFullSync = true;
17 | };
18 |
19 | }
20 |
21 | #endif // QTDATASYNC_ANDROIDBACKGROUNDSERVICE_P_H
22 |
--------------------------------------------------------------------------------
/src/messages/devicekeysmessage.cpp:
--------------------------------------------------------------------------------
1 | #include "devicekeysmessage_p.h"
2 | using namespace QtDataSync;
3 |
4 | DeviceKeysMessage::DeviceKeysMessage(quint32 keyIndex) :
5 | keyIndex{keyIndex},
6 | duplicated{true}
7 | {}
8 |
9 | DeviceKeysMessage::DeviceKeysMessage(quint32 keyIndex, QList devices) :
10 | keyIndex{keyIndex},
11 | duplicated{false},
12 | devices{std::move(devices)}
13 | {}
14 |
15 | const QMetaObject *DeviceKeysMessage::getMetaObject() const
16 | {
17 | return &staticMetaObject;
18 | }
19 |
--------------------------------------------------------------------------------
/src/plugins/keystores/keychain/keychain.pro:
--------------------------------------------------------------------------------
1 | TARGET = qkeychain
2 |
3 | QT += datasync
4 | QT -= gui
5 |
6 | HEADERS += \
7 | keychainkeystoreplugin.h \
8 | keychainkeystore.h
9 |
10 | SOURCES += \
11 | keychainkeystoreplugin.cpp
12 |
13 | OBJECTIVE_SOURCES += \
14 | keychainkeystore.mm
15 |
16 | DISTFILES += keychain.json
17 |
18 | LIBS += -framework Foundation -framework Security
19 |
20 | PLUGIN_TYPE = keystores
21 | PLUGIN_EXTENDS = datasync
22 | PLUGIN_CLASS_NAME = KeychainKeyStorePlugin
23 | load(qt_plugin)
24 |
--------------------------------------------------------------------------------
/tools/appserver/dockerbuild/env_start.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | echo "[server]" > $QDSAPP_CONFIG_FILE
4 | echo "port=4242" >> $QDSAPP_CONFIG_FILE
5 | echo "[database]" >> $QDSAPP_CONFIG_FILE
6 | echo "host=$QDSAPP_DATABASE_HOST" >> $QDSAPP_CONFIG_FILE
7 | echo "port=$QDSAPP_DATABASE_PORT" >> $QDSAPP_CONFIG_FILE
8 | echo "username=$QDSAPP_DATABASE_USER" >> $QDSAPP_CONFIG_FILE
9 | echo "password=$QDSAPP_DATABASE_PASSWORD" >> $QDSAPP_CONFIG_FILE
10 | echo "name=$QDSAPP_DATABASE_NAME" >> $QDSAPP_CONFIG_FILE
11 |
12 | exec /usr/bin/qdsappd
13 |
--------------------------------------------------------------------------------
/src/messages/changemessage.cpp:
--------------------------------------------------------------------------------
1 | #include "changemessage_p.h"
2 | using namespace QtDataSync;
3 |
4 | ChangeMessage::ChangeMessage(QByteArray dataId) :
5 | dataId{std::move(dataId)}
6 | {}
7 |
8 | const QMetaObject *ChangeMessage::getMetaObject() const
9 | {
10 | return &staticMetaObject;
11 | }
12 |
13 |
14 |
15 | ChangeAckMessage::ChangeAckMessage(const ChangeMessage &message) :
16 | dataId{message.dataId}
17 | {}
18 |
19 | const QMetaObject *ChangeAckMessage::getMetaObject() const
20 | {
21 | return &staticMetaObject;
22 | }
23 |
--------------------------------------------------------------------------------
/sync.profile:
--------------------------------------------------------------------------------
1 | %modules = (
2 | "QtDataSync" => "$basedir/src/datasync;$basedir/src/messages",
3 | "QtDataSyncAndroid" => "$basedir/src/datasyncandroid",
4 | "QtDataSyncIos" => "$basedir/src/datasyncios",
5 | );
6 |
7 | # Force generation of camel case headers for classes inside QtDataSync namespaces
8 | # Exception must be excluded, because it generates conflicts with the std::exception class (case-insensitive)
9 | $publicclassregexp = "QtDataSync::(?!__helpertypes|JsonObject|Exception|QtRoTransportRegistry|QtRoTransportRegistry::__private).+";
10 |
--------------------------------------------------------------------------------
/tools/appserver/qdsapp.conf:
--------------------------------------------------------------------------------
1 | [general]
2 | #threads/count=
3 | #threads/expire=
4 | #livesync=
5 | #cleanup/interval=
6 | #cleanup/auto=
7 | #quota/limit=
8 | #quota/force=
9 | #loglevel=
10 | #logIpAddress=
11 |
12 | [server]
13 | #name=
14 | #host=
15 | #port=
16 | #secret=
17 | #idleTimeout=
18 | #uploads/limit=
19 | #downloads/limit=
20 | #downloads/threshold=
21 | #wss=
22 | #wss/pfx=
23 | #wss/pass=
24 |
25 | [database]
26 | #driver=
27 | #name=
28 | #host=
29 | #port=
30 | #username=
31 | #password=
32 | #options=
33 | #keepaliveInterval=
34 |
--------------------------------------------------------------------------------
/examples/datasync/Sample/sampledata.h:
--------------------------------------------------------------------------------
1 | #ifndef SAMPLEDATA_H
2 | #define SAMPLEDATA_H
3 |
4 | #include
5 | #include
6 |
7 | class SampleData
8 | {
9 | Q_GADGET
10 |
11 | Q_PROPERTY(int id MEMBER id USER true)
12 | Q_PROPERTY(QString title MEMBER title)
13 | Q_PROPERTY(QString description MEMBER description)
14 |
15 | public:
16 | int id;
17 | QString title;
18 | QString description;
19 | };
20 |
21 | QDebug operator<<(QDebug debug, const SampleData &data);
22 |
23 | Q_DECLARE_METATYPE(SampleData)
24 |
25 | #endif // SAMPLEDATA_H
26 |
--------------------------------------------------------------------------------
/tests/auto/datasync/TestSyncController/testresolver.h:
--------------------------------------------------------------------------------
1 | #ifndef TESTRESOLVER_H
2 | #define TESTRESOLVER_H
3 |
4 | #include
5 | #include
6 |
7 | #include "testdata.h"
8 |
9 | class TestResolver : public QtDataSync::GenericConflictResolver
10 | {
11 | Q_OBJECT
12 |
13 | public:
14 | explicit TestResolver(QObject *parent = nullptr);
15 |
16 | TestData resolveConflict(TestData data1, TestData data2, QObject *parent) const override;
17 |
18 | bool shouldThrow = false;
19 | };
20 |
21 | #endif // TESTRESOLVER_H
22 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # C++ objects and libs
2 |
3 | *.slo
4 | *.lo
5 | *.o
6 | *.a
7 | *.la
8 | *.lai
9 | *.so
10 | *.dll
11 | *.dylib
12 |
13 | # Qt-es
14 |
15 | /.qmake.cache
16 | /.qmake.stash
17 | *.pro.user
18 | *.pro.user.*
19 | *.qbs.user
20 | *.qbs.user.*
21 | *.moc
22 | moc_*.cpp
23 | qrc_*.cpp
24 | ui_*.h
25 | Makefile*
26 | *build-*
27 | *.qmlc
28 |
29 | # QtCreator
30 |
31 | *.autosave
32 |
33 | # QtCtreator Qml
34 | *.qmlproject.user
35 | *.qmlproject.user.*
36 |
37 | # QtCtreator CMake
38 | CMakeLists.txt.user
39 |
40 | *.json.user
41 | .qpmx-dev-cache
42 |
43 |
--------------------------------------------------------------------------------
/src/plugins/keystores/secretservice/secretservice.pro:
--------------------------------------------------------------------------------
1 | TARGET = qsecretservice
2 |
3 | QT += datasync
4 | QT -= gui
5 |
6 | CONFIG += link_pkgconfig
7 | PKGCONFIG += libsecret-1
8 |
9 | HEADERS += \
10 | libsecretwrapper.h \
11 | secretservicekeystore.h \
12 | secretservicekeystoreplugin.h
13 |
14 | SOURCES += \
15 | libsecretwrapper.cpp \
16 | secretservicekeystore.cpp \
17 | secretservicekeystoreplugin.cpp
18 |
19 | DISTFILES += \
20 | secretservice.json
21 |
22 | PLUGIN_TYPE = keystores
23 | PLUGIN_EXTENDS = datasync
24 | PLUGIN_CLASS_NAME = GSecretKeyStorePlugin
25 | load(qt_plugin)
26 |
--------------------------------------------------------------------------------
/tests/auto/datasync/TestLib/testobject.h:
--------------------------------------------------------------------------------
1 | #ifndef TESTOBJECT_H
2 | #define TESTOBJECT_H
3 |
4 | #include
5 |
6 | class TestObject : public QObject
7 | {
8 | Q_OBJECT
9 |
10 | Q_PROPERTY(int id MEMBER id NOTIFY idChanged USER true)
11 | Q_PROPERTY(QString text MEMBER text NOTIFY textChanged)
12 |
13 | public:
14 | Q_INVOKABLE TestObject(QObject *parent = nullptr);
15 |
16 | int id;
17 | QString text;
18 |
19 | bool equals(const TestObject *other) const;
20 |
21 | signals:
22 | void idChanged(int id);
23 | void textChanged(QString text);
24 | };
25 |
26 | #endif // TESTOBJECT_H
27 |
--------------------------------------------------------------------------------
/examples/datasync/AndroidSync/AndroidSync.pro:
--------------------------------------------------------------------------------
1 | TEMPLATE = app
2 |
3 | QT += quick datasync datasyncandroid
4 | CONFIG += c++14
5 |
6 | TARGET = AndroidSync
7 |
8 | HEADERS += \
9 | syncservice.h
10 |
11 | SOURCES += \
12 | main.cpp \
13 | syncservice.cpp
14 |
15 | RESOURCES += qml.qrc
16 |
17 | target.path = $$[QT_INSTALL_EXAMPLES]/datasync/$$TARGET
18 | !install_ok: INSTALLS += target
19 |
20 | DISTFILES += \
21 | android/AndroidManifest.xml \
22 | $$files(android/src/*, true) \
23 | $$files(android/res/*, true) \
24 | android/build.gradle
25 |
26 | ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android
27 |
--------------------------------------------------------------------------------
/src/datasync/syncmanager_p.rep:
--------------------------------------------------------------------------------
1 | #include "qtdatasync_global.h"
2 | #include "syncmanager.h"
3 |
4 | class SyncManagerPrivate {
5 | PROP(QString setupName READONLY)
6 | PROP(bool syncEnabled=true);
7 | PROP(QtDataSync::SyncManager::SyncState syncState=QtDataSync::SyncManager::Initializing READONLY);
8 | PROP(qreal syncProgress=-1.0 READONLY);
9 | PROP(QString lastError READONLY);
10 |
11 | SLOT(void synchronize());
12 | SLOT(void reconnect());
13 |
14 | SLOT(void runOnState(QUuid id, bool downloadOnly, bool triggerSync));
15 | SIGNAL(stateReached(QUuid id, QtDataSync::SyncManager::SyncState syncState));
16 | };
17 |
--------------------------------------------------------------------------------
/src/messages/welcomemessage.cpp:
--------------------------------------------------------------------------------
1 | #include "welcomemessage_p.h"
2 | using namespace QtDataSync;
3 |
4 | WelcomeMessage::WelcomeMessage(bool hasChanges) :
5 | hasChanges{hasChanges}
6 | {}
7 |
8 | bool WelcomeMessage::hasKeyUpdate() const
9 | {
10 | return !key.isEmpty();
11 | }
12 |
13 | QByteArray WelcomeMessage::signatureData(QUuid deviceId) const
14 | {
15 | // keyIndex, scheme, deviceId, key
16 | return QByteArray::number(keyIndex) +
17 | scheme +
18 | deviceId.toRfc4122() +
19 | key;
20 | }
21 |
22 | const QMetaObject *WelcomeMessage::getMetaObject() const
23 | {
24 | return &staticMetaObject;
25 | }
26 |
--------------------------------------------------------------------------------
/src/java/java.pro:
--------------------------------------------------------------------------------
1 | TEMPLATE = aux
2 |
3 | CONFIG -= qt android_install
4 |
5 | javaresources.files = \
6 | $$PWD/res \
7 | $$PWD/src
8 |
9 | javaresources.path = $$[QT_INSTALL_PREFIX]/src/android/java
10 |
11 | INSTALLS += javaresources
12 |
13 | !prefix_build:!equals(OUT_PWD, $$PWD) {
14 | RETURN = $$escape_expand(\\n\\t)
15 | equals(QMAKE_HOST.os, Windows) {
16 | RETURN = $$escape_expand(\\r\\n\\t)
17 | }
18 | OUT_PATH = $$shell_path($$OUT_PWD)
19 |
20 | QMAKE_POST_LINK += \
21 | $${QMAKE_COPY_DIR} $$shell_path($$PWD/res) $$OUT_PATH $$RETURN \
22 | $${QMAKE_COPY_DIR} $$shell_path($$PWD/src) $$OUT_PATH
23 | }
24 |
--------------------------------------------------------------------------------
/src/messages/keychangemessage_p.h:
--------------------------------------------------------------------------------
1 | #ifndef QTDATASYNC_KEYCHANGEMESSAGE_P_H
2 | #define QTDATASYNC_KEYCHANGEMESSAGE_P_H
3 |
4 | #include "message_p.h"
5 |
6 | namespace QtDataSync {
7 |
8 | class Q_DATASYNC_EXPORT KeyChangeMessage : public Message
9 | {
10 | Q_GADGET
11 |
12 | Q_PROPERTY(quint32 nextIndex MEMBER nextIndex)
13 |
14 | public:
15 | KeyChangeMessage(quint32 nextIndex = 0);
16 |
17 | quint32 nextIndex;
18 |
19 | protected:
20 | const QMetaObject *getMetaObject() const override;
21 | };
22 |
23 | }
24 |
25 | Q_DECLARE_METATYPE(QtDataSync::KeyChangeMessage)
26 |
27 | #endif // QTDATASYNC_KEYCHANGEMESSAGE_P_H
28 |
--------------------------------------------------------------------------------
/tests/auto/datasync/TestLib/mockserver.h:
--------------------------------------------------------------------------------
1 | #ifndef MOCKSERVER_H
2 | #define MOCKSERVER_H
3 |
4 | #include
5 | #include
6 | #include
7 |
8 | #include "mockconnection.h"
9 |
10 | class MockServer : public QObject
11 | {
12 | Q_OBJECT
13 |
14 | public:
15 | explicit MockServer(QObject *parent = nullptr);
16 |
17 | void init();
18 | QUrl url() const;
19 |
20 | void clear();
21 | bool waitForConnected(MockConnection **connection, int timeout = 5000);
22 |
23 | private:
24 | QWebSocketServer *_server;
25 |
26 | QSignalSpy _connectedSpy;
27 | };
28 |
29 |
30 | #endif // MOCKSERVER_H
31 |
--------------------------------------------------------------------------------
/examples/datasync/AndroidSync/syncservice.h:
--------------------------------------------------------------------------------
1 | #ifndef SYNCSERVICE_H
2 | #define SYNCSERVICE_H
3 |
4 | #include
5 |
6 | //! [droid_service_hdr]
7 | class SyncService : public QtDataSync::AndroidBackgroundService
8 | {
9 | Q_OBJECT
10 |
11 | public:
12 | explicit SyncService(int &argc, char **argv);
13 |
14 | protected:
15 | void prepareSetup(QtDataSync::Setup &setup) override;
16 | void onSyncCompleted(QtDataSync::SyncManager::SyncState state) override;
17 | QAndroidJniObject createForegroundNotification() override;
18 | };
19 | //! [droid_service_hdr]
20 |
21 | #endif // SYNCSERVICE_H
22 |
--------------------------------------------------------------------------------
/examples/datasync/IosSync/main.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.10
2 | import QtQuick.Controls 2.4
3 | import QtQuick.Layouts 1.3
4 | import QtQuick.Window 2.10
5 | import de.skycoder42.QtDataSync 4.2
6 |
7 | Window {
8 | visible: true
9 | width: 640
10 | height: 480
11 | title: qsTr("Hello World")
12 |
13 | property IosSyncDelegate syncDelegate: IosSyncSingleton.delegate
14 |
15 | ColumnLayout {
16 | anchors.centerIn: parent
17 |
18 | CheckBox {
19 | id: cBox
20 | checked: syncDelegate.enabled
21 | onCheckedChanged: syncDelegate.enabled = cBox.checked
22 |
23 | text: qsTr("Background sync active")
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/datasync/rothreadedbackend/exchangerotransport_p.h:
--------------------------------------------------------------------------------
1 | #ifndef THREADEDCLIENT_P_H
2 | #define THREADEDCLIENT_P_H
3 |
4 | #include "qtdatasync_global.h"
5 | #include "qtrotransportregistry.h"
6 |
7 | namespace QtDataSync {
8 |
9 | class ThreadedQtRoServer : public QtRoTransportRegistry::Server
10 | {
11 | public:
12 | bool prepareHostNode(const QUrl &url, QRemoteObjectHostBase *host) override;
13 | };
14 |
15 | class ThreadedQtRoClient : public QtRoTransportRegistry::Client
16 | {
17 | public:
18 | bool prepareClientNode(const QUrl &url, QRemoteObjectNode *node) override;
19 | };
20 |
21 | }
22 |
23 | #endif // THREADEDCLIENT_P_H
24 |
--------------------------------------------------------------------------------
/tests/ci/setup.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -e
3 |
4 | scriptdir=$(dirname $0)
5 |
6 | # get postgres running for ws test
7 | if [[ $PLATFORM == "gcc_64" ]]; then
8 | sudo docker run -d --rm --name datasync_postgres -e "POSTGRES_PASSWORD=baum42" postgres:latest
9 |
10 | postgresIp=$(sudo docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' datasync_postgres)
11 | echo host=$postgresIp >> ./tests/ci/qdsapp.conf
12 | echo 'SETUP_FILE=$$PWD/../../../ci/qdsapp.conf' > ./tests/auto/datasync/TestAppServer/setup.pri
13 | echo 'SETUP_FILE=$$PWD/../../../ci/qdsapp.conf' > ./tests/auto/datasync/IntegrationTest/setup.pri
14 | fi
15 |
--------------------------------------------------------------------------------
/src/3rdparty/cryptopp/appveyor.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 |
3 | set version=7_0_0
4 |
5 | echo %PLATFORM% | findstr /C:"winrt_x64" > nul && (
6 | set pkgName=%PLATFORM:~10%_64
7 | )
8 | echo %PLATFORM% | findstr /C:"winrt_x86" > nul && (
9 | set pkgName=%PLATFORM:~10%
10 | )
11 | if "%PLATFORM%" == "mingw53_32" (
12 | set pkgName=mingw
13 | )
14 | if "%pkgName%" == "" (
15 | set pkgName=%PLATFORM%
16 | )
17 |
18 | powershell -Command "Invoke-WebRequest https://github.com/Skycoder42/ci-builds/releases/download/cryptopp_%version%/cryptopp_%version%_%pkgName%.zip -OutFile %temp%\cryptopp.zip" || exit /B 1
19 | 7z x %temp%\cryptopp.zip -o.\src\3rdparty || exit /B 1
20 |
--------------------------------------------------------------------------------
/src/src.pro:
--------------------------------------------------------------------------------
1 | TEMPLATE = subdirs
2 |
3 | SUBDIRS += \
4 | datasync \
5 | plugins \
6 | imports \
7 | messages \
8 | 3rdparty \
9 | translations
10 |
11 | messages.depends += 3rdparty
12 | datasync.depends += messages 3rdparty
13 | plugins.depends += datasync
14 | imports.depends += datasync
15 |
16 | android {
17 | SUBDIRS += datasyncandroid
18 | !android-embedded: SUBDIRS += java
19 |
20 | datasyncandroid.depends += datasync java
21 | imports.depends += datasyncandroid
22 | }
23 |
24 | ios {
25 | SUBDIRS += datasyncios
26 |
27 | datasyncios.depends += datasync
28 | imports.depends += datasyncios
29 | }
30 |
31 | QMAKE_EXTRA_TARGETS += run-tests
32 |
--------------------------------------------------------------------------------
/examples/datasync/IosSync/main.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include "syncdelegate.h"
4 |
5 | //! [delegate_main]
6 | int main(int argc, char *argv[])
7 | {
8 | QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
9 | QGuiApplication app(argc, argv);
10 |
11 | QtDataSync::IosSyncDelegate::init(new SyncDelegate{&app});
12 | QtDataSync::IosSyncDelegate::currentDelegate()->setEnabled(true);
13 |
14 | // ...
15 | //! [delegate_main]
16 | QQmlApplicationEngine engine;
17 | engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
18 | if (engine.rootObjects().isEmpty())
19 | return -1;
20 |
21 | return app.exec();
22 | }
23 |
--------------------------------------------------------------------------------
/src/messages/devicechangemessage.cpp:
--------------------------------------------------------------------------------
1 | #include "devicechangemessage_p.h"
2 | using namespace QtDataSync;
3 |
4 | DeviceChangeMessage::DeviceChangeMessage(QByteArray dataId, QUuid deviceId) :
5 | ChangeMessage{std::move(dataId)},
6 | deviceId{deviceId}
7 | {}
8 |
9 | const QMetaObject *DeviceChangeMessage::getMetaObject() const
10 | {
11 | return &staticMetaObject;
12 | }
13 |
14 |
15 |
16 | DeviceChangeAckMessage::DeviceChangeAckMessage(const DeviceChangeMessage &message) :
17 | ChangeAckMessage{message},
18 | deviceId{message.deviceId}
19 | {}
20 |
21 | const QMetaObject *DeviceChangeAckMessage::getMetaObject() const
22 | {
23 | return &staticMetaObject;
24 | }
25 |
--------------------------------------------------------------------------------
/src/datasync/signal_private_connect_p.h:
--------------------------------------------------------------------------------
1 | #ifndef QTDATASYNC_SIGNAL_PRIVATE_CONNECT_P_H
2 | #define QTDATASYNC_SIGNAL_PRIVATE_CONNECT_P_H
3 |
4 | #include
5 |
6 | #define EXTEND(a, x, ...) [a](auto... args) { \
7 | (a->*(x))(args..., __VA_ARGS__); \
8 | }
9 |
10 | #define EXTEND_NULL(a, x, ...) [a]() { \
11 | (a->*(x))(__VA_ARGS__); \
12 | }
13 |
14 | #define PSIG(x) EXTEND(this, x, QPrivateSignal{})
15 |
16 | #define PSIG_NULL(x) EXTEND_NULL(this, x, QPrivateSignal{})
17 |
18 | #if __cplusplus >= 201402L
19 | #define LAMBDA_MV(x) x = std::move(x)
20 | #else
21 | #define LAMBDA_MV(x) x
22 | #endif
23 |
24 | #endif // QTDATASYNC_SIGNAL_PRIVATE_CONNECT_P_H
25 |
--------------------------------------------------------------------------------
/src/datasyncandroid/androidsynccontrol_p.h:
--------------------------------------------------------------------------------
1 | #ifndef QTDATASYNC_ANDROIDSYNCCONTROL_P_H
2 | #define QTDATASYNC_ANDROIDSYNCCONTROL_P_H
3 |
4 | #include "androidsynccontrol.h"
5 |
6 | #include
7 | #include
8 |
9 | namespace QtDataSync {
10 |
11 | class AndroidSyncControlPrivate
12 | {
13 | public:
14 | QString serviceId {QStringLiteral("de.skycoder42.qtservice.AndroidService")};
15 | std::chrono::minutes interval{60};
16 |
17 | QAndroidIntent createIntent() const;
18 | QAndroidJniObject createPendingIntent(bool allowCreate) const;
19 | };
20 |
21 | }
22 |
23 | #endif // QTDATASYNC_ANDROIDSYNCCONTROL_P_H
24 |
--------------------------------------------------------------------------------
/src/messages/accountmessage_p.h:
--------------------------------------------------------------------------------
1 | #ifndef QTDATASYNC_ACCOUNTMESSAGE_P_H
2 | #define QTDATASYNC_ACCOUNTMESSAGE_P_H
3 |
4 | #include
5 |
6 | #include
7 |
8 | #include "message_p.h"
9 |
10 | namespace QtDataSync {
11 |
12 | class Q_DATASYNC_EXPORT AccountMessage : public Message
13 | {
14 | Q_GADGET
15 |
16 | Q_PROPERTY(QUuid deviceId MEMBER deviceId)
17 |
18 | public:
19 | AccountMessage(QUuid deviceId = {});
20 |
21 | QUuid deviceId;
22 |
23 | protected:
24 | const QMetaObject *getMetaObject() const override;
25 | };
26 |
27 | }
28 |
29 | Q_DECLARE_METATYPE(QtDataSync::AccountMessage)
30 |
31 | #endif // QTDATASYNC_ACCOUNTMESSAGE_P_H
32 |
--------------------------------------------------------------------------------
/src/datasync/remoteconfig_p.h:
--------------------------------------------------------------------------------
1 | #ifndef QTDATASYNC_REMOTECONFIG_P_H
2 | #define QTDATASYNC_REMOTECONFIG_P_H
3 |
4 | #include "qtdatasync_global.h"
5 | #include "remoteconfig.h"
6 |
7 | namespace QtDataSync {
8 |
9 | //no export needed
10 | class RemoteConfigPrivate : public QSharedData
11 | {
12 | public:
13 | RemoteConfigPrivate(QUrl url,
14 | QString accessKey,
15 | RemoteConfig::HeaderHash headers,
16 | int keepaliveTimeout);
17 | RemoteConfigPrivate(const RemoteConfigPrivate &other);
18 |
19 | QUrl url;
20 | QString accessKey;
21 | RemoteConfig::HeaderHash headers;
22 | int keepaliveTimeout;
23 | };
24 |
25 | }
26 |
27 | #endif // QTDATASYNC_REMOTECONFIG_P_H
28 |
--------------------------------------------------------------------------------
/doc/doc.pro:
--------------------------------------------------------------------------------
1 | TEMPLATE = aux
2 |
3 | OTHER_FILES += Doxyfile \
4 | makedoc.sh \
5 | doxme.py \
6 | ../README.md \
7 | *.dox \
8 | snippets/*.cpp \
9 | images/*
10 |
11 | system($$QMAKE_MKDIR $$shell_quote($$shell_path($$OUT_PWD/qtdatasync)))
12 |
13 | docTarget.target = doxygen
14 | docTarget.commands = $$PWD/makedoc.sh "$$PWD" "$$MODULE_VERSION" "$$[QT_INSTALL_BINS]" "$$[QT_INSTALL_HEADERS]" "$$[QT_INSTALL_DOCS]"
15 | QMAKE_EXTRA_TARGETS += docTarget
16 |
17 | docInst1.path = $$[QT_INSTALL_DOCS]
18 | docInst1.files = $$OUT_PWD/qtdatasync.qch
19 | docInst1.CONFIG += no_check_exist
20 | docInst2.path = $$[QT_INSTALL_DOCS]
21 | docInst2.files = $$OUT_PWD/qtdatasync
22 | INSTALLS += docInst1 docInst2
23 |
--------------------------------------------------------------------------------
/src/datasync/datastore_p.h:
--------------------------------------------------------------------------------
1 | #ifndef QTDATASYNC_DATASTORE_P_H
2 | #define QTDATASYNC_DATASTORE_P_H
3 |
4 | #include
5 |
6 | #include "qtdatasync_global.h"
7 | #include "datastore.h"
8 | #include "defaults.h"
9 | #include "logger.h"
10 | #include "localstore_p.h"
11 |
12 | namespace QtDataSync {
13 |
14 | //no export needed
15 | class DataStorePrivate
16 | {
17 | public:
18 | DataStorePrivate(DataStore *q, const QString &setupName);
19 |
20 | QByteArray typeName(int metaTypeId) const;
21 |
22 | Defaults defaults;
23 | Logger *logger;
24 | QPointer serializer;
25 |
26 | LocalStore *store;
27 | };
28 |
29 | }
30 |
31 | #endif // QTDATASYNC_DATASTORE_P_H
32 |
--------------------------------------------------------------------------------
/src/plugins/keystores/plain/plainkeystoreplugin.h:
--------------------------------------------------------------------------------
1 | #ifndef PLAINKEYSTOREPLUGIN_H
2 | #define PLAINKEYSTOREPLUGIN_H
3 |
4 | #include
5 |
6 | class PlainKeyStorePlugin : public QObject, public QtDataSync::KeyStorePlugin
7 | {
8 | Q_OBJECT
9 | Q_PLUGIN_METADATA(IID QtDataSync_KeyStorePlugin_Iid FILE "plain.json")
10 | Q_INTERFACES(QtDataSync::KeyStorePlugin)
11 |
12 | public:
13 | PlainKeyStorePlugin(QObject *parent = nullptr);
14 |
15 | bool keystoreAvailable(const QString &provider) const override;
16 | QtDataSync::KeyStore *createInstance(const QString &provider, const QtDataSync::Defaults &defaults, QObject *parent) override;
17 | };
18 |
19 | #endif // PLAINKEYSTOREPLUGIN_H
20 |
--------------------------------------------------------------------------------
/examples/datasync/Sample/docker-compose.yaml:
--------------------------------------------------------------------------------
1 | version: '2.2'
2 | services:
3 | datasync_postgres:
4 | container_name: datasync_postgres
5 | image: postgres:latest
6 | environment:
7 | POSTGRES_PASSWORD: baum42
8 | PGDATA: /var/lib/postgresql/data/pgdata
9 | volumes:
10 | - datasync_postgres_data:/var/lib/postgresql/data/pgdata
11 | datasync_qdsapp:
12 | container_name: datasync_qdsapp
13 | image: skycoder42/qdsapp:latest
14 | depends_on:
15 | - datasync_postgres
16 | ports:
17 | - "4242:4242/tcp"
18 | environment:
19 | QDSAPP_DATABASE_HOST: datasync_postgres
20 | QDSAPP_DATABASE_PASSWORD: baum42
21 | volumes:
22 | datasync_postgres_data:
23 |
--------------------------------------------------------------------------------
/tools/appserver/qdsapp.service.in:
--------------------------------------------------------------------------------
1 | [Unit]
2 | Description=QtDataSync AppServer Service
3 | Documentation=https://github.com/Skycoder42/QtDataSync
4 | After=network-online.target $${APPNAME}.socket
5 |
6 | [Service]
7 | Type=notify
8 | NotifyAccess=exec
9 | ExecStart=$$[QT_INSTALL_BINS]/$${TARGET} --backend systemd
10 | ExecReload=$$[QT_INSTALL_BINS]/$${TARGET} --backend systemd reload $MAINPID
11 | ExecStop=$$[QT_INSTALL_BINS]/$${TARGET} --backend systemd stop $MAINPID
12 | WatchdogSec=10
13 | Restart=on-abnormal
14 | RuntimeDirectory=$${APPNAME}
15 |
16 | [Install]
17 | # Use the following for a system service
18 | #WantedBy=multi-user.target
19 | # Use the following for a user service
20 | #WantedBy=default.target
21 |
--------------------------------------------------------------------------------
/src/plugins/keystores/android/androidkeystoreplugin.h:
--------------------------------------------------------------------------------
1 | #ifndef ANDROIDKEYSTOREPLUGIN_H
2 | #define ANDROIDKEYSTOREPLUGIN_H
3 |
4 | #include
5 |
6 | class AndroidKeyStorePlugin : public QObject, public QtDataSync::KeyStorePlugin
7 | {
8 | Q_OBJECT
9 | Q_PLUGIN_METADATA(IID QtDataSync_KeyStorePlugin_Iid FILE "android.json")
10 | Q_INTERFACES(QtDataSync::KeyStorePlugin)
11 |
12 | public:
13 | AndroidKeyStorePlugin(QObject *parent = nullptr);
14 |
15 | bool keystoreAvailable(const QString &provider) const override;
16 | QtDataSync::KeyStore *createInstance(const QString &provider, const QtDataSync::Defaults &defaults, QObject *parent) override;
17 | };
18 |
19 | #endif // ANDROIDKEYSTOREPLUGIN_H
20 |
--------------------------------------------------------------------------------
/src/plugins/keystores/kwallet/kwalletkeystoreplugin.h:
--------------------------------------------------------------------------------
1 | #ifndef KWALLETKEYSTOREPLUGIN_H
2 | #define KWALLETKEYSTOREPLUGIN_H
3 |
4 | #include
5 |
6 | class KWalletKeyStorePlugin : public QObject, public QtDataSync::KeyStorePlugin
7 | {
8 | Q_OBJECT
9 | Q_PLUGIN_METADATA(IID QtDataSync_KeyStorePlugin_Iid FILE "kwallet.json")
10 | Q_INTERFACES(QtDataSync::KeyStorePlugin)
11 |
12 | public:
13 | KWalletKeyStorePlugin(QObject *parent = nullptr);
14 |
15 | bool keystoreAvailable(const QString &provider) const override;
16 | QtDataSync::KeyStore *createInstance(const QString &provider, const QtDataSync::Defaults &defaults, QObject *parent) override;
17 | };
18 |
19 | #endif // KWALLETKEYSTOREPLUGIN_H
20 |
--------------------------------------------------------------------------------
/examples/datasync/AndroidSync/main.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.10
2 | import QtQuick.Window 2.10
3 | import QtQuick.Controls 2.4
4 | import QtQuick.Layouts 1.3
5 | import de.skycoder42.QtDataSync 4.2
6 |
7 | Window {
8 | visible: true
9 | width: 640
10 | height: 480
11 | title: qsTr("Hello World")
12 |
13 | AndroidSyncControl {
14 | id: syncControl
15 | }
16 |
17 | ColumnLayout {
18 | anchors.centerIn: parent
19 |
20 | CheckBox {
21 | id: cBox
22 | checked: syncControl.enabled
23 | onCheckedChanged: syncControl.enabled = cBox.checked
24 |
25 | text: qsTr("Background sync active")
26 | }
27 |
28 | Button {
29 | text: qsTr("Sync now")
30 | onClicked: syncControl.triggerSyncNow()
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/plugins/keystores/keychain/keychainkeystoreplugin.h:
--------------------------------------------------------------------------------
1 | #ifndef KEYCHAINKEYSTOREPLUGIN_H
2 | #define KEYCHAINKEYSTOREPLUGIN_H
3 |
4 | #include
5 |
6 | class KeychainKeyStorePlugin : public QObject, public QtDataSync::KeyStorePlugin
7 | {
8 | Q_OBJECT
9 | Q_PLUGIN_METADATA(IID QtDataSync_KeyStorePlugin_Iid FILE "keychain.json")
10 | Q_INTERFACES(QtDataSync::KeyStorePlugin)
11 |
12 | public:
13 | KeychainKeyStorePlugin(QObject *parent = nullptr);
14 |
15 | bool keystoreAvailable(const QString &provider) const override;
16 | QtDataSync::KeyStore *createInstance(const QString &provider, const QtDataSync::Defaults &defaults, QObject *parent) override;
17 | };
18 |
19 | #endif // KEYCHAINKEYSTOREPLUGIN_H
20 |
--------------------------------------------------------------------------------
/src/plugins/keystores/wincred/wincredkeystoreplugin.h:
--------------------------------------------------------------------------------
1 | #ifndef WINCREDKEYSTOREPLUGIN_H
2 | #define WINCREDKEYSTOREPLUGIN_H
3 |
4 | #include
5 |
6 | class WinCredKeyStorePlugin : public QObject, public QtDataSync::KeyStorePlugin
7 | {
8 | Q_OBJECT
9 | Q_PLUGIN_METADATA(IID QtDataSync_KeyStorePlugin_Iid FILE "wincred.json")
10 | Q_INTERFACES(QtDataSync::KeyStorePlugin)
11 |
12 | public:
13 | WinCredKeyStorePlugin(QObject *parent = nullptr);
14 |
15 | bool keystoreAvailable(const QString &provider) const override;
16 | QtDataSync::KeyStore *createInstance(const QString &provider, const QtDataSync::Defaults &defaults, QObject *parent) override;
17 | };
18 |
19 | #endif // WINCREDKEYSTOREPLUGIN_H
20 |
--------------------------------------------------------------------------------
/src/plugins/keystores/plain/plainkeystoreplugin.cpp:
--------------------------------------------------------------------------------
1 | #include "plainkeystoreplugin.h"
2 | #include "plainkeystore.h"
3 |
4 | #include
5 |
6 | PlainKeyStorePlugin::PlainKeyStorePlugin(QObject *parent) :
7 | QObject(parent),
8 | KeyStorePlugin()
9 | {}
10 |
11 | bool PlainKeyStorePlugin::keystoreAvailable(const QString &provider) const
12 | {
13 | if(provider == QStringLiteral("plain"))
14 | return true;
15 | else
16 | return false;
17 | }
18 |
19 | QtDataSync::KeyStore *PlainKeyStorePlugin::createInstance(const QString &provider, const QtDataSync::Defaults &defaults, QObject *parent)
20 | {
21 | if(provider == QStringLiteral("plain"))
22 | return new PlainKeyStore(defaults, parent);
23 | else
24 | return nullptr;
25 | }
26 |
--------------------------------------------------------------------------------
/src/plugins/keystores/kwallet/kwalletkeystoreplugin.cpp:
--------------------------------------------------------------------------------
1 | #include "kwalletkeystoreplugin.h"
2 | #include "kwalletkeystore.h"
3 |
4 | KWalletKeyStorePlugin::KWalletKeyStorePlugin(QObject *parent) :
5 | QObject(parent),
6 | KeyStorePlugin()
7 | {}
8 |
9 | QtDataSync::KeyStore *KWalletKeyStorePlugin::createInstance(const QString &provider, const QtDataSync::Defaults &defaults, QObject *parent)
10 | {
11 | if(provider == QStringLiteral("kwallet"))
12 | return new KWalletKeyStore(defaults, parent);
13 | else
14 | return nullptr;
15 | }
16 |
17 | bool KWalletKeyStorePlugin::keystoreAvailable(const QString &provider) const
18 | {
19 | if(provider == QStringLiteral("kwallet"))
20 | return KWallet::Wallet::isEnabled();
21 | else
22 | return false;
23 | }
24 |
--------------------------------------------------------------------------------
/src/datasync/qtdatasync_global.h:
--------------------------------------------------------------------------------
1 | #ifndef QTDATASYNC_GLOBAL_H
2 | #define QTDATASYNC_GLOBAL_H
3 |
4 | #include
5 | #include
6 |
7 | #ifndef QT_STATIC
8 | # if defined(QT_BUILD_DATASYNC_LIB)
9 | # define Q_DATASYNC_EXPORT Q_DECL_EXPORT
10 | # else
11 | # define Q_DATASYNC_EXPORT Q_DECL_IMPORT
12 | # endif
13 | #else
14 | # define Q_DATASYNC_EXPORT
15 | #endif
16 |
17 | #ifdef DOXYGEN_RUN
18 | #define QT_DATASYNC_REVISION_2
19 | #else
20 | #define QT_DATASYNC_REVISION_2 Q_REVISION(2)
21 | #endif
22 |
23 | //! The primary namespace of the QtDataSync library
24 | namespace QtDataSync {
25 | //! The default setup name
26 | extern Q_DATASYNC_EXPORT const QString DefaultSetup;
27 | }
28 |
29 | #endif // QTDATASYNC_GLOBAL_H
30 |
--------------------------------------------------------------------------------
/tools/appserver/de.skycoder42.qtdatasync.qdsapp.plist.in:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Label
6 | de.skycoder42.qtdatasync.qdsapp
7 | ProgramArguments
8 |
9 | $$[QT_INSTALL_BINS]/$${TARGET}
10 | --backend
11 | launchd
12 |
13 | RunAtLoad
14 | false
15 | Sockets
16 |
17 | Listeners
18 |
19 | SockServiceName
20 | 4242
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/src/messages/newkeymessage.cpp:
--------------------------------------------------------------------------------
1 | #include "newkeymessage_p.h"
2 | using namespace QtDataSync;
3 | using std::get;
4 |
5 | QByteArray NewKeyMessage::signatureData(const NewKeyMessage::KeyUpdate &deviceInfo) const
6 | {
7 | // keyIndex, scheme, deviceId, key
8 | return QByteArray::number(keyIndex) +
9 | scheme +
10 | get<0>(deviceInfo).toRfc4122() +
11 | get<1>(deviceInfo);
12 | }
13 |
14 | const QMetaObject *NewKeyMessage::getMetaObject() const
15 | {
16 | return &staticMetaObject;
17 | }
18 |
19 |
20 |
21 | NewKeyAckMessage::NewKeyAckMessage(const NewKeyMessage &message) :
22 | MacUpdateAckMessage{},
23 | keyIndex{message.keyIndex}
24 | {}
25 |
26 | const QMetaObject *NewKeyAckMessage::getMetaObject() const
27 | {
28 | return &staticMetaObject;
29 | }
30 |
--------------------------------------------------------------------------------
/src/plugins/keystores/secretservice/secretservicekeystoreplugin.h:
--------------------------------------------------------------------------------
1 | #ifndef SECRETSERVICEKEYSTOREPLUGIN_H
2 | #define SECRETSERVICEKEYSTOREPLUGIN_H
3 |
4 | #include
5 |
6 | class SecretServiceKeyStorePlugin : public QObject, public QtDataSync::KeyStorePlugin
7 | {
8 | Q_OBJECT
9 | Q_PLUGIN_METADATA(IID QtDataSync_KeyStorePlugin_Iid FILE "secretservice.json")
10 | Q_INTERFACES(QtDataSync::KeyStorePlugin)
11 |
12 | public:
13 | SecretServiceKeyStorePlugin(QObject *parent = nullptr);
14 |
15 | bool keystoreAvailable(const QString &provider) const override;
16 | QtDataSync::KeyStore *createInstance(const QString &provider, const QtDataSync::Defaults &defaults, QObject *parent) override;
17 | };
18 |
19 | #endif // SECRETSERVICEKEYSTOREPLUGIN_H
20 |
--------------------------------------------------------------------------------
/src/plugins/keystores/android/androidkeystoreplugin.cpp:
--------------------------------------------------------------------------------
1 | #include "androidkeystoreplugin.h"
2 | #include "androidkeystore.h"
3 |
4 | #include
5 |
6 | AndroidKeyStorePlugin::AndroidKeyStorePlugin(QObject *parent) :
7 | QObject(parent),
8 | KeyStorePlugin()
9 | {}
10 |
11 | bool AndroidKeyStorePlugin::keystoreAvailable(const QString &provider) const
12 | {
13 | if(provider == QStringLiteral("android"))
14 | return true;
15 | else
16 | return false;
17 | }
18 |
19 | QtDataSync::KeyStore *AndroidKeyStorePlugin::createInstance(const QString &provider, const QtDataSync::Defaults &defaults, QObject *parent)
20 | {
21 | if(provider == QStringLiteral("android"))
22 | return new AndroidKeyStore(defaults, parent);
23 | else
24 | return nullptr;
25 | }
26 |
--------------------------------------------------------------------------------
/tests/auto/datasync/TestLib/mockclient.cpp:
--------------------------------------------------------------------------------
1 | #include "mockclient.h"
2 |
3 | #ifdef Q_OS_WIN
4 | #define WAIT_TIMEOUT 15000
5 | #else
6 | #define WAIT_TIMEOUT 10000
7 | #endif
8 |
9 | MockClient::MockClient(QObject *parent) :
10 | MockConnection(new QWebSocket(), parent),
11 | _connectSpy(_socket, &QWebSocket::connected)
12 | {}
13 |
14 | bool MockClient::waitForConnected(quint16 port)
15 | {
16 | QUrl url;
17 | url.setScheme(QStringLiteral("ws"));
18 | url.setHost(QHostAddress(QHostAddress::LocalHost).toString());
19 | url.setPort(port);
20 | _socket->open(url);
21 |
22 | auto ok = false;
23 | [&]() {
24 | if(_connectSpy.isEmpty())
25 | QVERIFY(_connectSpy.wait(WAIT_TIMEOUT));
26 | QVERIFY(!_connectSpy.isEmpty());
27 | ok = true;
28 | }();
29 | return ok;
30 | }
31 |
--------------------------------------------------------------------------------
/src/plugins/keystores/keychain/keychainkeystoreplugin.cpp:
--------------------------------------------------------------------------------
1 | #include "keychainkeystoreplugin.h"
2 | #include "keychainkeystore.h"
3 |
4 | #include
5 |
6 | KeychainKeyStorePlugin::KeychainKeyStorePlugin(QObject *parent) :
7 | QObject(parent),
8 | KeyStorePlugin()
9 | {}
10 |
11 | bool KeychainKeyStorePlugin::keystoreAvailable(const QString &provider) const
12 | {
13 | if(provider == QStringLiteral("keychain"))
14 | return true;
15 | else
16 | return false;
17 | }
18 |
19 | QtDataSync::KeyStore *KeychainKeyStorePlugin::createInstance(const QString &provider, const QtDataSync::Defaults &defaults, QObject *parent)
20 | {
21 | if(provider == QStringLiteral("keychain"))
22 | return new KeychainKeyStore(defaults, parent);
23 | else
24 | return nullptr;
25 | }
26 |
--------------------------------------------------------------------------------
/tests/auto/datasync/TestSyncController/testresolver.cpp:
--------------------------------------------------------------------------------
1 | #include "testresolver.h"
2 |
3 | TestResolver::TestResolver(QObject *parent) :
4 | GenericConflictResolver(parent)
5 | {}
6 |
7 | TestData TestResolver::resolveConflict(TestData data1, TestData data2, QObject *parent) const
8 | {
9 | Q_ASSERT(parent);
10 | Q_ASSERT_X(data1.id == data2.id, Q_FUNC_INFO, "resolveConflict called on different datasets");
11 |
12 | TestData resData(data1.id);
13 | if(shouldThrow)
14 | throw NoConflictResultException{};
15 | if(data1.text < data2.text)
16 | resData.text = data1.text + QStringLiteral("+conflict");
17 | else if(data2.text < data1.text)
18 | resData.text = data2.text + QStringLiteral("+conflict");
19 | else
20 | throw NoConflictResultException{};
21 | return resData;
22 | }
23 |
--------------------------------------------------------------------------------
/doc/qtdatasync.dox:
--------------------------------------------------------------------------------
1 | /*!
2 | @namespace de::skycoder42::QtDataSync
3 | @brief The QML import for the QtDataSync QML module
4 |
5 | Current Version
6 | 4.2
7 |
8 | Available Types
9 | - @ref QtDataSync::DeviceInfo "DeviceInfo" (uncreatable)
10 | - @ref QtDataSync::LoginRequest "LoginRequest" (uncreatable)
11 | - @ref QtDataSync::UserInfo "UserInfo" (uncreatable)
12 | - @ref QtDataSync::EventCursor "EventCursor" (uncreatable)
13 | - DataStore
14 | - DataStoreModel
15 | - SyncManager
16 | - AccountManager
17 | - UserExchangeManager
18 | - EventLog (singleton)
19 | - @ref QtDataSync::AndroidSyncControl "AndroidSyncControl"
20 | - @ref QtDataSync::IosSyncDelegate "IosSyncDelegate" (uncreatable)
21 | - IosSyncSingleton (singleton)
22 | */
23 |
--------------------------------------------------------------------------------
/src/datasync/synchelper_p.h:
--------------------------------------------------------------------------------
1 | #ifndef QTDATASYNC_SYNCHELPER_P_H
2 | #define QTDATASYNC_SYNCHELPER_P_H
3 |
4 | #include
5 |
6 | #include
7 |
8 | #include "qtdatasync_global.h"
9 | #include "objectkey.h"
10 |
11 | namespace QtDataSync {
12 |
13 | namespace SyncHelper {
14 |
15 | //exports are needed for tests
16 | Q_DATASYNC_EXPORT QByteArray jsonHash(const QJsonObject &object);
17 |
18 | Q_DATASYNC_EXPORT QByteArray combine(const ObjectKey &key, quint64 version, const QJsonObject &data);
19 | Q_DATASYNC_EXPORT QByteArray combine(const ObjectKey &key, quint64 version);
20 | Q_DATASYNC_EXPORT std::tuple extract(const QByteArray &data); // (deleted, key, version, data)
21 |
22 | }
23 |
24 | }
25 |
26 | #endif // QTDATASYNC_SYNCHELPER_P_H
27 |
--------------------------------------------------------------------------------
/src/plugins/keystores/wincred/wincredkeystoreplugin.cpp:
--------------------------------------------------------------------------------
1 | #include "wincredkeystoreplugin.h"
2 | #include "wincredkeystore.h"
3 |
4 | #include
5 |
6 | WinCredKeyStorePlugin::WinCredKeyStorePlugin(QObject *parent) :
7 | QObject(parent),
8 | KeyStorePlugin()
9 | {}
10 |
11 | bool WinCredKeyStorePlugin::keystoreAvailable(const QString &provider) const
12 | {
13 | if(provider == QStringLiteral("wincred"))
14 | return true;
15 | else
16 | return false;
17 | }
18 |
19 | QtDataSync::KeyStore *WinCredKeyStorePlugin::createInstance(const QString &provider, const QtDataSync::Defaults &defaults, QObject *parent)
20 | {
21 | if(provider == QStringLiteral("wincred"))
22 | return new WinCredKeyStore(defaults, parent);
23 | else
24 | return nullptr;
25 | }
26 |
--------------------------------------------------------------------------------
/examples/datasync/AndroidSync/android/res/values/libs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | - https://download.qt.io/ministro/android/qt5/qt-5.9
5 |
6 |
7 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/src/messages/loginmessage_p.h:
--------------------------------------------------------------------------------
1 | #ifndef QTDATASYNC_LOGINMESSAGE_P_H
2 | #define QTDATASYNC_LOGINMESSAGE_P_H
3 |
4 | #include
5 |
6 | #include "message_p.h"
7 | #include "identifymessage_p.h"
8 |
9 | namespace QtDataSync {
10 |
11 | class Q_DATASYNC_EXPORT LoginMessage : public InitMessage
12 | {
13 | Q_GADGET
14 |
15 | Q_PROPERTY(QUuid deviceId MEMBER deviceId)
16 | Q_PROPERTY(QtDataSync::Utf8String deviceName MEMBER deviceName)
17 |
18 | public:
19 | LoginMessage(QUuid deviceId = {}, QString deviceName = {}, QByteArray nonce = {});
20 |
21 | QUuid deviceId;
22 | Utf8String deviceName;
23 |
24 | protected:
25 | const QMetaObject *getMetaObject() const override;
26 | };
27 |
28 | }
29 |
30 | Q_DECLARE_METATYPE(QtDataSync::LoginMessage)
31 |
32 | #endif // QTDATASYNC_LOGINMESSAGE_P_H
33 |
--------------------------------------------------------------------------------
/src/messages/changedmessage.cpp:
--------------------------------------------------------------------------------
1 | #include "changedmessage_p.h"
2 | using namespace QtDataSync;
3 |
4 | const QMetaObject *ChangedMessage::getMetaObject() const
5 | {
6 | return &staticMetaObject;
7 | }
8 |
9 |
10 |
11 | ChangedInfoMessage::ChangedInfoMessage(quint32 changeEstimate) :
12 | ChangedMessage{},
13 | changeEstimate{changeEstimate}
14 | {}
15 |
16 | const QMetaObject *ChangedInfoMessage::getMetaObject() const
17 | {
18 | return &staticMetaObject;
19 | }
20 |
21 |
22 |
23 | const QMetaObject *LastChangedMessage::getMetaObject() const
24 | {
25 | return &staticMetaObject;
26 | }
27 |
28 |
29 |
30 | ChangedAckMessage::ChangedAckMessage(quint64 dataIndex) :
31 | dataIndex{dataIndex}
32 | {}
33 |
34 | const QMetaObject *ChangedAckMessage::getMetaObject() const
35 | {
36 | return &staticMetaObject;
37 | }
38 |
--------------------------------------------------------------------------------
/src/plugins/keystores/plain/plainkeystore.h:
--------------------------------------------------------------------------------
1 | #ifndef PLAINKEYSTORE_H
2 | #define PLAINKEYSTORE_H
3 |
4 | #include
5 |
6 | #include
7 |
8 | class PlainKeyStore : public QtDataSync::KeyStore
9 | {
10 | Q_OBJECT
11 |
12 | public:
13 | explicit PlainKeyStore(const QtDataSync::Defaults &defaults, QObject *parent = nullptr);
14 |
15 | QString providerName() const override;
16 | bool isOpen() const override;
17 | void openStore() override;
18 | void closeStore() override;
19 | bool contains(const QString &key) const override;
20 | void save(const QString &key, const QByteArray &pKey) override;
21 | QByteArray load(const QString &key) override;
22 | void remove(const QString &key) override;
23 |
24 | private:
25 | QSettings *_settings;
26 | };
27 |
28 | #endif // PLAINKEYSTORE_H
29 |
--------------------------------------------------------------------------------
/src/datasync/synccontroller_p.h:
--------------------------------------------------------------------------------
1 | #ifndef QTDATASYNC_SYNCCONTROLLER_P_H
2 | #define QTDATASYNC_SYNCCONTROLLER_P_H
3 |
4 | #include "qtdatasync_global.h"
5 | #include "controller_p.h"
6 | #include "localstore_p.h"
7 |
8 | namespace QtDataSync {
9 |
10 | class Q_DATASYNC_EXPORT SyncController : public Controller
11 | {
12 | Q_OBJECT
13 |
14 | public:
15 | explicit SyncController(const Defaults &defaults, QObject *parent = nullptr);
16 |
17 | void initialize(const QVariantHash ¶ms) override;
18 |
19 | public Q_SLOTS:
20 | void setSyncEnabled(bool enabled);
21 | void syncChange(quint64 key, const QByteArray &changeData);
22 |
23 | Q_SIGNALS:
24 | void syncDone(quint64 key);
25 |
26 | private:
27 | LocalStore *_store = nullptr;
28 | bool _enabled = false;
29 | };
30 |
31 | }
32 |
33 | #endif // QTDATASYNC_SYNCCONTROLLER_P_H
34 |
--------------------------------------------------------------------------------
/src/messages/grantmessage_p.h:
--------------------------------------------------------------------------------
1 | #ifndef QTDATASYNC_GRANTMESSAGE_P_H
2 | #define QTDATASYNC_GRANTMESSAGE_P_H
3 |
4 | #include "message_p.h"
5 | #include "accountmessage_p.h"
6 | #include "proofmessage_p.h"
7 |
8 | namespace QtDataSync {
9 |
10 | class Q_DATASYNC_EXPORT GrantMessage : public AccountMessage
11 | {
12 | Q_GADGET
13 |
14 | Q_PROPERTY(quint32 index MEMBER index)
15 | Q_PROPERTY(QByteArray scheme MEMBER scheme)
16 | Q_PROPERTY(QByteArray secret MEMBER secret)
17 |
18 | public:
19 | GrantMessage();
20 | GrantMessage(const AcceptMessage &message);
21 |
22 | quint32 index = 0;
23 | QByteArray scheme;
24 | QByteArray secret;
25 |
26 | protected:
27 | const QMetaObject *getMetaObject() const override;
28 | };
29 |
30 | }
31 |
32 | Q_DECLARE_METATYPE(QtDataSync::GrantMessage)
33 |
34 | #endif // QTDATASYNC_GRANTMESSAGE_P_H
35 |
--------------------------------------------------------------------------------
/tools/appserver/docker-compose.yaml:
--------------------------------------------------------------------------------
1 | version: '2.2'
2 | services:
3 | datasync_postgres:
4 | container_name: datasync_example_postgres
5 | image: postgres:latest
6 | ports:
7 | - "15432:5432/tcp"
8 | environment:
9 | POSTGRES_USER: qtdatasync
10 | POSTGRES_PASSWORD: baum42
11 | POSTGRES_DB: QtDataSync
12 | PGDATA: /var/lib/postgresql/data/pgdata
13 | volumes:
14 | - datasync_example_postgres_data:/var/lib/postgresql/data/pgdata
15 | datasync_pgAdmin:
16 | container_name: datasync_example_pgAdmin
17 | image: thajeztah/pgadmin4:latest
18 | depends_on:
19 | - datasync_postgres
20 | ports:
21 | - "5050:5050/tcp"
22 | volumes:
23 | - datasync_example_pgAdmin_data:/pgadmin
24 | volumes:
25 | datasync_example_postgres_data:
26 | datasync_example_pgAdmin_data:
27 |
--------------------------------------------------------------------------------
/src/messages/accessmessage.cpp:
--------------------------------------------------------------------------------
1 | #include "accessmessage_p.h"
2 | using namespace QtDataSync;
3 |
4 | AccessMessage::AccessMessage() = default;
5 |
6 | AccessMessage::AccessMessage(QString deviceName, QByteArray nonce, const QSharedPointer &signKey, const QSharedPointer &cryptKey, AsymmetricCrypto *crypto, QByteArray pNonce, QUuid partnerId, QByteArray macscheme, QByteArray cmac, QByteArray trustmac) :
7 | RegisterBaseMessage{std::move(deviceName),
8 | std::move(nonce),
9 | signKey,
10 | cryptKey,
11 | crypto},
12 | pNonce{std::move(pNonce)},
13 | partnerId{partnerId},
14 | macscheme{std::move(macscheme)},
15 | cmac{std::move(cmac)},
16 | trustmac{std::move(trustmac)}
17 | {}
18 |
19 | const QMetaObject *AccessMessage::getMetaObject() const
20 | {
21 | return &staticMetaObject;
22 | }
23 |
--------------------------------------------------------------------------------
/src/plugins/keystores/kwallet/kwalletkeystore.h:
--------------------------------------------------------------------------------
1 | #ifndef KWALLETKEYSTORE_H
2 | #define KWALLETKEYSTORE_H
3 |
4 | #include
5 |
6 | #include
7 |
8 | #include
9 |
10 | class KWalletKeyStore : public QtDataSync::KeyStore
11 | {
12 | Q_OBJECT
13 |
14 | public:
15 | explicit KWalletKeyStore(const QtDataSync::Defaults &defaults, QObject *parent = nullptr);
16 |
17 | QString providerName() const override;
18 | bool isOpen() const override;
19 | void openStore() override;
20 | void closeStore() override;
21 | bool contains(const QString &key) const override;
22 | void save(const QString &key, const QByteArray &pKey) override;
23 | QByteArray load(const QString &key) override;
24 | void remove(const QString &key) override;
25 |
26 | private:
27 | QPointer _wallet;
28 | };
29 |
30 | #endif // KWALLETKEYSTORE_H
31 |
--------------------------------------------------------------------------------
/examples/datasync/Sample/widget.h:
--------------------------------------------------------------------------------
1 | #ifndef WIDGET_H
2 | #define WIDGET_H
3 |
4 | #include
5 | #include
6 | #include
7 |
8 | namespace Ui {
9 | class Widget;
10 | }
11 |
12 | class Widget : public QWidget
13 | {
14 | Q_OBJECT
15 |
16 | public:
17 | explicit Widget(const QString &setup, QWidget *parent = nullptr);
18 | ~Widget();
19 |
20 | private slots:
21 | void selectionChange(const QModelIndex &index);
22 | void updateState(QtDataSync::SyncManager::SyncState state);
23 |
24 | void on_addButton_clicked();
25 | void on_deleteButton_clicked();
26 | void on_clearButton_clicked();
27 |
28 | void on_accountButton_clicked();
29 |
30 | private:
31 | const QString _setup;
32 | Ui::Widget *ui;
33 | QtDataSync::SyncManager *_manager;
34 | QtDataSync::DataStoreModel *_model;
35 | };
36 |
37 | #endif // WIDGET_H
38 |
--------------------------------------------------------------------------------
/tests/auto/datasync/TestLib/TestLib.pro:
--------------------------------------------------------------------------------
1 | TEMPLATE = lib
2 |
3 | QT += datasync-private testlib
4 | # TODO why tho
5 | !linux: CONFIG += static
6 | linux: DESTDIR = $$shadowed($$dirname(_QMAKE_CONF_))/lib
7 |
8 | HEADERS += \
9 | testlib.h \
10 | testdata.h \
11 | testobject.h \
12 | mockserver.h \
13 | mockconnection.h \
14 | mockclient.h
15 |
16 | SOURCES += \
17 | testlib.cpp \
18 | testdata.cpp \
19 | testobject.cpp \
20 | mockserver.cpp \
21 | mockconnection.cpp \
22 | mockclient.cpp
23 |
24 | INCLUDEPATH += ../../../../src/messages
25 |
26 | verbose_tests: DEFINES += VERBOSE_TESTS
27 |
28 | include(../../../../src/3rdparty/cryptopp/cryptopp.pri)
29 |
30 | runtarget.target = run-tests
31 | win32: runtarget.depends += $(DESTDIR_TARGET)
32 | else:linux: runtarget.depends += $(DESTDIR)$(TARGET)
33 | else: runtarget.depends += $(TARGET)
34 | QMAKE_EXTRA_TARGETS += runtarget
35 |
--------------------------------------------------------------------------------
/tests/auto/qml/TestQmlDataSync/tst_qmldatasync.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | using namespace QtDataSync;
6 |
7 | static QTemporaryDir tDir;
8 |
9 | static void initImportPath()
10 | {
11 | #ifdef VERBOSE_TESTS
12 | QLoggingCategory::setFilterRules(QStringLiteral("qtdatasync.*.debug=true"));
13 | #endif
14 |
15 | tDir.setAutoRemove(false);
16 | qInfo() << "storage path:" << tDir.path();
17 | Setup().setLocalDir(tDir.path())
18 | .setKeyStoreProvider(QStringLiteral("plain"))
19 | .setSignatureScheme(Setup::RSA_PSS_SHA3_512)
20 | .setSignatureKeyParam(2048)
21 | .setEncryptionScheme(Setup::RSA_OAEP_SHA3_512)
22 | .setEncryptionKeyParam(2048)
23 | .setEventLoggingMode(Setup::EventMode::Enabled)
24 | .create();
25 | }
26 | Q_COREAPP_STARTUP_FUNCTION(initImportPath)
27 |
28 | QUICK_TEST_MAIN(qmldatasync)
29 |
--------------------------------------------------------------------------------
/src/imports/datasync/qqmliossyncsingleton.h:
--------------------------------------------------------------------------------
1 | #ifndef QQMLIOSSYNCSINGLETON_H
2 | #define QQMLIOSSYNCSINGLETON_H
3 |
4 | #include
5 |
6 | #include
7 |
8 | #ifdef DOXYGEN_RUN
9 | namespace de::skycoder42::QtDataSync {
10 |
11 | /*! @brief The QML bindings for the static methods of of QtDataSync::EventCursor
12 | *
13 | * @extends QtQml.QtObject
14 | * @since 4.2
15 | *
16 | * @sa QtDataSync::IosSyncDelegate
17 | */
18 | class IosSyncSingleton
19 | #else
20 | namespace QtDataSync {
21 |
22 | class QQmlIosSyncSingleton : public QObject
23 | #endif
24 | {
25 | Q_OBJECT
26 |
27 | public:
28 | //! @private
29 | explicit QQmlIosSyncSingleton(QObject *parent = nullptr);
30 |
31 | //! Returns the currently registered sync delegate
32 | Q_INVOKABLE QtDataSync::IosSyncDelegate *delegate() const;
33 | };
34 |
35 | }
36 |
37 | #endif // QQMLIOSSYNCSINGLETON_H
38 |
--------------------------------------------------------------------------------
/doc/doxme.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | # $1 The readme to be transformed
3 | # $pwd: dest dir
4 |
5 | import sys
6 |
7 | def readFirst(line, out):
8 | if line[0:2] != "# ":
9 | raise ValueError("Expected first line to start with '# '")
10 | # skip the first line
11 | out.write("[TOC]\n\n")
12 |
13 | readCounter = 0
14 | def readMore(line, out):
15 | global readCounter
16 | if line[0:2] == "##":
17 | out.write(line[1:] + " {{#qtdatasync_readme_label_{}}}\n".format(readCounter))
18 | readCounter += 1
19 | else:
20 | out.write(line + "\n")
21 |
22 | #read args
23 | readme = sys.argv[1]
24 | doxme = "./README.md"
25 |
26 | inFile = open(readme, "r")
27 | outFile = open(doxme, "w")
28 |
29 | isFirst = True
30 | for line in inFile:
31 | if isFirst:
32 | readFirst(line[:-1], outFile)
33 | isFirst = False
34 | else:
35 | readMore(line[:-1], outFile)
36 |
37 | inFile.close();
38 | outFile.close();
39 |
--------------------------------------------------------------------------------
/src/translations/translations.pro:
--------------------------------------------------------------------------------
1 | TEMPLATE = aux
2 |
3 | QDEP_LUPDATE_INPUTS += $$PWD/../datasync
4 | QDEP_LUPDATE_INPUTS += $$PWD/../datasyncandroid
5 | QDEP_LUPDATE_INPUTS += $$PWD/../datasyncios
6 | QDEP_LUPDATE_INPUTS += $$PWD/../imports
7 | QDEP_LUPDATE_INPUTS += $$PWD/../java
8 | QDEP_LUPDATE_INPUTS += $$PWD/../messages
9 | QDEP_LUPDATE_INPUTS += $$PWD/../plugins
10 |
11 | TRANSLATIONS += \
12 | qtdatasync_de.ts \
13 | qtdatasync_template.ts
14 |
15 | CONFIG += lrelease
16 | QM_FILES_INSTALL_PATH = $$[QT_INSTALL_TRANSLATIONS]
17 |
18 | QDEP_DEPENDS +=
19 |
20 | !load(qdep):error("Failed to load qdep feature! Run 'qdep prfgen --qmake $$QMAKE_QMAKE' to create it.")
21 |
22 | #replace template qm by ts
23 | QM_FILES -= $$__qdep_lrelease_real_dir/qtdatasync_template.qm
24 | QM_FILES += qtdatasync_template.ts
25 |
26 | HEADERS =
27 | SOURCES =
28 | GENERATED_SOURCES =
29 | OBJECTIVE_SOURCES =
30 | RESOURCES =
31 |
--------------------------------------------------------------------------------
/src/datasync/rothreadedbackend/exchangerotransport.cpp:
--------------------------------------------------------------------------------
1 | #include "exchangerotransport_p.h"
2 | #include "exchangebuffer_p.h"
3 | #include "exchangebufferserver_p.h"
4 | using namespace QtDataSync;
5 |
6 | bool ThreadedQtRoServer::prepareHostNode(const QUrl &url, QRemoteObjectHostBase *host)
7 | {
8 | auto server = new ExchangeBufferServer{host};
9 | if(server->registerInstance(url))
10 | return true;
11 | else {
12 | delete server;
13 | return false;
14 | }
15 | }
16 |
17 | bool ThreadedQtRoClient::prepareClientNode(const QUrl &url, QRemoteObjectNode *node)
18 | {
19 | auto buffer = new ExchangeBuffer{node};
20 | QObject::connect(buffer, &ExchangeBuffer::partnerConnected,
21 | node, [buffer, node]() {
22 | node->addClientSideConnection(buffer);
23 | });
24 |
25 | if(ExchangeBufferServer::connectTo(url, buffer))
26 | return true;
27 | else {
28 | delete buffer;
29 | return false;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/plugins/keystores/wincred/wincredkeystore.h:
--------------------------------------------------------------------------------
1 | #ifndef WINCREDKEYSTORE_H
2 | #define WINCREDKEYSTORE_H
3 |
4 | #include
5 |
6 | class WinCredKeyStore : public QtDataSync::KeyStore
7 | {
8 | Q_OBJECT
9 |
10 | public:
11 | explicit WinCredKeyStore(const QtDataSync::Defaults &defaults, QObject *parent = nullptr);
12 |
13 | QString providerName() const override;
14 | bool isOpen() const override;
15 | void openStore() override;
16 | void closeStore() override;
17 | bool contains(const QString &key) const override;
18 | void save(const QString &key, const QByteArray &pKey) override;
19 | QByteArray load(const QString &key) override;
20 | void remove(const QString &key) override;
21 |
22 | private:
23 | bool _open;
24 |
25 | static QString fullKey(const QString &key);
26 | QByteArray tryLoad(const QString &key) const;
27 | };
28 |
29 | #endif // WINCREDKEYSTORE_H
30 |
--------------------------------------------------------------------------------
/src/datasync/qtdatasync_global.cpp:
--------------------------------------------------------------------------------
1 | #include "qtdatasync_global.h"
2 | #include "objectkey.h"
3 | #include "changecontroller_p.h"
4 |
5 | #include "exchangerotransport_p.h"
6 | #include "exchangebufferserver_p.h"
7 |
8 | #include
9 | #include "message_p.h"
10 |
11 | const QString QtDataSync::DefaultSetup(QStringLiteral("default"));
12 |
13 | namespace {
14 |
15 | void setupQtDataSync()
16 | {
17 | qRegisterMetaType();
18 | qRegisterMetaType();
19 | qRegisterMetaTypeStreamOperators();
20 |
21 | QtDataSync::QtRoTransportRegistry::registerTransport(QtDataSync::ExchangeBufferServer::UrlScheme(),
22 | new QtDataSync::ThreadedQtRoServer{},
23 | new QtDataSync::ThreadedQtRoClient{});
24 |
25 | QtDataSync::Message::registerTypes();
26 | }
27 |
28 | }
29 | Q_COREAPP_STARTUP_FUNCTION(setupQtDataSync)
30 |
--------------------------------------------------------------------------------
/src/messages/macupdatemessage_p.h:
--------------------------------------------------------------------------------
1 | #ifndef QTDATASYNC_MACUPDATEMESSAGE_P_H
2 | #define QTDATASYNC_MACUPDATEMESSAGE_P_H
3 |
4 | #include "message_p.h"
5 |
6 | namespace QtDataSync {
7 |
8 | class Q_DATASYNC_EXPORT MacUpdateMessage : public Message
9 | {
10 | Q_GADGET
11 |
12 | Q_PROPERTY(quint32 keyIndex MEMBER keyIndex)
13 | Q_PROPERTY(QByteArray cmac MEMBER cmac)
14 |
15 | public:
16 | MacUpdateMessage(quint32 keyIndex = 0, QByteArray cmac = {});
17 |
18 | quint32 keyIndex;
19 | QByteArray cmac;
20 |
21 | protected:
22 | const QMetaObject *getMetaObject() const override;
23 | };
24 |
25 | class Q_DATASYNC_EXPORT MacUpdateAckMessage : public Message
26 | {
27 | Q_GADGET
28 |
29 | protected:
30 | const QMetaObject *getMetaObject() const override;
31 | };
32 |
33 | }
34 |
35 | Q_DECLARE_METATYPE(QtDataSync::MacUpdateMessage)
36 | Q_DECLARE_METATYPE(QtDataSync::MacUpdateAckMessage)
37 |
38 | #endif // QTDATASYNC_MACUPDATEMESSAGE_P_H
39 |
--------------------------------------------------------------------------------
/tests/auto/datasync/datasync.pro:
--------------------------------------------------------------------------------
1 | TEMPLATE = subdirs
2 |
3 | SUBDIRS += \
4 | TestLib \
5 | TestSetup \
6 | TestLocalStore \
7 | TestDataStore \
8 | TestDataTypeStore \
9 | TestChangeController \
10 | TestCryptoController \
11 | TestSyncController \
12 | TestRoThreadedBackend \
13 | TestMessages \
14 | TestKeystorePlugins \
15 | TestRemoteConnector \
16 | TestMigrationHelper \
17 | TestEventCursor
18 |
19 | include_server_tests {
20 | SUBDIRS += \
21 | TestAppServer \
22 | IntegrationTest
23 |
24 | IntegrationTest.depends += TestAppServer #ensure those two don't run in parallel
25 | }
26 |
27 | include_server_tests: message("Please run 'sudo docker-compose -f $$absolute_path(../../../tools/appserver/docker-compose.yaml) up -d' to start the services needed for server tests")
28 |
29 | for(subdir, SUBDIRS):!equals(subdir, "TestLib"): $${subdir}.depends += TestLib
30 |
31 | prepareRecursiveTarget(run-tests)
32 | QMAKE_EXTRA_TARGETS += run-tests
33 |
--------------------------------------------------------------------------------
/examples/datasync/Sample/Sample.pro:
--------------------------------------------------------------------------------
1 | TEMPLATE = app
2 |
3 | QT += core gui widgets datasync
4 | QT += testlib
5 |
6 | TARGET = Sample
7 |
8 | HEADERS += \
9 | widget.h \
10 | sampledata.h \
11 | accountdialog.h \
12 | exchangedialog.h
13 |
14 | SOURCES += \
15 | main.cpp \
16 | widget.cpp \
17 | sampledata.cpp \
18 | accountdialog.cpp \
19 | exchangedialog.cpp
20 |
21 | FORMS += \
22 | widget.ui \
23 | accountdialog.ui \
24 | exchangedialog.ui
25 |
26 | DISTFILES += docker-compose.yaml
27 |
28 | target.path = $$[QT_INSTALL_EXAMPLES]/datasync/$$TARGET
29 | !install_ok: INSTALLS += target
30 |
31 | #not found by linker?
32 | unix:!mac {
33 | LIBS += -L$$OUT_PWD/../../../lib #required to make this the first place to search
34 | LIBS += -L$$[QT_INSTALL_LIBS] -licudata
35 | LIBS += -L$$[QT_INSTALL_LIBS] -licui18n
36 | LIBS += -L$$[QT_INSTALL_LIBS] -licuuc
37 | }
38 |
39 | #add lib dir to rpath
40 | mac: QMAKE_LFLAGS += '-Wl,-rpath,\'$$OUT_PWD/../../../lib\''
41 |
--------------------------------------------------------------------------------
/src/plugins/keystores/secretservice/secretservicekeystoreplugin.cpp:
--------------------------------------------------------------------------------
1 | #include "secretservicekeystoreplugin.h"
2 | #include "secretservicekeystore.h"
3 |
4 | #include "libsecretwrapper.h"
5 |
6 | SecretServiceKeyStorePlugin::SecretServiceKeyStorePlugin(QObject *parent) :
7 | QObject(parent),
8 | KeyStorePlugin()
9 | {}
10 |
11 | bool SecretServiceKeyStorePlugin::keystoreAvailable(const QString &provider) const
12 | {
13 | if(provider == QStringLiteral("secretservice") ||
14 | provider == QStringLiteral("gnome-keyring"))
15 | return LibSecretWrapper::testAvailable();
16 | else
17 | return false;
18 | }
19 |
20 | QtDataSync::KeyStore *SecretServiceKeyStorePlugin::createInstance(const QString &provider, const QtDataSync::Defaults &defaults, QObject *parent)
21 | {
22 | if(provider == QStringLiteral("secretservice") ||
23 | provider == QStringLiteral("gnome-keyring"))
24 | return new SecretServiceKeyStore(defaults, provider, parent);
25 | else
26 | return nullptr;
27 | }
28 |
--------------------------------------------------------------------------------
/src/messages/removemessage_p.h:
--------------------------------------------------------------------------------
1 | #ifndef QTDATASYNC_REMOVEMESSAGE_P_H
2 | #define QTDATASYNC_REMOVEMESSAGE_P_H
3 |
4 | #include
5 |
6 | #include "message_p.h"
7 |
8 | namespace QtDataSync {
9 |
10 | class Q_DATASYNC_EXPORT RemoveMessage : public Message
11 | {
12 | Q_GADGET
13 |
14 | Q_PROPERTY(QUuid deviceId MEMBER deviceId)
15 |
16 | public:
17 | RemoveMessage(QUuid deviceId = {});
18 |
19 | QUuid deviceId;
20 |
21 | protected:
22 | const QMetaObject *getMetaObject() const override;
23 | };
24 |
25 | class Q_DATASYNC_EXPORT RemoveAckMessage : public Message
26 | {
27 | Q_GADGET
28 |
29 | Q_PROPERTY(QUuid deviceId MEMBER deviceId)
30 |
31 | public:
32 | RemoveAckMessage(QUuid deviceId = {});
33 |
34 | QUuid deviceId;
35 |
36 | protected:
37 | const QMetaObject *getMetaObject() const override;
38 | };
39 |
40 | }
41 |
42 | Q_DECLARE_METATYPE(QtDataSync::RemoveMessage)
43 | Q_DECLARE_METATYPE(QtDataSync::RemoveAckMessage)
44 |
45 | #endif // QTDATASYNC_REMOVEMESSAGE_P_H
46 |
--------------------------------------------------------------------------------
/mkspecs/features/masm.prf:
--------------------------------------------------------------------------------
1 | isEmpty(QMAKE_MASM_COMPILER) {
2 | contains(QT_ARCH, x86_64): QMAKE_MASM_COMPILER = ml64.exe
3 | else: QMAKE_MASM_COMPILER = ml.exe
4 | }
5 |
6 | contains(QT_ARCH, x86_64): QMAKE_MASM_FLAGS = /D_M_X64
7 | else: QMAKE_MASM_FLAGS = /D_M_X86 /safeseh
8 | QMAKE_MASM_FLAGS += /c /nologo /W3 /Cx /Zi
9 |
10 | isEmpty(MASM_DIR): MASM_DIR = .
11 | debug_and_release {
12 | CONFIG(debug, debug|release): MASM_DIR = $$MASM_DIR/debug
13 | CONFIG(release, debug|release): MASM_DIR = $$MASM_DIR/release
14 | }
15 |
16 | masm_c.name = QMAKE_MASM_COMPILER ${QMAKE_FILE_IN}
17 | masm_c.input = MASM_SOURCES
18 | masm_c.variable_out = OBJECTS
19 | masm_c.commands = $$QMAKE_MASM_COMPILER $$QMAKE_MASM_FLAGS /Fo${QMAKE_FILE_OUT} ${QMAKE_FILE_IN}
20 | masm_c.output = $$MASM_DIR/${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)}
21 | #masm_c.depends += $$QMAKE_MASM_COMPILER
22 | masm_c.dependency_type = TYPE_C
23 | QMAKE_EXTRA_COMPILERS += masm_c
24 |
25 | QMAKE_DIR_REPLACE += MASM_DIR
26 | QMAKE_DIR_REPLACE_SANE += MASM_DIR
27 |
--------------------------------------------------------------------------------
/src/messages/welcomemessage_p.h:
--------------------------------------------------------------------------------
1 | #ifndef QTDATASYNC_WELCOMEMESSAGE_P_H
2 | #define QTDATASYNC_WELCOMEMESSAGE_P_H
3 |
4 | #include
5 |
6 | #include "message_p.h"
7 |
8 | namespace QtDataSync {
9 |
10 | class Q_DATASYNC_EXPORT WelcomeMessage : public Message
11 | {
12 | Q_GADGET
13 |
14 | Q_PROPERTY(bool hasChanges MEMBER hasChanges)
15 | Q_PROPERTY(quint32 keyIndex MEMBER keyIndex)
16 | Q_PROPERTY(QByteArray scheme MEMBER scheme)
17 | Q_PROPERTY(QByteArray key MEMBER key)
18 | Q_PROPERTY(QByteArray cmac MEMBER cmac)
19 |
20 | public:
21 | WelcomeMessage(bool hasChanges = false);
22 |
23 | bool hasChanges;
24 | quint32 keyIndex = 0;
25 | QByteArray scheme;
26 | QByteArray key;
27 | QByteArray cmac;
28 |
29 | bool hasKeyUpdate() const;
30 | QByteArray signatureData(QUuid deviceId) const;
31 |
32 | protected:
33 | const QMetaObject *getMetaObject() const override;
34 | };
35 |
36 | }
37 |
38 | Q_DECLARE_METATYPE(QtDataSync::WelcomeMessage)
39 |
40 | #endif // QTDATASYNC_WELCOMEMESSAGE_P_H
41 |
--------------------------------------------------------------------------------
/src/plugins/keystores/keychain/keychainkeystore.h:
--------------------------------------------------------------------------------
1 | #ifndef KEYCHAINKEYSTORE_H
2 | #define KEYCHAINKEYSTORE_H
3 |
4 | #include
5 |
6 | #include
7 | #include
8 |
9 | #include
10 |
11 | class KeychainKeyStore : public QtDataSync::KeyStore
12 | {
13 | Q_OBJECT
14 |
15 | public:
16 | explicit KeychainKeyStore(const QtDataSync::Defaults &defaults, QObject *parent = nullptr);
17 |
18 | QString providerName() const override;
19 | bool isOpen() const override;
20 | void openStore() override;
21 | void closeStore() override;
22 | bool contains(const QString &key) const override;
23 | void save(const QString &key, const QByteArray &pKey) override;
24 | QByteArray load(const QString &key) override;
25 | void remove(const QString &key) override;
26 |
27 | private:
28 | bool _open;
29 | QtDataSync::Logger *_logger;
30 |
31 | static QString serviceName();
32 | static QString errorMsg(OSStatus status);
33 | };
34 |
35 | #endif // KEYCHAINKEYSTORE_H
36 |
--------------------------------------------------------------------------------
/src/plugins/keystores/secretservice/secretservicekeystore.h:
--------------------------------------------------------------------------------
1 | #ifndef SECRETSERVICEKEYSTORE_H
2 | #define SECRETSERVICEKEYSTORE_H
3 |
4 | #include
5 |
6 | #include
7 |
8 | #include "libsecretwrapper.h"
9 |
10 | class SecretServiceKeyStore : public QtDataSync::KeyStore
11 | {
12 | Q_OBJECT
13 |
14 | public:
15 | explicit SecretServiceKeyStore(const QtDataSync::Defaults &defaults,
16 | const QString &providerName,
17 | QObject *parent = nullptr);
18 |
19 | QString providerName() const override;
20 | bool isOpen() const override;
21 | void openStore() override;
22 | void closeStore() override;
23 | bool contains(const QString &key) const override;
24 | void save(const QString &key, const QByteArray &pKey) override;
25 | QByteArray load(const QString &key) override;
26 | void remove(const QString &key) override;
27 |
28 | private:
29 | const QString _providerName;
30 | QScopedPointer _libSecret;
31 | };
32 |
33 | #endif // SECRETSERVICEKEYSTORE_H
34 |
--------------------------------------------------------------------------------
/examples/datasync/AndroidSync/syncservice.cpp:
--------------------------------------------------------------------------------
1 | #include "syncservice.h"
2 | #include
3 |
4 | //! [droid_service_impl]
5 | SyncService::SyncService(int &argc, char **argv) :
6 | AndroidBackgroundService{argc, argv}
7 | {}
8 |
9 | void SyncService::prepareSetup(QtDataSync::Setup &setup)
10 | {
11 | // prepare the setup here, i.e.
12 | // setup.setRemoteConfiguration(QtDataSync::RemoteConfig{ ... ]);
13 | }
14 |
15 | void SyncService::onSyncCompleted(QtDataSync::SyncManager::SyncState state)
16 | {
17 | qDebug() << "[[SYNCSERVICE]]" << "Sync completed in state:" << state;
18 | exitAfterSync();
19 | }
20 | //! [droid_service_impl]
21 |
22 | //! [jni_create_notification]
23 | QAndroidJniObject SyncService::createForegroundNotification()
24 | {
25 | return QAndroidJniObject::callStaticObjectMethod("de/skycoder42/qtdatasync/sample/androidsync/SvcHelper",
26 | "createFgNotification",
27 | "(Landroid/content/Context;)Landroid/app/Notification;",
28 | QtAndroid::androidService().object());
29 | }
30 | //! [jni_create_notification]
31 |
--------------------------------------------------------------------------------
/src/datasync/syncmanager_p.h:
--------------------------------------------------------------------------------
1 | #ifndef QTDATASYNC_SYNCMANAGER_P_H
2 | #define QTDATASYNC_SYNCMANAGER_P_H
3 |
4 | #include
5 |
6 | #include "qtdatasync_global.h"
7 | #include "exchangeengine_p.h"
8 |
9 | #include "rep_syncmanager_p_source.h"
10 |
11 | namespace QtDataSync {
12 |
13 | //not exported because base it not, too
14 | class SyncManagerPrivate : public SyncManagerPrivateSource
15 | {
16 | Q_OBJECT
17 |
18 | public:
19 | SyncManagerPrivate(ExchangeEngine *engineParent);
20 |
21 | QString setupName() const override;
22 | bool syncEnabled() const override;
23 | SyncManager::SyncState syncState() const override;
24 | qreal syncProgress() const override;
25 | QString lastError() const override;
26 |
27 | void setSyncEnabled(bool syncEnabled) override;
28 |
29 | public Q_SLOTS:
30 | void synchronize() override;
31 | void reconnect() override;
32 | void runOnState(QUuid id, bool downloadOnly, bool triggerSync) override;
33 |
34 | private:
35 | QPointer _engine;
36 | };
37 |
38 | }
39 |
40 | #endif // QTDATASYNC_SYNCMANAGER_P_H
41 |
--------------------------------------------------------------------------------
/src/datasync/qtdatasync_helpertypes.h:
--------------------------------------------------------------------------------
1 | #ifndef QTDATASYNC_HELPERTYPES_H
2 | #define QTDATASYNC_HELPERTYPES_H
3 |
4 | #include
5 |
6 | #include
7 |
8 | #include "QtDataSync/qtdatasync_global.h"
9 |
10 | namespace QtDataSync {
11 | namespace __helpertypes {
12 |
13 | template
14 | struct is_gadget : public std::false_type {};
15 |
16 | template
17 | struct is_gadget : public std::true_type {};
18 |
19 | template
20 | struct is_object : public std::false_type {};
21 |
22 | template
23 | struct is_object : public std::is_base_of {};
24 |
25 | template
26 | struct is_storable : public is_gadget {};
27 |
28 | template
29 | struct is_storable : public std::is_base_of {};
30 |
31 | }
32 | }
33 |
34 | #define QTDATASYNC_STORE_ASSERT(T) static_assert(__helpertypes::is_storable::value, "Only Q_GADGETS or pointers to QObject extending classes can be stored")
35 |
36 | #endif // QTDATASYNC_HELPERTYPES_H
37 |
--------------------------------------------------------------------------------
/examples/datasync/Sample/exchangedialog.h:
--------------------------------------------------------------------------------
1 | #ifndef EXCHANGEDIALOG_H
2 | #define EXCHANGEDIALOG_H
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | namespace Ui {
10 | class ExchangeDialog;
11 | }
12 |
13 | class ExchangeDialog : public QDialog
14 | {
15 | Q_OBJECT
16 |
17 | public:
18 | explicit ExchangeDialog(QtDataSync::AccountManager *manager, QWidget *parent = nullptr);
19 | ~ExchangeDialog();
20 |
21 | static void exec(QtDataSync::AccountManager *manager, QWidget *parent = nullptr);
22 |
23 | private slots:
24 | void devicesChanged(QList devices);
25 | void userDataReceived(const QtDataSync::UserInfo &userInfo, bool trusted);
26 | void exchangeError(const QString &errorString);
27 |
28 | void on_treeWidget_itemActivated(QTreeWidgetItem *item, int column);
29 | void on_activeCheckBox_clicked(bool checked);
30 |
31 | private:
32 | Ui::ExchangeDialog *ui;
33 | QtDataSync::UserExchangeManager *_manager;
34 | };
35 |
36 | #endif // EXCHANGEDIALOG_H
37 |
--------------------------------------------------------------------------------
/src/messages/devicesmessage_p.h:
--------------------------------------------------------------------------------
1 | #ifndef QTDATASYNC_DEVICESMESSAGE_P_H
2 | #define QTDATASYNC_DEVICESMESSAGE_P_H
3 |
4 | #include
5 |
6 | #include
7 | #include
8 |
9 | #include "message_p.h"
10 |
11 | namespace QtDataSync {
12 |
13 | class Q_DATASYNC_EXPORT ListDevicesMessage : public Message
14 | {
15 | Q_GADGET
16 |
17 | protected:
18 | const QMetaObject *getMetaObject() const override;
19 | };
20 |
21 | class Q_DATASYNC_EXPORT DevicesMessage : public Message
22 | {
23 | Q_GADGET
24 |
25 | Q_PROPERTY(QList devices MEMBER devices)
26 |
27 | public:
28 | using DeviceInfo = std::tuple; // (deviceid, name, fingerprint)
29 |
30 | QList devices;
31 |
32 | protected:
33 | const QMetaObject *getMetaObject() const override;
34 | };
35 |
36 | }
37 |
38 | Q_DECLARE_METATYPE(QtDataSync::ListDevicesMessage)
39 | Q_DECLARE_METATYPE(QtDataSync::DevicesMessage)
40 | Q_DECLARE_METATYPE(QtDataSync::DevicesMessage::DeviceInfo)
41 |
42 | #endif // QTDATASYNC_DEVICESMESSAGE_P_H
43 |
--------------------------------------------------------------------------------
/src/datasync/conflictresolver.cpp:
--------------------------------------------------------------------------------
1 | #include "conflictresolver.h"
2 | #include "conflictresolver_p.h"
3 | #include "defaults_p.h"
4 | using namespace QtDataSync;
5 |
6 | ConflictResolver::ConflictResolver(QObject *parent) :
7 | QObject{parent},
8 | d{new ConflictResolverPrivate()}
9 | {}
10 |
11 | ConflictResolver::~ConflictResolver() = default;
12 |
13 | void ConflictResolver::setDefaults(const Defaults &defaults)
14 | {
15 | d->defaultsName = defaults.setupName();
16 | d->logger = defaults.createLogger(name(), this);
17 | d->settings = defaults.createSettings(this, QString::fromUtf8(name()));
18 | }
19 |
20 | QString ConflictResolver::setupName() const
21 | {
22 | return d->defaultsName;
23 | }
24 |
25 | QByteArray ConflictResolver::name() const
26 | {
27 | return "resolver";
28 | }
29 |
30 | Defaults ConflictResolver::defaults() const
31 | {
32 | return DefaultsPrivate::obtainDefaults(d->defaultsName);
33 | }
34 |
35 | Logger *ConflictResolver::logger() const
36 | {
37 | return d->logger;
38 | }
39 |
40 | QSettings *ConflictResolver::settings() const
41 | {
42 | return d->settings;
43 | }
44 |
--------------------------------------------------------------------------------
/src/messages/devicekeysmessage_p.h:
--------------------------------------------------------------------------------
1 | #ifndef QTDATASYNC_DEVICEKEYSMESSAGE_P_H
2 | #define QTDATASYNC_DEVICEKEYSMESSAGE_P_H
3 |
4 | #include
5 |
6 | #include "message_p.h"
7 |
8 | namespace QtDataSync {
9 |
10 | class Q_DATASYNC_EXPORT DeviceKeysMessage : public Message
11 | {
12 | Q_GADGET
13 |
14 | Q_PROPERTY(quint32 keyIndex MEMBER keyIndex)
15 | Q_PROPERTY(bool duplicated MEMBER duplicated)
16 | Q_PROPERTY(QList devices MEMBER devices)
17 |
18 | public:
19 | using DeviceKey = std::tuple; // (deviceid, scheme, key, mac)
20 |
21 | DeviceKeysMessage(quint32 keyIndex = 0);
22 | DeviceKeysMessage(quint32 keyIndex, QList devices);
23 |
24 | quint32 keyIndex;
25 | bool duplicated;
26 | QList devices;
27 |
28 | protected:
29 | const QMetaObject *getMetaObject() const override;
30 | };
31 |
32 | }
33 |
34 | Q_DECLARE_METATYPE(QtDataSync::DeviceKeysMessage)
35 | Q_DECLARE_METATYPE(QtDataSync::DeviceKeysMessage::DeviceKey)
36 |
37 | #endif // QTDATASYNC_DEVICEKEYSMESSAGE_P_H
38 |
--------------------------------------------------------------------------------
/src/plugins/keystores/android/androidkeystore.h:
--------------------------------------------------------------------------------
1 | #ifndef ANDROIDKEYSTORE_H
2 | #define ANDROIDKEYSTORE_H
3 |
4 | #include
5 |
6 | #include
7 | #include
8 |
9 | class AndroidKeyStore : public QtDataSync::KeyStore
10 | {
11 | Q_OBJECT
12 |
13 | public:
14 | explicit AndroidKeyStore(const QtDataSync::Defaults &defaults, QObject *parent = nullptr);
15 |
16 | QString providerName() const override;
17 | bool isOpen() const override;
18 | void openStore() override;
19 | void closeStore() override;
20 | bool contains(const QString &key) const override;
21 | void save(const QString &key, const QByteArray &pKey) override;
22 | QByteArray load(const QString &key) override;
23 | void remove(const QString &key) override;
24 |
25 | private:
26 | QAndroidJniObject _preferences;
27 |
28 | void jniThrow(QAndroidJniEnvironment &env) const;
29 | QAndroidJniObject prefEditor(QAndroidJniEnvironment &env);
30 | void prefApply(QAndroidJniObject &editor, QAndroidJniEnvironment &env);
31 | };
32 |
33 | #endif // ANDROIDKEYSTORE_H
34 |
--------------------------------------------------------------------------------
/src/plugins/keystores/secretservice/libsecretwrapper.h:
--------------------------------------------------------------------------------
1 | #ifndef LIBSECRETWRAPPER_H
2 | #define LIBSECRETWRAPPER_H
3 |
4 | #include
5 |
6 | //fwd declare
7 | typedef struct _GError GError;
8 | typedef struct _GHashTable GHashTable;
9 | typedef struct _SecretService SecretService;
10 |
11 | class LibSecretException : public std::exception
12 | {
13 | public:
14 | LibSecretException(GError *error = nullptr);
15 | const char *what() const noexcept override;
16 |
17 | private:
18 | const QByteArray _message;
19 | };
20 |
21 | class LibSecretWrapper
22 | {
23 | public:
24 | LibSecretWrapper(const QByteArray &appName);
25 | ~LibSecretWrapper();
26 |
27 | static bool testAvailable();
28 |
29 | bool isOpen() const;
30 | void setup();
31 | void cleanup();
32 |
33 | QByteArray loadSecret(const QByteArray &key);
34 | void storeSecret(const QByteArray &key, const QByteArray &data);
35 | void removeSecret(const QByteArray &key);
36 |
37 | private:
38 | QByteArray _appName;
39 | SecretService *_secret;
40 |
41 | GHashTable *attribs(const QByteArray &key);
42 | };
43 |
44 | #endif // LIBSECRETWRAPPER_H
45 |
--------------------------------------------------------------------------------
/src/messages/errormessage.cpp:
--------------------------------------------------------------------------------
1 | #include "errormessage_p.h"
2 |
3 | #include
4 |
5 | using namespace QtDataSync;
6 |
7 | ErrorMessage::ErrorMessage(ErrorMessage::ErrorType type, QString message, bool canRecover) :
8 | type{type},
9 | message{std::move(message)},
10 | canRecover{canRecover}
11 | {}
12 |
13 | const QMetaObject *ErrorMessage::getMetaObject() const
14 | {
15 | return &staticMetaObject;
16 | }
17 |
18 | bool ErrorMessage::validate()
19 | {
20 | if(!QMetaEnum::fromType().valueToKey(type))
21 | type = ErrorMessage::UnknownError;
22 | return true;
23 | }
24 |
25 | QDebug QtDataSync::operator<<(QDebug debug, const ErrorMessage &message)
26 | {
27 | QDebugStateSaver saver(debug);
28 | debug.nospace().noquote() << "ErrorMessage["
29 | << QMetaEnum::fromType().valueToKey(message.type)
30 | << ", "
31 | << (message.canRecover ? "recoverable" : "unrecoverable")
32 | << "]: "
33 | << (message.message.isNull() ? QStringLiteral("") : static_cast(message.message));
34 | return debug;
35 | }
36 |
--------------------------------------------------------------------------------
/src/messages/devicechangemessage_p.h:
--------------------------------------------------------------------------------
1 | #ifndef QTDATASYNC_DEVICECHANGEMESSAGE_P_H
2 | #define QTDATASYNC_DEVICECHANGEMESSAGE_P_H
3 |
4 | #include
5 |
6 | #include "message_p.h"
7 | #include "changemessage_p.h"
8 |
9 | namespace QtDataSync {
10 |
11 | class Q_DATASYNC_EXPORT DeviceChangeMessage : public ChangeMessage
12 | {
13 | Q_GADGET
14 |
15 | Q_PROPERTY(QUuid deviceId MEMBER deviceId)
16 |
17 | public:
18 | DeviceChangeMessage(QByteArray dataId = {}, QUuid deviceId = {});
19 |
20 | QUuid deviceId;
21 |
22 | protected:
23 | const QMetaObject *getMetaObject() const override;
24 | };
25 |
26 | class Q_DATASYNC_EXPORT DeviceChangeAckMessage : public ChangeAckMessage
27 | {
28 | Q_GADGET
29 |
30 | Q_PROPERTY(QUuid deviceId MEMBER deviceId)
31 |
32 | public:
33 | DeviceChangeAckMessage(const DeviceChangeMessage &message = {});
34 |
35 | QUuid deviceId;
36 |
37 | protected:
38 | const QMetaObject *getMetaObject() const override;
39 | };
40 |
41 | }
42 |
43 | Q_DECLARE_METATYPE(QtDataSync::DeviceChangeMessage)
44 | Q_DECLARE_METATYPE(QtDataSync::DeviceChangeAckMessage)
45 |
46 | #endif // QTDATASYNC_DEVICECHANGEMESSAGE_P_H
47 |
--------------------------------------------------------------------------------
/examples/datasync/Sample/accountdialog.h:
--------------------------------------------------------------------------------
1 | #ifndef ACCOUNTDIALOG_H
2 | #define ACCOUNTDIALOG_H
3 |
4 | #include
5 | #include
6 |
7 | #include
8 |
9 | namespace Ui {
10 | class AccountDialog;
11 | }
12 |
13 | class AccountDialog : public QDialog
14 | {
15 | Q_OBJECT
16 |
17 | public:
18 | explicit AccountDialog(const QString &setup, QWidget *parent = nullptr);
19 | ~AccountDialog();
20 |
21 | static void exec(const QString &setup, QWidget *parent = nullptr);
22 |
23 | private Q_SLOTS:
24 | void updateDevices(const QList &devices);
25 | void login(QtDataSync::LoginRequest request);
26 | void importDone();
27 | void engineError(const QString &error);
28 |
29 | void on_action_Remove_Device_triggered();
30 | void on_buttonBox_clicked(QAbstractButton *button);
31 | void on_pushButton_clicked();
32 | void on_pushButton_2_clicked();
33 |
34 | void on_exchangeButton_clicked();
35 |
36 | private:
37 | Ui::AccountDialog *ui;
38 | QtDataSync::AccountManager *_manager;
39 |
40 | static QString printFingerprint(const QByteArray &fingerprint);
41 | };
42 |
43 | #endif // ACCOUNTDIALOG_H
44 |
--------------------------------------------------------------------------------
/src/datasync/rothreadedbackend/exchangebufferserver_p.h:
--------------------------------------------------------------------------------
1 | #ifndef EXCHANGEBUFFERSERVER_P_H
2 | #define EXCHANGEBUFFERSERVER_P_H
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | #include "qtdatasync_global.h"
10 | #include "exchangebuffer_p.h"
11 | #include "qtrotransportregistry.h"
12 |
13 | namespace QtDataSync {
14 |
15 | class Q_DATASYNC_EXPORT ExchangeBufferServer : public QObject
16 | {
17 | Q_OBJECT
18 |
19 | public:
20 | static const QString UrlScheme();
21 | static bool connectTo(const QUrl &url,
22 | ExchangeBuffer *clientBuffer,
23 | bool allowCaching = true);
24 |
25 | explicit ExchangeBufferServer(QRemoteObjectHostBase *host);
26 |
27 | bool registerInstance(const QUrl &url);
28 |
29 | private Q_SLOTS:
30 | void addConnection(ExchangeBuffer *clientBuffer);
31 |
32 | private:
33 | static QMutex _lock;
34 | static QHash _servers;
35 | static QMultiHash> _connectCache;
36 |
37 | QRemoteObjectHostBase *_host;
38 | QUrl _listenAddress;
39 | };
40 |
41 | }
42 |
43 | #endif // EXCHANGEBUFFERSERVER_P_H
44 |
--------------------------------------------------------------------------------
/tests/auto/qml/TestQmlDataSync/tst_qmldatasync.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.5
2 | import de.skycoder42.QtDataSync 4.2
3 | import QtTest 1.1
4 |
5 | Item {
6 | id: root
7 |
8 | TestCase {
9 | name: "DataStore"
10 |
11 | DataStore {
12 | id: store
13 | }
14 |
15 | DataStoreModel {
16 | id: storeModel1
17 | }
18 |
19 | DataStoreModel {
20 | id: storeModel2
21 | dataStore: store
22 | }
23 |
24 | SyncManager {
25 | id: syncManager
26 | }
27 |
28 | AccountManager {
29 | id: accountManager
30 | }
31 |
32 | UserExchangeManager {
33 | id: exchangeManager1
34 | }
35 |
36 | UserExchangeManager {
37 | id: exchangeManager2
38 | manager: accountManager
39 | }
40 |
41 | property EventCursor cursor: null
42 |
43 | function test_valid() {
44 | verify(store.valid);
45 | verify(storeModel1.valid);
46 | verify(storeModel2.valid);
47 | verify(syncManager.valid);
48 | verify(accountManager.valid);
49 | verify(exchangeManager1.valid);
50 | verify(exchangeManager2.valid);
51 |
52 | cursor = EventLog.first();
53 | expectFail("", "No cursor until data was changed");
54 | verify(cursor.valid);
55 | }
56 | }
57 |
58 | }
59 |
--------------------------------------------------------------------------------
/src/messages/changemessage_p.h:
--------------------------------------------------------------------------------
1 | #ifndef QTDATASYNC_CHANGEMESSAGE_P_H
2 | #define QTDATASYNC_CHANGEMESSAGE_P_H
3 |
4 | #include "message_p.h"
5 |
6 | namespace QtDataSync {
7 |
8 | class Q_DATASYNC_EXPORT ChangeMessage : public Message
9 | {
10 | Q_GADGET
11 |
12 | Q_PROPERTY(QByteArray dataId MEMBER dataId)
13 | Q_PROPERTY(quint32 keyIndex MEMBER keyIndex)
14 | Q_PROPERTY(QByteArray salt MEMBER salt)
15 | Q_PROPERTY(QByteArray data MEMBER data)
16 |
17 | public:
18 | ChangeMessage(QByteArray dataId = {});
19 |
20 | QByteArray dataId;
21 | quint32 keyIndex = 0;
22 | QByteArray salt;
23 | QByteArray data;
24 |
25 | protected:
26 | const QMetaObject *getMetaObject() const override;
27 | };
28 |
29 | class Q_DATASYNC_EXPORT ChangeAckMessage : public Message
30 | {
31 | Q_GADGET
32 |
33 | Q_PROPERTY(QByteArray dataId MEMBER dataId)
34 |
35 | public:
36 | ChangeAckMessage(const ChangeMessage &message = {});
37 |
38 | QByteArray dataId;
39 |
40 | protected:
41 | const QMetaObject *getMetaObject() const override;
42 | };
43 |
44 | }
45 |
46 | Q_DECLARE_METATYPE(QtDataSync::ChangeMessage)
47 | Q_DECLARE_METATYPE(QtDataSync::ChangeAckMessage)
48 |
49 | #endif // QTDATASYNC_CHANGEMESSAGE_P_H
50 |
--------------------------------------------------------------------------------
/tools/appserver/clientconnector.h:
--------------------------------------------------------------------------------
1 | #ifndef CLIENTCONNECTOR_H
2 | #define CLIENTCONNECTOR_H
3 |
4 | #include "client.h"
5 | #include "databasecontroller.h"
6 |
7 | #include
8 | #include
9 |
10 | class ClientConnector : public QObject
11 | {
12 | Q_OBJECT
13 | public:
14 | explicit ClientConnector(DatabaseController *database, QObject *parent = nullptr);
15 |
16 | void recreateServer();
17 | bool setupWss();
18 | bool listen();
19 | void close();
20 |
21 | void setPaused(bool paused);
22 |
23 | public Q_SLOTS:
24 | void notifyChanged(QUuid deviceId);
25 |
26 | Q_SIGNALS:
27 | void disconnectAll();
28 |
29 | private Q_SLOTS:
30 | void verifySecret(QWebSocketCorsAuthenticator *authenticator);
31 | void newConnection();
32 | void serverError();
33 | void sslErrors(const QList &errors);
34 |
35 | void clientConnected(QUuid deviceId);
36 | void proofRequested(QUuid partner, const QtDataSync::ProofMessage &message);
37 | void forceDisconnect(QUuid partner);
38 |
39 | private:
40 | DatabaseController *database;
41 | QWebSocketServer *server = nullptr;
42 | QString secret;
43 | bool isActivated = false;
44 |
45 | QHash clients;
46 | };
47 |
48 | #endif // CLIENTCONNECTOR_H
49 |
--------------------------------------------------------------------------------
/src/datasync/eventcursor_p.h:
--------------------------------------------------------------------------------
1 | #ifndef QTDATASYNC_EVENTCURSOR_P_H
2 | #define QTDATASYNC_EVENTCURSOR_P_H
3 |
4 | #include
5 |
6 | #include "eventcursor.h"
7 |
8 | #include "defaults.h"
9 | #include "emitteradapter_p.h"
10 |
11 | namespace QtDataSync {
12 |
13 | class EventCursorPrivate
14 | {
15 | friend class QtDataSync::EventCursor;
16 |
17 | public:
18 | EventCursorPrivate(const QString &setupName, EventCursor *q_ptr);
19 |
20 | static bool isLogActive(const Defaults &defaults, DatabaseRef &database);
21 | static void initDatabase(const Defaults &defaults, DatabaseRef &database, Logger *logger, bool createTriggers);
22 | static void clearEventLog(const Defaults &defaults, DatabaseRef &database);
23 |
24 | private:
25 | void exec(QSqlQuery &query, quint64 qIndex = 0) const;
26 | void readQuery(const QSqlQuery &query);
27 | void prepareNextQuery(QSqlQuery &query, bool withData) const;
28 |
29 | Defaults defaults;
30 | DatabaseRef database;
31 | EmitterAdapter *emitter;
32 | Logger *logger;
33 |
34 | quint64 index = 0;
35 | QtDataSync::ObjectKey key;
36 | bool wasRemoved = false;
37 | QDateTime timestamp;
38 |
39 | bool skipObsolete = true;
40 | };
41 |
42 | }
43 |
44 | #endif // QTDATASYNC_EVENTCURSOR_P_H
45 |
--------------------------------------------------------------------------------
/src/datasyncios/iossyncdelegate_p.h:
--------------------------------------------------------------------------------
1 | #ifndef QTDATASYNC_IOSSYNCDELEGATE_P_H
2 | #define QTDATASYNC_IOSSYNCDELEGATE_P_H
3 |
4 | #include "iossyncdelegate.h"
5 |
6 | #include
7 | #include
8 |
9 | namespace QtDataSync {
10 |
11 | class IosSyncDelegatePrivate
12 | {
13 | friend class IosSyncDelegate;
14 |
15 | public:
16 | static void performFetch(std::function callback);
17 |
18 | private:
19 | static const QString SyncStateGroup;
20 | static const QString SyncIntervalKey;
21 | static const QString SyncEnabledKey;
22 | static const QString SyncWaitKey;
23 |
24 | static QPointer delegateInstance;
25 |
26 | IosSyncDelegatePrivate(QSettings *settings, IosSyncDelegate *q_ptr);
27 |
28 | IosSyncDelegate *q;
29 | bool enabled = true;
30 | std::chrono::minutes interval{60};
31 | bool waitFullSync = false;
32 |
33 | QSettings *settings;
34 | QtDataSync::SyncManager *manager = nullptr;
35 | bool allowUpdateSync = false;
36 |
37 | std::function currentCallback;
38 |
39 | void updateSyncInterval();
40 | void storeState();
41 | void onSyncDone(SyncManager::SyncState state);
42 | };
43 |
44 | }
45 |
46 | #endif // QTDATASYNC_IOSSYNCDELEGATE_P_H
47 |
--------------------------------------------------------------------------------
/src/datasync/datastoremodel_p.h:
--------------------------------------------------------------------------------
1 | #ifndef QTDATASYNC_DATASTOREMODEL_P_H
2 | #define QTDATASYNC_DATASTOREMODEL_P_H
3 |
4 | #include "qtdatasync_global.h"
5 | #include "datastoremodel.h"
6 |
7 | namespace QtDataSync {
8 |
9 | //no export needed
10 | class DataStoreModelPrivate
11 | {
12 | public:
13 | DataStoreModelPrivate(DataStoreModel *q_ptr);
14 |
15 | DataStoreModel *q;
16 | DataStore *store = nullptr;
17 | bool editable = false;
18 |
19 | int type = QMetaType::UnknownType;
20 | bool isObject = false;
21 | QHash roleNames;
22 |
23 | QStringList keyList;
24 | QVariantHash dataHash;
25 |
26 | QStringList columns;
27 | QHash> roleMapping; //column -> (role -> property)
28 |
29 | bool isFetching = false;
30 |
31 | QStringList activeKeys();
32 |
33 | void createRoleNames();
34 | void clearHashObjects();
35 | void deleteObject(const QVariant &value);
36 | bool testRoleValid(const QModelIndex &index, int role) const;
37 | QByteArray propertyName(const QModelIndex &index, int role) const;
38 |
39 | QVariant readProperty(const QString &key, const QByteArray &property);
40 | bool writeProperty(const QString &key, const QByteArray &property, const QVariant &value);
41 | };
42 |
43 | }
44 | #endif // QTDATASYNC_DATASTOREMODEL_P_H
45 |
--------------------------------------------------------------------------------
/src/datasync/migrationhelper_p.h:
--------------------------------------------------------------------------------
1 | #ifndef QTDATASYNC_MIGRATIONHELPER_P_H
2 | #define QTDATASYNC_MIGRATIONHELPER_P_H
3 |
4 | #include
5 | #include
6 |
7 | #include "qtdatasync_global.h"
8 | #include "migrationhelper.h"
9 | #include "defaults.h"
10 |
11 | namespace QtDataSync {
12 |
13 | class MigrationRunnable : public QRunnable
14 | {
15 | Q_DISABLE_COPY(MigrationRunnable)
16 | public:
17 | MigrationRunnable(Defaults defaults,
18 | MigrationHelper *helper,
19 | QString oldDir,
20 | MigrationHelper::MigrationFlags flags);
21 |
22 | void run() override;
23 |
24 | private:
25 | Defaults _defaults;
26 | const QPointer _helper;
27 | const QString _oldDir;
28 | const MigrationHelper::MigrationFlags _flags;
29 |
30 | QPointer _logger;
31 | int _progress = 0;
32 |
33 | void migrationPrepared(int count);
34 | void migrationProgress();
35 | void migrationDone(bool ok);
36 |
37 | void copyConf(QSettings *old, const QString &oldKey, QSettings *current, const QString &newKey) const;
38 | };
39 |
40 | class MigrationHelperPrivate
41 | {
42 | public:
43 | MigrationHelperPrivate(const QString &setupName);
44 |
45 | Defaults defaults;
46 | };
47 |
48 | }
49 |
50 | #endif // QTDATASYNC_MIGRATIONHELPER_P_H
51 |
--------------------------------------------------------------------------------
/src/messages/proofmessage.cpp:
--------------------------------------------------------------------------------
1 | #include "proofmessage_p.h"
2 | using namespace QtDataSync;
3 |
4 | ProofMessage::ProofMessage() = default;
5 |
6 | ProofMessage::ProofMessage(const AccessMessage &access, QUuid deviceId) :
7 | pNonce{access.pNonce},
8 | deviceId{deviceId},
9 | deviceName{access.deviceName},
10 | signAlgorithm{access.signAlgorithm},
11 | signKey{access.signKey},
12 | cryptAlgorithm{access.cryptAlgorithm},
13 | cryptKey{access.cryptKey},
14 | macscheme{access.macscheme},
15 | cmac{access.cmac},
16 | trustmac{access.trustmac}
17 | {}
18 |
19 | const QMetaObject *ProofMessage::getMetaObject() const
20 | {
21 | return &staticMetaObject;
22 | }
23 |
24 |
25 |
26 | DenyMessage::DenyMessage(QUuid deviceId) :
27 | deviceId{deviceId}
28 | {}
29 |
30 | const QMetaObject *DenyMessage::getMetaObject() const
31 | {
32 | return &staticMetaObject;
33 | }
34 |
35 |
36 |
37 | AcceptMessage::AcceptMessage(QUuid deviceId) :
38 | deviceId{deviceId}
39 | {}
40 |
41 | const QMetaObject *AcceptMessage::getMetaObject() const
42 | {
43 | return &staticMetaObject;
44 | }
45 |
46 |
47 |
48 | AcceptAckMessage::AcceptAckMessage(QUuid deviceId) :
49 | deviceId{deviceId}
50 | {}
51 |
52 | const QMetaObject *AcceptAckMessage::getMetaObject() const
53 | {
54 | return &staticMetaObject;
55 | }
56 |
--------------------------------------------------------------------------------
/appveyor.yml:
--------------------------------------------------------------------------------
1 | image:
2 | - Visual Studio 2017
3 |
4 | version: build-{build}
5 |
6 | environment:
7 | QT_VER: 5.13.1
8 | EXTRA_MODULES: .skycoder42.jsonserializer;.skycoder42.service
9 | MAKE_RUN_TESTS: true
10 | TARGET_NAME: qtdatasync
11 |
12 | matrix:
13 | - PLATFORM: msvc2017_64
14 | - PLATFORM: mingw73_64
15 | - PLATFORM: mingw73_32
16 | - PLATFORM: winrt_x64_msvc2017
17 | - PLATFORM: msvc2017
18 | - PLATFORM: winrt_x86_msvc2017
19 | - PLATFORM: winrt_armv7_msvc2017
20 |
21 | install:
22 | - git submodule init
23 | - git submodule update
24 | - git clone https://github.com/Skycoder42/QtModules.git .\qtmodules-travis
25 | - .\qtmodules-travis\ci\win\setup.bat
26 |
27 | build_script:
28 | - if "%PLATFORM%" == "mingw73_32" set NO_TESTS=true
29 | - .\qtmodules-travis\ci\win\build.bat
30 |
31 | after_build:
32 | - .\qtmodules-travis\ci\win\upload-prepare.bat
33 |
34 | artifacts:
35 | - path: install\%TARGET_NAME%_*_%QT_VER%.zip
36 |
37 | deploy:
38 | provider: GitHub
39 | auth_token:
40 | secure: Cp5GRQku2ZWnKPE12NB5q11ZO0Fr5mlzdUTjnLpYJr/dki4LPVqm231edFggogy8
41 | artifact: /.*\.zip/
42 | force_update: false
43 | on:
44 | appveyor_repo_tag: true
45 |
46 | cache:
47 | - 'C:\Users\appveyor\AppData\Local\qdep\qdep\Cache -> appveyor.yml'
48 |
--------------------------------------------------------------------------------
/src/messages/errormessage_p.h:
--------------------------------------------------------------------------------
1 | #ifndef QTDATASYNC_ERRORMESSAGE_P_H
2 | #define QTDATASYNC_ERRORMESSAGE_P_H
3 |
4 | #include
5 |
6 | #include "message_p.h"
7 |
8 | namespace QtDataSync {
9 |
10 | class Q_DATASYNC_EXPORT ErrorMessage : public Message
11 | {
12 | Q_GADGET
13 |
14 | Q_PROPERTY(ErrorType type MEMBER type)
15 | Q_PROPERTY(QtDataSync::Utf8String message MEMBER message)
16 | Q_PROPERTY(bool canRecover MEMBER canRecover)
17 |
18 | public:
19 | enum ErrorType {
20 | UnknownError = 0,
21 | IncompatibleVersionError = 1,
22 | UnexpectedMessageError = 2,
23 | ServerError = 3,
24 | ClientError = 4,
25 | AuthenticationError = 5,
26 | AccessError = 6,
27 | KeyIndexError = 7,
28 | KeyPendingError = 8,
29 | QuotaHitError = 9
30 | };
31 | Q_ENUM(ErrorType)
32 |
33 | ErrorMessage(ErrorType type = UnknownError,
34 | QString message = {},
35 | bool canRecover = false);
36 |
37 | ErrorType type;
38 | Utf8String message;
39 | bool canRecover;
40 |
41 | protected:
42 | const QMetaObject *getMetaObject() const override;
43 | bool validate() override;
44 | };
45 |
46 | Q_DATASYNC_EXPORT QDebug operator<<(QDebug debug, const ErrorMessage &message);
47 |
48 | }
49 |
50 | Q_DECLARE_METATYPE(QtDataSync::ErrorMessage)
51 |
52 | #endif // QTDATASYNC_ERRORMESSAGE_P_H
53 |
--------------------------------------------------------------------------------
/src/datasync/userexchangemanager_p.h:
--------------------------------------------------------------------------------
1 | #ifndef QTDATASYNC_USEREXCHANGEMANAGER_P_H
2 | #define QTDATASYNC_USEREXCHANGEMANAGER_P_H
3 |
4 | #include
5 | #include
6 |
7 | #include
8 | #include
9 |
10 | #include "qtdatasync_global.h"
11 | #include "userexchangemanager.h"
12 | #include "accountmanager.h"
13 | #include "logger.h"
14 |
15 | namespace QtDataSync {
16 |
17 | //no export needed
18 | class UserInfoPrivate : public QSharedData
19 | {
20 | public:
21 | UserInfoPrivate(QString name = {}, const QNetworkDatagram &datagram = {});
22 | UserInfoPrivate(const UserInfoPrivate &other);
23 |
24 | QString name;
25 | QHostAddress address;
26 | quint16 port;
27 | };
28 |
29 | //no export needed
30 | class UserExchangeManagerPrivate
31 | {
32 | public:
33 | enum DatagramType {
34 | DeviceInfo,
35 | DeviceDataUntrusted,
36 | DeviceDataTrusted
37 | };
38 |
39 | UserExchangeManagerPrivate(UserExchangeManager *q_ptr);
40 |
41 | AccountManager *manager = nullptr;
42 | QPointer socket;
43 | QTimer *timer;
44 |
45 | bool allowReuseAddress = false;
46 | QHash devices;
47 | QHash exchangeData;
48 |
49 | void clearSocket();
50 | };
51 |
52 | }
53 |
54 | #endif // QTDATASYNC_USEREXCHANGEMANAGER_P_H
55 |
--------------------------------------------------------------------------------
/src/messages/accessmessage_p.h:
--------------------------------------------------------------------------------
1 | #ifndef QTDATASYNC_ACCESSMESSAGE_P_H
2 | #define QTDATASYNC_ACCESSMESSAGE_P_H
3 |
4 | #include
5 |
6 | #include "message_p.h"
7 | #include "registermessage_p.h"
8 |
9 | namespace QtDataSync {
10 |
11 | class Q_DATASYNC_EXPORT AccessMessage : public RegisterBaseMessage
12 | {
13 | Q_GADGET
14 |
15 | Q_PROPERTY(QByteArray pNonce MEMBER pNonce)
16 | Q_PROPERTY(QUuid partnerId MEMBER partnerId)
17 | Q_PROPERTY(QByteArray macscheme MEMBER macscheme)
18 | Q_PROPERTY(QByteArray cmac MEMBER cmac)
19 | Q_PROPERTY(QByteArray trustmac MEMBER trustmac)
20 |
21 | public:
22 | AccessMessage();
23 | AccessMessage(QString deviceName,
24 | QByteArray nonce,
25 | const QSharedPointer &signKey,
26 | const QSharedPointer &cryptKey,
27 | AsymmetricCrypto *crypto,
28 | QByteArray pNonce,
29 | QUuid partnerId,
30 | QByteArray macscheme,
31 | QByteArray cmac,
32 | QByteArray trustmac);
33 |
34 | QByteArray pNonce;
35 | QUuid partnerId;
36 | QByteArray macscheme;
37 | QByteArray cmac;
38 | QByteArray trustmac;
39 |
40 | protected:
41 | const QMetaObject *getMetaObject() const override;
42 | };
43 |
44 | }
45 |
46 | Q_DECLARE_METATYPE(QtDataSync::AccessMessage)
47 |
48 | #endif // QTDATASYNC_ACCESSMESSAGE_P_H
49 |
--------------------------------------------------------------------------------
/examples/datasync/AndroidSync/main.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include "syncservice.h"
6 |
7 | namespace {
8 |
9 | //! [activity_main]
10 | int activityMain(int argc, char *argv[])
11 | {
12 | QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
13 | QGuiApplication app(argc, argv);
14 |
15 | QAndroidJniObject::callStaticMethod("de/skycoder42/qtdatasync/sample/androidsync/SvcHelper",
16 | "registerNotificationChannel",
17 | "(Landroid/content/Context;)V",
18 | QtAndroid::androidContext().object());
19 |
20 | QQmlApplicationEngine engine;
21 | engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
22 | if (engine.rootObjects().isEmpty())
23 | return -1;
24 |
25 | return app.exec();
26 | }
27 | //! [activity_main]
28 |
29 | //! [service_main]
30 | int serviceMain(int argc, char *argv[])
31 | {
32 | SyncService service{argc, argv};
33 | return service.exec();
34 | }
35 | //! [service_main]
36 |
37 | }
38 |
39 | //! [actual_main]
40 | int main(int argc, char *argv[])
41 | {
42 | for(auto i = 0; i < argc; i++) {
43 | if(qstrcmp(argv[i], "--backend") == 0)
44 | return serviceMain(argc, argv);
45 | }
46 | return activityMain(argc, argv);
47 | }
48 | //! [actual_main]
49 |
50 |
--------------------------------------------------------------------------------
/src/messages/newkeymessage_p.h:
--------------------------------------------------------------------------------
1 | #ifndef QTDATASYNC_NEWKEYMESSAGE_P_H
2 | #define QTDATASYNC_NEWKEYMESSAGE_P_H
3 |
4 | #include
5 |
6 | #include "message_p.h"
7 | #include "macupdatemessage_p.h"
8 |
9 | namespace QtDataSync {
10 |
11 | class Q_DATASYNC_EXPORT NewKeyMessage : public MacUpdateMessage
12 | {
13 | Q_GADGET
14 |
15 | Q_PROPERTY(QByteArray scheme MEMBER scheme)
16 | Q_PROPERTY(QList deviceKeys MEMBER deviceKeys)
17 |
18 | public:
19 | using KeyUpdate = std::tuple; //(deviceId, key, cmac)
20 |
21 | QByteArray scheme;
22 | QList deviceKeys;
23 |
24 | QByteArray signatureData(const KeyUpdate &deviceInfo) const;
25 |
26 | protected:
27 | const QMetaObject *getMetaObject() const override;
28 | };
29 |
30 | class Q_DATASYNC_EXPORT NewKeyAckMessage : public MacUpdateAckMessage
31 | {
32 | Q_GADGET
33 |
34 | Q_PROPERTY(quint32 keyIndex MEMBER keyIndex)
35 |
36 | public:
37 | NewKeyAckMessage(const NewKeyMessage &message = {});
38 |
39 | quint32 keyIndex;
40 |
41 | protected:
42 | const QMetaObject *getMetaObject() const override;
43 | };
44 |
45 | }
46 |
47 | Q_DECLARE_METATYPE(QtDataSync::NewKeyMessage)
48 | Q_DECLARE_METATYPE(QtDataSync::NewKeyMessage::KeyUpdate)
49 | Q_DECLARE_METATYPE(QtDataSync::NewKeyAckMessage)
50 |
51 | #endif // QTDATASYNC_NEWKEYMESSAGE_P_H
52 |
--------------------------------------------------------------------------------
/tests/auto/datasync/tests.pri:
--------------------------------------------------------------------------------
1 | TEMPLATE = app
2 |
3 | QT = core testlib datasync-private
4 |
5 | CONFIG += console
6 | CONFIG -= app_bundle
7 |
8 | DEFINES += SRCDIR=\\\"$$_PRO_FILE_PWD_/\\\"
9 |
10 | linux: BUILD_LIB_DIR = $$shadowed($$dirname(_QMAKE_CONF_))/lib
11 | else: BUILD_LIB_DIR = $$OUT_PWD/../TestLib/
12 |
13 | win32:CONFIG(release, debug|release): LIBS += -L$$BUILD_LIB_DIR/release -lTestLib
14 | else:win32:CONFIG(debug, debug|release): LIBS += -L$$BUILD_LIB_DIR/debug -lTestLib
15 | else:unix: LIBS += -L$$BUILD_LIB_DIR -lTestLib
16 |
17 | INCLUDEPATH += $$PWD/TestLib
18 | DEPENDPATH += $$PWD/TestLib
19 |
20 | !linux {
21 | win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../TestLib/release/libTestLib.a
22 | else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../TestLib/debug/libTestLib.a
23 | else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../TestLib/release/TestLib.lib
24 | else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../TestLib/debug/TestLib.lib
25 | else:unix: PRE_TARGETDEPS += $$OUT_PWD/../TestLib/libTestLib.a
26 | }
27 |
28 | INCLUDEPATH += $$PWD/../../../src/messages
29 |
30 | DEFINES += KEYSTORE_PATH=\\\"$$OUT_PWD/../../../../plugins/keystores/\\\"
31 |
32 | include($$PWD/../../../src/3rdparty/cryptopp/cryptopp.pri)
33 | include($$PWD/../testrun.pri)
34 |
--------------------------------------------------------------------------------
/src/datasync/logger.cpp:
--------------------------------------------------------------------------------
1 | #include "logger.h"
2 | #include "logger_p.h"
3 | #include "setup_p.h"
4 | using namespace QtDataSync;
5 |
6 | Logger::Logger(QByteArray subCategory, const QString &setupName, QObject *parent) :
7 | QObject{parent},
8 | d{new LoggerPrivate(setupName, std::move(subCategory))}
9 | {}
10 |
11 | Logger::~Logger() = default;
12 |
13 | const QLoggingCategory &Logger::loggingCategory() const
14 | {
15 | return d->logCat;
16 | }
17 |
18 | void Logger::reportFatalError(const QString &error, const char *file, int line, const char *function)
19 | {
20 | QMessageLogger logger(file, line, function, d->logCat.categoryName());
21 | logger.critical("%s", qUtf8Printable(error));
22 |
23 | try {
24 | SetupPrivate::engine(d->setupName)->enterFatalState(error, file, line, function, d->logCat.categoryName());
25 | } catch(...) {
26 | logger.fatal("%s", qUtf8Printable(error));
27 | }
28 | }
29 |
30 | void Logger::reportFatalError(const char *error, const char *file, int line, const char *function)
31 | {
32 | reportFatalError(QString::fromUtf8(error), file, line, function);
33 | }
34 |
35 | // ------------- PRIVATE IMPLEMENTATION -------------
36 |
37 | LoggerPrivate::LoggerPrivate(QString setupName, const QByteArray &subCategory) :
38 | setupName{std::move(setupName)},
39 | catName{"qtdatasync." + this->setupName.toUtf8() + "." + subCategory},
40 | logCat{catName.constData(), QtInfoMsg}
41 | {}
42 |
--------------------------------------------------------------------------------
/tools/appserver/datasyncservice.h:
--------------------------------------------------------------------------------
1 | #ifndef DATASYNCSERVICE_H
2 | #define DATASYNCSERVICE_H
3 |
4 | #include
5 |
6 | #include
7 | #include
8 |
9 | #include "clientconnector.h"
10 | #include "databasecontroller.h"
11 |
12 | class DatasyncService : public QtService::Service
13 | {
14 | Q_OBJECT
15 |
16 | public:
17 | enum ServiceCodes {
18 | CodeOffset = 128,
19 | CleanupCode
20 | };
21 | Q_ENUM(ServiceCodes)
22 |
23 | explicit DatasyncService(int &argc, char **argv);
24 |
25 | const QSettings *configuration() const;
26 | QThreadPool *threadPool() const;
27 | QString absolutePath(const QString &path) const;
28 |
29 | protected:
30 | CommandResult onStart() override;
31 | CommandResult onStop(int &exitCode) override;
32 | CommandResult onReload() override;
33 | CommandResult onPause() override;
34 | CommandResult onResume() override;
35 |
36 | private Q_SLOTS:
37 | void completeStartup(bool ok);
38 |
39 | private:
40 | const QSettings *_config;
41 | QThreadPool *_mainPool;
42 | ClientConnector *_connector;
43 | DatabaseController *_database;
44 |
45 | QString findConfig() const;
46 |
47 | void sigusr1();
48 | void command(int cmd);
49 | void setLogLevel();
50 | void setupThreadPool();
51 | };
52 |
53 | #undef qService
54 | #define qService static_cast(QtService::Service::instance())
55 |
56 | #endif // DATASYNCSERVICE_H
57 |
--------------------------------------------------------------------------------
/src/datasync/accountmanager_p.rep:
--------------------------------------------------------------------------------
1 | #include "qtdatasync_global.h"
2 | #include "accountmanager.h"
3 |
4 | class AccountManagerPrivate {
5 | PROP(QString setupName READONLY)
6 | PROP(QString deviceName READWRITE);
7 | PROP(QByteArray deviceFingerprint READONLY);
8 | PROP(QString lastError READONLY);
9 |
10 | SLOT(void listDevices());
11 | SLOT(void removeDevice(QUuid deviceId));
12 | SLOT(void updateExchangeKey());
13 | SLOT(void resetAccount(bool keepData));
14 | SLOT(void changeRemote(const QtDataSync::RemoteConfig &config, bool keepData));
15 | SLOT(void exportAccount(QUuid id, bool includeServer));
16 | SLOT(void exportAccountTrusted(QUuid id, bool includeServer, const QString &password));
17 | SLOT(void importAccount(const QtDataSync::JsonObject &importData, bool keepData));
18 | SLOT(void importAccountTrusted(const QtDataSync::JsonObject &importData, const QString &password, bool keepData));
19 | SLOT(void replyToLogin(QUuid deviceId, bool accept));
20 |
21 | SIGNAL(accountDevices(const QList &devices));
22 | SIGNAL(accountExportReady(QUuid id, const QtDataSync::JsonObject &exportData));
23 | SIGNAL(accountExportError(QUuid id, const QString &errorString));
24 | SIGNAL(accountImportResult(bool success, const QString &error));
25 | SIGNAL(loginRequested(const QtDataSync::DeviceInfo &deviceInfo));
26 | SIGNAL(importCompleted());
27 | SIGNAL(accountAccessGranted(QUuid deviceId));
28 | };
29 |
--------------------------------------------------------------------------------
/src/datasync/rothreadedbackend/exchangebuffer_p.h:
--------------------------------------------------------------------------------
1 | #ifndef EXCHANGEBUFFER_P_H
2 | #define EXCHANGEBUFFER_P_H
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | #include "qtdatasync_global.h"
10 |
11 | namespace QtDataSync {
12 |
13 | class Q_DATASYNC_EXPORT ExchangeBuffer : public QIODevice
14 | {
15 | Q_OBJECT
16 |
17 | public:
18 | explicit ExchangeBuffer(QObject *parent = nullptr);
19 | ~ExchangeBuffer() override;
20 |
21 | bool connectTo(ExchangeBuffer *partner, bool blocking = false);
22 |
23 | bool isSequential() const override;
24 | void close() override;
25 | qint64 bytesAvailable() const override;
26 |
27 | Q_SIGNALS:
28 | void partnerConnected(QPrivateSignal);
29 | void partnerDisconnected(QPrivateSignal);
30 | void disconnected(QPrivateSignal); //alias signal of partnerDisconnected for remote objects (naming convention)
31 |
32 | protected:
33 | qint64 readData(char *data, qint64 maxlen) override;
34 | qint64 writeData(const char *data, qint64 len) override;
35 |
36 | private Q_SLOTS:
37 | bool openInteral(ExchangeBuffer *partner);
38 | void receiveData(const QByteArray &data);
39 | void partnerClosed();
40 |
41 | private:
42 | QPointer _partner;
43 |
44 | QQueue _buffers;
45 | int _index;
46 | qint64 _size;
47 |
48 | bool open(OpenMode mode) override;
49 | };
50 |
51 | }
52 |
53 | Q_DECLARE_LOGGING_CATEGORY(rothreadedbackend)
54 |
55 | #endif // EXCHANGEBUFFER_P_H
56 |
--------------------------------------------------------------------------------
/src/datasync/controller_p.h:
--------------------------------------------------------------------------------
1 | #ifndef QTDATASYNC_CONTROLLER_P_H
2 | #define QTDATASYNC_CONTROLLER_P_H
3 |
4 | #include
5 |
6 | #include
7 | #include
8 | #include
9 |
10 | #include "qtdatasync_global.h"
11 | #include "defaults.h"
12 | #include "logger.h"
13 |
14 | namespace QtDataSync {
15 |
16 | class Q_DATASYNC_EXPORT Controller : public QObject
17 | {
18 | Q_OBJECT
19 |
20 | public:
21 | explicit Controller(const QByteArray &name,
22 | Defaults defaults,
23 | QObject *parent = nullptr);
24 |
25 | virtual void initialize(const QVariantHash ¶ms); //exceptions are allowed!
26 | virtual void finalize();
27 |
28 | Q_SIGNALS:
29 | void controllerError(const QString &error);
30 | void operationTimeout();
31 | void specialOperationTimeout();
32 | void progressAdded(quint32 delta);
33 | void progressIncrement();
34 |
35 | protected:
36 | Defaults defaults() const;
37 | Logger *logger() const;
38 | QSettings *settings() const;
39 |
40 | void beginOp(std::chrono::minutes interval = std::chrono::minutes(5),
41 | bool startIfNotRunning = true);
42 | void beginSpecialOp(std::chrono::minutes interval);
43 | void endOp();
44 |
45 | private Q_SLOTS:
46 | void onTimeout();
47 |
48 | private:
49 | Defaults _defaults;
50 | Logger *_logger;
51 | QSettings *_settings;
52 | QTimer *_opTimer;
53 |
54 | QDeadlineTimer _specialOp;
55 | };
56 |
57 | }
58 |
59 | #define QTDATASYNC_LOG_CONTROLLER logger()
60 |
61 | #endif // QTDATASYNC_CONTROLLER_P_H
62 |
--------------------------------------------------------------------------------
/src/datasync/changeemitter_p.h:
--------------------------------------------------------------------------------
1 | #ifndef QTDATASYNC_CHANGEEMITTER_P_H
2 | #define QTDATASYNC_CHANGEEMITTER_P_H
3 |
4 | #include
5 | #include
6 |
7 | #include "qtdatasync_global.h"
8 | #include "defaults.h"
9 | #include "emitteradapter_p.h"
10 |
11 | #include "rep_changeemitter_p_source.h"
12 |
13 | namespace QtDataSync {
14 |
15 | //not exported because base it not, too
16 | class ChangeEmitter : public ChangeEmitterSource
17 | {
18 | Q_OBJECT
19 |
20 | public:
21 | explicit ChangeEmitter(const Defaults &defaults, QObject *parent = nullptr);
22 |
23 | public Q_SLOTS:
24 | void triggerChange(QObject *origin,
25 | const QtDataSync::ObjectKey &key,
26 | bool deleted,
27 | bool changed);
28 | void triggerClear(QObject *origin, const QByteArray &typeName, const QStringList &ids);
29 | void triggerReset(QObject *origin);
30 | void triggerUpload() override;
31 |
32 | Q_SIGNALS:
33 | void uploadNeeded();
34 |
35 | void dataChanged(QObject *origin, const QtDataSync::ObjectKey &key, bool deleted);
36 | void dataResetted(QObject *origin);
37 |
38 | protected Q_SLOTS:
39 | //remcon interface
40 | void triggerRemoteChange(const ObjectKey &key, bool deleted, bool changed) override;
41 | void triggerRemoteClear(const QByteArray &typeName, const QStringList &ids) override;
42 | void triggerRemoteReset() override;
43 |
44 | private:
45 | QSharedPointer _cache;//needed to clear cache on remote changes
46 | };
47 |
48 | }
49 |
50 | #endif // QTDATASYNC_CHANGEEMITTER_P_H
51 |
--------------------------------------------------------------------------------
/src/datasync/objectkey.h:
--------------------------------------------------------------------------------
1 | #ifndef QTDATASYNC_OBJECTKEY_H
2 | #define QTDATASYNC_OBJECTKEY_H
3 |
4 | #include
5 |
6 | #include "QtDataSync/qtdatasync_global.h"
7 |
8 | namespace QtDataSync {
9 |
10 | //! Defines a unique key to identify a dataset globally
11 | struct Q_DATASYNC_EXPORT ObjectKey
12 | {
13 | //! The name of the type the dataset is of
14 | QByteArray typeName;
15 | //! The id of the dataset (it's USER property)
16 | QString id;
17 |
18 | //! Default constructor, with optional parameters
19 | ObjectKey(const QByteArray &typeName = {}, const QString &id = {});
20 |
21 | //! Creates a hash of the object key to anonymize ize
22 | QByteArray hashed() const;
23 |
24 | //! Equality operator
25 | bool operator==(const ObjectKey &other) const;
26 | //! Inequality operator
27 | bool operator!=(const ObjectKey &other) const;
28 | };
29 |
30 | //! Overload of qHash to use ObjectKey with QHash
31 | uint Q_DATASYNC_EXPORT qHash(const ObjectKey &key, uint seed = 0);
32 | //! Stream operator to stream into a QDataStream
33 | QDataStream Q_DATASYNC_EXPORT &operator<<(QDataStream &stream, const ObjectKey &key);
34 | //! Stream operator to stream out of a QDataStream
35 | QDataStream Q_DATASYNC_EXPORT &operator>>(QDataStream &stream, ObjectKey &key);
36 | //! Stream operator to stream into a QDebug
37 | QDebug Q_DATASYNC_EXPORT operator<<(QDebug debug, const ObjectKey &key);
38 |
39 | }
40 |
41 | Q_DECLARE_METATYPE(QtDataSync::ObjectKey)
42 | Q_DECLARE_TYPEINFO(QtDataSync::ObjectKey, Q_MOVABLE_TYPE);
43 |
44 | #endif // QTDATASYNC_OBJECTKEY_H
45 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | BSD 3-Clause License
2 |
3 | Copyright (c) 2017, Felix Barz
4 | All rights reserved.
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions are met:
8 |
9 | * Redistributions of source code must retain the above copyright notice, this
10 | list of conditions and the following disclaimer.
11 |
12 | * Redistributions in binary form must reproduce the above copyright notice,
13 | this list of conditions and the following disclaimer in the documentation
14 | and/or other materials provided with the distribution.
15 |
16 | * Neither the name of the copyright holder nor the names of its
17 | contributors may be used to endorse or promote products derived from
18 | this software without specific prior written permission.
19 |
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
--------------------------------------------------------------------------------
/src/datasync/objectkey.cpp:
--------------------------------------------------------------------------------
1 | #include "objectkey.h"
2 | #include "message_p.h"
3 |
4 | #include
5 | #include
6 | #include
7 |
8 | using namespace QtDataSync;
9 |
10 | ObjectKey::ObjectKey(const QByteArray &typeName, const QString &id) :
11 | typeName{typeName},
12 | id{id}
13 | {}
14 |
15 | QByteArray ObjectKey::hashed() const
16 | {
17 | QCryptographicHash hash(QCryptographicHash::Sha3_256);
18 | hash.addData(typeName);
19 | hash.addData(id.toUtf8());
20 | return hash.result();
21 | }
22 |
23 | bool ObjectKey::operator==(const QtDataSync::ObjectKey &other) const
24 | {
25 | return typeName == other.typeName &&
26 | id == other.id;
27 | }
28 |
29 | bool ObjectKey::operator!=(const QtDataSync::ObjectKey &other) const
30 | {
31 | return typeName != other.typeName ||
32 | id != other.id;
33 | }
34 |
35 | uint QtDataSync::qHash(const QtDataSync::ObjectKey &key, uint seed) {
36 | return qHash(key.typeName, seed) ^ qHash(key.id, seed);
37 | }
38 |
39 | QDataStream &QtDataSync::operator<<(QDataStream &stream, const ObjectKey &key)
40 | {
41 | stream << key.typeName
42 | << static_cast(key.id);
43 | return stream;
44 | }
45 |
46 | QDataStream &QtDataSync::operator>>(QDataStream &stream, ObjectKey &key)
47 | {
48 | Utf8String id;
49 | stream >> key.typeName
50 | >> id;
51 | key.id = id;
52 | return stream;
53 | }
54 |
55 | QDebug QtDataSync::operator<<(QDebug debug, const ObjectKey &key)
56 | {
57 | QDebugStateSaver saver(debug);
58 | debug.nospace().noquote() << '[' << key.typeName << ':' << key.id << ']';
59 | return debug;
60 | }
61 |
--------------------------------------------------------------------------------
/doc/rothreaded.dox:
--------------------------------------------------------------------------------
1 | /*!
2 | @page ro_threaded Threaded remote objects
3 | @brief Details on the "threaded" scheme extension to remote objects
4 |
5 | @tableofcontents
6 |
7 | @section ro_intro Threaded RemoteObjects connection
8 | QtRemoteObjects allows to register custom transport protocols. This library implements such a
9 | custom connection mode called `threaded`. Unlike most other protocls, this one only works
10 | within the same process and uses signals in order to transfer the data between source and
11 | replica.
12 |
13 | @section ro_motivation Motivation for such a connection
14 | The reasons are simply: security and performance. For most applications, a single process setup
15 | will be used, and there is no need to expose any of the engines interfaces outside of the
16 | process. This increases the security, as these interfaces could be used by an attacker to add
17 | a new device to your account without you noticing.
18 |
19 | @section ro_usage How to use
20 | The protocol can be used by anyone that links to the datasync library. The protocol gets
21 | selected by specifying a special scheme for the url. One example would be:
22 | @code
23 | threaded://some/identifier
24 | @endcode
25 |
26 | @section ro_multiproc Multi-Process setups
27 | In case you want to use datasync in a multi process context, you cannot use the threaded mode.
28 | Instead, use the QtDataSync::Setup::remoteObjectHost property to specify a custom url on all
29 | setups. As long as you stay on the same machine, it is recommended to use the "local" mode:
30 | @code{.cpp}
31 | setup.setRemoteObjectHost(QUrl("local:datasync_setup_myapp"));
32 | @endcode
33 | */
34 |
--------------------------------------------------------------------------------
/src/messages/registermessage.cpp:
--------------------------------------------------------------------------------
1 | #include "registermessage_p.h"
2 |
3 | using namespace QtDataSync;
4 |
5 | RegisterBaseMessage::RegisterBaseMessage() = default;
6 |
7 | RegisterBaseMessage::RegisterBaseMessage(QString deviceName, QByteArray nonce, const QSharedPointer &signKey, const QSharedPointer &cryptKey, AsymmetricCrypto *crypto) :
8 | InitMessage{std::move(nonce)},
9 | signAlgorithm{crypto->signatureScheme()},
10 | signKey{crypto->writeKey(signKey)},
11 | cryptAlgorithm{crypto->encryptionScheme()},
12 | cryptKey{crypto->writeKey(cryptKey)},
13 | deviceName{std::move(deviceName)}
14 | {}
15 |
16 | AsymmetricCryptoInfo *RegisterBaseMessage::createCryptoInfo(CryptoPP::RandomNumberGenerator &rng, QObject *parent) const
17 | {
18 | return new AsymmetricCryptoInfo(rng,
19 | signAlgorithm,
20 | signKey,
21 | cryptAlgorithm,
22 | cryptKey,
23 | parent);
24 | }
25 |
26 | const QMetaObject *RegisterBaseMessage::getMetaObject() const
27 | {
28 | return &staticMetaObject;
29 | }
30 |
31 |
32 |
33 | RegisterMessage::RegisterMessage() = default;
34 |
35 | RegisterMessage::RegisterMessage(QString deviceName, QByteArray nonce, const QSharedPointer &signKey, const QSharedPointer &cryptKey, AsymmetricCrypto *crypto, QByteArray cmac) :
36 | RegisterBaseMessage{std::move(deviceName),
37 | std::move(nonce),
38 | signKey,
39 | cryptKey,
40 | crypto},
41 | cmac{std::move(cmac)}
42 | {}
43 |
44 | const QMetaObject *RegisterMessage::getMetaObject() const
45 | {
46 | return &staticMetaObject;
47 | }
48 |
--------------------------------------------------------------------------------
/src/datasync/setup_p.h:
--------------------------------------------------------------------------------
1 | #ifndef QTDATASYNC_SETUP_P_H
2 | #define QTDATASYNC_SETUP_P_H
3 |
4 | #include
5 | #include
6 | #include
7 |
8 | #include
9 |
10 | #include "qtdatasync_global.h"
11 | #include "setup.h"
12 | #include "defaults.h"
13 | #include "exchangeengine_p.h"
14 | #include "conflictresolver.h"
15 |
16 | namespace QtDataSync {
17 |
18 | //must be exported for tests
19 | class Q_DATASYNC_EXPORT SetupPrivate
20 | {
21 | friend class QtDataSync::Setup;
22 | friend class QtDataSync::EngineThread;
23 |
24 | public:
25 | static void cleanupHandler();
26 | static unsigned long currentTimeout();
27 |
28 | static ExchangeEngine *engine(const QString &setupName);
29 |
30 | QDir createStorageDir(const QString &setupName);
31 | void createDefaults(const QString &setupName, const QDir &storageDir, bool passive);
32 |
33 | static QJsonObject parseObj(const QByteArray &data);
34 |
35 | private:
36 | static const QString DefaultLocalDir;
37 |
38 | static QMutex setupMutex;
39 | static QHash> engines;
40 | static unsigned long timeout;
41 |
42 | QString localDir;
43 | QUrl roAddress;
44 | QScopedPointer serializer;
45 | QScopedPointer resolver;
46 | QHash properties;
47 | Setup::FatalErrorHandler fatalErrorHandler;
48 | ExchangeEngine::ImportData initialImport;
49 |
50 | SetupPrivate();
51 |
52 | static void deleteThread(EngineThread *thread);
53 | };
54 |
55 | }
56 |
57 | Q_DECLARE_LOGGING_CATEGORY(qdssetup)
58 |
59 | #endif // QTDATASYNC_SETUP_P_H
60 |
--------------------------------------------------------------------------------
/examples/datasync/AndroidSync/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | repositories {
3 | jcenter()
4 | }
5 |
6 | dependencies {
7 | classpath 'com.android.tools.build:gradle:2.2.3'
8 | }
9 | }
10 |
11 | allprojects {
12 | repositories {
13 | jcenter()
14 | maven {
15 | url "https://maven.google.com"
16 | }
17 | }
18 | }
19 |
20 | apply plugin: 'com.android.application'
21 |
22 | dependencies {
23 | compile fileTree(dir: 'libs', include: ['*.jar'])
24 | compile "com.android.support:support-compat:+"
25 | }
26 |
27 | android {
28 | /*******************************************************
29 | * The following variables:
30 | * - androidBuildToolsVersion,
31 | * - androidCompileSdkVersion
32 | * - qt5AndroidDir - holds the path to qt android files
33 | * needed to build any Qt application
34 | * on Android.
35 | *
36 | * are defined in gradle.properties file. This file is
37 | * updated by QtCreator and androiddeployqt tools.
38 | * Changing them manually might break the compilation!
39 | *******************************************************/
40 |
41 | compileSdkVersion androidCompileSdkVersion.toInteger()
42 |
43 | buildToolsVersion androidBuildToolsVersion
44 |
45 | sourceSets {
46 | main {
47 | manifest.srcFile 'AndroidManifest.xml'
48 | java.srcDirs = [qt5AndroidDir + '/src', 'src', 'java']
49 | aidl.srcDirs = [qt5AndroidDir + '/src', 'src', 'aidl']
50 | res.srcDirs = [qt5AndroidDir + '/res', 'res']
51 | resources.srcDirs = ['src']
52 | renderscript.srcDirs = ['src']
53 | assets.srcDirs = ['assets']
54 | jniLibs.srcDirs = ['libs']
55 | }
56 | }
57 |
58 | lintOptions {
59 | abortOnError false
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/datasync/keystore.cpp:
--------------------------------------------------------------------------------
1 | #include "keystore.h"
2 | #include "cryptocontroller_p.h"
3 | using namespace QtDataSync;
4 |
5 | namespace QtDataSync {
6 | class Q_DATASYNC_EXPORT KeyStorePrivate
7 | {
8 | public:
9 | explicit KeyStorePrivate(Defaults defaults);
10 | Defaults defaults;
11 | };
12 | }
13 |
14 | KeyStore::KeyStore(const Defaults &defaults, QObject *parent) :
15 | QObject{parent},
16 | d{new KeyStorePrivate(defaults)}
17 | {}
18 |
19 | QString KeyStore::setupName() const
20 | {
21 | return d->defaults.setupName();
22 | }
23 |
24 | KeyStore::~KeyStore() = default;
25 |
26 | Defaults KeyStore::defaults() const
27 | {
28 | return d->defaults;
29 | }
30 |
31 |
32 |
33 | KeyStorePrivate::KeyStorePrivate(Defaults defaults) :
34 | defaults{std::move(defaults)}
35 | {}
36 |
37 |
38 |
39 | KeyStoreException::KeyStoreException(const KeyStore * const keyStore, const QString &what) :
40 | Exception{keyStore->defaults(), what},
41 | _keyStoreName{keyStore->providerName()}
42 | {}
43 |
44 | KeyStoreException::KeyStoreException(const KeyStoreException * const other) :
45 | Exception{other},
46 | _keyStoreName{other->_keyStoreName}
47 | {}
48 |
49 | QString KeyStoreException::storeProviderName() const
50 | {
51 | return _keyStoreName;
52 | }
53 |
54 | QByteArray KeyStoreException::className() const noexcept
55 | {
56 | return QTDATASYNC_EXCEPTION_NAME(KeyStoreException);
57 | }
58 |
59 | QString KeyStoreException::qWhat() const
60 | {
61 | return Exception::qWhat() +
62 | QStringLiteral("\n\tKeystore: %1")
63 | .arg(_keyStoreName);
64 | }
65 |
66 | void KeyStoreException::raise() const
67 | {
68 | throw (*this);
69 | }
70 |
71 | QException *KeyStoreException::clone() const
72 | {
73 | return new KeyStoreException(this);
74 | }
75 |
--------------------------------------------------------------------------------
/src/messages/messages.pro:
--------------------------------------------------------------------------------
1 | TEMPLATE = lib
2 |
3 | CONFIG += static
4 |
5 | TARGET = qtdatasync_messages
6 |
7 | DEFINES += QT_BUILD_DATASYNC_LIB #is build as part of the lib regarding exports
8 |
9 | HEADERS += \
10 | message_p.h \
11 | identifymessage_p.h \
12 | registermessage_p.h \
13 | asymmetriccrypto_p.h \
14 | accountmessage_p.h \
15 | loginmessage_p.h \
16 | welcomemessage_p.h \
17 | errormessage_p.h \
18 | syncmessage_p.h \
19 | changemessage_p.h \
20 | changedmessage_p.h \
21 | devicesmessage_p.h \
22 | removemessage_p.h \
23 | accessmessage_p.h \
24 | proofmessage_p.h \
25 | grantmessage_p.h \
26 | devicechangemessage_p.h \
27 | macupdatemessage_p.h \
28 | keychangemessage_p.h \
29 | devicekeysmessage_p.h \
30 | newkeymessage_p.h
31 |
32 | SOURCES += \
33 | message.cpp \
34 | identifymessage.cpp \
35 | registermessage.cpp \
36 | asymmetriccrypto.cpp \
37 | accountmessage.cpp \
38 | loginmessage.cpp \
39 | welcomemessage.cpp \
40 | errormessage.cpp \
41 | syncmessage.cpp \
42 | changemessage.cpp \
43 | changedmessage.cpp \
44 | devicesmessage.cpp \
45 | removemessage.cpp \
46 | accessmessage.cpp \
47 | proofmessage.cpp \
48 | grantmessage.cpp \
49 | devicechangemessage.cpp \
50 | macupdatemessage.cpp \
51 | keychangemessage.cpp \
52 | devicekeysmessage.cpp \
53 | newkeymessage.cpp
54 |
55 | DISTFILES += \
56 | messages.pri
57 |
58 | include(../3rdparty/cryptopp/cryptopp.pri)
59 |
60 | MODULE_INCLUDEPATH += $$PWD
61 |
62 | load(qt_helper_lib)
63 | CONFIG += qt warning_clean
64 | QT = core
65 |
66 | QDEP_DEPENDS += Skycoder42/CryptoQQ@2.0.3
67 | QDEP_EXPORTS += Skycoder42/CryptoQQ@2.0.3
68 | CONFIG += qdep_no_link
69 |
70 | !load(qdep):error("Failed to load qdep feature! Run 'qdep prfgen --qmake $$QMAKE_QMAKE' to create it.")
71 |
--------------------------------------------------------------------------------
/examples/datasync/IosSync/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDisplayName
6 | ${PRODUCT_NAME}
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleGetInfoString
10 | Created by Qt/QMake
11 | CFBundleIconFile
12 | ${ASSETCATALOG_COMPILER_APPICON_NAME}
13 | CFBundleIdentifier
14 | ${PRODUCT_BUNDLE_IDENTIFIER}
15 | CFBundleName
16 | ${PRODUCT_NAME}
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | ${QMAKE_SHORT_VERSION}
21 | CFBundleSignature
22 | ${QMAKE_PKGINFO_TYPEINFO}
23 | CFBundleVersion
24 | ${QMAKE_FULL_VERSION}
25 | LSRequiresIPhoneOS
26 |
27 | MinimumOSVersion
28 | ${IPHONEOS_DEPLOYMENT_TARGET}
29 | NOTE
30 | This file was generated by Qt/QMake.
31 | UILaunchStoryboardName
32 | LaunchScreen
33 | UISupportedInterfaceOrientations
34 |
35 | UIInterfaceOrientationPortrait
36 | UIInterfaceOrientationPortraitUpsideDown
37 | UIInterfaceOrientationLandscapeLeft
38 | UIInterfaceOrientationLandscapeRight
39 |
40 |
41 | UIBackgroundModes
42 |
43 | fetch
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/src/messages/changedmessage_p.h:
--------------------------------------------------------------------------------
1 | #ifndef QTDATASYNC_CHANGEDMESSAGE_P_H
2 | #define QTDATASYNC_CHANGEDMESSAGE_P_H
3 |
4 | #include "message_p.h"
5 |
6 | namespace QtDataSync {
7 |
8 | class Q_DATASYNC_EXPORT ChangedMessage : public Message
9 | {
10 | Q_GADGET
11 |
12 | Q_PROPERTY(quint64 dataIndex MEMBER dataIndex)
13 | Q_PROPERTY(quint32 keyIndex MEMBER keyIndex)
14 | Q_PROPERTY(QByteArray salt MEMBER salt)
15 | Q_PROPERTY(QByteArray data MEMBER data)
16 |
17 | public:
18 | quint64 dataIndex = 0;
19 | quint32 keyIndex = 0;
20 | QByteArray salt;
21 | QByteArray data;
22 |
23 | protected:
24 | const QMetaObject *getMetaObject() const override;
25 | };
26 |
27 | class Q_DATASYNC_EXPORT ChangedInfoMessage : public ChangedMessage
28 | {
29 | Q_GADGET
30 |
31 | Q_PROPERTY(quint32 changeEstimate MEMBER changeEstimate)
32 |
33 | public:
34 | ChangedInfoMessage(quint32 changeEstimate = 0);
35 |
36 | quint32 changeEstimate;
37 |
38 | protected:
39 | const QMetaObject *getMetaObject() const override;
40 | };
41 |
42 | class Q_DATASYNC_EXPORT LastChangedMessage : public Message
43 | {
44 | Q_GADGET
45 |
46 | protected:
47 | const QMetaObject *getMetaObject() const override;
48 | };
49 |
50 | class Q_DATASYNC_EXPORT ChangedAckMessage : public Message
51 | {
52 | Q_GADGET
53 |
54 | Q_PROPERTY(quint64 dataIndex MEMBER dataIndex)
55 |
56 | public:
57 | ChangedAckMessage(quint64 dataIndex = 0);
58 |
59 | quint64 dataIndex;
60 |
61 | protected:
62 | const QMetaObject *getMetaObject() const override;
63 | };
64 |
65 | }
66 |
67 | Q_DECLARE_METATYPE(QtDataSync::ChangedMessage)
68 | Q_DECLARE_METATYPE(QtDataSync::ChangedInfoMessage)
69 | Q_DECLARE_METATYPE(QtDataSync::LastChangedMessage)
70 | Q_DECLARE_METATYPE(QtDataSync::ChangedAckMessage)
71 |
72 | #endif // QTDATASYNC_CHANGEDMESSAGE_P_H
73 |
--------------------------------------------------------------------------------
/tools/appserver/singletaskqueue.h:
--------------------------------------------------------------------------------
1 | #ifndef SINGLETASKQUEUE_H
2 | #define SINGLETASKQUEUE_H
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 |
12 | class SingleTaskQueue : public QObject
13 | {
14 | Q_OBJECT
15 |
16 | public:
17 | class Task : public QRunnable {
18 | friend class SingleTaskQueue;
19 | public:
20 | Task(SingleTaskQueue *queue);
21 | virtual void safeRun() = 0;
22 | void run() final;
23 |
24 | private:
25 | QWeakPointer _lockRef;
26 | SingleTaskQueue *_queue;
27 | };
28 |
29 | template
30 | class GenericTask : public Task {
31 | public:
32 | GenericTask(const TFunction &fn, SingleTaskQueue *queue);
33 | void safeRun() final;
34 |
35 | private:
36 | const TFunction _fn;
37 | };
38 |
39 | explicit SingleTaskQueue(QThreadPool *pool, QObject *parent = nullptr);
40 | ~SingleTaskQueue() override;
41 |
42 | void enqueueTask(Task *task);
43 | template
44 | inline void enqueue(const TFunction &fn) {
45 | enqueueTask(new GenericTask(fn, this));
46 | }
47 |
48 | bool clear();
49 | bool isFinished() const;
50 |
51 | private:
52 | QThreadPool *_pool;
53 |
54 | QSharedPointer _lock;
55 | QQueue _tasks;
56 |
57 | void nextTask(QMutexLocker &lock);
58 | void completeTask(const Task * const task, QMutexLocker &lock);
59 | };
60 |
61 | template
62 | SingleTaskQueue::GenericTask::GenericTask(const TFunction &fn, SingleTaskQueue *queue) :
63 | Task(queue),
64 | _fn(fn)
65 | {}
66 |
67 | template
68 | void SingleTaskQueue::GenericTask::safeRun()
69 | {
70 | _fn();
71 | }
72 |
73 | #endif // SINGLETASKQUEUE_H
74 |
--------------------------------------------------------------------------------
/doc/migrationhelper.dox:
--------------------------------------------------------------------------------
1 | /*!
2 | @class QtDataSync::MigrationHelper
3 |
4 | If you used QtDataSync below version 4 before, you will have to use this class to migrate the data
5 | from that old datasync to the current new one, as they are not compatible. This is what this class
6 | is used for.
7 |
8 | The migration is performed asynchronously once started and cannot be stopped. To start a
9 | migration, use startMigration().
10 |
11 | @sa MigrationHelper::startMigration, MigrationHelper::migrationDone
12 | */
13 |
14 | /*!
15 | @fn QtDataSync::MigrationHelper::MigrationHelper(QObject *)
16 |
17 | @param parent The parent object
18 | @throws SetupDoesNotExistException Thrown if the default setup was not created yet
19 | */
20 |
21 | /*!
22 | @fn QtDataSync::MigrationHelper::MigrationHelper(const QString &, QObject *)
23 |
24 | @param setupName The name of the setup to connect to
25 | @param parent The parent object
26 | @throws SetupDoesNotExistException Thrown if the given setup was not created yet
27 | */
28 |
29 | /*!
30 | @fn QtDataSync::MigrationHelper::startMigration
31 |
32 | @param storageDir The old datasync directory to import the data from
33 | @param flags Flags to configure what and how to migrate the data
34 |
35 | The `storageDir` must be the directory that the old datasync used as storage directory. If you
36 | did not change it, the DefaultOldStorageDir constant can be used, as it points to the previous
37 | default datasync storage dir.
38 |
39 | Migration is performed asynchronously with the status beeing reported via the signals. Errors,
40 | warnings and other stuff is logged as usual. Use the `qtdatasync..migration` logging
41 | category to filter for it.
42 |
43 | @sa MigrationHelper::MigrationFlag, MigrationHelper::DefaultOldStorageDir,
44 | MigrationHelper::migrationDone, MigrationHelper::migrationPrepared,
45 | MigrationHelper::migrationProgress,
46 | */
47 |
--------------------------------------------------------------------------------
/src/datasyncios/QIOSApplicationDelegate+QtDatasyncAppDelegate.mm:
--------------------------------------------------------------------------------
1 | #import "QIOSApplicationDelegate+QtDatasyncAppDelegate_p.h"
2 | #import "qtdatasyncappdelegate_capi_p.h"
3 | #include
4 | #include "iossyncdelegate_p.h"
5 |
6 | @implementation QIOSApplicationDelegate (QtDatasyncAppDelegate)
7 |
8 | -(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
9 | {
10 | qDebug() << "initialized QtDatasyncAppDelegate";
11 | return YES;
12 | }
13 |
14 | -(void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
15 | {
16 | QtDataSync::IosSyncDelegatePrivate::performFetch([=](QtDataSync::IosSyncDelegate::SyncResult result) {
17 | switch(result) {
18 | case QtDataSync::IosSyncDelegate::SyncResult::NewData:
19 | completionHandler(UIBackgroundFetchResultNewData);
20 | break;
21 | case QtDataSync::IosSyncDelegate::SyncResult::NoData:
22 | completionHandler(UIBackgroundFetchResultNoData);
23 | break;
24 | case QtDataSync::IosSyncDelegate::SyncResult::Error:
25 | completionHandler(UIBackgroundFetchResultFailed);
26 | break;
27 | default:
28 | Q_UNREACHABLE();
29 | break;
30 | }
31 | });
32 | }
33 |
34 |
35 |
36 | void QtDatasyncAppDelegateInitialize()
37 | {
38 | QIOSApplicationDelegate *appDelegate = (QIOSApplicationDelegate *)[[UIApplication sharedApplication] delegate];
39 | Q_ASSERT_X(appDelegate, Q_FUNC_INFO, "Failed to initialize QIOSApplicationDelegate (QtDatasyncAppDelegate)");
40 | }
41 |
42 | void setSyncInterval(double intervalSeconds)
43 | {
44 | if(intervalSeconds == -1.0)
45 | [[UIApplication sharedApplication] setMinimumBackgroundFetchInterval:UIApplicationBackgroundFetchIntervalNever];
46 | else
47 | [[UIApplication sharedApplication] setMinimumBackgroundFetchInterval:intervalSeconds];
48 | }
49 |
50 | @end
51 |
--------------------------------------------------------------------------------
/src/imports/datasync/datasync.pro:
--------------------------------------------------------------------------------
1 | QT = core datasync qml
2 | android: QT += datasyncandroid
3 | ios: QT += datasyncios
4 |
5 | CXX_MODULE = datasync
6 | TARGETPATH = de/skycoder42/QtDataSync
7 | TARGET = declarative_datasync
8 | IMPORT_VERSION = $$MODULE_VERSION_IMPORT
9 | DEFINES += "VERSION_MAJOR=$$MODULE_VERSION_MAJOR"
10 | DEFINES += "VERSION_MINOR=$$MODULE_VERSION_MINOR"
11 |
12 | HEADERS += \
13 | qqmldatastore.h \
14 | qqmlsyncmanager.h \
15 | qqmlaccountmanager.h \
16 | qqmldatastoremodel.h \
17 | qqmluserexchangemanager.h \
18 | qtdatasync_plugin.h \
19 | qqmleventcursor.h
20 |
21 | SOURCES += \
22 | qqmldatastore.cpp \
23 | qqmlsyncmanager.cpp \
24 | qqmlaccountmanager.cpp \
25 | qqmldatastoremodel.cpp \
26 | qqmluserexchangemanager.cpp \
27 | qtdatasync_plugin.cpp \
28 | qqmleventcursor.cpp
29 |
30 | ios {
31 | HEADERS += qqmliossyncsingleton.h
32 | SOURCES += qqmliossyncsingleton.cpp
33 | }
34 |
35 | OTHER_FILES += qmldir
36 |
37 | CONFIG += qmlcache
38 | load(qml_plugin)
39 |
40 | generate_qmltypes {
41 | # run again to overwrite module env
42 | ldpath.name = LD_LIBRARY_PATH
43 | ldpath.value = "$$shadowed($$dirname(_QMAKE_CONF_))/lib/:$$[QT_INSTALL_LIBS]:$$(LD_LIBRARY_PATH)"
44 | qmlpath.name = QML2_IMPORT_PATH
45 | qmlpath.value = "$$shadowed($$dirname(_QMAKE_CONF_))/qml/:$$[QT_INSTALL_QML]:$$(QML2_IMPORT_PATH)"
46 | PLGDUMP_ENV = ldpath qmlpath
47 | QT_TOOL_ENV = ldpath qmlpath
48 | qtPrepareTool(QMLPLUGINDUMP, qmlplugindump)
49 | QT_TOOL_ENV =
50 |
51 | #overwrite the target deps as make target is otherwise not detected
52 | qmltypes.depends = ../../../qml/$$TARGETPATH/$(TARGET)
53 | OLDDMP = $$take_first(qmltypes.commands)
54 | qmltypes.commands = $$QMLPLUGINDUMP $${qmltypes.commands}
55 | message("replaced $$OLDDMP with $$QMLPLUGINDUMP")
56 |
57 | mfirst.target = all
58 | mfirst.depends += qmltypes
59 | QMAKE_EXTRA_TARGETS += mfirst
60 | }
61 |
62 |
--------------------------------------------------------------------------------
/tests/auto/datasync/TestLib/mockserver.cpp:
--------------------------------------------------------------------------------
1 | #include "mockserver.h"
2 |
3 | #ifdef Q_OS_WIN
4 | #define WAIT_TIMEOUT 10000
5 | #else
6 | #define WAIT_TIMEOUT 5000
7 | #endif
8 |
9 | MockServer::MockServer(QObject *parent) :
10 | QObject(parent),
11 | _server(new QWebSocketServer(QStringLiteral("mockserver"), QWebSocketServer::NonSecureMode, this)),
12 | _connectedSpy(_server, &QWebSocketServer::newConnection)
13 | {
14 | connect(_server, &QWebSocketServer::acceptError, this, [this]() {
15 | QFAIL(qUtf8Printable(_server->errorString()));
16 | });
17 | connect(_server, &QWebSocketServer::serverError, this, [this]() {
18 | QFAIL(qUtf8Printable(_server->errorString()));
19 | });
20 | connect(_server, &QWebSocketServer::closed, this, [this]() {
21 | QFAIL(qUtf8Printable(_server->errorString()));
22 | });
23 | connect(_server, &QWebSocketServer::peerVerifyError, this, [this](const QSslError &error) {
24 | QFAIL(qUtf8Printable(error.errorString()));
25 | });
26 | connect(_server, &QWebSocketServer::sslErrors, this, [this](const QList &errors) {
27 | for(auto error : errors)
28 | QFAIL(qUtf8Printable(error.errorString()));
29 | });
30 | }
31 |
32 | void MockServer::init()
33 | {
34 | QVERIFY(_server->listen(QHostAddress::LocalHost));
35 | }
36 |
37 | QUrl MockServer::url() const
38 | {
39 | return _server->serverUrl();
40 | }
41 |
42 | void MockServer::clear()
43 | {
44 | _connectedSpy.clear();
45 | }
46 |
47 | bool MockServer::waitForConnected(MockConnection **connection, int timeout)
48 | {
49 | auto ok = false;
50 | [&]() {
51 | QVERIFY(connection);
52 | if(_connectedSpy.isEmpty())
53 | QVERIFY(_connectedSpy.wait(WAIT_TIMEOUT + timeout));
54 | QVERIFY(!_connectedSpy.isEmpty());
55 | QVERIFY(_server->hasPendingConnections());
56 | _connectedSpy.removeFirst();
57 | *connection = new MockConnection(_server->nextPendingConnection(), this);
58 | ok = true;
59 | }();
60 | return ok;
61 | }
62 |
--------------------------------------------------------------------------------
/src/messages/identifymessage_p.h:
--------------------------------------------------------------------------------
1 | #ifndef QTDATASYNC_IDENTIFYMESSAGE_H
2 | #define QTDATASYNC_IDENTIFYMESSAGE_H
3 |
4 | #include
5 | #include
6 |
7 | #include
8 |
9 | #include "message_p.h"
10 |
11 | namespace QtDataSync {
12 |
13 | class Q_DATASYNC_EXPORT IncompatibleVersionException : public QException
14 | {
15 | public:
16 | IncompatibleVersionException(QVersionNumber invalidVersion);
17 |
18 | QVersionNumber invalidVersion() const;
19 |
20 | const char *what() const noexcept override;
21 | void raise() const override;
22 | QException *clone() const override;
23 |
24 | private:
25 | const QVersionNumber _version;
26 | const QByteArray _msg;
27 | };
28 |
29 | class Q_DATASYNC_EXPORT InitMessage : public Message
30 | {
31 | Q_GADGET
32 |
33 | Q_PROPERTY(QVersionNumber protocolVersion MEMBER protocolVersion)
34 | Q_PROPERTY(QByteArray nonce MEMBER nonce)
35 |
36 | public:
37 | static const QVersionNumber CurrentVersion;
38 | static const QVersionNumber CompatVersion;
39 | static const int NonceSize = 16;
40 | InitMessage();
41 |
42 | QVersionNumber protocolVersion = CurrentVersion;
43 | QByteArray nonce;
44 |
45 | protected:
46 | InitMessage(QByteArray nonce);
47 |
48 | const QMetaObject *getMetaObject() const override;
49 | bool validate() override;
50 | };
51 |
52 | class Q_DATASYNC_EXPORT IdentifyMessage : public InitMessage
53 | {
54 | Q_GADGET
55 |
56 | Q_PROPERTY(quint32 uploadLimit MEMBER uploadLimit)
57 |
58 | public:
59 | IdentifyMessage(quint32 uploadLimit = 0);
60 |
61 | static IdentifyMessage createRandom(quint32 uploadLimit, CryptoPP::RandomNumberGenerator &rng);
62 |
63 | quint32 uploadLimit;
64 |
65 | protected:
66 | const QMetaObject *getMetaObject() const override;
67 | };
68 |
69 | }
70 |
71 | Q_DECLARE_METATYPE(QtDataSync::InitMessage)
72 | Q_DECLARE_METATYPE(QtDataSync::IdentifyMessage)
73 |
74 | #endif // QTDATASYNC_IDENTIFYMESSAGE_H
75 |
--------------------------------------------------------------------------------
/tools/appserver/dockerbuild/install.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | set -ex
3 |
4 | export MAKEFLAGS=-j$(nproc)
5 | export QDEP_CACHE_DIR=/tmp/qdep-cache
6 |
7 | DS_NAME=qdsappd
8 | MAIN_DEP="qt5-qtbase qt5-qtbase-postgresql qt5-qtwebsockets icu-libs"
9 | DEV_DEP="qt5-qtbase-dev qt5-qtwebsockets-dev qt5-qttools qt5-qttools-dev icu-dev build-base python3 git perl gawk"
10 | PIP_DEV_DEPS="qdep appdirs lockfile argcomplete"
11 |
12 | if [ ! -d "/tmp/src/.git" ]; then
13 | echo "Failed to find .git directory - not supported!"
14 | exit 1
15 | fi
16 |
17 | apk add --no-cache $MAIN_DEP $DEV_DEP
18 | pip3 install $PIP_DEV_DEPS
19 |
20 | # prepare qdep
21 | qdep prfgen --qmake qmake-qt5
22 |
23 | # build json serializer, qtservice
24 | mkdir /tmp/sysbuild
25 | cd /tmp/sysbuild
26 | for repo in QtJsonSerializer QtService; do
27 | git clone https://github.com/Skycoder42/$repo.git ./$repo
28 | cd $repo
29 | git checkout $(git describe --tags --abbrev=0)
30 |
31 | if [ -f src/imports/imports.pro ]; then
32 | echo "SUBDIRS -= imports" >> src/src.pro
33 | fi
34 |
35 | qmake-qt5
36 | make
37 | make install
38 | cd ..
39 | done
40 |
41 | # build datasync
42 | cd /tmp/src
43 | echo "SUBDIRS = 3rdparty messages" >> src/src.pro
44 | echo "SUBDIRS = " >> examples/examples.pro
45 | echo "SUBDIRS = " >> tests/tests.pro
46 |
47 | qmake-qt5
48 | make qmake_all
49 | make
50 | make install
51 |
52 | #create special symlinks, dirs and move the env script
53 | mkdir -p /etc/$DS_NAME
54 | ln -s $(qmake-qt5 -query QT_INSTALL_BINS)/$DS_NAME /usr/bin/$DS_NAME || true #allow to fail if already exists
55 | mv /tmp/src/tools/appserver/dockerbuild/env_start.sh /usr/bin/
56 |
57 | # test if working
58 | /usr/bin/$DS_NAME --version
59 |
60 | # remove unused stuff
61 | pip3 uninstall -y $PIP_DEV_DEPS
62 | apk del --no-cache --purge "*-dev" $DEV_DEP
63 | rm -rf /tmp/*
64 | rm -rf $HOME/.cache/qpmx
65 | rm -rf /usr/local/bin/qpm
66 |
67 | # test if still working
68 | /usr/bin/$DS_NAME --version
69 |
--------------------------------------------------------------------------------
/src/plugins/keystores/plain/plainkeystore.cpp:
--------------------------------------------------------------------------------
1 | #include "plainkeystore.h"
2 | #include
3 | #include
4 |
5 | #include
6 |
7 | PlainKeyStore::PlainKeyStore(const QtDataSync::Defaults &defaults, QObject *parent) :
8 | KeyStore(defaults, parent),
9 | _settings(nullptr)
10 | {}
11 |
12 | QString PlainKeyStore::providerName() const
13 | {
14 | return QStringLiteral("plain");
15 | }
16 |
17 | bool PlainKeyStore::isOpen() const
18 | {
19 | return _settings;
20 | }
21 |
22 | void PlainKeyStore::openStore()
23 | {
24 | if(!_settings) {
25 | _settings = new QSettings(defaults().storageDir().absoluteFilePath(QStringLiteral("plain.keystore")),
26 | QSettings::IniFormat,
27 | this);
28 | if(_settings->status() != QSettings::NoError) {
29 | _settings->deleteLater();
30 | _settings = nullptr;
31 | throw QtDataSync::KeyStoreException(this, QStringLiteral("Keystore file is not accessible"));
32 | }
33 | }
34 | }
35 |
36 | void PlainKeyStore::closeStore()
37 | {
38 | if(_settings) {
39 | _settings->sync();
40 | _settings->deleteLater();
41 | _settings = nullptr;
42 | }
43 | }
44 |
45 | bool PlainKeyStore::contains(const QString &key) const
46 | {
47 | return _settings->contains(key);
48 | }
49 |
50 | void PlainKeyStore::save(const QString &key, const QByteArray &pKey)
51 | {
52 | _settings->setValue(key, pKey);
53 | _settings->sync();
54 | if(_settings->status() != QSettings::NoError)
55 | throw QtDataSync::KeyStoreException(this, QStringLiteral("Failed to write to keystore file"));
56 | }
57 |
58 | QByteArray PlainKeyStore::load(const QString &key)
59 | {
60 | return _settings->value(key).toByteArray();
61 | }
62 |
63 | void PlainKeyStore::remove(const QString &key)
64 | {
65 | _settings->remove(key);
66 | _settings->sync();
67 | if(_settings->status() != QSettings::NoError)
68 | throw QtDataSync::KeyStoreException(this, QStringLiteral("Failed to delete from keystore file"));
69 | }
70 |
--------------------------------------------------------------------------------
/doc/makedoc.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # $1: $$SRCDIR
3 | # $2: $$VERSION
4 | # $3: $$[QT_INSTALL_BINS]
5 | # $4: $$[QT_INSTALL_HEADERS]
6 | # $5: $$[QT_INSTALL_DOCS]
7 | # $pwd: dest dir
8 | set -e
9 |
10 | scriptDir=$(dirname "$0")
11 | destDir="$(pwd)"
12 | srcDir=$1
13 | version=$2
14 | verTag=$(echo "$version" | sed -e 's/\.//g')
15 | qtBins=$3
16 | qtHeaders=$4
17 | qtDocs=$5
18 | doxyTemplate="$srcDir/Doxyfile"
19 | doxyRes=Doxyfile.generated
20 | readme="$destDir/README.md"
21 | doxme="$scriptDir/doxme.py"
22 |
23 | python3 "$doxme" "$srcDir/../README.md"
24 |
25 | cat "$doxyTemplate" > $doxyRes
26 | echo "PROJECT_NUMBER = \"$version\"" >> $doxyRes
27 | echo "INPUT += \"$readme\"" >> $doxyRes
28 | echo "USE_MDFILE_AS_MAINPAGE = \"$readme\"" >> $doxyRes
29 | echo "OUTPUT_DIRECTORY = \"$destDir\"" >> $doxyRes
30 | echo "QHP_NAMESPACE = \"de.skycoder42.qtdatasync.$verTag\"" >> $doxyRes
31 | echo "QHP_CUST_FILTER_NAME = \"DataSync $version\"" >> $doxyRes
32 | echo "QHP_CUST_FILTER_ATTRS = \"qtdatasync $version\"" >> $doxyRes
33 | echo "QHG_LOCATION = \"$qtBins/qhelpgenerator\"" >> $doxyRes
34 | echo "INCLUDE_PATH += \"$qtHeaders\"" >> $doxyRes
35 | echo "GENERATE_TAGFILE = \"$destDir/qtdatasync/qtdatasync.tags\"" >> $doxyRes
36 | if [ "$DOXY_STYLE" ]; then
37 | echo "HTML_STYLESHEET = \"$DOXY_STYLE\"" >> $doxyRes
38 | fi
39 | if [ "$DOXY_STYLE_EXTRA" ]; then
40 | echo "HTML_EXTRA_STYLESHEET = \"$DOXY_STYLE_EXTRA\"" >> $doxyRes
41 | fi
42 |
43 | for tagFile in $(find "$qtDocs" -name *.tags); do
44 | if [ $(basename "$tagFile") == "qtjsonserializer.tags" ]; then
45 | echo "TAGFILES += \"$tagFile=https://skycoder42.github.io/QtJsonSerializer\"" >> $doxyRes
46 | elif [ $(basename "$tagFile") == "qtservice.tags" ]; then
47 | echo "TAGFILES += \"$tagFile=https://skycoder42.github.io/QtService\"" >> $doxyRes
48 | elif [ $(basename "$tagFile") != "qtdatasync.tags" ]; then
49 | echo "TAGFILES += \"$tagFile=https://doc.qt.io/qt-5\"" >> $doxyRes
50 | fi
51 | done
52 |
53 | cd "$srcDir"
54 | doxygen "$destDir/$doxyRes"
55 |
--------------------------------------------------------------------------------
/src/datasync/emitteradapter_p.h:
--------------------------------------------------------------------------------
1 | #ifndef QTDATASYNC_EMITTERADAPTER_P_H
2 | #define QTDATASYNC_EMITTERADAPTER_P_H
3 |
4 | #include
5 | #include
6 | #include
7 |
8 | #include "qtdatasync_global.h"
9 | #include "objectkey.h"
10 | #include "defaults.h"
11 |
12 | namespace QtDataSync {
13 |
14 | class Q_DATASYNC_EXPORT EmitterAdapter : public QObject
15 | {
16 | Q_OBJECT
17 |
18 | public:
19 | struct Q_DATASYNC_EXPORT CacheInfo {
20 | QReadWriteLock lock;
21 | QCache cache;
22 |
23 | CacheInfo(int maxSize);
24 | };
25 |
26 | explicit EmitterAdapter(QObject *changeEmitter,
27 | QSharedPointer cacheInfo,
28 | QObject *origin = nullptr);
29 |
30 | void triggerChange(const QtDataSync::ObjectKey &key, bool deleted, bool changed);
31 | void triggerClear(const QByteArray &typeName, const QStringList &ids);
32 | void triggerReset();
33 | void triggerUpload();
34 |
35 | void putCached(const ObjectKey &key, const QJsonObject &data, int costs);
36 | void putCached(const QList &keys, const QList &data, const QList &costs);
37 | bool getCached(const ObjectKey &key, QJsonObject &data);
38 | bool dropCached(const ObjectKey &key);
39 | void dropCached(const QByteArray &typeName, const QStringList &ids);
40 | void dropCached();
41 |
42 | Q_SIGNALS:
43 | void dataChanged(const QtDataSync::ObjectKey &key, bool deleted);
44 | void dataResetted();
45 |
46 | private Q_SLOTS:
47 | void dataChangedImpl(QObject *origin, const QtDataSync::ObjectKey &key, bool deleted);
48 | void dataResettedImpl(QObject *origin);
49 | void remoteDataChangedImpl(const QtDataSync::ObjectKey &key, bool deleted);
50 | void remoteDataResettedImpl();
51 |
52 | private:
53 | bool _isPrimary;
54 | QObject *_emitterBackend;
55 | QSharedPointer _cache;
56 | };
57 |
58 | }
59 |
60 | Q_DECLARE_METATYPE(QSharedPointer)
61 |
62 | #endif // QTDATASYNC_EMITTERADAPTER_P_H
63 |
--------------------------------------------------------------------------------
/src/plugins/keystores/secretservice/secretservicekeystore.cpp:
--------------------------------------------------------------------------------
1 | #include "secretservicekeystore.h"
2 |
3 | #include
4 |
5 | SecretServiceKeyStore::SecretServiceKeyStore(const QtDataSync::Defaults &defaults, const QString &providerName, QObject *parent) :
6 | KeyStore(defaults, parent),
7 | _providerName(providerName),
8 | _libSecret(new LibSecretWrapper(QCoreApplication::applicationName().toUtf8()))
9 | {}
10 |
11 | QString SecretServiceKeyStore::providerName() const
12 | {
13 | return _providerName;
14 | }
15 |
16 | bool SecretServiceKeyStore::isOpen() const
17 | {
18 | return _libSecret->isOpen();
19 | }
20 |
21 | void SecretServiceKeyStore::openStore()
22 | {
23 | try {
24 | _libSecret->setup();
25 | } catch(LibSecretException &e) {
26 | throw QtDataSync::KeyStoreException(this, QString::fromUtf8(e.what()));
27 | }
28 | }
29 |
30 | void SecretServiceKeyStore::closeStore()
31 | {
32 | _libSecret->cleanup();
33 | }
34 |
35 | bool SecretServiceKeyStore::contains(const QString &key) const
36 | {
37 | try {
38 | if(_libSecret->loadSecret(key.toUtf8()).isEmpty())
39 | return false;
40 | else
41 | return true;
42 | } catch (...) {
43 | return false;
44 | }
45 | }
46 |
47 | void SecretServiceKeyStore::save(const QString &key, const QByteArray &pKey)
48 | {
49 | try {
50 | _libSecret->storeSecret(key.toUtf8(), pKey);
51 | } catch(LibSecretException &e) {
52 | throw QtDataSync::KeyStoreException(this, QString::fromUtf8(e.what()));
53 | }
54 | }
55 |
56 | QByteArray SecretServiceKeyStore::load(const QString &key)
57 | {
58 | try {
59 | return _libSecret->loadSecret(key.toUtf8());
60 | } catch(LibSecretException &e) {
61 | throw QtDataSync::KeyStoreException(this, QString::fromUtf8(e.what()));
62 | }
63 | }
64 |
65 | void SecretServiceKeyStore::remove(const QString &key)
66 | {
67 | try {
68 | _libSecret->removeSecret(key.toUtf8());
69 | } catch(LibSecretException &e) {
70 | throw QtDataSync::KeyStoreException(this, QString::fromUtf8(e.what()));
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/examples/datasync/AndroidSync/android/src/de/skycoder42/qtdatasync/sample/androidsync/SvcHelper.java:
--------------------------------------------------------------------------------
1 | package de.skycoder42.qtdatasync.sample.androidsync;
2 |
3 | import android.os.Build;
4 |
5 | import android.content.Context;
6 |
7 | import android.app.Notification;
8 | import android.app.NotificationChannel;
9 | import android.app.NotificationManager;
10 |
11 | import android.graphics.BitmapFactory;
12 |
13 | import android.support.v4.app.NotificationCompat;
14 |
15 | public class SvcHelper {
16 | private static final String ForegroundChannelId = "de.skycoder42.qtdatasync.sample.androidsync.notify";
17 |
18 | //! [java_create_notification]
19 | public static Notification createFgNotification(Context context) {
20 | return new NotificationCompat.Builder(context, ForegroundChannelId)
21 | .setContentTitle("AndroidSync Synchronization Service")
22 | .setContentText("Synchronizing…")
23 | .setContentInfo("AndroidSync")
24 | .setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.drawable.icon))
25 | .setSmallIcon(R.drawable.icon)
26 | .setLocalOnly(true)
27 | .setOngoing(true)
28 | .setCategory(NotificationCompat.CATEGORY_SERVICE)
29 | .build();
30 | }
31 | //! [java_create_notification]
32 |
33 | //! [java_create_channel]
34 | public static void registerNotificationChannel(Context context) {
35 | if(Build.VERSION.SDK_INT < Build.VERSION_CODES.O)
36 | return;
37 |
38 | NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
39 |
40 | //create foreground channel
41 | NotificationChannel foreground = new NotificationChannel(ForegroundChannelId,
42 | "Synchronization Service",
43 | NotificationManager.IMPORTANCE_MIN);
44 | foreground.setDescription("Is shown when the application synchronizes");
45 | foreground.enableLights(false);
46 | foreground.enableVibration(false);
47 | foreground.setShowBadge(false);
48 | manager.createNotificationChannel(foreground);
49 | }
50 | //! [java_create_channel]
51 | }
52 |
--------------------------------------------------------------------------------
/src/datasync/accountmanager_p.h:
--------------------------------------------------------------------------------
1 | #ifndef QTDATASYNC_ACCOUNTMANAGER_P_H
2 | #define QTDATASYNC_ACCOUNTMANAGER_P_H
3 |
4 | #include
5 |
6 | #include "qtdatasync_global.h"
7 | #include "exchangeengine_p.h"
8 |
9 | #include "rep_accountmanager_p_source.h"
10 |
11 | namespace QtDataSync {
12 |
13 | //not exported, because base class is not too
14 | class AccountManagerPrivate : public AccountManagerPrivateSource
15 | {
16 | Q_OBJECT
17 |
18 | public:
19 | explicit AccountManagerPrivate(ExchangeEngine *engineParent);
20 |
21 | QString setupName() const override;
22 | QString deviceName() const override;
23 | QByteArray deviceFingerprint() const override;
24 | QString lastError() const override;
25 | void setDeviceName(QString deviceName) override;
26 |
27 | void importAccountInternal(const JsonObject &importData, bool keepData);
28 | void importAccountTrustedInternal(const JsonObject &importData, const QString &password, bool keepData);
29 |
30 | public Q_SLOTS:
31 | void listDevices() override;
32 | void removeDevice(QUuid deviceId) override;
33 | void updateExchangeKey() override;
34 | void resetAccount(bool keepData) override;
35 | void changeRemote(const RemoteConfig &config, bool keepData) override;
36 | void exportAccount(QUuid id, bool includeServer) override;
37 | void exportAccountTrusted(QUuid id, bool includeServer, const QString &password) override;
38 | void importAccount(const JsonObject &importData, bool keepData) override;
39 | void importAccountTrusted(const JsonObject &importData, const QString &password, bool keepData) override;
40 | void replyToLogin(QUuid deviceId, bool accept) override;
41 |
42 | private Q_SLOTS:
43 | void requestLogin(const DeviceInfo &deviceInfo);
44 |
45 | private:
46 | QPointer _engine;
47 | Logger *_logger;
48 | QSet _loginRequests;
49 |
50 | QJsonObject serializeExportData(const ExportData &data) const;
51 | ExportData deserializeExportData(const QJsonObject &importData) const;
52 | };
53 |
54 | }
55 |
56 | #endif // QTDATASYNC_ACCOUNTMANAGER_P_H
57 |
--------------------------------------------------------------------------------
/src/imports/datasync/qqmleventcursor.h:
--------------------------------------------------------------------------------
1 | #ifndef QQMLEVENTCURSOR_H
2 | #define QQMLEVENTCURSOR_H
3 |
4 | #include
5 |
6 | #ifdef DOXYGEN_RUN
7 | namespace de::skycoder42::QtDataSync {
8 |
9 | /*! @brief The QML bindings for the static methods of of QtDataSync::EventCursor
10 | *
11 | * @extends QtQml.QtObject
12 | * @since 4.2
13 | *
14 | * @sa QtDataSync::EventCursor
15 | */
16 | class EventLog
17 | #else
18 | namespace QtDataSync {
19 |
20 | class QQmlEventCursor : public QObject
21 | #endif
22 | {
23 | Q_OBJECT
24 |
25 | public:
26 | //! @private
27 | explicit QQmlEventCursor(QObject *parent = nullptr);
28 |
29 | //! @copydoc QtDataSync::EventCursor::first(QObject*)
30 | Q_INVOKABLE QtDataSync::EventCursor *first(QObject *parent = nullptr);
31 | //! @copydoc QtDataSync::EventCursor::first(const QString &, QObject*)
32 | Q_INVOKABLE QtDataSync::EventCursor *first(const QString &setupName, QObject *parent = nullptr);
33 | //! @copydoc QtDataSync::EventCursor::last(QObject*)
34 | Q_INVOKABLE QtDataSync::EventCursor *last(QObject *parent = nullptr);
35 | //! @copydoc QtDataSync::EventCursor::last(const QString &, QObject*)
36 | Q_INVOKABLE QtDataSync::EventCursor *last(const QString &setupName, QObject *parent = nullptr);
37 | //! @copydoc QtDataSync::EventCursor::create(quint64, QObject*)
38 | Q_INVOKABLE QtDataSync::EventCursor *create(quint64 index, QObject *parent = nullptr);
39 | //! @copydoc QtDataSync::EventCursor::create(quint64, const QString &, QObject*)
40 | Q_INVOKABLE QtDataSync::EventCursor *create(quint64 index, const QString &setupName, QObject *parent = nullptr);
41 | //! @copydoc QtDataSync::EventCursor::load(const QByteArray &, QObject*)
42 | Q_INVOKABLE QtDataSync::EventCursor *load(const QByteArray &data, QObject *parent = nullptr);
43 | //! @copydoc QtDataSync::EventCursor::load(const QByteArray &, const QString &, QObject*)
44 | Q_INVOKABLE QtDataSync::EventCursor *load(const QByteArray &data, const QString &setupName, QObject *parent = nullptr);
45 | };
46 |
47 | }
48 |
49 | #endif // QQMLEVENTCURSOR_H
50 |
--------------------------------------------------------------------------------
/tests/auto/datasync/TestLib/testlib.h:
--------------------------------------------------------------------------------
1 | #ifndef TESTLIB_H
2 | #define TESTLIB_H
3 |
4 | #include
5 | #include
6 | #include "testdata.h"
7 |
8 | #ifndef KEYSTORE_PATH
9 | #define KEYSTORE_PATH ""
10 | #endif
11 |
12 | class TestLib
13 | {
14 | public:
15 | typedef QHash DataSet;
16 | static const QByteArray TypeName;
17 |
18 | static void init(const QByteArray &keystorePath = KEYSTORE_PATH);
19 | static QtDataSync::Setup &setup(QtDataSync::Setup &setup);
20 |
21 | static QtDataSync::ObjectKey generateKey(int index);
22 | static TestData generateData(int index);
23 | static QList generateData(int from, int to);
24 | static QString generateDataKey(int index);
25 | static QStringList generateDataKeys(int from, int to);
26 | static QJsonObject generateDataJson(int index, const QString &specialText = {});
27 | static DataSet generateDataJson(int from, int to);
28 | static QJsonArray dataListJson(const DataSet &data);
29 |
30 | static QTemporaryDir tDir;
31 | };
32 |
33 | namespace Tst {
34 |
35 | template
36 | bool compareUnordered(const QList &actual, QList expected, QByteArray aName, QByteArray eName, const char *file, int line) {
37 | if(actual.size() != expected.size()) {
38 | QTest::qFail(aName + " and " + eName +
39 | " differ in size (" +
40 | QByteArray::number(actual.size()) + " vs. " +
41 | QByteArray::number(expected.size()) + ")",
42 | file,
43 | line);
44 | return false;
45 | }
46 |
47 | auto i = 0;
48 | for(auto a : actual) {
49 | if(!expected.removeOne(a)) {
50 | QTest::qFail("Data of " + aName +
51 | " at index" + QByteArray::number(i) +
52 | " is not contained in " + eName,
53 | file,
54 | line);
55 | return false;
56 | }
57 | }
58 |
59 | return true;
60 | }
61 |
62 | }
63 |
64 | #define QCOMPAREUNORDERED(actual, expected) \
65 | do {\
66 | if (!Tst::compareUnordered(actual, expected, #actual, #expected, __FILE__, __LINE__))\
67 | return;\
68 | } while (false)
69 |
70 | #endif // TESTLIB_H
71 |
--------------------------------------------------------------------------------
/src/messages/registermessage_p.h:
--------------------------------------------------------------------------------
1 | #ifndef QTDATASYNC_REGISTERMESSAGE_H
2 | #define QTDATASYNC_REGISTERMESSAGE_H
3 |
4 | #include
5 |
6 | #include