diff --git a/harbour-nextcloudnotes.pro b/harbour-nextcloudnotes.pro index 113f0a0..0213fce 100644 --- a/harbour-nextcloudnotes.pro +++ b/harbour-nextcloudnotes.pro @@ -1,58 +1,60 @@ -# NOTICE: -# -# Application name defined in TARGET has a corresponding QML filename. -# If name defined in TARGET is changed, the following needs to be done -# to match new name: -# - corresponding QML filename must be changed -# - desktop icon filename must be changed -# - desktop filename must be changed -# - icon definition filename in desktop file must be changed -# - translation filenames have to be changed - -# The name of your application -TARGET = harbour-nextcloudnotes - -CONFIG += sailfishapp - -DEFINES += APP_VERSION=\\\"$$VERSION\\\" - -HEADERS += \ - src/sslconfiguration.h - -SOURCES += src/harbour-nextcloudnotes.cpp \ - src/sslconfiguration.cpp - -DISTFILES += qml/harbour-nextcloudnotes.qml \ - qml/cover/CoverPage.qml \ - rpm/harbour-nextcloudnotes.changes.run.in \ - rpm/harbour-nextcloudnotes.changes \ - rpm/harbour-nextcloudnotes.spec \ - rpm/harbour-nextcloudnotes.yaml \ - translations/*.ts \ - harbour-nextcloudnotes.desktop \ - qml/pages/NotePage.qml \ - qml/pages/NotesPage.qml \ - qml/pages/LoginDialog.qml \ - qml/pages/EditPage.qml \ - qml/pages/SettingsPage.qml \ - qml/pages/AboutPage.qml \ - qml/pages/UnencryptedDialog.qml \ - qml/pages/NotesApi.qml \ - qml/pages/MITLicense.qml \ - qml/pages/GPLLicense.qml \ - qml/pages/SyntaxPage.qml \ - qml/components/NotesApi.qml \ - qml/components/NoteDelegateModel.qml - -SAILFISHAPP_ICONS = 86x86 108x108 128x128 172x172 - -# to disable building translations every time, comment out the -# following CONFIG line -CONFIG += sailfishapp_i18n - -# German translation is enabled as an example. If you aren't -# planning to localize your app, remember to comment out the -# following TRANSLATIONS line. And also do not forget to -# modify the localized app name in the the .desktop file. -TRANSLATIONS += translations/harbour-nextcloudnotes-de.ts \ - translations/harbour-nextcloudnotes-sv.ts +# NOTICE: +# +# Application name defined in TARGET has a corresponding QML filename. +# If name defined in TARGET is changed, the following needs to be done +# to match new name: +# - corresponding QML filename must be changed +# - desktop icon filename must be changed +# - desktop filename must be changed +# - icon definition filename in desktop file must be changed +# - translation filenames have to be changed + +# The name of your application +TARGET = harbour-nextcloudnotes + +CONFIG += sailfishapp + +DEFINES += APP_VERSION=\\\"$$VERSION\\\" + +HEADERS += \ + src/sslconfiguration.h \ + src/notesmodel.h + +SOURCES += src/harbour-nextcloudnotes.cpp \ + src/sslconfiguration.cpp \ + src/notesmodel.cpp + +DISTFILES += qml/harbour-nextcloudnotes.qml \ + qml/cover/CoverPage.qml \ + rpm/harbour-nextcloudnotes.changes.run.in \ + rpm/harbour-nextcloudnotes.changes \ + rpm/harbour-nextcloudnotes.spec \ + rpm/harbour-nextcloudnotes.yaml \ + translations/*.ts \ + harbour-nextcloudnotes.desktop \ + qml/pages/NotePage.qml \ + qml/pages/NotesPage.qml \ + qml/pages/LoginDialog.qml \ + qml/pages/EditPage.qml \ + qml/pages/SettingsPage.qml \ + qml/pages/AboutPage.qml \ + qml/pages/UnencryptedDialog.qml \ + qml/pages/NotesApi.qml \ + qml/pages/MITLicense.qml \ + qml/pages/GPLLicense.qml \ + qml/pages/SyntaxPage.qml \ + qml/components/NotesApi.qml \ + qml/components/NoteDelegateModel.qml + +SAILFISHAPP_ICONS = 86x86 108x108 128x128 172x172 + +# to disable building translations every time, comment out the +# following CONFIG line +CONFIG += sailfishapp_i18n + +# German translation is enabled as an example. If you aren't +# planning to localize your app, remember to comment out the +# following TRANSLATIONS line. And also do not forget to +# modify the localized app name in the the .desktop file. +TRANSLATIONS += translations/harbour-nextcloudnotes-de.ts \ + translations/harbour-nextcloudnotes-sv.ts diff --git a/qml/components/NotesApi.qml b/qml/components/NotesApi.qml index 459a2af..df5354f 100644 --- a/qml/components/NotesApi.qml +++ b/qml/components/NotesApi.qml @@ -11,7 +11,7 @@ Item { property bool saveFile: false property bool busy: jobsRunning > 0 property int jobsRunning: 0 - property int status: 204 + property int status: 0 //204 property string statusText: "No Content" signal noteCreated(int id) @@ -22,10 +22,10 @@ Item { console.log("Network status: " + statusText + " (" + status + ")") } onUuidChanged: { - onUuidChanged: console.log("Account : " + uuid) + appSettings.currentAccount = uuid account.path = "/apps/harbour-nextcloudnotes/accounts/" + uuid model.clear() - appSettings.currentAccount = uuid + onUuidChanged: console.log("Account : " + account.name) } function clear() { model.clear() @@ -38,10 +38,12 @@ Item { var endpoint = account.server + "/index.php/apps/notes/api/" + account.version + "/notes" if (data) { if (method === "POST" || method === "PUT") { - addToModel(data) + console.log("Adding note...") + //addToModel(data) } else if (data.id && method === "DELETE") { - removeFromModel(data.id) + console.log("Deleting note...") + //removeFromModel(data.id) } if (method === "GET" || method === "PUT" || method === "DELETE") { if (data.id) { diff --git a/qml/harbour-nextcloudnotes.qml b/qml/harbour-nextcloudnotes.qml index 9589a53..673d884 100644 --- a/qml/harbour-nextcloudnotes.qml +++ b/qml/harbour-nextcloudnotes.qml @@ -1,7 +1,8 @@ import QtQuick 2.0 import Sailfish.Silica 1.0 import Nemo.Configuration 1.0 -import SslConfiguration 1.0 +import harbour.nextcloudnotes.notesmodel 1.0 +import harbour.nextcloudnotes.sslconfiguration 1.0 import "pages" import "components" @@ -17,7 +18,7 @@ ApplicationWindow ConfigurationGroup { id: account - //path: "/apps/harbour-nextcloudnotes/accounts/" + appSettings.currentAccount + path: "/apps/harbour-nextcloudnotes/accounts/" + appSettings.currentAccount property string name: value("name", "", String) property url server: value("server", "", String) property string version: value("version", "v0.2", String) @@ -27,7 +28,6 @@ ApplicationWindow property bool unencryptedConnection: account.value("unencryptedConnection", false, Boolean) property date update: value("update", "", Date) onValuesChanged: console.log("A property of the current account has changed") - //onUnsecureConnectionChanged: ssl.checkCert = !unsecureConnection } ConfigurationGroup { @@ -43,7 +43,6 @@ ApplicationWindow property bool showSeparator: value("showSeparator", false, Boolean) property bool useMonoFont: value("useMonoFont", false, Boolean) property bool useCapitalX: value("useCapitalX", false, Boolean) - onCurrentAccountChanged: api.uuid = currentAccount function addAccount() { diff --git a/rpm/harbour-nextcloudnotes.changes b/rpm/harbour-nextcloudnotes.changes index 0c60775..a537514 100644 --- a/rpm/harbour-nextcloudnotes.changes +++ b/rpm/harbour-nextcloudnotes.changes @@ -12,6 +12,9 @@ # * date Author's Name version-release # - Summary of changes +* Fri Dec 28 2018 Scharel Clemens 0.3-0 +- Began implementing the data model in C++ + * Thu Dec 27 2018 Scharel Clemens 0.2-10 - Implemented #24: "Option to show favorite notes on the top of the list" - Implemented #32: "Allow selfsigned SSL certificates" (not tested!) diff --git a/rpm/harbour-nextcloudnotes.spec b/rpm/harbour-nextcloudnotes.spec index 0a642cc..6795097 100644 --- a/rpm/harbour-nextcloudnotes.spec +++ b/rpm/harbour-nextcloudnotes.spec @@ -13,8 +13,8 @@ Name: harbour-nextcloudnotes %{!?qtc_make:%define qtc_make make} %{?qtc_builddir:%define _builddir %qtc_builddir} Summary: Nextcloud Notes -Version: 0.2 -Release: 10 +Version: 0.3 +Release: 0 Group: Applications/Editors License: MIT URL: https://github.com/scharel/harbour-nextcloudnotes diff --git a/rpm/harbour-nextcloudnotes.spec.22312 b/rpm/harbour-nextcloudnotes.spec.22312 new file mode 100644 index 0000000..6795097 --- /dev/null +++ b/rpm/harbour-nextcloudnotes.spec.22312 @@ -0,0 +1,72 @@ +# +# Do NOT Edit the Auto-generated Part! +# Generated by: spectacle version 0.27 +# + +Name: harbour-nextcloudnotes + +# >> macros +# << macros + +%{!?qtc_qmake:%define qtc_qmake %qmake} +%{!?qtc_qmake5:%define qtc_qmake5 %qmake5} +%{!?qtc_make:%define qtc_make make} +%{?qtc_builddir:%define _builddir %qtc_builddir} +Summary: Nextcloud Notes +Version: 0.3 +Release: 0 +Group: Applications/Editors +License: MIT +URL: https://github.com/scharel/harbour-nextcloudnotes +Source0: %{name}-%{version}.tar.bz2 +Source100: harbour-nextcloudnotes.yaml +Requires: sailfishsilica-qt5 >= 0.10.9 +BuildRequires: pkgconfig(sailfishapp) >= 1.0.2 +BuildRequires: pkgconfig(Qt5Core) +BuildRequires: pkgconfig(Qt5Qml) +BuildRequires: pkgconfig(Qt5Quick) +BuildRequires: desktop-file-utils + +%description +A client app for the Nextcloud Notes server app + + +%prep +%setup -q -n %{name}-%{version} + +# >> setup +# << setup + +%build +# >> build pre +# << build pre + +%qtc_qmake5 \ + VERSION='%{version}-%{release}' + +%qtc_make %{?_smp_mflags} + +# >> build post +# << build post + +%install +rm -rf %{buildroot} +# >> install pre +# << install pre +%qmake5_install + +# >> install post +# << install post + +desktop-file-install --delete-original \ + --dir %{buildroot}%{_datadir}/applications \ + %{buildroot}%{_datadir}/applications/*.desktop + +%files +%defattr(-,root,root,-) +%{_bindir} +%{_datadir}/%{name} +%{_datadir}/applications/%{name}.desktop +%{_datadir}/icons/hicolor/*/apps/%{name}.png +# >> files +# << files diff --git a/rpm/harbour-nextcloudnotes.yaml b/rpm/harbour-nextcloudnotes.yaml index d6ac106..cfdc6a2 100644 --- a/rpm/harbour-nextcloudnotes.yaml +++ b/rpm/harbour-nextcloudnotes.yaml @@ -1,7 +1,7 @@ Name: harbour-nextcloudnotes Summary: Nextcloud Notes -Version: 0.2 -Release: 10 +Version: 0.3 +Release: 0 # The contents of the Group field should be one of the groups listed here: # https://github.com/mer-tools/spectacle/blob/master/data/GROUPS Group: Applications/Editors diff --git a/src/harbour-nextcloudnotes.cpp b/src/harbour-nextcloudnotes.cpp index 88b2ed6..9005401 100644 --- a/src/harbour-nextcloudnotes.cpp +++ b/src/harbour-nextcloudnotes.cpp @@ -1,6 +1,8 @@ #include #include +#include #include +#include "notesmodel.h" #include "sslconfiguration.h" int main(int argc, char *argv[]) @@ -13,7 +15,8 @@ int main(int argc, char *argv[]) app->setOrganizationName("harbour-nextcloudnotes"); qDebug() << app->applicationDisplayName() << app->applicationVersion(); - qmlRegisterType("SslConfiguration", 1, 0, "SslConfiguration"); + qmlRegisterType("harbour.nextcloudnotes.notesmodel", 1, 0, "NotesModel"); + qmlRegisterType("harbour.nextcloudnotes.sslconfiguration", 1, 0, "SslConfiguration"); QQuickView* view = SailfishApp::createView(); diff --git a/src/notesmodel.cpp b/src/notesmodel.cpp new file mode 100644 index 0000000..a54a29d --- /dev/null +++ b/src/notesmodel.cpp @@ -0,0 +1,347 @@ +#include "notesmodel.h" +#include +#include + +const QHash noteRoles = QHash{ + {NotesModel::idRole, "id"}, + {NotesModel::modifiedRole, "modified"}, + {NotesModel::titleRole, "title"}, + {NotesModel::categoryRole, "category"}, + {NotesModel::contentRole, "content"}, + {NotesModel::favoriteRole, "favorite"}, + {NotesModel::etagRole, "etag"}, + {NotesModel::errorRole, "error"}, + {NotesModel::errorMessageRole, "errorMessage"} +}; + +struct Note { + int id; + uint modified; + QString title; + QString category; + QString content; + bool favorite; + QString etag; + bool error; + QString errorMessage; + bool operator==(const Note& n) { + return id == n.id; + } + void fromjson(const QJsonObject& jobj) { + id = jobj.value(noteRoles[NotesModel::idRole]).toInt(); + modified = jobj.value(noteRoles[NotesModel::modifiedRole]).toInt(); + title = jobj.value(noteRoles[NotesModel::titleRole]).toString(); + category = jobj.value(noteRoles[NotesModel::categoryRole]).toString(); + content = jobj.value(noteRoles[NotesModel::contentRole]).toString(); + favorite = jobj.value(noteRoles[NotesModel::favoriteRole]).toBool(); + etag = jobj.value(noteRoles[NotesModel::etagRole]).toString(); + error = jobj.value(noteRoles[NotesModel::errorRole]).toBool(true); + errorMessage = jobj.value(noteRoles[NotesModel::errorMessageRole]).toString(); + } +}; + +NotesModel::NotesModel(QObject *parent) : QAbstractListModel(parent) +{ + m_sortBy = sortByDate; + m_favoritesOnTop = true; +} + +NotesModel::~NotesModel() { + m_notes.clear(); +} + +void NotesModel::setSortBy(int sortBy) { + if (sortBy != m_sortBy) { + m_sortBy = sortBy; + sort(); + emit sortByChanged(m_sortBy); + } +} + +void NotesModel::setFavoritesOnTop(bool favoritesOnTop) { + if (favoritesOnTop != m_favoritesOnTop) { + m_favoritesOnTop = favoritesOnTop; + sort(); + emit favoritesOnTopChanged(m_favoritesOnTop); + } +} + +bool NotesModel::applyJSON(QString json, bool replaceIfArray) { + QJsonDocument jdoc = QJsonDocument::fromJson(json.toUtf8()); + if (!jdoc.isNull()) { + if (jdoc.isArray()) { + QJsonArray jarr = jdoc.array(); + while (!jarr.empty()) { + QJsonValue jval = jarr.first(); + if (jval.isObject()) { + QJsonObject jobj = jval.toObject(); + if (!jobj.isEmpty() && !jobj.value(noteRoles[errorRole]).toBool(true)) { + Note note; + note.fromjson(jobj); + int index = m_notes.indexOf(note); + if (index >= 0) { + m_notes.replace(index, note); + } + else { + // TODO + } + } + } + jarr.pop_front(); + } + } + else if (jdoc.isObject()) { + QJsonObject jobj = jdoc.object(); + if (!jobj.isEmpty() && !jobj.value(noteRoles[errorRole]).toBool(true)) { + Note note; + note.fromjson(jobj); + int index = m_notes.indexOf(note); + if (index >= 0) { + m_notes.replace(index, note); + } + else { + // TODO + } + } + } + sort(); + return true; + } + return false; +} + +bool NotesModel::removeNote(int id) { + // TODO + return false; +} + +void NotesModel::search(QString query) const { + // TODO +} + +void NotesModel::clearSearch() const { + // TODO +} + +/* +bool NotesModel::addNote(Note ¬e) { + m_notes.append(note); + return false; +} + +bool NotesModel::addNotes(QList ¬es) { + for (int i = 0; i < notes.length(); i++) { + addNote(notes[i]); + } + return false; +} +*/ + +QHash NotesModel::roleNames() const { + QHash roles; + roles[idRole] = "id"; + roles[modifiedRole] = "modified"; + roles[titleRole] = "title"; + roles[categoryRole] = "category"; + roles[contentRole] = "content"; + roles[favoriteRole] = "favorite"; + roles[etagRole] = "etag"; + roles[errorRole] = "error"; + roles[errorMessageRole] = "errorMessage"; + return noteRoles; +} + +QHash NotesModel::sortingNames() const { + QHash criteria; + criteria[sortByDate] = "date"; + criteria[sortByCategory] = "category"; + criteria[sortByTitle] = "title"; + return criteria; +} + +Qt::ItemFlags NotesModel::flags(const QModelIndex &index) const { + return Qt::ItemIsEnabled; //| Qt::ItemIsEditable | Qt::ItemIsSelectable +} + +int NotesModel::rowCount(const QModelIndex &parent) const { + return m_notes.size(); +} + +QVariant NotesModel::data(const QModelIndex &index, int role) const { + if (!index.isValid()) return QVariant(); + else if (role == idRole) return m_notes[index.row()].id; + else if (role == modifiedRole) return m_notes[index.row()].modified; + else if (role == titleRole) return m_notes[index.row()].title; + else if (role == categoryRole) return m_notes[index.row()].category; + else if (role == contentRole) return m_notes[index.row()].content; + else if (role == favoriteRole) return m_notes[index.row()].favorite; + else if (role == etagRole) return m_notes[index.row()].etag; + else if (role == errorRole) return m_notes[index.row()].error; + else if (role == errorMessageRole) return m_notes[index.row()].errorMessage; + return QVariant(); +} + +void NotesModel::sort() { + QList notes; + QMap map; + QMap favorites; + switch (m_sortBy) { + case sortByDate: + emit layoutAboutToBeChanged(); + foreach (const Note ¬e, m_notes) { + if (m_favoritesOnTop && note.favorite) + favorites.insert(QString::number(note.modified), note); + else + map.insert(QString::number(note.modified), note); + } + notes = favorites.values(); + notes.append(map.values()); + m_notes = notes; + emit layoutChanged(); + break; + case sortByCategory: + emit layoutAboutToBeChanged(); + foreach (const Note ¬e, m_notes) { + if (m_favoritesOnTop && note.favorite) + favorites.insert(note.category, note); + else + map.insert(note.category, note); + } + notes = favorites.values(); + notes.append(map.values()); + m_notes = notes; + emit layoutChanged(); + break; + case sortByTitle: + emit layoutAboutToBeChanged(); + foreach (const Note ¬e, m_notes) { + if (m_favoritesOnTop && note.favorite) + favorites.insert(note.title, note); + else + map.insert(note.title, note); + } + notes = favorites.values(); + notes.append(map.values()); + m_notes = notes; + emit layoutChanged(); + break; + default: + break; + } +} + +/*bool NotesModel::noteLessThanByDate(const Note &n1, const Note &n2) { + if (m_favoritesOnTop && n1.favorite != n2.favorite) + return n1.favorite; + else + return n1.modified > n2.modified; +} + +bool NotesModel::noteLessThanByCategory(const Note &n1, const Note &n2) { + if (m_favoritesOnTop && n1.favorite != n2.favorite) + return n1.favorite; + else + return n1.category < n2.category; +} + +bool NotesModel::noteLessThanByTitle(const Note &n1, const Note &n2) { + if (m_favoritesOnTop && n1.favorite != n2.favorite) + return n1.favorite; + else + return n1.title < n2.title; +}*/ + +/*bool NotesModel::noteLessThan(const Note &n1, const Note &n2) const { + switch (m_sortBy) { + case sortByDate: + if (m_favoritesOnTop && n1.favorite != n2.favorite) + return n1.favorite; + else + return n1.modified > n2.modified; + break; + case sortByCategory: + if (m_favoritesOnTop && n1.favorite != n2.favorite) + return n1.favorite; + else + return n1.category < n2.category; + break; + case sortByTitle: + if (m_favoritesOnTop && n1.favorite != n2.favorite) + return n1.favorite; + else + return n1.title < n2.title; + break; + default: + break; + } +}*/ + +/* +bool NotesModel::setData(const QModelIndex &index, const QVariant &value, int role) { + if (!index.isValid()) return false; + else if (role == modifiedRole) { + m_notes[index.row()].modified = value.toDateTime(); + return true; + } + else if (role == categoryRole) { + m_notes[index.row()].category = value.toString(); + return true; + } + else if (role == contentRole) { + m_notes[index.row()].content = value.toString(); + return true; + } + else if (role == favoriteRole) { + m_notes[index.row()].favorite = value.toBool(); + return true; + } + return false; +} + +bool NotesModel::insertRow(int row, const QModelIndex &parent) { + beginInsertRows(parent, row, row); + m_notes.insert(row, Note()); + endInsertRows(); + return true; +} + +bool NotesModel::insertRows(int row, int count, const QModelIndex &parent) { + if (count > 0) { + beginInsertRows(parent, row, row+count); + for (int i = 0; i < count; i++) { + m_notes.insert(row + i, Note()); + } + endInsertRows(); + return true; + } + else { + return false; + } +} + +bool NotesModel::removeRow(int row, const QModelIndex &parent) { + if (row >= 0 && row < m_notes.size()) { + beginRemoveRows(parent, row, row); + m_notes.removeAt(row); + endRemoveRows(); + return true; + } + else { + return false; + } +} + +bool NotesModel::removeRows(int row, int count, const QModelIndex &parent) { + if (row >= 0 && row < m_notes.size()) { + beginRemoveRows(parent, row, count); + for (int i = 0; i < count && row + i < m_notes.size(); i++) { + m_notes.removeAt(row); + } + endRemoveRows(); + return true; + } + else { + return false; + } +} +*/ diff --git a/src/notesmodel.h b/src/notesmodel.h new file mode 100644 index 0000000..81864b9 --- /dev/null +++ b/src/notesmodel.h @@ -0,0 +1,78 @@ +#ifndef NOTESMODEL_H +#define NOTESMODEL_H + +#include +#include +#include + +struct Note; + +class NotesModel : public QAbstractListModel { + Q_OBJECT +public: + explicit NotesModel(QObject *parent = 0); + virtual ~NotesModel(); + + Q_PROPERTY(int sortBy READ sortBy WRITE setSortBy NOTIFY sortByChanged) + int sortBy() { return m_sortBy; } + void setSortBy(int sortBy); + + Q_PROPERTY(bool favoritesOnTop READ favoritesOnTop WRITE setFavoritesOnTop NOTIFY favoritesOnTopChanged) + bool favoritesOnTop() { return m_favoritesOnTop; } + void setFavoritesOnTop(bool favoritesOnTop); + + Q_INVOKABLE bool applyJSON(QString json, bool replaceIfArray = true); + Q_INVOKABLE bool removeNote(int id); + + Q_INVOKABLE void search(QString query) const; + Q_INVOKABLE void clearSearch() const; + + enum NoteRoles { + idRole = Qt::UserRole + 1, + modifiedRole = Qt::UserRole + 2, + titleRole = Qt::UserRole + 3, + categoryRole = Qt::UserRole + 4, + contentRole = Qt::UserRole + 5, + favoriteRole = Qt::UserRole + 6, + etagRole = Qt::UserRole + 7, + errorRole = Qt::UserRole + 8, + errorMessageRole = Qt::UserRole + 9 + }; + QHash roleNames() const; + + enum SortingCriteria { + sortByDate, + sortByCategory, + sortByTitle + }; + QHash sortingNames() const; + + Qt::ItemFlags flags(const QModelIndex &index) const; + virtual int rowCount(const QModelIndex &parent) const; + virtual QVariant data(const QModelIndex &index, int role) const; + //virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const; + //virtual bool setData(const QModelIndex &index, const QVariant &value, int role); + + //bool insertRow(int row, const QModelIndex &parent); + //bool insertRows(int row, int count, const QModelIndex &parent); + //bool removeRow(int row, const QModelIndex &parent); + //bool removeRows(int row, int count, const QModelIndex &parent); + +protected: + static bool noteLessThanByDate(const Note &n1, const Note &n2); + static bool noteLessThanByCategory(const Note &n1, const Note &n2); + static bool noteLessThanByTitle(const Note &n1, const Note &n2); + +signals: + void sortByChanged(int sortBy); + void favoritesOnTopChanged(bool favoritesOnTop); + +private: + QList m_notes; + int m_sortBy; + bool m_favoritesOnTop; + + void sort(); +}; + +#endif // NOTESMODEL_H diff --git a/translations/harbour-nextcloudnotes.ts b/translations/harbour-nextcloudnotes.ts index a7522c7..49b7fdb 100644 --- a/translations/harbour-nextcloudnotes.ts +++ b/translations/harbour-nextcloudnotes.ts @@ -272,17 +272,17 @@ NotesApi - + Unable to connect - + Today - + Yesterday