mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-24 10:27:10 +02:00
Add delete folder
This commit is contained in:
parent
e751dfc793
commit
4570fcac18
@ -5,39 +5,78 @@ Item {
|
||||
id: root
|
||||
width: parent.width
|
||||
height: 25
|
||||
property int mouseAreaDefaultWidth
|
||||
property Menu contextMenu
|
||||
|
||||
signal stoppedEditing;
|
||||
signal editingAccepted(int index, string text);
|
||||
|
||||
function makeEditable(editable) {
|
||||
if (typeof editable === 'undefined') editable = true;
|
||||
|
||||
if (editable === isEditable()) return; // Nothing to do
|
||||
|
||||
if (editable) {
|
||||
label.visible = false
|
||||
mouseArea.anchors.rightMargin = 10000; // Hack because `mouseArea.visible = false` makes the MouseArea ignore the next click event
|
||||
textField.visible = true
|
||||
textField.focus = true
|
||||
textField.text = display
|
||||
root.ListView.view.focus = true;
|
||||
textField.selectAll()
|
||||
} else {
|
||||
mouseArea.anchors.rightMargin = 0;
|
||||
label.visible = true
|
||||
textField.visible = false
|
||||
root.stoppedEditing();
|
||||
}
|
||||
}
|
||||
|
||||
function startEditing() {
|
||||
makeEditable(true);
|
||||
}
|
||||
|
||||
function stopEditing() {
|
||||
makeEditable(false);
|
||||
}
|
||||
|
||||
function isEditable() {
|
||||
return textField.visible;
|
||||
}
|
||||
|
||||
Text {
|
||||
id: label
|
||||
text: display
|
||||
anchors.fill: parent
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
root.ListView.view.currentIndex = index
|
||||
}
|
||||
onDoubleClicked: {
|
||||
label.visible = false
|
||||
textField.visible = true
|
||||
textField.focus = true
|
||||
textField.selectAll()
|
||||
textField.text = display
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TextField {
|
||||
id: textField
|
||||
text: display
|
||||
visible: false
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
onAccepted: {
|
||||
root.ListView.view.model.setData(index, text)
|
||||
root.editingAccepted(index, text);
|
||||
}
|
||||
onEditingFinished: {
|
||||
label.visible = true
|
||||
textField.visible = false
|
||||
stopEditing();
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||
onClicked: {
|
||||
root.ListView.view.currentIndex = index
|
||||
if (mouse.button === Qt.RightButton) {
|
||||
contextMenu.open();
|
||||
}
|
||||
}
|
||||
onDoubleClicked: {
|
||||
startEditing();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -6,6 +6,20 @@ Item {
|
||||
property alias model: listView.model
|
||||
property alias currentIndex: listView.currentIndex
|
||||
property alias currentItem: listView.currentItem
|
||||
property string currentItemId
|
||||
|
||||
signal stoppedEditing;
|
||||
signal editingAccepted(int index, string text);
|
||||
signal deleteButtonClicked(int index);
|
||||
|
||||
function startEditing(index) {
|
||||
currentIndex = model.rowCount() - 1;
|
||||
currentItem.startEditing();
|
||||
}
|
||||
|
||||
function stopEditing() {
|
||||
currentItem.stopEditing();
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
color: "#eeeeff"
|
||||
@ -14,22 +28,48 @@ Item {
|
||||
}
|
||||
|
||||
ListView {
|
||||
|
||||
Connections {
|
||||
target: model
|
||||
onDataChanged: {
|
||||
if (currentItemId !== "") {
|
||||
var newIndex = model.idToIndex(currentItemId);
|
||||
currentIndex = newIndex
|
||||
if (newIndex < 0) currentItemId = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onCurrentItemChanged: {
|
||||
currentItemId = model.idAtIndex(currentIndex);
|
||||
}
|
||||
|
||||
id: listView
|
||||
highlightMoveVelocity: -1
|
||||
highlightMoveDuration: 100
|
||||
anchors.fill: parent
|
||||
delegate: folderDelegate
|
||||
ScrollBar.vertical: ScrollBar { }
|
||||
highlight: Rectangle { color: "lightsteelblue"; radius: 5 }
|
||||
focus: true
|
||||
// onModelChanged: {
|
||||
//// listView.model.onDataChanged = function() {
|
||||
//// console.info("testaaaaaaaaaaaaaaaaaaa")
|
||||
//// }
|
||||
// console.info("MODEL CHANGAID")
|
||||
// }
|
||||
}
|
||||
|
||||
Component {
|
||||
id: folderDelegate
|
||||
EditableListItem {}
|
||||
EditableListItem {
|
||||
contextMenu:
|
||||
Menu {
|
||||
MenuItem {
|
||||
text: "Delete"
|
||||
onTriggered: deleteButtonClicked(currentIndex);
|
||||
}
|
||||
}
|
||||
onStoppedEditing: {
|
||||
root.stoppedEditing();
|
||||
}
|
||||
onEditingAccepted: function(index, text) {
|
||||
root.editingAccepted(index, text);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,9 @@ SOURCES += \
|
||||
webapi.cpp \
|
||||
synchronizer.cpp \
|
||||
settings.cpp \
|
||||
models/foldercollection.cpp
|
||||
models/foldercollection.cpp \
|
||||
uuid.cpp \
|
||||
dispatcher.cpp
|
||||
|
||||
RESOURCES += qml.qrc \
|
||||
database.qrc
|
||||
@ -45,7 +47,9 @@ HEADERS += \
|
||||
synchronizer.h \
|
||||
settings.h \
|
||||
models/foldercollection.h \
|
||||
simpletypes.h
|
||||
simpletypes.h \
|
||||
uuid.h \
|
||||
dispatcher.h
|
||||
|
||||
DISTFILES +=
|
||||
|
||||
|
@ -5,6 +5,8 @@
|
||||
#include "models/foldermodel.h"
|
||||
#include "services/folderservice.h"
|
||||
#include "settings.h"
|
||||
#include "uuid.h"
|
||||
#include "dispatcher.h"
|
||||
|
||||
using namespace jop;
|
||||
|
||||
@ -38,21 +40,27 @@ Application::Application(int &argc, char **argv) :
|
||||
|
||||
connect(rootObject, SIGNAL(currentFolderChanged()), this, SLOT(view_currentFolderChanged()));
|
||||
connect(rootObject, SIGNAL(currentNoteChanged()), this, SLOT(view_currentNoteChanged()));
|
||||
connect(rootObject, SIGNAL(addFolderButtonClicked()), this, SLOT(view_addFolderButtonClicked()));
|
||||
|
||||
view_.show();
|
||||
|
||||
connect(&api_, SIGNAL(requestDone(const QJsonObject&, const QString&)), this, SLOT(api_requestDone(const QJsonObject&, const QString&)));
|
||||
|
||||
QString sessionId = settings.value("sessionId").toString();
|
||||
if (sessionId == "") {
|
||||
//if (sessionId == "") {
|
||||
QUrlQuery postData;
|
||||
postData.addQueryItem("email", "laurent@cozic.net");
|
||||
postData.addQueryItem("password", "12345678");
|
||||
postData.addQueryItem("client_id", "B6E12222B6E12222");
|
||||
api_.post("sessions", QUrlQuery(), postData, "getSession");
|
||||
} else {
|
||||
afterSessionInitialization();
|
||||
}
|
||||
// } else {
|
||||
// afterSessionInitialization();
|
||||
// }
|
||||
|
||||
|
||||
|
||||
//emit jop::dispatcher().folderCreated("test");
|
||||
//.folderCreated("tes");
|
||||
}
|
||||
|
||||
void Application::api_requestDone(const QJsonObject& response, const QString& tag) {
|
||||
@ -91,7 +99,7 @@ void Application::afterSessionInitialization() {
|
||||
QString sessionId = settings.value("sessionId").toString();
|
||||
qDebug() << "Session:" << sessionId;
|
||||
api_.setSessionId(sessionId);
|
||||
//synchronizer_.start();
|
||||
synchronizer_.start();
|
||||
}
|
||||
|
||||
void Application::view_currentFolderChanged() {
|
||||
@ -107,9 +115,18 @@ void Application::view_currentNoteChanged() {
|
||||
}
|
||||
|
||||
void Application::view_addNoteButtonClicked() {
|
||||
qDebug() << "ici";
|
||||
|
||||
}
|
||||
|
||||
void Application::view_addFolderButtonClicked() {
|
||||
// QStringList fields;
|
||||
// fields << "id";
|
||||
// VariantVector values;
|
||||
// values << uuid::createUuid();
|
||||
// QSqlQuery q = db_.buildSqlQuery(Database::Insert, "folders", fields, values);
|
||||
// q.exec();
|
||||
|
||||
// emit jop::dispatcher().folderCreated("test");
|
||||
|
||||
//qDebug() << "Added" << q.lastInsertId().toString();
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ using namespace jop;
|
||||
Database::Database(const QString &path) {
|
||||
version_ = -1;
|
||||
|
||||
//QFile::remove(path);
|
||||
// QFile::remove(path);
|
||||
|
||||
db_ = QSqlDatabase::addDatabase("QSQLITE");
|
||||
db_.setDatabaseName(path);
|
||||
@ -84,13 +84,13 @@ QSqlQuery Database::buildSqlQuery(Database::QueryType type, const QString &table
|
||||
}
|
||||
}
|
||||
|
||||
qDebug() <<"SQL:"<<sql;
|
||||
// qDebug() <<"SQL:"<<sql;
|
||||
|
||||
QMapIterator<QString, QVariant> i(query.boundValues());
|
||||
while (i.hasNext()) {
|
||||
i.next();
|
||||
qDebug() << i.key() << ":" << i.value().toString();
|
||||
}
|
||||
// QMapIterator<QString, QVariant> i(query.boundValues());
|
||||
// while (i.hasNext()) {
|
||||
// i.next();
|
||||
// qDebug() << i.key() << ":" << i.value().toString();
|
||||
// }
|
||||
|
||||
return query;
|
||||
}
|
||||
|
17
QtClient/JoplinQtClient/dispatcher.cpp
Executable file
17
QtClient/JoplinQtClient/dispatcher.cpp
Executable file
@ -0,0 +1,17 @@
|
||||
#include "dispatcher.h"
|
||||
|
||||
using namespace jop;
|
||||
|
||||
Dispatcher::Dispatcher() {
|
||||
|
||||
}
|
||||
|
||||
Dispatcher instance_;
|
||||
|
||||
Dispatcher& jop::dispatcher() {
|
||||
return instance_;
|
||||
}
|
||||
|
||||
//Dispatcher &Dispatcher::instance() {
|
||||
// return instance_;
|
||||
//}
|
29
QtClient/JoplinQtClient/dispatcher.h
Executable file
29
QtClient/JoplinQtClient/dispatcher.h
Executable file
@ -0,0 +1,29 @@
|
||||
#ifndef DISPATCHER_H
|
||||
#define DISPATCHER_H
|
||||
|
||||
namespace jop {
|
||||
|
||||
class Dispatcher : public QObject {
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
Dispatcher();
|
||||
//static Dispatcher& instance();
|
||||
|
||||
signals:
|
||||
|
||||
void folderCreated(const QString& id);
|
||||
|
||||
private:
|
||||
|
||||
//static Dispatcher& instance_;
|
||||
|
||||
};
|
||||
|
||||
Dispatcher& dispatcher();
|
||||
|
||||
}
|
||||
|
||||
#endif // DISPATCHER_H
|
@ -32,6 +32,24 @@ Item {
|
||||
onCurrentItemChanged: {
|
||||
root.currentFolderChanged()
|
||||
}
|
||||
|
||||
onEditingAccepted: function(index, text) {
|
||||
if (folderList.model.virtualItemShown()) {
|
||||
folderList.model.addData(text)
|
||||
} else {
|
||||
folderList.model.setData(index, text)
|
||||
}
|
||||
}
|
||||
|
||||
onStoppedEditing: {
|
||||
if (folderList.model.virtualItemShown()) {
|
||||
folderList.model.hideVirtualItem();
|
||||
}
|
||||
}
|
||||
|
||||
onDeleteButtonClicked: {
|
||||
folderList.model.deleteData(index)
|
||||
}
|
||||
}
|
||||
|
||||
NoteList {
|
||||
@ -64,7 +82,10 @@ Item {
|
||||
id: addButton
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
onAddFolderButtonClicked: root.addFolderButtonClicked()
|
||||
onAddFolderButtonClicked: {
|
||||
folderList.model.showVirtualItem();
|
||||
folderList.startEditing(folderList.model.rowCount() - 1);
|
||||
}
|
||||
onAddNoteButtonClicked: root.addNoteButtonClicked()
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include "foldercollection.h"
|
||||
#include "databaseutils.h"
|
||||
#include "dispatcher.h"
|
||||
#include "uuid.h"
|
||||
|
||||
using namespace jop;
|
||||
|
||||
@ -8,24 +10,35 @@ FolderCollection::FolderCollection(Database& db, const QString& parentId, const
|
||||
db_ = db;
|
||||
parentId_ = parentId;
|
||||
orderBy_ = orderBy;
|
||||
|
||||
connect(&jop::dispatcher(), SIGNAL(folderCreated(const QString&)), this, SLOT(dispatcher_folderCreated(QString)));
|
||||
}
|
||||
|
||||
Folder FolderCollection::at(int index) const {
|
||||
if (cache_.size()) return cache_[index];
|
||||
if (cache_.size()) {
|
||||
if (index < 0 || index >= count()) {
|
||||
qWarning() << "Invalid folder index:" << index;
|
||||
return Folder();
|
||||
}
|
||||
|
||||
QSqlQuery q = db_.query("SELECT id, title FROM folders ORDER BY " + orderBy_);
|
||||
return cache_[index];
|
||||
}
|
||||
|
||||
QSqlQuery q = db_.query("SELECT " + Folder::dbFields().join(",") + " FROM folders ORDER BY " + orderBy_);
|
||||
q.exec();
|
||||
|
||||
while (q.next()) {
|
||||
Folder folder;
|
||||
folder.setId(q.value(0).toString());
|
||||
folder.setTitle(q.value(1).toString());
|
||||
|
||||
folder.fromSqlQuery(q);
|
||||
cache_.push_back(folder);
|
||||
}
|
||||
|
||||
|
||||
return at(index);
|
||||
if (!cache_.size()) {
|
||||
qWarning() << "Invalid folder index:" << index;
|
||||
return Folder();
|
||||
} else {
|
||||
return at(index);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: cache result
|
||||
@ -37,19 +50,57 @@ int FolderCollection::count() const {
|
||||
}
|
||||
|
||||
Folder FolderCollection::byId(const QString& id) const {
|
||||
int index = idToIndex(id);
|
||||
return at(index);
|
||||
}
|
||||
|
||||
int FolderCollection::idToIndex(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;
|
||||
if (folder.id() == id) return i;
|
||||
}
|
||||
|
||||
qWarning() << "Invalid folder ID:" << id;
|
||||
return Folder();
|
||||
return -1;
|
||||
}
|
||||
|
||||
void FolderCollection::update(const QString &id, const QStringList &fields, const VariantVector &values) {
|
||||
QString FolderCollection::indexToId(int index) const {
|
||||
Folder folder = at(index);
|
||||
return folder.id();
|
||||
}
|
||||
|
||||
void FolderCollection::update(const QString &id, QStringList fields, VariantVector values) {
|
||||
if (!fields.contains("synced")) {
|
||||
fields.push_back("synced");
|
||||
values.push_back(QVariant(0));
|
||||
}
|
||||
QSqlQuery q = db_.buildSqlQuery(Database::Update, "folders", fields, values, "id = \"" + id + "\"");
|
||||
q.exec();
|
||||
cache_.clear();
|
||||
emit changed(0, count() - 1, fields);
|
||||
}
|
||||
|
||||
void FolderCollection::add(QStringList fields, VariantVector values) {
|
||||
fields.push_back("synced");
|
||||
values.push_back(QVariant(0));
|
||||
|
||||
fields.push_back("id");
|
||||
values.push_back(uuid::createUuid());
|
||||
|
||||
QSqlQuery q = db_.buildSqlQuery(Database::Insert, "folders", fields, values);
|
||||
q.exec();
|
||||
cache_.clear();
|
||||
emit changed(0, count() - 1, fields);
|
||||
}
|
||||
|
||||
void FolderCollection::remove(const QString& id) {
|
||||
QSqlQuery q(db_.database());
|
||||
q.prepare("DELETE FROM folders WHERE id = :id");
|
||||
q.bindValue(":id", id);
|
||||
q.exec();
|
||||
cache_.clear();
|
||||
emit changed(0, count(), QStringList());
|
||||
}
|
||||
|
||||
void FolderCollection::dispatcher_folderCreated(const QString &id) {
|
||||
|
||||
}
|
||||
|
@ -22,7 +22,11 @@ public:
|
||||
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);
|
||||
int idToIndex(const QString& id) const;
|
||||
QString indexToId(int index) const;
|
||||
void update(const QString& id, QStringList fields, VariantVector values);
|
||||
void add(QStringList fields, VariantVector values);
|
||||
void remove(const QString &id);
|
||||
|
||||
private:
|
||||
|
||||
@ -35,6 +39,10 @@ signals:
|
||||
|
||||
void changed(int from, int to, const QStringList& fields);
|
||||
|
||||
public slots:
|
||||
|
||||
void dispatcher_folderCreated(const QString& id);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -2,20 +2,27 @@
|
||||
|
||||
using namespace jop;
|
||||
|
||||
FolderModel::FolderModel(Database &database) : QAbstractListModel(), folderCollection_(database, 0, "title") {
|
||||
FolderModel::FolderModel(Database &database) : QAbstractListModel(), folderCollection_(database, 0, "title"), db_(database), orderBy_("title") {
|
||||
virtualItemShown_ = false;
|
||||
connect(&folderCollection_, SIGNAL(changed(int,int,const QStringList&)), this, SLOT(folderCollection_changed(int,int,const QStringList&)));
|
||||
}
|
||||
|
||||
int FolderModel::rowCount(const QModelIndex & parent) const {
|
||||
Q_UNUSED(parent);
|
||||
return folderCollection_.count();
|
||||
return folderCollection_.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 {
|
||||
Folder folder = folderCollection_.at(index.row());
|
||||
Folder folder;
|
||||
|
||||
if (virtualItemShown_ && index.row() == rowCount() - 1) {
|
||||
folder.setTitle("Untitled");
|
||||
} else {
|
||||
folder = folderCollection_.at(index.row());
|
||||
}
|
||||
|
||||
if (role == Qt::DisplayRole) {
|
||||
return QVariant(folder.title());
|
||||
@ -32,6 +39,8 @@ bool FolderModel::setData(const QModelIndex &index, const QVariant &value, int r
|
||||
Folder folder = folderCollection_.at(index.row());
|
||||
|
||||
if (role == Qt::EditRole) {
|
||||
emit dataChanging();
|
||||
|
||||
QStringList fields;
|
||||
fields << "title";
|
||||
VariantVector values;
|
||||
@ -44,6 +53,30 @@ bool FolderModel::setData(const QModelIndex &index, const QVariant &value, int r
|
||||
return false;
|
||||
}
|
||||
|
||||
void FolderModel::showVirtualItem() {
|
||||
virtualItemShown_ = true;
|
||||
beginInsertRows(QModelIndex(), this->rowCount() - 1, this->rowCount() - 1);
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
void FolderModel::hideVirtualItem() {
|
||||
beginRemoveRows(QModelIndex(), this->rowCount() - 1, this->rowCount() - 1);
|
||||
virtualItemShown_ = false;
|
||||
endRemoveRows();
|
||||
}
|
||||
|
||||
QString FolderModel::idAtIndex(int index) const {
|
||||
return data(this->index(index), IdRole).toString();
|
||||
}
|
||||
|
||||
int FolderModel::idToIndex(const QString &id) const {
|
||||
return folderCollection_.idToIndex(id);
|
||||
}
|
||||
|
||||
bool FolderModel::virtualItemShown() const {
|
||||
return virtualItemShown_;
|
||||
}
|
||||
|
||||
bool FolderModel::setData(int index, const QVariant &value, int role) {
|
||||
return setData(this->index(index), value, role);
|
||||
}
|
||||
@ -56,8 +89,26 @@ QHash<int, QByteArray> FolderModel::roleNames() const {
|
||||
return roles;
|
||||
}
|
||||
|
||||
void FolderModel::addData(const QString &title) {
|
||||
emit dataChanging();
|
||||
|
||||
QStringList fields;
|
||||
fields << "title";
|
||||
VariantVector values;
|
||||
values << QVariant(title);
|
||||
folderCollection_.add(fields, values);
|
||||
}
|
||||
|
||||
void FolderModel::deleteData(const int index) {
|
||||
QString id = folderCollection_.indexToId(index);
|
||||
folderCollection_.remove(id);
|
||||
}
|
||||
|
||||
void FolderModel::folderCollection_changed(int from, int to, const QStringList& fields) {
|
||||
beginRemoveRows(QModelIndex(), from, to);
|
||||
QVector<int> roles;
|
||||
roles << Qt::DisplayRole;
|
||||
qDebug() << "update" << from << to;
|
||||
emit dataChanged(this->index(from), this->index(to), roles);
|
||||
endRemoveRows();
|
||||
}
|
||||
|
@ -23,11 +23,8 @@ public:
|
||||
FolderModel(Database& database);
|
||||
|
||||
void addFolder(Folder* folder);
|
||||
|
||||
int rowCount(const QModelIndex & parent = QModelIndex()) const;
|
||||
|
||||
QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;
|
||||
|
||||
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
|
||||
|
||||
protected:
|
||||
@ -38,11 +35,25 @@ private:
|
||||
|
||||
QList<Folder> folders_;
|
||||
FolderCollection folderCollection_;
|
||||
bool virtualItemShown_;
|
||||
QString orderBy_;
|
||||
Database& db_;
|
||||
|
||||
public slots:
|
||||
|
||||
void addData(const QString& title);
|
||||
void deleteData(const int index);
|
||||
bool setData(int index, const QVariant &value, int role = Qt::EditRole);
|
||||
void folderCollection_changed(int from, int to, const QStringList &fields);
|
||||
void showVirtualItem();
|
||||
bool virtualItemShown() const;
|
||||
void hideVirtualItem();
|
||||
QString idAtIndex(int index) const;
|
||||
int idToIndex(const QString& id) const;
|
||||
|
||||
signals:
|
||||
|
||||
void dataChanging();
|
||||
|
||||
};
|
||||
|
||||
|
@ -4,7 +4,6 @@
|
||||
using namespace jop;
|
||||
|
||||
Item::Item() {
|
||||
isPartial_ = true;
|
||||
synced_ = false;
|
||||
}
|
||||
|
||||
@ -24,6 +23,10 @@ int Item::updatedTime() const {
|
||||
return updatedTime_;
|
||||
}
|
||||
|
||||
bool Item::synced() const {
|
||||
return synced_;
|
||||
}
|
||||
|
||||
void Item::setId(const QString& v) {
|
||||
id_ = v;
|
||||
}
|
||||
@ -36,12 +39,8 @@ void Item::setCreatedTime(int v) {
|
||||
createdTime_ = v;
|
||||
}
|
||||
|
||||
void Item::setIsPartial(bool v) {
|
||||
isPartial_ = v;
|
||||
}
|
||||
|
||||
bool Item::isPartial() const {
|
||||
return isPartial_;
|
||||
void Item::setSynced(bool v) {
|
||||
synced_ = v;
|
||||
}
|
||||
|
||||
QStringList Item::dbFields() {
|
||||
|
@ -15,13 +15,13 @@ public:
|
||||
QString title() const;
|
||||
int createdTime() const;
|
||||
int updatedTime() const;
|
||||
bool isPartial() const;
|
||||
bool synced() const;
|
||||
static QStringList dbFields();
|
||||
|
||||
void setId(const QString &v);
|
||||
void setTitle(const QString& v);
|
||||
void setCreatedTime(int v);
|
||||
void setIsPartial(bool v);
|
||||
void setSynced(bool v);
|
||||
|
||||
void fromSqlQuery(const QSqlQuery& query);
|
||||
|
||||
@ -33,8 +33,6 @@ private:
|
||||
time_t updatedTime_;
|
||||
bool synced_;
|
||||
|
||||
bool isPartial_;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -24,8 +24,6 @@ Note NoteCollection::at(int index) const {
|
||||
int from = indexes[0];
|
||||
int to = indexes[indexes.size() - 1];
|
||||
|
||||
qDebug() << "Getting from" << from << "to" << to;
|
||||
|
||||
QSqlQuery q = db_.query("SELECT id, title, body FROM notes WHERE parent_id = :parent_id ORDER BY " + orderBy_ + " LIMIT " + QString::number(to - from + 1) + " OFFSET " + QString::number(from));
|
||||
q.bindValue(":parent_id", parentId_);
|
||||
q.exec();
|
||||
@ -36,7 +34,6 @@ Note NoteCollection::at(int index) const {
|
||||
note.setId(q.value(0).toString());
|
||||
note.setTitle(q.value(1).toString());
|
||||
note.setBody(q.value(2).toString());
|
||||
note.setIsPartial(true);
|
||||
|
||||
cache_.set(noteIndex, note);
|
||||
|
||||
|
@ -64,6 +64,13 @@ CREATE TABLE version (
|
||||
version INT
|
||||
);
|
||||
|
||||
CREATE TABLE changes (
|
||||
id INTEGER PRIMARY KEY,
|
||||
item_id TEXT,
|
||||
item_type INT,
|
||||
item_property TEXT
|
||||
);
|
||||
|
||||
--CREATE TABLE mimetypes (
|
||||
-- id INT,
|
||||
-- mime TEXT
|
||||
|
@ -44,6 +44,8 @@ void Synchronizer::start() {
|
||||
api_.put("folders/" + folder.id(), QUrlQuery(), data, "putFolder:" + folder.id());
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
for (int i = 0; i < notes.size(); i++) {
|
||||
Note note = notes[i];
|
||||
QUrlQuery data;
|
||||
@ -68,10 +70,10 @@ void Synchronizer::api_requestDone(const QJsonObject& response, const QString& t
|
||||
}
|
||||
|
||||
if (action == "putFolder") {
|
||||
// qDebug() << "Done folder" << id;
|
||||
// query = db_.query("UPDATE folders SET synced = 1 WHERE id = ?");
|
||||
// query.addBindValue(id);
|
||||
// query.exec();
|
||||
qDebug() << "Synced folder" << id;
|
||||
query = db_.query("UPDATE folders SET synced = 1 WHERE id = ?");
|
||||
query.addBindValue(id);
|
||||
query.exec();
|
||||
}
|
||||
|
||||
if (action == "putNote") {
|
||||
|
@ -4,19 +4,11 @@
|
||||
namespace jop {
|
||||
namespace uuid {
|
||||
|
||||
//QUuid fromString(const QString& s) {
|
||||
// // {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
|
||||
// QString mod = s;
|
||||
// mod.insert(8, '-');
|
||||
// mod.insert(13, '-');
|
||||
// mod.insert(18, '-');
|
||||
// mod.insert(23, '-');
|
||||
// mod = "{" + mod + "}";
|
||||
|
||||
// //qDebug() << mod;
|
||||
|
||||
// return QUuid(mod);
|
||||
//}
|
||||
QString createUuid(QString s) {
|
||||
if (s == "") s = QString("%1%2").arg(qrand()).arg(QDateTime::currentMSecsSinceEpoch());
|
||||
QString hash = QString(QCryptographicHash::hash(s.toUtf8(), QCryptographicHash::Sha256).toHex());
|
||||
return hash.left(32);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
namespace jop {
|
||||
namespace uuid {
|
||||
|
||||
//QUuid fromString(const QString& s);
|
||||
QString createUuid(QString s = "");
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -40,6 +40,13 @@ void WebApi::processQueue() {
|
||||
QueuedRequest& r = queuedRequests_.takeFirst();
|
||||
|
||||
QString url = baseUrl_ + "/" + r.path;
|
||||
QUrlQuery query = r.query;
|
||||
|
||||
if (sessionId_ != "") {
|
||||
query.addQueryItem("session", sessionId_);
|
||||
}
|
||||
|
||||
url += "?" + query.toString(QUrl::FullyEncoded);
|
||||
|
||||
QNetworkRequest* request = new QNetworkRequest(url);
|
||||
request->setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
|
||||
@ -72,11 +79,12 @@ void WebApi::processQueue() {
|
||||
cmd << "curl";
|
||||
if (r.method == QNetworkAccessManager::PutOperation) {
|
||||
cmd << "-X" << "PUT";
|
||||
cmd << "--data" << "'" + r.data.toString(QUrl::FullyEncoded) + "'";
|
||||
cmd << url;
|
||||
}
|
||||
|
||||
//qDebug().noquote() << cmd.join(" ");
|
||||
cmd << "--data" << "'" + r.data.toString(QUrl::FullyEncoded) + "'";
|
||||
cmd << url;
|
||||
|
||||
qDebug().noquote() << cmd.join(" ");
|
||||
|
||||
inProgressRequests_.push_back(r);
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ abstract class ApiController extends Controller {
|
||||
protected $session = null;
|
||||
protected $user = null;
|
||||
|
||||
private $useTestUserAndSession = true;
|
||||
private $useTestUserAndSession = false;
|
||||
private $testClientNum = 1;
|
||||
|
||||
public function setContainer(\Symfony\Component\DependencyInjection\ContainerInterface $container = null) {
|
||||
@ -47,9 +47,14 @@ abstract class ApiController extends Controller {
|
||||
|
||||
$s = $this->session();
|
||||
|
||||
// TODO: find less hacky way to get request path
|
||||
$requestPath = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '';
|
||||
$requestPath = ltrim($requestPath, '/');
|
||||
$requestPath = rtrim($requestPath, '?');
|
||||
|
||||
// TODO: to keep it simple, only respond to logged in users, but in theory some data
|
||||
// could be public.
|
||||
if (!$s || !$this->user()) throw new UnauthorizedException('A session and user are required');
|
||||
if ($requestPath != 'sessions' && (!$s || !$this->user())) throw new UnauthorizedException('A session and user are required');
|
||||
|
||||
BaseModel::setClientId($s ? $s->client_id : 0);
|
||||
}
|
||||
|
38
web/client.php
Executable file
38
web/client.php
Executable file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
function config($name) {
|
||||
$config = array(
|
||||
'baseUrl' => 'http://joplin.local',
|
||||
);
|
||||
if (isset($config[$name])) {
|
||||
return $config[$name];
|
||||
}
|
||||
throw new Exception('Unknown config: ' . $name);
|
||||
}
|
||||
|
||||
function execRequest($method, $path, $query = null, $data = null) {
|
||||
$url = config('baseUrl') . '/' . $path;
|
||||
if ($query) $url .= '?' . http_build_query($query);
|
||||
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
if ($data) curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
|
||||
$response = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
|
||||
$output = json_decode($response, true);
|
||||
if ($output === null) {
|
||||
return array('error' => 'Cannot decode JSON', 'body' => $response);
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
$session = execRequest('POST', 'session', null, array(
|
||||
'email' => 'laurent@cozic.net',
|
||||
'password' => '12345678',
|
||||
));
|
||||
|
||||
var_dump($session);
|
||||
|
||||
die();
|
Loading…
Reference in New Issue
Block a user