Changed internal data handling to QJson___ for easier conversion to raw output to save the notes to files.
This commit is contained in:
parent
e2aaa47a7e
commit
426f7ea509
12 changed files with 406 additions and 183 deletions
|
@ -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 \
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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();
|
||||
|
|
246
src/note.cpp
246
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;
|
||||
}
|
||||
|
|
104
src/note.h
104
src/note.h
|
@ -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
|
||||
|
|
|
@ -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>) {
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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 ¬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<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 ¬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<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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 ¬e) const;
|
||||
int indexOf(int id) const;
|
||||
void addNote(const QJsonValue ¬e);
|
||||
QVector<double> 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<int> &roles = QVector<int> ());
|
||||
|
||||
private:
|
||||
QVector<Note> m_notes;
|
||||
//QJsonArray m_notes;
|
||||
};
|
||||
|
||||
#endif // NOTESMODEL_H
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in a new issue