From 312be40fcfc5b88b8c40bd6938e596c0784e5638 Mon Sep 17 00:00:00 2001 From: Scharel Clemens Date: Wed, 15 Apr 2020 08:31:04 +0200 Subject: [PATCH] Just pushing to github to have the code available somewhere else --- harbour-nextcloudnotes.pro | 1 - qml/harbour-nextcloudnotes.qml | 8 +- qml/pages/NotePage.qml | 6 +- qml/pages/NotesPage.qml | 19 ++- qml/pages/SettingsPage.qml | 1 - rpm/harbour-nextcloudnotes.changes | 3 + rpm/harbour-nextcloudnotes.spec | 2 +- rpm/harbour-nextcloudnotes.yaml | 2 +- src/harbour-nextcloudnotes.cpp | 5 +- src/note.h | 1 + src/notesapi.cpp | 28 ++- src/notesapi.h | 16 +- src/notesinterface.h | 42 ----- src/notesmodel.cpp | 225 +++++++++---------------- src/notesmodel.h | 20 ++- src/notesstore.cpp | 31 ++-- src/notesstore.h | 31 ++-- translations/harbour-nextcloudnotes.ts | 124 +++++++------- 18 files changed, 232 insertions(+), 333 deletions(-) delete mode 100644 src/notesinterface.h diff --git a/harbour-nextcloudnotes.pro b/harbour-nextcloudnotes.pro index c35f7a9..9b6c178 100644 --- a/harbour-nextcloudnotes.pro +++ b/harbour-nextcloudnotes.pro @@ -18,7 +18,6 @@ DEFINES += APP_VERSION=\\\"$$VERSION\\\" HEADERS += src/note.h \ src/notesapi.h \ - src/notesinterface.h \ src/notesmodel.h \ src/notesstore.h diff --git a/qml/harbour-nextcloudnotes.qml b/qml/harbour-nextcloudnotes.qml index 8e52599..ee4613c 100644 --- a/qml/harbour-nextcloudnotes.qml +++ b/qml/harbour-nextcloudnotes.qml @@ -54,7 +54,7 @@ ApplicationWindow property bool useCapitalX: value("useCapitalX", false, Boolean) onCurrentAccountChanged: { - notesModel.sourceModel.clear() + notesProxyModel.sourceModel.clear() account.path = "/apps/harbour-nextcloudnotes/accounts/" + currentAccount notesStore.account = currentAccount notesStore.getAllNotes() @@ -64,12 +64,12 @@ ApplicationWindow onSortByChanged: { if (sortBy == "none") - notesModel.invalidate() + notesProxyModel.invalidate() else - notesModel.sortRole = notesModel.roleFromName(sortBy) + notesProxyModel.sortRole = notesProxyModel.roleFromName(sortBy) } onFavoritesOnTopChanged: { - notesModel.favoritesOnTop = favoritesOnTop + notesProxyModel.favoritesOnTop = favoritesOnTop } function addAccount() { diff --git a/qml/pages/NotePage.qml b/qml/pages/NotePage.qml index 9983f65..7f190fa 100644 --- a/qml/pages/NotePage.qml +++ b/qml/pages/NotePage.qml @@ -6,7 +6,7 @@ Dialog { id: noteDialog property int index - property var note: notesModel.getNote(notesModel.index(index, 0)) + property var note: notesProxyModel.getNote(notesProxyModel.index(index, 0)) property var showdown: ShowDown.showdown @@ -47,10 +47,10 @@ Dialog { parseContent() } Connections { - target: notesModel + target: notesProxyModel onDataChanged: { console.log(topLeft, bottomRight, index) - if (notesModel.index(topLeft, bottomRight) === index) { + if (notesProxyModel.index(topLeft, bottomRight) === index) { console.log("This note changed") } else { diff --git a/qml/pages/NotesPage.qml b/qml/pages/NotesPage.qml index e3649bd..c9e06c3 100644 --- a/qml/pages/NotesPage.qml +++ b/qml/pages/NotesPage.qml @@ -7,7 +7,7 @@ Page { property string searchString onStatusChanged: { - if (status === PageStatus.Active) { + if (status === PageStatus.Activating) { if (accounts.value.length <= 0) { addAccountHint.restart() } @@ -15,6 +15,9 @@ Page { autoSyncTimer.restart() } } + else if (status === PageStatus.Deactivating) { + autoSyncTimer.stop() + } } SilicaListView { @@ -59,7 +62,7 @@ Page { EnterKey.onClicked: focus = false onTextChanged: { searchString = text - notesModel.setFilterFixedString(text) + notesProxyModel.setFilterFixedString(text) } } Label { @@ -84,7 +87,7 @@ Page { currentIndex: -1 - model: notesModel + model: notesProxyModel delegate: BackgroundItem { id: note @@ -120,9 +123,9 @@ Page { icon.source: (favorite ? "image://theme/icon-m-favorite-selected?" : "image://theme/icon-m-favorite?") + (note.highlighted ? Theme.secondaryHighlightColor : Theme.secondaryColor) onClicked: { - console.log("Setting favoirte: " + !favorite) - notesStore.updateNote(id, {'favorite': !favorite, 'modified': new Date().valueOf() / 1000 } ) - notesApi.updateNote(id, {'favorite': !favorite, 'modified': new Date().valueOf() / 1000 } ) + var newFavorite = !favorite + notesStore.updateNote(id, {'favorite': newFavorite } ) + notesApi.updateNote(id, {'favorite': newFavorite } ) } } @@ -192,7 +195,7 @@ Page { text: qsTr("Delete") onClicked: { remorse.execute(note, qsTr("Deleting note"), function() { - //notesStore.deleteNote(id) + notesStore.deleteNote(id) notesApi.deleteNote(id) }) } @@ -241,7 +244,7 @@ Page { ViewPlaceholder { id: noSearchPlaceholder - enabled: notesList.count === 0 && searchString !== "" //notesModel.filterRegExp !== "" + enabled: notesList.count === 0 && searchString !== "" //notesProxyModel.filterRegExp !== "" text: qsTr("No result") hintText: qsTr("Try another query") } diff --git a/qml/pages/SettingsPage.qml b/qml/pages/SettingsPage.qml index b4d9078..57b9fd3 100644 --- a/qml/pages/SettingsPage.qml +++ b/qml/pages/SettingsPage.qml @@ -2,7 +2,6 @@ import QtQuick 2.2 import Sailfish.Silica 1.0 import Nemo.Configuration 1.0 import Nemo.Notifications 1.0 -//import harbour.nextcloudnotes.notesmodel 1.0 Page { id: page diff --git a/rpm/harbour-nextcloudnotes.changes b/rpm/harbour-nextcloudnotes.changes index e83e4d7..6a7975e 100644 --- a/rpm/harbour-nextcloudnotes.changes +++ b/rpm/harbour-nextcloudnotes.changes @@ -12,6 +12,9 @@ # * date Author's Name version-release # - Summary of changes +* Mon Apr 13 2020 Scharel Clemens 0.8-0 +- New methods for data handling improved + * Fri Apr 10 2020 Scharel Clemens 0.7-0 - New methods for data handling are now usable diff --git a/rpm/harbour-nextcloudnotes.spec b/rpm/harbour-nextcloudnotes.spec index 876e093..8c047e2 100644 --- a/rpm/harbour-nextcloudnotes.spec +++ b/rpm/harbour-nextcloudnotes.spec @@ -13,7 +13,7 @@ Name: harbour-nextcloudnotes %{!?qtc_make:%define qtc_make make} %{?qtc_builddir:%define _builddir %qtc_builddir} Summary: Nextcloud Notes -Version: 0.7 +Version: 0.8 Release: 0 Group: Applications/Editors License: MIT diff --git a/rpm/harbour-nextcloudnotes.yaml b/rpm/harbour-nextcloudnotes.yaml index dbf96fe..91e02e5 100644 --- a/rpm/harbour-nextcloudnotes.yaml +++ b/rpm/harbour-nextcloudnotes.yaml @@ -1,6 +1,6 @@ Name: harbour-nextcloudnotes Summary: Nextcloud Notes -Version: 0.7 +Version: 0.8 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 diff --git a/src/harbour-nextcloudnotes.cpp b/src/harbour-nextcloudnotes.cpp index 8e1e0cd..e7707ff 100644 --- a/src/harbour-nextcloudnotes.cpp +++ b/src/harbour-nextcloudnotes.cpp @@ -31,7 +31,7 @@ int main(int argc, char *argv[]) NotesApi* notesApi = new NotesApi; QObject::connect(notesApi, SIGNAL(noteUpdated(int, QJsonObject)), notesStore, SLOT(updateNote(int, QJsonObject))); - //QObject::connect(notesStore, SIGNAL(noteUpdated(Note)), notesApi, SLOT(updateNote(Note))); + //QObject::connect(notesStore, SIGNAL(noteUpdated(int, QJsonObject)), notesApi, SLOT(updateNote(int, QJsonObject))); QObject::connect(notesApi, SIGNAL(noteDeleted(int)), notesStore, SLOT(deleteNote(int))); //QObject::connect(notesStore, SIGNAL(noteDeleted(int)), notesApi, SLOT(deleteNote(int))); @@ -46,7 +46,8 @@ int main(int argc, char *argv[]) #else view->rootContext()->setContextProperty("debug", QVariant(false)); #endif - view->rootContext()->setContextProperty("notesModel", notesProxyModel); + view->rootContext()->setContextProperty("notesModel", notesModel); + view->rootContext()->setContextProperty("notesProxyModel", notesProxyModel); view->rootContext()->setContextProperty("notesStore", notesStore); view->rootContext()->setContextProperty("notesApi", notesApi); diff --git a/src/note.h b/src/note.h index a070b8a..bc1d9b1 100644 --- a/src/note.h +++ b/src/note.h @@ -8,6 +8,7 @@ #include #include +// TODO derive from QJsonObject class Note : public QObject { Q_OBJECT diff --git a/src/notesapi.cpp b/src/notesapi.cpp index 9907d20..645a148 100644 --- a/src/notesapi.cpp +++ b/src/notesapi.cpp @@ -3,10 +3,11 @@ #include #include #include +#include #include NotesApi::NotesApi(const QString statusEndpoint, const QString loginEndpoint, const QString ocsEndpoint, const QString notesEndpoint, QObject *parent) - : NotesInterface(parent), m_statusEndpoint(statusEndpoint), m_loginEndpoint(loginEndpoint), m_ocsEndpoint(ocsEndpoint), m_notesEndpoint(notesEndpoint) + : m_statusEndpoint(statusEndpoint), m_loginEndpoint(loginEndpoint), m_ocsEndpoint(ocsEndpoint), m_notesEndpoint(notesEndpoint) { // TODO verify connections (also in destructor) m_loginPollTimer.setInterval(POLL_INTERVALL); @@ -41,15 +42,6 @@ NotesApi::~NotesApi() { disconnect(&m_manager, SIGNAL(sslErrors(QNetworkReply*,QList)), this, SLOT(sslError(QNetworkReply*,QList))); } -void NotesApi::setAccount(const QString &account) { - qDebug() << "Setting account: " << account; - if (account != m_account) { - m_account = account; - // TODO reset the class - emit accountChanged(m_account); - } -} - void NotesApi::getAllNotes(const QStringList& exclude) { qDebug() << "Getting all notes"; QUrl url = apiEndpointUrl(m_notesEndpoint); @@ -113,14 +105,14 @@ void NotesApi::deleteNote(const int id) { } bool NotesApi::busy() const { - return !(m_getAllNotesReplies.empty() || - m_getNoteReplies.empty() || - m_createNoteReplies.empty() || - m_updateNoteReplies.empty() || - m_deleteNoteReplies.empty() || - m_statusReplies.empty() || - m_loginReplies.empty() || - m_pollReplies.empty() || + return !(m_getAllNotesReplies.empty() && + m_getNoteReplies.empty() && + m_createNoteReplies.empty() && + m_updateNoteReplies.empty() && + m_deleteNoteReplies.empty() && + m_statusReplies.empty() && + m_loginReplies.empty() && + m_pollReplies.empty() && m_ocsReplies.empty()); } diff --git a/src/notesapi.h b/src/notesapi.h index 66fb37c..8f0b238 100644 --- a/src/notesapi.h +++ b/src/notesapi.h @@ -2,6 +2,7 @@ #define NOTESAPI_H #include +#include #include #include #include @@ -9,9 +10,6 @@ #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/notes" @@ -19,7 +17,7 @@ #define EXCLUDE_QUERY "exclude=" #define POLL_INTERVALL 5000 -class NotesApi : public NotesInterface +class NotesApi : public QObject { Q_OBJECT @@ -140,9 +138,6 @@ public: Q_ENUM(ErrorCodes) Q_INVOKABLE const QString errorMessage(int error) const; - QString account() const { return m_account; } - void setAccount(const QString& account); - public slots: Q_INVOKABLE void getAllNotes(const QStringList& exclude = QStringList()); //void getAllNotes(Note::NoteField exclude); @@ -183,6 +178,11 @@ signals: void loginStatusChanged(LoginStatus status); void loginUrlChanged(QUrl url); + void noteCreated(const int id, const QJsonObject& note); + void noteUpdated(const int id, const QJsonObject& note); + void noteDeleted(const int id); + void noteError(ErrorCodes error); + public slots: private slots: @@ -194,8 +194,6 @@ private slots: void sslError(QNetworkReply* reply, const QList &errors); private: - QString m_account; - QUrl m_url; QNetworkAccessManager m_manager; QNetworkRequest m_request; diff --git a/src/notesinterface.h b/src/notesinterface.h deleted file mode 100644 index 2cc3283..0000000 --- a/src/notesinterface.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef NOTESINTERFACE_H -#define NOTESINTERFACE_H - -#include -#include - -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 const QString errorMessage(int error) const = 0; - -public slots: - Q_INVOKABLE virtual void getAllNotes(const QStringList& exclude = QStringList()) = 0; - //virtual void getAllNotes(Note::NoteField exclude) = 0; - Q_INVOKABLE virtual void getNote(const int id, const QStringList& exclude = QStringList()) = 0; - //virtual void getNote(const int id, Note::NoteField) = 0; - Q_INVOKABLE virtual void createNote(const QJsonObject& note) = 0; - //virtual void createNote(const Note& note) = 0; - Q_INVOKABLE virtual void updateNote(const int id, const QJsonObject& note) = 0; - //virtual void updateNote(const Note& note) = 0; - Q_INVOKABLE virtual void deleteNote(const int id) = 0; - -signals: - void accountChanged(const QString& account); - void noteError(int error); - void noteUpdated(const int id, const QJsonObject& note); - //void noteUpdated(const Note& note); - void noteDeleted(const int id); - -}; - -#endif // NOTESINTERFACE_H diff --git a/src/notesmodel.cpp b/src/notesmodel.cpp index e328abe..0662f86 100644 --- a/src/notesmodel.cpp +++ b/src/notesmodel.cpp @@ -54,6 +54,19 @@ void NotesProxyModel::sort() { QSortFilterProxyModel::sort(0); } +const QHash NotesModel::m_roleNames = QHash ( { + {NotesModel::IdRole, "id"}, + {NotesModel::ModifiedRole, "modified"}, + {NotesModel::TitleRole, "title"}, + {NotesModel::CategoryRole, "category"}, + {NotesModel::ContentRole, "content"}, + {NotesModel::FavoriteRole, "favorite"}, + {NotesModel::EtagRole, "etag"}, + {NotesModel::ErrorRole, "error"}, + {NotesModel::ErrorMessageRole, "errorMessage"}, + {NotesModel::ModifiedStringRole, "modifiedString"}, + {NotesModel::NoneRole, "none"} } ); + NotesModel::NotesModel(QObject *parent) : QAbstractListModel(parent) { } @@ -62,55 +75,65 @@ NotesModel::~NotesModel() { clear(); } -QList NotesModel::ids() const { - QList ids; - for (int i = 0; i < m_notes.size(); ++i) { - ids.append(m_notes[i].id()); +const QJsonArray NotesModel::getAllNotes(const QStringList &exclude) { + qDebug() << "Getting all Notes"; + QJsonArray array; + QMapIterator i(m_notes); + while (i.hasNext()) { + i.next(); + array << QJsonValue(i.value()); } - return ids; + return array; } -int NotesModel::insertNote(const int id, const QJsonObject& note) { - qDebug() << "Inserting note: " << id; - Note tmpNote(note); - int position = m_notes.indexOf(tmpNote); - if (position >= 0) { - if (m_notes.at(position).equal(tmpNote)) { - qDebug() << "Note already present and unchanged."; +const QJsonObject NotesModel::getNote(const int id, const QStringList &exclude) { + qDebug() << "Getting note: " << id; + return m_notes.value(id); +} + +void NotesModel::createNote(const int id, const QJsonObject ¬e) { + qDebug() << "New note, adding it"; + if (!m_notes.contains(id)) { + beginInsertRows(QModelIndex(), indexOfNoteById(id), indexOfNoteById(id)); + m_notes.insert(id, note); + emit noteUpdated(id, note); + endInsertRows(); + } + else { + qDebug() << "Note already present"; + } +} + +void NotesModel::updateNote(const int id, const QJsonObject& note) { + qDebug() << "Updating note: " << id; + if (m_notes.contains(id)) { + if (m_notes.value(id) == note) { + qDebug() << "Note unchanged"; } else { - qDebug() << "Note already present, updating it."; - m_notes.replace(position, tmpNote); - emit dataChanged(index(position), index(position)); + m_notes.insert(id, note); + emit dataChanged(index(indexOfNoteById(id)), index(indexOfNoteById(id))); + emit noteUpdated(id, note); + qDebug() << "Note changed"; } } else { - qDebug() << "New note, adding it"; - position = m_notes.size(); - beginInsertRows(QModelIndex(), position, position); - m_notes.append(tmpNote); - endInsertRows(); - emit dataChanged(index(position), index(position)); + qDebug() << "Note not found"; } - return position; } -bool NotesModel::removeNote(const QJsonObject ¬e) { - Note tmpNote(note); - qDebug() << "Removing note: " << tmpNote.id(); - int position = m_notes.indexOf(tmpNote); - if (position >= 0 && position < m_notes.size()) { - beginRemoveRows(QModelIndex(), position, position); - m_notes.removeAt(position); +void NotesModel::deleteNote(const int id) { + qDebug() << "Removing note: " << id; + if (m_notes.contains(id)) { + beginRemoveRows(QModelIndex(), indexOfNoteById(id), indexOfNoteById(id)); + if (m_notes.remove(id) == 0) { + qDebug() << "Note not found"; + } + else { + emit noteDeleted(id); + } endRemoveRows(); - emit dataChanged(index(position), index(position)); - return true; } - return false; -} - -bool NotesModel::removeNote(int id) { - return removeNote(QJsonObject{ {"id", id} } ); } void NotesModel::clear() { @@ -120,20 +143,12 @@ void NotesModel::clear() { endResetModel(); } +int NotesModel::indexOfNoteById(int id) const { + return std::distance(m_notes.begin(), m_notes.lowerBound(id)); +} + QHash NotesModel::roleNames() const { - return QHash { - {NotesModel::IdRole, "id"}, - {NotesModel::ModifiedRole, "modified"}, - {NotesModel::TitleRole, "title"}, - {NotesModel::CategoryRole, "category"}, - {NotesModel::ContentRole, "content"}, - {NotesModel::FavoriteRole, "favorite"}, - {NotesModel::EtagRole, "etag"}, - {NotesModel::ErrorRole, "error"}, - {NotesModel::ErrorMessageRole, "errorMessage"}, - {NotesModel::ModifiedStringRole, "modifiedString"}, - {NotesModel::NoneRole, "none"} - }; + return m_roleNames; } Qt::ItemFlags NotesModel::flags(const QModelIndex &index) const { @@ -150,111 +165,29 @@ int NotesModel::rowCount(const QModelIndex &parent) const { } QVariant NotesModel::data(const QModelIndex &index, int role) const { - if (!index.isValid()) return QVariant(); - else if (role == IdRole) return m_notes[index.row()].id(); - else if (role == ModifiedRole) return m_notes[index.row()].modified(); - else if (role == TitleRole) return m_notes[index.row()].title(); - else if (role == CategoryRole) return m_notes[index.row()].category(); - else if (role == ContentRole) return m_notes[index.row()].content(); - else if (role == FavoriteRole) return m_notes[index.row()].favorite(); - else if (role == EtagRole) return m_notes[index.row()].etag(); - else if (role == ErrorRole) return m_notes[index.row()].error(); - else if (role == ErrorMessageRole) return m_notes[index.row()].errorMessage(); - else if (role == ModifiedStringRole) return m_notes[index.row()].modifiedString(); - return QVariant(); + QVariant data; + if (index.isValid() && index.row() <= m_notes.size()) { + QMap::const_iterator i = m_notes.cbegin(); + i += index.row(); + data = i.value()[(m_roleNames[role])]; + } + return data; } bool NotesModel::setData(const QModelIndex &index, const QVariant &value, int role) { - bool retval = false; - if (index.isValid()) { - switch (role) { - case IdRole: { - double id = value.toInt(&retval); - if (retval && id != m_notes[index.row()].id()) { - m_notes[index.row()].setId(id); - emit dataChanged(index, index, QVector{ IdRole }); - } - break; - } - case ModifiedRole: { - double modified = value.toInt(&retval); - if (retval && modified != m_notes[index.row()].modified()) { - m_notes[index.row()].setModified(modified); - emit dataChanged(index, index, QVector{ ModifiedRole }); - } - break; - } - case TitleRole: { - QString title = value.toString(); - if (title != m_notes[index.row()].title()) { - m_notes[index.row()].setTitle(title); - emit dataChanged(index, index, QVector{ TitleRole }); - retval = true; - } - break; - } - case CategoryRole: { - QString category = value.toString(); - if (category != m_notes[index.row()].category()) { - m_notes[index.row()].setCategory(category); - emit dataChanged(index, index, QVector{ CategoryRole }); - retval = true; - } - break; - } - case ContentRole: { - QString content = value.toString(); - if (content != m_notes[index.row()].content()) { - m_notes[index.row()].setContent(content); - emit dataChanged(index, index, QVector{ ContentRole }); - retval = true; - } - break; - } - case FavoriteRole: { - bool favorite = value.toBool(); - if (favorite != m_notes[index.row()].favorite()) { - m_notes[index.row()].setFavorite(favorite); - emit dataChanged(index, index, QVector{ FavoriteRole }); - retval = true; - } - break; - } - case EtagRole: { - QString etag = value.toString(); - if (etag != m_notes[index.row()].etag()) { - m_notes[index.row()].setEtag(etag); - emit dataChanged(index, index, QVector{ EtagRole }); - retval = true; - } - break; - } - case ErrorRole: { - bool error = value.toBool(); - if (error != m_notes[index.row()].error()) { - m_notes[index.row()].setError(error); - emit dataChanged(index, index, QVector{ ErrorRole }); - retval = true; - } - break; - } - case ErrorMessageRole: { - QString errorMessage = value.toString(); - if (errorMessage != m_notes[index.row()].errorMessage()) { - m_notes[index.row()].setErrorMessage(errorMessage); - emit dataChanged(index, index, QVector{ ErrorMessageRole }); - retval = true; - } - break; - } } + if (index.isValid() && index.row() <= m_notes.size()) { + QMap::iterator i = m_notes.begin(); + i += index.row(); + i.value()[m_roleNames[role]] = QJsonValue::fromVariant(value); + emit dataChanged(index, index, QVector( role )); + return true; } - return retval; + return false; } QMap NotesModel::itemData(const QModelIndex &index) const { QMap map; - if (!index.isValid()) return map; - else { + if (index.isValid() && index.row() <= m_notes.size()) { for (int role = IdRole; role < NoneRole; ++role) { map.insert(role, data(index, role)); } diff --git a/src/notesmodel.h b/src/notesmodel.h index fc83c6e..4088f6f 100644 --- a/src/notesmodel.h +++ b/src/notesmodel.h @@ -37,8 +37,6 @@ private: class NotesModel : public QAbstractListModel { Q_OBJECT - Q_PROPERTY(QList ids READ ids NOTIFY idsChanged) - public: explicit NotesModel(QObject *parent = 0); virtual ~NotesModel(); @@ -66,18 +64,24 @@ public: virtual bool setItemData(const QModelIndex &index, const QMap &roles); public slots: - int insertNote(const int id, const QJsonObject& note); - bool removeNote(const QJsonObject& note); - bool removeNote(int id); + Q_INVOKABLE const QJsonArray getAllNotes(const QStringList& exclude = QStringList()); + Q_INVOKABLE const QJsonObject getNote(const int id, const QStringList& exclude = QStringList()); + Q_INVOKABLE void createNote(const int id, const QJsonObject& note); + Q_INVOKABLE void updateNote(const int id, const QJsonObject& note); + Q_INVOKABLE void deleteNote(const int id); + Q_INVOKABLE void clear(); - Q_INVOKABLE QList ids() const; + Q_INVOKABLE int indexOfNoteById(int id) const; signals: void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector &roles = QVector ()); - void idsChanged(QList ids); + void noteCreated(const int id, const QJsonObject& note); + void noteUpdated(const int id, const QJsonObject& note); + void noteDeleted(const int id); private: - QVector m_notes; + QMap m_notes; + const static QHash m_roleNames; }; #endif // NOTESMODEL_H diff --git a/src/notesstore.cpp b/src/notesstore.cpp index 5f8a730..866beff 100644 --- a/src/notesstore.cpp +++ b/src/notesstore.cpp @@ -6,7 +6,7 @@ const QString NotesStore::m_suffix = "json"; -NotesStore::NotesStore(QString directory, QObject *parent) : NotesInterface(parent) +NotesStore::NotesStore(QString directory, QObject *parent) { m_dir.setCurrent(directory); m_dir.setPath(""); @@ -45,7 +45,7 @@ void NotesStore::setAccount(const QString& account) { } } -const QString NotesStore::errorMessage(int error) const { +const QString NotesStore::errorMessage(ErrorCodes error) const { QString message; switch (error) { case NoError: @@ -76,36 +76,39 @@ const QString NotesStore::errorMessage(int error) const { return message; } -void NotesStore::getAllNotes(const QStringList& exclude) { +const QJsonArray NotesStore::getAllNotes(const QStringList& exclude) { qDebug() << "Getting all notes"; + QJsonArray notes; if (m_dir.exists()) { 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, exclude); + notes.append(QJsonValue(getNote(id, exclude))); } } } else { + qDebug() << errorMessage(DirNotFoundError); emit noteError(DirCannotReadError); } + return notes; } -void NotesStore::getNote(const int id, const QStringList& exclude) { +const QJsonObject NotesStore::getNote(const int id, const QStringList& exclude) { qDebug() << "Getting note: " << id; + QJsonObject note; if (id >= 0) { - QJsonObject note = readNoteFile(id, exclude); - if (note.value("id").toInt(-1) >= 0) - emit noteUpdated(id, note); + note = readNoteFile(id, exclude); } else { qDebug() << "Skipping, invalid ID"; } + return note; } -void NotesStore::createNote(const QJsonObject& note) { +bool NotesStore::createNote(const QJsonObject& note) { int id = note.value("id").toInt(-1); qDebug() << "Creating note: " << id; if (id < 0) { @@ -115,14 +118,16 @@ void NotesStore::createNote(const QJsonObject& note) { else if (!noteFileExists(id)) { if (writeNoteFile(id, note)) { emit noteUpdated(id, note); + return true; } } else { qDebug() << "Note already exists"; } + return false; } -void NotesStore::updateNote(const int id, const QJsonObject& note) { +const QJsonObject NotesStore::updateNote(const int id, const QJsonObject& note) { qDebug() << "Updating note: " << id; if (id >= 0) { QJsonObject tmpNote = readNoteFile(id); @@ -133,14 +138,14 @@ void NotesStore::updateNote(const int id, const QJsonObject& note) { tmpNote[fields[i]] = note[fields[i]]; } if (tmpNote.value("modified").toInt() == 0) { - tmpNote["modified"] = QDateTime::currentDateTime().toMSecsSinceEpoch() / 1000; + tmpNote["modified"] = QJsonValue::fromVariant(QDateTime::currentDateTime().toTime_t()); } if (writeNoteFile(id, tmpNote)) { emit noteUpdated(id, tmpNote); } } else { - qDebug() << "Skipping, note is older" << note.value("modified") << tmpNote.value("modified"); + qDebug() << "Skipping, note is older" << QDateTime::fromTime_t(note.value("modified").toInt()) << QDateTime::fromTime_t(tmpNote.value("modified").toInt()); } } else { @@ -152,7 +157,7 @@ void NotesStore::updateNote(const int id, const QJsonObject& note) { } } -void NotesStore::deleteNote(const int id) { +bool NotesStore::deleteNote(const int id) { qDebug() << "Deleting note: " << id; if (removeNoteFile(id)) { emit noteDeleted(id); diff --git a/src/notesstore.h b/src/notesstore.h index 05703aa..14187e1 100644 --- a/src/notesstore.h +++ b/src/notesstore.h @@ -2,12 +2,12 @@ #define NOTESSTORE_H #include -#include +#include +#include #include +#include -#include "notesinterface.h" - -class NotesStore : public NotesInterface +class NotesStore : public QObject { Q_OBJECT @@ -30,18 +30,21 @@ public: DirCannotWriteError }; Q_ENUM(ErrorCodes) - Q_INVOKABLE const QString errorMessage(int error) const; + Q_INVOKABLE const QString errorMessage(ErrorCodes error) const; public slots: - Q_INVOKABLE void getAllNotes(const QStringList& exclude = QStringList()); - //void getAllNotes(Note::NoteField exclude); - Q_INVOKABLE void getNote(const int id, const QStringList& exclude = QStringList()); - //void getNote(const int id, Note::NoteField exclude); - Q_INVOKABLE void createNote(const QJsonObject& note); - //void createNote(const Note& note); - Q_INVOKABLE void updateNote(const int id, const QJsonObject& note); - //void updateNote(const Note& note); - Q_INVOKABLE void deleteNote(const int id); + Q_INVOKABLE const QJsonArray getAllNotes(const QStringList& exclude = QStringList()); + Q_INVOKABLE const QJsonObject getNote(const int id, const QStringList& exclude = QStringList()); + Q_INVOKABLE bool createNote(const QJsonObject& note); + Q_INVOKABLE const QJsonObject updateNote(const int id, const QJsonObject& note); + Q_INVOKABLE bool deleteNote(const int id); + +signals: + void accountChanged(const QString& account); + void noteCreated(const int id, const QJsonObject& note); + void noteUpdated(const int id, const QJsonObject& note); + void noteDeleted(const int id); + void noteError(const ErrorCodes error); private: QDir m_dir; diff --git a/translations/harbour-nextcloudnotes.ts b/translations/harbour-nextcloudnotes.ts index d1fffd4..d7d80d7 100644 --- a/translations/harbour-nextcloudnotes.ts +++ b/translations/harbour-nextcloudnotes.ts @@ -311,32 +311,32 @@ NotesApi - + No error - + No network connection available - + Failed to communicate with the Nextcloud server - + An error occured while establishing an encrypted connection - + Could not authenticate to the Nextcloud instance - + Unknown error @@ -344,97 +344,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 @@ -485,188 +485,188 @@ SettingsPage - + About - + Settings - + Accounts - + No Nextcloud account yet - + Unnamed account + - unknown - + Edit - + Delete - + Deleting account - + Add account - + Synchronization - + Auto-Sync - + Periodically pull notes from the server - + Disabled - + every - + Minutes - + Seconds - + The Answer is 42 - + Congratulation you found the Answer to the Ultimate Question of Life, The Universe, and Everything! - + Appearance - + No sorting - + Favorites on top - + Show notes marked as favorite above the others - + Last edited - + Category - + Title alphabetically - + Sort notes by - + This will also change how the notes are grouped - + Show separator - + Show a separator line between the notes - + lines - + Number of lines in the preview - + Editing - + Monospaced font - + Use a monospeced font to edit a note - + Capital 'X' in checkboxes - + For interoperability with other apps such as Joplin