1
0
mirror of https://github.com/laurent22/joplin.git synced 2024-12-24 10:27:10 +02:00

Merge changes

This commit is contained in:
Laurent Cozic 2017-01-02 16:28:03 +01:00
parent 9cd3554e4a
commit 65d93d4b6d
8 changed files with 133 additions and 21 deletions

View File

@ -3,6 +3,7 @@
#include "models/folder.h"
#include "database.h"
#include "models/foldermodel.h"
#include "models/change.h"
#include "services/folderservice.h"
#include "settings.h"
#include "uuid.h"
@ -21,6 +22,18 @@ Application::Application(int &argc, char **argv) :
jop::db().initialize("D:/Web/www/joplin/QtClient/data/notes.sqlite");
// QVector<Change> changes = Change::all();
// foreach (Change change, changes) {
// qDebug() << change.value("item_id").toString() << change.value("type").toInt() << change.mergedFields();
// }
// qDebug() << "=====================================";
// changes = Change::mergedChanges(changes);
// foreach (Change change, changes) {
// qDebug() << change.value("item_id").toString() << change.value("type").toInt() << change.mergedFields();
// }
// This is linked to where the QSettings will be saved. In other words,
// if these values are changed, the settings will be reset and saved
// somewhere else.
@ -101,7 +114,7 @@ void Application::afterSessionInitialization() {
QString sessionId = settings.value("sessionId").toString();
qDebug() << "Session:" << sessionId;
api_.setSessionId(sessionId);
//synchronizer_.start();
synchronizer_.start();
}
void Application::view_currentFolderChanged() {

View File

@ -14,7 +14,7 @@ void Database::initialize(const QString &path) {
db_.setDatabaseName(path);
if (!db_.open()) {
qDebug() << "Error: connection with database fail";
qFatal("Error: connection with database fail");
} else {
qDebug() << "Database: connection ok";
}
@ -22,13 +22,6 @@ void Database::initialize(const QString &path) {
upgrade();
}
//QSqlQuery Database::query(const QString &sql) const {
// QSqlQuery output(db_);
// output.prepare(sql);
// //log(sql);
// return output;
//}
QSqlDatabase &Database::database() {
return db_;
}
@ -86,16 +79,6 @@ QSqlQuery Database::buildSqlQuery(Database::QueryType type, const QString &table
}
}
//log(sql, query);
// qDebug() <<"SQL:"<<sql;
// QMapIterator<QString, QVariant> i(query.boundValues());
// while (i.hasNext()) {
// i.next();
// qDebug() << i.key() << ":" << i.value().toString();
// }
return query;
}

View File

