Changed internal data handling to QJson___ for easier conversion to raw output to save the notes to files.

This commit is contained in:
Scharel Clemens 2019-12-30 18:14:38 +01:00
parent e2aaa47a7e
commit 426f7ea509
12 changed files with 406 additions and 183 deletions

View file

@ -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 \

View file

@ -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()
}

View file

@ -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

View file

@ -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 {

View file

@ -17,7 +17,6 @@ int main(int argc, char *argv[])
qDebug() << app->applicationDisplayName() << app->applicationVersion();
qmlRegisterType<NotesApi>("harbour.nextcloudnotes.notesapi", 1, 0, "NotesApi");
qmlRegisterType<Note>("harbour.nextcloudnotes.note", 1, 0, "Note");
qmlRegisterType<NotesProxyModel>("harbour.nextcloudnotes.notesmodel", 1, 0, "NotesModel");
QQuickView* view = SailfishApp::createView();

View file

@ -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 &note, 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 &note) 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 &note) 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 &note) 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;
}

View file

@ -3,64 +3,99 @@
#include <QObject>
#include <QJsonObject>
#include <QJsonDocument>
#include <QDateTime>
#include <QDebug>
#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

View file

@ -3,7 +3,6 @@
#include <QAuthenticator>
#include <QJsonDocument>
#include <QJsonObject>
#include <QFile>
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<int>)), this, SLOT(saveToFile(QModelIndex,QModelIndex,QVector<int>)));
}
NotesApi::~NotesApi() {
disconnect(mp_model, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>)), this, SLOT(saveToFile(QModelIndex,QModelIndex,QVector<int>)));
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<QSslError>)), this, SLOT(sslError(QNetworkReply*,QList<QSslError>)));
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<QSslError> &errors) {
qDebug() << errors[i].errorString();
}
}
void NotesApi::saveToFile(QModelIndex, QModelIndex, QVector<int>) {
}

View file

@ -5,7 +5,7 @@
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QDir>
#include <QFile>
#include <QDebug>
#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<QSslError> &errors);
void saveToFile(QModelIndex,QModelIndex,QVector<int>);
private:
QUrl m_url;
QNetworkAccessManager m_manager;
QNetworkRequest m_request;
QVector<QNetworkReply*> m_replies;
QDir m_jsonDir;
QFile m_jsonFile;
NotesModel* mp_model;
NotesProxyModel* mp_modelProxy;
};

View file

@ -1,8 +1,7 @@
#include "notesmodel.h"
#include <algorithm> // std::sort
//#include <algorithm> // std::sort
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QtMath>
#include <QDebug>
@ -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<Note> newNotes;
QVector<double> 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 &note) 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<double> NotesModel::ids() const {
QVector<double> ids;
for (int i = 0; i < m_notes.size(); ++i) {
ids.append(m_notes[i].id());
}
return ids;
}
int NotesModel::insertNote(const Note &note) {
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 &note) {
}
bool NotesModel::removeNote(const Note &note) {
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<int, QByteArray> NotesModel::roleNames() const {
return QHash<int, QByteArray> {
{NotesModel::IdRole, "id"},
@ -174,7 +158,7 @@ QHash<int, QByteArray> 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<int, QVariant> NotesModel::itemData(const QModelIndex &index) const {
QMap<int, QVariant> 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));
}
}

View file

@ -3,6 +3,7 @@
#include <QSortFilterProxyModel>
#include <QAbstractListModel>
#include <QJsonArray>
#include <QDateTime>
#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<int, QByteArray> roleNames() const;
@ -61,18 +62,21 @@ public:
QMap<int, QVariant> itemData(const QModelIndex &index) const;
protected:
int indexOf(const Note &note) const;
int indexOf(int id) const;
void addNote(const QJsonValue &note);
QVector<double> ids() const;
//int indexOf(const Note &note) const;
//int indexOf(int id) const;
int insertNote(const Note &note);
bool replaceNote(const Note &note);
//bool replaceNote(const Note &note);
bool removeNote(const Note &note);
bool removeNote(int id);
bool removeNote(double id);
signals:
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles = QVector<int> ());
private:
QVector<Note> m_notes;
//QJsonArray m_notes;
};
#endif // NOTESMODEL_H

View file

@ -196,12 +196,12 @@
<context>
<name>Note</name>
<message>
<location filename="../src/note.cpp" line="66"/>
<location filename="../src/note.cpp" line="249"/>
<source>Today</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/note.cpp" line="68"/>
<location filename="../src/note.cpp" line="251"/>
<source>Yesterday</source>
<translation type="unfinished"></translation>
</message>
@ -209,52 +209,52 @@
<context>
<name>NotePage</name>
<message>
<location filename="../qml/pages/NotePage.qml" line="114"/>
<location filename="../qml/pages/NotePage.qml" line="111"/>
<source>Delete</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/pages/NotePage.qml" line="118"/>
<location filename="../qml/pages/NotePage.qml" line="115"/>
<source>Reload</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/pages/NotePage.qml" line="118"/>
<location filename="../qml/pages/NotePage.qml" line="115"/>
<source>Updating...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/pages/NotePage.qml" line="124"/>
<location filename="../qml/pages/NotePage.qml" line="121"/>
<source>Last update</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/pages/NotePage.qml" line="127"/>
<location filename="../qml/pages/NotePage.qml" line="124"/>
<source>never</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/pages/NotePage.qml" line="134"/>
<location filename="../qml/pages/NotePage.qml" line="131"/>
<source>Edit</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/pages/NotePage.qml" line="135"/>
<location filename="../qml/pages/NotePage.qml" line="132"/>
<source>Notes</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/pages/NotePage.qml" line="255"/>
<location filename="../qml/pages/NotePage.qml" line="252"/>
<source>No category</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/pages/NotePage.qml" line="256"/>
<location filename="../qml/pages/NotePage.qml" line="253"/>
<source>Category</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/pages/NotePage.qml" line="271"/>
<location filename="../qml/pages/NotePage.qml" line="268"/>
<source>Modified</source>
<translation type="unfinished"></translation>
</message>