NotesModel now directly uses files as backend
This commit is contained in:
parent
964011847c
commit
09c5a68b2f
12 changed files with 160 additions and 710 deletions
|
@ -18,14 +18,12 @@ DEFINES += APP_VERSION=\\\"$$VERSION\\\"
|
|||
|
||||
HEADERS += src/note.h \
|
||||
src/notesapi.h \
|
||||
src/notesmodel.h \
|
||||
src/notesstore.h
|
||||
src/notesmodel.h
|
||||
|
||||
SOURCES += src/harbour-nextcloudnotes.cpp \
|
||||
src/note.cpp \
|
||||
src/notesapi.cpp \
|
||||
src/notesmodel.cpp \
|
||||
src/notesstore.cpp
|
||||
src/notesmodel.cpp
|
||||
|
||||
DISTFILES += qml/harbour-nextcloudnotes.qml \
|
||||
qml/cover/CoverPage.qml \
|
||||
|
|
|
@ -54,10 +54,8 @@ ApplicationWindow
|
|||
property bool useCapitalX: value("useCapitalX", false, Boolean)
|
||||
|
||||
onCurrentAccountChanged: {
|
||||
notesProxyModel.sourceModel.clear()
|
||||
account.path = "/apps/harbour-nextcloudnotes/accounts/" + currentAccount
|
||||
notesStore.account = currentAccount
|
||||
notesModel.getAllNotes()
|
||||
notesModel.account = currentAccount
|
||||
}
|
||||
|
||||
onSortByChanged: {
|
||||
|
@ -147,7 +145,7 @@ ApplicationWindow
|
|||
running: interval > 0 && notesApi.networkAccessible && appWindow.visible
|
||||
triggeredOnStart: true
|
||||
onTriggered: {
|
||||
notesModel.getAllNotes()
|
||||
notesApi.getAllNotes()
|
||||
}
|
||||
onIntervalChanged: {
|
||||
if (interval > 0) {
|
||||
|
@ -156,19 +154,6 @@ 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 {
|
||||
target: notesApi
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
#include <QObject>
|
||||
#include "note.h"
|
||||
#include "notesapi.h"
|
||||
#include "notesstore.h"
|
||||
#include "notesmodel.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
|
@ -27,10 +26,10 @@ int main(int argc, char *argv[])
|
|||
notesProxyModel->setFilterRole(NotesModel::ContentRole);
|
||||
notesProxyModel->setSourceModel(notesModel);
|
||||
|
||||
NotesStore* notesStore = new NotesStore;
|
||||
//NotesStore* notesStore = new NotesStore;
|
||||
NotesApi* notesApi = new NotesApi;
|
||||
notesModel->setNotesApi(notesApi);
|
||||
notesModel->setNotesStore(notesStore);
|
||||
//notesModel->setNotesStore(notesStore);
|
||||
|
||||
QQuickView* view = SailfishApp::createView();
|
||||
#ifdef QT_DEBUG
|
||||
|
@ -40,7 +39,7 @@ int main(int argc, char *argv[])
|
|||
#endif
|
||||
view->rootContext()->setContextProperty("notesModel", notesModel);
|
||||
view->rootContext()->setContextProperty("notesProxyModel", notesProxyModel);
|
||||
view->rootContext()->setContextProperty("notesStore", notesStore);
|
||||
//view->rootContext()->setContextProperty("notesStore", notesStore);
|
||||
view->rootContext()->setContextProperty("notesApi", notesApi);
|
||||
|
||||
view->setSource(SailfishApp::pathTo("qml/harbour-nextcloudnotes.qml"));
|
||||
|
@ -49,7 +48,7 @@ int main(int argc, char *argv[])
|
|||
int retval = app->exec();
|
||||
|
||||
notesApi->deleteLater();
|
||||
notesStore->deleteLater();
|
||||
//notesStore->deleteLater();
|
||||
notesProxyModel->deleteLater();
|
||||
notesModel->deleteLater();
|
||||
return retval;
|
||||
|
|
|
@ -42,17 +42,6 @@ NotesApi::~NotesApi() {
|
|||
disconnect(&m_manager, SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)), this, SLOT(sslError(QNetworkReply*,QList<QSslError>)));
|
||||
}
|
||||
|
||||
QString NotesApi::account() const {
|
||||
return m_account;
|
||||
}
|
||||
|
||||
void NotesApi::setAccount(const QString &account) {
|
||||
if (account != m_account) {
|
||||
m_account = account;
|
||||
emit accountChanged(account);
|
||||
}
|
||||
}
|
||||
|
||||
const QList<int> NotesApi::noteIds() {
|
||||
return m_syncedNotes.keys();
|
||||
}
|
||||
|
@ -612,19 +601,16 @@ void NotesApi::setLoginStatus(LoginStatus status, bool *changed) {
|
|||
}
|
||||
|
||||
void NotesApi::updateApiNotes(const QJsonArray &json) {
|
||||
QList<int> ids;
|
||||
for (int i = 0; i < json.size(); ++i) {
|
||||
if (json[i].isObject()) {
|
||||
QJsonObject object = json[i].toObject();
|
||||
if (!object.isEmpty()) {
|
||||
updateApiNote(json[i].toObject());
|
||||
ids << object.value("id").toInt(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
m_lastSync = QDateTime::currentDateTime();
|
||||
emit lastSyncChanged(m_lastSync);
|
||||
emit allNotesChanged(ids);
|
||||
}
|
||||
|
||||
void NotesApi::updateApiNote(const QJsonObject &json) {
|
||||
|
|
|
@ -182,11 +182,9 @@ signals:
|
|||
void loginStatusChanged(LoginStatus status);
|
||||
void loginUrlChanged(QUrl url);
|
||||
|
||||
void accountChanged(const QString& account);
|
||||
void allNotesChanged(const QList<int>& ids);
|
||||
void noteCreated(const int id, const QJsonObject& note);
|
||||
void noteUpdated(const int id, const QJsonObject& note);
|
||||
void noteDeleted(const int id);
|
||||
void noteCreated(int id, const QJsonObject& note);
|
||||
void noteUpdated(int id, const QJsonObject& note);
|
||||
void noteDeleted(int id);
|
||||
void noteError(ErrorCodes error);
|
||||
|
||||
private slots:
|
||||
|
@ -199,7 +197,6 @@ private slots:
|
|||
|
||||
private:
|
||||
QUrl m_url;
|
||||
QString m_account;
|
||||
QMap<int, int> m_syncedNotes;
|
||||
QNetworkAccessManager m_manager;
|
||||
QNetworkRequest m_request;
|
||||
|
|
|
@ -72,19 +72,25 @@ const QHash<int, QByteArray> NotesModel::m_roleNames = QHash<int, QByteArray> (
|
|||
{NotesModel::ModifiedStringRole, "modifiedString"},
|
||||
{NotesModel::NoneRole, "none"} } );
|
||||
|
||||
const QString NotesModel::m_fileSuffix = "json";
|
||||
|
||||
NotesModel::NotesModel(QObject *parent) : QAbstractListModel(parent) {
|
||||
mp_notesApi = nullptr;
|
||||
mp_notesStore = nullptr;
|
||||
//m_fileDir.setCurrent(directory);
|
||||
m_fileDir.setPath("");
|
||||
m_fileDir.setFilter(QDir::Files);
|
||||
m_fileDir.setFilter(QDir::Files | QDir::NoDotAndDotDot);
|
||||
m_fileDir.setSorting(QDir::Name | QDir::DirsLast);
|
||||
m_fileDir.setNameFilters( { "*." + m_fileSuffix } );
|
||||
}
|
||||
|
||||
NotesModel::~NotesModel() {
|
||||
/*QMapIterator<int, QFile> i(m_files);
|
||||
while (i.hasNext()) {
|
||||
i.next();
|
||||
m_files.take(i.key()).close();
|
||||
i.toFront();
|
||||
}*/
|
||||
setNotesApi(nullptr);
|
||||
setNotesStore(nullptr);
|
||||
clear();
|
||||
}
|
||||
|
||||
void NotesModel::setNotesApi(NotesApi *notesApi) {
|
||||
|
@ -98,31 +104,13 @@ void NotesModel::setNotesApi(NotesApi *notesApi) {
|
|||
mp_notesApi = notesApi;
|
||||
if (mp_notesApi) {
|
||||
// connect stuff
|
||||
connect(mp_notesApi, SIGNAL(accountChanged(QString)), this, SIGNAL(accountChanged(QString)));
|
||||
//connect(mp_notesApi, SIGNAL(accountChanged(QString)), this, SIGNAL(accountChanged(QString)));
|
||||
connect(mp_notesApi, SIGNAL(noteCreated(int,QJsonObject)), this, SLOT(insert(int,QJsonObject)));
|
||||
connect(mp_notesApi, SIGNAL(noteUpdated(int,QJsonObject)), this, SLOT(update(int,QJsonObject)));
|
||||
connect(mp_notesApi, SIGNAL(noteDeleted(int)), this, SLOT(remove(int)));
|
||||
}
|
||||
}
|
||||
|
||||
void NotesModel::setNotesStore(NotesStore *notesStore) {
|
||||
if (mp_notesStore) {
|
||||
// disconnect stuff
|
||||
disconnect(mp_notesStore, SIGNAL(accountChanged(QString)), this, SIGNAL(accountChanged(QString)));
|
||||
disconnect(mp_notesStore, SIGNAL(noteCreated(int,QJsonObject)), this, SLOT(insert(int,QJsonObject)));
|
||||
disconnect(mp_notesStore, SIGNAL(noteUpdated(int,QJsonObject)), this, SLOT(update(int,QJsonObject)));
|
||||
disconnect(mp_notesStore, SIGNAL(noteDeleted(int)), this, SLOT(remove(int)));
|
||||
}
|
||||
mp_notesStore = notesStore;
|
||||
if (mp_notesStore) {
|
||||
// connect stuff
|
||||
connect(mp_notesStore, SIGNAL(accountChanged(QString)), this, SIGNAL(accountChanged(QString)));
|
||||
connect(mp_notesStore, SIGNAL(noteCreated(int,QJsonObject)), this, SLOT(insert(int,QJsonObject)));
|
||||
connect(mp_notesStore, SIGNAL(noteUpdated(int,QJsonObject)), this, SLOT(update(int,QJsonObject)));
|
||||
connect(mp_notesStore, SIGNAL(noteDeleted(int)), this, SLOT(remove(int)));
|
||||
}
|
||||
}
|
||||
|
||||
QString NotesModel::account() const {
|
||||
if (m_fileDir != QDir(QStandardPaths::writableLocation(QStandardPaths::DataLocation))) {
|
||||
return m_fileDir.path();
|
||||
|
@ -132,6 +120,7 @@ QString NotesModel::account() const {
|
|||
|
||||
void NotesModel::setAccount(const QString& account) {
|
||||
qDebug() << "Setting account: " << account;
|
||||
beginRemoveRows(QModelIndex(), 0, rowCount() - 1);
|
||||
if (account != m_fileDir.path()) {
|
||||
if (m_fileDir != QDir(QStandardPaths::writableLocation(QStandardPaths::DataLocation))) {
|
||||
m_fileDir = QDir(QStandardPaths::writableLocation(QStandardPaths::DataLocation));
|
||||
|
@ -139,6 +128,9 @@ void NotesModel::setAccount(const QString& account) {
|
|||
if (!account.isEmpty()) {
|
||||
m_fileDir.setPath(account);
|
||||
if (m_fileDir.mkpath(".")) {
|
||||
m_fileDir.setFilter(QDir::Files | QDir::NoDotAndDotDot);
|
||||
m_fileDir.setSorting(QDir::Name | QDir::DirsLast);
|
||||
m_fileDir.setNameFilters( { "*." + m_fileSuffix } );
|
||||
emit accountChanged(m_fileDir.path());
|
||||
}
|
||||
else {
|
||||
|
@ -149,6 +141,10 @@ void NotesModel::setAccount(const QString& account) {
|
|||
}
|
||||
//qDebug() << account << m_dir.path();
|
||||
}
|
||||
endRemoveRows();
|
||||
beginInsertRows(QModelIndex(), 0, rowCount() - 1);
|
||||
qDebug() << rowCount() << " notes in account";
|
||||
endInsertRows();
|
||||
}
|
||||
/*
|
||||
const QList<int> NotesModel::noteIds() {
|
||||
|
@ -179,8 +175,22 @@ int NotesModel::noteModified(const int id) {
|
|||
return Note::modified(QJsonObject::fromVariantMap(getNoteById(id)));
|
||||
}
|
||||
*/
|
||||
|
||||
int NotesModel::newNotePosition(const int id) const {
|
||||
if (m_fileDir.exists() && !account().isEmpty() && id >= 0) {
|
||||
QStringList fileList = m_fileDir.entryList();
|
||||
qDebug() << fileList;
|
||||
fileList << QString("%1.%2").arg(id).arg(m_fileSuffix);
|
||||
fileList.sort(Qt::CaseInsensitive);
|
||||
qDebug() << fileList;
|
||||
return fileList.indexOf(QString("%1.%2").arg(id).arg(m_fileSuffix));
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
const QVariantMap NotesModel::note(const int id) const {
|
||||
QVariantMap json;
|
||||
if (m_fileDir.exists() && !account().isEmpty() && id >= 0) {
|
||||
QFileInfo fileinfo(m_fileDir, QString("%1.%2").arg(id).arg(m_fileSuffix));
|
||||
QFile file(fileinfo.filePath());
|
||||
if (file.exists()) {
|
||||
|
@ -188,172 +198,111 @@ const QVariantMap NotesModel::note(const int id) const {
|
|||
json = QJsonDocument::fromJson(file.readAll()).object().toVariantMap();
|
||||
file.close();
|
||||
}
|
||||
else {
|
||||
//emit noteError(FileCannotReadError);
|
||||
}
|
||||
}
|
||||
else {
|
||||
//emit noteError(FileNotFoundError);
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
bool NotesModel::setNote(const QVariantMap ¬e, int id) const {
|
||||
bool NotesModel::setNote(const QVariantMap ¬e, int id) {
|
||||
bool ok;
|
||||
if (id < 0) {
|
||||
id = note.value(m_roleNames[IdRole]).toInt(&ok);
|
||||
if (!ok) id = -1;
|
||||
}
|
||||
else {
|
||||
ok = true;
|
||||
}
|
||||
if (id >= 0 && ok) {
|
||||
ok = false;
|
||||
if (m_fileDir.exists() && !account().isEmpty() && id >= 0) {
|
||||
QFileInfo fileinfo(m_fileDir, QString("%1.%2").arg(id).arg(m_fileSuffix));
|
||||
QFile file(fileinfo.filePath());
|
||||
if (file.open(QIODevice::ReadWrite | QIODevice::Truncate | QIODevice::Text)) {
|
||||
if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
||||
QByteArray data = QJsonDocument(QJsonObject::fromVariantMap(note)).toJson();
|
||||
if (file.write(data) == data.size()) {
|
||||
ok = true;
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool NotesModel::getAllNotes(const QStringList &exclude) {
|
||||
bool success = true;
|
||||
if (mp_notesApi)
|
||||
success &= mp_notesApi->getAllNotes(exclude);
|
||||
if (mp_notesStore)
|
||||
success &= mp_notesStore->getAllNotes(exclude);
|
||||
return success;
|
||||
}
|
||||
|
||||
bool NotesModel::getNote(const int id, const QStringList &exclude) {
|
||||
bool success = true;
|
||||
if (mp_notesApi)
|
||||
success &= mp_notesApi->getNote(id, exclude);
|
||||
if (mp_notesStore)
|
||||
success &= mp_notesStore->getNote(id, exclude);
|
||||
return success;
|
||||
}
|
||||
|
||||
bool NotesModel::createNote(const QJsonObject ¬e) {
|
||||
bool success = true;
|
||||
if (mp_notesApi)
|
||||
success &= mp_notesApi->createNote(note);
|
||||
return success;
|
||||
}
|
||||
|
||||
bool NotesModel::updateNote(const int id, const QJsonObject ¬e) {
|
||||
bool success = true;
|
||||
if (mp_notesApi)
|
||||
success &= mp_notesApi->updateNote(id, note);
|
||||
if (mp_notesStore)
|
||||
success &= mp_notesStore->updateNote(id, note);
|
||||
return success;
|
||||
}
|
||||
|
||||
bool NotesModel::deleteNote(const int id) {
|
||||
bool success = true;
|
||||
if (mp_notesApi)
|
||||
success &= mp_notesApi->deleteNote(id);
|
||||
if (mp_notesStore)
|
||||
success &= mp_notesStore->deleteNote(id);
|
||||
return success;
|
||||
if (m_fileDir.exists() && !account().isEmpty() && id >= 0) {
|
||||
QFileInfo fileinfo(m_fileDir, QString("%1.%2").arg(id).arg(m_fileSuffix));
|
||||
QFile file(fileinfo.filePath());
|
||||
if (file.exists()) {
|
||||
if (file.remove()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool NotesModel::syncNotes() {
|
||||
if (mp_notesApi && mp_notesStore) {
|
||||
// TODO
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void NotesModel::insert(const int id, const QJsonObject& note) {
|
||||
void NotesModel::insert(int id, const QJsonObject& json) {
|
||||
if (id < 0) {
|
||||
id = json.value(m_roleNames[IdRole]).toInt(-1);
|
||||
}
|
||||
if (id >= 0) {
|
||||
qDebug() << "Inserting note: " << id;
|
||||
if (m_notes.contains(id)) {
|
||||
if (indexOfNoteById(id) >= 0) {
|
||||
qDebug() << "Note already present";
|
||||
update(id, note);
|
||||
update(id, json);
|
||||
}
|
||||
else {
|
||||
beginInsertRows(QModelIndex(), indexOfNoteById(id), indexOfNoteById(id));
|
||||
m_notes.insert(id, note);
|
||||
qDebug() << "New position: " << newNotePosition(id);
|
||||
beginInsertRows(QModelIndex(), newNotePosition(id), newNotePosition(id));
|
||||
setNote(json.toVariantMap(), id);
|
||||
endInsertRows();
|
||||
//emit noteInserted(id, note);
|
||||
qDebug() << "Note inserted";
|
||||
}
|
||||
if (mp_notesApi && mp_notesStore) {
|
||||
if (sender() == mp_notesApi) {
|
||||
if (!mp_notesStore->noteExists(id)) {
|
||||
mp_notesStore->createNote(note);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NotesModel::update(const int id, const QJsonObject ¬e) {
|
||||
void NotesModel::update(int id, const QJsonObject &json) {
|
||||
if (id < 0) {
|
||||
id = json.value(m_roleNames[IdRole]).toInt(-1);
|
||||
}
|
||||
if (id >= 0) {
|
||||
qDebug() << "Updating note: " << id;
|
||||
if (!m_notes.contains(id)) {
|
||||
if (indexOfNoteById(id) < 0) {
|
||||
qDebug() << "Note is new";
|
||||
insert(id, note);
|
||||
insert(id, json);
|
||||
}
|
||||
else {
|
||||
if (m_notes.value(id) == note) {
|
||||
qDebug() << "Note unchanged";
|
||||
}
|
||||
else {
|
||||
m_notes.insert(id, note);
|
||||
setNote(json.toVariantMap(), id);
|
||||
emit dataChanged(index(indexOfNoteById(id)), index(indexOfNoteById(id)));
|
||||
emit noteUpdated(id, note);
|
||||
qDebug() << "Note changed";
|
||||
}
|
||||
}
|
||||
if (mp_notesApi && mp_notesStore) {
|
||||
if (sender() == mp_notesApi) {
|
||||
if (Note::modified(note) > mp_notesStore->noteModified(id)) {
|
||||
mp_notesStore->updateNote(id, note);
|
||||
}
|
||||
}
|
||||
if (sender() == mp_notesStore) {
|
||||
if (Note::modified(note) > mp_notesApi->noteModified(id) && !mp_notesApi->lastSync().isNull()) {
|
||||
mp_notesApi->updateNote(id, note);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NotesModel::remove(const int id) {
|
||||
void NotesModel::remove(int id) {
|
||||
qDebug() << "Removing note: " << id;
|
||||
if (m_notes.contains(id)) {
|
||||
if (indexOfNoteById(id) >= 0) {
|
||||
beginRemoveRows(QModelIndex(), indexOfNoteById(id), indexOfNoteById(id));
|
||||
if (m_notes.remove(id) > 0) {
|
||||
emit noteDeleted(id);
|
||||
}
|
||||
else {
|
||||
qDebug() << "Note not found";
|
||||
}
|
||||
deleteNote(id);
|
||||
endRemoveRows();
|
||||
qDebug() << "Note removed";
|
||||
}
|
||||
if (mp_notesApi && mp_notesStore) {
|
||||
if (sender() == mp_notesApi) {
|
||||
mp_notesStore->deleteNote(id);
|
||||
}
|
||||
if (sender() == mp_notesStore) {
|
||||
mp_notesApi->deleteNote(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NotesModel::clear() {
|
||||
qDebug() << "Clearing model";
|
||||
beginResetModel();
|
||||
m_notes.clear();
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
int NotesModel::indexOfNoteById(int id) const {
|
||||
return std::distance(m_notes.begin(), m_notes.lowerBound(id));
|
||||
int index = -1;
|
||||
if (m_fileDir.exists() && !account().isEmpty()) {
|
||||
index = m_fileDir.entryList().indexOf(QRegExp(QString("^%1.%2$").arg(id).arg(m_fileSuffix)));
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
int NotesModel::idOfNoteByINdex(int index) const {
|
||||
int id = -1;
|
||||
if (m_fileDir.exists() && !account().isEmpty()) {
|
||||
QFileInfo fileName = m_fileDir.entryInfoList().value(index);
|
||||
bool ok;
|
||||
id = fileName.baseName().toInt(&ok);
|
||||
if (!ok) id = -1;
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> NotesModel::roleNames() const {
|
||||
|
@ -374,7 +323,7 @@ Qt::ItemFlags NotesModel::flags(const QModelIndex &index) const {
|
|||
}
|
||||
|
||||
int NotesModel::rowCount(const QModelIndex &parent) const {
|
||||
if (parent.column() == 0 && m_fileDir.exists() && !account().isEmpty()) {
|
||||
if (m_fileDir.exists() && !account().isEmpty()) {
|
||||
return static_cast<int>(m_fileDir.count());
|
||||
}
|
||||
else {
|
||||
|
@ -382,58 +331,39 @@ int NotesModel::rowCount(const QModelIndex &parent) const {
|
|||
}
|
||||
}
|
||||
|
||||
QVariant NotesModel::data(const QModelIndex &index, int role) {
|
||||
if (role == ModifiedStringRole)
|
||||
QVariant NotesModel::data(const QModelIndex &index, int role) const {
|
||||
return itemData(index).value(role);
|
||||
}
|
||||
|
||||
bool NotesModel::setData(const QModelIndex &index, const QVariant &value, int role) {
|
||||
return setItemData(index, QMap<int, QVariant>{ { role, value } } );
|
||||
if (setItemData(index, QMap<int, QVariant>{ { role, value } } )) {
|
||||
emit dataChanged(index, index);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
QMap<int, QVariant> NotesModel::itemData(const QModelIndex &index) {
|
||||
QMap<int, QVariant> NotesModel::itemData(const QModelIndex &index) const {
|
||||
QMap<int, QVariant> map;
|
||||
if (index.isValid() && index.row() < m_files.size()) {
|
||||
QMap<int, QFile>::iterator i = m_files.begin();
|
||||
i += index.row();
|
||||
if (i.value().isReadable()) {
|
||||
QJsonObject json = QJsonDocument::fromJson(i.value().readAll()).object();
|
||||
if (index.isValid() && index.row() < rowCount()) {
|
||||
QVariantMap note = this->note(idOfNoteByINdex(index.row()));
|
||||
for (int role = IdRole; role <= ErrorMessageRole; ++role) {
|
||||
map.insert(role, json.value(m_roleNames[role]));
|
||||
}
|
||||
}
|
||||
else {
|
||||
qDebug() << "File not readable: " << i.value().fileName();
|
||||
map.insert(role, note.value(m_roleNames[role]));
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
bool NotesModel::setItemData(const QModelIndex &index, const QMap<int, QVariant> &roles) {
|
||||
if (index.isValid() && index.row() < m_files.size()) {
|
||||
QMap<int, QFile>::iterator i = m_files.begin();
|
||||
i += index.row();
|
||||
if (i.value().isReadable() && i.value().isWritable()) {
|
||||
QJsonObject json = QJsonDocument::fromJson(i.value().readAll()).object();
|
||||
QVariantMap note;
|
||||
if (index.isValid() && index.row() < rowCount()) {
|
||||
note = this->note(idOfNoteByINdex(index.row()));
|
||||
QMapIterator<int, QVariant> i(roles);
|
||||
while (i.hasNext()) {
|
||||
i.next();
|
||||
json.insert(m_roleNames[i.key()], QJsonValue::fromVariant(i.value()));
|
||||
note.insert(m_roleNames[i.key()], i.value());
|
||||
}
|
||||
|
||||
return setNote(note, idOfNoteByINdex(index.row()));
|
||||
}
|
||||
}
|
||||
else {
|
||||
qDebug() << "File not writable: " << i.value().fileName();
|
||||
}
|
||||
|
||||
|
||||
//qDebug();
|
||||
bool retval = true;
|
||||
QMapIterator<int, QVariant> role(roles);
|
||||
while (role.hasNext()) {
|
||||
role.next();
|
||||
retval &= setData(index, role.value(), role.key());
|
||||
}
|
||||
return retval;
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -3,12 +3,13 @@
|
|||
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QAbstractListModel>
|
||||
#include <QStandardPaths>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QJsonArray>
|
||||
#include <QDateTime>
|
||||
#include "note.h"
|
||||
#include "notesapi.h"
|
||||
#include "notesstore.h"
|
||||
|
||||
class NotesProxyModel : public QSortFilterProxyModel {
|
||||
Q_OBJECT
|
||||
|
@ -50,6 +51,10 @@ public:
|
|||
explicit NotesModel(QObject *parent = nullptr);
|
||||
virtual ~NotesModel();
|
||||
|
||||
Q_PROPERTY(QString account READ account WRITE setAccount NOTIFY accountChanged)
|
||||
QString account() const;
|
||||
void setAccount(const QString& account);
|
||||
|
||||
enum NoteRoles {
|
||||
IdRole = Qt::UserRole,
|
||||
ModifiedRole = Qt::UserRole + 1,
|
||||
|
@ -68,57 +73,41 @@ public:
|
|||
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const;
|
||||
virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
virtual QVariant data(const QModelIndex &index, int role);
|
||||
virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
|
||||
virtual QVariant data(const QModelIndex &index, int role) const;
|
||||
//virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
|
||||
virtual bool setData(const QModelIndex &index, const QVariant &value, int role);
|
||||
virtual bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex());
|
||||
virtual bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex());
|
||||
QMap<int, QVariant> itemData(const QModelIndex &index);
|
||||
//virtual bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex());
|
||||
//virtual bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex());
|
||||
virtual QMap<int, QVariant> itemData(const QModelIndex &index) const;
|
||||
virtual bool setItemData(const QModelIndex &index, const QMap<int, QVariant> &roles);
|
||||
|
||||
void setNotesApi(NotesApi* notesApi);
|
||||
void setNotesStore(NotesStore *notesStore);
|
||||
|
||||
QString account() const;
|
||||
void setAccount(const QString& account);
|
||||
|
||||
int newNotePosition(const int id) const;
|
||||
Q_INVOKABLE const QVariantMap note(const int id) const;
|
||||
Q_INVOKABLE bool setNote(const QVariantMap& note, int id = -1) const;
|
||||
Q_INVOKABLE bool setNote(const QVariantMap& note, int id = -1);
|
||||
Q_INVOKABLE bool deleteNote(const int id);
|
||||
|
||||
public slots:
|
||||
Q_INVOKABLE bool getAllNotes(const QStringList& exclude = QStringList());
|
||||
Q_INVOKABLE bool getNote(const int id, const QStringList& exclude = QStringList());
|
||||
Q_INVOKABLE bool createNote(const QJsonObject& note);
|
||||
Q_INVOKABLE bool updateNote(const int id, const QJsonObject& note);
|
||||
Q_INVOKABLE bool deleteNote(const int id);
|
||||
Q_INVOKABLE bool syncNotes();
|
||||
void insert(int id, const QJsonObject& json);
|
||||
void update(int id, const QJsonObject& json);
|
||||
void remove(int id);
|
||||
|
||||
void insert(const int id, const QJsonObject& note);
|
||||
void update(const int id, const QJsonObject& note);
|
||||
void remove(const int id);
|
||||
|
||||
Q_INVOKABLE void clear();
|
||||
Q_INVOKABLE int indexOfNoteById(int id) const;
|
||||
Q_INVOKABLE int idOfNoteByINdex(int index) const;
|
||||
|
||||
signals:
|
||||
void accountChanged(const QString& account);
|
||||
void allNotesChanged(const QList<int>& ids);
|
||||
void noteCreated(const int id, const QJsonObject& note);
|
||||
void noteUpdated(const int id, const QJsonObject& note);
|
||||
void noteDeleted(const int id);
|
||||
|
||||
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles = QVector<int> ());
|
||||
|
||||
private:
|
||||
QMap<int, QJsonObject> m_notes;
|
||||
const static QHash<int, QByteArray> m_roleNames;
|
||||
|
||||
QMap<int, QFile> m_files;
|
||||
//QMap<int, QFile> m_files;
|
||||
QDir m_fileDir;
|
||||
const static QString m_fileSuffix;
|
||||
|
||||
NotesApi* mp_notesApi;
|
||||
NotesStore* mp_notesStore;
|
||||
};
|
||||
|
||||
#endif // NOTESMODEL_H
|
||||
|
|
|
@ -1,256 +0,0 @@
|
|||
#include "notesstore.h"
|
||||
#include "note.h"
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QDateTime>
|
||||
#include <QDebug>
|
||||
|
||||
const QString NotesStore::m_suffix = "json";
|
||||
|
||||
NotesStore::NotesStore(QString directory, QObject *parent) : QObject(parent)
|
||||
{
|
||||
m_dir.setCurrent(directory);
|
||||
m_dir.setPath("");
|
||||
m_dir.setFilter(QDir::Files);
|
||||
m_dir.setNameFilters( { "*." + m_suffix } );
|
||||
}
|
||||
|
||||
NotesStore::~NotesStore() {
|
||||
}
|
||||
|
||||
QString NotesStore::account() const {
|
||||
if (m_dir != QDir(QStandardPaths::writableLocation(QStandardPaths::DataLocation))) {
|
||||
return m_dir.path();
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
void NotesStore::setAccount(const QString& account) {
|
||||
qDebug() << "Setting account: " << account;
|
||||
if (account != m_dir.path()) {
|
||||
if (m_dir != QDir(QStandardPaths::writableLocation(QStandardPaths::DataLocation))) {
|
||||
m_dir = QDir(QStandardPaths::writableLocation(QStandardPaths::DataLocation));
|
||||
}
|
||||
if (!account.isEmpty()) {
|
||||
m_dir.setPath(account);
|
||||
if (m_dir.mkpath(".")) {
|
||||
emit accountChanged(m_dir.path());
|
||||
}
|
||||
else {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
const QList<int> NotesStore::noteIds() {
|
||||
QList<int> ids;
|
||||
if (m_dir.exists() && !account().isEmpty()) {
|
||||
QFileInfoList files = m_dir.entryInfoList();
|
||||
for (int i = 0; i < files.size(); ++i) {
|
||||
bool ok;
|
||||
int id = files[i].baseName().toInt(&ok);
|
||||
if (ok) {
|
||||
ids << id;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
qDebug() << errorMessage(DirNotFoundError);
|
||||
emit noteError(DirCannotReadError);
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
|
||||
bool NotesStore::noteExists(const int id) {
|
||||
QFileInfo fileinfo(m_dir, QString("%1.%2").arg(id).arg(m_suffix));
|
||||
return fileinfo.exists();
|
||||
}
|
||||
|
||||
int NotesStore::noteModified(const int id) {
|
||||
return Note::modified(readNoteFile(id, { "content" }));
|
||||
}
|
||||
|
||||
const QString NotesStore::errorMessage(ErrorCodes error) const {
|
||||
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;
|
||||
}
|
||||
|
||||
QJsonObject NotesStore::readNoteFile(const int id, const QStringList& exclude) {
|
||||
QJsonObject json;
|
||||
QFileInfo fileinfo(m_dir, QString("%1.%2").arg(id).arg(m_suffix));
|
||||
QFile file(fileinfo.filePath());
|
||||
if (file.exists()) {
|
||||
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
QByteArray data = file.readAll();
|
||||
json = QJsonDocument::fromJson(data).object();
|
||||
file.close();
|
||||
for (int i = 0; i < exclude.size(); ++i) {
|
||||
json.remove(exclude[i]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
emit noteError(FileCannotReadError);
|
||||
}
|
||||
}
|
||||
else {
|
||||
//emit noteError(FileNotFoundError);
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
bool NotesStore::writeNoteFile(const int id, const QJsonObject& note) {
|
||||
bool success = false;
|
||||
if (!account().isEmpty()) {
|
||||
QFileInfo fileinfo(m_dir, QString("%1.%2").arg(id).arg(m_suffix));
|
||||
QFile file(fileinfo.filePath());
|
||||
if (file.open(QIODevice::ReadWrite | QIODevice::Truncate | QIODevice::Text)) {
|
||||
QByteArray data = QJsonDocument(note).toJson();
|
||||
if (file.write(data) == data.size()) {
|
||||
success = true;
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
else {
|
||||
emit noteError(FileCannotWriteError);
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool NotesStore::removeNoteFile(const int id) {
|
||||
bool success = false;
|
||||
if (!account().isEmpty()) {
|
||||
QFileInfo fileinfo(m_dir, QString("%1.%2").arg(id).arg(m_suffix));
|
||||
QFile file(fileinfo.filePath());
|
||||
if (file.exists()) {
|
||||
if (file.remove()) {
|
||||
success = true;
|
||||
}
|
||||
else {
|
||||
emit noteError(FileCannotWriteError);
|
||||
}
|
||||
}
|
||||
else {
|
||||
emit noteError(FileNotFoundError);
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool NotesStore::getAllNotes(const QStringList& exclude) {
|
||||
qDebug() << "Getting all notes";
|
||||
const QList<int> ids = noteIds();
|
||||
if (!ids.empty()) {
|
||||
for (int i = 0; i < ids.size(); ++i) {
|
||||
getNote(ids.at(i), exclude);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool NotesStore::getNote(const int id, const QStringList& exclude) {
|
||||
qDebug() << "Getting note: " << id;
|
||||
QJsonObject note;
|
||||
if (id >= 0) {
|
||||
note = readNoteFile(id, exclude);
|
||||
emit noteUpdated(id, note);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
qDebug() << "Skipping, invalid ID";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NotesStore::createNote(const QJsonObject& note) {
|
||||
int id = note.value("id").toInt(-1);
|
||||
qDebug() << "Creating note: " << id;
|
||||
if (id < 0) {
|
||||
// TODO probably crate files with an '.json.<NUMBER>.new' extension
|
||||
qDebug() << "Creating notes without the server API is not supported yet!";
|
||||
}
|
||||
else if (!noteExists(id)) {
|
||||
if (writeNoteFile(id, note)) {
|
||||
emit noteUpdated(id, note);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
qDebug() << "Note already exists";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NotesStore::updateNote(const int id, const QJsonObject& note) {
|
||||
qDebug() << "Updating note: " << id;
|
||||
if (id >= 0) {
|
||||
QJsonObject tmpNote = readNoteFile(id);
|
||||
if (note != tmpNote) {
|
||||
if (note.value("modified").toInt() >= tmpNote.value("modified").toInt() || note.value("modified").toInt() == 0) {
|
||||
QStringList fields = note.keys();
|
||||
for (int i = 0; i < fields.size(); ++i) {
|
||||
tmpNote[fields[i]] = note[fields[i]];
|
||||
}
|
||||
if (tmpNote.value("modified").toInt() == 0) {
|
||||
tmpNote["modified"] = QJsonValue::fromVariant(QDateTime::currentDateTime().toTime_t());
|
||||
}
|
||||
if (writeNoteFile(id, tmpNote)) {
|
||||
emit noteUpdated(id, tmpNote);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
qDebug() << "Skipping, note is older" << QDateTime::fromTime_t(note.value("modified").toInt()) << QDateTime::fromTime_t(tmpNote.value("modified").toInt());
|
||||
}
|
||||
}
|
||||
else {
|
||||
qDebug() << "Skipping, note is equal";
|
||||
}
|
||||
}
|
||||
else {
|
||||
qDebug() << "Skipping, invalid ID";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NotesStore::deleteNote(const int id) {
|
||||
qDebug() << "Deleting note: " << id;
|
||||
if (removeNoteFile(id)) {
|
||||
emit noteDeleted(id);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
|
@ -1,65 +0,0 @@
|
|||
#ifndef NOTESSTORE_H
|
||||
#define NOTESSTORE_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
#include <QDir>
|
||||
#include <QStandardPaths>
|
||||
|
||||
class NotesStore : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit NotesStore(
|
||||
QString directory = QStandardPaths::writableLocation(QStandardPaths::DataLocation),
|
||||
QObject *parent = nullptr);
|
||||
virtual ~NotesStore();
|
||||
|
||||
Q_PROPERTY(QString account READ account WRITE setAccount NOTIFY accountChanged)
|
||||
|
||||
QString account() const;
|
||||
void setAccount(const QString& account);
|
||||
|
||||
const QList<int> noteIds();
|
||||
bool noteExists(const int id);
|
||||
int noteModified(const int id);
|
||||
|
||||
enum ErrorCodes {
|
||||
NoError,
|
||||
FileNotFoundError,
|
||||
FileCannotReadError,
|
||||
FileCannotWriteError,
|
||||
DirNotFoundError,
|
||||
DirCannotReadError,
|
||||
DirCannotWriteError
|
||||
};
|
||||
Q_ENUM(ErrorCodes)
|
||||
Q_INVOKABLE const QString errorMessage(ErrorCodes error) const;
|
||||
|
||||
QJsonObject readNoteFile(const int id, const QStringList& exclude = QStringList());
|
||||
bool writeNoteFile(const int id, const QJsonObject& note);
|
||||
bool removeNoteFile(const int id);
|
||||
|
||||
public slots:
|
||||
Q_INVOKABLE bool getAllNotes(const QStringList& exclude = QStringList());
|
||||
Q_INVOKABLE bool getNote(const int id, const QStringList& exclude = QStringList());
|
||||
Q_INVOKABLE bool createNote(const QJsonObject& note);
|
||||
Q_INVOKABLE bool updateNote(const int id, const QJsonObject& note);
|
||||
Q_INVOKABLE bool deleteNote(const int id);
|
||||
|
||||
signals:
|
||||
void accountChanged(const QString& account);
|
||||
void allNotesChanged(const QList<int>& ids);
|
||||
void noteCreated(const int id, const QJsonObject& note);
|
||||
void noteUpdated(const int id, const QJsonObject& note);
|
||||
void noteDeleted(const int id);
|
||||
void noteError(const ErrorCodes error);
|
||||
|
||||
private:
|
||||
QDir m_dir;
|
||||
const static QString m_suffix;
|
||||
};
|
||||
|
||||
#endif // NOTESSTORE_H
|
|
@ -362,41 +362,6 @@
|
|||
<translation>Ein Fehler ist aufgetreten</translation>
|
||||
</message>
|
||||
</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>
|
||||
<name>SettingsPage</name>
|
||||
<message>
|
||||
|
|
|
@ -362,41 +362,6 @@
|
|||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</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>
|
||||
<name>SettingsPage</name>
|
||||
<message>
|
||||
|
|
|
@ -316,32 +316,32 @@
|
|||
<context>
|
||||
<name>NotesApi</name>
|
||||
<message>
|
||||
<location filename="../src/notesapi.cpp" line="336"/>
|
||||
<location filename="../src/notesapi.cpp" line="325"/>
|
||||
<source>No error</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/notesapi.cpp" line="339"/>
|
||||
<location filename="../src/notesapi.cpp" line="328"/>
|
||||
<source>No network connection available</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/notesapi.cpp" line="342"/>
|
||||
<location filename="../src/notesapi.cpp" line="331"/>
|
||||
<source>Failed to communicate with the Nextcloud server</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/notesapi.cpp" line="345"/>
|
||||
<location filename="../src/notesapi.cpp" line="334"/>
|
||||
<source>An error occured while establishing an encrypted connection</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/notesapi.cpp" line="348"/>
|
||||
<location filename="../src/notesapi.cpp" line="337"/>
|
||||
<source>Could not authenticate to the Nextcloud instance</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/notesapi.cpp" line="351"/>
|
||||
<location filename="../src/notesapi.cpp" line="340"/>
|
||||
<source>Unknown error</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
@ -444,49 +444,6 @@
|
|||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>NotesStore</name>
|
||||
<message>
|
||||
<location filename="../src/notesstore.cpp" line="81"/>
|
||||
<source>No error</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/notesstore.cpp" line="84"/>
|
||||
<source>File not found</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/notesstore.cpp" line="87"/>
|
||||
<source>Cannot read from the file</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/notesstore.cpp" line="90"/>
|
||||
<source>Cannot write to the file</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/notesstore.cpp" line="93"/>
|
||||
<source>Directory not found</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/notesstore.cpp" line="96"/>
|
||||
<source>Cannot read from directory</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/notesstore.cpp" line="99"/>
|
||||
<source>Cannot create or write to directory</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/notesstore.cpp" line="102"/>
|
||||
<source>Unknown error</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>SettingsPage</name>
|
||||
<message>
|
||||
|
@ -883,27 +840,27 @@ You can also use other markdown syntax inside them.</source>
|
|||
<context>
|
||||
<name>harbour-nextcloudnotes</name>
|
||||
<message>
|
||||
<location filename="../qml/harbour-nextcloudnotes.qml" line="123"/>
|
||||
<location filename="../qml/harbour-nextcloudnotes.qml" line="121"/>
|
||||
<source>Notes</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../qml/harbour-nextcloudnotes.qml" line="124"/>
|
||||
<location filename="../qml/harbour-nextcloudnotes.qml" line="122"/>
|
||||
<source>Offline</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../qml/harbour-nextcloudnotes.qml" line="125"/>
|
||||
<location filename="../qml/harbour-nextcloudnotes.qml" line="123"/>
|
||||
<source>Synced</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../qml/harbour-nextcloudnotes.qml" line="139"/>
|
||||
<location filename="../qml/harbour-nextcloudnotes.qml" line="137"/>
|
||||
<source>API error</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../qml/harbour-nextcloudnotes.qml" line="132"/>
|
||||
<location filename="../qml/harbour-nextcloudnotes.qml" line="130"/>
|
||||
<source>File error</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
|
Loading…
Reference in a new issue