mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-24 10:27:10 +02:00
Syncing items
This commit is contained in:
parent
96cd7d67b0
commit
9786786e7f
@ -19,7 +19,8 @@ SOURCES += \
|
|||||||
uuid.cpp \
|
uuid.cpp \
|
||||||
dispatcher.cpp \
|
dispatcher.cpp \
|
||||||
models/change.cpp \
|
models/change.cpp \
|
||||||
models/basemodel.cpp
|
models/basemodel.cpp \
|
||||||
|
models/setting.cpp
|
||||||
|
|
||||||
RESOURCES += qml.qrc \
|
RESOURCES += qml.qrc \
|
||||||
database.qrc
|
database.qrc
|
||||||
@ -52,7 +53,8 @@ HEADERS += \
|
|||||||
dispatcher.h \
|
dispatcher.h \
|
||||||
models/change.h \
|
models/change.h \
|
||||||
models/basemodel.h \
|
models/basemodel.h \
|
||||||
enum.h
|
enum.h \
|
||||||
|
models/setting.h
|
||||||
|
|
||||||
DISTFILES +=
|
DISTFILES +=
|
||||||
|
|
||||||
|
@ -29,6 +29,8 @@ Application::Application(int &argc, char **argv) :
|
|||||||
QCoreApplication::setOrganizationDomain("cozic.net");
|
QCoreApplication::setOrganizationDomain("cozic.net");
|
||||||
QCoreApplication::setApplicationName("Joplin");
|
QCoreApplication::setApplicationName("Joplin");
|
||||||
|
|
||||||
|
Settings::initialize();
|
||||||
|
|
||||||
Settings settings;
|
Settings settings;
|
||||||
|
|
||||||
view_.setResizeMode(QQuickView::SizeRootObjectToView);
|
view_.setResizeMode(QQuickView::SizeRootObjectToView);
|
||||||
|
@ -139,6 +139,11 @@ bool Database::execQuery(QSqlQuery &query) {
|
|||||||
return query.exec();
|
return query.exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Database::execQuery(const QString &sql) {
|
||||||
|
QSqlQuery query(sql, db_);
|
||||||
|
return execQuery(query);
|
||||||
|
}
|
||||||
|
|
||||||
QSqlQuery Database::prepare(const QString &sql) {
|
QSqlQuery Database::prepare(const QString &sql) {
|
||||||
QSqlQuery query(db_);
|
QSqlQuery query(db_);
|
||||||
query.prepare(sql);
|
query.prepare(sql);
|
||||||
|
@ -22,6 +22,7 @@ public:
|
|||||||
bool transaction();
|
bool transaction();
|
||||||
bool commit();
|
bool commit();
|
||||||
bool execQuery(QSqlQuery &query);
|
bool execQuery(QSqlQuery &query);
|
||||||
|
bool execQuery(const QString &query);
|
||||||
QSqlQuery prepare(const QString& sql);
|
QSqlQuery prepare(const QString& sql);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -48,7 +48,7 @@ bool BaseModel::load(const QString &id) {
|
|||||||
loadSqlQuery(q);
|
loadSqlQuery(q);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BaseModel::save() {
|
bool BaseModel::save(bool trackChanges) {
|
||||||
bool isNew = this->isNew();
|
bool isNew = this->isNew();
|
||||||
|
|
||||||
if (!changedFields_.size() && !isNew) return true;
|
if (!changedFields_.size() && !isNew) return true;
|
||||||
@ -106,7 +106,7 @@ bool BaseModel::save() {
|
|||||||
isSaved = jop::db().errorCheck(q);
|
isSaved = jop::db().errorCheck(q);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isSaved && trackChanges()) {
|
if (isSaved && this->trackChanges() && trackChanges) {
|
||||||
if (isNew) {
|
if (isNew) {
|
||||||
Change change;
|
Change change;
|
||||||
change.setValue("item_id", id());
|
change.setValue("item_id", id());
|
||||||
|
@ -43,7 +43,7 @@ public:
|
|||||||
QStringList changedFields() const;
|
QStringList changedFields() const;
|
||||||
static int count(jop::Table table);
|
static int count(jop::Table table);
|
||||||
bool load(const QString& id);
|
bool load(const QString& id);
|
||||||
virtual bool save();
|
virtual bool save(bool trackChanges = true);
|
||||||
virtual bool dispose();
|
virtual bool dispose();
|
||||||
|
|
||||||
virtual Table table() const;
|
virtual Table table() const;
|
||||||
|
30
QtClient/JoplinQtClient/models/setting.cpp
Executable file
30
QtClient/JoplinQtClient/models/setting.cpp
Executable file
@ -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;
|
||||||
|
}
|
21
QtClient/JoplinQtClient/models/setting.h
Executable file
21
QtClient/JoplinQtClient/models/setting.h
Executable file
@ -0,0 +1,21 @@
|
|||||||
|
#ifndef SETTING_H
|
||||||
|
#define SETTING_H
|
||||||
|
|
||||||
|
#include <stable.h>
|
||||||
|
|
||||||
|
#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
|
@ -66,6 +66,12 @@ CREATE TABLE changes (
|
|||||||
item_field TEXT
|
item_field TEXT
|
||||||
);
|
);
|
||||||
|
|
||||||
|
CREATE TABLE settings (
|
||||||
|
`key` TEXT PRIMARY KEY,
|
||||||
|
`value` TEXT,
|
||||||
|
`type` INT
|
||||||
|
);
|
||||||
|
|
||||||
--CREATE TABLE mimetypes (
|
--CREATE TABLE mimetypes (
|
||||||
-- id INT,
|
-- id INT,
|
||||||
-- mime TEXT
|
-- mime TEXT
|
||||||
|
@ -1,3 +1,34 @@
|
|||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
#include "models/setting.h"
|
||||||
|
|
||||||
using namespace jop;
|
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";
|
||||||
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#define SETTINGS_H
|
#define SETTINGS_H
|
||||||
|
|
||||||
#include <stable.h>
|
#include <stable.h>
|
||||||
|
#include "database.h"
|
||||||
|
|
||||||
namespace jop {
|
namespace jop {
|
||||||
|
|
||||||
@ -9,6 +10,12 @@ class Settings : public QSettings {
|
|||||||
|
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Settings();
|
||||||
|
|
||||||
|
static void initialize();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "synchronizer.h"
|
#include "synchronizer.h"
|
||||||
#include "models/folder.h"
|
#include "models/folder.h"
|
||||||
#include "models/note.h"
|
#include "models/note.h"
|
||||||
|
#include "settings.h"
|
||||||
|
|
||||||
using namespace jop;
|
using namespace jop;
|
||||||
|
|
||||||
@ -80,40 +81,44 @@ QUrlQuery Synchronizer::valuesToUrlQuery(const QHash<QString, Change::Value>& va
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Synchronizer::downloadChanges() {
|
void Synchronizer::downloadChanges() {
|
||||||
|
Settings settings;
|
||||||
|
QString lastRevId = settings.value("lastRevId", "0").toString();
|
||||||
|
|
||||||
state_ = DownloadingChanges;
|
state_ = DownloadingChanges;
|
||||||
//QUrlQuery data = valuesToUrlQuery(folder.values());
|
QUrlQuery query;
|
||||||
api_.get("synchronizer", QUrlQuery(), QUrlQuery(), "download:getSynchronizer");
|
query.addQueryItem("last_id", lastRevId);
|
||||||
|
api_.get("synchronizer", query, QUrlQuery(), "download:getSynchronizer");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Synchronizer::api_requestDone(const QJsonObject& response, const QString& tag) {
|
void Synchronizer::api_requestDone(const QJsonObject& response, const QString& tag) {
|
||||||
QStringList parts = tag.split(':');
|
QStringList parts = tag.split(':');
|
||||||
QString category = parts[0];
|
QString category = parts[0];
|
||||||
QString action = parts[1];
|
QString action = parts[1];
|
||||||
QString id = "";
|
QString arg1 = "";
|
||||||
|
QString arg2 = "";
|
||||||
|
|
||||||
if (parts.size() == 3) {
|
if (parts.size() == 3) arg1 = parts[2];
|
||||||
id = 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
|
// TODO: check for error
|
||||||
|
|
||||||
if (category == "upload") {
|
if (category == "upload") {
|
||||||
uploadsRemaining_--;
|
uploadsRemaining_--;
|
||||||
|
|
||||||
qDebug() << "Synced folder" << id;
|
qDebug() << "Synced folder" << arg1;
|
||||||
|
|
||||||
if (action == "putFolder") {
|
if (action == "putFolder") {
|
||||||
Change::disposeByItemId(id);
|
Change::disposeByItemId(arg1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action == "patchFolder") {
|
if (action == "patchFolder") {
|
||||||
Change::disposeByItemId(id);
|
Change::disposeByItemId(arg1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action == "deleteFolder") {
|
if (action == "deleteFolder") {
|
||||||
Change::disposeByItemId(id);
|
Change::disposeByItemId(arg1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uploadsRemaining_ < 0) {
|
if (uploadsRemaining_ < 0) {
|
||||||
@ -132,11 +137,12 @@ void Synchronizer::api_requestDone(const QJsonObject& response, const QString& t
|
|||||||
QString itemId = obj["item_id"].toString();
|
QString itemId = obj["item_id"].toString();
|
||||||
QString itemType = obj["item_type"].toString();
|
QString itemType = obj["item_type"].toString();
|
||||||
QString operationType = obj["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") {
|
if (operationType == "create") {
|
||||||
api_.get(path + "/" + itemId, QUrlQuery(), QUrlQuery(), "download:getFolder:" + itemId);
|
api_.get(path + "/" + itemId, QUrlQuery(), QUrlQuery(), "download:getFolder:" + itemId + ":" + revId);
|
||||||
}
|
}
|
||||||
|
|
||||||
downloadsRemaining_++;
|
downloadsRemaining_++;
|
||||||
@ -144,12 +150,14 @@ void Synchronizer::api_requestDone(const QJsonObject& response, const QString& t
|
|||||||
} else {
|
} else {
|
||||||
downloadsRemaining_--;
|
downloadsRemaining_--;
|
||||||
|
|
||||||
|
Settings settings;
|
||||||
|
|
||||||
if (action == "getFolder") {
|
if (action == "getFolder") {
|
||||||
Folder folder;
|
Folder folder;
|
||||||
folder.loadJsonObject(response);
|
folder.loadJsonObject(response);
|
||||||
folder.save();
|
folder.save(false);
|
||||||
|
|
||||||
// TODO: save last rev ID
|
settings.setValue("lastRevId", arg2);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (downloadsRemaining_ < 0) {
|
if (downloadsRemaining_ < 0) {
|
||||||
|
@ -57,15 +57,29 @@ class Change extends BaseModel {
|
|||||||
$change->type = Change::enumId('type', 'create');
|
$change->type = Change::enumId('type', 'create');
|
||||||
}
|
}
|
||||||
|
|
||||||
$output[] = $change;
|
$output[] = $change->toSyncItem();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
usort($output, function($a, $b) {
|
||||||
|
return strnatcmp($a['id'], $b['id']);
|
||||||
|
});
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
'has_more' => $hasMore,
|
'has_more' => $hasMore,
|
||||||
'items' => $output,
|
'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) {
|
static public function itemFieldHistory($itemId, $itemField, $toId = null) {
|
||||||
$query = self::where('item_id', '=', $itemId);
|
$query = self::where('item_id', '=', $itemId);
|
||||||
$query->where('item_field', '=', $itemField);
|
$query->where('item_field', '=', $itemField);
|
||||||
|
Loading…
Reference in New Issue
Block a user