Worked on the C++ model and its integration

This commit is contained in:
Scharel Clemens 2019-03-10 20:20:41 +01:00
parent fc8072bb60
commit 87f7ba83fd
10 changed files with 165 additions and 145 deletions

View file

@ -3,11 +3,9 @@ import Sailfish.Silica 1.0
import Nemo.Configuration 1.0 import Nemo.Configuration 1.0
Item { Item {
property string uuid
property string response property string response
property var categories: [ ] property var categories: [ ]
property string file: StandardPaths.data + "/" + uuid + ".json" property string file: StandardPaths.data + "/" + appSettings.currentAccount + ".json"
property bool saveFile: false property bool saveFile: false
property bool busy: jobsRunning > 0 property bool busy: jobsRunning > 0
property int jobsRunning: 0 property int jobsRunning: 0
@ -17,13 +15,17 @@ Item {
onStatusChanged: { onStatusChanged: {
console.log("Network status: " + statusText + " (" + status + ")") console.log("Network status: " + statusText + " (" + status + ")")
} }
onUuidChanged: {
appSettings.currentAccount = uuid /*function getNote(id) {
account.path = "/apps/harbour-nextcloudnotes/accounts/" + uuid var dict
onUuidChanged: console.log("Account : " + account.name) if (id) {
} for (var i = 0; i < model.count; i++) {
/*function clear() { dict = model.get(i)
account.clear() if (dict.id === id) {
return dict
}
}
}
}*/ }*/
function apiCall(method, data) { function apiCall(method, data) {
@ -52,7 +54,7 @@ Item {
apiReq.setRequestHeader("Content-Type", "application/json") apiReq.setRequestHeader("Content-Type", "application/json")
apiReq.setRequestHeader("Authorization", "Basic " + Qt.btoa(account.username + ":" + account.password)) apiReq.setRequestHeader("Authorization", "Basic " + Qt.btoa(account.username + ":" + account.password))
apiReq.withCredentials = true apiReq.withCredentials = true
apiReq.timeout = 5000 //apiReq.timeout = 5000
apiReq.onreadystatechange = function() { apiReq.onreadystatechange = function() {
if (apiReq.readyState === XMLHttpRequest.DONE) { if (apiReq.readyState === XMLHttpRequest.DONE) {
statusText = apiReq.statusText statusText = apiReq.statusText
@ -92,18 +94,6 @@ Item {
} }
} }
function getNote(id) {
var dict
if (id) {
for (var i = 0; i < model.count; i++) {
dict = model.get(i)
if (dict.id === id) {
return dict
}
}
}
}
function getNotesFromApi() { function getNotesFromApi() {
apiCall("GET") apiCall("GET")
} }
@ -132,7 +122,7 @@ Item {
} }
// source: https://stackoverflow.com/a/14339782 // source: https://stackoverflow.com/a/14339782
function getPrettyDate(date) { /*function getPrettyDate(date) {
var today = new Date() var today = new Date()
today.setHours(0) today.setHours(0)
today.setMinutes(0) today.setMinutes(0)
@ -154,7 +144,7 @@ Item {
} else { } else {
return compDate.toLocaleDateString(Qt.locale(), "MMMM yyyy") return compDate.toLocaleDateString(Qt.locale(), "MMMM yyyy")
} }
} }*/
/*Component.onCompleted: { /*Component.onCompleted: {
if (saveFile) { if (saveFile) {

View file

@ -19,6 +19,7 @@ ApplicationWindow
ConfigurationGroup { ConfigurationGroup {
id: account id: account
path: "/apps/harbour-nextcloudnotes/accounts/" + appSettings.currentAccount path: "/apps/harbour-nextcloudnotes/accounts/" + appSettings.currentAccount
property string name: value("name", "", String) property string name: value("name", "", String)
property url server: value("server", "", String) property url server: value("server", "", String)
property string version: value("version", "v0.2", String) property string version: value("version", "v0.2", String)
@ -28,22 +29,27 @@ ApplicationWindow
property bool unencryptedConnection: account.value("unencryptedConnection", false, Boolean) property bool unencryptedConnection: account.value("unencryptedConnection", false, Boolean)
property date update: value("update", "", Date) property date update: value("update", "", Date)
onValuesChanged: console.log("A property of the current account has changed") onValuesChanged: console.log("A property of the current account has changed")
onNameChanged: console.log("Account: " + name)
} }
ConfigurationGroup { ConfigurationGroup {
id: appSettings id: appSettings
path: "/apps/harbour-nextcloudnotes/settings" path: "/apps/harbour-nextcloudnotes/settings"
property string currentAccount: value("currentAccount", "") property string currentAccount: value("currentAccount", "", String)
property var accountIDs: value("accountIDs", [ ]) property var accountIDs: value("accountIDs", [ ], Array)
property int autoSyncInterval: value("autoSyncInterval", 0) property int autoSyncInterval: value("autoSyncInterval", 0, Number)
property int previewLineCount: value("previewLineCount", 4) property int previewLineCount: value("previewLineCount", 4, Number)
property bool favoritesOnTop: value("favoritesOnTop", true, Boolean) property bool favoritesOnTop: value("favoritesOnTop", true, Boolean)
property string sortBy: value("sortBy", "date", String) property string sortBy: value("sortBy", "date", String)
property bool showSeparator: value("showSeparator", false, Boolean) property bool showSeparator: value("showSeparator", false, Boolean)
property bool useMonoFont: value("useMonoFont", false, Boolean) property bool useMonoFont: value("useMonoFont", false, Boolean)
property bool useCapitalX: value("useCapitalX", false, Boolean) property bool useCapitalX: value("useCapitalX", false, Boolean)
onCurrentAccountChanged: api.uuid = currentAccount onCurrentAccountChanged: {
account.path = "/apps/harbour-nextcloudnotes/accounts/" + currentAccount
noteListModel.clear()
api.getNotesFromApi()
}
function addAccount() { function addAccount() {
var uuid = uuidv4() var uuid = uuidv4()
@ -66,13 +72,15 @@ ApplicationWindow
} }
}) })
accounts.value = newIds accounts.value = newIds
for (var i = accountIDs.length-1; i > 0; i--) { for (var i = accountIDs.length-1; i >= 0; i--) {
if (accountIDs[i] !== uuid) { if (accountIDs[i] !== uuid) {
api.uuid = accountIDs[i] api.uuid = accountIDs[i]
break break
} }
} }
autoSyncTimer.start() if (autoSyncInterval > 0 && appWindow.visible) {
autoSyncTimer.start()
}
} }
function uuidv4() { function uuidv4() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
@ -103,31 +111,24 @@ ApplicationWindow
triggeredOnStart = true triggeredOnStart = true
} }
} }
onIntervalChanged: console.log("Auto-Sync every " + interval / 1000 + " seconds") onIntervalChanged: {
if (interval > 0) {
console.log("Auto-Sync every " + interval / 1000 + " seconds")
}
}
} }
NotesApi { NotesApi {
id: api id: api
uuid: appSettings.currentAccount
onResponseChanged: noteListModel.applyJSON(response) onResponseChanged: noteListModel.applyJSON(response)
onUuidChanged: noteListModel.clear()
} }
NotesModel { NotesModel {
id: noteListModel id: noteListModel
sortBy: 0 // TODO sortBy: appSettings.sortBy
favoritesOnTop: appSettings.favoritesOnTop favoritesOnTop: appSettings.favoritesOnTop
} }
/*NoteDelegateModel {
id: noteListModel
model: api.model
favoritesOnTop: appSettings.favoritesOnTop
sortBy: appSettings.sortBy
showSeparator: appSettings.showSeparator
previewLineCount: appSettings.previewLineCount
}*/
initialPage: Component { NotesPage { } } initialPage: Component { NotesPage { } }
cover: Qt.resolvedUrl("cover/CoverPage.qml") cover: Qt.resolvedUrl("cover/CoverPage.qml")
allowedOrientations: defaultAllowedOrientations allowedOrientations: defaultAllowedOrientations

View file

@ -60,10 +60,9 @@ Page {
TextSwitch { TextSwitch {
id: accountTextSwitch id: accountTextSwitch
automaticCheck: false automaticCheck: false
checked: modelData === api.uuid checked: modelData === appSettings.currentAccount
onClicked: { onClicked: {
api.uuid = modelData appSettings.currentAccount = modelData
api.getNotesFromApi()
} }
onPressAndHold: openMenu() onPressAndHold: openMenu()
} }
@ -144,27 +143,30 @@ Page {
} }
ComboBox { ComboBox {
id: sortByComboBox id: sortByComboBox
property var names: [qsTr("Last edited"), qsTr("Category"), qsTr("Title alphabetically")] property var names: { "date" : qsTr("Last edited"),
"category" : qsTr("Category"),
"title" : qsTr("Title alphabetically"),
"none" : qsTr("No sorting") }
label: qsTr("Sort notes by") label: qsTr("Sort notes by")
description: qsTr("This will also change how the notes are grouped") description: qsTr("This will also change how the notes are grouped")
menu: ContextMenu { menu: ContextMenu {
Repeater { Repeater {
id: sortByRepeater id: sortByRepeater
model: ["date", "category", "title"] model: noteListModel.sortingCriteria()
MenuItem { MenuItem {
text: sortByComboBox.names[index] text: sortByComboBox.names[modelData]
//enabled: modelData !== "title"
Component.onCompleted: { Component.onCompleted: {
if (modelData === appSettings.sortBy) { if (modelData === appSettings.sortBy) {
sortByComboBox.currentIndex = index sortByComboBox.currentIndex = index
} }
} }
onClicked: appSettings.sortBy = modelData
} }
} }
} }
onCurrentIndexChanged: { /*onCurrentIndexChanged: {
appSettings.sortBy = sortByRepeater.model[currentIndex] appSettings.sortBy = sortByRepeater.model[currentIndex]
} }*/
} }
TextSwitch { TextSwitch {
text: qsTr("Favorites on top") text: qsTr("Favorites on top")

View file

@ -16,6 +16,7 @@ Note::Note(const Note& note, QObject *parent) : QObject(parent) {
m_etag = note.etag(); m_etag = note.etag();
m_error = note.error(); m_error = note.error();
m_errorMessage = note.errorMessage(); m_errorMessage = note.errorMessage();
m_date = note.date();
} }
Note& Note::operator=(const Note& note) { Note& Note::operator=(const Note& note) {
@ -28,6 +29,7 @@ Note& Note::operator=(const Note& note) {
m_etag = note.etag(); m_etag = note.etag();
m_error = note.error(); m_error = note.error();
m_errorMessage = note.errorMessage(); m_errorMessage = note.errorMessage();
m_date = note.date();
return *this; return *this;
} }

View file

@ -3,6 +3,8 @@
#include <QObject> #include <QObject>
#include <QJsonObject> #include <QJsonObject>
#include <QDateTime>
#include <QDebug>
class Note : public QObject { class Note : public QObject {
Q_OBJECT Q_OBJECT
@ -16,6 +18,7 @@ class Note : public QObject {
Q_PROPERTY(QString etag READ etag WRITE setEtag NOTIFY etagChanged) Q_PROPERTY(QString etag READ etag WRITE setEtag NOTIFY etagChanged)
Q_PROPERTY(bool error READ error WRITE setError NOTIFY errorChanged) Q_PROPERTY(bool error READ error WRITE setError NOTIFY errorChanged)
Q_PROPERTY(QString errorMessage READ errorMessage WRITE setErrorMessage NOTIFY errorMessageChanged) Q_PROPERTY(QString errorMessage READ errorMessage WRITE setErrorMessage NOTIFY errorMessageChanged)
Q_PROPERTY(QString date READ date NOTIFY dateChanged)
public: public:
Note(QObject *parent = NULL); Note(QObject *parent = NULL);
@ -30,9 +33,30 @@ public:
QString etag() const { return m_etag; } QString etag() const { return m_etag; }
bool error() const { return m_error; } bool error() const { return m_error; }
QString errorMessage() const { return m_errorMessage; } QString errorMessage() const { return m_errorMessage; }
QString date() const { return m_date; }
void setId(int id) { if (id != m_id) { m_id = id; emit idChanged(id); } } void setId(int id) { if (id != m_id) { m_id = id; emit idChanged(id); } }
void setModified(uint modified) { if (modified != m_modified) { m_modified = modified; emit modifiedChanged(modified); } } void setModified(uint modified) {
if (modified != m_modified) {
m_modified = modified;
QDateTime date;
QString newDate;
date.setTime_t(modified);
qint64 diff = date.daysTo(QDateTime::currentDateTime());
if (diff == 0)
newDate = "Today";
else if (diff == 1)
newDate = "Yesterday";
else if (diff < 7)
newDate = date.toLocalTime().toString("dddd");
else if (date.toLocalTime().toString("yyyy") == QDateTime::currentDateTime().toString("yyyy"))
newDate = date.toLocalTime().toString("MMMM");
else
newDate = date.toLocalTime().toString("MMMM yyyy");
if (newDate != m_date) { m_date = newDate; emit dateChanged(newDate); }
emit modifiedChanged(modified);
}
}
void setTitle(QString title) { if (title != m_title) { m_title = title; emit titleChanged(title); } } void setTitle(QString title) { if (title != m_title) { m_title = title; emit titleChanged(title); } }
void setCategory(QString category) { if (category != m_category) { m_category = category; emit categoryChanged(category); } } void setCategory(QString category) { if (category != m_category) { m_category = category; emit categoryChanged(category); } }
void setContent(QString content) { if (content != m_content) { m_content = content; emit contentChanged(content); } } void setContent(QString content) { if (content != m_content) { m_content = content; emit contentChanged(content); } }
@ -40,6 +64,7 @@ public:
void setEtag(QString etag) { if (etag != m_etag) { m_etag = etag; emit etagChanged(etag); } } void setEtag(QString etag) { if (etag != m_etag) { m_etag = etag; emit etagChanged(etag); } }
void setError(bool error) { if (error != m_error) { m_error = error; emit errorChanged(error); } } void setError(bool error) { if (error != m_error) { m_error = error; emit errorChanged(error); } }
void setErrorMessage(QString errorMessage) { if (errorMessage != m_errorMessage) { m_errorMessage = errorMessage; emit errorMessageChanged(errorMessage); } } void setErrorMessage(QString errorMessage) { if (errorMessage != m_errorMessage) { m_errorMessage = errorMessage; emit errorMessageChanged(errorMessage); } }
void setDate(QString date) { if (date != m_date) { m_date = date; emit dateChanged(date); } }
Note& operator=(const Note& note); Note& operator=(const Note& note);
bool operator==(const Note& note) const { bool operator==(const Note& note) const {
@ -91,6 +116,7 @@ signals:
void etagChanged(QString etag); void etagChanged(QString etag);
void errorChanged(bool error); void errorChanged(bool error);
void errorMessageChanged(QString errorMessage); void errorMessageChanged(QString errorMessage);
void dateChanged(QString date);
private: private:
int m_id; int m_id;
@ -102,6 +128,7 @@ private:
QString m_etag; QString m_etag;
bool m_error; bool m_error;
QString m_errorMessage; QString m_errorMessage;
QString m_date;
}; };
Q_DECLARE_OPERATORS_FOR_FLAGS(Note::SearchAttributes) Q_DECLARE_OPERATORS_FOR_FLAGS(Note::SearchAttributes)

View file

@ -15,8 +15,8 @@ NotesModel::~NotesModel() {
clear(); clear();
} }
void NotesModel::setSortBy(int sortBy) { void NotesModel::setSortBy(QString sortBy) {
if (sortBy != m_sortBy && sortBy > 0 && sortBy <= noSorting) { if (sortBy != m_sortBy && sortingNames().values().contains(sortBy.toLocal8Bit())) {
m_sortBy = sortBy; m_sortBy = sortBy;
sort(); sort();
emit sortByChanged(m_sortBy); emit sortByChanged(m_sortBy);
@ -24,6 +24,7 @@ void NotesModel::setSortBy(int sortBy) {
} }
void NotesModel::setFavoritesOnTop(bool favoritesOnTop) { void NotesModel::setFavoritesOnTop(bool favoritesOnTop) {
qDebug() << "Changed favorites on top:" << favoritesOnTop;
if (favoritesOnTop != m_favoritesOnTop) { if (favoritesOnTop != m_favoritesOnTop) {
m_favoritesOnTop = favoritesOnTop; m_favoritesOnTop = favoritesOnTop;
sort(); sort();
@ -56,7 +57,7 @@ bool NotesModel::applyJSON(QString json, bool replaceIfArray) {
QJsonObject jobj = jval.toObject(); QJsonObject jobj = jval.toObject();
if (!jobj.isEmpty() && !jobj.value(roleNames()[ErrorRole]).toBool(true)) { if (!jobj.isEmpty() && !jobj.value(roleNames()[ErrorRole]).toBool(true)) {
//qDebug() << "Adding it to the model..."; //qDebug() << "Adding it to the model...";
Note* note = Note::fromjson(jobj); Note* note = Note::fromjson(jobj); // TODO connect signals
int position = indexOf(note->id()); int position = indexOf(note->id());
if (position >= 0 && replaceIfArray) { if (position >= 0 && replaceIfArray) {
//qDebug() << "Replacing note" << note.title << "on position" << position; //qDebug() << "Replacing note" << note.title << "on position" << position;
@ -103,7 +104,7 @@ bool NotesModel::applyJSON(QString json, bool replaceIfArray) {
//qDebug() << "It's a single object..."; //qDebug() << "It's a single object...";
QJsonObject jobj = jdoc.object(); QJsonObject jobj = jdoc.object();
if (!jobj.isEmpty() && !jobj.value(roleNames()[ErrorRole]).toBool(true)) { if (!jobj.isEmpty() && !jobj.value(roleNames()[ErrorRole]).toBool(true)) {
Note* note = Note::fromjson(jobj); Note* note = Note::fromjson(jobj); // TODO connect signals
int position = indexOf(note->id()); int position = indexOf(note->id());
if (position >= 0 && replaceIfArray) { if (position >= 0 && replaceIfArray) {
m_notes[position].note = note; m_notes[position].note = note;
@ -146,7 +147,7 @@ void NotesModel::clear() {
m_searchText.clear(); m_searchText.clear();
beginRemoveRows(QModelIndex(), 0, rowCount()); beginRemoveRows(QModelIndex(), 0, rowCount());
for (int i = 0; i < m_notes.size(); i++) { for (int i = 0; i < m_notes.size(); i++) {
delete m_notes[i].note; delete m_notes[i].note; // TODO disconnect signals
} }
m_notes.clear(); m_notes.clear();
endRemoveRows(); endRemoveRows();
@ -212,7 +213,8 @@ QHash<int, QByteArray> NotesModel::roleNames() const {
{NotesModel::FavoriteRole, "favorite"}, {NotesModel::FavoriteRole, "favorite"},
{NotesModel::EtagRole, "etag"}, {NotesModel::EtagRole, "etag"},
{NotesModel::ErrorRole, "error"}, {NotesModel::ErrorRole, "error"},
{NotesModel::ErrorMessageRole, "errorMessage"} {NotesModel::ErrorMessageRole, "errorMessage"},
{NotesModel::DateRole, "date"}
}; };
} }
@ -225,6 +227,14 @@ QHash<int, QByteArray> NotesModel::sortingNames() const {
return criteria; return criteria;
} }
QStringList NotesModel::sortingCriteria() const {
QStringList criteria;
QHash<int, QByteArray> names = sortingNames();
for (int i = 0; i <= noSorting; i++)
criteria << names[i];
return criteria;
}
Qt::ItemFlags NotesModel::flags(const QModelIndex &index) const { Qt::ItemFlags NotesModel::flags(const QModelIndex &index) const {
if (index.isValid()) { if (index.isValid()) {
return Qt::ItemIsEnabled | Qt::ItemIsEditable; // | Qt::ItemIsSelectable return Qt::ItemIsEnabled | Qt::ItemIsEditable; // | Qt::ItemIsSelectable
@ -255,6 +265,7 @@ QVariant NotesModel::data(const QModelIndex &index, int role) const {
else if (role == EtagRole) return m_notes[index.row()].note->etag(); else if (role == EtagRole) return m_notes[index.row()].note->etag();
else if (role == ErrorRole) return m_notes[index.row()].note->error(); else if (role == ErrorRole) return m_notes[index.row()].note->error();
else if (role == ErrorMessageRole) return m_notes[index.row()].note->errorMessage(); else if (role == ErrorMessageRole) return m_notes[index.row()].note->errorMessage();
else if (role == DateRole) return m_notes[index.row()].note->date();
return QVariant(); return QVariant();
} }
@ -273,25 +284,26 @@ bool NotesModel::setData(const QModelIndex &index, const QVariant &value, int ro
if (!index.isValid()) return false; if (!index.isValid()) return false;
else if (role == ModifiedRole && m_notes[index.row()].note->modified() != value.toUInt()) { else if (role == ModifiedRole && m_notes[index.row()].note->modified() != value.toUInt()) {
m_notes[index.row()].note->setModified(value.toInt()); m_notes[index.row()].note->setModified(value.toInt());
emit dataChanged(this->index(index.row()), this->index(index.row()), QVector<int> { 1, role } ); emit dataChanged(this->index(index.row()), this->index(index.row()), QVector<int> { 1, role } ); // TODO remove when signals from Note are connected
emit dataChanged(this->index(index.row()), this->index(index.row()), QVector<int> { 1, DateRole} ); // TODO remove when signals from Note are connected
sort(); sort();
return true; return true;
} }
else if (role == CategoryRole && m_notes[index.row()].note->category() != value.toString()) { else if (role == CategoryRole && m_notes[index.row()].note->category() != value.toString()) {
m_notes[index.row()].note->setCategory(value.toString()); m_notes[index.row()].note->setCategory(value.toString());
emit dataChanged(this->index(index.row()), this->index(index.row()), QVector<int> { 1, role } ); emit dataChanged(this->index(index.row()), this->index(index.row()), QVector<int> { 1, role } ); // TODO remove when signals from Note are connected
sort(); sort();
return true; return true;
} }
else if (role == ContentRole && m_notes[index.row()].note->content() != value.toString()) { else if (role == ContentRole && m_notes[index.row()].note->content() != value.toString()) {
m_notes[index.row()].note->setContent(value.toString()); m_notes[index.row()].note->setContent(value.toString());
emit dataChanged(this->index(index.row()), this->index(index.row()), QVector<int> { 1, role } ); emit dataChanged(this->index(index.row()), this->index(index.row()), QVector<int> { 1, role } ); // TODO remove when signals from Note are connected
sort(); sort();
return true; return true;
} }
else if (role == FavoriteRole && m_notes[index.row()].note->favorite() != value.toBool()) { else if (role == FavoriteRole && m_notes[index.row()].note->favorite() != value.toBool()) {
m_notes[index.row()].note->setFavorite(value.toBool()); m_notes[index.row()].note->setFavorite(value.toBool());
emit dataChanged(this->index(index.row()), this->index(index.row()), QVector<int> { 1, role } ); emit dataChanged(this->index(index.row()), this->index(index.row()), QVector<int> { 1, role } ); // TODO remove when signals from Note are connected
sort(); sort();
return true; return true;
} }
@ -311,11 +323,11 @@ bool NotesModel::setItemData(const QModelIndex &index, const QMap<int, QVariant>
} }
void NotesModel::sort() { void NotesModel::sort() {
qDebug() << "Sorting notes in the model";
QList<ModelNote<Note*, bool> > notes; QList<ModelNote<Note*, bool> > notes;
QMap<QString, ModelNote<Note*, bool> > map; QMap<QString, ModelNote<Note*, bool> > map;
QMap<QString, ModelNote<Note*, bool> > favorites; QMap<QString, ModelNote<Note*, bool> > favorites;
switch (m_sortBy) { if (m_sortBy == sortingNames()[sortByDate]) {
case sortByDate:
emit layoutAboutToBeChanged(QList<QPersistentModelIndex> (), VerticalSortHint); emit layoutAboutToBeChanged(QList<QPersistentModelIndex> (), VerticalSortHint);
for (int i = 0; i < m_notes.size(); i++) { for (int i = 0; i < m_notes.size(); i++) {
if (m_favoritesOnTop && m_notes[i].note->favorite()) if (m_favoritesOnTop && m_notes[i].note->favorite())
@ -327,8 +339,8 @@ void NotesModel::sort() {
notes.append(map.values()); notes.append(map.values());
m_notes = notes; m_notes = notes;
emit layoutChanged(QList<QPersistentModelIndex> (), VerticalSortHint); emit layoutChanged(QList<QPersistentModelIndex> (), VerticalSortHint);
break; }
case sortByCategory: else if (m_sortBy == sortingNames()[sortByCategory]) {
emit layoutAboutToBeChanged(QList<QPersistentModelIndex> (), VerticalSortHint); emit layoutAboutToBeChanged(QList<QPersistentModelIndex> (), VerticalSortHint);
for (int i = 0; i < m_notes.size(); i++) { for (int i = 0; i < m_notes.size(); i++) {
if (m_favoritesOnTop && m_notes[i].note->favorite()) if (m_favoritesOnTop && m_notes[i].note->favorite())
@ -340,8 +352,8 @@ void NotesModel::sort() {
notes.append(map.values()); notes.append(map.values());
m_notes = notes; m_notes = notes;
emit layoutChanged(QList<QPersistentModelIndex> (), VerticalSortHint); emit layoutChanged(QList<QPersistentModelIndex> (), VerticalSortHint);
break; }
case sortByTitle: else if (m_sortBy == sortingNames()[sortByTitle]) {
emit layoutAboutToBeChanged(QList<QPersistentModelIndex> (), VerticalSortHint); emit layoutAboutToBeChanged(QList<QPersistentModelIndex> (), VerticalSortHint);
for (int i = 0; i < m_notes.size(); i++) { for (int i = 0; i < m_notes.size(); i++) {
if (m_favoritesOnTop && m_notes[i].note->favorite()) if (m_favoritesOnTop && m_notes[i].note->favorite())
@ -353,34 +365,31 @@ void NotesModel::sort() {
notes.append(map.values()); notes.append(map.values());
m_notes = notes; m_notes = notes;
emit layoutChanged(QList<QPersistentModelIndex> (), VerticalSortHint); emit layoutChanged(QList<QPersistentModelIndex> (), VerticalSortHint);
break;
default:
break;
} }
} }
bool NotesModel::noteLessThan(const Note &n1, const Note &n2) const { bool NotesModel::noteLessThan(const Note &n1, const Note &n2) const {
switch (m_sortBy) { if (m_sortBy == sortingNames()[sortByDate]) {
case sortByDate:
if (m_favoritesOnTop && n1.favorite() != n2.favorite()) if (m_favoritesOnTop && n1.favorite() != n2.favorite())
return n1.favorite(); return n1.favorite();
else else
return n1.modified() > n2.modified(); return n1.modified() > n2.modified();
break; }
case sortByCategory: else if (m_sortBy == sortingNames()[sortByCategory]) {
if (m_favoritesOnTop && n1.favorite() != n2.favorite()) if (m_favoritesOnTop && n1.favorite() != n2.favorite())
return n1.favorite(); return n1.favorite();
else else
return n1.category() < n2.category(); return n1.category() < n2.category();
break; }
case sortByTitle: else if (m_sortBy == sortingNames()[sortByTitle]) {
if (m_favoritesOnTop && n1.favorite() != n2.favorite()) if (m_favoritesOnTop && n1.favorite() != n2.favorite())
return n1.favorite(); return n1.favorite();
else else
return n1.title() < n2.title(); return n1.title() < n2.title();
break; }
default: else {
break; if (m_favoritesOnTop && n1.favorite() != n2.favorite())
return n1.favorite();
} }
return true; return true;
} }

View file

@ -17,9 +17,9 @@ public:
explicit NotesModel(QObject *parent = 0); explicit NotesModel(QObject *parent = 0);
virtual ~NotesModel(); virtual ~NotesModel();
Q_PROPERTY(int sortBy READ sortBy WRITE setSortBy NOTIFY sortByChanged) Q_PROPERTY(QString sortBy READ sortBy WRITE setSortBy NOTIFY sortByChanged)
int sortBy() const { return m_sortBy; } QString sortBy() const { return m_sortBy; }
void setSortBy(int sortBy); void setSortBy(QString sortBy);
Q_PROPERTY(bool favoritesOnTop READ favoritesOnTop WRITE setFavoritesOnTop NOTIFY favoritesOnTopChanged) Q_PROPERTY(bool favoritesOnTop READ favoritesOnTop WRITE setFavoritesOnTop NOTIFY favoritesOnTopChanged)
bool favoritesOnTop() const { return m_favoritesOnTop; } bool favoritesOnTop() const { return m_favoritesOnTop; }
@ -49,7 +49,8 @@ public:
FavoriteRole = Qt::UserRole + 6, FavoriteRole = Qt::UserRole + 6,
EtagRole = Qt::UserRole + 7, EtagRole = Qt::UserRole + 7,
ErrorRole = Qt::UserRole + 8, ErrorRole = Qt::UserRole + 8,
ErrorMessageRole = Qt::UserRole + 9 ErrorMessageRole = Qt::UserRole + 9,
DateRole = Qt::UserRole + 10
}; };
QHash<int, QByteArray> roleNames() const; QHash<int, QByteArray> roleNames() const;
@ -60,6 +61,7 @@ public:
noSorting noSorting
}; };
QHash<int, QByteArray> sortingNames() const; QHash<int, QByteArray> sortingNames() const;
Q_INVOKABLE QStringList sortingCriteria() const;
Qt::ItemFlags flags(const QModelIndex &index) const; Qt::ItemFlags flags(const QModelIndex &index) const;
virtual int rowCount(const QModelIndex &parent = QModelIndex()) const; virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
@ -78,13 +80,13 @@ protected:
signals: signals:
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles = QVector<int> ()); void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles = QVector<int> ());
void sortByChanged(int sortBy); void sortByChanged(QString sortBy);
void favoritesOnTopChanged(bool favoritesOnTop); void favoritesOnTopChanged(bool favoritesOnTop);
void searchTextChanged(QString searchText); void searchTextChanged(QString searchText);
private: private:
QList<ModelNote<Note*, bool> > m_notes; QList<ModelNote<Note*, bool> > m_notes;
int m_sortBy; QString m_sortBy;
bool m_favoritesOnTop; bool m_favoritesOnTop;
QString m_searchText; QString m_searchText;

View file

@ -223,14 +223,6 @@
</context> </context>
<context> <context>
<name>NotesApi</name> <name>NotesApi</name>
<message>
<source>Today</source>
<translation>Heute</translation>
</message>
<message>
<source>Yesterday</source>
<translation>Gestern</translation>
</message>
<message> <message>
<source>Unable to connect</source> <source>Unable to connect</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
@ -457,6 +449,10 @@
<source>Show notes marked as favorite above the others</source> <source>Show notes marked as favorite above the others</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>No sorting</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>SyntaxPage</name> <name>SyntaxPage</name>

View file

@ -223,14 +223,6 @@
</context> </context>
<context> <context>
<name>NotesApi</name> <name>NotesApi</name>
<message>
<source>Today</source>
<translation>I dag</translation>
</message>
<message>
<source>Yesterday</source>
<translation>I går</translation>
</message>
<message> <message>
<source>Unable to connect</source> <source>Unable to connect</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
@ -457,6 +449,10 @@
<source>Show notes marked as favorite above the others</source> <source>Show notes marked as favorite above the others</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>No sorting</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>SyntaxPage</name> <name>SyntaxPage</name>

View file

@ -272,20 +272,10 @@
<context> <context>
<name>NotesApi</name> <name>NotesApi</name>
<message> <message>
<location filename="../qml/components/NotesApi.qml" line="65"/> <location filename="../qml/components/NotesApi.qml" line="67"/>
<source>Unable to connect</source> <source>Unable to connect</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<location filename="../qml/components/NotesApi.qml" line="147"/>
<source>Today</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/components/NotesApi.qml" line="149"/>
<source>Yesterday</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>NotesPage</name> <name>NotesPage</name>
@ -413,87 +403,92 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/SettingsPage.qml" line="72"/> <location filename="../qml/pages/SettingsPage.qml" line="71"/>
<source>Edit</source> <source>Edit</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/SettingsPage.qml" line="78"/> <location filename="../qml/pages/SettingsPage.qml" line="77"/>
<source>Delete</source> <source>Delete</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/SettingsPage.qml" line="80"/> <location filename="../qml/pages/SettingsPage.qml" line="79"/>
<source>Deleting account</source> <source>Deleting account</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/SettingsPage.qml" line="90"/> <location filename="../qml/pages/SettingsPage.qml" line="89"/>
<source>Add account</source> <source>Add account</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/SettingsPage.qml" line="99"/> <location filename="../qml/pages/SettingsPage.qml" line="98"/>
<source>Synchronization</source> <source>Synchronization</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/SettingsPage.qml" line="103"/> <location filename="../qml/pages/SettingsPage.qml" line="102"/>
<source>Auto-Sync</source> <source>Auto-Sync</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/SettingsPage.qml" line="104"/> <location filename="../qml/pages/SettingsPage.qml" line="103"/>
<source>Periodically pull notes from the server</source> <source>Periodically pull notes from the server</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/SettingsPage.qml" line="111"/> <location filename="../qml/pages/SettingsPage.qml" line="110"/>
<source>Disabled</source> <source>Disabled</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/SettingsPage.qml" line="111"/> <location filename="../qml/pages/SettingsPage.qml" line="110"/>
<source>every</source> <source>every</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/SettingsPage.qml" line="113"/> <location filename="../qml/pages/SettingsPage.qml" line="112"/>
<source>Minutes</source> <source>Minutes</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/SettingsPage.qml" line="114"/> <location filename="../qml/pages/SettingsPage.qml" line="113"/>
<source>Seconds</source> <source>Seconds</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/SettingsPage.qml" line="134"/> <location filename="../qml/pages/SettingsPage.qml" line="133"/>
<source>The Answer is 42</source> <source>The Answer is 42</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/SettingsPage.qml" line="135"/> <location filename="../qml/pages/SettingsPage.qml" line="134"/>
<source>Congratulation you found the Answer to the Ultimate Question of Life, The Universe, and Everything!</source> <source>Congratulation you found the Answer to the Ultimate Question of Life, The Universe, and Everything!</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/SettingsPage.qml" line="143"/> <location filename="../qml/pages/SettingsPage.qml" line="142"/>
<source>Appearance</source> <source>Appearance</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/SettingsPage.qml" line="170"/> <location filename="../qml/pages/SettingsPage.qml" line="149"/>
<source>No sorting</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/pages/SettingsPage.qml" line="172"/>
<source>Favorites on top</source> <source>Favorites on top</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/SettingsPage.qml" line="171"/> <location filename="../qml/pages/SettingsPage.qml" line="173"/>
<source>Show notes marked as favorite above the others</source> <source>Show notes marked as favorite above the others</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/SettingsPage.qml" line="147"/> <location filename="../qml/pages/SettingsPage.qml" line="146"/>
<source>Last edited</source> <source>Last edited</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -503,62 +498,62 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/SettingsPage.qml" line="147"/> <location filename="../qml/pages/SettingsPage.qml" line="148"/>
<source>Title alphabetically</source> <source>Title alphabetically</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/SettingsPage.qml" line="148"/> <location filename="../qml/pages/SettingsPage.qml" line="150"/>
<source>Sort notes by</source> <source>Sort notes by</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/SettingsPage.qml" line="149"/> <location filename="../qml/pages/SettingsPage.qml" line="151"/>
<source>This will also change how the notes are grouped</source> <source>This will also change how the notes are grouped</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/SettingsPage.qml" line="176"/> <location filename="../qml/pages/SettingsPage.qml" line="178"/>
<source>Show separator</source> <source>Show separator</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/SettingsPage.qml" line="177"/> <location filename="../qml/pages/SettingsPage.qml" line="179"/>
<source>Show a separator line between the notes</source> <source>Show a separator line between the notes</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/SettingsPage.qml" line="187"/> <location filename="../qml/pages/SettingsPage.qml" line="189"/>
<source>lines</source> <source>lines</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/SettingsPage.qml" line="188"/> <location filename="../qml/pages/SettingsPage.qml" line="190"/>
<source>Number of lines in the preview</source> <source>Number of lines in the preview</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/SettingsPage.qml" line="193"/> <location filename="../qml/pages/SettingsPage.qml" line="195"/>
<source>Editing</source> <source>Editing</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/SettingsPage.qml" line="196"/> <location filename="../qml/pages/SettingsPage.qml" line="198"/>
<source>Monospaced font</source> <source>Monospaced font</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/SettingsPage.qml" line="197"/> <location filename="../qml/pages/SettingsPage.qml" line="199"/>
<source>Use a monospeced font to edit a note</source> <source>Use a monospeced font to edit a note</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/SettingsPage.qml" line="202"/> <location filename="../qml/pages/SettingsPage.qml" line="204"/>
<source>Capital &apos;X&apos; in checkboxes</source> <source>Capital &apos;X&apos; in checkboxes</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/SettingsPage.qml" line="203"/> <location filename="../qml/pages/SettingsPage.qml" line="205"/>
<source>For interoperability with other apps such as Joplin</source> <source>For interoperability with other apps such as Joplin</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>