Implemented API in C++. Next: I discovered QSortFilterProxyModel :)
This commit is contained in:
parent
a026c2ee8d
commit
3f128bcd63
16 changed files with 334 additions and 660 deletions
|
@ -18,13 +18,11 @@ DEFINES += APP_VERSION=\\\"$$VERSION\\\"
|
|||
|
||||
HEADERS += \
|
||||
src/notesapi.h \
|
||||
src/sslconfiguration.h \
|
||||
src/notesmodel.h \
|
||||
src/note.h
|
||||
|
||||
SOURCES += src/harbour-nextcloudnotes.cpp \
|
||||
src/notesapi.cpp \
|
||||
src/sslconfiguration.cpp \
|
||||
src/notesmodel.cpp \
|
||||
src/note.cpp
|
||||
|
||||
|
@ -46,8 +44,7 @@ DISTFILES += qml/harbour-nextcloudnotes.qml \
|
|||
qml/pages/NotesApi.qml \
|
||||
qml/pages/MITLicense.qml \
|
||||
qml/pages/GPLLicense.qml \
|
||||
qml/pages/SyntaxPage.qml \
|
||||
qml/components/NotesApi.qml
|
||||
qml/pages/SyntaxPage.qml
|
||||
|
||||
SAILFISHAPP_ICONS = 86x86 108x108 128x128 172x172
|
||||
|
||||
|
|
|
@ -1,175 +0,0 @@
|
|||
import QtQuick 2.5
|
||||
import Sailfish.Silica 1.0
|
||||
import Nemo.Configuration 1.0
|
||||
|
||||
Item {
|
||||
property string response
|
||||
property var categories: [ ]
|
||||
property string file: StandardPaths.data + "/" + appSettings.currentAccount + ".json"
|
||||
property bool saveFile: false
|
||||
property bool busy: jobsRunning > 0
|
||||
property int jobsRunning: 0
|
||||
property int status: 0 //204
|
||||
property string statusText: "No Content"
|
||||
|
||||
onStatusChanged: {
|
||||
//console.log("Network response: " + statusText + " (" + status + ")")
|
||||
}
|
||||
|
||||
/*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 apiCall(method, data) {
|
||||
jobsRunning++
|
||||
|
||||
var endpoint = account.server + "/index.php/apps/notes/api/" + account.version + "/notes"
|
||||
if (data) {
|
||||
if (method === "POST" || method === "PUT") {
|
||||
console.log("Adding note...")
|
||||
}
|
||||
else if (data.id && method === "DELETE") {
|
||||
console.log("Deleting note...")
|
||||
}
|
||||
if (method === "GET" || method === "PUT" || method === "DELETE") {
|
||||
if (data.id) {
|
||||
endpoint = endpoint + "/" + data.id
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log("Calling " + endpoint)
|
||||
var apiReq = new XMLHttpRequest
|
||||
apiReq.open(method, endpoint, true)
|
||||
apiReq.setRequestHeader('User-Agent', 'SailfishOS/harbour-nextcloudnotes')
|
||||
apiReq.setRequestHeader('OCS-APIRequest', 'true')
|
||||
apiReq.setRequestHeader("Content-Type", "application/json")
|
||||
apiReq.setRequestHeader("Authorization", "Basic " + Qt.btoa(account.username + ":" + account.password))
|
||||
apiReq.withCredentials = true
|
||||
//apiReq.timeout = 5000
|
||||
apiReq.onreadystatechange = function() {
|
||||
if (apiReq.readyState === XMLHttpRequest.DONE) {
|
||||
statusText = apiReq.statusText
|
||||
status = apiReq.status
|
||||
if (apiReq.status === 200) {
|
||||
response = apiReq.responseText
|
||||
//console.log(response)
|
||||
console.log("Network response: " + statusText + " (" + status + ")")
|
||||
}
|
||||
else if(apiReq.status === 0) {
|
||||
statusText = qsTr("Unable to connect")
|
||||
}
|
||||
/*
|
||||
else if (apiReq.status === 304) {
|
||||
console.log("ETag does not differ!")
|
||||
}
|
||||
else if (apiReq.status === 401) {
|
||||
console.log("Unauthorized!")
|
||||
}
|
||||
else if (apiReq.status === 404) {
|
||||
console.log("Note does not exist!")
|
||||
}*/
|
||||
else {
|
||||
//console.log("Network error: " + apiReq.statusText + " (" + apiReq.status + ")")
|
||||
}
|
||||
jobsRunning--
|
||||
}
|
||||
}
|
||||
if (method === "GET") {
|
||||
apiReq.send()
|
||||
}
|
||||
else if (method === "POST" || method === "PUT" || method === "DELETE") {
|
||||
apiReq.send(JSON.stringify(data))
|
||||
}
|
||||
else {
|
||||
console.log("Unsupported method: " + method)
|
||||
apiReq.abort()
|
||||
}
|
||||
}
|
||||
|
||||
function getNotesFromApi() {
|
||||
apiCall("GET")
|
||||
}
|
||||
|
||||
function getNoteFromApi(id) {
|
||||
if (id) {
|
||||
apiCall("GET", { 'id': id } )
|
||||
}
|
||||
}
|
||||
|
||||
function createNote(data) {
|
||||
if (data)
|
||||
apiCall("POST", data)
|
||||
}
|
||||
|
||||
function updateNote(id, data) {
|
||||
if (id && data) {
|
||||
data.id = id
|
||||
apiCall("PUT", data)
|
||||
}
|
||||
}
|
||||
|
||||
function deleteNote(id) {
|
||||
if (id)
|
||||
apiCall("DELETE", { 'id': id } )
|
||||
}
|
||||
|
||||
// source: https://stackoverflow.com/a/14339782
|
||||
/*function getPrettyDate(date) {
|
||||
var today = new Date()
|
||||
today.setHours(0)
|
||||
today.setMinutes(0)
|
||||
today.setSeconds(0)
|
||||
today.setMilliseconds(0)
|
||||
var compDate = new Date(date*1000)
|
||||
compDate.setHours(0)
|
||||
compDate.setMinutes(0)
|
||||
compDate.setSeconds(0)
|
||||
compDate.setMilliseconds(0)
|
||||
if (compDate.getTime() === today.getTime()) {
|
||||
return qsTr("Today")
|
||||
} else if ((today.getTime() - compDate.getTime()) === (24 * 60 * 60 * 1000)) {
|
||||
return qsTr("Yesterday")
|
||||
} else if ((today.getTime() - compDate.getTime()) <= (7 * 24 * 60 * 60 * 1000)) {
|
||||
return compDate.toLocaleDateString(Qt.locale(), "dddd")
|
||||
} else if (today.getFullYear() === compDate.getFullYear()) {
|
||||
return compDate.toLocaleDateString(Qt.locale(), "MMMM")
|
||||
} else {
|
||||
return compDate.toLocaleDateString(Qt.locale(), "MMMM yyyy")
|
||||
}
|
||||
}*/
|
||||
|
||||
/*Component.onCompleted: {
|
||||
if (saveFile) {
|
||||
if (account.name === "") {
|
||||
saveFile = false
|
||||
}
|
||||
else {
|
||||
busy = true
|
||||
var fileReq = new XMLHttpRequest
|
||||
fileReq.open("GET", file)
|
||||
fileReq.onreadystatechange = function() {
|
||||
if (fileReq.readyState === XMLHttpRequest.DONE) {
|
||||
if (fileReq.responseText === "") {
|
||||
update()
|
||||
}
|
||||
else {
|
||||
console.log("Loaded " + account.name + " from local JSON file")
|
||||
json = fileReq.responseText
|
||||
busy = false
|
||||
}
|
||||
}
|
||||
}
|
||||
fileReq.send()
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
|
@ -2,10 +2,7 @@ import QtQuick 2.0
|
|||
import Sailfish.Silica 1.0
|
||||
import Nemo.Configuration 1.0
|
||||
import harbour.nextcloudnotes.notesapi 1.0
|
||||
import harbour.nextcloudnotes.notesmodel 1.0
|
||||
import harbour.nextcloudnotes.sslconfiguration 1.0
|
||||
import "pages"
|
||||
//import "components"
|
||||
|
||||
ApplicationWindow
|
||||
{
|
||||
|
@ -26,8 +23,8 @@ ApplicationWindow
|
|||
property string version: value("version", "v0.2", String)
|
||||
property string username: value("username", "", String)
|
||||
property string password: account.value("password", "", String)
|
||||
property bool unsecureConnection: account.value("unsecureConnection", false, Boolean)
|
||||
property bool unencryptedConnection: account.value("unencryptedConnection", false, Boolean)
|
||||
property bool doNotVerifySsl: account.value("doNotVerifySsl", false, Boolean)
|
||||
property bool allowUnecrypted: account.value("allowUnecrypted", false, Boolean)
|
||||
property date update: value("update", "", Date)
|
||||
onValuesChanged: console.log("A property of the current account has changed")
|
||||
onNameChanged: console.log("Account: " + name)
|
||||
|
@ -37,6 +34,7 @@ ApplicationWindow
|
|||
id: appSettings
|
||||
path: "/apps/harbour-nextcloudnotes/settings"
|
||||
|
||||
property bool initialized: false
|
||||
property string currentAccount: value("currentAccount", "", String)
|
||||
property var accountIDs: value("accountIDs", [ ], Array)
|
||||
property int autoSyncInterval: value("autoSyncInterval", 0, Number)
|
||||
|
@ -48,10 +46,12 @@ ApplicationWindow
|
|||
property bool useCapitalX: value("useCapitalX", false, Boolean)
|
||||
onCurrentAccountChanged: {
|
||||
account.path = "/apps/harbour-nextcloudnotes/accounts/" + currentAccount
|
||||
//noteListModel.clear()
|
||||
//api.getNotesFromApi()
|
||||
api.getAllNotes();
|
||||
account.sync()
|
||||
if (initialized)
|
||||
notesApi.getAllNotes();
|
||||
autoSyncTimer.restart()
|
||||
}
|
||||
Component.onCompleted: initialized = true
|
||||
|
||||
function addAccount() {
|
||||
var uuid = uuidv4()
|
||||
|
@ -88,26 +88,18 @@ ApplicationWindow
|
|||
}
|
||||
}
|
||||
|
||||
/*SslConfiguration {
|
||||
id: ssl
|
||||
checkCert: !account.unsecureConnection
|
||||
}*/
|
||||
|
||||
Timer {
|
||||
id: autoSyncTimer
|
||||
interval: appSettings.autoSyncInterval * 1000
|
||||
repeat: true
|
||||
running: interval > 0 && appWindow.visible
|
||||
triggeredOnStart: true
|
||||
triggeredOnStart: false
|
||||
onTriggered: {
|
||||
if (!api.busy) {
|
||||
//api.getNotesFromApi()
|
||||
api.getAllNotes();
|
||||
if (!notesApi.busy) {
|
||||
notesApi.getAllNotes();
|
||||
}
|
||||
else {
|
||||
triggeredOnStart = false
|
||||
restart()
|
||||
triggeredOnStart = true
|
||||
}
|
||||
}
|
||||
onIntervalChanged: {
|
||||
|
@ -118,33 +110,16 @@ ApplicationWindow
|
|||
}
|
||||
|
||||
NotesApi {
|
||||
id: api
|
||||
/*scheme: "https"
|
||||
id: notesApi
|
||||
scheme: account.allowUnecrypted ? "http" : "https"
|
||||
host: account.server
|
||||
path: "/index.php/apps/notes/api/" + account.version
|
||||
username: account.username
|
||||
password: account.password*/
|
||||
password: account.password
|
||||
sslVerify: !account.doNotVerifySsl
|
||||
Component.onCompleted: getAllNotes()
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
api.scheme = "https"
|
||||
api.host = account.server
|
||||
api.path = "/index.php/apps/notes/api/" + account.version
|
||||
api.username = account.username
|
||||
api.password = account.password
|
||||
}
|
||||
|
||||
/*NotesApi {
|
||||
id: api
|
||||
onResponseChanged: noteListModel.applyJSON(response)
|
||||
}
|
||||
|
||||
/*NotesModel {
|
||||
id: noteListModel
|
||||
sortBy: appSettisignangs.sortBy
|
||||
favoritesOnTop: appSettings.favoritesOnTop
|
||||
}*/
|
||||
|
||||
initialPage: Component { NotesPage { } }
|
||||
cover: Qt.resolvedUrl("cover/CoverPage.qml")
|
||||
allowedOrientations: defaultAllowedOrientations
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import QtQuick 2.0
|
||||
import Sailfish.Silica 1.0
|
||||
import harbour.nextcloudnotes.note 1.0
|
||||
import "../components"
|
||||
import harbour.nextcloudnotes.notesmodel 1.0
|
||||
|
||||
Page {
|
||||
id: page
|
||||
|
||||
property string searchText: ""
|
||||
property NotesModel notesModel: notesApi.model()
|
||||
|
||||
onStatusChanged: {
|
||||
if (status === PageStatus.Active) {
|
||||
|
@ -25,7 +25,7 @@ Page {
|
|||
spacing: Theme.paddingLarge
|
||||
|
||||
PullDownMenu {
|
||||
busy: api.busy
|
||||
busy: notesApi.busy
|
||||
|
||||
MenuItem {
|
||||
text: qsTr("Settings")
|
||||
|
@ -34,12 +34,12 @@ Page {
|
|||
MenuItem {
|
||||
text: qsTr("Add note")
|
||||
enabled: appSettings.currentAccount.length > 0
|
||||
onClicked: api.createNote( { 'content': "" } )
|
||||
onClicked: notesApi.createNote( { 'content': "" } )
|
||||
}
|
||||
MenuItem {
|
||||
text: enabled ? qsTr("Reload") : qsTr("Updating...")
|
||||
enabled: appSettings.currentAccount.length > 0 && !api.busy
|
||||
onClicked: api.getNotesFromApi()
|
||||
enabled: appSettings.currentAccount.length > 0 && !notesApi.busy
|
||||
onClicked: notesApi.getAllNotes()
|
||||
}
|
||||
MenuLabel {
|
||||
visible: appSettings.currentAccount.length > 0
|
||||
|
@ -59,7 +59,7 @@ Page {
|
|||
placeholderText: account.name.length > 0 ? account.name : qsTr("Nextcloud Notes")
|
||||
EnterKey.iconSource: "image://theme/icon-m-enter-close"
|
||||
EnterKey.onClicked: focus = false
|
||||
onTextChanged: noteListModel.searchText = text
|
||||
onTextChanged: notesModel.searchText = text
|
||||
}
|
||||
Label {
|
||||
id: description
|
||||
|
@ -70,24 +70,25 @@ Page {
|
|||
anchors.bottomMargin: Theme.paddingMedium
|
||||
color: Theme.secondaryHighlightColor
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
text: account.username + "@" + account.server.toString().split("://")[1]
|
||||
text: account.username + "@" + account.server
|
||||
}
|
||||
BusyIndicator {
|
||||
anchors.verticalCenter: searchField.verticalCenter
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: Theme.horizontalPageMargin
|
||||
size: BusyIndicatorSize.Medium
|
||||
running: api.busy && !busyIndicator.running
|
||||
running: notesApi.busy && !busyIndicator.running
|
||||
}
|
||||
}
|
||||
|
||||
currentIndex: -1
|
||||
|
||||
model: api.model()
|
||||
model: notesModel
|
||||
|
||||
delegate: BackgroundItem {
|
||||
id: note
|
||||
|
||||
visible: inSearch
|
||||
contentHeight: titleLabel.height + previewLabel.height + 2*Theme.paddingSmall
|
||||
height: contentHeight + menu.height
|
||||
width: parent.width
|
||||
|
@ -103,7 +104,7 @@ Page {
|
|||
}
|
||||
|
||||
onClicked: pageStack.push(Qt.resolvedUrl("../pages/NotePage.qml"),
|
||||
{ note: noteListModel.get(index),
|
||||
{ //note: noteListModel.get(index),
|
||||
id: id,
|
||||
modified: modified,
|
||||
title: title,
|
||||
|
@ -112,8 +113,8 @@ Page {
|
|||
favorite: favorite,
|
||||
etag: etag,
|
||||
error: error,
|
||||
errorMessage: errorMessage,
|
||||
date: date
|
||||
errorMessage: errorMessage
|
||||
//date: date
|
||||
})
|
||||
onPressAndHold: menu.open(note)
|
||||
|
||||
|
@ -131,7 +132,7 @@ Page {
|
|||
icon.source: (favorite ? "image://theme/icon-m-favorite-selected?" : "image://theme/icon-m-favorite?") +
|
||||
(note.highlighted ? Theme.secondaryHighlightColor : Theme.secondaryColor)
|
||||
onClicked: {
|
||||
api.updateNote(id, {'favorite': !favorite} )
|
||||
notesApi.updateNote(id, {'favorite': !favorite} )
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -201,7 +202,7 @@ Page {
|
|||
text: qsTr("Delete")
|
||||
onClicked: {
|
||||
remorse.execute(note, qsTr("Deleting note"), function() {
|
||||
api.deleteNote(id)
|
||||
notesApi.deleteNote(id)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -219,7 +220,7 @@ Page {
|
|||
id: busyIndicator
|
||||
anchors.centerIn: parent
|
||||
size: BusyIndicatorSize.Large
|
||||
running: notesList.count === 0 && api.busy
|
||||
running: notesList.count === 0 && notesApi.busy
|
||||
}
|
||||
Label {
|
||||
id: busyLabel
|
||||
|
@ -232,7 +233,7 @@ Page {
|
|||
horizontalAlignment: Qt.AlignHCenter
|
||||
text: qsTr("Loading notes...")
|
||||
}
|
||||
/*
|
||||
|
||||
ViewPlaceholder {
|
||||
id: noLoginPlaceholder
|
||||
enabled: appSettings.accountIDs.length <= 0
|
||||
|
@ -242,14 +243,14 @@ Page {
|
|||
|
||||
ViewPlaceholder {
|
||||
id: noNotesPlaceholder
|
||||
enabled: api.status === 204 && !busyIndicator.running && !noLoginPlaceholder.enabled
|
||||
enabled: notesApi.status === 204 && !busyIndicator.running && !noLoginPlaceholder.enabled
|
||||
text: qsTr("No notes yet")
|
||||
hintText: qsTr("Pull down to add a note")
|
||||
}
|
||||
|
||||
ViewPlaceholder {
|
||||
id: noSearchPlaceholder
|
||||
enabled: notesList.count === 0 && noteListModel.searchText !== ""
|
||||
enabled: notesList.count === 0 && notesModel.searchText !== ""
|
||||
text: qsTr("No result")
|
||||
hintText: qsTr("Try another query")
|
||||
}
|
||||
|
@ -258,9 +259,9 @@ Page {
|
|||
id: errorPlaceholder
|
||||
enabled: notesList.count === 0 && !busyIndicator.running && !noSearchPlaceholder.enabled && !noNotesPlaceholder.enabled && !noLoginPlaceholder.enabled
|
||||
text: qsTr("An error occurred")
|
||||
hintText: api.statusText
|
||||
hintText: notesApi.statusText
|
||||
}
|
||||
*/
|
||||
|
||||
TouchInteractionHint {
|
||||
id: addAccountHint
|
||||
interactionMode: TouchInteraction.Pull
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
#include "notesapi.h"
|
||||
#include "note.h"
|
||||
#include "notesmodel.h"
|
||||
#include "sslconfiguration.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
@ -20,7 +19,6 @@ int main(int argc, char *argv[])
|
|||
qmlRegisterType<NotesApi>("harbour.nextcloudnotes.notesapi", 1, 0, "NotesApi");
|
||||
qmlRegisterType<Note>("harbour.nextcloudnotes.note", 1, 0, "Note");
|
||||
qmlRegisterType<NotesModel>("harbour.nextcloudnotes.notesmodel", 1, 0, "NotesModel");
|
||||
qmlRegisterType<SslConfiguration>("harbour.nextcloudnotes.sslconfiguration", 1, 0, "SslConfiguration");
|
||||
|
||||
QQuickView* view = SailfishApp::createView();
|
||||
|
||||
|
|
36
src/note.cpp
36
src/note.cpp
|
@ -42,7 +42,7 @@ Note& Note::operator=(const Note& note) {
|
|||
}
|
||||
|
||||
bool Note::operator==(const Note& note) const {
|
||||
return same(note);
|
||||
return equal(note);
|
||||
}
|
||||
|
||||
bool Note::same(const Note& note) const {
|
||||
|
@ -118,3 +118,37 @@ bool Note::searchInNote(const QString &query, const Note ¬e, SearchAttributes
|
|||
}
|
||||
return queryFound;
|
||||
}
|
||||
|
||||
bool Note::lessThanByDate(const Note &n1, const Note &n2) {
|
||||
return n1.modified() > n2.modified();
|
||||
}
|
||||
|
||||
bool Note::lessThanByCategory(const Note &n1, const Note &n2) {
|
||||
return n1.category() > n2.category();
|
||||
}
|
||||
|
||||
bool Note::lessThanByTitle(const Note &n1, const Note &n2) {
|
||||
return n1.title() > n2.title();
|
||||
}
|
||||
|
||||
bool Note::lessThanByDateFavOnTop(const Note &n1, const Note &n2) {
|
||||
if (n1.favorite() != n2.favorite())
|
||||
return n1.favorite();
|
||||
else
|
||||
return n1.modified() > n2.modified();
|
||||
}
|
||||
|
||||
bool Note::lessThanByCategoryFavOnTop(const Note &n1, const Note &n2) {
|
||||
if (n1.favorite() != n2.favorite())
|
||||
return n1.favorite();
|
||||
else
|
||||
return n1.category() > n2.category();
|
||||
}
|
||||
|
||||
bool Note::lessThanByTitleFavOnTop(const Note &n1, const Note &n2) {
|
||||
if (n1.favorite() != n2.favorite())
|
||||
return n1.favorite();
|
||||
else
|
||||
return n1.title() > n2.title();
|
||||
}
|
||||
|
||||
|
|
|
@ -64,6 +64,12 @@ public:
|
|||
|
||||
static Note fromjson(const QJsonObject& jobj);
|
||||
static bool searchInNote(const QString &query, const Note ¬e, SearchAttributes criteria = QFlag(SearchAll), Qt::CaseSensitivity cs = Qt::CaseInsensitive);
|
||||
static bool lessThanByDate(const Note &n1, const Note &n2);
|
||||
static bool lessThanByCategory(const Note &n1, const Note &n2);
|
||||
static bool lessThanByTitle(const Note &n1, const Note &n2);
|
||||
static bool lessThanByDateFavOnTop(const Note &n1, const Note &n2);
|
||||
static bool lessThanByCategoryFavOnTop(const Note &n1, const Note &n2);
|
||||
static bool lessThanByTitleFavOnTop(const Note &n1, const Note &n2);
|
||||
|
||||
signals:
|
||||
void idChanged(int id);
|
||||
|
|
|
@ -147,24 +147,24 @@ void NotesApi::getNote(int noteId, QStringList excludeFields) {
|
|||
}
|
||||
}
|
||||
|
||||
void NotesApi::createNote(QVariantHash fields) {
|
||||
void NotesApi::createNote(QVariantMap fields) {
|
||||
QUrl url = m_url;
|
||||
url.setPath(url.path() + "/notes");
|
||||
if (url.isValid()) {
|
||||
qDebug() << "POST" << url.toDisplayString();
|
||||
m_request.setUrl(url);
|
||||
m_replies << m_manager.post(m_request, QJsonDocument(QJsonObject::fromVariantHash(fields)).toJson());
|
||||
m_replies << m_manager.post(m_request, QJsonDocument(QJsonObject::fromVariantMap(fields)).toJson());
|
||||
emit busyChanged(busy());
|
||||
}
|
||||
}
|
||||
|
||||
void NotesApi::updateNote(int noteId, QVariantHash fields) {
|
||||
void NotesApi::updateNote(int noteId, QVariantMap fields) {
|
||||
QUrl url = m_url;
|
||||
url.setPath(url.path() + QString("/notes/%1").arg(noteId));
|
||||
if (url.isValid()) {
|
||||
qDebug() << "PUT" << url.toDisplayString();
|
||||
m_request.setUrl(url);
|
||||
m_replies << m_manager.put(m_request, QJsonDocument(QJsonObject::fromVariantHash(fields)).toJson());
|
||||
m_replies << m_manager.put(m_request, QJsonDocument(QJsonObject::fromVariantMap(fields)).toJson());
|
||||
emit busyChanged(busy());
|
||||
}
|
||||
}
|
||||
|
@ -197,7 +197,7 @@ void NotesApi::replyFinished(QNetworkReply *reply) {
|
|||
//qDebug() << json;
|
||||
}
|
||||
else {
|
||||
qDebug() << reply->errorString();
|
||||
qDebug() << reply->error() << reply->errorString();
|
||||
}
|
||||
m_replies.removeAll(reply);
|
||||
reply->deleteLater();
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkRequest>
|
||||
#include <QNetworkReply>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QDebug>
|
||||
#include "notesmodel.h"
|
||||
|
||||
|
@ -58,10 +59,10 @@ public:
|
|||
|
||||
Q_INVOKABLE void getAllNotes(QStringList excludeFields = QStringList());
|
||||
Q_INVOKABLE void getNote(int noteId, QStringList excludeFields = QStringList());
|
||||
Q_INVOKABLE void createNote(QVariantHash fields = QVariantHash());
|
||||
Q_INVOKABLE void updateNote(int noteId, QVariantHash fields = QVariantHash());
|
||||
Q_INVOKABLE void createNote(QVariantMap fields = QVariantMap());
|
||||
Q_INVOKABLE void updateNote(int noteId, QVariantMap fields = QVariantMap());
|
||||
Q_INVOKABLE void deleteNote(int noteId);
|
||||
Q_INVOKABLE NotesModel& model() const { return *mp_model; }
|
||||
Q_INVOKABLE NotesModel* model() const { return mp_model; }
|
||||
|
||||
signals:
|
||||
void sslVerifyChanged(bool verify);
|
||||
|
@ -91,6 +92,7 @@ private:
|
|||
QNetworkRequest m_request;
|
||||
QVector<QNetworkReply*> m_replies;
|
||||
NotesModel* mp_model;
|
||||
QSortFilterProxyModel* mp_modelProxy; // TODO: use!
|
||||
};
|
||||
|
||||
#endif // NOTESAPI_H
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "notesmodel.h"
|
||||
#include <algorithm> // std::sort
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonArray>
|
||||
|
@ -8,11 +9,11 @@
|
|||
NotesModel::NotesModel(QObject *parent) : QAbstractListModel(parent)
|
||||
{
|
||||
m_sortBy = noSorting;
|
||||
m_favoritesOnTop = false;
|
||||
m_favoritesOnTop = true;
|
||||
}
|
||||
|
||||
NotesModel::~NotesModel() {
|
||||
clear();
|
||||
//clear();
|
||||
}
|
||||
|
||||
void NotesModel::setSortBy(QString sortBy) {
|
||||
|
@ -37,15 +38,24 @@ void NotesModel::setSearchText(QString searchText) {
|
|||
qDebug() << "Searching by:" << searchText;
|
||||
if (searchText != m_searchText) {
|
||||
m_searchText = searchText;
|
||||
for (int i = 0; i < m_notes.size(); i++) {
|
||||
if (m_searchText.isEmpty()) {
|
||||
m_notes[i].param = true;
|
||||
}
|
||||
else {
|
||||
m_notes[i].param = Note::searchInNote(m_searchText, m_notes[i].note);
|
||||
emit searchTextChanged(m_searchText);
|
||||
if (m_searchText.isEmpty()) {
|
||||
m_invisibleIds.clear();
|
||||
emit dataChanged(this->index(0), this->index(m_notes.size()));
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < m_notes.size(); i++) {
|
||||
if (Note::searchInNote(m_searchText, m_notes[i])) {
|
||||
//qDebug() << "Note" << m_notes[i].title() << "in search";
|
||||
m_invisibleIds.removeAll(m_notes[i].id());
|
||||
}
|
||||
else {
|
||||
//qDebug() << "Note" << m_notes[i].title() << "not in search";
|
||||
m_invisibleIds.append(m_notes[i].id());
|
||||
}
|
||||
emit dataChanged(this->index(i), this->index(i));
|
||||
}
|
||||
}
|
||||
emit searchTextChanged(m_searchText);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -57,54 +67,46 @@ void NotesModel::clearSearch() {
|
|||
search();
|
||||
}
|
||||
|
||||
bool NotesModel::applyJSONobject(const QJsonObject &jobj) {
|
||||
if (!jobj.isEmpty()) {
|
||||
Note note = Note::fromjson(jobj); // TODO connect signals
|
||||
if (!note.error()) {
|
||||
int position = indexOf(note.id());
|
||||
Note oldNote = get(position);
|
||||
if (position >= 0 && note.etag() != oldNote.etag()) {
|
||||
qDebug() << "-- Existing note " << note.title() << "changed, updating the model.";
|
||||
replaceNote(note);
|
||||
}
|
||||
else if (position < 0) {
|
||||
qDebug() << "-- New note" << note.title() << ", adding it to the model.";
|
||||
insertNote(note);
|
||||
}
|
||||
else {
|
||||
qDebug() << "-- Existing note " << note.title() << "unchanged, nothing to do.";
|
||||
}
|
||||
}
|
||||
else {
|
||||
qDebug() << "Note contains an error:" << note.errorMessage();
|
||||
}
|
||||
}
|
||||
else {
|
||||
qDebug() << "Unknown JSON object. This message should never occure!";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NotesModel::applyJSON(const QJsonDocument &jdoc) {
|
||||
qDebug() << "Applying new JSON input";// << json;
|
||||
if (!jdoc.isNull()) {
|
||||
if (jdoc.isArray()) {
|
||||
qDebug() << "- It's an array...";
|
||||
QVector<Note> newNotes;
|
||||
QJsonArray jarr = jdoc.array();
|
||||
while (!jarr.empty()) {
|
||||
//qDebug() << jarr.count() << "JSON Objects to handle...";
|
||||
QJsonValue jval = jarr.first();
|
||||
if (jval.isObject()) {
|
||||
//qDebug() << "It's an object, all fine...";
|
||||
applyJSONobject(jval.toObject());
|
||||
QJsonObject jobj = jval.toObject();
|
||||
if (!jobj.isEmpty()) {
|
||||
newNotes.append(Note::fromjson(jobj));
|
||||
}
|
||||
}
|
||||
jarr.pop_front();
|
||||
}
|
||||
for (int i = 0; i < m_notes.size(); ++i) {
|
||||
bool noteToBeRemoved = true;
|
||||
for (int j = 0; j < newNotes.size(); ++j) {
|
||||
if (m_notes[i].id() == newNotes[j].id())
|
||||
noteToBeRemoved = false;
|
||||
}
|
||||
if (noteToBeRemoved) {
|
||||
qDebug() << "-- Removing note " << m_notes[i].title();
|
||||
removeNote(m_notes[i]);
|
||||
}
|
||||
}
|
||||
while (!newNotes.empty()) {
|
||||
insertNote(newNotes.first());
|
||||
newNotes.pop_front();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if (jdoc.isObject()) {
|
||||
qDebug() << "- It's a single object...";
|
||||
return applyJSONobject(jdoc.object());
|
||||
insertNote(Note::fromjson(jdoc.object()));
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
qDebug() << "Unknown JSON document. This message should never occure!";
|
||||
|
@ -127,22 +129,29 @@ bool NotesModel::applyJSON(const QString &json) {
|
|||
}
|
||||
|
||||
int NotesModel::insertNote(const Note ¬e) {
|
||||
int position = insertPosition(note);
|
||||
ModelNote<Note, bool> modelNote;
|
||||
modelNote.note = note;
|
||||
modelNote.param = true;
|
||||
beginInsertRows(QModelIndex(), position, position);
|
||||
m_notes.insert(position, modelNote);
|
||||
endInsertRows();
|
||||
int position = indexOf(note.id());
|
||||
if (position >= 0) {
|
||||
if (note.etag() != m_notes[position].etag()) {
|
||||
qDebug() << "-- Existing note " << note.title() << "changed, updating the model.";
|
||||
m_notes.replace(position, note);
|
||||
emit dataChanged(this->index(position), this->index(position));
|
||||
}
|
||||
else {
|
||||
qDebug() << "-- Existing note " << note.title() << "unchanged, nothing to do.";
|
||||
}
|
||||
}
|
||||
else {
|
||||
qDebug() << "-- New note" << note.title() << ", adding it to the model.";
|
||||
position = insertPosition(note);
|
||||
beginInsertRows(QModelIndex(), position, position);
|
||||
m_notes.insert(position, note);
|
||||
endInsertRows();
|
||||
}
|
||||
return position;
|
||||
}
|
||||
|
||||
bool NotesModel::removeNote(const Note ¬e) {
|
||||
return removeNote(note.id());
|
||||
}
|
||||
|
||||
bool NotesModel::removeNote(int id) {
|
||||
int position = indexOf(id);
|
||||
int position = m_notes.indexOf(note);
|
||||
if (position >= 0 && position < m_notes.size()) {
|
||||
beginRemoveRows(QModelIndex(), position, position);
|
||||
m_notes.removeAt(position);
|
||||
|
@ -152,61 +161,19 @@ bool NotesModel::removeNote(int id) {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool NotesModel::replaceNote(const Note ¬e) {
|
||||
int position = indexOf(note.id());
|
||||
if (position >= 0 && position < m_notes.size()) {
|
||||
ModelNote<Note, bool> modelNote;
|
||||
modelNote.note = note;
|
||||
modelNote.param = m_notes[position].param;
|
||||
m_notes.replace(position, modelNote);
|
||||
QVector<int> roles;
|
||||
roles << ModifiedRole << TitleRole << CategoryRole << ContentRole << FavoriteRole << EtagRole;
|
||||
emit dataChanged(this->index(position), this->index(position), roles);
|
||||
return true;
|
||||
bool NotesModel::removeNote(int id) {
|
||||
bool retval = false;
|
||||
for (int i = 0; i < m_notes.size(); ++i) {
|
||||
if (m_notes[i].id() == id) {
|
||||
retval |= removeNote(m_notes[i]);
|
||||
if (i > 0) i--;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return retval;
|
||||
}
|
||||
|
||||
void NotesModel::clear() {
|
||||
m_searchText.clear();
|
||||
beginRemoveRows(QModelIndex(), 0, rowCount());
|
||||
m_notes.clear();
|
||||
endRemoveRows();
|
||||
}
|
||||
|
||||
int NotesModel::indexOf(int id) const {
|
||||
for (int i = 0; i < m_notes.size(); i++) {
|
||||
if (m_notes[i].note.id() == id)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
Note NotesModel::get(int index) const {
|
||||
Note note;
|
||||
if (index >= 0 && index < m_notes.size()) {
|
||||
note = m_notes[index].note;
|
||||
}
|
||||
return note;
|
||||
}
|
||||
|
||||
/*
|
||||
bool NotesModel::addNote(Note ¬e) {
|
||||
m_notes.append(note);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NotesModel::addNotes(QList<Note> ¬es) {
|
||||
for (int i = 0; i < notes.length(); i++) {
|
||||
addNote(notes[i]);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
|
||||
QHash<int, QByteArray> NotesModel::roleNames() const {
|
||||
return QHash<int, QByteArray> {
|
||||
{NotesModel::VisibleRole, "visible"},
|
||||
{NotesModel::IdRole, "id"},
|
||||
{NotesModel::ModifiedRole, "modified"},
|
||||
{NotesModel::TitleRole, "title"},
|
||||
|
@ -216,17 +183,17 @@ QHash<int, QByteArray> NotesModel::roleNames() const {
|
|||
{NotesModel::EtagRole, "etag"},
|
||||
{NotesModel::ErrorRole, "error"},
|
||||
{NotesModel::ErrorMessageRole, "errorMessage"},
|
||||
{NotesModel::DateStringRole, "date"}
|
||||
{NotesModel::InSearchRole, "inSearch"}
|
||||
};
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> NotesModel::sortingNames() const {
|
||||
QHash<int, QByteArray> criteria;
|
||||
criteria[sortByDate] = "date";
|
||||
criteria[sortByCategory] = "category";
|
||||
criteria[sortByTitle] = "title";
|
||||
criteria[noSorting] = "none";
|
||||
return criteria;
|
||||
return QHash<int, QByteArray> {
|
||||
{NotesModel::sortByDate, "date"},
|
||||
{NotesModel::sortByCategory, "category"},
|
||||
{NotesModel::sortByTitle, "title"},
|
||||
{NotesModel::noSorting, "none"}
|
||||
};
|
||||
}
|
||||
|
||||
QStringList NotesModel::sortingCriteria() const {
|
||||
|
@ -257,17 +224,19 @@ int NotesModel::rowCount(const QModelIndex &parent) const {
|
|||
|
||||
QVariant NotesModel::data(const QModelIndex &index, int role) const {
|
||||
if (!index.isValid()) return QVariant();
|
||||
else if (role == VisibleRole) return m_notes[index.row()].param;
|
||||
else if (role == IdRole) return m_notes[index.row()].note.id();
|
||||
else if (role == ModifiedRole) return m_notes[index.row()].note.modified();
|
||||
else if (role == TitleRole) return m_notes[index.row()].note.title();
|
||||
else if (role == CategoryRole) return m_notes[index.row()].note.category();
|
||||
else if (role == ContentRole) return m_notes[index.row()].note.content();
|
||||
else if (role == FavoriteRole) return m_notes[index.row()].note.favorite();
|
||||
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 == ErrorMessageRole) return m_notes[index.row()].note.errorMessage();
|
||||
else if (role == DateStringRole) return m_notes[index.row()].note.dateString();
|
||||
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();
|
||||
else if (role == InSearchRole) {
|
||||
qDebug() << "Invisible:" << m_invisibleIds.contains(m_notes[index.row()].id());
|
||||
return !m_invisibleIds.contains(m_notes[index.row()].id());
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
|
@ -275,99 +244,47 @@ QMap<int, QVariant> NotesModel::itemData(const QModelIndex &index) const {
|
|||
QMap<int, QVariant> map;
|
||||
if (!index.isValid()) return map;
|
||||
else {
|
||||
for (int role = VisibleRole; role <= ErrorMessageRole; role++) {
|
||||
for (int role = Qt::UserRole; role < Qt::UserRole + 10; ++role) {
|
||||
map.insert(role, data(index, role));
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
bool NotesModel::setData(const QModelIndex &index, const QVariant &value, int role) {
|
||||
if (!index.isValid()) return false;
|
||||
else if (role == ModifiedRole && m_notes[index.row()].note.modified() != value.toUInt()) {
|
||||
m_notes[index.row()].note.setModified(value.toInt());
|
||||
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, DateStringRole} ); // TODO remove when signals from Note are connected
|
||||
sort();
|
||||
return true;
|
||||
}
|
||||
else if (role == CategoryRole && m_notes[index.row()].note.category() != value.toString()) {
|
||||
m_notes[index.row()].note.setCategory(value.toString());
|
||||
emit dataChanged(this->index(index.row()), this->index(index.row()), QVector<int> { 1, role } ); // TODO remove when signals from Note are connected
|
||||
sort();
|
||||
return true;
|
||||
}
|
||||
else if (role == ContentRole && m_notes[index.row()].note.content() != value.toString()) {
|
||||
m_notes[index.row()].note.setContent(value.toString());
|
||||
emit dataChanged(this->index(index.row()), this->index(index.row()), QVector<int> { 1, role } ); // TODO remove when signals from Note are connected
|
||||
sort();
|
||||
return true;
|
||||
}
|
||||
else if (role == FavoriteRole && m_notes[index.row()].note.favorite() != value.toBool()) {
|
||||
m_notes[index.row()].note.setFavorite(value.toBool());
|
||||
emit dataChanged(this->index(index.row()), this->index(index.row()), QVector<int> { 1, role } ); // TODO remove when signals from Note are connected
|
||||
sort();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NotesModel::setItemData(const QModelIndex &index, const QMap<int, QVariant> &roles) {
|
||||
if (!index.isValid()) return false;
|
||||
else if (roles.contains(ModifiedRole) || roles.contains(CategoryRole) || roles.contains(ContentRole) || roles.contains(FavoriteRole)) {
|
||||
QMap<int, QVariant>::const_iterator i = roles.constBegin();
|
||||
while (i != roles.constEnd()) {
|
||||
setData(index, i.value(), i.key());
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void NotesModel::sort() {
|
||||
qDebug() << "Sorting notes in the model";
|
||||
QList<ModelNote<Note, bool> > notes;
|
||||
QMap<QString, ModelNote<Note, bool> > map;
|
||||
QMap<QString, ModelNote<Note, bool> > favorites;
|
||||
if (m_sortBy == sortingNames()[sortByDate]) {
|
||||
emit layoutAboutToBeChanged(QList<QPersistentModelIndex> (), VerticalSortHint);
|
||||
for (int i = 0; i < m_notes.size(); i++) {
|
||||
if (m_favoritesOnTop && m_notes[i].note.favorite())
|
||||
favorites.insert(QString::number(std::numeric_limits<uint>::max() - m_notes[i].note.modified()), m_notes[i]);
|
||||
else
|
||||
map.insert(QString::number(std::numeric_limits<uint>::max() - m_notes[i].note.modified()), m_notes[i]);
|
||||
emit layoutAboutToBeChanged(QList<QPersistentModelIndex> (), VerticalSortHint);
|
||||
if (m_favoritesOnTop) {
|
||||
if (m_sortBy == sortingNames()[sortByDate]) {
|
||||
std::sort(m_notes.begin(), m_notes.end(), Note::lessThanByDateFavOnTop);
|
||||
}
|
||||
notes = favorites.values();
|
||||
notes.append(map.values());
|
||||
m_notes = notes;
|
||||
emit layoutChanged(QList<QPersistentModelIndex> (), VerticalSortHint);
|
||||
}
|
||||
else if (m_sortBy == sortingNames()[sortByCategory]) {
|
||||
emit layoutAboutToBeChanged(QList<QPersistentModelIndex> (), VerticalSortHint);
|
||||
for (int i = 0; i < m_notes.size(); i++) {
|
||||
if (m_favoritesOnTop && m_notes[i].note.favorite())
|
||||
favorites.insert(m_notes[i].note.category(), m_notes[i]);
|
||||
else
|
||||
map.insert(m_notes[i].note.category(), m_notes[i]);
|
||||
else if (m_sortBy == sortingNames()[sortByCategory]) {
|
||||
std::sort(m_notes.begin(), m_notes.end(), Note::lessThanByCategoryFavOnTop);
|
||||
}
|
||||
notes = favorites.values();
|
||||
notes.append(map.values());
|
||||
m_notes = notes;
|
||||
emit layoutChanged(QList<QPersistentModelIndex> (), VerticalSortHint);
|
||||
}
|
||||
else if (m_sortBy == sortingNames()[sortByTitle]) {
|
||||
emit layoutAboutToBeChanged(QList<QPersistentModelIndex> (), VerticalSortHint);
|
||||
for (int i = 0; i < m_notes.size(); i++) {
|
||||
if (m_favoritesOnTop && m_notes[i].note.favorite())
|
||||
favorites.insert(m_notes[i].note.title(), m_notes[i]);
|
||||
else
|
||||
map.insert(m_notes[i].note.title(), m_notes[i]);
|
||||
else if (m_sortBy == sortingNames()[sortByTitle]) {
|
||||
std::sort(m_notes.begin(), m_notes.end(), Note::lessThanByTitleFavOnTop);
|
||||
}
|
||||
notes = favorites.values();
|
||||
notes.append(map.values());
|
||||
m_notes = notes;
|
||||
emit layoutChanged(QList<QPersistentModelIndex> (), VerticalSortHint);
|
||||
}
|
||||
else {
|
||||
if (m_sortBy == sortingNames()[sortByDate]) {
|
||||
std::sort(m_notes.begin(), m_notes.end(), Note::lessThanByDate);
|
||||
}
|
||||
else if (m_sortBy == sortingNames()[sortByCategory]) {
|
||||
std::sort(m_notes.begin(), m_notes.end(), Note::lessThanByCategory);
|
||||
}
|
||||
else if (m_sortBy == sortingNames()[sortByTitle]) {
|
||||
std::sort(m_notes.begin(), m_notes.end(), Note::lessThanByTitle);
|
||||
}
|
||||
}
|
||||
emit layoutChanged(QList<QPersistentModelIndex> (), VerticalSortHint);
|
||||
}
|
||||
|
||||
int NotesModel::indexOf(int id) const {
|
||||
for (int i = 0; i < m_notes.size(); i++) {
|
||||
if (m_notes[i].id() == id)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int NotesModel::insertPosition(const Note &n) const {
|
||||
|
@ -375,7 +292,7 @@ int NotesModel::insertPosition(const Note &n) const {
|
|||
int upper = m_notes.size();
|
||||
while (lower < upper) {
|
||||
int middle = qFloor(lower + (upper-lower) / 2);
|
||||
bool result = noteLessThan(n, m_notes[middle].note);
|
||||
bool result = noteLessThan(n, m_notes[middle]);
|
||||
if (result)
|
||||
upper = middle;
|
||||
else
|
||||
|
@ -386,22 +303,13 @@ int NotesModel::insertPosition(const Note &n) const {
|
|||
|
||||
bool NotesModel::noteLessThan(const Note &n1, const Note &n2) const {
|
||||
if (m_sortBy == sortingNames()[sortByDate]) {
|
||||
if (m_favoritesOnTop && n1.favorite() != n2.favorite())
|
||||
return n1.favorite();
|
||||
else
|
||||
return n1.modified() > n2.modified();
|
||||
return m_favoritesOnTop ? Note::lessThanByDateFavOnTop(n1, n2) : Note::lessThanByDate(n1, n2);
|
||||
}
|
||||
else if (m_sortBy == sortingNames()[sortByCategory]) {
|
||||
if (m_favoritesOnTop && n1.favorite() != n2.favorite())
|
||||
return n1.favorite();
|
||||
else
|
||||
return n1.category() < n2.category();
|
||||
return m_favoritesOnTop ? Note::lessThanByCategoryFavOnTop(n1, n2) : Note::lessThanByCategory(n1, n2);
|
||||
}
|
||||
else if (m_sortBy == sortingNames()[sortByTitle]) {
|
||||
if (m_favoritesOnTop && n1.favorite() != n2.favorite())
|
||||
return n1.favorite();
|
||||
else
|
||||
return n1.title() < n2.title();
|
||||
return m_favoritesOnTop ? Note::lessThanByTitleFavOnTop(n1, n2) : Note::lessThanByTitle(n1, n2);
|
||||
}
|
||||
else {
|
||||
if (m_favoritesOnTop && n1.favorite() != n2.favorite())
|
||||
|
@ -409,73 +317,3 @@ bool NotesModel::noteLessThan(const Note &n1, const Note &n2) const {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*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::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;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
|
|
@ -5,12 +5,6 @@
|
|||
#include <QDateTime>
|
||||
#include "note.h"
|
||||
|
||||
template <typename N, typename P>
|
||||
struct ModelNote {
|
||||
N note;
|
||||
P param;
|
||||
};
|
||||
|
||||
class NotesModel : public QAbstractListModel {
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
@ -32,29 +26,20 @@ public:
|
|||
Q_INVOKABLE void search(QString searchText = QString());
|
||||
Q_INVOKABLE void clearSearch();
|
||||
|
||||
Q_INVOKABLE bool applyJSON(const QJsonDocument &jdoc);
|
||||
Q_INVOKABLE bool applyJSON(const QString &json);
|
||||
Q_INVOKABLE int insertNote(const Note ¬e);
|
||||
Q_INVOKABLE bool removeNote(const Note ¬e);
|
||||
Q_INVOKABLE bool removeNote(int position);
|
||||
Q_INVOKABLE bool replaceNote(const Note ¬e);
|
||||
Q_INVOKABLE void clear();
|
||||
|
||||
Q_INVOKABLE int indexOf(int id) const;
|
||||
Q_INVOKABLE Note get(int index) const;
|
||||
bool applyJSON(const QJsonDocument &jdoc);
|
||||
bool applyJSON(const QString &json);
|
||||
|
||||
enum NoteRoles {
|
||||
VisibleRole = Qt::UserRole,
|
||||
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,
|
||||
DateStringRole = Qt::UserRole + 10
|
||||
IdRole = Qt::UserRole,
|
||||
ModifiedRole = Qt::UserRole + 1,
|
||||
TitleRole = Qt::UserRole + 2,
|
||||
CategoryRole = Qt::UserRole + 3,
|
||||
ContentRole = Qt::UserRole + 4,
|
||||
FavoriteRole = Qt::UserRole + 5,
|
||||
EtagRole = Qt::UserRole + 6,
|
||||
ErrorRole = Qt::UserRole + 7,
|
||||
ErrorMessageRole = Qt::UserRole + 8,
|
||||
InSearchRole = Qt::UserRole + 9
|
||||
};
|
||||
QHash<int, QByteArray> roleNames() const;
|
||||
|
||||
|
@ -71,14 +56,6 @@ public:
|
|||
virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
virtual QVariant data(const QModelIndex &index, int role) const;
|
||||
QMap<int, QVariant> itemData(const QModelIndex &index) const;
|
||||
//virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const;
|
||||
virtual bool setData(const QModelIndex &index, const QVariant &value, int role);
|
||||
virtual bool setItemData(const QModelIndex &index, const QMap<int, QVariant> &roles);
|
||||
|
||||
//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:
|
||||
|
||||
|
@ -89,19 +66,21 @@ signals:
|
|||
void searchTextChanged(QString searchText);
|
||||
|
||||
private:
|
||||
QList<ModelNote<Note, bool> > m_notes;
|
||||
QVector<Note> m_notes;
|
||||
QVector<int> m_invisibleIds;
|
||||
QString m_sortBy;
|
||||
bool m_favoritesOnTop;
|
||||
QString m_searchText;
|
||||
|
||||
void sort();
|
||||
//void update();
|
||||
bool applyJSONobject(const QJsonObject &jobj);
|
||||
int insertNote(const Note ¬e);
|
||||
bool replaceNote(const Note ¬e);
|
||||
bool removeNote(const Note ¬e);
|
||||
bool removeNote(int id);
|
||||
int indexOf(int id) const;
|
||||
int insertPosition(const Note &n) const;
|
||||
bool noteLessThan(const Note &n1, const Note &n2) const;
|
||||
/*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);*/
|
||||
};
|
||||
|
||||
#endif // NOTESMODEL_H
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
#include "sslconfiguration.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
SslConfiguration::SslConfiguration(QObject *parent) : QObject(parent), _checkCert(true) {
|
||||
checkCertConfig = noCheckConfig = QSslConfiguration::defaultConfiguration();
|
||||
noCheckConfig.setPeerVerifyMode(QSslSocket::VerifyNone);
|
||||
QSslConfiguration::setDefaultConfiguration(checkCertConfig);
|
||||
}
|
||||
|
||||
bool SslConfiguration::checkCert() {
|
||||
return _checkCert;
|
||||
}
|
||||
|
||||
void SslConfiguration::setCheckCert(bool check) {
|
||||
if (_checkCert != check) {
|
||||
qDebug() << "Changing SSL Cert check to" << check;
|
||||
_checkCert = check;
|
||||
QSslConfiguration::setDefaultConfiguration(_checkCert ? checkCertConfig : noCheckConfig);
|
||||
emit checkCertChanged(_checkCert);
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
#ifndef SSLCONFIGURATION_H
|
||||
#define SSLCONFIGURATION_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QSslConfiguration>
|
||||
#include <QSslSocket>
|
||||
|
||||
class SslConfiguration : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(bool checkCert READ checkCert WRITE setCheckCert NOTIFY checkCertChanged)
|
||||
public:
|
||||
explicit SslConfiguration(QObject *parent = nullptr);
|
||||
|
||||
public slots:
|
||||
bool checkCert();
|
||||
void setCheckCert(bool check);
|
||||
|
||||
signals:
|
||||
void checkCertChanged(bool check);
|
||||
|
||||
private:
|
||||
bool _checkCert;
|
||||
QSslConfiguration checkCertConfig;
|
||||
QSslConfiguration noCheckConfig;
|
||||
};
|
||||
|
||||
#endif // SSLCONFIGURATION_H
|
|
@ -213,13 +213,6 @@
|
|||
<translation>Geändert</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>NotesApi</name>
|
||||
<message>
|
||||
<source>Unable to connect</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>NotesPage</name>
|
||||
<message>
|
||||
|
@ -270,6 +263,34 @@
|
|||
<source>Open the settings to configure your Nextcloud accounts</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>No account yet</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Got to the settings to add an account</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>No notes yet</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Pull down to add a note</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>No result</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Try another query</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>An error occurred</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>SettingsPage</name>
|
||||
|
|
|
@ -213,13 +213,6 @@
|
|||
<translation>Ingen kategori</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>NotesApi</name>
|
||||
<message>
|
||||
<source>Unable to connect</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>NotesPage</name>
|
||||
<message>
|
||||
|
@ -270,6 +263,34 @@
|
|||
<source>Open the settings to configure your Nextcloud accounts</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>No account yet</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Got to the settings to add an account</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>No notes yet</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Pull down to add a note</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>No result</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Try another query</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>An error occurred</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>SettingsPage</name>
|
||||
|
|
|
@ -259,73 +259,100 @@
|
|||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>NotesApi</name>
|
||||
<message>
|
||||
<location filename="../qml/components/NotesApi.qml" line="68"/>
|
||||
<source>Unable to connect</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>NotesPage</name>
|
||||
<message>
|
||||
<location filename="../qml/pages/NotesPage.qml" line="31"/>
|
||||
<location filename="../qml/pages/NotesPage.qml" line="38"/>
|
||||
<source>Settings</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../qml/pages/NotesPage.qml" line="35"/>
|
||||
<location filename="../qml/pages/NotesPage.qml" line="42"/>
|
||||
<source>Add note</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../qml/pages/NotesPage.qml" line="40"/>
|
||||
<location filename="../qml/pages/NotesPage.qml" line="47"/>
|
||||
<source>Reload</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../qml/pages/NotesPage.qml" line="40"/>
|
||||
<location filename="../qml/pages/NotesPage.qml" line="47"/>
|
||||
<source>Updating...</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../qml/pages/NotesPage.qml" line="46"/>
|
||||
<location filename="../qml/pages/NotesPage.qml" line="53"/>
|
||||
<source>Last update</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../qml/pages/NotesPage.qml" line="49"/>
|
||||
<location filename="../qml/pages/NotesPage.qml" line="56"/>
|
||||
<source>never</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../qml/pages/NotesPage.qml" line="59"/>
|
||||
<location filename="../qml/pages/NotesPage.qml" line="66"/>
|
||||
<source>Nextcloud Notes</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../qml/pages/NotesPage.qml" line="198"/>
|
||||
<location filename="../qml/pages/NotesPage.qml" line="206"/>
|
||||
<source>Modified</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../qml/pages/NotesPage.qml" line="201"/>
|
||||
<location filename="../qml/pages/NotesPage.qml" line="209"/>
|
||||
<source>Delete</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../qml/pages/NotesPage.qml" line="203"/>
|
||||
<location filename="../qml/pages/NotesPage.qml" line="211"/>
|
||||
<source>Deleting note</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../qml/pages/NotesPage.qml" line="233"/>
|
||||
<location filename="../qml/pages/NotesPage.qml" line="241"/>
|
||||
<source>Loading notes...</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../qml/pages/NotesPage.qml" line="271"/>
|
||||
<location filename="../qml/pages/NotesPage.qml" line="247"/>
|
||||
<source>No account yet</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../qml/pages/NotesPage.qml" line="248"/>
|
||||
<source>Got to the settings to add an account</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../qml/pages/NotesPage.qml" line="254"/>
|
||||
<source>No notes yet</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../qml/pages/NotesPage.qml" line="255"/>
|
||||
<source>Pull down to add a note</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../qml/pages/NotesPage.qml" line="261"/>
|
||||
<source>No result</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../qml/pages/NotesPage.qml" line="262"/>
|
||||
<source>Try another query</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../qml/pages/NotesPage.qml" line="268"/>
|
||||
<source>An error occurred</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../qml/pages/NotesPage.qml" line="279"/>
|
||||
<source>Open the settings to configure your Nextcloud accounts</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
|
Loading…
Reference in a new issue