You've already forked joplin
mirror of
https://github.com/laurent22/joplin.git
synced 2025-07-16 00:14:34 +02:00
Modify list of folders
This commit is contained in:
42
QtClient/JoplinQtClient/AddButton.qml
Executable file
42
QtClient/JoplinQtClient/AddButton.qml
Executable file
@ -0,0 +1,42 @@
|
|||||||
|
import QtQuick 2.0
|
||||||
|
import QtQuick.Controls 2.0
|
||||||
|
import QtQuick.Layouts 1.1
|
||||||
|
|
||||||
|
Item {
|
||||||
|
|
||||||
|
id: root
|
||||||
|
width: 120
|
||||||
|
height: 100
|
||||||
|
signal addNoteButtonClicked
|
||||||
|
signal addFolderButtonClicked
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
spacing: 2
|
||||||
|
|
||||||
|
Button {
|
||||||
|
id: addNoteButton
|
||||||
|
text: "Add note"
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
onClicked: root.addNoteButtonClicked()
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
id: addFolderButton
|
||||||
|
text: "Add folder"
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
onClicked: root.addFolderButtonClicked()
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
text: "ADD"
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
39
QtClient/JoplinQtClient/EditableListDelegate.qml
Executable file
39
QtClient/JoplinQtClient/EditableListDelegate.qml
Executable file
@ -0,0 +1,39 @@
|
|||||||
|
import QtQuick 2.0
|
||||||
|
import QtQuick.Controls 2.0
|
||||||
|
|
||||||
|
Component {
|
||||||
|
Item {
|
||||||
|
width: parent.width
|
||||||
|
height: 25
|
||||||
|
Text {
|
||||||
|
id: label
|
||||||
|
text: display
|
||||||
|
anchors.fill: parent
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked: {
|
||||||
|
listView.currentIndex = index
|
||||||
|
}
|
||||||
|
onDoubleClicked: {
|
||||||
|
label.visible = false
|
||||||
|
textField.visible = true
|
||||||
|
textField.focus = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TextField {
|
||||||
|
id: textField
|
||||||
|
text: display
|
||||||
|
visible: false
|
||||||
|
width: parent.width
|
||||||
|
height: parent.height
|
||||||
|
onAccepted: {
|
||||||
|
|
||||||
|
}
|
||||||
|
onEditingFinished: {
|
||||||
|
label.visible = true
|
||||||
|
textField.visible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
43
QtClient/JoplinQtClient/EditableListItem.qml
Executable file
43
QtClient/JoplinQtClient/EditableListItem.qml
Executable file
@ -0,0 +1,43 @@
|
|||||||
|
import QtQuick 2.0
|
||||||
|
import QtQuick.Controls 2.0
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
width: parent.width
|
||||||
|
height: 25
|
||||||
|
Text {
|
||||||
|
id: label
|
||||||
|
text: display
|
||||||
|
anchors.fill: parent
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked: {
|
||||||
|
root.ListView.view.currentIndex = index
|
||||||
|
}
|
||||||
|
onDoubleClicked: {
|
||||||
|
label.visible = false
|
||||||
|
textField.visible = true
|
||||||
|
textField.focus = true
|
||||||
|
console.info("Editing ", index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TextField {
|
||||||
|
id: textField
|
||||||
|
text: display
|
||||||
|
visible: false
|
||||||
|
width: parent.width
|
||||||
|
height: parent.height
|
||||||
|
onAccepted: {
|
||||||
|
console.info(root.ListView.view.model);
|
||||||
|
console.info("Done ", index)
|
||||||
|
root.ListView.view.model.setData(index, text)
|
||||||
|
//root.ListView.view.model.setDataInt(index, "trest")
|
||||||
|
//root.ListView.view.currentItem = "test"
|
||||||
|
}
|
||||||
|
onEditingFinished: {
|
||||||
|
label.visible = true
|
||||||
|
textField.visible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
38
QtClient/JoplinQtClient/EditableListViewItem.qml
Executable file
38
QtClient/JoplinQtClient/EditableListViewItem.qml
Executable file
@ -0,0 +1,38 @@
|
|||||||
|
import QtQuick 2.0
|
||||||
|
import QtQuick.Controls 2.0
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: folderDelegateRoot
|
||||||
|
width: 100//parent.width
|
||||||
|
height: 25
|
||||||
|
Text {
|
||||||
|
id: label
|
||||||
|
text: display
|
||||||
|
anchors.fill: parent
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked: {
|
||||||
|
listView.currentIndex = index
|
||||||
|
}
|
||||||
|
onDoubleClicked: {
|
||||||
|
label.visible = false
|
||||||
|
textField.visible = true
|
||||||
|
textField.focus = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TextField {
|
||||||
|
id: textField
|
||||||
|
text: display
|
||||||
|
visible: false
|
||||||
|
width: parent.width
|
||||||
|
height: parent.height
|
||||||
|
onAccepted: {
|
||||||
|
|
||||||
|
}
|
||||||
|
onEditingFinished: {
|
||||||
|
label.visible = true
|
||||||
|
textField.visible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -13,23 +13,6 @@ Item {
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
}
|
}
|
||||||
|
|
||||||
Component {
|
|
||||||
id: folderDelegate
|
|
||||||
Item {
|
|
||||||
width: parent.width
|
|
||||||
height: 25
|
|
||||||
Text {
|
|
||||||
text: display
|
|
||||||
}
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: parent
|
|
||||||
onClicked: {
|
|
||||||
listView.currentIndex = index
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ListView {
|
ListView {
|
||||||
id: listView
|
id: listView
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
@ -37,5 +20,16 @@ Item {
|
|||||||
ScrollBar.vertical: ScrollBar { }
|
ScrollBar.vertical: ScrollBar { }
|
||||||
highlight: Rectangle { color: "lightsteelblue"; radius: 5 }
|
highlight: Rectangle { color: "lightsteelblue"; radius: 5 }
|
||||||
focus: true
|
focus: true
|
||||||
|
// onModelChanged: {
|
||||||
|
//// listView.model.onDataChanged = function() {
|
||||||
|
//// console.info("testaaaaaaaaaaaaaaaaaaa")
|
||||||
|
//// }
|
||||||
|
// console.info("MODEL CHANGAID")
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: folderDelegate
|
||||||
|
EditableListItem {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,9 @@ SOURCES += \
|
|||||||
models/qmlnote.cpp \
|
models/qmlnote.cpp \
|
||||||
webapi.cpp \
|
webapi.cpp \
|
||||||
synchronizer.cpp \
|
synchronizer.cpp \
|
||||||
settings.cpp
|
settings.cpp \
|
||||||
|
models/foldercollection.cpp \
|
||||||
|
databaseutils.cpp
|
||||||
|
|
||||||
RESOURCES += qml.qrc \
|
RESOURCES += qml.qrc \
|
||||||
database.qrc
|
database.qrc
|
||||||
@ -50,7 +52,10 @@ HEADERS += \
|
|||||||
models/qmlnote.h \
|
models/qmlnote.h \
|
||||||
webapi.h \
|
webapi.h \
|
||||||
synchronizer.h \
|
synchronizer.h \
|
||||||
settings.h
|
settings.h \
|
||||||
|
models/foldercollection.h \
|
||||||
|
databaseutils.h \
|
||||||
|
simpletypes.h
|
||||||
|
|
||||||
DISTFILES +=
|
DISTFILES +=
|
||||||
|
|
||||||
|
4
QtClient/JoplinQtClient/Test.qml
Executable file
4
QtClient/JoplinQtClient/Test.qml
Executable file
@ -0,0 +1,4 @@
|
|||||||
|
import QtQuick 2.4
|
||||||
|
|
||||||
|
TestForm {
|
||||||
|
}
|
26
QtClient/JoplinQtClient/TestForm.ui.qml
Executable file
26
QtClient/JoplinQtClient/TestForm.ui.qml
Executable file
@ -0,0 +1,26 @@
|
|||||||
|
import QtQuick 2.4
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: item1
|
||||||
|
width: 400
|
||||||
|
height: 400
|
||||||
|
|
||||||
|
AddButton {
|
||||||
|
id: addButton1
|
||||||
|
x: 232
|
||||||
|
y: 294
|
||||||
|
width: 100
|
||||||
|
height: 50
|
||||||
|
anchors.rightMargin: 0
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.right: parent.right
|
||||||
|
}
|
||||||
|
|
||||||
|
FolderList {
|
||||||
|
id: folderList1
|
||||||
|
width: 107
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.left: parent.left
|
||||||
|
}
|
||||||
|
}
|
@ -8,7 +8,16 @@
|
|||||||
|
|
||||||
using namespace jop;
|
using namespace jop;
|
||||||
|
|
||||||
Application::Application(int &argc, char **argv) : QGuiApplication(argc, argv), db_("D:/Web/www/joplin/QtClient/data/notes.sqlite"), api_("http://joplin.local"), synchronizer_(api_, db_) {
|
Application::Application(int &argc, char **argv) :
|
||||||
|
QGuiApplication(argc, argv),
|
||||||
|
db_("D:/Web/www/joplin/QtClient/data/notes.sqlite"),
|
||||||
|
api_("http://joplin.local"),
|
||||||
|
synchronizer_(api_, db_),
|
||||||
|
folderCollection_(db_, 0, "title ASC"),
|
||||||
|
folderModel_(db_)
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
// This is linked to where the QSettings will be saved. In other words,
|
// 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
|
// if these values are changed, the settings will be reset and saved
|
||||||
// somewhere else.
|
// somewhere else.
|
||||||
@ -18,8 +27,11 @@ Application::Application(int &argc, char **argv) : QGuiApplication(argc, argv),
|
|||||||
|
|
||||||
Settings settings;
|
Settings settings;
|
||||||
|
|
||||||
|
//folderCollection_ = FolderCollection(db_, 0, "title ASC");
|
||||||
|
|
||||||
folderService_ = FolderService(db_);
|
folderService_ = FolderService(db_);
|
||||||
folderModel_.setService(folderService_);
|
//folderModel_.setService(folderService_);
|
||||||
|
//folderModel_.setCollection(folderCollection_);
|
||||||
|
|
||||||
noteService_ = NoteService(db_);
|
noteService_ = NoteService(db_);
|
||||||
noteModel_.setService(noteService_);
|
noteModel_.setService(noteService_);
|
||||||
@ -89,7 +101,7 @@ void Application::afterSessionInitialization() {
|
|||||||
QString sessionId = settings.value("sessionId").toString();
|
QString sessionId = settings.value("sessionId").toString();
|
||||||
qDebug() << "Session:" << sessionId;
|
qDebug() << "Session:" << sessionId;
|
||||||
api_.setSessionId(sessionId);
|
api_.setSessionId(sessionId);
|
||||||
synchronizer_.start();
|
//synchronizer_.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::view_currentFolderChanged() {
|
void Application::view_currentFolderChanged() {
|
||||||
@ -103,3 +115,11 @@ void Application::view_currentNoteChanged() {
|
|||||||
Note note = noteCollection_.byId(noteId);
|
Note note = noteCollection_.byId(noteId);
|
||||||
selectedQmlNote_.setNote(note);
|
selectedQmlNote_.setNote(note);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Application::view_addNoteButtonClicked() {
|
||||||
|
qDebug() << "ici";
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::view_addFolderButtonClicked() {
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "services/noteservice.h"
|
#include "services/noteservice.h"
|
||||||
#include "models/foldermodel.h"
|
#include "models/foldermodel.h"
|
||||||
#include "models/notecollection.h"
|
#include "models/notecollection.h"
|
||||||
|
#include "models/foldercollection.h"
|
||||||
#include "services/notecache.h"
|
#include "services/notecache.h"
|
||||||
#include "models/notemodel.h"
|
#include "models/notemodel.h"
|
||||||
#include "models/qmlnote.h"
|
#include "models/qmlnote.h"
|
||||||
@ -30,6 +31,7 @@ private:
|
|||||||
Database db_;
|
Database db_;
|
||||||
FolderService folderService_;
|
FolderService folderService_;
|
||||||
NoteCollection noteCollection_;
|
NoteCollection noteCollection_;
|
||||||
|
FolderCollection folderCollection_;
|
||||||
NoteService noteService_;
|
NoteService noteService_;
|
||||||
FolderModel folderModel_;
|
FolderModel folderModel_;
|
||||||
NoteModel noteModel_;
|
NoteModel noteModel_;
|
||||||
@ -46,6 +48,8 @@ public slots:
|
|||||||
|
|
||||||
void view_currentFolderChanged();
|
void view_currentFolderChanged();
|
||||||
void view_currentNoteChanged();
|
void view_currentNoteChanged();
|
||||||
|
void view_addNoteButtonClicked();
|
||||||
|
void view_addFolderButtonClicked();
|
||||||
void api_requestDone(const QJsonObject& response, const QString& tag);
|
void api_requestDone(const QJsonObject& response, const QString& tag);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -27,6 +27,10 @@ QSqlQuery Database::query(const QString &sql) const {
|
|||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QSqlDatabase &Database::database() {
|
||||||
|
return db_;
|
||||||
|
}
|
||||||
|
|
||||||
//QSqlQuery Database::exec(const QString &sql, const QMap<QString, QVariant> ¶meters) {
|
//QSqlQuery Database::exec(const QString &sql, const QMap<QString, QVariant> ¶meters) {
|
||||||
// QSqlQuery query;
|
// QSqlQuery query;
|
||||||
// query.prepare(sql);
|
// query.prepare(sql);
|
||||||
|
@ -12,6 +12,7 @@ public:
|
|||||||
Database(const QString& path);
|
Database(const QString& path);
|
||||||
Database();
|
Database();
|
||||||
QSqlQuery query(const QString& sql) const;
|
QSqlQuery query(const QString& sql) const;
|
||||||
|
QSqlDatabase& database();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
69
QtClient/JoplinQtClient/databaseutils.cpp
Executable file
69
QtClient/JoplinQtClient/databaseutils.cpp
Executable file
@ -0,0 +1,69 @@
|
|||||||
|
#include <stable.h>
|
||||||
|
|
||||||
|
#include "databaseutils.h"
|
||||||
|
|
||||||
|
using namespace jop;
|
||||||
|
|
||||||
|
QSqlQuery dbUtils::buildSqlQuery(QSqlDatabase* db, const QString& type, const QString& tableName, const QStringList& fields, const VariantVector& values, const QString& whereCondition) {
|
||||||
|
QString sql;
|
||||||
|
|
||||||
|
if (type.toLower() == "insert") {
|
||||||
|
QString fieldString = "";
|
||||||
|
QString valueString = "";
|
||||||
|
for (int i = 0; i < fields.length(); i++) {
|
||||||
|
QString f = fields[i];
|
||||||
|
if (fieldString != "") fieldString += ", ";
|
||||||
|
if (valueString != "") valueString += ", ";
|
||||||
|
fieldString += f;
|
||||||
|
valueString += ":" + f;
|
||||||
|
}
|
||||||
|
|
||||||
|
sql = QString("INSERT INTO %1 (%2) VALUES (%3)").arg(tableName).arg(fieldString).arg(valueString);
|
||||||
|
} else if (type.toLower() == "update") {
|
||||||
|
QString fieldString = "";
|
||||||
|
for (int i = 0; i < fields.length(); i++) {
|
||||||
|
QString f = fields[i];
|
||||||
|
if (fieldString != "") fieldString += ", ";
|
||||||
|
fieldString += f + " = :" + f;
|
||||||
|
}
|
||||||
|
|
||||||
|
sql = QString("UPDATE %1 SET %2").arg(tableName).arg(fieldString);
|
||||||
|
if (whereCondition != "") sql += " WHERE " + whereCondition;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSqlQuery query(*db);
|
||||||
|
query.prepare(sql);
|
||||||
|
for (int i = 0; i < values.size(); i++) {
|
||||||
|
QVariant v = values[i];
|
||||||
|
QString fieldName = ":" + fields[i];
|
||||||
|
if (v.type() == QVariant::String) {
|
||||||
|
query.bindValue(fieldName, v.toString());
|
||||||
|
} else if (v.type() == QVariant::Int) {
|
||||||
|
query.bindValue(fieldName, v.toInt());
|
||||||
|
} else if (v.isNull()) {
|
||||||
|
query.bindValue(fieldName, (int)NULL);
|
||||||
|
} else if (v.type() == QVariant::Double) {
|
||||||
|
query.bindValue(fieldName, v.toDouble());
|
||||||
|
} else if (v.type() == (QVariant::Type)QMetaType::Float) {
|
||||||
|
query.bindValue(fieldName, v.toFloat());
|
||||||
|
} else if (v.type() == QVariant::LongLong) {
|
||||||
|
query.bindValue(fieldName, v.toLongLong());
|
||||||
|
} else if (v.type() == QVariant::UInt) {
|
||||||
|
query.bindValue(fieldName, v.toUInt());
|
||||||
|
} else if (v.type() == QVariant::Char) {
|
||||||
|
query.bindValue(fieldName, v.toChar());
|
||||||
|
} else {
|
||||||
|
qWarning() << Q_FUNC_INFO << "Unsupported variant type:" << v.type();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug() <<"SQL:"<<sql;
|
||||||
|
|
||||||
|
QMapIterator<QString, QVariant> i(query.boundValues());
|
||||||
|
while (i.hasNext()) {
|
||||||
|
i.next();
|
||||||
|
qDebug() << i.key() << ":" << i.value().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
return query;
|
||||||
|
}
|
15
QtClient/JoplinQtClient/databaseutils.h
Executable file
15
QtClient/JoplinQtClient/databaseutils.h
Executable file
@ -0,0 +1,15 @@
|
|||||||
|
#ifndef DATABASEUTILS_H
|
||||||
|
#define DATABASEUTILS_H
|
||||||
|
|
||||||
|
#include <stable.h>
|
||||||
|
#include "simpletypes.h"
|
||||||
|
|
||||||
|
namespace jop {
|
||||||
|
namespace dbUtils {
|
||||||
|
|
||||||
|
QSqlQuery buildSqlQuery(QSqlDatabase* db, const QString& type, const QString& tableName, const QStringList& fields, const VariantVector& values, const QString& whereCondition = "");
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // DATABASEUTILS_H
|
@ -9,6 +9,8 @@ Item {
|
|||||||
height: 600
|
height: 600
|
||||||
signal currentFolderChanged()
|
signal currentFolderChanged()
|
||||||
signal currentNoteChanged()
|
signal currentNoteChanged()
|
||||||
|
signal addNoteButtonClicked()
|
||||||
|
signal addFolderButtonClicked()
|
||||||
property alias currentFolderIndex: folderList.currentIndex
|
property alias currentFolderIndex: folderList.currentIndex
|
||||||
property alias currentNoteIndex: noteList.currentIndex
|
property alias currentNoteIndex: noteList.currentIndex
|
||||||
|
|
||||||
@ -58,4 +60,12 @@ Item {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AddButton {
|
||||||
|
id: addButton
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
onAddFolderButtonClicked: root.addFolderButtonClicked()
|
||||||
|
onAddNoteButtonClicked: root.addNoteButtonClicked()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,57 @@
|
|||||||
#include "foldercollection.h"
|
#include "foldercollection.h"
|
||||||
|
#include "databaseutils.h"
|
||||||
|
|
||||||
using namespace jop;
|
using namespace jop;
|
||||||
|
|
||||||
FolderCollection::FolderCollection() {
|
//FolderCollection::FolderCollection() {}
|
||||||
|
|
||||||
|
// Note: although parentId is supplied, it is currently not being used.
|
||||||
|
FolderCollection::FolderCollection(Database& db, const QString& parentId, const QString& orderBy) {
|
||||||
|
db_ = db;
|
||||||
|
parentId_ = parentId;
|
||||||
|
orderBy_ = orderBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
Folder FolderCollection::at(int index) const {
|
||||||
|
if (cache_.size()) return cache_[index];
|
||||||
|
|
||||||
|
QSqlQuery q = db_.query("SELECT id, title FROM folders ORDER BY " + orderBy_);
|
||||||
|
q.exec();
|
||||||
|
|
||||||
|
while (q.next()) {
|
||||||
|
Folder folder;
|
||||||
|
folder.setId(q.value(0).toString());
|
||||||
|
folder.setTitle(q.value(1).toString());
|
||||||
|
|
||||||
|
cache_.push_back(folder);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return at(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: cache result
|
||||||
|
int FolderCollection::count() const {
|
||||||
|
QSqlQuery q = db_.query("SELECT count(*) as row_count FROM folders");
|
||||||
|
q.exec();
|
||||||
|
q.next();
|
||||||
|
return q.value(0).toInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
Folder FolderCollection::byId(const QString& id) const {
|
||||||
|
int count = this->count();
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
Folder folder = at(i);
|
||||||
|
if (folder.id() == id) return folder;
|
||||||
|
}
|
||||||
|
|
||||||
|
qWarning() << "Invalid folder ID:" << id;
|
||||||
|
return Folder();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FolderCollection::update(const QString &id, const QStringList &fields, const VariantVector &values) {
|
||||||
|
QSqlQuery q = dbUtils::buildSqlQuery(&db_.database(), "update", "folders", fields, values, "id = \"" + id + "\"");
|
||||||
|
q.exec();
|
||||||
|
cache_.clear();
|
||||||
|
emit changed(0, count() - 1, fields);
|
||||||
}
|
}
|
||||||
|
@ -2,20 +2,38 @@
|
|||||||
#define FOLDERCOLLECTION_H
|
#define FOLDERCOLLECTION_H
|
||||||
|
|
||||||
#include <stable.h>
|
#include <stable.h>
|
||||||
#include "model/folder.h"
|
|
||||||
|
#include "database.h"
|
||||||
|
#include "models/note.h"
|
||||||
|
#include "models/folder.h"
|
||||||
|
#include "sparsevector.hpp"
|
||||||
|
#include "simpletypes.h"
|
||||||
|
|
||||||
namespace jop {
|
namespace jop {
|
||||||
|
|
||||||
class FolderCollection {
|
class FolderCollection : public QObject {
|
||||||
|
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
FolderCollection();
|
//FolderCollection();
|
||||||
void add(const Folder* folder);
|
FolderCollection(Database& db, const QString &parentId, const QString& orderBy);
|
||||||
|
Folder at(int index) const;
|
||||||
|
int count() const;
|
||||||
|
Folder byId(const QString &id) const;
|
||||||
|
void update(const QString& id, const QStringList& fields, const VariantVector& values);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
std::vector<Folder*> collection_;
|
QString parentId_;
|
||||||
|
QString orderBy_;
|
||||||
|
Database db_;
|
||||||
|
mutable QVector<Folder> cache_;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
|
||||||
|
void changed(int from, int to, const QStringList& fields);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2,32 +2,20 @@
|
|||||||
|
|
||||||
using namespace jop;
|
using namespace jop;
|
||||||
|
|
||||||
FolderModel::FolderModel() : QAbstractListModel() {}
|
FolderModel::FolderModel(Database &database) : QAbstractListModel(), folderCollection_(database, 0, "title") {
|
||||||
|
connect(&folderCollection_, SIGNAL(changed(int,int,const QStringList&)), this, SLOT(folderCollection_changed(int,int,const QStringList&)));
|
||||||
void FolderModel::setService(FolderService &folderService) {
|
|
||||||
folderService_ = folderService;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderModel::addFolder(Folder* folder) {
|
|
||||||
//folders_.push_back(folder);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int FolderModel::rowCount(const QModelIndex & parent) const {
|
int FolderModel::rowCount(const QModelIndex & parent) const {
|
||||||
Q_UNUSED(parent);
|
Q_UNUSED(parent);
|
||||||
return folderService_.count();
|
return folderCollection_.count();
|
||||||
//return 10;
|
|
||||||
//return folders_.size();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: to lazy load - send back "Loading..." if item not currently loaded
|
// NOTE: to lazy load - send back "Loading..." if item not currently loaded
|
||||||
// queue the item for loading.
|
// queue the item for loading.
|
||||||
// Then batch load them a bit later.
|
// 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 {
|
||||||
QList<Folder> list = folderService_.overviewList();
|
Folder folder = folderCollection_.at(index.row());
|
||||||
|
|
||||||
if (index.row() < 0 || index.row() >= list.size()) return QVariant();
|
|
||||||
|
|
||||||
Folder folder = list[index.row()];
|
|
||||||
|
|
||||||
if (role == Qt::DisplayRole) {
|
if (role == Qt::DisplayRole) {
|
||||||
return QVariant(folder.title());
|
return QVariant(folder.title());
|
||||||
@ -40,6 +28,26 @@ QVariant FolderModel::data(const QModelIndex & index, int role) const {
|
|||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FolderModel::setData(const QModelIndex &index, const QVariant &value, int role) {
|
||||||
|
Folder folder = folderCollection_.at(index.row());
|
||||||
|
|
||||||
|
if (role == Qt::EditRole) {
|
||||||
|
QStringList fields;
|
||||||
|
fields << "title";
|
||||||
|
VariantVector values;
|
||||||
|
values << value;
|
||||||
|
folderCollection_.update(folder.id(), fields, values);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
qWarning() << "Unsupported role" << role;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FolderModel::setData(int index, const QVariant &value, int role) {
|
||||||
|
return setData(this->index(index), value, role);
|
||||||
|
}
|
||||||
|
|
||||||
QHash<int, QByteArray> FolderModel::roleNames() const {
|
QHash<int, QByteArray> FolderModel::roleNames() const {
|
||||||
QHash<int, QByteArray> roles = QAbstractItemModel::roleNames();
|
QHash<int, QByteArray> roles = QAbstractItemModel::roleNames();
|
||||||
roles[TitleRole] = "title";
|
roles[TitleRole] = "title";
|
||||||
@ -48,10 +56,8 @@ QHash<int, QByteArray> FolderModel::roleNames() const {
|
|||||||
return roles;
|
return roles;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FolderModel::canFetchMore(const QModelIndex &parent) const {
|
void FolderModel::folderCollection_changed(int from, int to, const QStringList& fields) {
|
||||||
return folders_.size() < folderService_.count();
|
QVector<int> roles;
|
||||||
}
|
roles << Qt::DisplayRole;
|
||||||
|
emit dataChanged(this->index(from), this->index(to), roles);
|
||||||
void FolderModel::fetchMore(const QModelIndex &parent) {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,9 @@
|
|||||||
|
|
||||||
#include <stable.h>
|
#include <stable.h>
|
||||||
|
|
||||||
|
#include "database.h"
|
||||||
#include "services/folderservice.h"
|
#include "services/folderservice.h"
|
||||||
|
#include "models/foldercollection.h"
|
||||||
|
|
||||||
namespace jop {
|
namespace jop {
|
||||||
|
|
||||||
@ -19,9 +21,10 @@ public:
|
|||||||
RawRole
|
RawRole
|
||||||
};
|
};
|
||||||
|
|
||||||
FolderModel();
|
FolderModel(Database& database);
|
||||||
|
|
||||||
void setService(FolderService& folderService);
|
//void setService(FolderService& folderService);
|
||||||
|
//void setCollection(FolderCollection& folderCollection);
|
||||||
|
|
||||||
void addFolder(Folder* folder);
|
void addFolder(Folder* folder);
|
||||||
|
|
||||||
@ -29,16 +32,23 @@ public:
|
|||||||
|
|
||||||
QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;
|
QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;
|
||||||
|
|
||||||
|
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
QHash<int, QByteArray> roleNames() const;
|
QHash<int, QByteArray> roleNames() const;
|
||||||
bool canFetchMore(const QModelIndex &parent) const Q_DECL_OVERRIDE;
|
|
||||||
void fetchMore(const QModelIndex &parent) Q_DECL_OVERRIDE;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
QList<Folder> folders_;
|
QList<Folder> folders_;
|
||||||
FolderService folderService_;
|
FolderService folderService_;
|
||||||
|
FolderCollection folderCollection_;
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
|
||||||
|
bool setData(int index, const QVariant &value, int role = Qt::EditRole);
|
||||||
|
void folderCollection_changed(int from, int to, const QStringList &fields);
|
||||||
|
//bool setDataInt(int index, const QVariant &value, int role = Qt::EditRole);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
#include "database.h"
|
#include "database.h"
|
||||||
#include "models/note.h"
|
#include "models/note.h"
|
||||||
#include "services/notecache.h"
|
|
||||||
#include "sparsevector.hpp"
|
#include "sparsevector.hpp"
|
||||||
|
|
||||||
namespace jop {
|
namespace jop {
|
||||||
|
@ -4,5 +4,9 @@
|
|||||||
<file>FolderList.qml</file>
|
<file>FolderList.qml</file>
|
||||||
<file>NoteList.qml</file>
|
<file>NoteList.qml</file>
|
||||||
<file>NoteEditor.qml</file>
|
<file>NoteEditor.qml</file>
|
||||||
|
<file>AddButton.qml</file>
|
||||||
|
<file>Test.qml</file>
|
||||||
|
<file>TestForm.ui.qml</file>
|
||||||
|
<file>EditableListItem.qml</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
@ -47,3 +47,7 @@ const QList<Folder> FolderService::overviewList() const {
|
|||||||
|
|
||||||
return cache_;
|
return cache_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FolderService::clearCache() {
|
||||||
|
cache_.clear();
|
||||||
|
}
|
||||||
|
@ -17,6 +17,7 @@ public:
|
|||||||
Folder byId(const QString &id) const;
|
Folder byId(const QString &id) const;
|
||||||
//Folder partialAt(int index) const;
|
//Folder partialAt(int index) const;
|
||||||
const QList<Folder> overviewList() const;
|
const QList<Folder> overviewList() const;
|
||||||
|
void clearCache();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
12
QtClient/JoplinQtClient/simpletypes.h
Executable file
12
QtClient/JoplinQtClient/simpletypes.h
Executable file
@ -0,0 +1,12 @@
|
|||||||
|
#ifndef SIMPLETYPES_H
|
||||||
|
#define SIMPLETYPES_H
|
||||||
|
|
||||||
|
#include <stable.h>
|
||||||
|
|
||||||
|
namespace jop {
|
||||||
|
|
||||||
|
typedef QVector<QVariant> VariantVector;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // SIMPLETYPES_H
|
@ -32,3 +32,4 @@ INCLUDEPATH += "C:/Program Files (x86)/Windows Kits/10/Include/10.0.10240.0/ucrt
|
|||||||
LIBS += -L"C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/lib"
|
LIBS += -L"C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/lib"
|
||||||
LIBS += -L"C:/Program Files (x86)/Windows Kits/8.1/Lib/winv6.3/um/x86"
|
LIBS += -L"C:/Program Files (x86)/Windows Kits/8.1/Lib/winv6.3/um/x86"
|
||||||
LIBS += -L"C:/Program Files (x86)/Windows Kits/10/Lib/10.0.10240.0/ucrt/x86"
|
LIBS += -L"C:/Program Files (x86)/Windows Kits/10/Lib/10.0.10240.0/ucrt/x86"
|
||||||
|
|
||||||
|
@ -41,15 +41,6 @@ abstract class ApiController extends Controller {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 1. client 1 : bla bla bla
|
|
||||||
// 2. client 2 : bla bla bla fromclient2
|
|
||||||
// 3. client 1 : client1bla bla bla
|
|
||||||
|
|
||||||
// RESULT: client1bla bla bla
|
|
||||||
|
|
||||||
// Because diff for 3 is done between 2 and 3
|
|
||||||
// Need to introduce revID so that Change class knows between which versions the diff should be made
|
|
||||||
|
|
||||||
// HACK: get connection once here so that it's initialized and can
|
// HACK: get connection once here so that it's initialized and can
|
||||||
// be accessed from models.
|
// be accessed from models.
|
||||||
$this->db = $this->get('app.eloquent')->connection();
|
$this->db = $this->get('app.eloquent')->connection();
|
||||||
|
Reference in New Issue
Block a user