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

Display notes

This commit is contained in:
Laurent Cozic 2017-01-12 17:59:19 +01:00
parent d3e8ce55f9
commit 4e549695cf
23 changed files with 178 additions and 158 deletions

View File

@ -1,4 +1,4 @@
import QtQuick 2.0 import QtQuick 2.7
import QtQuick.Controls 2.0 import QtQuick.Controls 2.0
import QtQuick.Layouts 1.1 import QtQuick.Layouts 1.1

View File

@ -11,7 +11,6 @@ SOURCES += \
models/notemodel.cpp \ models/notemodel.cpp \
models/note.cpp \ models/note.cpp \
application.cpp \ application.cpp \
models/notecollection.cpp \
models/qmlnote.cpp \ models/qmlnote.cpp \
webapi.cpp \ webapi.cpp \
synchronizer.cpp \ synchronizer.cpp \
@ -45,7 +44,6 @@ HEADERS += \
models/notemodel.h \ models/notemodel.h \
models/note.h \ models/note.h \
application.h \ application.h \
models/notecollection.h \
sparsevector.hpp \ sparsevector.hpp \
models/qmlnote.h \ models/qmlnote.h \
webapi.h \ webapi.h \

View File

@ -32,14 +32,4 @@ LoginPageForm {
} }
} }
// Connections {
// target: dispatcher
// onLoginFailed: {
// root.enabled = true;
// }
// onLoginSuccess: {
// root.enabled = true;
// }
// }
} }

View File

@ -1,6 +1,6 @@
import QtQuick 2.7 import QtQuick 2.7
import QtQuick.Controls 2.0 import QtQuick.Controls 2.0
import QtQuick.Controls 1.4 //import QtQuick.Controls 1.4
import QtQuick.Layouts 1.0 import QtQuick.Layouts 1.0
Item { Item {
@ -103,7 +103,7 @@ Item {
text: "Logout" text: "Logout"
anchors.right: syncButton.left anchors.right: syncButton.left
anchors.top: parent.top anchors.top: parent.top
onClicked: appRoot.logoutClicked() //dispatcher.logoutClicked() onClicked: appRoot.logoutClicked()
} }
} }

View File

@ -58,12 +58,10 @@ Item {
} }
function emitLoginStarted() { function emitLoginStarted() {
print("CALLING emitLoginStarted");
root.loginStarted(); root.loginStarted();
} }
function emitLoginFailed() { function emitLoginFailed() {
print("CALLING emitLoginFailed");
root.loginFailed(); root.loginFailed();
} }

View File

