Improved communication between the modules. Offline mode seems to work fine now. Some kind of synchronisation of offline changes is now needed
This commit is contained in:
parent
629d752dee
commit
4ff667e3d1
15 changed files with 432 additions and 224 deletions
|
@ -129,9 +129,16 @@ ApplicationWindow
|
||||||
}
|
}
|
||||||
|
|
||||||
Notification {
|
Notification {
|
||||||
id: errorNotification
|
id: storeErrorNotification
|
||||||
appName: offlineNotification.appName
|
appName: offlineNotification.appName
|
||||||
summary: qsTr("Error")
|
summary: qsTr("File error")
|
||||||
|
Component.onDestruction: close()
|
||||||
|
}
|
||||||
|
|
||||||
|
Notification {
|
||||||
|
id: apiErrorNotification
|
||||||
|
appName: offlineNotification.appName
|
||||||
|
summary: qsTr("API error")
|
||||||
Component.onDestruction: close()
|
Component.onDestruction: close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,6 +164,19 @@ ApplicationWindow
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: notesStore
|
||||||
|
|
||||||
|
onNoteError: {
|
||||||
|
storeErrorNotification.close()
|
||||||
|
if (error) {
|
||||||
|
console.log("Notes Store error (" + error + "): " + notesStore.errorMessage(error))
|
||||||
|
storeErrorNotification.body = notesStore.errorMessage(error)
|
||||||
|
storeErrorNotification.publish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: notesApi
|
target: notesApi
|
||||||
|
|
||||||
|
@ -164,18 +184,24 @@ ApplicationWindow
|
||||||
console.log("Device is " + (accessible ? "online" : "offline"))
|
console.log("Device is " + (accessible ? "online" : "offline"))
|
||||||
accessible ? offlineNotification.close(Notification.Closed) : offlineNotification.publish()
|
accessible ? offlineNotification.close(Notification.Closed) : offlineNotification.publish()
|
||||||
}
|
}
|
||||||
onError: {
|
onNoteError: {
|
||||||
|
apiErrorNotification.close()
|
||||||
if (error)
|
if (error)
|
||||||
console.log("Error (" + error + "): " + notesApi.errorMessage(error))
|
console.log("Notes API error (" + error + "): " + notesApi.errorMessage(error))
|
||||||
errorNotification.close()
|
|
||||||
if (error && notesApi.networkAccessible) {
|
if (error && notesApi.networkAccessible) {
|
||||||
errorNotification.body = notesApi.errorMessage(error)
|
apiErrorNotification.body = notesApi.errorMessage(error)
|
||||||
errorNotification.publish()
|
apiErrorNotification.publish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onLastSyncChanged: account.update = lastSync
|
onLastSyncChanged: account.update = lastSync
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Component.onDestruction: {
|
||||||
|
offlineNotification.close()
|
||||||
|
storeErrorNotification.close()
|
||||||
|
apiErrorNotification.close()
|
||||||
|
}
|
||||||
|
|
||||||
initialPage: Component { NotesPage { } }
|
initialPage: Component { NotesPage { } }
|
||||||
cover: Qt.resolvedUrl("cover/CoverPage.qml")
|
cover: Qt.resolvedUrl("cover/CoverPage.qml")
|
||||||
allowedOrientations: defaultAllowedOrientations
|
allowedOrientations: defaultAllowedOrientations
|
||||||
|
|
|
@ -120,6 +120,7 @@ Page {
|
||||||
icon.source: (favorite ? "image://theme/icon-m-favorite-selected?" : "image://theme/icon-m-favorite?") +
|
icon.source: (favorite ? "image://theme/icon-m-favorite-selected?" : "image://theme/icon-m-favorite?") +
|
||||||
(note.highlighted ? Theme.secondaryHighlightColor : Theme.secondaryColor)
|
(note.highlighted ? Theme.secondaryHighlightColor : Theme.secondaryColor)
|
||||||
onClicked: {
|
onClicked: {
|
||||||
|
console.log("Setting favoirte: " + !favorite)
|
||||||
notesStore.updateNote(id, {'favorite': !favorite, 'modified': new Date().valueOf() / 1000 } )
|
notesStore.updateNote(id, {'favorite': !favorite, 'modified': new Date().valueOf() / 1000 } )
|
||||||
notesApi.updateNote(id, {'favorite': !favorite, 'modified': new Date().valueOf() / 1000 } )
|
notesApi.updateNote(id, {'favorite': !favorite, 'modified': new Date().valueOf() / 1000 } )
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,15 +30,15 @@ int main(int argc, char *argv[])
|
||||||
NotesStore* notesStore = new NotesStore;
|
NotesStore* notesStore = new NotesStore;
|
||||||
NotesApi* notesApi = new NotesApi;
|
NotesApi* notesApi = new NotesApi;
|
||||||
|
|
||||||
QObject::connect(notesApi, SIGNAL(noteUpdated(Note)), notesStore, SLOT(updateNote(Note)));
|
QObject::connect(notesApi, SIGNAL(noteUpdated(int, QJsonObject)), notesStore, SLOT(updateNote(int, QJsonObject)));
|
||||||
//QObject::connect(notesStore, SIGNAL(noteUpdated(Note)), notesApi, SLOT(updateNote(Note)));
|
//QObject::connect(notesStore, SIGNAL(noteUpdated(Note)), notesApi, SLOT(updateNote(Note)));
|
||||||
QObject::connect(notesApi, SIGNAL(noteDeleted(int)), notesStore, SLOT(deleteNote(int)));
|
QObject::connect(notesApi, SIGNAL(noteDeleted(int)), notesStore, SLOT(deleteNote(int)));
|
||||||
//QObject::connect(notesStore, SIGNAL(noteDeleted(int)), notesApi, SLOT(deleteNote(int)));
|
//QObject::connect(notesStore, SIGNAL(noteDeleted(int)), notesApi, SLOT(deleteNote(int)));
|
||||||
|
|
||||||
QObject::connect(notesStore, SIGNAL(noteUpdated(Note)), notesModel, SLOT(insertNote(Note)));
|
QObject::connect(notesStore, SIGNAL(noteUpdated(int, QJsonObject)), notesModel, SLOT(insertNote(int, QJsonObject)));
|
||||||
QObject::connect(notesStore, SIGNAL(noteDeleted(int)), notesModel, SLOT(removeNote(int)));
|
QObject::connect(notesStore, SIGNAL(noteDeleted(int)), notesModel, SLOT(removeNote(int)));
|
||||||
QObject::connect(notesApi, SIGNAL(noteUpdated(Note)), notesModel, SLOT(insertNote(Note)));
|
//QObject::connect(notesApi, SIGNAL(noteUpdated(Note)), notesModel, SLOT(insertNote(Note)));
|
||||||
QObject::connect(notesApi, SIGNAL(noteDeleted(int)), notesModel, SLOT(removeNote(int)));
|
//QObject::connect(notesApi, SIGNAL(noteDeleted(int)), notesModel, SLOT(removeNote(int)));
|
||||||
|
|
||||||
QQuickView* view = SailfishApp::createView();
|
QQuickView* view = SailfishApp::createView();
|
||||||
#ifdef QT_DEBUG
|
#ifdef QT_DEBUG
|
||||||
|
@ -54,15 +54,15 @@ int main(int argc, char *argv[])
|
||||||
view->show();
|
view->show();
|
||||||
|
|
||||||
int retval = app->exec();
|
int retval = app->exec();
|
||||||
QObject::disconnect(notesApi, SIGNAL(noteDeleted(int)), notesModel, SLOT(removeNote(int)));
|
//QObject::disconnect(notesApi, SIGNAL(noteDeleted(int)), notesModel, SLOT(removeNote(int)));
|
||||||
QObject::disconnect(notesApi, SIGNAL(noteUpdated(Note)), notesModel, SLOT(insertNote(Note)));
|
//QObject::disconnect(notesApi, SIGNAL(noteUpdated(Note)), notesModel, SLOT(insertNote(Note)));
|
||||||
QObject::disconnect(notesStore, SIGNAL(noteDeleted(int)), notesModel, SLOT(removeNote(int)));
|
QObject::disconnect(notesStore, SIGNAL(noteDeleted(int)), notesModel, SLOT(removeNote(int)));
|
||||||
QObject::disconnect(notesStore, SIGNAL(noteUpdated(Note)), notesModel, SLOT(insertNote(Note)));
|
QObject::disconnect(notesStore, SIGNAL(noteUpdated(int, QJsonObject)), notesModel, SLOT(insertNote(int, QJsonObject)));
|
||||||
|
|
||||||
//QObject::disconnect(notesStore, SIGNAL(noteDeleted(int)), notesApi, SLOT(deleteNote(int)));
|
//QObject::disconnect(notesStore, SIGNAL(noteDeleted(int)), notesApi, SLOT(deleteNote(int)));
|
||||||
QObject::disconnect(notesApi, SIGNAL(noteDeleted(int)), notesStore, SLOT(deleteNote(int)));
|
QObject::disconnect(notesApi, SIGNAL(noteDeleted(int)), notesStore, SLOT(deleteNote(int)));
|
||||||
//QObject::disconnect(notesStore, SIGNAL(noteUpdated(Note)), notesApi, SLOT(updateNote(Note)));
|
//QObject::disconnect(notesStore, SIGNAL(noteUpdated(Note)), notesApi, SLOT(updateNote(Note)));
|
||||||
QObject::disconnect(notesApi, SIGNAL(noteUpdated(Note)), notesStore, SLOT(updateNote(Note)));
|
QObject::disconnect(notesApi, SIGNAL(noteUpdated(int, QJsonObject)), notesStore, SLOT(updateNote(int, QJsonObject)));
|
||||||
|
|
||||||
notesApi->deleteLater();
|
notesApi->deleteLater();
|
||||||
notesStore->deleteLater();
|
notesStore->deleteLater();
|
||||||
|
|
22
src/note.cpp
22
src/note.cpp
|
@ -70,6 +70,28 @@ Note& Note::operator =(const QJsonObject& note) {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Note& Note::operator <<(const QJsonObject& note) {
|
||||||
|
if (note.contains(Note::noteFieldName(Note::Id)))
|
||||||
|
setId(id(note));
|
||||||
|
if (note.contains(Note::noteFieldName(Note::Modified)))
|
||||||
|
setModified(modified(note));
|
||||||
|
if (note.contains(Note::noteFieldName(Note::Title)))
|
||||||
|
setTitle(title(note));
|
||||||
|
if (note.contains(Note::noteFieldName(Note::Category)))
|
||||||
|
setCategory(category(note));
|
||||||
|
if (note.contains(Note::noteFieldName(Note::Content)))
|
||||||
|
setContent(content(note));
|
||||||
|
if (note.contains(Note::noteFieldName(Note::Favorite)))
|
||||||
|
setFavorite(favorite(note));
|
||||||
|
if (note.contains(Note::noteFieldName(Note::Etag)))
|
||||||
|
setEtag(etag(note));
|
||||||
|
if (note.contains(Note::noteFieldName(Note::Error)))
|
||||||
|
setError(error(note));
|
||||||
|
if (note.contains(Note::noteFieldName(Note::ErrorMessage)))
|
||||||
|
setErrorMessage(errorMessage(note));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
bool Note::operator ==(const Note& note) const {
|
bool Note::operator ==(const Note& note) const {
|
||||||
return id() == note.id();
|
return id() == note.id();
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ public:
|
||||||
|
|
||||||
Note& operator =(const Note& note);
|
Note& operator =(const Note& note);
|
||||||
Note& operator =(const QJsonObject& note);
|
Note& operator =(const QJsonObject& note);
|
||||||
|
Note& operator <<(const QJsonObject& note);
|
||||||
bool operator ==(const Note& note) const;
|
bool operator ==(const Note& note) const;
|
||||||
bool operator ==(const QJsonObject& note) const;
|
bool operator ==(const QJsonObject& note) const;
|
||||||
bool equal(const Note& note) const;
|
bool equal(const Note& note) const;
|
||||||
|
|
115
src/notesapi.cpp
115
src/notesapi.cpp
|
@ -50,24 +50,12 @@ void NotesApi::setAccount(const QString &account) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NotesApi::getAllNotes(const QStringList exclude) {
|
void NotesApi::getAllNotes(const QStringList& exclude) {
|
||||||
getAllNotes(Note::noteFieldsFromStringList(exclude));
|
|
||||||
}
|
|
||||||
|
|
||||||
void NotesApi::getAllNotes(Note::NoteField exclude) {
|
|
||||||
qDebug() << "Getting all notes";
|
qDebug() << "Getting all notes";
|
||||||
QUrl url = apiEndpointUrl(m_notesEndpoint);
|
QUrl url = apiEndpointUrl(m_notesEndpoint);
|
||||||
QStringList excludeFields;
|
|
||||||
QList<Note::NoteField> noteFields = Note::noteFields();
|
|
||||||
QFlags<Note::NoteField> flags(exclude);
|
|
||||||
|
|
||||||
for (int i = 0; i < noteFields.size(); ++i) {
|
if (!exclude.isEmpty())
|
||||||
if (flags.testFlag(noteFields[i])) {
|
url.setQuery(QString(EXCLUDE_QUERY).append(exclude.join(",")));
|
||||||
excludeFields << Note::noteFieldName(noteFields[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!excludeFields.isEmpty())
|
|
||||||
url.setQuery(QString(EXCLUDE_QUERY).append(excludeFields.join(",")));
|
|
||||||
|
|
||||||
if (url.isValid() && !url.scheme().isEmpty() && !url.host().isEmpty()) {
|
if (url.isValid() && !url.scheme().isEmpty() && !url.host().isEmpty()) {
|
||||||
qDebug() << "GET" << url.toDisplayString();
|
qDebug() << "GET" << url.toDisplayString();
|
||||||
|
@ -77,24 +65,11 @@ void NotesApi::getAllNotes(Note::NoteField exclude) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NotesApi::getNote(const int id, const QStringList exclude) {
|
void NotesApi::getNote(const int id, const QStringList& exclude) {
|
||||||
getNote(id, Note::noteFieldsFromStringList(exclude));
|
|
||||||
}
|
|
||||||
|
|
||||||
void NotesApi::getNote(const int id, Note::NoteField exclude) {
|
|
||||||
qDebug() << "Getting note: " << id;
|
qDebug() << "Getting note: " << id;
|
||||||
QUrl url = apiEndpointUrl(m_notesEndpoint + QString("/%1").arg(id));
|
QUrl url = apiEndpointUrl(m_notesEndpoint + QString("/%1").arg(id));
|
||||||
QStringList excludeFields;
|
if (!exclude.isEmpty())
|
||||||
QList<Note::NoteField> noteFields = Note::noteFields();
|
url.setQuery(QString(EXCLUDE_QUERY).append(exclude.join(",")));
|
||||||
QFlags<Note::NoteField> flags(exclude);
|
|
||||||
|
|
||||||
for (int i = 0; i < noteFields.size(); ++i) {
|
|
||||||
if (flags.testFlag(noteFields[i])) {
|
|
||||||
excludeFields << Note::noteFieldName(noteFields[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!excludeFields.isEmpty())
|
|
||||||
url.setQuery(QString(EXCLUDE_QUERY).append(excludeFields.join(",")));
|
|
||||||
|
|
||||||
if (url.isValid() && !url.scheme().isEmpty() && !url.host().isEmpty()) {
|
if (url.isValid() && !url.scheme().isEmpty() && !url.host().isEmpty()) {
|
||||||
qDebug() << "GET" << url.toDisplayString();
|
qDebug() << "GET" << url.toDisplayString();
|
||||||
|
@ -104,34 +79,24 @@ void NotesApi::getNote(const int id, Note::NoteField exclude) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NotesApi::createNote(const QVariantMap ¬e) {
|
void NotesApi::createNote(const QJsonObject& note) {
|
||||||
createNote(Note(QJsonObject::fromVariantMap(note)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void NotesApi::createNote(const Note ¬e) {
|
|
||||||
qDebug() << "Creating note";
|
qDebug() << "Creating note";
|
||||||
QUrl url = apiEndpointUrl(m_notesEndpoint);
|
QUrl url = apiEndpointUrl(m_notesEndpoint);
|
||||||
if (url.isValid() && !url.scheme().isEmpty() && !url.host().isEmpty()) {
|
if (url.isValid() && !url.scheme().isEmpty() && !url.host().isEmpty()) {
|
||||||
qDebug() << "POST" << url.toDisplayString();
|
qDebug() << "POST" << url.toDisplayString();
|
||||||
m_authenticatedRequest.setUrl(url);
|
m_authenticatedRequest.setUrl(url);
|
||||||
m_createNoteReplies << m_manager.post(m_authenticatedRequest, noteApiData(note));
|
m_createNoteReplies << m_manager.post(m_authenticatedRequest, QJsonDocument(note).toJson());
|
||||||
emit busyChanged(true);
|
emit busyChanged(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NotesApi::updateNote(const int id, const QVariantMap ¬e) {
|
void NotesApi::updateNote(const int id, const QJsonObject& note) {
|
||||||
Note newNote(QJsonObject::fromVariantMap(note));
|
qDebug() << "Updating note: " << id;
|
||||||
newNote.setId(id);
|
QUrl url = apiEndpointUrl(m_notesEndpoint + QString("/%1").arg(id));
|
||||||
updateNote(newNote);
|
if (id >= 0 && url.isValid() && !url.scheme().isEmpty() && !url.host().isEmpty()) {
|
||||||
}
|
|
||||||
|
|
||||||
void NotesApi::updateNote(const Note ¬e) {
|
|
||||||
qDebug() << "Updating note: " << note.id();
|
|
||||||
QUrl url = apiEndpointUrl(m_notesEndpoint + QString("/%1").arg(note.id()));
|
|
||||||
if (note.isValid() && url.isValid() && !url.scheme().isEmpty() && !url.host().isEmpty()) {
|
|
||||||
qDebug() << "PUT" << url.toDisplayString();
|
qDebug() << "PUT" << url.toDisplayString();
|
||||||
m_authenticatedRequest.setUrl(url);
|
m_authenticatedRequest.setUrl(url);
|
||||||
m_updateNoteReplies << m_manager.put(m_authenticatedRequest, noteApiData(note));
|
m_updateNoteReplies << m_manager.put(m_authenticatedRequest, QJsonDocument(note).toJson());
|
||||||
emit busyChanged(true);
|
emit busyChanged(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -159,26 +124,6 @@ bool NotesApi::busy() const {
|
||||||
m_ocsReplies.empty());
|
m_ocsReplies.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
const QByteArray NotesApi::noteApiData(const Note ¬e) {
|
|
||||||
QJsonObject json = note.toJsonObject();
|
|
||||||
json.remove(Note::noteFieldName(Note::Id));
|
|
||||||
if (note.modified() == 0)
|
|
||||||
json.remove(Note::noteFieldName(Note::Modified));
|
|
||||||
if (note.title().isNull())
|
|
||||||
json.remove(Note::noteFieldName(Note::Title));
|
|
||||||
if (note.category().isNull())
|
|
||||||
json.remove(Note::noteFieldName(Note::Category));
|
|
||||||
if (note.content().isNull())
|
|
||||||
json.remove(Note::noteFieldName(Note::Content));
|
|
||||||
json.remove(Note::noteFieldName(Note::Etag));
|
|
||||||
json.remove(Note::noteFieldName(Note::Error));
|
|
||||||
json.remove(Note::noteFieldName(Note::ErrorMessage));
|
|
||||||
|
|
||||||
return QJsonDocument(json).toJson(QJsonDocument::Compact);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO ab hier überarbeiten
|
|
||||||
|
|
||||||
void NotesApi::setVerifySsl(bool verify) {
|
void NotesApi::setVerifySsl(bool verify) {
|
||||||
if (verify != (m_request.sslConfiguration().peerVerifyMode() == QSslSocket::VerifyPeer)) {
|
if (verify != (m_request.sslConfiguration().peerVerifyMode() == QSslSocket::VerifyPeer)) {
|
||||||
m_request.sslConfiguration().setPeerVerifyMode(verify ? QSslSocket::VerifyPeer : QSslSocket::VerifyNone);
|
m_request.sslConfiguration().setPeerVerifyMode(verify ? QSslSocket::VerifyPeer : QSslSocket::VerifyNone);
|
||||||
|
@ -359,10 +304,11 @@ void NotesApi::verifyLogin(QString username, QString password) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const QString NotesApi::errorMessage(ErrorCodes error) const {
|
const QString NotesApi::errorMessage(int error) const {
|
||||||
QString message;
|
QString message;
|
||||||
switch (error) {
|
switch (error) {
|
||||||
case NoError:
|
case NoError:
|
||||||
|
message = tr("No error");
|
||||||
break;
|
break;
|
||||||
case NoConnectionError:
|
case NoConnectionError:
|
||||||
message = tr("No network connection available");
|
message = tr("No network connection available");
|
||||||
|
@ -393,7 +339,7 @@ void NotesApi::requireAuthentication(QNetworkReply *reply, QAuthenticator *authe
|
||||||
authenticator->setPassword(password());
|
authenticator->setPassword(password());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
emit error(AuthenticationError);
|
emit noteError(AuthenticationError);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NotesApi::onNetworkAccessibleChanged(QNetworkAccessManager::NetworkAccessibility accessible) {
|
void NotesApi::onNetworkAccessibleChanged(QNetworkAccessManager::NetworkAccessibility accessible) {
|
||||||
|
@ -405,13 +351,13 @@ void NotesApi::replyFinished(QNetworkReply *reply) {
|
||||||
qDebug() << reply->error() << reply->errorString();
|
qDebug() << reply->error() << reply->errorString();
|
||||||
|
|
||||||
if (reply->error() == QNetworkReply::NoError)
|
if (reply->error() == QNetworkReply::NoError)
|
||||||
emit error(NoError);
|
emit noteError(NoError);
|
||||||
else if (reply->error() == QNetworkReply::AuthenticationRequiredError)
|
else if (reply->error() == QNetworkReply::AuthenticationRequiredError)
|
||||||
emit error(AuthenticationError);
|
emit noteError(AuthenticationError);
|
||||||
else if (reply->error() == QNetworkReply::ContentNotFoundError && m_pollReplies.contains(reply))
|
else if (reply->error() == QNetworkReply::ContentNotFoundError && m_pollReplies.contains(reply))
|
||||||
emit error(NoError);
|
emit noteError(NoError);
|
||||||
else
|
else
|
||||||
emit error(CommunicationError);
|
emit noteError(CommunicationError);
|
||||||
|
|
||||||
QByteArray data = reply->readAll();
|
QByteArray data = reply->readAll();
|
||||||
QJsonDocument json = QJsonDocument::fromJson(data);
|
QJsonDocument json = QJsonDocument::fromJson(data);
|
||||||
|
@ -435,9 +381,14 @@ void NotesApi::replyFinished(QNetworkReply *reply) {
|
||||||
m_createNoteReplies.removeOne(reply);
|
m_createNoteReplies.removeOne(reply);
|
||||||
}
|
}
|
||||||
else if (m_updateNoteReplies.contains(reply)) {
|
else if (m_updateNoteReplies.contains(reply)) {
|
||||||
qDebug() << "Update note reply";
|
qDebug() << "Update note reply";bool ok;
|
||||||
if (reply->error() == QNetworkReply::NoError && json.isObject())
|
QString idString = reply->url().path().split('/', QString::SkipEmptyParts).last();
|
||||||
updateApiNote(json.object());
|
int id = idString.toInt(&ok);
|
||||||
|
if (reply->error() == QNetworkReply::NoError && json.isObject() && id >= 0 && ok) {
|
||||||
|
QJsonObject obj = json.object();
|
||||||
|
obj["id"] = id;
|
||||||
|
updateApiNote(obj);
|
||||||
|
}
|
||||||
m_updateNoteReplies.removeOne(reply);
|
m_updateNoteReplies.removeOne(reply);
|
||||||
}
|
}
|
||||||
else if (m_deleteNoteReplies.contains(reply)) {
|
else if (m_deleteNoteReplies.contains(reply)) {
|
||||||
|
@ -445,7 +396,7 @@ void NotesApi::replyFinished(QNetworkReply *reply) {
|
||||||
bool ok;
|
bool ok;
|
||||||
QString idString = reply->url().path().split('/', QString::SkipEmptyParts).last();
|
QString idString = reply->url().path().split('/', QString::SkipEmptyParts).last();
|
||||||
int id = idString.toInt(&ok);
|
int id = idString.toInt(&ok);
|
||||||
if (reply->error() == QNetworkReply::NoError && ok)
|
if (reply->error() == QNetworkReply::NoError && id >= 0 && ok)
|
||||||
emit noteDeleted(id);
|
emit noteDeleted(id);
|
||||||
m_deleteNoteReplies.removeOne(reply);
|
m_deleteNoteReplies.removeOne(reply);
|
||||||
}
|
}
|
||||||
|
@ -510,7 +461,7 @@ void NotesApi::sslError(QNetworkReply *reply, const QList<QSslError> &errors) {
|
||||||
for (int i = 0; i < errors.size(); ++i) {
|
for (int i = 0; i < errors.size(); ++i) {
|
||||||
qDebug() << errors[i].errorString();
|
qDebug() << errors[i].errorString();
|
||||||
}
|
}
|
||||||
emit error(SslHandshakeError);
|
emit noteError(SslHandshakeError);
|
||||||
}
|
}
|
||||||
|
|
||||||
QUrl NotesApi::apiEndpointUrl(const QString endpoint) const {
|
QUrl NotesApi::apiEndpointUrl(const QString endpoint) const {
|
||||||
|
@ -640,7 +591,7 @@ void NotesApi::updateApiNotes(const QJsonArray &json) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void NotesApi::updateApiNote(const QJsonObject &json) {
|
void NotesApi::updateApiNote(const QJsonObject &json) {
|
||||||
Note note(json);
|
int id = json["id"].toInt(-1);
|
||||||
if (!note.error())
|
if (id >= 0)
|
||||||
emit noteUpdated(note);
|
emit noteUpdated(id, json);
|
||||||
}
|
}
|
||||||
|
|
|
@ -138,20 +138,20 @@ public:
|
||||||
AuthenticationError
|
AuthenticationError
|
||||||
};
|
};
|
||||||
Q_ENUM(ErrorCodes)
|
Q_ENUM(ErrorCodes)
|
||||||
Q_INVOKABLE const QString errorMessage(ErrorCodes error) const;
|
Q_INVOKABLE const QString errorMessage(int error) const;
|
||||||
|
|
||||||
QString account() const { return m_account; }
|
QString account() const { return m_account; }
|
||||||
void setAccount(const QString& account);
|
void setAccount(const QString& account);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
Q_INVOKABLE void getAllNotes(const QStringList exclude = QStringList());
|
Q_INVOKABLE void getAllNotes(const QStringList& exclude = QStringList());
|
||||||
void getAllNotes(Note::NoteField exclude);
|
//void getAllNotes(Note::NoteField exclude);
|
||||||
Q_INVOKABLE void getNote(const int id, const QStringList exclude = QStringList());
|
Q_INVOKABLE void getNote(const int id, const QStringList& exclude = QStringList());
|
||||||
void getNote(const int id, Note::NoteField exclude);
|
//void getNote(const int id, Note::NoteField exclude);
|
||||||
Q_INVOKABLE void createNote(const QVariantMap& note);
|
Q_INVOKABLE void createNote(const QJsonObject& note);
|
||||||
void createNote(const Note& note);
|
//void createNote(const Note& note);
|
||||||
Q_INVOKABLE void updateNote(const int id, const QVariantMap& note);
|
Q_INVOKABLE void updateNote(const int id, const QJsonObject& note);
|
||||||
void updateNote(const Note& note);
|
//void updateNote(const Note& note);
|
||||||
Q_INVOKABLE void deleteNote(const int id);
|
Q_INVOKABLE void deleteNote(const int id);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
@ -182,7 +182,6 @@ signals:
|
||||||
|
|
||||||
void loginStatusChanged(LoginStatus status);
|
void loginStatusChanged(LoginStatus status);
|
||||||
void loginUrlChanged(QUrl url);
|
void loginUrlChanged(QUrl url);
|
||||||
void error(ErrorCodes error);
|
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
|
@ -196,7 +195,6 @@ private slots:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString m_account;
|
QString m_account;
|
||||||
static const QByteArray noteApiData(const Note& note);
|
|
||||||
|
|
||||||
QUrl m_url;
|
QUrl m_url;
|
||||||
QNetworkAccessManager m_manager;
|
QNetworkAccessManager m_manager;
|
||||||
|
|
|
@ -2,8 +2,7 @@
|
||||||
#define NOTESINTERFACE_H
|
#define NOTESINTERFACE_H
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <QJsonObject>
|
||||||
#include "note.h"
|
|
||||||
|
|
||||||
class NotesInterface : public QObject
|
class NotesInterface : public QObject
|
||||||
{
|
{
|
||||||
|
@ -18,22 +17,24 @@ public:
|
||||||
|
|
||||||
virtual QString account() const = 0;
|
virtual QString account() const = 0;
|
||||||
virtual void setAccount(const QString& account) = 0;
|
virtual void setAccount(const QString& account) = 0;
|
||||||
|
Q_INVOKABLE virtual const QString errorMessage(int error) const = 0;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
Q_INVOKABLE virtual void getAllNotes(const QStringList exclude = QStringList()) = 0;
|
Q_INVOKABLE virtual void getAllNotes(const QStringList& exclude = QStringList()) = 0;
|
||||||
virtual void getAllNotes(Note::NoteField exclude) = 0;
|
//virtual void getAllNotes(Note::NoteField exclude) = 0;
|
||||||
Q_INVOKABLE virtual void getNote(const int id, const QStringList exclude = QStringList()) = 0;
|
Q_INVOKABLE virtual void getNote(const int id, const QStringList& exclude = QStringList()) = 0;
|
||||||
virtual void getNote(const int id, Note::NoteField) = 0;
|
//virtual void getNote(const int id, Note::NoteField) = 0;
|
||||||
Q_INVOKABLE virtual void createNote(const QVariantMap& note) = 0;
|
Q_INVOKABLE virtual void createNote(const QJsonObject& note) = 0;
|
||||||
virtual void createNote(const Note& note) = 0;
|
//virtual void createNote(const Note& note) = 0;
|
||||||
Q_INVOKABLE virtual void updateNote(const int id, const QVariantMap& note) = 0;
|
Q_INVOKABLE virtual void updateNote(const int id, const QJsonObject& note) = 0;
|
||||||
virtual void updateNote(const Note& note) = 0;
|
//virtual void updateNote(const Note& note) = 0;
|
||||||
Q_INVOKABLE virtual void deleteNote(const int id) = 0;
|
Q_INVOKABLE virtual void deleteNote(const int id) = 0;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void accountChanged(const QString& account);
|
void accountChanged(const QString& account);
|
||||||
void noteUpdated(const QVariantMap& note);
|
void noteError(int error);
|
||||||
void noteUpdated(const Note& note);
|
void noteUpdated(const int id, const QJsonObject& note);
|
||||||
|
//void noteUpdated(const Note& note);
|
||||||
void noteDeleted(const int id);
|
void noteDeleted(const int id);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -70,16 +70,17 @@ QList<int> NotesModel::ids() const {
|
||||||
return ids;
|
return ids;
|
||||||
}
|
}
|
||||||
|
|
||||||
int NotesModel::insertNote(const Note ¬e) {
|
int NotesModel::insertNote(const int id, const QJsonObject& note) {
|
||||||
qDebug() << "Inserting note: " << note.id();
|
qDebug() << "Inserting note: " << id;
|
||||||
int position = m_notes.indexOf(note);
|
Note tmpNote(note);
|
||||||
|
int position = m_notes.indexOf(tmpNote);
|
||||||
if (position >= 0) {
|
if (position >= 0) {
|
||||||
if (m_notes.at(position).equal(note)) {
|
if (m_notes.at(position).equal(tmpNote)) {
|
||||||
qDebug() << "Note already present and unchanged.";
|
qDebug() << "Note already present and unchanged.";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
qDebug() << "Note already present, updating it.";
|
qDebug() << "Note already present, updating it.";
|
||||||
m_notes.replace(position, note);
|
m_notes.replace(position, tmpNote);
|
||||||
emit dataChanged(index(position), index(position));
|
emit dataChanged(index(position), index(position));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -87,16 +88,17 @@ int NotesModel::insertNote(const Note ¬e) {
|
||||||
qDebug() << "New note, adding it";
|
qDebug() << "New note, adding it";
|
||||||
position = m_notes.size();
|
position = m_notes.size();
|
||||||
beginInsertRows(QModelIndex(), position, position);
|
beginInsertRows(QModelIndex(), position, position);
|
||||||
m_notes.append(note);
|
m_notes.append(tmpNote);
|
||||||
endInsertRows();
|
endInsertRows();
|
||||||
emit dataChanged(index(position), index(position));
|
emit dataChanged(index(position), index(position));
|
||||||
}
|
}
|
||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NotesModel::removeNote(const Note ¬e) {
|
bool NotesModel::removeNote(const QJsonObject ¬e) {
|
||||||
qDebug() << "Removing note: " << note.id();
|
Note tmpNote(note);
|
||||||
int position = m_notes.indexOf(note);
|
qDebug() << "Removing note: " << tmpNote.id();
|
||||||
|
int position = m_notes.indexOf(tmpNote);
|
||||||
if (position >= 0 && position < m_notes.size()) {
|
if (position >= 0 && position < m_notes.size()) {
|
||||||
beginRemoveRows(QModelIndex(), position, position);
|
beginRemoveRows(QModelIndex(), position, position);
|
||||||
m_notes.removeAt(position);
|
m_notes.removeAt(position);
|
||||||
|
@ -108,8 +110,7 @@ bool NotesModel::removeNote(const Note ¬e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NotesModel::removeNote(int id) {
|
bool NotesModel::removeNote(int id) {
|
||||||
qDebug() << "Removing note: " << id;
|
return removeNote(QJsonObject{ {"id", id} } );
|
||||||
return removeNote(Note(QJsonObject{ {"id", id} } ));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NotesModel::clear() {
|
void NotesModel::clear() {
|
||||||
|
|
|
@ -66,8 +66,8 @@ public:
|
||||||
virtual bool setItemData(const QModelIndex &index, const QMap<int, QVariant> &roles);
|
virtual bool setItemData(const QModelIndex &index, const QMap<int, QVariant> &roles);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
int insertNote(const Note ¬e);
|
int insertNote(const int id, const QJsonObject& note);
|
||||||
bool removeNote(const Note ¬e);
|
bool removeNote(const QJsonObject& note);
|
||||||
bool removeNote(int id);
|
bool removeNote(int id);
|
||||||
Q_INVOKABLE void clear();
|
Q_INVOKABLE void clear();
|
||||||
Q_INVOKABLE QList<int> ids() const;
|
Q_INVOKABLE QList<int> ids() const;
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#include "notesstore.h"
|
#include "notesstore.h"
|
||||||
|
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QDateTime>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
const QString NotesStore::m_suffix = "json";
|
const QString NotesStore::m_suffix = "json";
|
||||||
|
@ -26,61 +28,93 @@ void NotesStore::setAccount(const QString& account) {
|
||||||
qDebug() << "Setting account: " << account;
|
qDebug() << "Setting account: " << account;
|
||||||
if (account != m_dir.path()) {
|
if (account != m_dir.path()) {
|
||||||
if (m_dir != QDir(QStandardPaths::writableLocation(QStandardPaths::DataLocation))) {
|
if (m_dir != QDir(QStandardPaths::writableLocation(QStandardPaths::DataLocation))) {
|
||||||
m_dir.cdUp();
|
m_dir = QDir(QStandardPaths::writableLocation(QStandardPaths::DataLocation));
|
||||||
}
|
}
|
||||||
if (!account.isEmpty()) {
|
if (!account.isEmpty()) {
|
||||||
m_dir.setPath(account);
|
m_dir.setPath(account);
|
||||||
if (!m_dir.mkpath(".")) {
|
if (m_dir.mkpath(".")) {
|
||||||
|
emit accountChanged(m_dir.path());
|
||||||
|
}
|
||||||
|
else {
|
||||||
qDebug() << "Failed to create or already present: " << m_dir.path();
|
qDebug() << "Failed to create or already present: " << m_dir.path();
|
||||||
|
m_dir = QDir(QStandardPaths::writableLocation(QStandardPaths::DataLocation));
|
||||||
|
emit noteError(DirCannotWriteError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//qDebug() << account << m_dir.path();
|
//qDebug() << account << m_dir.path();
|
||||||
emit accountChanged(m_dir.path());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NotesStore::getAllNotes(const QStringList exclude) {
|
const QString NotesStore::errorMessage(int error) const {
|
||||||
getAllNotes(Note::noteFieldsFromStringList(exclude));
|
QString message;
|
||||||
|
switch (error) {
|
||||||
|
case NoError:
|
||||||
|
message = tr("No error");
|
||||||
|
break;
|
||||||
|
case FileNotFoundError:
|
||||||
|
message = tr("File not found");
|
||||||
|
break;
|
||||||
|
case FileCannotReadError:
|
||||||
|
message = tr("Cannot read from the file");
|
||||||
|
break;
|
||||||
|
case FileCannotWriteError:
|
||||||
|
message = tr("Cannot write to the file");
|
||||||
|
break;
|
||||||
|
case DirNotFoundError:
|
||||||
|
message = tr("Directory not found");
|
||||||
|
break;
|
||||||
|
case DirCannotReadError:
|
||||||
|
message = tr("Cannot read from directory");
|
||||||
|
break;
|
||||||
|
case DirCannotWriteError:
|
||||||
|
message = tr("Cannot create or write to directory");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
message = tr("Unknown error");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NotesStore::getAllNotes(Note::NoteField exclude) {
|
void NotesStore::getAllNotes(const QStringList& exclude) {
|
||||||
qDebug() << "Getting all notes";
|
qDebug() << "Getting all notes";
|
||||||
QFileInfoList files = m_dir.entryInfoList();
|
if (m_dir.exists()) {
|
||||||
for (int i = 0; i < files.size(); ++i) {
|
QFileInfoList files = m_dir.entryInfoList();
|
||||||
bool ok;
|
for (int i = 0; i < files.size(); ++i) {
|
||||||
int id = files[i].baseName().toInt(&ok);
|
bool ok;
|
||||||
if (ok) {
|
int id = files[i].baseName().toInt(&ok);
|
||||||
getNote(id, exclude);
|
if (ok) {
|
||||||
|
getNote(id, exclude);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
else {
|
||||||
|
emit noteError(DirCannotReadError);
|
||||||
void NotesStore::getNote(const int id, const QStringList exclude) {
|
|
||||||
getNote(id, Note::noteFieldsFromStringList(exclude));
|
|
||||||
}
|
|
||||||
|
|
||||||
void NotesStore::getNote(const int id, Note::NoteField exclude) {
|
|
||||||
qDebug() << "Getting note: " << id;
|
|
||||||
if (id >= 0) {
|
|
||||||
Note note = readNoteFile(id, exclude);
|
|
||||||
if (note.isValid())
|
|
||||||
emit noteUpdated(note);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NotesStore::createNote(const QVariantMap ¬e) {
|
void NotesStore::getNote(const int id, const QStringList& exclude) {
|
||||||
createNote(Note(QJsonObject::fromVariantMap(note)));
|
qDebug() << "Getting note: " << id;
|
||||||
|
if (id >= 0) {
|
||||||
|
QJsonObject note = readNoteFile(id, exclude);
|
||||||
|
if (note.value("id").toInt(-1) >= 0)
|
||||||
|
emit noteUpdated(id, note);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
qDebug() << "Skipping, invalid ID";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NotesStore::createNote(const Note& note) {
|
void NotesStore::createNote(const QJsonObject& note) {
|
||||||
qDebug() << "Creating note: " << note.id();
|
int id = note.value("id").toInt(-1);
|
||||||
if (!note.isValid()) {
|
qDebug() << "Creating note: " << id;
|
||||||
|
if (id < 0) {
|
||||||
// TODO probably crate files with an '.json.<NUMBER>.new' extension
|
// TODO probably crate files with an '.json.<NUMBER>.new' extension
|
||||||
qDebug() << "Creating notes without the server API is not supported yet!";
|
qDebug() << "Creating notes without the server API is not supported yet!";
|
||||||
}
|
}
|
||||||
else if (!noteFileExists(note.id())) {
|
else if (!noteFileExists(id)) {
|
||||||
if (writeNoteFile(note)) {
|
if (writeNoteFile(id, note)) {
|
||||||
emit noteUpdated(note);
|
emit noteUpdated(id, note);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -88,21 +122,33 @@ void NotesStore::createNote(const Note& note) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NotesStore::updateNote(const int id, const QVariantMap ¬e) {
|
void NotesStore::updateNote(const int id, const QJsonObject& note) {
|
||||||
Note newNote(QJsonObject::fromVariantMap(note));
|
qDebug() << "Updating note: " << id;
|
||||||
newNote.setId(id);
|
if (id >= 0) {
|
||||||
updateNote(newNote);
|
QJsonObject tmpNote = readNoteFile(id);
|
||||||
}
|
if (note != tmpNote) {
|
||||||
|
if (note.value("modified").toInt() >= tmpNote.value("modified").toInt() || note.value("modified").toInt() == 0) {
|
||||||
void NotesStore::updateNote(const Note& note) {
|
QStringList fields = note.keys();
|
||||||
qDebug() << "Updating note: " << note.id();
|
for (int i = 0; i < fields.size(); ++i) {
|
||||||
if (note.isValid()) {
|
tmpNote[fields[i]] = note[fields[i]];
|
||||||
Note file = readNoteFile(note.id());
|
}
|
||||||
if (!file.equal(note) && note > file) {
|
if (tmpNote.value("modified").toInt() == 0) {
|
||||||
if (writeNoteFile(note)) {
|
tmpNote["modified"] = QDateTime::currentDateTime().toMSecsSinceEpoch() / 1000;
|
||||||
emit noteUpdated(note);
|
}
|
||||||
|
if (writeNoteFile(id, tmpNote)) {
|
||||||
|
emit noteUpdated(id, tmpNote);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
qDebug() << "Skipping, note is older" << note.value("modified") << tmpNote.value("modified");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
qDebug() << "Skipping, note is equal";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
qDebug() << "Skipping, invalid ID";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,7 +164,7 @@ bool NotesStore::noteFileExists(const int id) const {
|
||||||
return fileinfo.exists();
|
return fileinfo.exists();
|
||||||
}
|
}
|
||||||
|
|
||||||
Note NotesStore::readNoteFile(const int id, Note::NoteField exclude) const {
|
QJsonObject NotesStore::readNoteFile(const int id, const QStringList& exclude) {
|
||||||
QJsonObject json;
|
QJsonObject json;
|
||||||
QFileInfo fileinfo(m_dir, QString("%1.%2").arg(id).arg(m_suffix));
|
QFileInfo fileinfo(m_dir, QString("%1.%2").arg(id).arg(m_suffix));
|
||||||
QFile file(fileinfo.filePath());
|
QFile file(fileinfo.filePath());
|
||||||
|
@ -127,36 +173,40 @@ Note NotesStore::readNoteFile(const int id, Note::NoteField exclude) const {
|
||||||
QByteArray data = file.readAll();
|
QByteArray data = file.readAll();
|
||||||
json = QJsonDocument::fromJson(data).object();
|
json = QJsonDocument::fromJson(data).object();
|
||||||
file.close();
|
file.close();
|
||||||
QList<Note::NoteField> noteFields = Note::noteFields();
|
for (int i = 0; i < exclude.size(); ++i) {
|
||||||
QFlags<Note::NoteField> flags(exclude);
|
json.remove(exclude[i]);
|
||||||
for (int i = 0; i < noteFields.size(); ++i) {
|
|
||||||
if (flags.testFlag(noteFields[i])) {
|
|
||||||
json.remove(Note::noteFieldName(noteFields[i]));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
emit noteError(FileCannotReadError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//emit noteError(FileNotFoundError);
|
||||||
}
|
}
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NotesStore::writeNoteFile(const Note ¬e) const {
|
bool NotesStore::writeNoteFile(const int id, const QJsonObject& note) {
|
||||||
bool success = false;
|
bool success = false;
|
||||||
if (!account().isEmpty()) {
|
if (!account().isEmpty()) {
|
||||||
QJsonDocument json = note.toJsonDocument();
|
QFileInfo fileinfo(m_dir, QString("%1.%2").arg(id).arg(m_suffix));
|
||||||
QFileInfo fileinfo(m_dir, QString("%1.%2").arg(note.id()).arg(m_suffix));
|
|
||||||
QFile file(fileinfo.filePath());
|
QFile file(fileinfo.filePath());
|
||||||
if (file.open(QIODevice::ReadWrite | QIODevice::Truncate | QIODevice::Text)) {
|
if (file.open(QIODevice::ReadWrite | QIODevice::Truncate | QIODevice::Text)) {
|
||||||
QByteArray data = json.toJson();
|
QByteArray data = QJsonDocument(note).toJson();
|
||||||
if (file.write(data) == data.size()) {
|
if (file.write(data) == data.size()) {
|
||||||
success = true;
|
success = true;
|
||||||
}
|
}
|
||||||
file.close();
|
file.close();
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
emit noteError(FileCannotWriteError);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NotesStore::removeNoteFile(const int id) const {
|
bool NotesStore::removeNoteFile(const int id) {
|
||||||
bool success = false;
|
bool success = false;
|
||||||
if (!account().isEmpty()) {
|
if (!account().isEmpty()) {
|
||||||
QFileInfo fileinfo(m_dir, QString("%1.%2").arg(id).arg(m_suffix));
|
QFileInfo fileinfo(m_dir, QString("%1.%2").arg(id).arg(m_suffix));
|
||||||
|
@ -165,6 +215,12 @@ bool NotesStore::removeNoteFile(const int id) const {
|
||||||
if (file.remove()) {
|
if (file.remove()) {
|
||||||
success = true;
|
success = true;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
emit noteError(FileCannotWriteError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
emit noteError(FileNotFoundError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return success;
|
return success;
|
||||||
|
|
|
@ -20,15 +20,27 @@ public:
|
||||||
QString account() const;
|
QString account() const;
|
||||||
void setAccount(const QString& account);
|
void setAccount(const QString& account);
|
||||||
|
|
||||||
|
enum ErrorCodes {
|
||||||
|
NoError,
|
||||||
|
FileNotFoundError,
|
||||||
|
FileCannotReadError,
|
||||||
|
FileCannotWriteError,
|
||||||
|
DirNotFoundError,
|
||||||
|
DirCannotReadError,
|
||||||
|
DirCannotWriteError
|
||||||
|
};
|
||||||
|
Q_ENUM(ErrorCodes)
|
||||||
|
Q_INVOKABLE const QString errorMessage(int error) const;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
Q_INVOKABLE void getAllNotes(const QStringList exclude = QStringList());
|
Q_INVOKABLE void getAllNotes(const QStringList& exclude = QStringList());
|
||||||
void getAllNotes(Note::NoteField exclude);
|
//void getAllNotes(Note::NoteField exclude);
|
||||||
Q_INVOKABLE void getNote(const int id, const QStringList exclude = QStringList());
|
Q_INVOKABLE void getNote(const int id, const QStringList& exclude = QStringList());
|
||||||
void getNote(const int id, Note::NoteField exclude);
|
//void getNote(const int id, Note::NoteField exclude);
|
||||||
Q_INVOKABLE void createNote(const QVariantMap& note);
|
Q_INVOKABLE void createNote(const QJsonObject& note);
|
||||||
void createNote(const Note& note);
|
//void createNote(const Note& note);
|
||||||
Q_INVOKABLE void updateNote(const int id, const QVariantMap& note);
|
Q_INVOKABLE void updateNote(const int id, const QJsonObject& note);
|
||||||
void updateNote(const Note& note);
|
//void updateNote(const Note& note);
|
||||||
Q_INVOKABLE void deleteNote(const int id);
|
Q_INVOKABLE void deleteNote(const int id);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -36,9 +48,9 @@ private:
|
||||||
const static QString m_suffix;
|
const static QString m_suffix;
|
||||||
|
|
||||||
bool noteFileExists(const int id) const;
|
bool noteFileExists(const int id) const;
|
||||||
Note readNoteFile(const int id, Note::NoteField exclude = Note::None) const;
|
QJsonObject readNoteFile(const int id, const QStringList& exclude = QStringList());
|
||||||
bool writeNoteFile(const Note& note) const;
|
bool writeNoteFile(const int id, const QJsonObject& note);
|
||||||
bool removeNoteFile(const int id) const;
|
bool removeNoteFile(const int id);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // NOTESSTORE_H
|
#endif // NOTESSTORE_H
|
||||||
|
|
|
@ -274,6 +274,10 @@
|
||||||
<source>Unknown error</source>
|
<source>Unknown error</source>
|
||||||
<translation>Unbekannter Fehler</translation>
|
<translation>Unbekannter Fehler</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>No error</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>NotesPage</name>
|
<name>NotesPage</name>
|
||||||
|
@ -354,6 +358,41 @@
|
||||||
<translation>Ein Fehler ist aufgetreten</translation>
|
<translation>Ein Fehler ist aufgetreten</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
|
<context>
|
||||||
|
<name>NotesStore</name>
|
||||||
|
<message>
|
||||||
|
<source>File not found</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Cannot read from the file</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Cannot write to the file</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Directory not found</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Cannot read from directory</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Cannot create or write to directory</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Unknown error</source>
|
||||||
|
<translation type="unfinished">Unbekannter Fehler</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>No error</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>SettingsPage</name>
|
<name>SettingsPage</name>
|
||||||
<message>
|
<message>
|
||||||
|
@ -686,8 +725,12 @@ You can also use other markdown syntax inside them.</source>
|
||||||
<translation>Synchronisiert</translation>
|
<translation>Synchronisiert</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Error</source>
|
<source>API error</source>
|
||||||
<translation>Fehler</translation>
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>File error</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
</TS>
|
</TS>
|
||||||
|
|
|
@ -274,6 +274,10 @@
|
||||||
<source>Unknown error</source>
|
<source>Unknown error</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>No error</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>NotesPage</name>
|
<name>NotesPage</name>
|
||||||
|
@ -354,6 +358,41 @@
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
|
<context>
|
||||||
|
<name>NotesStore</name>
|
||||||
|
<message>
|
||||||
|
<source>File not found</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Cannot read from the file</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Cannot write to the file</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Directory not found</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Cannot read from directory</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Cannot create or write to directory</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Unknown error</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>No error</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>SettingsPage</name>
|
<name>SettingsPage</name>
|
||||||
<message>
|
<message>
|
||||||
|
@ -686,7 +725,11 @@ You can also use other markdown syntax inside them.</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Error</source>
|
<source>API error</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>File error</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
|
|
|
@ -245,12 +245,12 @@
|
||||||
<context>
|
<context>
|
||||||
<name>Note</name>
|
<name>Note</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/note.cpp" line="335"/>
|
<location filename="../src/note.cpp" line="357"/>
|
||||||
<source>Today</source>
|
<source>Today</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/note.cpp" line="337"/>
|
<location filename="../src/note.cpp" line="359"/>
|
||||||
<source>Yesterday</source>
|
<source>Yesterday</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
@ -311,27 +311,32 @@
|
||||||
<context>
|
<context>
|
||||||
<name>NotesApi</name>
|
<name>NotesApi</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/notesapi.cpp" line="368"/>
|
<location filename="../src/notesapi.cpp" line="311"/>
|
||||||
|
<source>No error</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../src/notesapi.cpp" line="314"/>
|
||||||
<source>No network connection available</source>
|
<source>No network connection available</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/notesapi.cpp" line="371"/>
|
<location filename="../src/notesapi.cpp" line="317"/>
|
||||||
<source>Failed to communicate with the Nextcloud server</source>
|
<source>Failed to communicate with the Nextcloud server</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/notesapi.cpp" line="374"/>
|
<location filename="../src/notesapi.cpp" line="320"/>
|
||||||
<source>An error occured while establishing an encrypted connection</source>
|
<source>An error occured while establishing an encrypted connection</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/notesapi.cpp" line="377"/>
|
<location filename="../src/notesapi.cpp" line="323"/>
|
||||||
<source>Could not authenticate to the Nextcloud instance</source>
|
<source>Could not authenticate to the Nextcloud instance</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/notesapi.cpp" line="380"/>
|
<location filename="../src/notesapi.cpp" line="326"/>
|
||||||
<source>Unknown error</source>
|
<source>Unknown error</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
@ -374,66 +379,109 @@
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../qml/pages/NotesPage.qml" line="188"/>
|
<location filename="../qml/pages/NotesPage.qml" line="189"/>
|
||||||
<source>Modified</source>
|
<source>Modified</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../qml/pages/NotesPage.qml" line="191"/>
|
<location filename="../qml/pages/NotesPage.qml" line="192"/>
|
||||||
<source>Delete</source>
|
<source>Delete</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../qml/pages/NotesPage.qml" line="193"/>
|
<location filename="../qml/pages/NotesPage.qml" line="194"/>
|
||||||
<source>Deleting note</source>
|
<source>Deleting note</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../qml/pages/NotesPage.qml" line="224"/>
|
<location filename="../qml/pages/NotesPage.qml" line="225"/>
|
||||||
<source>Loading notes...</source>
|
<source>Loading notes...</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../qml/pages/NotesPage.qml" line="230"/>
|
<location filename="../qml/pages/NotesPage.qml" line="231"/>
|
||||||
<source>No account yet</source>
|
<source>No account yet</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../qml/pages/NotesPage.qml" line="231"/>
|
<location filename="../qml/pages/NotesPage.qml" line="232"/>
|
||||||
<source>Got to the settings to add an account</source>
|
<source>Got to the settings to add an account</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../qml/pages/NotesPage.qml" line="237"/>
|
<location filename="../qml/pages/NotesPage.qml" line="238"/>
|
||||||
<source>No notes yet</source>
|
<source>No notes yet</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../qml/pages/NotesPage.qml" line="238"/>
|
<location filename="../qml/pages/NotesPage.qml" line="239"/>
|
||||||
<source>Pull down to add a note</source>
|
<source>Pull down to add a note</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../qml/pages/NotesPage.qml" line="244"/>
|
<location filename="../qml/pages/NotesPage.qml" line="245"/>
|
||||||
<source>No result</source>
|
<source>No result</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../qml/pages/NotesPage.qml" line="245"/>
|
<location filename="../qml/pages/NotesPage.qml" line="246"/>
|
||||||
<source>Try another query</source>
|
<source>Try another query</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../qml/pages/NotesPage.qml" line="251"/>
|
<location filename="../qml/pages/NotesPage.qml" line="252"/>
|
||||||
<source>An error occurred</source>
|
<source>An error occurred</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../qml/pages/NotesPage.qml" line="262"/>
|
<location filename="../qml/pages/NotesPage.qml" line="263"/>
|
||||||
<source>Open the settings to configure your Nextcloud accounts</source>
|
<source>Open the settings to configure your Nextcloud accounts</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
|
<context>
|
||||||
|
<name>NotesStore</name>
|
||||||
|
<message>
|
||||||
|
<location filename="../src/notesstore.cpp" line="52"/>
|
||||||
|
<source>No error</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../src/notesstore.cpp" line="55"/>
|
||||||
|
<source>File not found</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../src/notesstore.cpp" line="58"/>
|
||||||
|
<source>Cannot read from the file</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../src/notesstore.cpp" line="61"/>
|
||||||
|
<source>Cannot write to the file</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../src/notesstore.cpp" line="64"/>
|
||||||
|
<source>Directory not found</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../src/notesstore.cpp" line="67"/>
|
||||||
|
<source>Cannot read from directory</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../src/notesstore.cpp" line="70"/>
|
||||||
|
<source>Cannot create or write to directory</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../src/notesstore.cpp" line="73"/>
|
||||||
|
<source>Unknown error</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>SettingsPage</name>
|
<name>SettingsPage</name>
|
||||||
<message>
|
<message>
|
||||||
|
@ -844,9 +892,14 @@ You can also use other markdown syntax inside them.</source>
|
||||||
<source>Synced</source>
|
<source>Synced</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../qml/harbour-nextcloudnotes.qml" line="141"/>
|
||||||
|
<source>API error</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../qml/harbour-nextcloudnotes.qml" line="134"/>
|
<location filename="../qml/harbour-nextcloudnotes.qml" line="134"/>
|
||||||
<source>Error</source>
|
<source>File error</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
|
|
Loading…
Reference in a new issue