From 9786786e7fb2dc984d5e47e1154da8f365bf8a2f Mon Sep 17 00:00:00 2001 From: Laurent Cozic Date: Thu, 5 Jan 2017 23:54:13 +0100 Subject: [PATCH] Syncing items --- QtClient/JoplinQtClient/JoplinQtClient.pro | 6 ++-- QtClient/JoplinQtClient/application.cpp | 2 ++ QtClient/JoplinQtClient/database.cpp | 5 +++ QtClient/JoplinQtClient/database.h | 1 + QtClient/JoplinQtClient/models/basemodel.cpp | 4 +-- QtClient/JoplinQtClient/models/basemodel.h | 2 +- QtClient/JoplinQtClient/models/setting.cpp | 30 ++++++++++++++++ QtClient/JoplinQtClient/models/setting.h | 21 +++++++++++ QtClient/JoplinQtClient/schema.sql | 6 ++++ QtClient/JoplinQtClient/settings.cpp | 31 ++++++++++++++++ QtClient/JoplinQtClient/settings.h | 7 ++++ QtClient/JoplinQtClient/synchronizer.cpp | 38 ++++++++++++-------- src/AppBundle/Model/Change.php | 16 ++++++++- 13 files changed, 148 insertions(+), 21 deletions(-) create mode 100755 QtClient/JoplinQtClient/models/setting.cpp create mode 100755 QtClient/JoplinQtClient/models/setting.h diff --git a/QtClient/JoplinQtClient/JoplinQtClient.pro b/QtClient/JoplinQtClient/JoplinQtClient.pro index 306f34ab8..f9d44cbcd 100755 --- a/QtClient/JoplinQtClient/JoplinQtClient.pro +++ b/QtClient/JoplinQtClient/JoplinQtClient.pro @@ -19,7 +19,8 @@ SOURCES += \ uuid.cpp \ dispatcher.cpp \ models/change.cpp \ - models/basemodel.cpp + models/basemodel.cpp \ + models/setting.cpp RESOURCES += qml.qrc \ database.qrc @@ -52,7 +53,8 @@ HEADERS += \ dispatcher.h \ models/change.h \ models/basemodel.h \ - enum.h + enum.h \ + models/setting.h DISTFILES += diff --git a/QtClient/JoplinQtClient/application.cpp b/QtClient/JoplinQtClient/application.cpp index 4e5ea8c5f..7779df09c 100755 --- a/QtClient/JoplinQtClient/application.cpp +++ b/QtClient/JoplinQtClient/application.cpp @@ -29,6 +29,8 @@ Application::Application(int &argc, char **argv) : QCoreApplication::setOrganizationDomain("cozic.net"); QCoreApplication::setApplicationName("Joplin"); + Settings::initialize(); + Settings settings; view_.setResizeMode(QQuickView::SizeRootObjectToView); diff --git a/QtClient/JoplinQtClient/database.cpp b/QtClient/JoplinQtClient/database.cpp index dd9754832..f63c008a3 100755 --- a/QtClient/JoplinQtClient/database.cpp +++ b/QtClient/JoplinQtClient/database.cpp @@ -139,6 +139,11 @@ bool Database::execQuery(QSqlQuery &query) { return query.exec(); } +bool Database::execQuery(const QString &sql) { + QSqlQuery query(sql, db_); + return execQuery(query); +} + QSqlQuery Database::prepare(const QString &sql) { QSqlQuery query(db_); query.prepare(sql); diff --git a/QtClient/JoplinQtClient/database.h b/QtClient/JoplinQtClient/database.h index 4438a0204..021649da2 100755 --- a/QtClient/JoplinQtClient/database.h +++ b/QtClient/JoplinQtClient/database.h @@ -22,6 +22,7 @@ public: bool transaction(); bool commit(); bool execQuery(QSqlQuery &query); + bool execQuery(const QString &query); QSqlQuery prepare(const QString& sql); private: diff --git a/QtClient/JoplinQtClient/models/basemodel.cpp b/QtClient/JoplinQtClient/models/basemodel.cpp index 67bd5e292..49045bade 100755 --- a/QtClient/JoplinQtClient/models/basemodel.cpp +++ b/QtClient/JoplinQtClient/models/basemodel.cpp @@ -48,7 +48,7 @@ bool BaseModel::load(const QString &id) { loadSqlQuery(q); } -bool BaseModel::save() { +bool BaseModel::save(bool trackChanges) { bool isNew = this->isNew(); if (!changedFields_.size() && !isNew) return true; @@ -106,7 +106,7 @@ bool BaseModel::save() { isSaved = jop::db().errorCheck(q); } - if (isSaved && trackChanges()) { + if (isSaved && this->trackChanges() && trackChanges) { if (isNew) { Change change; change.setValue("item_id", id()); diff --git a/QtClient/JoplinQtClient/models/basemodel.h b/QtClient/JoplinQtClient/models/basemodel.h index 32d9ce8df..2ee62cf97 100755 --- a/QtClient/JoplinQtClient/models/basemodel.h +++ b/QtClient/JoplinQtClient/models/basemodel.h @@ -43,7 +43,7 @@ public: QStringList changedFields() const; static int count(jop::Table table); bool load(const QString& id); - virtual bool save(); + virtual bool save(bool trackChanges = true); virtual bool dispose(); virtual Table table() const; diff --git a/QtClient/JoplinQtClient/models/setting.cpp b/QtClient/JoplinQtClient/models/setting.cpp new file mode 100755 index 000000000..160c22371 --- /dev/null +++ b/QtClient/JoplinQtClient/models/setting.cpp @@ -0,0 +1,30 @@ +#include "setting.h" + +#include "database.h" + +using namespace jop; + +void Setting::setSettings(const QSettings::SettingsMap &map) { + jop::db().transaction(); + QString sql = "INSERT OR REPLACE INTO settings (`key`, `value`, `type`) VALUES (:key, :value, :type)"; + QSqlQuery query = jop::db().prepare(sql); + for (QSettings::SettingsMap::const_iterator it = map.begin(); it != map.end(); ++it) { + query.bindValue(":key", it.key()); + query.bindValue(":value", it.value()); + query.bindValue(":type", (int)it.value().type()); + jop::db().execQuery(query); + } + jop::db().commit(); +} + +QSettings::SettingsMap Setting::settings() { + QSettings::SettingsMap output; + QSqlQuery query("SELECT key, value, type FROM settings"); + jop::db().execQuery(query); + while (query.next()) { + QString key = query.value(0).toString(); + QMetaType::Type type = (QMetaType::Type)query.value(2).toInt(); + qDebug() << key << type; + } + return output; +} diff --git a/QtClient/JoplinQtClient/models/setting.h b/QtClient/JoplinQtClient/models/setting.h new file mode 100755 index 000000000..6748dee78 --- /dev/null +++ b/QtClient/JoplinQtClient/models/setting.h @@ -0,0 +1,21 @@ +#ifndef SETTING_H +#define SETTING_H + +#include + +#include "models/basemodel.h" + +namespace jop { + +class Setting : public BaseModel { + +public: + + static void setSettings(const QSettings::SettingsMap &map); + static QSettings::SettingsMap settings(); + +}; + +} + +#endif // SETTING_H diff --git a/QtClient/JoplinQtClient/schema.sql b/QtClient/JoplinQtClient/schema.sql index aa660b99e..1c210a842 100755 --- a/QtClient/JoplinQtClient/schema.sql +++ b/QtClient/JoplinQtClient/schema.sql @@ -66,6 +66,12 @@ CREATE TABLE changes ( item_field TEXT ); +CREATE TABLE settings ( + `key` TEXT PRIMARY KEY, + `value` TEXT, + `type` INT +); + --CREATE TABLE mimetypes ( -- id INT, -- mime TEXT diff --git a/QtClient/JoplinQtClient/settings.cpp b/QtClient/JoplinQtClient/settings.cpp index b6eb0013a..42a9a1653 100755 --- a/QtClient/JoplinQtClient/settings.cpp +++ b/QtClient/JoplinQtClient/settings.cpp @@ -1,3 +1,34 @@ #include "settings.h" +#include "models/setting.h" using namespace jop; + +Settings::Settings() : QSettings() { + +} + +bool readSqlite(QIODevice &device, QSettings::SettingsMap &map) { + //qDebug() << "XXXXXXXXXXXX"; + // map = Setting::settings(); + qDebug() << "Calling readSqlite"; + return true; +} + +bool writeSqlite(QIODevice &device, const QSettings::SettingsMap &map) { + //Setting::setSettings(map); + qDebug() << "Calling writeSqlite"; + return true; +} + +void Settings::initialize() { +// const QSettings::Format SqliteFormat = QSettings::registerFormat("sqlite", &readSqlite, &writeSqlite); +// QSettings::setDefaultFormat(SqliteFormat); + +// QSettings settings; +// //qDebug() << settings.value("test"); +// settings.setValue("test", 123456); + +// QSettings s(SqliteFormat, QSettings::UserScope, "MySoft", +// "Star Runner"); +// qDebug() << "IN" << s.value("test") << "test"; +} diff --git a/QtClient/JoplinQtClient/settings.h b/QtClient/JoplinQtClient/settings.h index 767a6cc4c..ac76d4063 100755 --- a/QtClient/JoplinQtClient/settings.h +++ b/QtClient/JoplinQtClient/settings.h @@ -2,6 +2,7 @@ #define SETTINGS_H #include +#include "database.h" namespace jop { @@ -9,6 +10,12 @@ class Settings : public QSettings { Q_OBJECT +public: + + Settings(); + + static void initialize(); + }; } diff --git a/QtClient/JoplinQtClient/synchronizer.cpp b/QtClient/JoplinQtClient/synchronizer.cpp index 43fb4828d..317dbc2af 100755 --- a/QtClient/JoplinQtClient/synchronizer.cpp +++ b/QtClient/JoplinQtClient/synchronizer.cpp @@ -1,6 +1,7 @@ #include "synchronizer.h" #include "models/folder.h" #include "models/note.h" +#include "settings.h" using namespace jop; @@ -80,40 +81,44 @@ QUrlQuery Synchronizer::valuesToUrlQuery(const QHash& va } void Synchronizer::downloadChanges() { + Settings settings; + QString lastRevId = settings.value("lastRevId", "0").toString(); + state_ = DownloadingChanges; - //QUrlQuery data = valuesToUrlQuery(folder.values()); - api_.get("synchronizer", QUrlQuery(), QUrlQuery(), "download:getSynchronizer"); + QUrlQuery query; + query.addQueryItem("last_id", lastRevId); + api_.get("synchronizer", query, QUrlQuery(), "download:getSynchronizer"); } void Synchronizer::api_requestDone(const QJsonObject& response, const QString& tag) { QStringList parts = tag.split(':'); QString category = parts[0]; QString action = parts[1]; - QString id = ""; + QString arg1 = ""; + QString arg2 = ""; - if (parts.size() == 3) { - id = parts[2]; - } + if (parts.size() == 3) arg1 = parts[2]; + if (parts.size() == 4) arg2 = parts[3]; - qDebug() << "WebApi: done" << category << action << id; + qDebug() << "WebApi: done" << category << action << arg1 << arg2; // TODO: check for error if (category == "upload") { uploadsRemaining_--; - qDebug() << "Synced folder" << id; + qDebug() << "Synced folder" << arg1; if (action == "putFolder") { - Change::disposeByItemId(id); + Change::disposeByItemId(arg1); } if (action == "patchFolder") { - Change::disposeByItemId(id); + Change::disposeByItemId(arg1); } if (action == "deleteFolder") { - Change::disposeByItemId(id); + Change::disposeByItemId(arg1); } if (uploadsRemaining_ < 0) { @@ -132,11 +137,12 @@ void Synchronizer::api_requestDone(const QJsonObject& response, const QString& t QString itemId = obj["item_id"].toString(); QString itemType = obj["item_type"].toString(); QString operationType = obj["type"].toString(); + QString revId = QString::number(obj["id"].toInt()); - QString path = itemType + "s"; // That should remain true + QString path = itemType + "s"; if (operationType == "create") { - api_.get(path + "/" + itemId, QUrlQuery(), QUrlQuery(), "download:getFolder:" + itemId); + api_.get(path + "/" + itemId, QUrlQuery(), QUrlQuery(), "download:getFolder:" + itemId + ":" + revId); } downloadsRemaining_++; @@ -144,12 +150,14 @@ void Synchronizer::api_requestDone(const QJsonObject& response, const QString& t } else { downloadsRemaining_--; + Settings settings; + if (action == "getFolder") { Folder folder; folder.loadJsonObject(response); - folder.save(); + folder.save(false); - // TODO: save last rev ID + settings.setValue("lastRevId", arg2); } if (downloadsRemaining_ < 0) { diff --git a/src/AppBundle/Model/Change.php b/src/AppBundle/Model/Change.php index 847f2d347..5aee8a8df 100755 --- a/src/AppBundle/Model/Change.php +++ b/src/AppBundle/Model/Change.php @@ -57,15 +57,29 @@ class Change extends BaseModel { $change->type = Change::enumId('type', 'create'); } - $output[] = $change; + $output[] = $change->toSyncItem(); } + usort($output, function($a, $b) { + return strnatcmp($a['id'], $b['id']); + }); + return array( 'has_more' => $hasMore, 'items' => $output, ); } + public function toSyncItem() { + return array( + 'id' => (string)$this->id, + 'type' => self::enumName('type', $this->type), + 'item_id' => self::hex($this->item_id), + 'item_type' => FolderItem::enumName('type', $this->item_type), + 'item_field' => BaseModel::enumName('field', $this->item_field), + ); + } + static public function itemFieldHistory($itemId, $itemField, $toId = null) { $query = self::where('item_id', '=', $itemId); $query->where('item_field', '=', $itemField);