@ -17,8 +17,7 @@ using namespace jop;
Application::Application(int &argc, char **argv) : Application::Application(int &argc, char **argv) :
QGuiApplication(argc, argv), QGuiApplication(argc, argv),
db_(jop::db()), db_(jop::db()),
synchronizer_(db_), synchronizer_(db_)
folderModel_(db_)
{ {
@ -51,7 +50,6 @@ Application::Application(int &argc, char **argv) :
ctxt->setContextProperty("folderListModel", &folderModel_); ctxt->setContextProperty("folderListModel", &folderModel_);
ctxt->setContextProperty("noteListModel", &noteModel_); ctxt->setContextProperty("noteListModel", &noteModel_);
ctxt->setContextProperty("noteModel", &selectedQmlNote_); ctxt->setContextProperty("noteModel", &selectedQmlNote_);
ctxt->setContextProperty("dispatcher", &dispatcher());
ctxt->setContextProperty("settings", qmlSettings); ctxt->setContextProperty("settings", qmlSettings);
view_.setSource(QUrl("qrc:/app.qml")); view_.setSource(QUrl("qrc:/app.qml"));
@ -65,12 +63,6 @@ Application::Application(int &argc, char **argv) :
connect(rootObject, SIGNAL(loginClicked(QString,QString,QString)), this, SLOT(dispatcher_loginClicked(QString,QString,QString))); connect(rootObject, SIGNAL(loginClicked(QString,QString,QString)), this, SLOT(dispatcher_loginClicked(QString,QString,QString)));
connect(rootObject, SIGNAL(logoutClicked()), this, SLOT(dispatcher_logoutClicked())); connect(rootObject, SIGNAL(logoutClicked()), this, SLOT(dispatcher_logoutClicked()));
connect(&dispatcher(), SIGNAL(folderCreated(QString)), this, SLOT(dispatcher_folderCreated(QString)));
connect(&dispatcher(), SIGNAL(folderUpdated(QString)), this, SLOT(dispatcher_folderUpdated(QString)));
connect(&dispatcher(), SIGNAL(folderDeleted(QString)), this, SLOT(dispatcher_folderDeleted(QString)));
//connect(&dispatcher(), SIGNAL(loginClicked(QString,QString,QString)), this, SLOT(dispatcher_loginClicked(QString,QString,QString)));
//connect(&dispatcher(), SIGNAL(logoutClicked()), this, SLOT(dispatcher_logoutClicked()));
view_.show(); view_.show();
synchronizerTimer_.setInterval(1000 * 120); synchronizerTimer_.setInterval(1000 * 120);
@ -81,6 +73,7 @@ Application::Application(int &argc, char **argv) :
connect(&api_, SIGNAL(requestDone(const QJsonObject&, const QString&)), this, SLOT(api_requestDone(const QJsonObject&, const QString&))); connect(&api_, SIGNAL(requestDone(const QJsonObject&, const QString&)), this, SLOT(api_requestDone(const QJsonObject&, const QString&)));
if (!settings.contains("user.email") || !settings.contains("session.id") || !settings.contains("api.baseUrl")) { if (!settings.contains("user.email") || !settings.contains("session.id") || !settings.contains("api.baseUrl")) {
synchronizer_.freeze();
view_.showPage("login"); view_.showPage("login");
} else { } else {
afterSessionInitialization(); afterSessionInitialization();
@ -121,9 +114,7 @@ void Application::api_requestDone(const QJsonObject& response, const QString& ta
if (tag == "getSession") { if (tag == "getSession") {
if (response.contains("error")) { if (response.contains("error")) {
qWarning() << "Could not get session:" << response.value("error").toString(); qWarning() << "Could not get session:" << response.value("error").toString();
//dispatcher().emitLoginFailed();
view_.emitSignal("loginFailed"); view_.emitSignal("loginFailed");
//qDebug() << "FAILEDFAILEDFAILEDFAILEDFAILEDFAILEDFAILEDFAILEDFAILEDFAILEDFAILEDFAILED";
view_.showPage("login"); view_.showPage("login");
} else { } else {
QString sessionId = response.value("id").toString(); QString sessionId = response.value("id").toString();
@ -131,7 +122,6 @@ void Application::api_requestDone(const QJsonObject& response, const QString& ta
Settings settings; Settings settings;
settings.setValue("session.id", sessionId); settings.setValue("session.id", sessionId);
afterSessionInitialization(); afterSessionInitialization();
//dispatcher().emitLoginSuccess();
view_.emitSignal("loginSuccess"); view_.emitSignal("loginSuccess");
view_.showPage("main"); view_.showPage("main");
} }
@ -139,21 +129,6 @@ void Application::api_requestDone(const QJsonObject& response, const QString& ta
} }
} }
void Application::dispatcher_folderCreated(const QString &folderId) {
qDebug() << "Folder created" << folderId;
//synchronizerTimer_.start(1000 * 3);
}
void Application::dispatcher_folderUpdated(const QString &folderId) {
qDebug() << "Folder udpated" << folderId;
//synchronizerTimer_.start(1000 * 3);
}
void Application::dispatcher_folderDeleted(const QString &folderId) {
qDebug() << "Folder deleted" << folderId;
//synchronizerTimer_.start(1000 * 3);
}
void Application::dispatcher_loginClicked(const QString &apiBaseUrl, const QString &email, const QString &password) { void Application::dispatcher_loginClicked(const QString &apiBaseUrl, const QString &email, const QString &password) {
qDebug() << apiBaseUrl << email << password; qDebug() << apiBaseUrl << email << password;
@ -188,7 +163,7 @@ void Application::dispatcher_logoutClicked() {
synchronizer_.freeze(); synchronizer_.freeze();
Settings settings; Settings settings;
settings.setValue("session.id", ""); settings.remove("session.id");
api_.setSessionId(""); api_.setSessionId("");
synchronizer_.setSessionId(""); synchronizer_.setSessionId("");
@ -232,9 +207,8 @@ void Application::afterSessionInitialization() {
} }
void Application::view_currentFolderChanged() { void Application::view_currentFolderChanged() {
// QString folderId = selectedFolderId(); QString folderId = selectedFolderId();
// noteCollection_ = NoteCollection(db_, folderId, "title ASC"); noteModel_.setFolderId(folderId);
// noteModel_.setCollection(noteCollection_);
} }
void Application::view_currentNoteChanged() { void Application::view_currentNoteChanged() {

View File

@ -5,7 +5,6 @@
#include "database.h" #include "database.h"
#include "models/foldermodel.h" #include "models/foldermodel.h"
#include "models/notecollection.h"
#include "models/notemodel.h" #include "models/notemodel.h"
#include "models/qmlnote.h" #include "models/qmlnote.h"
#include "webapi.h" #include "webapi.h"
@ -27,7 +26,6 @@ private:
Window view_; Window view_;
Database& db_; Database& db_;
NoteCollection noteCollection_;
FolderModel folderModel_; FolderModel folderModel_;
NoteModel noteModel_; NoteModel noteModel_;
QString selectedFolderId() const; QString selectedFolderId() const;
@ -49,9 +47,6 @@ public slots:
void api_requestDone(const QJsonObject& response, const QString& tag); void api_requestDone(const QJsonObject& response, const QString& tag);
void dispatcher_folderCreated(const QString& folderId);
void dispatcher_folderUpdated(const QString& folderId);
void dispatcher_folderDeleted(const QString& folderId);
void dispatcher_loginClicked(const QString &domain, const QString &email, const QString &password); void dispatcher_loginClicked(const QString &domain, const QString &email, const QString &password);
void dispatcher_logoutClicked(); void dispatcher_logoutClicked();

View File

@ -7,6 +7,7 @@ Database::Database() {}
void Database::initialize(const QString &path) { void Database::initialize(const QString &path) {
version_ = -1; version_ = -1;
transactionCount_ = 0; transactionCount_ = 0;
logQueries_ = false;
//QFile::remove(path); //QFile::remove(path);
@ -19,9 +20,6 @@ void Database::initialize(const QString &path) {
qDebug() << "Database: connection ok"; qDebug() << "Database: connection ok";
} }
// execQuery("DELETE FROM folders");
// execQuery("DELETE FROM settings");
upgrade(); upgrade();
} }
@ -131,13 +129,15 @@ bool Database::commit() {
} }
bool Database::execQuery(QSqlQuery &query) { bool Database::execQuery(QSqlQuery &query) {
// qDebug().noquote() << "SQL:" << query.lastQuery(); if (logQueries_) {
qDebug().noquote() << "SQL:" << query.lastQuery();
// QMapIterator<QString, QVariant> i(query.boundValues()); QMapIterator<QString, QVariant> i(query.boundValues());
// while (i.hasNext()) { while (i.hasNext()) {
// i.next(); i.next();
// qDebug().noquote() << "SQL:" << i.key() << "=" << i.value().toString(); qDebug().noquote() << "SQL:" << i.key() << "=" << i.value().toString();
// } }
}
return query.exec(); return query.exec();
} }

View File

@ -33,6 +33,7 @@ private:
mutable int version_; mutable int version_;
QStringList sqlStringToLines(const QString& sql); QStringList sqlStringToLines(const QString& sql);
int transactionCount_; int transactionCount_;
bool logQueries_;
}; };

View File

@ -52,8 +52,6 @@ bool BaseModel::load(const QString &id) {
bool BaseModel::save(bool trackChanges) { bool BaseModel::save(bool trackChanges) {
bool isNew = this->isNew(); bool isNew = this->isNew();
qDebug() << "SAVING" << valuesToString();
if (!changedFields_.size() && !isNew) return true; if (!changedFields_.size() && !isNew) return true;
QStringList fields = changedFields(); QStringList fields = changedFields();
@ -170,7 +168,7 @@ bool BaseModel::dispose() {
} }
Table BaseModel::table() const { Table BaseModel::table() const {
qCritical() << "BaseModel::table() must be overriden"; qFatal("BaseModel::table() must be overriden");
return jop::UndefinedTable; return jop::UndefinedTable;
} }
@ -209,12 +207,33 @@ QVector<BaseModel::Field> BaseModel::tableFields(jop::Table table) {
output.push_back(createField("title", QMetaType::QString )); output.push_back(createField("title", QMetaType::QString ));
output.push_back(createField("created_time", QMetaType::Int )); output.push_back(createField("created_time", QMetaType::Int ));
output.push_back(createField("updated_time", QMetaType::Int )); output.push_back(createField("updated_time", QMetaType::Int ));
} else if (table == jop::NotesTable) {
output.push_back(createField("id", QMetaType::Int ));
output.push_back(createField("title", QMetaType::QString ));
output.push_back(createField("body", QMetaType::QString ));
output.push_back(createField("parent_id", QMetaType::QString ));
output.push_back(createField("created_time", QMetaType::Int ));
output.push_back(createField("updated_time", QMetaType::Int ));
output.push_back(createField("latitude", QMetaType::QString ));
output.push_back(createField("longitude", QMetaType::QString ));
output.push_back(createField("altitude", QMetaType::QString ));
output.push_back(createField("source", QMetaType::QString ));
output.push_back(createField("author", QMetaType::QString ));
output.push_back(createField("source_url", QMetaType::QString ));
output.push_back(createField("is_todo", QMetaType::Int ));
output.push_back(createField("todo_due", QMetaType::Int ));
output.push_back(createField("todo_completed", QMetaType::Int ));
output.push_back(createField("source_application", QMetaType::QString ));
output.push_back(createField("application_data", QMetaType::QString ));
output.push_back(createField("order", QMetaType::Int ));
} else if (table == jop::ChangesTable) { } else if (table == jop::ChangesTable) {
output.push_back(createField("id", QMetaType::Int )); output.push_back(createField("id", QMetaType::Int ));
output.push_back(createField("type", QMetaType::Int )); output.push_back(createField("type", QMetaType::Int ));
output.push_back(createField("item_id", QMetaType::QString )); output.push_back(createField("item_id", QMetaType::QString ));
output.push_back(createField("item_type", QMetaType::Int )); output.push_back(createField("item_type", QMetaType::Int ));
output.push_back(createField("item_field", QMetaType::QString )); output.push_back(createField("item_field", QMetaType::QString ));
} else {
qFatal("Field not defined for table %d", table);
} }
BaseModel::tableFields_[table] = output; BaseModel::tableFields_[table] = output;
@ -238,6 +257,16 @@ QStringList BaseModel::tableFieldNames(Table table) {
return output; return output;
} }
QString BaseModel::sqlTableFields(Table table) {
QString output = "";
QStringList fields = BaseModel::tableFieldNames(table);
for (int i = 0; i < fields.size(); i++) {
if (output != "") output += ",";
output += QString("`%1`").arg(fields[i]);
}
return output;
}
bool BaseModel::isValidFieldName(Table table, const QString &name) { bool BaseModel::isValidFieldName(Table table, const QString &name) {
QVector<BaseModel::Field> fields = BaseModel::tableFields(table); QVector<BaseModel::Field> fields = BaseModel::tableFields(table);
foreach (BaseModel::Field col, fields) { foreach (BaseModel::Field col, fields) {
@ -348,7 +377,7 @@ void BaseModel::setValue(const QString &name, const QJsonValue &value, QMetaType
} else if (type == QMetaType::Int) { } else if (type == QMetaType::Int) {
setValue(name, value.toInt()); setValue(name, value.toInt());
} else { } else {
qCritical() << "Unsupported value type" << name << type; qFatal("Unsupported value type %s %d", name.toStdString(), type);
} }
} }
@ -370,7 +399,7 @@ QString BaseModel::tableName(Table t) {
if (t == jop::FoldersTable) return "folders"; if (t == jop::FoldersTable) return "folders";
if (t == jop::NotesTable) return "notes"; if (t == jop::NotesTable) return "notes";
if (t == jop::ChangesTable) return "changes"; if (t == jop::ChangesTable) return "changes";
return "UNDEFINED"; qFatal("Unknown table %d", t);
} }
QVariant BaseModel::cacheGet(const QString &key) { QVariant BaseModel::cacheGet(const QString &key) {

View File

@ -56,6 +56,7 @@ public:
static QVector<BaseModel::Field> tableFields(Table table); static QVector<BaseModel::Field> tableFields(Table table);
static bool hasField(jop::Table table, const QString& name); static bool hasField(jop::Table table, const QString& name);
static QStringList tableFieldNames(Table table); static QStringList tableFieldNames(Table table);
static QString sqlTableFields(Table table);
static bool isValidFieldName(Table table, const QString& name); static bool isValidFieldName(Table table, const QString& name);
static void deleteAll(Table table); static void deleteAll(Table table);

View File

@ -20,6 +20,35 @@ bool Folder::trackChanges() const {
return true; return true;
} }
int Folder::noteCount() const {
QSqlQuery q = jop::db().prepare(QString("SELECT count(*) AS row_count FROM %1 WHERE parent_id = :parent_id").arg(BaseModel::tableName(jop::NotesTable)));
q.bindValue(":parent_id", id().toString());
jop::db().execQuery(q);
q.next();
return q.value(0).toInt();
}
QVector<Note> Folder::notes(const QString &orderBy, int limit, int offset) const {
QVector<Note> output;
QSqlQuery q = jop::db().prepare(QString("SELECT %1 FROM notes WHERE parent_id = :parent_id ORDER BY %2 LIMIT %3 OFFSET %4")
.arg(BaseModel::sqlTableFields(jop::NotesTable))
.arg(orderBy)
.arg(limit)
.arg(offset));
q.bindValue(":parent_id", id().toString());
jop::db().execQuery(q);
if (!jop::db().errorCheck(q)) return output;
while (q.next()) {
Note note;
note.loadSqlQuery(q);
output.push_back(note);
}
return output;
}
int Folder::count() { int Folder::count() {
return BaseModel::count(jop::FoldersTable); return BaseModel::count(jop::FoldersTable);
} }

View File

@ -3,6 +3,7 @@
#include <stable.h> #include <stable.h>
#include "models/item.h" #include "models/item.h"
#include "models/note.h"
namespace jop { namespace jop {
@ -18,6 +19,8 @@ public:
Table table() const; Table table() const;
bool primaryKeyIsUuid() const; bool primaryKeyIsUuid() const;
bool trackChanges() const; bool trackChanges() const;
int noteCount() const;
QVector<Note> notes(const QString& orderBy, int limit, int offset) const;
// bool save(); // bool save();
// bool dispose(); // bool dispose();

View File

@ -4,7 +4,7 @@
using namespace jop; using namespace jop;
FolderModel::FolderModel(Database &database) : QAbstractListModel(), db_(database), orderBy_("title") { FolderModel::FolderModel() : QAbstractListModel(), orderBy_("title") {
virtualItemShown_ = false; virtualItemShown_ = false;
connect(&dispatcher(), SIGNAL(folderCreated(QString)), this, SLOT(dispatcher_folderCreated(QString))); connect(&dispatcher(), SIGNAL(folderCreated(QString)), this, SLOT(dispatcher_folderCreated(QString)));
@ -17,9 +17,6 @@ int FolderModel::rowCount(const QModelIndex & parent) const { Q_UNUSED(parent);
return Folder::count() + (virtualItemShown_ ? 1 : 0); return Folder::count() + (virtualItemShown_ ? 1 : 0);
} }
// NOTE: to lazy load - send back "Loading..." if item not currently loaded
// queue the item for loading.
// Then batch load them a bit later.
QVariant FolderModel::data(const QModelIndex & index, int role) const { QVariant FolderModel::data(const QModelIndex & index, int role) const {
Folder folder; Folder folder;
@ -47,10 +44,6 @@ bool FolderModel::setData(const QModelIndex &index, const QVariant &value, int r
folder.setValue("title", value); folder.setValue("title", value);
if (!folder.save()) return false; if (!folder.save()) return false;
cache_.clear(); cache_.clear();
// QVector<int> roles;
// roles << Qt::DisplayRole;
// emit dataChanged(this->index(0), this->index(rowCount() - 1), roles);
return true; return true;
} }
@ -134,36 +127,12 @@ void FolderModel::addData(const QString &title) {
folder.setValue("title", title); folder.setValue("title", title);
if (!folder.save()) return; if (!folder.save()) return;
//cache_.clear();
lastInsertId_ = folder.id().toString(); lastInsertId_ = folder.id().toString();
// QVector<int> roles;
// roles << Qt::DisplayRole;
// int from = 0;
// int to = rowCount() - 1;
// // Necessary to make sure a new item is added to the view, even
// // though it might not be positioned there due to sorting
// beginInsertRows(QModelIndex(), to, to);
// endInsertRows();
// emit dataChanged(this->index(from), this->index(to), roles);
} }
void FolderModel::deleteData(const int index) { void FolderModel::deleteData(const int index) {
Folder folder = atIndex(index); Folder folder = atIndex(index);
if (!folder.dispose()) return; if (!folder.dispose()) return;
// cache_.clear();
// beginRemoveRows(QModelIndex(), index, index);
// endRemoveRows();
// QVector<int> roles;
// roles << Qt::DisplayRole;
// emit dataChanged(this->index(0), this->index(rowCount() - 1), roles);
} }
// TODO: instead of clearing the whole cache every time, the individual items // TODO: instead of clearing the whole cache every time, the individual items

View File

@ -20,7 +20,7 @@ public:
RawRole RawRole
}; };
FolderModel(Database& database); FolderModel();
void addFolder(Folder* folder); void addFolder(Folder* folder);
int rowCount(const QModelIndex & parent = QModelIndex()) const; int rowCount(const QModelIndex & parent = QModelIndex()) const;
@ -38,7 +38,6 @@ private:
QList<Folder> folders_; QList<Folder> folders_;
bool virtualItemShown_; bool virtualItemShown_;
QString orderBy_; QString orderBy_;
Database& db_;
mutable QVector<Folder> cache_; mutable QVector<Folder> cache_;
QString lastInsertId_; QString lastInsertId_;

View File

@ -2,27 +2,16 @@
using namespace jop; using namespace jop;
Note::Note() Note::Note() : Item() {}
{
Table Note::table() const {
return jop::NotesTable;
} }
//QString Note::body() const { bool Note::primaryKeyIsUuid() const {
// return body_; return true;
//} }
//void Note::setBody(const QString &v) { bool Note::trackChanges() const {
// body_ = v; return true;
//} }
//QStringList Note::dbFields() {
// QStringList output = Item::dbFields();
// output << "body";
// return output;
//}
//void Note::fromSqlQuery(const QSqlQuery &q) {
// Item::fromSqlQuery(q);
// int idx = Item::dbFields().size();
// body_ = q.value(idx).toString();
//}

View File

@ -11,14 +11,9 @@ class Note : public Item {
public: public:
Note(); Note();
// QString body() const; Table table() const;
// void setBody(const QString& v); bool primaryKeyIsUuid() const;
// static QStringList dbFields(); bool trackChanges() const;
// void fromSqlQuery(const QSqlQuery &q);
//private:
// QString body_;
}; };

View File

@ -78,5 +78,6 @@ Note NoteCollection::byId(const QString& id) const {
// note.setId(q.value(0).toString()); // note.setId(q.value(0).toString());
// note.setTitle(q.value(1).toString()); // note.setTitle(q.value(1).toString());
// note.setBody(q.value(2).toString()); // note.setBody(q.value(2).toString());
// return note; // return note;
} }

View File

@ -1,35 +1,65 @@
#include "notemodel.h" #include "notemodel.h"
jop::NoteModel::NoteModel() jop::NoteModel::NoteModel() {
{ folderId_ = "";
orderBy_ = "title";
} }
int jop::NoteModel::rowCount(const QModelIndex &parent) const { int jop::NoteModel::rowCount(const QModelIndex &parent) const {
Q_UNUSED(parent); Q_UNUSED(parent);
return collection_.count(); return folder().noteCount();
} }
QVariant jop::NoteModel::data(const QModelIndex &index, int role) const { QVariant jop::NoteModel::data(const QModelIndex &index, int role) const {
if (index.row() < 0 || index.row() >= rowCount()) return QVariant(); Note note = atIndex(index.row());
// Note note = collection_.at(index.row()); if (role == IdRole) {
return QVariant(note.id().toString());
}
// if (role == IdRole) { return QVariant(note.value("title").toString());
// return QVariant(note.id()); }
// }
// return QVariant(note.title()); jop::Note jop::NoteModel::atIndex(int index) const {
if (folderId_ == "") return Note();
if (index < 0 || index >= rowCount()) return Note();
if (cache_.isset(index)) return cache_.get(index);
std::vector<int> indexes = cache_.availableBufferAround(index, 32);
if (!indexes.size()) {
qWarning() << "Couldn't acquire buffer"; // "Cannot happen"
return Note();
}
int from = indexes[0];
int to = indexes[indexes.size() - 1];
Folder folder = this->folder();
QVector<Note> notes = folder.notes(orderBy_, to - from + 1, from);
int noteIndex = from;
for (int i = 0; i < notes.size(); i++) {
cache_.set(noteIndex, notes[i]);
noteIndex++;
}
return cache_.get(index);
} }
void jop::NoteModel::setFolderId(const QString &v) { void jop::NoteModel::setFolderId(const QString &v) {
if (v == folderId_) return;
beginResetModel();
cache_.clear();
folderId_ = v; folderId_ = v;
endResetModel();
} }
void jop::NoteModel::setCollection(jop::NoteCollection &noteCollection) { jop::Folder jop::NoteModel::folder() const {
beginResetModel(); Folder folder;
collection_ = noteCollection; if (folderId_ == "") return folder;
endResetModel(); folder.load(folderId_);
return folder;
} }
QHash<int, QByteArray> jop::NoteModel::roleNames() const { QHash<int, QByteArray> jop::NoteModel::roleNames() const {

View File

@ -3,7 +3,8 @@
#include <stable.h> #include <stable.h>
#include "models/notecollection.h" #include "models/folder.h"
#include "sparsevector.hpp"
namespace jop { namespace jop {
@ -21,8 +22,9 @@ public:
NoteModel(); NoteModel();
int rowCount(const QModelIndex & parent = QModelIndex()) const; int rowCount(const QModelIndex & parent = QModelIndex()) const;
QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const; QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;
Note atIndex(int index) const;
void setFolderId(const QString& v); void setFolderId(const QString& v);
void setCollection(NoteCollection& noteCollection); Folder folder() const;
protected: protected:
@ -32,7 +34,8 @@ private:
QList<Note> notes_; QList<Note> notes_;
QString folderId_; QString folderId_;
NoteCollection collection_; QString orderBy_;
mutable SparseVector<Note> cache_;
}; };

View File

@ -6,7 +6,8 @@ using namespace jop;
void Setting::setSettings(const QSettings::SettingsMap &map) { void Setting::setSettings(const QSettings::SettingsMap &map) {
jop::db().transaction(); jop::db().transaction();
QString sql = "INSERT OR REPLACE INTO settings (`key`, `value`, `type`) VALUES (:key, :value, :type)"; jop::db().execQuery("DELETE FROM settings");
QString sql = "INSERT INTO settings (`key`, `value`, `type`) VALUES (:key, :value, :type)";
QSqlQuery query = jop::db().prepare(sql); QSqlQuery query = jop::db().prepare(sql);
for (QSettings::SettingsMap::const_iterator it = map.begin(); it != map.end(); ++it) { for (QSettings::SettingsMap::const_iterator it = map.begin(); it != map.end(); ++it) {
query.bindValue(":key", it.key()); query.bindValue(":key", it.key());

View File

@ -9,7 +9,7 @@ CREATE TABLE notes (
id TEXT PRIMARY KEY, id TEXT PRIMARY KEY,
title TEXT, title TEXT,
body TEXT, body TEXT,
parent_id INT, parent_id TEXT,
created_time INT, created_time INT,
updated_time INT, updated_time INT,
latitude NUMERIC, latitude NUMERIC,

View File

@ -355,8 +355,10 @@ int main(int argc, char *argv[]) {
qsrand(QTime::currentTime().msec()); qsrand(QTime::currentTime().msec());
QString dbPath = "D:/Web/www/joplin/QtClient/data/notes.sqlite"; QString dbPath = "C:/Users/Laurent/AppData/Local/Joplin/Joplin.sqlite";
QString resourceDir = "D:/Web/www/joplin/QtClient/data/resources"; QString resourceDir = "C:/Users/Laurent/AppData/Local/Joplin/resources";
QDir(resourceDir).mkpath(".");
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE"); QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName(dbPath); db.setDatabaseName(dbPath);
@ -371,9 +373,11 @@ int main(int argc, char *argv[]) {
// TODO: REMOVE REMOVE REMOVE // TODO: REMOVE REMOVE REMOVE
db.exec("DELETE FROM folders"); db.exec("DELETE FROM folders");
db.exec("DELETE FROM notes"); db.exec("DELETE FROM notes");
db.exec("DELETE FROM changes");
db.exec("DELETE FROM resources"); db.exec("DELETE FROM resources");
db.exec("DELETE FROM note_resources"); db.exec("DELETE FROM note_resources");
db.exec("DELETE FROM tags"); db.exec("DELETE FROM tags");
db.exec("DELETE FROM settings WHERE key = 'lastRevId'");
// TODO: REMOVE REMOVE REMOVE // TODO: REMOVE REMOVE REMOVE
QDir dir("S:/Docs/Textes/Calendrier/EvernoteBackup/Enex20161219"); QDir dir("S:/Docs/Textes/Calendrier/EvernoteBackup/Enex20161219");
@ -388,13 +392,24 @@ int main(int argc, char *argv[]) {
QString folderId = createUuid(QString("%1%2%3%4").arg(fileInfo.baseName()).arg(fileInfo.created().toTime_t()).arg((int)qrand()).arg(QDateTime::currentMSecsSinceEpoch())); QString folderId = createUuid(QString("%1%2%3%4").arg(fileInfo.baseName()).arg(fileInfo.created().toTime_t()).arg((int)qrand()).arg(QDateTime::currentMSecsSinceEpoch()));
QSqlQuery query(db); {
query.prepare("INSERT INTO folders (id, title, created_time, updated_time) VALUES (?, ?, ?, ?)"); QSqlQuery query(db);
query.addBindValue(folderId); query.prepare("INSERT INTO folders (id, title, created_time, updated_time) VALUES (?, ?, ?, ?)");
query.addBindValue(fileInfo.baseName()); query.addBindValue(folderId);
query.addBindValue(fileInfo.created().toTime_t()); query.addBindValue(fileInfo.baseName());
query.addBindValue(fileInfo.created().toTime_t()); query.addBindValue(fileInfo.created().toTime_t());
query.exec(); query.addBindValue(fileInfo.created().toTime_t());
query.exec();
}
{
QSqlQuery query(db);
query.prepare("INSERT INTO changes (type, item_id, item_type) VALUES (?, ?, ?)");
query.addBindValue(1);
query.addBindValue(folderId);
query.addBindValue(1);
query.exec();
}
std::vector<Note> notes = parseXmlFile(fileInfo.absoluteFilePath()); std::vector<Note> notes = parseXmlFile(fileInfo.absoluteFilePath());