Implementing new methods for data handling (files and API targets)
This commit is contained in:
parent
ffffd306d6
commit
60e1eb0bdd
16 changed files with 334 additions and 65 deletions
|
@ -18,12 +18,15 @@ DEFINES += APP_VERSION=\\\"$$VERSION\\\"
|
||||||
|
|
||||||
HEADERS += src/note.h \
|
HEADERS += src/note.h \
|
||||||
src/notesapi.h \
|
src/notesapi.h \
|
||||||
src/notesmodel.h
|
src/notesinterface.h \
|
||||||
|
src/notesmodel.h \
|
||||||
|
src/notesstore.h
|
||||||
|
|
||||||
SOURCES += src/harbour-nextcloudnotes.cpp \
|
SOURCES += src/harbour-nextcloudnotes.cpp \
|
||||||
src/note.cpp \
|
src/note.cpp \
|
||||||
src/notesapi.cpp \
|
src/notesapi.cpp \
|
||||||
src/notesmodel.cpp
|
src/notesmodel.cpp \
|
||||||
|
src/notesstore.cpp
|
||||||
|
|
||||||
DISTFILES += qml/harbour-nextcloudnotes.qml \
|
DISTFILES += qml/harbour-nextcloudnotes.qml \
|
||||||
qml/cover/CoverPage.qml \
|
qml/cover/CoverPage.qml \
|
||||||
|
|
|
@ -2,7 +2,10 @@ import QtQuick 2.2
|
||||||
import Sailfish.Silica 1.0
|
import Sailfish.Silica 1.0
|
||||||
import Nemo.Configuration 1.0
|
import Nemo.Configuration 1.0
|
||||||
import Nemo.Notifications 1.0
|
import Nemo.Notifications 1.0
|
||||||
|
import harbour.nextcloudnotes.note 1.0
|
||||||
|
import harbour.nextcloudnotes.notesstore 1.0
|
||||||
import harbour.nextcloudnotes.notesapi 1.0
|
import harbour.nextcloudnotes.notesapi 1.0
|
||||||
|
import harbour.nextcloudnotes.notesmodel 1.0
|
||||||
import "pages"
|
import "pages"
|
||||||
|
|
||||||
ApplicationWindow
|
ApplicationWindow
|
||||||
|
@ -33,7 +36,10 @@ ApplicationWindow
|
||||||
onUsernameChanged: notesApi.username = username
|
onUsernameChanged: notesApi.username = username
|
||||||
onPasswordChanged: notesApi.password = password
|
onPasswordChanged: notesApi.password = password
|
||||||
onDoNotVerifySslChanged: notesApi.sslVerify = !doNotVerifySsl
|
onDoNotVerifySslChanged: notesApi.sslVerify = !doNotVerifySsl
|
||||||
onPathChanged: notesApi.dataFile = appSettings.currentAccount !== "" ? StandardPaths.data + "/" + appSettings.currentAccount + ".json" : ""
|
onPathChanged: {
|
||||||
|
notesStore.account = appSettings.currentAccount
|
||||||
|
notesApi.dataFile = appSettings.currentAccount !== "" ? StandardPaths.data + "/" + appSettings.currentAccount + ".json" : ""
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// General settings of the app
|
// General settings of the app
|
||||||
|
@ -121,6 +127,7 @@ ApplicationWindow
|
||||||
running: interval > 0 && notesApi.networkAccessible && appWindow.visible
|
running: interval > 0 && notesApi.networkAccessible && appWindow.visible
|
||||||
triggeredOnStart: true
|
triggeredOnStart: true
|
||||||
onTriggered: {
|
onTriggered: {
|
||||||
|
notesStore.getAllNotes()
|
||||||
if (!notesApi.busy) {
|
if (!notesApi.busy) {
|
||||||
notesApi.getAllNotes();
|
notesApi.getAllNotes();
|
||||||
}
|
}
|
||||||
|
@ -135,6 +142,26 @@ ApplicationWindow
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NotesStore {
|
||||||
|
id: notesStore
|
||||||
|
|
||||||
|
Component.onCompleted: getAllNotes()
|
||||||
|
onAccountChanged: {
|
||||||
|
console.log(account)
|
||||||
|
if (account !== "")
|
||||||
|
getAllNotes()
|
||||||
|
}
|
||||||
|
onNoteCreated: {
|
||||||
|
//console.log("Note created", createdNote.id)
|
||||||
|
}
|
||||||
|
onNoteUpdated: {
|
||||||
|
//console.log("Note updated", updatedNote.id)
|
||||||
|
}
|
||||||
|
onNoteDeleted: {
|
||||||
|
//console.log("Note deleted", deletedNoteId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
NotesApi {
|
NotesApi {
|
||||||
id: notesApi
|
id: notesApi
|
||||||
|
|
||||||
|
@ -143,7 +170,8 @@ ApplicationWindow
|
||||||
networkAccessible ? offlineNotification.close(Notification.Closed) : offlineNotification.publish()
|
networkAccessible ? offlineNotification.close(Notification.Closed) : offlineNotification.publish()
|
||||||
}
|
}
|
||||||
onError: {
|
onError: {
|
||||||
console.log("Error (" + error + "): " + errorMessage(error))
|
if (error)
|
||||||
|
console.log("Error (" + error + "): " + errorMessage(error))
|
||||||
errorNotification.close()
|
errorNotification.close()
|
||||||
if (error && networkAccessible) {
|
if (error && networkAccessible) {
|
||||||
errorNotification.body = errorMessage(error)
|
errorNotification.body = errorMessage(error)
|
||||||
|
|
|
@ -12,6 +12,9 @@
|
||||||
# * date Author's Name <author's email> version-release
|
# * date Author's Name <author's email> version-release
|
||||||
# - Summary of changes
|
# - Summary of changes
|
||||||
|
|
||||||
|
* Sun Apr 05 2020 Scharel Clemens <harbour-nextcloudnotes@scharel.rocks> 0.6-1
|
||||||
|
- Implementing new methods for data handling (files and API targets)
|
||||||
|
|
||||||
* Sun Mar 29 2020 Scharel Clemens <harbour-nextcloudnotes@scharel.rocks> 0.6-0
|
* Sun Mar 29 2020 Scharel Clemens <harbour-nextcloudnotes@scharel.rocks> 0.6-0
|
||||||
- Improved changes of 0.5
|
- Improved changes of 0.5
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ Name: harbour-nextcloudnotes
|
||||||
%{?qtc_builddir:%define _builddir %qtc_builddir}
|
%{?qtc_builddir:%define _builddir %qtc_builddir}
|
||||||
Summary: Nextcloud Notes
|
Summary: Nextcloud Notes
|
||||||
Version: 0.6
|
Version: 0.6
|
||||||
Release: 0
|
Release: 1
|
||||||
Group: Applications/Editors
|
Group: Applications/Editors
|
||||||
License: MIT
|
License: MIT
|
||||||
URL: https://github.com/scharel/harbour-nextcloudnotes
|
URL: https://github.com/scharel/harbour-nextcloudnotes
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
Name: harbour-nextcloudnotes
|
Name: harbour-nextcloudnotes
|
||||||
Summary: Nextcloud Notes
|
Summary: Nextcloud Notes
|
||||||
Version: 0.6
|
Version: 0.6
|
||||||
Release: 0
|
Release: 1
|
||||||
# The contents of the Group field should be one of the groups listed here:
|
# The contents of the Group field should be one of the groups listed here:
|
||||||
# https://github.com/mer-tools/spectacle/blob/master/data/GROUPS
|
# https://github.com/mer-tools/spectacle/blob/master/data/GROUPS
|
||||||
Group: Applications/Editors
|
Group: Applications/Editors
|
||||||
|
|
|
@ -2,8 +2,9 @@
|
||||||
#include <sailfishapp.h>
|
#include <sailfishapp.h>
|
||||||
#include <QtQml>
|
#include <QtQml>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include "notesapi.h"
|
|
||||||
#include "note.h"
|
#include "note.h"
|
||||||
|
#include "notesapi.h"
|
||||||
|
#include "notesstore.h"
|
||||||
#include "notesmodel.h"
|
#include "notesmodel.h"
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
|
@ -17,13 +18,13 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
qDebug() << app->applicationDisplayName() << app->applicationVersion();
|
qDebug() << app->applicationDisplayName() << app->applicationVersion();
|
||||||
|
|
||||||
|
qRegisterMetaType<Note>();
|
||||||
|
qmlRegisterType<Note>("harbour.nextcloudnotes.note", 1, 0, "Note");
|
||||||
qmlRegisterType<NotesApi>("harbour.nextcloudnotes.notesapi", 1, 0, "NotesApi");
|
qmlRegisterType<NotesApi>("harbour.nextcloudnotes.notesapi", 1, 0, "NotesApi");
|
||||||
|
qmlRegisterType<NotesStore>("harbour.nextcloudnotes.notesstore", 1, 0, "NotesStore");
|
||||||
qmlRegisterType<NotesProxyModel>("harbour.nextcloudnotes.notesmodel", 1, 0, "NotesModel");
|
qmlRegisterType<NotesProxyModel>("harbour.nextcloudnotes.notesmodel", 1, 0, "NotesModel");
|
||||||
|
|
||||||
NotesApi notesApi;
|
|
||||||
QQuickView* view = SailfishApp::createView();
|
QQuickView* view = SailfishApp::createView();
|
||||||
//view->engine()->rootContext()->setContextProperty("notesApi", ¬esApi);
|
|
||||||
//view->engine()->rootContext()->setContextProperty("notesModel", notesApi.model());
|
|
||||||
view->setSource(SailfishApp::pathTo("qml/harbour-nextcloudnotes.qml"));
|
view->setSource(SailfishApp::pathTo("qml/harbour-nextcloudnotes.qml"));
|
||||||
|
|
||||||
#ifdef QT_DEBUG
|
#ifdef QT_DEBUG
|
||||||
|
|
28
src/note.cpp
28
src/note.cpp
|
@ -4,6 +4,10 @@ Note::Note(QObject *parent) : QObject(parent) {
|
||||||
connectSignals();
|
connectSignals();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Note::~Note() {
|
||||||
|
//qDebug() << "Note destroyed: " << id();
|
||||||
|
}
|
||||||
|
|
||||||
Note::Note(const Note& note, QObject *parent) : QObject(parent) {
|
Note::Note(const Note& note, QObject *parent) : QObject(parent) {
|
||||||
setId(note.id());
|
setId(note.id());
|
||||||
setModified(note.modified());
|
setModified(note.modified());
|
||||||
|
@ -111,26 +115,26 @@ QJsonDocument Note::toJsonDocument() const {
|
||||||
return QJsonDocument(m_json);
|
return QJsonDocument(m_json);
|
||||||
}
|
}
|
||||||
|
|
||||||
double Note::id() const {
|
int Note::id() const {
|
||||||
return m_json.value(ID).toDouble(-1);
|
return m_json.value(ID).toInt(-1);
|
||||||
}
|
}
|
||||||
double Note::id(const QJsonObject &jobj) {
|
int Note::id(const QJsonObject &jobj) {
|
||||||
return jobj.value(ID).toDouble(-1);
|
return jobj.value(ID).toInt(-1);
|
||||||
}
|
}
|
||||||
void Note::setId(double id) {
|
void Note::setId(int id) {
|
||||||
if (id != this->id()) {
|
if (id != this->id()) {
|
||||||
m_json.insert(ID, QJsonValue(id));
|
m_json.insert(ID, QJsonValue(id));
|
||||||
emit idChanged(this->id());
|
emit idChanged(this->id());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
double Note::modified() const {
|
int Note::modified() const {
|
||||||
return m_json.value(MODIFIED).toDouble();
|
return m_json.value(MODIFIED).toInt();
|
||||||
}
|
}
|
||||||
double Note::modified(const QJsonObject &jobj) {
|
int Note::modified(const QJsonObject &jobj) {
|
||||||
return jobj.value(MODIFIED).toDouble();
|
return jobj.value(MODIFIED).toInt();
|
||||||
}
|
}
|
||||||
void Note::setModified(double modified) {
|
void Note::setModified(int modified) {
|
||||||
if (modified != this->modified()){
|
if (modified != this->modified()){
|
||||||
m_json.insert(MODIFIED, QJsonValue(modified));
|
m_json.insert(MODIFIED, QJsonValue(modified));
|
||||||
emit modifiedChanged(this->modified());
|
emit modifiedChanged(this->modified());
|
||||||
|
@ -260,8 +264,8 @@ QDateTime Note::modifiedDateTime(const QJsonObject &jobj) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Note::connectSignals() {
|
void Note::connectSignals() {
|
||||||
connect(this, SIGNAL(idChanged(double)), this, SIGNAL(noteChanged()));
|
connect(this, SIGNAL(idChanged(int)), this, SIGNAL(noteChanged()));
|
||||||
connect(this, SIGNAL(modifiedChanged(double)), this, SIGNAL(noteChanged()));
|
connect(this, SIGNAL(modifiedChanged(int)), this, SIGNAL(noteChanged()));
|
||||||
connect(this, SIGNAL(titleChanged(QString)), this, SIGNAL(noteChanged()));
|
connect(this, SIGNAL(titleChanged(QString)), this, SIGNAL(noteChanged()));
|
||||||
connect(this, SIGNAL(categoryChanged(QString)), this, SIGNAL(noteChanged()));
|
connect(this, SIGNAL(categoryChanged(QString)), this, SIGNAL(noteChanged()));
|
||||||
connect(this, SIGNAL(contentChanged(QString)), this, SIGNAL(noteChanged()));
|
connect(this, SIGNAL(contentChanged(QString)), this, SIGNAL(noteChanged()));
|
||||||
|
|
41
src/note.h
41
src/note.h
|
@ -24,6 +24,7 @@ public:
|
||||||
Note(QObject *parent = NULL);
|
Note(QObject *parent = NULL);
|
||||||
Note(const Note& note, QObject *parent = NULL);
|
Note(const Note& note, QObject *parent = NULL);
|
||||||
Note(const QJsonObject& note, QObject *parent = NULL);
|
Note(const QJsonObject& note, QObject *parent = NULL);
|
||||||
|
~Note();
|
||||||
|
|
||||||
Note& operator =(const Note& note);
|
Note& operator =(const Note& note);
|
||||||
Note& operator =(const QJsonObject& note);
|
Note& operator =(const QJsonObject& note);
|
||||||
|
@ -40,49 +41,49 @@ public:
|
||||||
QJsonValue toJsonValue() const;
|
QJsonValue toJsonValue() const;
|
||||||
QJsonDocument toJsonDocument() const;
|
QJsonDocument toJsonDocument() const;
|
||||||
|
|
||||||
Q_PROPERTY(double id READ id WRITE setId NOTIFY idChanged)
|
Q_PROPERTY(int id READ id WRITE setId NOTIFY idChanged)
|
||||||
double id() const;
|
Q_INVOKABLE int id() const;
|
||||||
void setId(double id);
|
void setId(int id);
|
||||||
|
|
||||||
Q_PROPERTY(double modified READ modified WRITE setModified NOTIFY modifiedChanged)
|
Q_PROPERTY(int modified READ modified WRITE setModified NOTIFY modifiedChanged)
|
||||||
double modified() const;
|
Q_INVOKABLE int modified() const;
|
||||||
void setModified(double modified);
|
void setModified(int modified);
|
||||||
|
|
||||||
Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY titleChanged)
|
Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY titleChanged)
|
||||||
QString title() const;
|
Q_INVOKABLE QString title() const;
|
||||||
void setTitle(QString title);
|
void setTitle(QString title);
|
||||||
|
|
||||||
Q_PROPERTY(QString category READ category WRITE setCategory NOTIFY categoryChanged)
|
Q_PROPERTY(QString category READ category WRITE setCategory NOTIFY categoryChanged)
|
||||||
QString category() const;
|
Q_INVOKABLE QString category() const;
|
||||||
void setCategory(QString category);
|
void setCategory(QString category);
|
||||||
|
|
||||||
Q_PROPERTY(QString content READ content WRITE setContent NOTIFY contentChanged)
|
Q_PROPERTY(QString content READ content WRITE setContent NOTIFY contentChanged)
|
||||||
QString content() const;
|
Q_INVOKABLE QString content() const;
|
||||||
void setContent(QString content);
|
void setContent(QString content);
|
||||||
|
|
||||||
Q_PROPERTY(bool favorite READ favorite WRITE setFavorite NOTIFY favoriteChanged)
|
Q_PROPERTY(bool favorite READ favorite WRITE setFavorite NOTIFY favoriteChanged)
|
||||||
bool favorite() const;
|
Q_INVOKABLE bool favorite() const;
|
||||||
void setFavorite(bool favorite);
|
void setFavorite(bool favorite);
|
||||||
|
|
||||||
Q_PROPERTY(QString etag READ etag WRITE setEtag NOTIFY etagChanged)
|
Q_PROPERTY(QString etag READ etag WRITE setEtag NOTIFY etagChanged)
|
||||||
QString etag() const;
|
Q_INVOKABLE QString etag() const;
|
||||||
void setEtag(QString etag);
|
void setEtag(QString etag);
|
||||||
|
|
||||||
Q_PROPERTY(bool error READ error WRITE setError NOTIFY errorChanged)
|
Q_PROPERTY(bool error READ error WRITE setError NOTIFY errorChanged)
|
||||||
bool error() const;
|
Q_INVOKABLE bool error() const;
|
||||||
void setError(bool error);
|
void setError(bool error);
|
||||||
|
|
||||||
Q_PROPERTY(QString errorMessage READ errorMessage WRITE setErrorMessage NOTIFY errorMessageChanged)
|
Q_PROPERTY(QString errorMessage READ errorMessage WRITE setErrorMessage NOTIFY errorMessageChanged)
|
||||||
QString errorMessage() const;
|
Q_INVOKABLE QString errorMessage() const;
|
||||||
void setErrorMessage(QString errorMessage);
|
void setErrorMessage(QString errorMessage);
|
||||||
|
|
||||||
Q_PROPERTY(QString modifiedString READ modifiedString NOTIFY modifiedStringChanged)
|
Q_PROPERTY(QString modifiedString READ modifiedString NOTIFY modifiedStringChanged)
|
||||||
QString modifiedString() const;
|
Q_INVOKABLE QString modifiedString() const;
|
||||||
|
|
||||||
QDateTime modifiedDateTime() const;
|
Q_INVOKABLE QDateTime modifiedDateTime() const;
|
||||||
|
|
||||||
static double id(const QJsonObject& jobj);
|
static int id(const QJsonObject& jobj);
|
||||||
static double modified(const QJsonObject& jobj);
|
static int modified(const QJsonObject& jobj);
|
||||||
static QString title(const QJsonObject& jobj);
|
static QString title(const QJsonObject& jobj);
|
||||||
static QString category(const QJsonObject& jobj);
|
static QString category(const QJsonObject& jobj);
|
||||||
static QString content(const QJsonObject& jobj);
|
static QString content(const QJsonObject& jobj);
|
||||||
|
@ -94,8 +95,8 @@ public:
|
||||||
static QDateTime modifiedDateTime(const QJsonObject& jobj);
|
static QDateTime modifiedDateTime(const QJsonObject& jobj);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void idChanged(double id);
|
void idChanged(int id);
|
||||||
void modifiedChanged(double modified);
|
void modifiedChanged(int modified);
|
||||||
void titleChanged(QString title);
|
void titleChanged(QString title);
|
||||||
void categoryChanged(QString category);
|
void categoryChanged(QString category);
|
||||||
void contentChanged(QString content);
|
void contentChanged(QString content);
|
||||||
|
@ -113,4 +114,6 @@ private:
|
||||||
void connectSignals();
|
void connectSignals();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(Note)
|
||||||
|
|
||||||
#endif // NOTE_H
|
#endif // NOTE_H
|
||||||
|
|
|
@ -261,7 +261,7 @@ void NotesApi::getAllNotes(QStringList excludeFields) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NotesApi::getNote(double noteId, QStringList excludeFields) {
|
void NotesApi::getNote(int noteId, QStringList excludeFields) {
|
||||||
QUrl url = apiEndpointUrl(m_notesEndpoint + QString("/notes/%1").arg(noteId));
|
QUrl url = apiEndpointUrl(m_notesEndpoint + QString("/notes/%1").arg(noteId));
|
||||||
if (!excludeFields.isEmpty())
|
if (!excludeFields.isEmpty())
|
||||||
url.setQuery(QString("exclude=").append(excludeFields.join(",")));
|
url.setQuery(QString("exclude=").append(excludeFields.join(",")));
|
||||||
|
@ -288,7 +288,7 @@ void NotesApi::createNote(QVariantMap fields) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NotesApi::updateNote(double noteId, QVariantMap fields) {
|
void NotesApi::updateNote(int noteId, QVariantMap fields) {
|
||||||
// Update note in the model
|
// Update note in the model
|
||||||
Note note(QJsonObject::fromVariantMap(fields));
|
Note note(QJsonObject::fromVariantMap(fields));
|
||||||
mp_model->insertNote(note);
|
mp_model->insertNote(note);
|
||||||
|
@ -303,7 +303,7 @@ void NotesApi::updateNote(double noteId, QVariantMap fields) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NotesApi::deleteNote(double noteId) {
|
void NotesApi::deleteNote(int noteId) {
|
||||||
// Remove note from the model
|
// Remove note from the model
|
||||||
mp_model->removeNote(noteId);
|
mp_model->removeNote(noteId);
|
||||||
|
|
||||||
|
@ -350,9 +350,6 @@ const QString NotesApi::errorMessage(ErrorCodes error) const {
|
||||||
|
|
||||||
void NotesApi::verifyUrl(QUrl url) {
|
void NotesApi::verifyUrl(QUrl url) {
|
||||||
emit urlValidChanged(url.isValid());
|
emit urlValidChanged(url.isValid());
|
||||||
if (m_url.isValid() && !m_url.scheme().isEmpty() && !m_url.host().isEmpty()) {
|
|
||||||
getNcStatus();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NotesApi::requireAuthentication(QNetworkReply *reply, QAuthenticator *authenticator) {
|
void NotesApi::requireAuthentication(QNetworkReply *reply, QAuthenticator *authenticator) {
|
||||||
|
|
|
@ -53,7 +53,7 @@ public:
|
||||||
const QString loginEndpoint = LOGIN_ENDPOINT,
|
const QString loginEndpoint = LOGIN_ENDPOINT,
|
||||||
const QString ocsEndpoint = OCS_ENDPOINT,
|
const QString ocsEndpoint = OCS_ENDPOINT,
|
||||||
const QString notesEndpoint = NOTES_ENDPOINT,
|
const QString notesEndpoint = NOTES_ENDPOINT,
|
||||||
QObject *parent = NULL);
|
QObject *parent = nullptr);
|
||||||
virtual ~NotesApi();
|
virtual ~NotesApi();
|
||||||
|
|
||||||
bool sslVerify() const { return m_authenticatedRequest.sslConfiguration().peerVerifyMode() == QSslSocket::VerifyPeer; }
|
bool sslVerify() const { return m_authenticatedRequest.sslConfiguration().peerVerifyMode() == QSslSocket::VerifyPeer; }
|
||||||
|
@ -131,10 +131,10 @@ public:
|
||||||
Q_INVOKABLE void abortFlowV2Login();
|
Q_INVOKABLE void abortFlowV2Login();
|
||||||
Q_INVOKABLE void verifyLogin(QString username = QString(), QString password = QString());
|
Q_INVOKABLE void verifyLogin(QString username = QString(), QString password = QString());
|
||||||
Q_INVOKABLE void getAllNotes(QStringList excludeFields = QStringList());
|
Q_INVOKABLE void getAllNotes(QStringList excludeFields = QStringList());
|
||||||
Q_INVOKABLE void getNote(double noteId, QStringList excludeFields = QStringList());
|
Q_INVOKABLE void getNote(int noteId, QStringList excludeFields = QStringList());
|
||||||
Q_INVOKABLE void createNote(QVariantMap fields = QVariantMap());
|
Q_INVOKABLE void createNote(QVariantMap fields = QVariantMap());
|
||||||
Q_INVOKABLE void updateNote(double noteId, QVariantMap fields = QVariantMap());
|
Q_INVOKABLE void updateNote(int noteId, QVariantMap fields = QVariantMap());
|
||||||
Q_INVOKABLE void deleteNote(double noteId);
|
Q_INVOKABLE void deleteNote(int noteId);
|
||||||
Q_INVOKABLE NotesProxyModel* model() const { return mp_modelProxy; }
|
Q_INVOKABLE NotesProxyModel* model() const { return mp_modelProxy; }
|
||||||
|
|
||||||
enum ErrorCodes {
|
enum ErrorCodes {
|
||||||
|
|
43
src/notesinterface.h
Normal file
43
src/notesinterface.h
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
#ifndef NOTESINTERFACE_H
|
||||||
|
#define NOTESINTERFACE_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QVector>
|
||||||
|
|
||||||
|
#include "note.h"
|
||||||
|
|
||||||
|
class NotesInterface : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(QString account READ account WRITE setAccount NOTIFY accountChanged)
|
||||||
|
Q_CLASSINFO("author", "Scharel Clemens")
|
||||||
|
Q_CLASSINFO("url", "https://github.com/scharel/harbour-nextcloudnotes")
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit NotesInterface(QObject *parent = nullptr) : QObject(parent) {
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual QString account() const = 0;
|
||||||
|
virtual void setAccount(const QString& account) = 0;
|
||||||
|
|
||||||
|
Q_INVOKABLE virtual void getAllNotes() = 0;
|
||||||
|
Q_INVOKABLE virtual void getNote(const int id) = 0;
|
||||||
|
Q_INVOKABLE virtual void getNote(const Note& note) = 0;
|
||||||
|
Q_INVOKABLE virtual void createNote(const Note& note) = 0;
|
||||||
|
Q_INVOKABLE virtual void updateNote(const Note& note) = 0;
|
||||||
|
Q_INVOKABLE virtual void deleteNote(const int id) = 0;
|
||||||
|
Q_INVOKABLE virtual void deleteNote(const Note& note) = 0;
|
||||||
|
Q_INVOKABLE virtual Note* noteData(const int id) = 0;
|
||||||
|
Q_INVOKABLE virtual Note* noteData(const Note& note) = 0;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void accountChanged(const QString& account);
|
||||||
|
void noteCreated(Note* createdNote);
|
||||||
|
void noteUpdated(Note* updatedNote);
|
||||||
|
void noteDeleted(int deletedNoteId);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // NOTESINTERFACE_H
|
|
@ -55,7 +55,7 @@ bool NotesModel::fromJsonDocument(const QJsonDocument &jdoc) {
|
||||||
if (!jdoc.isNull() && !jdoc.isEmpty()) {
|
if (!jdoc.isNull() && !jdoc.isEmpty()) {
|
||||||
if (jdoc.isArray()) {
|
if (jdoc.isArray()) {
|
||||||
//qDebug() << "- It's an array...";
|
//qDebug() << "- It's an array...";
|
||||||
QVector<double> notesIdsToRemove;
|
QVector<int> notesIdsToRemove;
|
||||||
QJsonArray jarr = jdoc.array();
|
QJsonArray jarr = jdoc.array();
|
||||||
if (!jarr.empty())
|
if (!jarr.empty())
|
||||||
notesIdsToRemove = ids();
|
notesIdsToRemove = ids();
|
||||||
|
@ -104,8 +104,8 @@ QJsonDocument NotesModel::toJsonDocument() const {
|
||||||
return QJsonDocument(jarr);
|
return QJsonDocument(jarr);
|
||||||
}
|
}
|
||||||
|
|
||||||
QVector<double> NotesModel::ids() const {
|
QVector<int> NotesModel::ids() const {
|
||||||
QVector<double> ids;
|
QVector<int> ids;
|
||||||
for (int i = 0; i < m_notes.size(); ++i) {
|
for (int i = 0; i < m_notes.size(); ++i) {
|
||||||
ids.append(m_notes[i].id());
|
ids.append(m_notes[i].id());
|
||||||
}
|
}
|
||||||
|
@ -149,7 +149,7 @@ bool NotesModel::removeNote(const Note ¬e) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NotesModel::removeNote(double id) {
|
bool NotesModel::removeNote(int id) {
|
||||||
return removeNote(Note(QJsonObject{ {"id", id} } ));
|
return removeNote(Note(QJsonObject{ {"id", id} } ));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,7 +202,7 @@ bool NotesModel::setData(const QModelIndex &index, const QVariant &value, int ro
|
||||||
if (index.isValid()) {
|
if (index.isValid()) {
|
||||||
switch (role) {
|
switch (role) {
|
||||||
case IdRole: {
|
case IdRole: {
|
||||||
double id = value.toDouble(&retval);
|
double id = value.toInt(&retval);
|
||||||
if (retval && id != m_notes[index.row()].id()) {
|
if (retval && id != m_notes[index.row()].id()) {
|
||||||
m_notes[index.row()].setId(id);
|
m_notes[index.row()].setId(id);
|
||||||
emit dataChanged(index, index, QVector<int>{ IdRole });
|
emit dataChanged(index, index, QVector<int>{ IdRole });
|
||||||
|
@ -210,7 +210,7 @@ bool NotesModel::setData(const QModelIndex &index, const QVariant &value, int ro
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ModifiedRole: {
|
case ModifiedRole: {
|
||||||
double modified = value.toDouble(&retval);
|
double modified = value.toInt(&retval);
|
||||||
if (retval && modified != m_notes[index.row()].modified()) {
|
if (retval && modified != m_notes[index.row()].modified()) {
|
||||||
m_notes[index.row()].setModified(modified);
|
m_notes[index.row()].setModified(modified);
|
||||||
emit dataChanged(index, index, QVector<int>{ ModifiedRole });
|
emit dataChanged(index, index, QVector<int>{ ModifiedRole });
|
||||||
|
|
|
@ -43,7 +43,7 @@ public:
|
||||||
|
|
||||||
int insertNote(const Note ¬e);
|
int insertNote(const Note ¬e);
|
||||||
bool removeNote(const Note ¬e);
|
bool removeNote(const Note ¬e);
|
||||||
bool removeNote(double id);
|
bool removeNote(int id);
|
||||||
|
|
||||||
enum NoteRoles {
|
enum NoteRoles {
|
||||||
IdRole = Qt::UserRole,
|
IdRole = Qt::UserRole,
|
||||||
|
@ -69,7 +69,7 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
//void addNote(const QJsonValue ¬e);
|
//void addNote(const QJsonValue ¬e);
|
||||||
QVector<double> ids() const;
|
QVector<int> ids() const;
|
||||||
//int indexOf(const Note ¬e) const;
|
//int indexOf(const Note ¬e) const;
|
||||||
//int indexOf(int id) const;
|
//int indexOf(int id) const;
|
||||||
//bool replaceNote(const Note ¬e);
|
//bool replaceNote(const Note ¬e);
|
||||||
|
|
147
src/notesstore.cpp
Normal file
147
src/notesstore.cpp
Normal file
|
@ -0,0 +1,147 @@
|
||||||
|
#include "notesstore.h"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
NotesStore::NotesStore(QString directory, QObject *parent) : NotesInterface(parent)
|
||||||
|
{
|
||||||
|
m_dir.setCurrent(directory);
|
||||||
|
m_dir.setPath("");
|
||||||
|
m_dir.setFilter(QDir::Files);
|
||||||
|
m_dir.setNameFilters( { "*.json" } );
|
||||||
|
m_note = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
NotesStore::~NotesStore() {
|
||||||
|
if (m_note)
|
||||||
|
m_note->deleteLater();
|
||||||
|
m_note = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString NotesStore::account() const {
|
||||||
|
QString dir;
|
||||||
|
if (m_dir != QDir(QStandardPaths::writableLocation(QStandardPaths::DataLocation))) {
|
||||||
|
dir = m_dir.dirName();
|
||||||
|
}
|
||||||
|
return dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NotesStore::setAccount(const QString& account) {
|
||||||
|
//qDebug() << account << m_dir.path();
|
||||||
|
if (account != m_dir.path()) {
|
||||||
|
if (m_dir != QDir(QStandardPaths::writableLocation(QStandardPaths::DataLocation))) {
|
||||||
|
m_dir.cdUp();
|
||||||
|
}
|
||||||
|
if (!account.isEmpty()) {
|
||||||
|
m_dir.setPath(account);
|
||||||
|
if (!m_dir.mkpath(".")) {
|
||||||
|
qDebug() << "Failed to create or already present: " << m_dir.path();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//qDebug() << account << m_dir.path();
|
||||||
|
emit accountChanged(m_dir.path());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NotesStore::getAllNotes() {
|
||||||
|
QFileInfoList files = m_dir.entryInfoList();
|
||||||
|
for (int i = 0; i < files.size(); ++i) {
|
||||||
|
bool ok;
|
||||||
|
int id = files[i].baseName().toInt(&ok);
|
||||||
|
if (ok) {
|
||||||
|
getNote(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NotesStore::getNote(const int id) {
|
||||||
|
QFileInfo file(m_dir, QString("%1.json").arg(id));
|
||||||
|
if (file.exists()) {
|
||||||
|
emit noteUpdated(noteData(id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NotesStore::getNote(const Note& note) {
|
||||||
|
getNote(note.id());
|
||||||
|
}
|
||||||
|
|
||||||
|
void NotesStore::createNote(const Note& note) {
|
||||||
|
if (note.id() < 0) {
|
||||||
|
// TODO probably crate files with an '.json.<NUMBER>.new' extension
|
||||||
|
qDebug() << "Creating notes without the server API is not supported yet!";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
updateNote(note);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NotesStore::updateNote(const Note& note) {
|
||||||
|
if (note.id() >= 0) {
|
||||||
|
QFileInfo fileinfo(m_dir, QString("%1.json").arg(note.id()));
|
||||||
|
QFile file(fileinfo.filePath());
|
||||||
|
if (file.exists()) {
|
||||||
|
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||||
|
QJsonDocument fileJson = QJsonDocument::fromBinaryData(file.readAll());
|
||||||
|
file.close();
|
||||||
|
if (!note.equal(fileJson.object())) {
|
||||||
|
if (file.open(QIODevice::ReadWrite | QIODevice::Truncate | QIODevice::Text)) {
|
||||||
|
QByteArray data = note.toJsonDocument().toJson();
|
||||||
|
if (file.write(data) == data.size()) {
|
||||||
|
emit noteUpdated(noteData(note));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (file.open(QIODevice::ReadWrite | QIODevice::Text)) {
|
||||||
|
QByteArray data = note.toJsonDocument().toJson();
|
||||||
|
if (file.write(data) == data.size()) {
|
||||||
|
emit noteCreated(noteData(note));
|
||||||
|
}
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
createNote(note);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NotesStore::deleteNote(const int id) {
|
||||||
|
QFileInfo fileinfo(m_dir, QString("%1.json").arg(id));
|
||||||
|
if (fileinfo.exists()) {
|
||||||
|
QFile file(fileinfo.filePath());
|
||||||
|
if (file.remove()) {
|
||||||
|
emit noteDeleted(id);
|
||||||
|
if (m_note)
|
||||||
|
m_note->deleteLater();
|
||||||
|
m_note = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NotesStore::deleteNote(const Note& note) {
|
||||||
|
deleteNote(note.id());
|
||||||
|
}
|
||||||
|
|
||||||
|
Note* NotesStore::noteData(const int id) {
|
||||||
|
if (m_note)
|
||||||
|
m_note->deleteLater();
|
||||||
|
m_note = nullptr;
|
||||||
|
QFileInfo fileinfo(m_dir, QString("%1.json").arg(id));
|
||||||
|
QFile file(fileinfo.filePath());
|
||||||
|
if (file.exists()) {
|
||||||
|
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||||
|
QByteArray data = file.readAll();
|
||||||
|
QJsonDocument json = QJsonDocument::fromJson(data);
|
||||||
|
m_note = new Note(json.object());
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m_note;
|
||||||
|
}
|
||||||
|
|
||||||
|
Note* NotesStore::noteData(const Note& note) {
|
||||||
|
return noteData(note.id());
|
||||||
|
}
|
40
src/notesstore.h
Normal file
40
src/notesstore.h
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
#ifndef NOTESSTORE_H
|
||||||
|
#define NOTESSTORE_H
|
||||||
|
|
||||||
|
#include "notesinterface.h"
|
||||||
|
#include <QObject>
|
||||||
|
#include <QStandardPaths>
|
||||||
|
#include <QDir>
|
||||||
|
|
||||||
|
class NotesStore : public NotesInterface
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit NotesStore(
|
||||||
|
QString directory = QStandardPaths::writableLocation(QStandardPaths::DataLocation),
|
||||||
|
QObject *parent = nullptr);
|
||||||
|
virtual ~NotesStore();
|
||||||
|
|
||||||
|
QString account() const;
|
||||||
|
void setAccount(const QString& account);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
Q_INVOKABLE void getAllNotes();
|
||||||
|
Q_INVOKABLE void getNote(const int id);
|
||||||
|
Q_INVOKABLE void getNote(const Note& note);
|
||||||
|
Q_INVOKABLE void createNote(const Note& note);
|
||||||
|
Q_INVOKABLE void updateNote(const Note& note);
|
||||||
|
Q_INVOKABLE void deleteNote(const int id);
|
||||||
|
Q_INVOKABLE void deleteNote(const Note& note);
|
||||||
|
Q_INVOKABLE Note* noteData(const int id);
|
||||||
|
Q_INVOKABLE Note* noteData(const Note& note);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QDir m_dir;
|
||||||
|
Note* m_note;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // NOTESSTORE_H
|
|
@ -245,12 +245,12 @@
|
||||||
<context>
|
<context>
|
||||||
<name>Note</name>
|
<name>Note</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/note.cpp" line="241"/>
|
<location filename="../src/note.cpp" line="245"/>
|
||||||
<source>Today</source>
|
<source>Today</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/note.cpp" line="243"/>
|
<location filename="../src/note.cpp" line="247"/>
|
||||||
<source>Yesterday</source>
|
<source>Yesterday</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
@ -840,22 +840,22 @@ You can also use other markdown syntax inside them.</source>
|
||||||
<context>
|
<context>
|
||||||
<name>harbour-nextcloudnotes</name>
|
<name>harbour-nextcloudnotes</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../qml/harbour-nextcloudnotes.qml" line="104"/>
|
<location filename="../qml/harbour-nextcloudnotes.qml" line="110"/>
|
||||||
<source>Notes</source>
|
<source>Notes</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../qml/harbour-nextcloudnotes.qml" line="105"/>
|
<location filename="../qml/harbour-nextcloudnotes.qml" line="111"/>
|
||||||
<source>Offline</source>
|
<source>Offline</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../qml/harbour-nextcloudnotes.qml" line="106"/>
|
<location filename="../qml/harbour-nextcloudnotes.qml" line="112"/>
|
||||||
<source>Synced</source>
|
<source>Synced</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../qml/harbour-nextcloudnotes.qml" line="113"/>
|
<location filename="../qml/harbour-nextcloudnotes.qml" line="119"/>
|
||||||
<source>Error</source>
|
<source>Error</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
|
Loading…
Reference in a new issue