From 4ea61c565f7fa68b7fc66b3117ff2a9b74e2e1c5 Mon Sep 17 00:00:00 2001 From: Scharel Clemens Date: Fri, 10 Apr 2020 20:40:23 +0200 Subject: [PATCH] NotesStore and NotesApi Classes based on a common interface class. Seems to work fine :) --- qml/harbour-nextcloudnotes.qml | 53 ++---- qml/pages/LoginPage.qml | 4 +- qml/pages/NotesPage.qml | 3 +- rpm/harbour-nextcloudnotes.changes | 3 + rpm/harbour-nextcloudnotes.spec | 4 +- rpm/harbour-nextcloudnotes.yaml | 4 +- src/harbour-nextcloudnotes.cpp | 47 ++++- src/note.cpp | 139 ++++++++++---- src/note.h | 69 ++++--- src/notesapi.cpp | 239 +++++++++++++------------ src/notesapi.h | 56 +++--- src/notesinterface.h | 50 ++---- src/notesmodel.h | 10 +- src/notesstore.cpp | 79 ++++---- src/notesstore.h | 21 ++- translations/harbour-nextcloudnotes.ts | 56 +++--- 16 files changed, 453 insertions(+), 384 deletions(-) diff --git a/qml/harbour-nextcloudnotes.qml b/qml/harbour-nextcloudnotes.qml index ccb1b11..5000683 100644 --- a/qml/harbour-nextcloudnotes.qml +++ b/qml/harbour-nextcloudnotes.qml @@ -2,10 +2,6 @@ import QtQuick 2.2 import Sailfish.Silica 1.0 import Nemo.Configuration 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.notesmodel 1.0 import "pages" ApplicationWindow @@ -35,10 +31,10 @@ ApplicationWindow onServerChanged: notesApi.server = server onUsernameChanged: notesApi.username = username onPasswordChanged: notesApi.password = password - onDoNotVerifySslChanged: notesApi.sslVerify = !doNotVerifySsl + onDoNotVerifySslChanged: notesApi.verifySsl = !doNotVerifySsl onPathChanged: { notesStore.account = appSettings.currentAccount - notesApi.dataFile = appSettings.currentAccount !== "" ? StandardPaths.data + "/" + appSettings.currentAccount + ".json" : "" + notesApi.account = appSettings.currentAccount } } @@ -142,55 +138,40 @@ 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) - } - }*/ - Connections { target: notesStore onAccountChanged: { - console.log(notesStore.account) + //console.log(notesStore.account) if (notesStore.account !== "") notesStore.getAllNotes() } onNoteUpdated: { - console.log("Note updated", note["id"]) + //console.log("Note updated", note.id) } onNoteDeleted: { - console.log("Note deleted", note["id"]) + //console.log("Note deleted", note.id) } } - NotesApi { - id: notesApi + Connections { + target: notesApi + onAccountChanged: { + //console.log(notesStore.account) + if (notesApi.account !== "") + notesApi.getAllNotes() + } onNetworkAccessibleChanged: { - console.log("Device is " + (networkAccessible ? "online" : "offline")) - networkAccessible ? offlineNotification.close(Notification.Closed) : offlineNotification.publish() + console.log("Device is " + (accessible ? "online" : "offline")) + accessible ? offlineNotification.close(Notification.Closed) : offlineNotification.publish() } onError: { if (error) - console.log("Error (" + error + "): " + errorMessage(error)) + console.log("Error (" + error + "): " + notesApi.errorMessage(error)) errorNotification.close() - if (error && networkAccessible) { - errorNotification.body = errorMessage(error) + if (error && notesApi.networkAccessible) { + errorNotification.body = notesApi.errorMessage(error) errorNotification.publish() } } diff --git a/qml/pages/LoginPage.qml b/qml/pages/LoginPage.qml index 5a97571..6543528 100644 --- a/qml/pages/LoginPage.qml +++ b/qml/pages/LoginPage.qml @@ -34,7 +34,7 @@ Page { notesApi.server = server notesApi.username = username notesApi.password = password - notesApi.sslVerify = !doNotVerifySsl + notesApi.verifySsl = !doNotVerifySsl notesApi.verifyLogin() } } @@ -277,7 +277,7 @@ Page { description: qsTr("Enable this option to allow selfsigned certificates") onCheckedChanged: { account.doNotVerifySsl = checked - notesApi.sslVerify = !account.doNotVerifySsl + notesApi.verifySsl = !account.doNotVerifySsl } } TextSwitch { diff --git a/qml/pages/NotesPage.qml b/qml/pages/NotesPage.qml index 2b4ce4d..63746f7 100644 --- a/qml/pages/NotesPage.qml +++ b/qml/pages/NotesPage.qml @@ -1,11 +1,10 @@ import QtQuick 2.2 import Sailfish.Silica 1.0 -import harbour.nextcloudnotes.notesmodel 1.0 +//import harbour.nextcloudnotes.notesmodel 1.0 Page { id: page - property NotesModel notesModel: notesApi.model() property string searchString Connections { diff --git a/rpm/harbour-nextcloudnotes.changes b/rpm/harbour-nextcloudnotes.changes index 0c56e1c..e83e4d7 100644 --- a/rpm/harbour-nextcloudnotes.changes +++ b/rpm/harbour-nextcloudnotes.changes @@ -12,6 +12,9 @@ # * date Author's Name version-release # - Summary of changes +* Fri Apr 10 2020 Scharel Clemens 0.7-0 +- New methods for data handling are now usable + * Sun Apr 05 2020 Scharel Clemens 0.6-1 - Implementing new methods for data handling (files and API targets) diff --git a/rpm/harbour-nextcloudnotes.spec b/rpm/harbour-nextcloudnotes.spec index 2de9658..876e093 100644 --- a/rpm/harbour-nextcloudnotes.spec +++ b/rpm/harbour-nextcloudnotes.spec @@ -13,8 +13,8 @@ Name: harbour-nextcloudnotes %{!?qtc_make:%define qtc_make make} %{?qtc_builddir:%define _builddir %qtc_builddir} Summary: Nextcloud Notes -Version: 0.6 -Release: 1 +Version: 0.7 +Release: 0 Group: Applications/Editors License: MIT URL: https://github.com/scharel/harbour-nextcloudnotes diff --git a/rpm/harbour-nextcloudnotes.yaml b/rpm/harbour-nextcloudnotes.yaml index a813b00..dbf96fe 100644 --- a/rpm/harbour-nextcloudnotes.yaml +++ b/rpm/harbour-nextcloudnotes.yaml @@ -1,7 +1,7 @@ Name: harbour-nextcloudnotes Summary: Nextcloud Notes -Version: 0.6 -Release: 1 +Version: 0.7 +Release: 0 # The contents of the Group field should be one of the groups listed here: # https://github.com/mer-tools/spectacle/blob/master/data/GROUPS Group: Applications/Editors diff --git a/src/harbour-nextcloudnotes.cpp b/src/harbour-nextcloudnotes.cpp index 29d8521..eef617c 100644 --- a/src/harbour-nextcloudnotes.cpp +++ b/src/harbour-nextcloudnotes.cpp @@ -19,23 +19,54 @@ int main(int argc, char *argv[]) qDebug() << app->applicationDisplayName() << app->applicationVersion(); qRegisterMetaType(); - qmlRegisterType("harbour.nextcloudnotes.note", 1, 0, "Note"); - qmlRegisterType("harbour.nextcloudnotes.notesapi", 1, 0, "NotesApi"); - //qmlRegisterType("harbour.nextcloudnotes.notesstore", 1, 0, "NotesStore"); - qmlRegisterType("harbour.nextcloudnotes.notesmodel", 1, 0, "NotesModel"); + NotesModel* notesModel = new NotesModel; + NotesProxyModel* notesProxyModel = new NotesProxyModel; + notesProxyModel->setSortCaseSensitivity(Qt::CaseInsensitive); + notesProxyModel->setSortLocaleAware(true); + notesProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); + notesProxyModel->setFilterRole(NotesModel::ContentRole); + notesProxyModel->setSourceModel(notesModel); NotesStore* notesStore = new NotesStore; + NotesApi* notesApi = new NotesApi; + + QObject::connect(notesApi, SIGNAL(noteUpdated(Note)), notesStore, SLOT(updateNote(Note))); + //QObject::connect(notesStore, SIGNAL(noteUpdated(Note)), notesApi, SLOT(updateNote(Note))); + QObject::connect(notesApi, SIGNAL(noteDeleted(int)), notesStore, SLOT(deleteNote(int))); + //QObject::connect(notesStore, SIGNAL(noteDeleted(int)), notesApi, SLOT(deleteNote(int))); + + QObject::connect(notesStore, SIGNAL(noteUpdated(Note)), notesModel, SLOT(insertNote(Note))); + QObject::connect(notesStore, SIGNAL(noteDeleted(int)), notesModel, SLOT(removeNote(int))); + QObject::connect(notesApi, SIGNAL(noteUpdated(Note)), notesModel, SLOT(insertNote(Note))); + QObject::connect(notesApi, SIGNAL(noteDeleted(int)), notesModel, SLOT(removeNote(int))); QQuickView* view = SailfishApp::createView(); - view->rootContext()->setContextProperty("notesStore", notesStore); - view->setSource(SailfishApp::pathTo("qml/harbour-nextcloudnotes.qml")); - #ifdef QT_DEBUG view->rootContext()->setContextProperty("debug", QVariant(true)); #else view->rootContext()->setContextProperty("debug", QVariant(false)); #endif + view->rootContext()->setContextProperty("notesModel", notesProxyModel); + view->rootContext()->setContextProperty("notesStore", notesStore); + view->rootContext()->setContextProperty("notesApi", notesApi); + + view->setSource(SailfishApp::pathTo("qml/harbour-nextcloudnotes.qml")); view->show(); - return app->exec(); + int retval = app->exec(); + QObject::disconnect(notesApi, SIGNAL(noteDeleted(int)), notesModel, SLOT(removeNote(int))); + QObject::disconnect(notesApi, SIGNAL(noteUpdated(Note)), notesModel, SLOT(insertNote(Note))); + QObject::disconnect(notesStore, SIGNAL(noteDeleted(int)), notesModel, SLOT(removeNote(int))); + QObject::disconnect(notesStore, SIGNAL(noteUpdated(Note)), notesModel, SLOT(insertNote(Note))); + + //QObject::disconnect(notesStore, SIGNAL(noteDeleted(int)), notesApi, SLOT(deleteNote(int))); + QObject::disconnect(notesApi, SIGNAL(noteDeleted(int)), notesStore, SLOT(deleteNote(int))); + //QObject::disconnect(notesStore, SIGNAL(noteUpdated(Note)), notesApi, SLOT(updateNote(Note))); + QObject::disconnect(notesApi, SIGNAL(noteUpdated(Note)), notesStore, SLOT(updateNote(Note))); + + notesApi->deleteLater(); + notesStore->deleteLater(); + notesProxyModel->deleteLater(); + notesModel->deleteLater(); + return retval; } diff --git a/src/note.cpp b/src/note.cpp index fb7d382..633efc2 100644 --- a/src/note.cpp +++ b/src/note.cpp @@ -1,5 +1,16 @@ #include "note.h" +const QMap Note::m_noteFieldNames = QMap( { + {Note::Id, "id"}, + {Note::Modified, "modified"}, + {Note::Title, "title"}, + {Note::Category, "category"}, + {Note::Content, "content"}, + {Note::Favorite, "favorite"}, + {Note::Etag, "etag"}, + {Note::Error, "error"}, + {Note::ErrorMessage, "errorMessage"} } ); + Note::Note(QObject *parent) : QObject(parent) { connectSignals(); } @@ -103,40 +114,54 @@ bool Note::operator >(const QJsonObject& note) const { return modified() > modified(note); } -QJsonObject Note::toJsonObject() const { +const QJsonObject Note::toJsonObject() const { return m_json; } -QJsonValue Note::toJsonValue() const { +const QJsonValue Note::toJsonValue() const { return QJsonValue(m_json); } -QJsonDocument Note::toJsonDocument() const { +const QJsonDocument Note::toJsonDocument() const { return QJsonDocument(m_json); } int Note::id() const { - return m_json.value(ID).toInt(-1); + return m_json.value(noteFieldName(Id)).toInt(-1); } int Note::id(const QJsonObject &jobj) { - return jobj.value(ID).toInt(-1); + return jobj.value(noteFieldName(Id)).toInt(-1); } void Note::setId(int id) { - if (id != this->id()) { - m_json.insert(ID, QJsonValue(id)); + if (id >= 0) { + if (id != this->id()) { + m_json.insert(noteFieldName(Id), QJsonValue(id)); + emit idChanged(this->id()); + } + } + else { + m_json.remove(noteFieldName(Id)); emit idChanged(this->id()); } } int Note::modified() const { - return m_json.value(MODIFIED).toInt(); + return m_json.value(noteFieldName(Modified)).toInt(); } int Note::modified(const QJsonObject &jobj) { - return jobj.value(MODIFIED).toInt(); + return jobj.value(noteFieldName(Modified)).toInt(); } void Note::setModified(int modified) { - if (modified != this->modified()){ - m_json.insert(MODIFIED, QJsonValue(modified)); + if (modified > 0) { + if (modified != this->modified()) { + m_json.insert(noteFieldName(Modified), QJsonValue(modified)); + emit modifiedChanged(this->modified()); + emit modifiedStringChanged(modifiedString()); + emit modifiedDateTimeChanged(modifiedDateTime()); + } + } + else { + m_json.remove(noteFieldName(Modified)); emit modifiedChanged(this->modified()); emit modifiedStringChanged(modifiedString()); emit modifiedDateTimeChanged(modifiedDateTime()); @@ -144,92 +169,128 @@ void Note::setModified(int modified) { } QString Note::title() const { - return m_json.value(TITLE).toString(); + return m_json.value(noteFieldName(Title)).toString(); } QString Note::title(const QJsonObject &jobj) { - return jobj.value(TITLE).toString(); + return jobj.value(noteFieldName(Title)).toString(); } void Note::setTitle(QString title) { - if (title != this->title()) { - m_json.insert(TITLE, QJsonValue(title)); + if (!title.isNull()) { + if (title != this->title()) { + m_json.insert(noteFieldName(Title), QJsonValue(title)); + emit titleChanged(this->title()); + } + } + else { + m_json.remove(noteFieldName(Title)); emit titleChanged(this->title()); } } QString Note::category() const { - return m_json.value(CATEGORY).toString(); + return m_json.value(noteFieldName(Category)).toString(); } QString Note::category(const QJsonObject &jobj) { - return jobj.value(CATEGORY).toString(); + return jobj.value(noteFieldName(Category)).toString(); } void Note::setCategory(QString category) { - if (category != this->category()) { - m_json.insert(CATEGORY, QJsonValue(category)); + if (!category.isNull()) { + if (category != this->category()) { + m_json.insert(noteFieldName(Category), QJsonValue(category)); + emit categoryChanged(this->category()); + } + } + else { + m_json.remove(noteFieldName(Category)); emit categoryChanged(this->category()); } } QString Note::content() const { - return m_json.value(CONTENT).toString(); + return m_json.value(noteFieldName(Content)).toString(); } QString Note::content(const QJsonObject &jobj) { - return jobj.value(CONTENT).toString(); + return jobj.value(noteFieldName(Content)).toString(); } void Note::setContent(QString content) { - if (content != this->content()) { - m_json.insert(CONTENT, QJsonValue(content)); + if (!content.isNull()) { + if (content != this->content()) { + m_json.insert(noteFieldName(Content), QJsonValue(content)); + emit contentChanged(this->content()); + } + } + else { + m_json.remove(noteFieldName(Content)); emit contentChanged(this->content()); } } bool Note::favorite() const { - return m_json.value(FAVORITE).toBool(); + return m_json.value(noteFieldName(Favorite)).toBool(); } bool Note::favorite(const QJsonObject &jobj) { - return jobj.value(FAVORITE).toBool(); + return jobj.value(noteFieldName(Favorite)).toBool(); } void Note::setFavorite(bool favorite) { if (favorite != this->favorite()) { - m_json.insert(FAVORITE, QJsonValue(favorite)); + m_json.insert(noteFieldName(Favorite), QJsonValue(favorite)); emit favoriteChanged(this->favorite()); } } QString Note::etag() const { - return m_json.value(ETAG).toString(); + return m_json.value(noteFieldName(Etag)).toString(); } QString Note::etag(const QJsonObject &jobj) { - return jobj.value(ETAG).toString(); + return jobj.value(noteFieldName(Etag)).toString(); } void Note::setEtag(QString etag) { - if (etag != this->etag()) { - m_json.insert(ETAG, QJsonValue(etag)); + if (!etag.isNull()) { + if (etag != this->etag()) { + m_json.insert(noteFieldName(Etag), QJsonValue(etag)); + emit etagChanged(this->etag()); + } + } + else { + m_json.remove(noteFieldName(Etag)); emit etagChanged(this->etag()); } } bool Note::error() const { - return m_json.value(ERROR).toBool(true); + return m_json.value(noteFieldName(Error)).toBool(); } bool Note::error(const QJsonObject &jobj) { - return jobj.value(ERROR).toBool(true); + return jobj.value(noteFieldName(Error)).toBool(); } void Note::setError(bool error) { - if (error != this->error()) { - m_json.insert(ERROR, QJsonValue(error)); + if (error) { + if (error != this->error()) { + m_json.insert(noteFieldName(Error), QJsonValue(error)); + emit errorChanged(this->error()); + } + } + else { + m_json.remove(noteFieldName(Error)); emit errorChanged(this->error()); } } QString Note::errorMessage() const { - return m_json.value(ERRORMESSAGE).toString(); + return m_json.value(noteFieldName(ErrorMessage)).toString(); } QString Note::errorMessage(const QJsonObject &jobj) { - return jobj.value(ERRORMESSAGE).toString(); + return jobj.value(noteFieldName(ErrorMessage)).toString(); } void Note::setErrorMessage(QString errorMessage) { - if (errorMessage != this->errorMessage()) { - m_json.insert(ERRORMESSAGE, QJsonValue(errorMessage)); + if (!errorMessage.isNull()) { + if (errorMessage != this->errorMessage()) { + m_json.insert(noteFieldName(ErrorMessage), QJsonValue(errorMessage)); + emit errorMessageChanged(this->errorMessage()); + } + } + else { + m_json.remove(noteFieldName(ErrorMessage)); emit errorMessageChanged(this->errorMessage()); } } @@ -249,7 +310,7 @@ QString Note::modifiedString(const QJsonObject &jobj) { dateString = date.toLocalTime().toString("dddd"); else if (date.toLocalTime().toString("yyyy") == QDateTime::currentDateTime().toString("yyyy")) dateString = date.toLocalTime().toString("MMMM"); - else + else if (!date.isValid()) dateString = date.toLocalTime().toString("MMMM yyyy"); return dateString; } diff --git a/src/note.h b/src/note.h index 4378b15..7402df8 100644 --- a/src/note.h +++ b/src/note.h @@ -1,22 +1,13 @@ -#ifndef NOTE_H + #ifndef NOTE_H #define NOTE_H #include #include #include #include +#include #include -#define ID "id" -#define MODIFIED "modified" -#define TITLE "title" -#define CATEGORY "category" -#define CONTENT "content" -#define FAVORITE "favorite" -#define ETAG "etag" -#define ERROR "error" -#define ERRORMESSAGE "errorMessage" - class Note : public QObject { Q_OBJECT @@ -37,50 +28,77 @@ public: bool operator >(const Note& note) const; bool operator >(const QJsonObject& note) const; - QJsonObject toJsonObject() const; - QJsonValue toJsonValue() const; - QJsonDocument toJsonDocument() const; + bool isValid() const { return id() >= 0; } + + const QJsonObject toJsonObject() const; + const QJsonValue toJsonValue() const; + const QJsonDocument toJsonDocument() const; + + enum NoteField { + None = 0x0000, + Id = 0x0001, + Modified = 0x0002, + Title = 0x0004, + Category = 0x0008, + Content = 0x0010, + Favorite = 0x0020, + Etag = 0x0040, + Error = 0x0080, + ErrorMessage = 0x0100 + }; + Q_DECLARE_FLAGS(NoteFields, NoteField) + Q_FLAG(NoteFields) + Q_INVOKABLE static QList noteFields() { + return m_noteFieldNames.keys(); + } + Q_INVOKABLE static QString noteFieldName(NoteField field) { + return m_noteFieldNames[field]; + } + Q_INVOKABLE static QStringList noteFieldNames() { + return m_noteFieldNames.values(); + } Q_PROPERTY(int id READ id WRITE setId NOTIFY idChanged) - Q_INVOKABLE int id() const; + int id() const; void setId(int id); Q_PROPERTY(int modified READ modified WRITE setModified NOTIFY modifiedChanged) - Q_INVOKABLE int modified() const; + int modified() const; void setModified(int modified); Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY titleChanged) - Q_INVOKABLE QString title() const; + QString title() const; void setTitle(QString title); Q_PROPERTY(QString category READ category WRITE setCategory NOTIFY categoryChanged) - Q_INVOKABLE QString category() const; + QString category() const; void setCategory(QString category); Q_PROPERTY(QString content READ content WRITE setContent NOTIFY contentChanged) - Q_INVOKABLE QString content() const; + QString content() const; void setContent(QString content); Q_PROPERTY(bool favorite READ favorite WRITE setFavorite NOTIFY favoriteChanged) - Q_INVOKABLE bool favorite() const; + bool favorite() const; void setFavorite(bool favorite); Q_PROPERTY(QString etag READ etag WRITE setEtag NOTIFY etagChanged) - Q_INVOKABLE QString etag() const; + QString etag() const; void setEtag(QString etag); Q_PROPERTY(bool error READ error WRITE setError NOTIFY errorChanged) - Q_INVOKABLE bool error() const; + bool error() const; void setError(bool error); Q_PROPERTY(QString errorMessage READ errorMessage WRITE setErrorMessage NOTIFY errorMessageChanged) - Q_INVOKABLE QString errorMessage() const; + QString errorMessage() const; void setErrorMessage(QString errorMessage); Q_PROPERTY(QString modifiedString READ modifiedString NOTIFY modifiedStringChanged) - Q_INVOKABLE QString modifiedString() const; + QString modifiedString() const; - Q_INVOKABLE QDateTime modifiedDateTime() const; + Q_PROPERTY(QDateTime modifiedDateTime READ modifiedDateTime NOTIFY modifiedDateTimeChanged) + QDateTime modifiedDateTime() const; static int id(const QJsonObject& jobj); static int modified(const QJsonObject& jobj); @@ -110,6 +128,7 @@ signals: private: QJsonObject m_json; + const static QMap m_noteFieldNames; void connectSignals(); }; diff --git a/src/notesapi.cpp b/src/notesapi.cpp index 2eb3e3a..4fb766b 100644 --- a/src/notesapi.cpp +++ b/src/notesapi.cpp @@ -6,7 +6,7 @@ #include NotesApi::NotesApi(const QString statusEndpoint, const QString loginEndpoint, const QString ocsEndpoint, const QString notesEndpoint, QObject *parent) - : QObject(parent), m_statusEndpoint(statusEndpoint), m_loginEndpoint(loginEndpoint), m_ocsEndpoint(ocsEndpoint), m_notesEndpoint(notesEndpoint) + : NotesInterface(parent), m_statusEndpoint(statusEndpoint), m_loginEndpoint(loginEndpoint), m_ocsEndpoint(ocsEndpoint), m_notesEndpoint(notesEndpoint) { // TODO verify connections (also in destructor) m_loginPollTimer.setInterval(POLL_INTERVALL); @@ -22,13 +22,6 @@ NotesApi::NotesApi(const QString statusEndpoint, const QString loginEndpoint, co m_status_needsDbUpgrade = false; m_status_extendedSupport = false; m_loginStatus = LoginStatus::LoginUnknown; - mp_model = new NotesModel(this); - mp_modelProxy = new NotesProxyModel(this); - mp_modelProxy->setSourceModel(mp_model); - mp_modelProxy->setSortCaseSensitivity(Qt::CaseInsensitive); - mp_modelProxy->setSortLocaleAware(true); - mp_modelProxy->setFilterCaseSensitivity(Qt::CaseInsensitive); - mp_modelProxy->setFilterRole(NotesModel::ContentRole); connect(this, SIGNAL(urlChanged(QUrl)), this, SLOT(verifyUrl(QUrl))); connect(&m_manager, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)), this, SLOT(requireAuthentication(QNetworkReply*,QAuthenticator*))); connect(&m_manager, SIGNAL(networkAccessibleChanged(QNetworkAccessManager::NetworkAccessibility)), this, SLOT(onNetworkAccessibleChanged(QNetworkAccessManager::NetworkAccessibility))); @@ -40,7 +33,6 @@ NotesApi::NotesApi(const QString statusEndpoint, const QString loginEndpoint, co m_request.setRawHeader("OCS-APIREQUEST", "true"); m_authenticatedRequest = m_request; m_authenticatedRequest.setHeader(QNetworkRequest::ContentTypeHeader, QString("application/json").toUtf8()); - connect(mp_model, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector)), this, SLOT(saveToFile(QModelIndex,QModelIndex,QVector))); } NotesApi::~NotesApi() { @@ -50,22 +42,118 @@ NotesApi::~NotesApi() { disconnect(&m_manager, SIGNAL(networkAccessibleChanged(QNetworkAccessManager::NetworkAccessibility)), this, SLOT(onNetworkAccessibleChanged(QNetworkAccessManager::NetworkAccessibility))); disconnect(&m_manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyFinished(QNetworkReply*))); disconnect(&m_manager, SIGNAL(sslErrors(QNetworkReply*,QList)), this, SLOT(sslError(QNetworkReply*,QList))); - disconnect(mp_model, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector)), this, SLOT(saveToFile(QModelIndex,QModelIndex,QVector))); - m_jsonFile.close(); - if (mp_modelProxy) - delete mp_modelProxy; - if (mp_model) - delete mp_model; } -void NotesApi::setSslVerify(bool verify) { +void NotesApi::setAccount(const QString &account) { + if (account != m_account) { + m_account = account; + // TODO reset the class + emit accountChanged(m_account); + } +} + +void NotesApi::getAllNotes(Note::NoteField exclude) { + QUrl url = apiEndpointUrl(m_notesEndpoint); + QStringList excludeFields; + QList noteFields = Note::noteFields(); + QFlags flags(exclude); + + for (int i = 0; i < noteFields.size(); ++i) { + if (flags.testFlag(noteFields[i])) { + excludeFields << Note::noteFieldName(noteFields[i]); + } + } + if (!excludeFields.isEmpty()) + url.setQuery(QString(EXCLUDE_QUERY).append(excludeFields.join(","))); + + if (url.isValid() && !url.scheme().isEmpty() && !url.host().isEmpty()) { + qDebug() << "GET" << url.toDisplayString(); + m_authenticatedRequest.setUrl(url); + m_notesReplies << m_manager.get(m_authenticatedRequest); + emit busyChanged(true); + } +} + +void NotesApi::getNote(const int id, Note::NoteField exclude) { + QUrl url = apiEndpointUrl(m_notesEndpoint + QString("/%1").arg(id)); + QStringList excludeFields; + QList noteFields = Note::noteFields(); + QFlags flags(exclude); + + for (int i = 0; i < noteFields.size(); ++i) { + if (flags.testFlag(noteFields[i])) { + excludeFields << Note::noteFieldName(noteFields[i]); + } + } + if (!excludeFields.isEmpty()) + url.setQuery(QString(EXCLUDE_QUERY).append(excludeFields.join(","))); + + if (url.isValid() && !url.scheme().isEmpty() && !url.host().isEmpty()) { + qDebug() << "GET" << url.toDisplayString(); + m_authenticatedRequest.setUrl(url); + m_notesReplies << m_manager.get(m_authenticatedRequest); + emit busyChanged(true); + } +} + +void NotesApi::createNote(const Note ¬e) { + QUrl url = apiEndpointUrl(m_notesEndpoint); + if (url.isValid() && !url.scheme().isEmpty() && !url.host().isEmpty()) { + qDebug() << "POST" << url.toDisplayString(); + m_authenticatedRequest.setUrl(url); + m_notesReplies << m_manager.post(m_authenticatedRequest, noteApiData(note)); + emit busyChanged(true); + } +} + +void NotesApi::updateNote(const Note ¬e) { + QUrl url = apiEndpointUrl(m_notesEndpoint + QString("/%1").arg(note.id())); + if (url.isValid() && !url.scheme().isEmpty() && !url.host().isEmpty()) { + qDebug() << "PUT" << url.toDisplayString(); + m_authenticatedRequest.setUrl(url); + m_notesReplies << m_manager.put(m_authenticatedRequest, noteApiData(note)); + emit busyChanged(true); + } +} + +void NotesApi::deleteNote(const int id) { + QUrl url = apiEndpointUrl(m_notesEndpoint + QString("/%1").arg(id)); + if (url.isValid() && !url.scheme().isEmpty() && !url.host().isEmpty()) { + qDebug() << "DELETE" << url.toDisplayString(); + m_authenticatedRequest.setUrl(url); + m_notesReplies << m_manager.deleteResource(m_authenticatedRequest); + emit busyChanged(true); + } +} + +const QByteArray NotesApi::noteApiData(const Note ¬e) { + QJsonObject json = note.toJsonObject(); + json.remove(Note::noteFieldName(Note::Id)); + if (note.modified() == 0) + json.remove(Note::noteFieldName(Note::Modified)); + if (note.title().isNull()) + json.remove(Note::noteFieldName(Note::Title)); + if (note.category().isNull()) + json.remove(Note::noteFieldName(Note::Category)); + if (note.content().isNull()) + json.remove(Note::noteFieldName(Note::Content)); + json.remove(Note::noteFieldName(Note::Etag)); + json.remove(Note::noteFieldName(Note::Error)); + json.remove(Note::noteFieldName(Note::ErrorMessage)); + + return QJsonDocument(json).toJson(QJsonDocument::Compact); +} + +// TODO ab hier überarbeiten + +void NotesApi::setVerifySsl(bool verify) { if (verify != (m_request.sslConfiguration().peerVerifyMode() == QSslSocket::VerifyPeer)) { m_request.sslConfiguration().setPeerVerifyMode(verify ? QSslSocket::VerifyPeer : QSslSocket::VerifyNone); - emit sslVerifyChanged(verify); + emit verifySslChanged(verify); } if (verify != (m_authenticatedRequest.sslConfiguration().peerVerifyMode() == QSslSocket::VerifyPeer)) { m_authenticatedRequest.sslConfiguration().setPeerVerifyMode(verify ? QSslSocket::VerifyPeer : QSslSocket::VerifyNone); - emit sslVerifyChanged(verify); + emit verifySslChanged(verify); } } @@ -164,17 +252,6 @@ void NotesApi::setPath(QString path) { } } -void NotesApi::setDataFile(const QString &dataFile) { - if (dataFile != m_jsonFile.fileName()) { - m_jsonFile.close(); - m_jsonFile.setFileName(dataFile); - QFileInfo fileinfo(m_jsonFile); - QDir filepath; - filepath.mkpath(fileinfo.absolutePath()); - emit dataFileChanged(m_jsonFile.fileName()); - } -} - bool NotesApi::getNcStatus() { QUrl url = apiEndpointUrl(m_statusEndpoint); qDebug() << "POST" << url.toDisplayString(); @@ -249,75 +326,6 @@ void NotesApi::verifyLogin(QString username, QString password) { } } -void NotesApi::getAllNotes(QStringList excludeFields) { - QUrl url = apiEndpointUrl(m_notesEndpoint + "/notes"); - if (!excludeFields.isEmpty()) - url.setQuery(QString("exclude=").append(excludeFields.join(","))); - if (url.isValid() && !url.scheme().isEmpty() && !url.host().isEmpty()) { - qDebug() << "GET" << url.toDisplayString(); - m_authenticatedRequest.setUrl(url); - m_notesReplies << m_manager.get(m_authenticatedRequest); - emit busyChanged(true); - } -} - -void NotesApi::getNote(int noteId, QStringList excludeFields) { - QUrl url = apiEndpointUrl(m_notesEndpoint + QString("/notes/%1").arg(noteId)); - if (!excludeFields.isEmpty()) - url.setQuery(QString("exclude=").append(excludeFields.join(","))); - if (url.isValid() && !url.scheme().isEmpty() && !url.host().isEmpty()) { - qDebug() << "GET" << url.toDisplayString(); - m_authenticatedRequest.setUrl(url); - m_notesReplies << m_manager.get(m_authenticatedRequest); - emit busyChanged(true); - } -} - -void NotesApi::createNote(QVariantMap fields) { - // Update note in the model - Note note(QJsonObject::fromVariantMap(fields)); - //mp_model->insertNote(note); - - // Create note via the API - QUrl url = apiEndpointUrl(m_notesEndpoint + "/notes"); - if (url.isValid() && !url.scheme().isEmpty() && !url.host().isEmpty()) { - qDebug() << "POST" << url.toDisplayString(); - m_authenticatedRequest.setUrl(url); - m_notesReplies << m_manager.post(m_authenticatedRequest, note.toJsonDocument().toJson()); - emit busyChanged(true); - } -} - -void NotesApi::updateNote(int noteId, QVariantMap fields) { - // Update note in the model - Note note(QJsonObject::fromVariantMap(fields)); - mp_model->insertNote(note); - - // Update note on the server - QUrl url = apiEndpointUrl(m_notesEndpoint + QString("/notes/%1").arg(noteId)); - if (url.isValid() && !url.scheme().isEmpty() && !url.host().isEmpty()) { - qDebug() << "PUT" << url.toDisplayString(); - m_authenticatedRequest.setUrl(url); - m_notesReplies << m_manager.put(m_authenticatedRequest, note.toJsonDocument().toJson()); - emit busyChanged(true); - } -} - -void NotesApi::deleteNote(int noteId) { - // Remove note from the model - mp_model->removeNote(noteId); - - // Remove note from the server - QUrl url = apiEndpointUrl(m_notesEndpoint + QString("/notes/%1").arg(noteId)); - if (url.isValid() && !url.scheme().isEmpty() && !url.host().isEmpty()) { - qDebug() << "DELETE" << url.toDisplayString(); - m_authenticatedRequest.setUrl(url); - m_notesReplies << m_manager.deleteResource(m_authenticatedRequest); - emit busyChanged(true); - } - mp_model->removeNote(noteId); -} - const QString NotesApi::errorMessage(ErrorCodes error) const { QString message; switch (error) { @@ -407,12 +415,10 @@ void NotesApi::replyFinished(QNetworkReply *reply) { } else if (m_notesReplies.contains(reply)) { qDebug() << "Notes reply"; - if (mp_model) { - if (mp_model->fromJsonDocument(json)) { - m_lastSync = QDateTime::currentDateTimeUtc(); - emit lastSyncChanged(m_lastSync); - } - } + if (json.isArray()) + updateApiNotes(json.array()); + else if (json.isObject()) + updateApiNote(json.object()); m_notesReplies.removeOne(reply); emit busyChanged(busy()); } @@ -463,18 +469,6 @@ void NotesApi::sslError(QNetworkReply *reply, const QList &errors) { emit error(SslHandshakeError); } -void NotesApi::saveToFile(QModelIndex, QModelIndex, QVector) { - if (m_jsonFile.open(QIODevice::ReadWrite | QIODevice::Truncate | QIODevice::Text)) { - //qDebug() << "Writing data to file" << m_jsonFile.fileName(); - QByteArray data = mp_model->toJsonDocument().toJson(); - if (m_jsonFile.write(data) < data.size()) - emit error(LocalFileWriteError); - m_jsonFile.close(); - } - else - emit error(LocalFileWriteError); -} - QUrl NotesApi::apiEndpointUrl(const QString endpoint) const { QUrl url = server(); url.setPath(url.path() + endpoint); @@ -593,3 +587,16 @@ void NotesApi::setLoginStatus(LoginStatus status, bool *changed) { emit loginStatusChanged(m_loginStatus); } } + +void NotesApi::updateApiNotes(const QJsonArray &json) { + for (int i = 0; i < json.size(); ++i) { + if (json[i].isObject()) + updateApiNote(json[i].toObject()); + } +} + +void NotesApi::updateApiNote(const QJsonObject &json) { + Note note(json); + if (!note.error()) + emit noteUpdated(note); +} diff --git a/src/notesapi.h b/src/notesapi.h index ef48f0e..b51bd10 100644 --- a/src/notesapi.h +++ b/src/notesapi.h @@ -8,31 +8,22 @@ #include #include #include + +#include "notesinterface.h" #include "notesmodel.h" #define STATUS_ENDPOINT "/status.php" #define LOGIN_ENDPOINT "/index.php/login/v2" -#define NOTES_ENDPOINT "/index.php/apps/notes/api/v0.2" +#define NOTES_ENDPOINT "/index.php/apps/notes/api/v0.2/notes" #define OCS_ENDPOINT "/ocs/v1.php/cloud" +#define EXCLUDE_QUERY "exclude=" #define POLL_INTERVALL 5000 -/* -m_noteFieldNames[Id] = "id"; -m_noteFieldNames[Modified] = "modified"; -m_noteFieldNames[Title] = "title"; -m_noteFieldNames[Category] = "category"; -m_noteFieldNames[Content] = "content"; -m_noteFieldNames[Favorite] = "favorite"; -m_noteFieldNames[Etag] = "etag"; -m_noteFieldNames[Error] = "error"; -m_noteFieldNames[ErrorMessage] = "errorMessage"; -*/ - -class NotesApi : public QObject +class NotesApi : public NotesInterface { Q_OBJECT - Q_PROPERTY(bool sslVerify READ sslVerify WRITE setSslVerify NOTIFY sslVerifyChanged) + Q_PROPERTY(bool verifySsl READ verifySsl() WRITE setVerifySsl NOTIFY verifySslChanged) Q_PROPERTY(QUrl url READ url WRITE setUrl NOTIFY urlChanged) Q_PROPERTY(bool urlValid READ urlValid NOTIFY urlValidChanged) Q_PROPERTY(QString server READ server WRITE setServer NOTIFY serverChanged) @@ -42,7 +33,6 @@ class NotesApi : public QObject Q_PROPERTY(QString username READ username WRITE setUsername NOTIFY usernameChanged) Q_PROPERTY(QString password READ password WRITE setPassword NOTIFY passwordChanged) Q_PROPERTY(QString path READ path WRITE setPath NOTIFY pathChanged) - Q_PROPERTY(QString dataFile READ dataFile WRITE setDataFile NOTIFY dataFileChanged) Q_PROPERTY(bool networkAccessible READ networkAccessible NOTIFY networkAccessibleChanged) Q_PROPERTY(QDateTime lastSync READ lastSync NOTIFY lastSyncChanged) Q_PROPERTY(bool busy READ busy NOTIFY busyChanged) @@ -68,8 +58,8 @@ public: QObject *parent = nullptr); virtual ~NotesApi(); - bool sslVerify() const { return m_authenticatedRequest.sslConfiguration().peerVerifyMode() == QSslSocket::VerifyPeer; } - void setSslVerify(bool verify); + bool verifySsl() const { return m_authenticatedRequest.sslConfiguration().peerVerifyMode() == QSslSocket::VerifyPeer; } + void setVerifySsl(bool verify); QUrl url() const { return m_url; } void setUrl(QUrl url); @@ -97,9 +87,6 @@ public: QString path() const { return m_url.path(); } void setPath(QString path); - QString dataFile() const { return m_jsonFile.fileName(); } - void setDataFile(const QString &dataFile); - bool networkAccessible() const { return m_manager.networkAccessible() == QNetworkAccessManager::Accessible; } QDateTime lastSync() const { return m_lastSync; } @@ -142,12 +129,6 @@ public: Q_INVOKABLE bool initiateFlowV2Login(); Q_INVOKABLE void abortFlowV2Login(); Q_INVOKABLE void verifyLogin(QString username = QString(), QString password = QString()); - Q_INVOKABLE void getAllNotes(QStringList excludeFields = QStringList()); - Q_INVOKABLE void getNote(int noteId, QStringList excludeFields = QStringList()); - Q_INVOKABLE void createNote(QVariantMap fields = QVariantMap()); - Q_INVOKABLE void updateNote(int noteId, QVariantMap fields = QVariantMap()); - Q_INVOKABLE void deleteNote(int noteId); - Q_INVOKABLE NotesProxyModel* model() const { return mp_modelProxy; } enum ErrorCodes { NoError, @@ -161,8 +142,18 @@ public: Q_ENUM(ErrorCodes) Q_INVOKABLE const QString errorMessage(ErrorCodes error) const; + QString account() const { return m_account; } + void setAccount(const QString& account); + +public slots: + Q_INVOKABLE void getAllNotes(Note::NoteField exclude = Note::None); + Q_INVOKABLE void getNote(const int id, Note::NoteField exclude = Note::None); + Q_INVOKABLE void createNote(const Note& note); + Q_INVOKABLE void updateNote(const Note& note); + Q_INVOKABLE void deleteNote(const int id); + signals: - void sslVerifyChanged(bool verify); + void verifySslChanged(bool verify); void urlChanged(QUrl url); void urlValidChanged(bool valid); void serverChanged(QString server); @@ -200,17 +191,16 @@ private slots: void replyFinished(QNetworkReply* reply); void pollLoginUrl(); void sslError(QNetworkReply* reply, const QList &errors); - void saveToFile(QModelIndex,QModelIndex,QVector); private: + QString m_account; + static const QByteArray noteApiData(const Note& note); + QUrl m_url; QNetworkAccessManager m_manager; QNetworkRequest m_request; QNetworkRequest m_authenticatedRequest; QNetworkRequest m_ocsRequest; - QFile m_jsonFile; - NotesModel* mp_model; - NotesProxyModel* mp_modelProxy; QUrl apiEndpointUrl(const QString endpoint) const; // Nextcloud status.php @@ -248,6 +238,8 @@ private: // Nextcloud Notes API - https://github.com/nextcloud/notes/wiki/Notes-0.2 const QString m_notesEndpoint; QVector m_notesReplies; + void updateApiNotes(const QJsonArray& json); + void updateApiNote(const QJsonObject& json); QDateTime m_lastSync; }; diff --git a/src/notesinterface.h b/src/notesinterface.h index 5ff8369..994d532 100644 --- a/src/notesinterface.h +++ b/src/notesinterface.h @@ -2,8 +2,8 @@ #define NOTESINTERFACE_H #include -#include -#include + +#include "note.h" class NotesInterface : public QObject { @@ -13,50 +13,22 @@ class NotesInterface : public QObject Q_CLASSINFO("url", "https://github.com/scharel/harbour-nextcloudnotes") public: - explicit NotesInterface(QObject *parent = nullptr) : QObject(parent) { - m_noteFieldNames = QMap( { {Id, "id"}, {Modified, "modified"}, {Title, "title"}, {Category, "category"}, {Content, "content"}, {Favorite, "favorite"}, {Etag, "etag"}, {Error, "error"}, {ErrorMessage, "errorMessage"} } ); - } + explicit NotesInterface(QObject *parent = nullptr) : QObject(parent) { } virtual QString account() const = 0; virtual void setAccount(const QString& account) = 0; - enum NoteField { - None = 0x0000, - Id = 0x0001, - Modified = 0x0002, - Title = 0x0004, - Category = 0x0008, - Content = 0x0010, - Favorite = 0x0020, - Etag = 0x0040, - Error = 0x0080, - ErrorMessage = 0x0100 - }; - Q_DECLARE_FLAGS(NoteFields, NoteField) - Q_FLAG(NoteFields) - Q_INVOKABLE QList noteFields() const { - return m_noteFieldNames.keys(); - } - Q_INVOKABLE QString noteFieldName(NoteField field) { - return m_noteFieldNames[field]; - } - - Q_INVOKABLE virtual void getAllNotes(NoteField exclude = None) = 0; - Q_INVOKABLE virtual void getNote(const int id, NoteField exclude = None) = 0; - Q_INVOKABLE virtual void createNote(const QJsonObject& note) = 0; - Q_INVOKABLE virtual void updateNote(const QJsonObject& note) = 0; +public slots: + Q_INVOKABLE virtual void getAllNotes(Note::NoteField exclude = Note::None) = 0; + Q_INVOKABLE virtual void getNote(const int id, Note::NoteField exclude = Note::None) = 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; signals: - void accountChanged(const QString account); - void noteUpdated(const QJsonObject note); - void noteDeleted(const int deletedNoteId); - -public slots: - -protected: - QMap m_noteFieldNames; - + void accountChanged(const QString& account); + void noteUpdated(const Note& note); + void noteDeleted(const int id); }; #endif // NOTESINTERFACE_H diff --git a/src/notesmodel.h b/src/notesmodel.h index 19aceff..d459089 100644 --- a/src/notesmodel.h +++ b/src/notesmodel.h @@ -41,10 +41,6 @@ public: bool fromJsonDocument(const QJsonDocument &jdoc); QJsonDocument toJsonDocument() const; - int insertNote(const Note ¬e); - bool removeNote(const Note ¬e); - bool removeNote(int id); - enum NoteRoles { IdRole = Qt::UserRole, ModifiedRole = Qt::UserRole + 1, @@ -67,6 +63,12 @@ public: QMap itemData(const QModelIndex &index) const; virtual bool setItemData(const QModelIndex &index, const QMap &roles); +public slots: + int insertNote(const Note ¬e); + bool removeNote(const Note ¬e); + bool removeNote(int id); + + protected: //void addNote(const QJsonValue ¬e); QVector ids() const; diff --git a/src/notesstore.cpp b/src/notesstore.cpp index 83234b4..59f413d 100644 --- a/src/notesstore.cpp +++ b/src/notesstore.cpp @@ -1,15 +1,15 @@ #include "notesstore.h" -#include "note.h" - #include +const QString NotesStore::m_suffix = "json"; + 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_dir.setNameFilters( { "*." + m_suffix } ); } NotesStore::~NotesStore() { @@ -39,7 +39,7 @@ void NotesStore::setAccount(const QString& account) { } } -void NotesStore::getAllNotes(NoteField exclude) { +void NotesStore::getAllNotes(Note::NoteField exclude) { QFileInfoList files = m_dir.entryInfoList(); for (int i = 0; i < files.size(); ++i) { bool ok; @@ -50,30 +50,30 @@ void NotesStore::getAllNotes(NoteField exclude) { } } -void NotesStore::getNote(const int id, NoteField exclude) { +void NotesStore::getNote(const int id, Note::NoteField exclude) { if (id >= 0) { - QJsonObject file = readNoteFile(id, exclude); - if (!file.empty()) - emit noteUpdated(file); + Note note = readNoteFile(id, exclude); + if (note.isValid()) + emit noteUpdated(note); } } -void NotesStore::createNote(const QJsonObject& note) { - if (Note::id(note) < 0) { +void NotesStore::createNote(const Note& note) { + if (!note.isValid()) { // TODO probably crate files with an '.json..new' extension qDebug() << "Creating notes without the server API is not supported yet!"; } - else if (!noteFileExists(Note::id(note))) { + else if (!noteFileExists(note.id())) { if (writeNoteFile(note)) { emit noteUpdated(note); } } } -void NotesStore::updateNote(const QJsonObject& note) { - if (Note::id(note) >= 0) { - QJsonObject file = readNoteFile(Note::id(note)); - if (!Note(file).equal(note)) { +void NotesStore::updateNote(const Note& note) { + if (note.isValid()) { + Note file = readNoteFile(note.id()); + if (!file.equal(note)) { if (writeNoteFile(note)) { emit noteUpdated(note); } @@ -88,25 +88,24 @@ void NotesStore::deleteNote(const int id) { } bool NotesStore::noteFileExists(const int id) const { - QFileInfo fileinfo(m_dir, QString("%1.json").arg(id)); + QFileInfo fileinfo(m_dir, QString("%1.%2").arg(id).arg(m_suffix)); return fileinfo.exists(); } -QJsonObject NotesStore::readNoteFile(const int id, NoteField exclude) const { +Note NotesStore::readNoteFile(const int id, Note::NoteField exclude) const { QJsonObject json; - QFileInfo fileinfo(m_dir, QString("%1.json").arg(id)); + QFileInfo fileinfo(m_dir, QString("%1.%2").arg(id).arg(m_suffix)); QFile file(fileinfo.filePath()); if (file.exists()) { if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { QByteArray data = file.readAll(); json = QJsonDocument::fromJson(data).object(); file.close(); - QFlags flags(exclude); - QMapIterator fields(m_noteFieldNames); - while (fields.hasNext()) { - fields.next(); - if (flags.testFlag(fields.key())) { - json.remove(fields.value()); + QList noteFields = Note::noteFields(); + QFlags flags(exclude); + for (int i = 0; i < noteFields.size(); ++i) { + if (flags.testFlag(noteFields[i])) { + json.remove(Note::noteFieldName(noteFields[i])); } } } @@ -114,28 +113,32 @@ QJsonObject NotesStore::readNoteFile(const int id, NoteField exclude) const { return json; } -bool NotesStore::writeNoteFile(const QJsonObject ¬e) const { +bool NotesStore::writeNoteFile(const Note ¬e) const { bool success = false; - QJsonDocument json(note); - QFileInfo fileinfo(m_dir, QString("%1.json").arg(Note::id(note))); - QFile file(fileinfo.filePath()); - if (file.open(QIODevice::ReadWrite | QIODevice::Truncate | QIODevice::Text)) { - QByteArray data = json.toJson(); - if (file.write(data) == data.size()) { - success = true; + if (!account().isEmpty()) { + QJsonDocument json = note.toJsonDocument(); + QFileInfo fileinfo(m_dir, QString("%1.%2").arg(note.id()).arg(m_suffix)); + QFile file(fileinfo.filePath()); + if (file.open(QIODevice::ReadWrite | QIODevice::Truncate | QIODevice::Text)) { + QByteArray data = json.toJson(); + if (file.write(data) == data.size()) { + success = true; + } + file.close(); } - file.close(); } return success; } bool NotesStore::removeNoteFile(const int id) const { bool success = false; - QFileInfo fileinfo(m_dir, QString("%1.json").arg(id)); - QFile file(fileinfo.filePath()); - if (file.exists()) { - if (file.remove()) { - success = true; + if (!account().isEmpty()) { + QFileInfo fileinfo(m_dir, QString("%1.%2").arg(id).arg(m_suffix)); + QFile file(fileinfo.filePath()); + if (file.exists()) { + if (file.remove()) { + success = true; + } } } return success; diff --git a/src/notesstore.h b/src/notesstore.h index ff1788c..82b4e09 100644 --- a/src/notesstore.h +++ b/src/notesstore.h @@ -1,11 +1,12 @@ #ifndef NOTESSTORE_H #define NOTESSTORE_H -#include "notesinterface.h" #include #include #include +#include "notesinterface.h" + class NotesStore : public NotesInterface { Q_OBJECT @@ -19,22 +20,20 @@ public: QString account() const; void setAccount(const QString& account); - Q_INVOKABLE void getAllNotes(NoteField exclude = None); - Q_INVOKABLE void getNote(const int id, NoteField exclude = None); - Q_INVOKABLE void createNote(const QJsonObject& note); - Q_INVOKABLE void updateNote(const QJsonObject& note); - Q_INVOKABLE void deleteNote(const int id); - -signals: - public slots: + Q_INVOKABLE void getAllNotes(Note::NoteField exclude = Note::None); + Q_INVOKABLE void getNote(const int id, Note::NoteField exclude = Note::None); + Q_INVOKABLE void createNote(const Note& note); + Q_INVOKABLE void updateNote(const Note& note); + Q_INVOKABLE void deleteNote(const int id); private: QDir m_dir; + const static QString m_suffix; bool noteFileExists(const int id) const; - QJsonObject readNoteFile(const int id, NoteField exclude = None) const; - bool writeNoteFile(const QJsonObject& note) const; + Note readNoteFile(const int id, Note::NoteField exclude = Note::None) const; + bool writeNoteFile(const Note& note) const; bool removeNoteFile(const int id) const; }; diff --git a/translations/harbour-nextcloudnotes.ts b/translations/harbour-nextcloudnotes.ts index f8d52df..f6276e3 100644 --- a/translations/harbour-nextcloudnotes.ts +++ b/translations/harbour-nextcloudnotes.ts @@ -245,12 +245,12 @@ Note - + Today - + Yesterday @@ -311,37 +311,37 @@ NotesApi - + No network connection available - + Failed to communicate with the Nextcloud server - + An error happened while reading from the local storage - + An error happened while writing to the local storage - + An error occured while establishing an encrypted connection - + Could not authenticate to the Nextcloud instance - + Unknown error @@ -349,97 +349,97 @@ NotesPage - + Settings - + Add note - + Reload - + Updating... - + Last update - + never - + Nextcloud Notes - + Modified - + Delete - + Deleting note - + Loading notes... - + No account yet - + Got to the settings to add an account - + No notes yet - + Pull down to add a note - + No result - + Try another query - + An error occurred - + Open the settings to configure your Nextcloud accounts