diff --git a/harbour-nextcloudnotes.pro b/harbour-nextcloudnotes.pro index 7edf7e2..1df938e 100644 --- a/harbour-nextcloudnotes.pro +++ b/harbour-nextcloudnotes.pro @@ -17,14 +17,14 @@ CONFIG += sailfishapp DEFINES += APP_VERSION=\\\"$$VERSION\\\" HEADERS += \ + src/note.h \ src/notesapi.h \ - src/notesmodel.h \ - src/note.h + src/notesmodel.h SOURCES += src/harbour-nextcloudnotes.cpp \ + src/note.cpp \ src/notesapi.cpp \ - src/notesmodel.cpp \ - src/note.cpp + src/notesmodel.cpp DISTFILES += qml/harbour-nextcloudnotes.qml \ qml/cover/CoverPage.qml \ diff --git a/qml/harbour-nextcloudnotes.qml b/qml/harbour-nextcloudnotes.qml index 5605b2f..7f744c1 100644 --- a/qml/harbour-nextcloudnotes.qml +++ b/qml/harbour-nextcloudnotes.qml @@ -118,7 +118,7 @@ ApplicationWindow username: account.username password: account.password sslVerify: !account.doNotVerifySsl - dataDir: StandardPaths.data + dataFile: appSettings.currentAccount !== "" ? StandardPaths.data + "/" + appSettings.currentAccount + ".json" : "" Component.onCompleted: getAllNotes() } diff --git a/qml/pages/NotePage.qml b/qml/pages/NotePage.qml index 7b73907..8e58fc7 100644 --- a/qml/pages/NotePage.qml +++ b/qml/pages/NotePage.qml @@ -1,13 +1,10 @@ import QtQuick 2.5 import Sailfish.Silica 1.0 -import harbour.nextcloudnotes.note 1.0 import "../js/showdown/dist/showdown.js" as ShowDown Dialog { id: noteDialog - //property Note note - property int id property int modified property string title diff --git a/qml/pages/NotesPage.qml b/qml/pages/NotesPage.qml index d6a32c1..dde9c5a 100644 --- a/qml/pages/NotesPage.qml +++ b/qml/pages/NotesPage.qml @@ -1,12 +1,12 @@ import QtQuick 2.0 import Sailfish.Silica 1.0 -import harbour.nextcloudnotes.note 1.0 import harbour.nextcloudnotes.notesmodel 1.0 Page { id: page property NotesModel notesModel: notesApi.model() + Connections { target: appSettings onSortByChanged: { @@ -264,7 +264,7 @@ Page { ViewPlaceholder { id: noSearchPlaceholder - enabled: notesList.count === 0 && notesModel.filterRegExp !== "" + enabled: notesList.count === 0 && searchField.text !== "" //notesModel.filterRegExp !== "" text: qsTr("No result") hintText: qsTr("Try another query") } @@ -273,7 +273,7 @@ Page { id: errorPlaceholder enabled: notesList.count === 0 && !busyIndicator.running && !noSearchPlaceholder.enabled && !noNotesPlaceholder.enabled && !noLoginPlaceholder.enabled text: qsTr("An error occurred") - hintText: notesApi.statusText + //hintText: notesApi.statusText } TouchInteractionHint { diff --git a/src/harbour-nextcloudnotes.cpp b/src/harbour-nextcloudnotes.cpp index 9327371..a50f53d 100644 --- a/src/harbour-nextcloudnotes.cpp +++ b/src/harbour-nextcloudnotes.cpp @@ -17,7 +17,6 @@ int main(int argc, char *argv[]) qDebug() << app->applicationDisplayName() << app->applicationVersion(); qmlRegisterType("harbour.nextcloudnotes.notesapi", 1, 0, "NotesApi"); - qmlRegisterType("harbour.nextcloudnotes.note", 1, 0, "Note"); qmlRegisterType("harbour.nextcloudnotes.notesmodel", 1, 0, "NotesModel"); QQuickView* view = SailfishApp::createView(); diff --git a/src/note.cpp b/src/note.cpp index c3d19b1..3e29e74 100644 --- a/src/note.cpp +++ b/src/note.cpp @@ -1,11 +1,8 @@ #include "note.h" Note::Note(QObject *parent) : QObject(parent) { - m_id = -1; - m_modified = 0; - m_error = true; - connect(this, SIGNAL(idChanged(int)), this, SIGNAL(noteChanged())); - connect(this, SIGNAL(modifiedChanged(uint)), this, SIGNAL(noteChanged())); + connect(this, SIGNAL(idChanged(double)), this, SIGNAL(noteChanged())); + connect(this, SIGNAL(modifiedChanged(double)), this, SIGNAL(noteChanged())); connect(this, SIGNAL(titleChanged(QString)), this, SIGNAL(noteChanged())); connect(this, SIGNAL(categoryChanged(QString)), this, SIGNAL(noteChanged())); connect(this, SIGNAL(contentChanged(QString)), this, SIGNAL(noteChanged())); @@ -14,6 +11,7 @@ Note::Note(QObject *parent) : QObject(parent) { connect(this, SIGNAL(errorChanged(bool)), this, SIGNAL(noteChanged())); connect(this, SIGNAL(errorMessageChanged(QString)), this, SIGNAL(noteChanged())); connect(this, SIGNAL(prettyDateChanged(QString)), this, SIGNAL(noteChanged())); + connect(this, SIGNAL(dateTimeChanged(QDateTime)), this, SIGNAL(noteChanged())); } Note::Note(const Note& note, QObject *parent) : QObject(parent) { @@ -28,7 +26,19 @@ Note::Note(const Note& note, QObject *parent) : QObject(parent) { setErrorMessage(note.errorMessage()); } -Note& Note::operator=(const Note& note) { +Note::Note(const QJsonObject ¬e, QObject *parent) { + setId(id(note)); + setModified(modified(note)); + setTitle(title(note)); + setCategory(category(note)); + setContent(content(note)); + setFavorite(favorite(note)); + setEtag(etag(note)); + setError(error(note)); + setErrorMessage(errorMessage(note)); +} + +Note& Note::operator =(const Note& note) { setId(note.id()); setModified(note.modified()); setTitle(note.title()); @@ -40,27 +50,200 @@ Note& Note::operator=(const Note& note) { setErrorMessage(note.errorMessage()); return *this; } - -bool Note::operator==(const Note& note) const { - return m_id == note.id() && - m_modified == note.modified() && - m_title == note.title() && - m_category == note.category() && - m_content == note.content() && - m_favorite == note.favorite() && - m_etag == note.etag() && - m_error == note.error() && - m_errorMessage == note.errorMessage(); +Note& Note::operator =(const QJsonObject& note) { + setId(id(note)); + setModified(modified(note)); + setTitle(title(note)); + setCategory(category(note)); + setContent(content(note)); + setFavorite(favorite(note)); + setEtag(etag(note)); + setError(error(note)); + setErrorMessage(errorMessage(note)); + return *this; } -bool Note::same(const Note ¬e) const { - return m_id == note.id(); +bool Note::operator ==(const Note& note) const { + return id() == note.id(); +} +bool Note::operator ==(const QJsonObject& note) const { + return id() == id(note); } -QString Note::prettyDate() const { - QDateTime date; +bool Note::equal(const Note ¬e) const { + return id() == note.id() && + modified() == note.modified() && + title() == note.title() && + category() == note.category() && + content() == note.content() && + favorite() == note.favorite() && + etag() == note.etag() && + error() == note.error() && + errorMessage() == note.errorMessage(); +} +bool Note::equal(const QJsonObject ¬e) const { + return 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); +} + +bool Note::operator <(const Note& note) const { + return modified() < note.modified(); +} +bool Note::operator <(const QJsonObject& note) const { + return modified() < modified(note); +} + +bool Note::operator >(const Note& note) const { + return modified() > note.modified(); +} +bool Note::operator >(const QJsonObject& note) const { + return modified() > modified(note); +} + +QJsonObject Note::toJsonObject() const { + return m_json; +} + +QJsonValue Note::toJsonValue() const { + return QJsonValue(m_json); +} + +QJsonDocument Note::toJsonDocument() const { + return QJsonDocument(m_json); +} + +double Note::id() const { + return m_json.value(ID).toDouble(-1); +} +double Note::id(const QJsonObject &jobj) { + return jobj.value(ID).toDouble(-1); +} +void Note::setId(double id) { + if (id != this->id()) { + m_json.insert(ID, QJsonValue(id)); + emit idChanged(this->id()); + } +} + +double Note::modified() const { + return m_json.value(MODIFIED).toDouble(); +} +double Note::modified(const QJsonObject &jobj) { + return jobj.value(MODIFIED).toDouble(); +} +void Note::setModified(double modified) { + if (modified != this->modified()){ + m_json.insert(MODIFIED, QJsonValue(modified)); + emit modifiedChanged(this->modified()); + emit modifiedStringChanged(modifiedString()); + emit modifiedDateTimeChanged(modifiedDateTime()); + } +} + +QString Note::title() const { + return m_json.value(TITLE).toString(); +} +QString Note::title(const QJsonObject &jobj) { + return jobj.value(TITLE).toString(); +} +void Note::setTitle(QString title) { + if (title != this->title()) { + m_json.insert(TITLE, QJsonValue(title)); + emit titleChanged(this->title()); + } +} + +QString Note::category() const { + return m_json.value(CATEGORY).toString(); +} +QString Note::category(const QJsonObject &jobj) { + return jobj.value(CATEGORY).toString(); +} +void Note::setCategory(QString category) { + if (category != this->category()) { + m_json.insert(CATEGORY, QJsonValue(category)); + emit categoryChanged(this->category()); + } +} + +QString Note::content() const { + return m_json.value(CONTENT).toString(); +} +QString Note::content(const QJsonObject &jobj) { + return jobj.value(CONTENT).toString(); +} +void Note::setContent(QString content) { + if (content != this->content()) { + m_json.insert(CONTENT, QJsonValue(content)); + emit contentChanged(this->content()); + } +} + +bool Note::favorite() const { + return m_json.value(FAVORITE).toBool(); +} +bool Note::favorite(const QJsonObject &jobj) { + return jobj.value(FAVORITE).toBool(); +} +void Note::setFavorite(bool favorite) { + if (favorite != this->favorite()) { + m_json.insert(FAVORITE, QJsonValue(favorite)); + emit favoriteChanged(this->favorite()); + } +} + +QString Note::etag() const { + return m_json.value(ETAG).toString(); +} +QString Note::etag(const QJsonObject &jobj) { + return jobj.value(ETAG).toString(); +} +void Note::setEtag(QString etag) { + if (etag != this->etag()) { + m_json.insert(ETAG, QJsonValue(etag)); + emit etagChanged(this->etag()); + } +} + +bool Note::error() const { + return m_json.value(ERROR).toBool(true); +} +bool Note::error(const QJsonObject &jobj) { + return jobj.value(ERROR).toBool(true); +} +void Note::setError(bool error) { + if (error != this->error()) { + m_json.insert(ERROR, QJsonValue(error)); + emit errorChanged(this->error()); + } +} + +QString Note::errorMessage() const { + return m_json.value(ERRORMESSAGE).toString(); +} +QString Note::errorMessage(const QJsonObject &jobj) { + return jobj.value(ERRORMESSAGE).toString(); +} +void Note::setErrorMessage(QString errorMessage) { + if (errorMessage != this->errorMessage()) { + m_json.insert(ERRORMESSAGE, QJsonValue(errorMessage)); + emit errorMessageChanged(this->errorMessage()); + } +} + +QString Note::modifiedString() const { + return modifiedString(m_json); +} +QString Note::modifiedString(const QJsonObject &jobj) { + QDateTime date = modifiedDateTime(jobj); QString dateString; - date.setTime_t(m_modified); qint64 diff = date.daysTo(QDateTime::currentDateTime()); if (diff == 0) dateString = tr("Today"); @@ -75,16 +258,11 @@ QString Note::prettyDate() const { return dateString; } -Note Note::fromjson(const QJsonObject& jobj) { - Note note = new Note; - note.setId(jobj.value("id").toInt()); - note.setModified(jobj.value("modified").toInt()); - note.setTitle(jobj.value("title").toString()); - note.setCategory(jobj.value("category").toString()); - note.setContent(jobj.value("content").toString()); - note.setFavorite(jobj.value("favorite").toBool()); - note.setEtag(jobj.value("etag").toString()); - note.setError(jobj.value("error").toBool(true)); - note.setErrorMessage(jobj.value("errorMessage").toString()); - return note; +QDateTime Note::modifiedDateTime() const { + return modifiedDateTime(m_json); +} +QDateTime Note::modifiedDateTime(const QJsonObject &jobj) { + QDateTime date; + date.setTime_t(modified(jobj)); + return date; } diff --git a/src/note.h b/src/note.h index f3cadc4..4e3d053 100644 --- a/src/note.h +++ b/src/note.h @@ -3,64 +3,99 @@ #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 public: Note(QObject *parent = NULL); Note(const Note& note, QObject *parent = NULL); + Note(const QJsonObject& note, QObject *parent = NULL); - Note& operator=(const Note& note); - bool operator==(const Note& note) const; - bool same(const Note& note) const; + Note& operator =(const Note& note); + Note& operator =(const QJsonObject& note); + bool operator ==(const Note& note) const; + bool operator ==(const QJsonObject& note) const; + bool equal(const Note& note) const; + bool equal(const QJsonObject& note) const; + bool operator <(const Note& note) const; + bool operator <(const QJsonObject& note) const; + bool operator >(const Note& note) const; + bool operator >(const QJsonObject& note) const; - Q_PROPERTY(int id READ id WRITE setId NOTIFY idChanged) - int id() const { return m_id; } - void setId(int id) { if (id != m_id) { m_id = id; emit idChanged(id); } } + QJsonObject toJsonObject() const; + QJsonValue toJsonValue() const; + QJsonDocument toJsonDocument() const; - Q_PROPERTY(uint modified READ modified WRITE setModified NOTIFY modifiedChanged) - uint modified() const { return m_modified; } - void setModified(uint modified) { if (modified != m_modified) { m_modified = modified; emit modifiedChanged(modified); emit prettyDateChanged(prettyDate()); } } + Q_PROPERTY(double id READ id WRITE setId NOTIFY idChanged) + double id() const; + void setId(double id); + + Q_PROPERTY(double modified READ modified WRITE setModified NOTIFY modifiedChanged) + double modified() const; + void setModified(double modified); Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY titleChanged) - QString title() const { return m_title; } - void setTitle(QString title) { if (title != m_title) { m_title = title; emit titleChanged(title); } } + QString title() const; + void setTitle(QString title); Q_PROPERTY(QString category READ category WRITE setCategory NOTIFY categoryChanged) - QString category() const { return m_category; } - void setCategory(QString category) { if (category != m_category) { m_category = category; emit categoryChanged(category); } } + QString category() const; + void setCategory(QString category); Q_PROPERTY(QString content READ content WRITE setContent NOTIFY contentChanged) - QString content() const { return m_content; } - void setContent(QString content) { if (content != m_content) { m_content = content; emit contentChanged(content); } } + QString content() const; + void setContent(QString content); Q_PROPERTY(bool favorite READ favorite WRITE setFavorite NOTIFY favoriteChanged) - bool favorite() const { return m_favorite; } - void setFavorite(bool favorite) { if (favorite != m_favorite) { m_favorite = favorite; emit favoriteChanged(favorite); } } + bool favorite() const; + void setFavorite(bool favorite); Q_PROPERTY(QString etag READ etag WRITE setEtag NOTIFY etagChanged) - QString etag() const { return m_etag; } - void setEtag(QString etag) { if (etag != m_etag) { m_etag = etag; emit etagChanged(etag); } } + QString etag() const; + void setEtag(QString etag); Q_PROPERTY(bool error READ error WRITE setError NOTIFY errorChanged) - bool error() const { return m_error; } - void setError(bool error) { if (error != m_error) { m_error = error; emit errorChanged(error); } } + bool error() const; + void setError(bool error); Q_PROPERTY(QString errorMessage READ errorMessage WRITE setErrorMessage NOTIFY errorMessageChanged) - QString errorMessage() const { return m_errorMessage; } - void setErrorMessage(QString errorMessage) { if (errorMessage != m_errorMessage) { m_errorMessage = errorMessage; emit errorMessageChanged(errorMessage); } } + QString errorMessage() const; + void setErrorMessage(QString errorMessage); - Q_PROPERTY(QString prettyDate READ prettyDate NOTIFY prettyDateChanged) - QString prettyDate() const; + Q_PROPERTY(QString modifiedString READ modifiedString NOTIFY modifiedStringChanged) + QString modifiedString() const; - static Note fromjson(const QJsonObject& jobj); + QDateTime modifiedDateTime() const; + + static double id(const QJsonObject& jobj); + static double modified(const QJsonObject& jobj); + static QString title(const QJsonObject& jobj); + static QString category(const QJsonObject& jobj); + static QString content(const QJsonObject& jobj); + static bool favorite(const QJsonObject& jobj); + static QString etag(const QJsonObject& jobj); + static bool error(const QJsonObject& jobj); + static QString errorMessage(const QJsonObject& jobj); + static QString modifiedString(const QJsonObject& jobj); + static QDateTime modifiedDateTime(const QJsonObject& jobj); signals: - void idChanged(int id); - void modifiedChanged(uint modified); + void idChanged(double id); + void modifiedChanged(double modified); void titleChanged(QString title); void categoryChanged(QString category); void contentChanged(QString content); @@ -68,19 +103,12 @@ signals: void etagChanged(QString etag); void errorChanged(bool error); void errorMessageChanged(QString errorMessage); - void prettyDateChanged(QString date); + void modifiedStringChanged(QString date); + void modifiedDateTimeChanged(QDateTime dateTime); void noteChanged(); private: - int m_id; - uint m_modified; - QString m_title; - QString m_category; - QString m_content; - bool m_favorite; - QString m_etag; - bool m_error; - QString m_errorMessage; + QJsonObject m_json; }; #endif // NOTE_H diff --git a/src/notesapi.cpp b/src/notesapi.cpp index 03c6990..5a3d56f 100644 --- a/src/notesapi.cpp +++ b/src/notesapi.cpp @@ -3,7 +3,6 @@ #include #include #include -#include NotesApi::NotesApi(QObject *parent) : QObject(parent) { @@ -23,9 +22,17 @@ NotesApi::NotesApi(QObject *parent) : QObject(parent) m_request.setHeader(QNetworkRequest::UserAgentHeader, QGuiApplication::applicationDisplayName() + " / " + QGuiApplication::applicationVersion()); m_request.setRawHeader("OCS-APIREQUEST", "true"); m_request.setHeader(QNetworkRequest::ContentTypeHeader, QString("application/json").toUtf8()); + connect(mp_model, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector)), this, SLOT(saveToFile(QModelIndex,QModelIndex,QVector))); } NotesApi::~NotesApi() { + disconnect(mp_model, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector)), this, SLOT(saveToFile(QModelIndex,QModelIndex,QVector))); + disconnect(this, SIGNAL(urlChanged(QUrl)), this, SLOT(verifyUrl(QUrl))); + disconnect(&m_manager, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)), this, SLOT(requireAuthentication(QNetworkReply*,QAuthenticator*))); + 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))); + m_jsonFile.close(); delete mp_modelProxy; delete mp_model; } @@ -47,6 +54,7 @@ void NotesApi::requireAuthentication(QNetworkReply *reply, QAuthenticator *authe void NotesApi::setUrl(QUrl url) { if (url != m_url) { QUrl oldUrl = m_url; + bool oldReady = ready(); m_url = url; emit urlChanged(m_url); if (m_url.scheme() != oldUrl.scheme()) @@ -61,7 +69,10 @@ void NotesApi::setUrl(QUrl url) { emit passwordChanged(m_url.password()); if (m_url.path() != oldUrl.path()) emit pathChanged(m_url.path()); - qDebug() << "API URL changed:" << m_url.toDisplayString(); + if (ready() != oldReady) + emit readyChanged(ready()); + if (m_url.isValid()) + qDebug() << "API URL:" << m_url.toDisplayString(); } } @@ -121,14 +132,26 @@ void NotesApi::setPath(QString path) { } } -void NotesApi::setDataDir(QString dataDir) { - QDir newPath(dataDir); - if (newPath != m_jsonDir) { - m_jsonDir.setPath(dataDir); - emit dataDirChanged(m_jsonDir.absolutePath()); +void NotesApi::setDataFile(QString dataFile) { + if (dataFile != m_jsonFile.fileName()) { + m_jsonFile.close(); + if (!dataFile.isEmpty()) { + m_jsonFile.setFileName(dataFile); + m_jsonFile.open(QIODevice::ReadWrite | QIODevice::Text); // | QIODevice::Unbuffered + } + emit dataFileChanged(m_jsonFile.fileName()); + //qDebug() << m_jsonFile.fileName(); } } +bool NotesApi::ready() const { + return !m_url.scheme().isEmpty() && + !m_url.userName().isEmpty() && + !m_url.host().isEmpty() && + !m_url.path().isEmpty() && + !m_url.query().isEmpty(); +} + bool NotesApi::busy() const { bool busy = false; for (int i = 0; i < m_replies.size(); ++i) { @@ -207,9 +230,10 @@ void NotesApi::onNetworkAccessibleChanged(QNetworkAccessManager::NetworkAccessib void NotesApi::replyFinished(QNetworkReply *reply) { if (reply->error() == QNetworkReply::NoError) { - QJsonDocument json = QJsonDocument::fromJson(reply->readAll()); + QByteArray data = reply->readAll(); + QJsonDocument json = QJsonDocument::fromJson(data); if (mp_model) - mp_model->applyJSON(json); + mp_model->fromJsonDocument(json); //qDebug() << json; } else { @@ -226,3 +250,7 @@ void NotesApi::sslError(QNetworkReply *reply, const QList &errors) { qDebug() << errors[i].errorString(); } } + +void NotesApi::saveToFile(QModelIndex, QModelIndex, QVector) { + +} diff --git a/src/notesapi.h b/src/notesapi.h index 4d05504..4dfb36c 100644 --- a/src/notesapi.h +++ b/src/notesapi.h @@ -5,7 +5,7 @@ #include #include #include -#include +#include #include #include "notesmodel.h" @@ -51,13 +51,16 @@ public: QString path() const { return m_url.path(); } void setPath(QString path); - Q_PROPERTY(QString dataDir READ dataDir WRITE setDataDir NOTIFY dataDirChanged) - QString dataDir() const { return m_jsonDir.absolutePath(); } - void setDataDir(QString dataDir); + Q_PROPERTY(QString dataFile READ dataFile WRITE setDataFile NOTIFY dataFileChanged) + QString dataFile() const { return m_jsonFile.fileName(); } + void setDataFile(QString dataFile); Q_PROPERTY(bool networkAccessible READ networkAccessible NOTIFY networkAccessibleChanged) bool networkAccessible() const { return m_manager.networkAccessible() == QNetworkAccessManager::Accessible; } + Q_PROPERTY(bool ready READ ready NOTIFY readyChanged) + bool ready() const; + Q_PROPERTY(bool busy READ busy NOTIFY busyChanged) bool busy() const; @@ -78,8 +81,9 @@ signals: void usernameChanged(QString username); void passwordChanged(QString password); void pathChanged(QString path); - void dataDirChanged(QString dataDir); + void dataFileChanged(QString dataFile); void networkAccessibleChanged(bool accessible); + void readyChanged(bool ready); void busyChanged(bool busy); public slots: @@ -90,13 +94,14 @@ private slots: void onNetworkAccessibleChanged(QNetworkAccessManager::NetworkAccessibility accessible); void replyFinished(QNetworkReply* reply); void sslError(QNetworkReply* reply, const QList &errors); + void saveToFile(QModelIndex,QModelIndex,QVector); private: QUrl m_url; QNetworkAccessManager m_manager; QNetworkRequest m_request; QVector m_replies; - QDir m_jsonDir; + QFile m_jsonFile; NotesModel* mp_model; NotesProxyModel* mp_modelProxy; }; diff --git a/src/notesmodel.cpp b/src/notesmodel.cpp index 7f7ed06..380f39d 100644 --- a/src/notesmodel.cpp +++ b/src/notesmodel.cpp @@ -1,8 +1,7 @@ #include "notesmodel.h" -#include // std::sort +//#include // std::sort #include #include -#include #include #include @@ -32,7 +31,7 @@ bool NotesProxyModel::lessThan(const QModelIndex &source_left, const QModelIndex QAbstractItemModel* source = sourceModel(); if (m_favoritesOnTop && source->data(source_left, NotesModel::FavoriteRole).toBool() != source->data(source_right, NotesModel::FavoriteRole).toBool()) return source->data(source_left, NotesModel::FavoriteRole).toBool(); - else if (sortRole() == NotesModel::PrettyDateRole) + else if (sortRole() == NotesModel::ModifiedStringRole) return source->data(source_left, NotesModel::ModifiedRole).toInt() >= source->data(source_right, NotesModel::ModifiedRole).toInt(); else return QSortFilterProxyModel::lessThan(source_left, source_right); @@ -48,99 +47,84 @@ NotesModel::NotesModel(QObject *parent) { } NotesModel::~NotesModel() { - + m_notes.clear(); } -bool NotesModel::applyJSON(const QJsonDocument &jdoc) { - qDebug() << "Applying new JSON input";// << json; +bool NotesModel::fromJsonDocument(const QJsonDocument &jdoc) { + qDebug() << "Applying new JSON input"; // << json; if (!jdoc.isNull()) { if (jdoc.isArray()) { qDebug() << "- It's an array..."; - QVector newNotes; + QVector notesIdsToRemove = ids(); QJsonArray jarr = jdoc.array(); while (!jarr.empty()) { - //qDebug() << jarr.count() << "JSON Objects to handle..."; QJsonValue jval = jarr.first(); if (jval.isObject()) { - //qDebug() << "It's an object, all fine..."; QJsonObject jobj = jval.toObject(); if (!jobj.isEmpty()) { - newNotes.append(Note::fromjson(jobj)); + insertNote(jobj); + notesIdsToRemove.removeAll(Note::id(jobj)); } } + else { + qDebug() << "-- JSON array element is not an object!"; + } jarr.pop_front(); } - for (int i = 0; i < m_notes.size(); ++i) { - bool noteToBeRemoved = true; - for (int j = 0; j < newNotes.size(); ++j) { - if (m_notes[i].id() == newNotes[j].id()) - noteToBeRemoved = false; - } - if (noteToBeRemoved) { - qDebug() << "-- Removing note " << m_notes[i].title(); - removeNote(m_notes[i]); - } - } - while (!newNotes.empty()) { - insertNote(newNotes.first()); - newNotes.pop_front(); + while (!notesIdsToRemove.empty()) { + removeNote(notesIdsToRemove.first()); + notesIdsToRemove.pop_front(); } return true; } else if (jdoc.isObject()) { qDebug() << "- It's a single object..."; - insertNote(Note::fromjson(jdoc.object())); - return true; + return insertNote(jdoc.object()) >= 0; + } + else if (jdoc.isEmpty()) { + qDebug() << "- Empty JSON document."; } else { - qDebug() << "Unknown JSON document. This message should never occure!"; + qDebug() << "- Unknown JSON document. This message should never occure!"; } } - else - { - qDebug() << "JSON document is empty!"; + else { + qDebug() << "JSON document is NULL!"; } return false; } -bool NotesModel::applyJSON(const QString &json) { - QJsonParseError error; - QJsonDocument jdoc = QJsonDocument::fromJson(json.toUtf8(), &error); - if (!jdoc.isNull() && error.error == QJsonParseError::NoError) { - return applyJSON(jdoc); - } - return error.error == QJsonParseError::NoError; -} - -int NotesModel::indexOf(const Note ¬e) const { - return indexOf(note.id()); -} - -int NotesModel::indexOf(int id) const { - int retval = -1; +QJsonDocument NotesModel::toJsonDocument() const { + QJsonArray jarr; for (int i = 0; i < m_notes.size(); ++i) { - if (m_notes[i].id() == id) { - retval = i; - } + jarr << m_notes[i].toJsonValue(); } - return retval; + return QJsonDocument(jarr); +} + +QVector NotesModel::ids() const { + QVector ids; + for (int i = 0; i < m_notes.size(); ++i) { + ids.append(m_notes[i].id()); + } + return ids; } int NotesModel::insertNote(const Note ¬e) { - int position = indexOf(note.id()); + int position = m_notes.indexOf(note); if (position >= 0) { - if (note.etag() != m_notes[position].etag()) { - qDebug() << "-- Existing note " << note.title() << "changed, updating the model."; + if (m_notes.at(position).equal(note)) { + qDebug() << "-- Note already present but unchanged."; + } + else { + qDebug() << "-- Note already present, updating it."; m_notes.replace(position, note); emit dataChanged(index(position), index(position)); } - else { - qDebug() << "-- Existing note " << note.title() << "unchanged, nothing to do."; - } } else { - qDebug() << "-- New note" << note.title() << ", adding it to the model."; - position = rowCount(); + qDebug() << "-- New note, adding it"; + position = m_notes.size(); beginInsertRows(QModelIndex(), position, position); m_notes.append(note); endInsertRows(); @@ -149,11 +133,7 @@ int NotesModel::insertNote(const Note ¬e) { } bool NotesModel::removeNote(const Note ¬e) { - return removeNote(note.id()); -} - -bool NotesModel::removeNote(int id) { - int position = indexOf(id); + int position = m_notes.indexOf(note); if (position >= 0 && position < m_notes.size()) { beginRemoveRows(QModelIndex(), position, position); m_notes.removeAt(position); @@ -163,6 +143,10 @@ bool NotesModel::removeNote(int id) { return false; } +bool NotesModel::removeNote(double id) { + return removeNote(Note(QJsonObject{ {"id", id} } )); +} + QHash NotesModel::roleNames() const { return QHash { {NotesModel::IdRole, "id"}, @@ -174,7 +158,7 @@ QHash NotesModel::roleNames() const { {NotesModel::EtagRole, "etag"}, {NotesModel::ErrorRole, "error"}, {NotesModel::ErrorMessageRole, "errorMessage"}, - {NotesModel::PrettyDateRole, "prettyDate"}, + {NotesModel::ModifiedStringRole, "modifiedString"}, {NotesModel::NoneRole, "none"} }; } @@ -203,7 +187,7 @@ QVariant NotesModel::data(const QModelIndex &index, int role) const { 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 == PrettyDateRole) return m_notes[index.row()].prettyDate(); + else if (role == ModifiedStringRole) return m_notes[index.row()].modifiedString(); return QVariant(); } @@ -211,7 +195,7 @@ QMap NotesModel::itemData(const QModelIndex &index) const { QMap map; if (!index.isValid()) return map; else { - for (int role = IdRole; role <= ErrorMessageRole; ++role) { + for (int role = IdRole; role < NoneRole; ++role) { map.insert(role, data(index, role)); } } diff --git a/src/notesmodel.h b/src/notesmodel.h index 4d517a0..2bdd249 100644 --- a/src/notesmodel.h +++ b/src/notesmodel.h @@ -3,6 +3,7 @@ #include #include +#include #include #include "note.h" @@ -37,8 +38,8 @@ public: explicit NotesModel(QObject *parent = 0); virtual ~NotesModel(); - bool applyJSON(const QJsonDocument &jdoc); - bool applyJSON(const QString &json); + bool fromJsonDocument(const QJsonDocument &jdoc); + QJsonDocument toJsonDocument() const; enum NoteRoles { IdRole = Qt::UserRole, @@ -50,7 +51,7 @@ public: EtagRole = Qt::UserRole + 6, ErrorRole = Qt::UserRole + 7, ErrorMessageRole = Qt::UserRole + 8, - PrettyDateRole = Qt::UserRole + 9, + ModifiedStringRole = Qt::UserRole + 9, NoneRole = Qt::UserRole + 10 }; QHash roleNames() const; @@ -61,18 +62,21 @@ public: QMap itemData(const QModelIndex &index) const; protected: - int indexOf(const Note ¬e) const; - int indexOf(int id) const; + void addNote(const QJsonValue ¬e); + QVector ids() const; + //int indexOf(const Note ¬e) const; + //int indexOf(int id) const; int insertNote(const Note ¬e); - bool replaceNote(const Note ¬e); + //bool replaceNote(const Note ¬e); bool removeNote(const Note ¬e); - bool removeNote(int id); + bool removeNote(double id); signals: void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector &roles = QVector ()); private: QVector m_notes; + //QJsonArray m_notes; }; #endif // NOTESMODEL_H diff --git a/translations/harbour-nextcloudnotes.ts b/translations/harbour-nextcloudnotes.ts index 5048310..51884d7 100644 --- a/translations/harbour-nextcloudnotes.ts +++ b/translations/harbour-nextcloudnotes.ts @@ -196,12 +196,12 @@ Note - + Today - + Yesterday @@ -209,52 +209,52 @@ NotePage - + Delete - + Reload - + Updating... - + Last update - + never - + Edit - + Notes - + No category - + Category - + Modified