@ -11,6 +11,10 @@ QHash<QString, QVariant> BaseModel::cache_;
BaseModel::BaseModel() {}
BaseModel::BaseModel(const QSqlQuery &query) {
loadSqlQuery(query);
}
QStringList BaseModel::changedFields() const {
QStringList output;
for (QHash<QString, bool>::const_iterator it = changedFields_.begin(); it != changedFields_.end(); ++it) {
@ -169,11 +173,18 @@ QVector<BaseModel::Field> BaseModel::tableFields(jop::Table table) {
if (BaseModel::tableFields_.contains(table)) return BaseModel::tableFields_[table];
QVector<BaseModel::Field> output;
if (table == jop::FoldersTable) {
output.push_back(createField("id", QMetaType::QString ));
output.push_back(createField("title", QMetaType::QString ));
output.push_back(createField("created_time", QMetaType::Int ));
output.push_back(createField("updated_time", QMetaType::Int ));
} else if (table == jop::ChangesTable) {
output.push_back(createField("id", QMetaType::Int ));
output.push_back(createField("type", QMetaType::Int ));
output.push_back(createField("item_id", QMetaType::QString ));
output.push_back(createField("item_type", QMetaType::Int ));
output.push_back(createField("item_field", QMetaType::QString ));
}
BaseModel::tableFields_[table] = output;

View File

@ -40,6 +40,7 @@ public:
};
BaseModel();
BaseModel(const QSqlQuery& query);
QStringList changedFields() const;
static int count(jop::Table table);
bool save();

View File

@ -1,9 +1,96 @@
#include "change.h"
#include "database.h"
using namespace jop;
Change::Change() {}
Change::Change(const QSqlQuery &query) {
loadSqlQuery(query);
}
Table Change::table() const {
return jop::ChangesTable;
}
QVector<Change> Change::all(int limit) {
QString sql = QString("SELECT %1 FROM %2 ORDER BY id ASC LIMIT %3")
.arg(BaseModel::tableFieldNames(jop::ChangesTable).join(","))
.arg(BaseModel::tableName(jop::ChangesTable))
.arg(QString::number(limit));
QSqlQuery q(sql);
jop::db().execQuery(q);
QVector<Change> output;
while (q.next()) {
Change change(q);
output.push_back(change);
}
return output;
}
QVector<Change> Change::mergedChanges(const QVector<Change>& changes) {
QStringList createdItems;
QStringList deletedItems;
QHash<QString, Change> itemChanges;
foreach (Change change, changes) {
QString itemId = change.value("item_id").toString();
Change::Type type = (Change::Type)change.value("type").toInt();
if (type == Change::Create) {
createdItems.push_back(itemId);
} else if (type == Change::Delete) {
deletedItems.push_back(itemId);
}
if (itemChanges.contains(itemId) && type == Change::Update) {
// Merge all the "Update" event into one.
Change& existingChange = itemChanges[itemId];
existingChange.addMergedField(change.value("item_field").toString());
} else {
itemChanges[itemId] = change;
}
}
QVector<Change> output;
for (QHash<QString, Change>::iterator it = itemChanges.begin(); it != itemChanges.end(); ++it) {
QString itemId = it.key();
Change& change = it.value();
if (createdItems.contains(itemId) && deletedItems.contains(itemId)) {
// Item both created then deleted - skip
continue;
}
if (deletedItems.contains(itemId)) {
// Item was deleted at some point - just return one 'delete' event
change.setValue("type", Change::Delete);
} else if (createdItems.contains(itemId)) {
// Item was created then updated - just return one 'create' event with the latest changes
change.setValue("type", Change::Create);
}
output.push_back(change);
}
return output;
}
void Change::addMergedField(const QString &name) {
if (mergedFields_.contains(name)) return;
mergedFields_.push_back(name);
}
QStringList Change::mergedFields() const {
QStringList output(mergedFields_);
QString itemField = value("item_field").toString();
if (!mergedFields_.contains(itemField)) {
output.push_back(itemField);
}
return output;
}

View File

@ -14,8 +14,19 @@ public:
enum Type { Undefined, Create, Update, Delete };
Change();
Change(const QSqlQuery& query);
Table table() const;
static QVector<Change> all(int limit = 100);
static QVector<Change> mergedChanges(const QVector<Change> &changes);
void addMergedField(const QString& name);
QStringList mergedFields() const;
private:
QStringList mergedFields_;
};
}

View File

@ -24,7 +24,7 @@ int Folder::count() {
}
QVector<Folder> Folder::all(const QString &orderBy) {
QSqlQuery q("SELECT " + BaseModel::tableFieldNames(jop::FoldersTable).join(",") + " FROM folders ORDER BY " + orderBy);
QSqlQuery q("SELECT " + BaseModel::tableFieldNames(jop::FoldersTable).join(",") + " FROM " + BaseModel::tableName(jop::FoldersTable) + " ORDER BY " + orderBy);
jop::db().execQuery(q);
QVector<Folder> output;

View File

@ -1,6 +1,7 @@
#include "synchronizer.h"
#include "models/folder.h"
#include "models/note.h"
#include "models/change.h"
using namespace jop;
@ -12,7 +13,12 @@ Synchronizer::Synchronizer(WebApi& api, Database &database) : api_(api), db_(dat
void Synchronizer::start() {
qDebug() << "Starting synchronizer...";
QSqlQuery query;
QVector<Change> changes = Change::all();
foreach (Change& change, changes) {
}
// QSqlQuery query;
// std::vector<Folder> folders;
// query = db_.query("SELECT " + Folder::dbFields().join(',') + " FROM folders WHERE synced = 0");