diff --git a/main.qml b/main.qml index d7c3c19..86b97d6 100644 --- a/main.qml +++ b/main.qml @@ -1,104 +1,126 @@ import QtQuick 2.9 import QtQuick.Controls 2.2 import org.kde.kirigami 2.0 as Kirigami import org.kde.maui 1.0 as Maui import "src/widgets" import "src/views/notes" Maui.ApplicationWindow { id: root title: qsTr("Buho") /***** PROPS *****/ property var views : ({ notes: 0, links: 1, books: 2 - }) headBar.middleContent: Row { spacing: space.medium Maui.ToolButton { display: root.isWide ? ToolButton.TextBesideIcon : ToolButton.IconOnly iconName: "draw-text" text: qsTr("Notes") } Maui.ToolButton { display: root.isWide ? ToolButton.TextBesideIcon : ToolButton.IconOnly iconName: "link" text: qsTr("Links") } Maui.ToolButton { display: root.isWide ? ToolButton.TextBesideIcon : ToolButton.IconOnly iconName: "document-new" text: qsTr("Books") } } footBar.middleContent: Maui.PieButton { id: addButton iconName: "list-add" model: ListModel { ListElement {iconName: "document-new"; mid: "page"} ListElement {iconName: "link"; mid: "link"} ListElement {iconName: "draw-text"; mid: "note"} } onItemClicked: { if(item.mid === "note") newNoteDialog.open() } } footBar.leftContent: Maui.ToolButton { iconName: "document-share" } footBar.rightContent: Maui.ToolButton { iconName: "archive-remove" } /***** COMPONENTS *****/ NewNoteDialog { id: newNoteDialog + onNoteSaved: + { + if(owl.insertNote(note.title, note.body, note.color, note.tags)) + notesView.append(note) + } + } + + NewNoteDialog + { + id: editNote + onNoteSaved: + { + console.log("BAHABHABH", notesView.currentNote.id) + owl.updateNote(notesView.currentNote.id, note.title, note.body, note.color, note.tags) + } } /***** VIEWS *****/ SwipeView { anchors.fill: parent currentIndex: views.notes NotesView { id: notesView + onNoteClicked: setNote(note) + } } Component.onCompleted: { notesView.populate() } + + function setNote(note) + { + notesView.currentNote = note + editNote.fill(note) + } } diff --git a/src/db/dbactions.cpp b/src/db/dbactions.cpp index ee936a0..78c73b8 100644 --- a/src/db/dbactions.cpp +++ b/src/db/dbactions.cpp @@ -1,140 +1,136 @@ /*** Buho Copyright (C) 2018 Camilo Higuita This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . ***/ #include "dbactions.h" #include #include #include #include DBActions::DBActions(QObject *parent) : DB(parent) { qDebug() << "Getting collectionDB info from: " << OWL::CollectionDBPath; qDebug()<< "Starting DBActions"; } DBActions::~DBActions() {} OWL::DB_LIST DBActions::getDBData(const QString &queryTxt) { OWL::DB_LIST mapList; auto query = this->getQuery(queryTxt); if(query.exec()) { while(query.next()) { OWL::DB data; for(auto key : OWL::KEYMAP.keys()) if(query.record().indexOf(OWL::KEYMAP[key])>-1) data.insert(key, query.value(OWL::KEYMAP[key]).toString()); mapList<< data; } }else qDebug()<< query.lastError()<< query.lastQuery(); return mapList; } QVariantList DBActions::get(const QString &queryTxt) { QVariantList mapList; auto query = this->getQuery(queryTxt); if(query.exec()) { while(query.next()) { QVariantMap data; for(auto key : OWL::KEYMAP.keys()) if(query.record().indexOf(OWL::KEYMAP[key])>-1) data[OWL::KEYMAP[key]] = query.value(OWL::KEYMAP[key]).toString(); mapList<< data; } }else qDebug()<< query.lastError()<< query.lastQuery(); return mapList; } bool DBActions::insertNote(const QString &title, const QString &body, const QString &color, const QString &tags) { - QVariantMap json_note = - { - {OWL::SLANG[OWL::W::TITLE], title}, - {OWL::SLANG[OWL::W::BODY], body} - }; - - auto json = QJsonDocument::fromVariant(json_note); - auto note_url = OWL::NotesPath+title+QUuid::createUuid().toString(); - OWL::saveJson(json, note_url); + auto id = QUuid::createUuid().toString(); QVariantMap note_map = { - {OWL::KEYMAP[OWL::KEY::URL], note_url}, + {OWL::KEYMAP[OWL::KEY::ID], id}, + {OWL::KEYMAP[OWL::KEY::TITLE], title}, + {OWL::KEYMAP[OWL::KEY::BODY], body}, {OWL::KEYMAP[OWL::KEY::COLOR], color}, + {OWL::KEYMAP[OWL::KEY::UPDATED], QDateTime::currentDateTime()}, {OWL::KEYMAP[OWL::KEY::ADD_DATE], QDateTime::currentDateTime()} }; - if(!tags.isEmpty()) - { - for(auto tag : tags.split(",")) - { - this->insert(OWL::TABLEMAP[OWL::TABLE::TAGS], {{OWL::KEYMAP[OWL::KEY::TAG], tag}}); - this->insert(OWL::TABLEMAP[OWL::TABLE::NOTES_TAGS], - { - {OWL::KEYMAP[OWL::KEY::TAG], tag}, - {OWL::KEYMAP[OWL::KEY::URL], note_url} - }); - } - } + // if(!tags.isEmpty()) + // { + // for(auto tag : tags.split(",")) + // { + // this->insert(OWL::TABLEMAP[OWL::TABLE::TAGS], {{OWL::KEYMAP[OWL::KEY::TAG], tag}}); + // this->insert(OWL::TABLEMAP[OWL::TABLE::NOTES_TAGS], + // { + // {OWL::KEYMAP[OWL::KEY::TAG], tag}, + // {OWL::KEYMAP[OWL::KEY::URL], note_url} + // }); + // } + // } return this->insert(OWL::TABLEMAP[OWL::TABLE::NOTES], note_map); } -QVariantList DBActions::getNotes() +bool DBActions::updateNote(const QString &id, const QString &title, const QString &body, const QString &color, const QString &tags) { - QVariantList res; - auto data = this->getDBData("select * from notes"); - - for(auto note : data) + OWL::DB note = { - auto map = OWL::openJson(note[OWL::KEY::URL]); - map.insert(OWL::SLANG[OWL::W::ADD_DATE], note[OWL::KEY::ADD_DATE]); - map.insert(OWL::SLANG[OWL::W::COLOR], note[OWL::KEY::COLOR]); + {OWL::KEY::TITLE, title}, + {OWL::KEY::BODY, body}, + {OWL::KEY::COLOR, color}, + {OWL::KEY::UPDATED, QDateTime::currentDateTime().toString()} + }; - res << map; - } + return this->update(OWL::TABLEMAP[OWL::TABLE::NOTES], note, {{OWL::KEYMAP[OWL::KEY::ID], id}} ); +} - return res; +QVariantList DBActions::getNotes() +{ + return this->get("select * from notes"); } bool DBActions::execQuery(const QString &queryTxt) { auto query = this->getQuery(queryTxt); return query.exec(); } diff --git a/src/db/dbactions.h b/src/db/dbactions.h index 114cf45..ee5e6c7 100644 --- a/src/db/dbactions.h +++ b/src/db/dbactions.h @@ -1,49 +1,50 @@ /*** Buho Copyright (C) 2018 Camilo Higuita This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . ***/ #ifndef DBACTIONS_H #define DBACTIONS_H #include #include "db.h" class DBActions : public DB { Q_OBJECT public: explicit DBActions(QObject *parent = nullptr); ~DBActions(); Q_INVOKABLE QVariantList get(const QString &queryTxt); /*main actions*/ Q_INVOKABLE bool insertNote(const QString &title, const QString &body, const QString &color = QString(), const QString &tags = QString()); + Q_INVOKABLE bool updateNote(const QString &id, const QString &title, const QString &body, const QString &color = QString(), const QString &tags = QString()); Q_INVOKABLE QVariantList getNotes(); protected: OWL::DB_LIST getDBData(const QString &queryTxt); bool execQuery(const QString &queryTxt); signals: void tagAdded(QString tag); }; #endif // DBACTIONS_H diff --git a/src/db/script.sql b/src/db/script.sql index 66e5141..46c5856 100644 --- a/src/db/script.sql +++ b/src/db/script.sql @@ -1,13 +1,16 @@ CREATE TABLE IF NOT EXISTS NOTES ( -url TEXT PRIMARY KEY, +id TEXT PRIMARY KEY, +title TEXT, +body TEXT, color TEXT, -addDate DATE +addDate DATE, +updated DATE ); CREATE TABLE IF NOT EXISTS BOOKS ( url TEXT PRIMARY KEY, title TEXT NOT NULL, fav INTEGER NOT NULL, addDate DATE ); diff --git a/src/utils/owl.h b/src/utils/owl.h index 772cc0c..6108cde 100644 --- a/src/utils/owl.h +++ b/src/utils/owl.h @@ -1,141 +1,149 @@ #ifndef OWL_H #define OWL_H #include #include #include #include #include #include #include #include #include #include #include namespace OWL { Q_NAMESPACE enum class W : uint8_t { TITLE, BODY, IMAGE, VIDEO, LINK, TAG, AUTHOR, DATE, NOTE, TAGS, ADD_DATE, COLOR }; static const QMap SLANG = { {W::TITLE, "title"}, {W::BODY, "body"}, {W::IMAGE, "image"}, {W::VIDEO, "video"}, {W::LINK, "link"}, {W::TAG, "tag"}, {W::AUTHOR, "author"}, {W::DATE, "date"}, {W::NOTE, "note"}, {W::TAGS, "tags"}, {W::ADD_DATE, "addDate"}, {W::COLOR, "color"} }; enum class TABLE : uint8_t { NOTES, NOTES_TAGS, TAGS, BOOKS, PAGES, BOOKS_PAGES, LINKS, LINKS_TAGS, PAGES_TAGS, NONE }; static const QMap TABLEMAP = { {TABLE::NOTES,"notes"}, {TABLE::NOTES_TAGS,"notes_tags"}, {TABLE::TAGS,"tags"}, {TABLE::BOOKS,"books"}, {TABLE::PAGES,"pages"}, {TABLE::BOOKS_PAGES,"books_pages"}, {TABLE::LINKS,"links"}, {TABLE::LINKS_TAGS,"links_tags"}, {TABLE::PAGES_TAGS,"pages_tags"}, {TABLE::LINKS_TAGS,"links_tags"} }; enum class KEY :uint8_t { URL, + UPDATED, + ID, + TITLE, + BODY, FAV, COLOR, ADD_DATE, TAG, NONE }; typedef QMap DB; typedef QList DB_LIST; static const DB KEYMAP = { + {KEY::ID, "id"}, + {KEY::BODY, "body"}, + {KEY::UPDATED, "updated"}, + {KEY::TITLE, "title"}, {KEY::URL, "url"}, {KEY::FAV, "fav"}, {KEY::COLOR, "color"}, {KEY::ADD_DATE, "addDate"}, {KEY::TAG, "tag"} }; const QString CollectionDBPath = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation)+"/buho/"; const QString NotesPath = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation)+"/buho/notes/"; const QString BooksPath = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation)+"/buho/books/"; const QString LinksPath = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation)+"/buho/links/"; const QString App = "Buho"; const QString version = "1.0"; const QString DBName = "collection.db"; inline bool fileExists(const QString &url) { QFileInfo path(url); if (path.exists()) return true; else return false; } inline void saveJson(QJsonDocument document, QString fileName) { QFile jsonFile(fileName); jsonFile.open(QFile::WriteOnly); jsonFile.write(document.toJson()); } inline QVariantMap openJson(const QString &url) { QString val; QFile file; file.setFileName(url); file.open(QIODevice::ReadOnly | QIODevice::Text); val = file.readAll(); file.close(); QJsonDocument d = QJsonDocument::fromJson(val.toUtf8()); QJsonObject obj = d.object(); return obj.toVariantMap(); } } #endif // OWL_H diff --git a/src/views/notes/NotesView.qml b/src/views/notes/NotesView.qml index 3f1b273..397c436 100644 --- a/src/views/notes/NotesView.qml +++ b/src/views/notes/NotesView.qml @@ -1,20 +1,29 @@ import QtQuick 2.9 import "../../widgets" import org.kde.maui 1.0 as Maui Maui.Page { + property var currentNote : ({}) + signal noteClicked(var note) + headBarVisible: false CardsView { id: cardsView anchors.fill: parent + onItemClicked: noteClicked(cardsView.model.get(index)) } function populate() { var data = owl.getNotes() for(var i in data) - cardsView.model.append(data[i]) + append(data[i]) + } + + function append(note) + { + cardsView.model.append(note) } } diff --git a/src/widgets/CardsView.qml b/src/widgets/CardsView.qml index 34114a4..5d81255 100644 --- a/src/widgets/CardsView.qml +++ b/src/widgets/CardsView.qml @@ -1,50 +1,55 @@ import QtQuick 2.9 import QtQuick.Controls 2.2 import org.kde.kirigami 2.2 as Kirigami import org.kde.maui 1.0 as Maui GridView { property alias holder : holder property int itemWidth : Kirigami.Units.devicePixelRatio * 200 - property int itemHeight: Kirigami.Units.devicePixelRatio * 120 + property int itemHeight: Kirigami.Units.devicePixelRatio * 120 property int itemSpacing: space.huge + signal itemClicked(int index) + cellWidth: itemWidth + itemSpacing cellHeight: itemHeight + itemSpacing Maui.Holder { id: holder visible: count < 1 message: "

No notes!

You can create new notes from the add button

" } model: ListModel { ListElement {title: "Hteu"; body: "lalajsjsjdjdjdjd djdjdjdj sjsjsjsj"} ListElement {title: "Hteu"; body: "lalajsjsjdjdjdjd djdjdjdj sjsjsjsj"} ListElement {title: "Hteu"; body: "lalajsjsjdjdjdjd djdjdjdj sjsjsjsj"} ListElement {title: "Hteu"; body: "lalajsjsjdjdjdjd djdjdjdj sjsjsjsj"} } delegate: CardDelegate { id: delegate cardWidth: itemWidth cardHeight: itemHeight + + onClicked: itemClicked(index) } + onWidthChanged: adaptGrid() function adaptGrid() { var amount = parseInt(width/(itemWidth + itemSpacing),10) var leftSpace = parseInt(width-(amount*(itemWidth + itemSpacing)), 10) var size = parseInt((itemWidth + itemSpacing)+(parseInt(leftSpace/amount, 10)), 10) size = size > itemWidth + itemSpacing ? size : itemWidth + itemSpacing cellWidth = size } } diff --git a/src/widgets/NewNoteDialog.qml b/src/widgets/NewNoteDialog.qml index 5454810..7634e06 100644 --- a/src/widgets/NewNoteDialog.qml +++ b/src/widgets/NewNoteDialog.qml @@ -1,223 +1,237 @@ import QtQuick 2.9 import QtQuick.Controls 2.2 import QtQuick.Layouts 1.0 import org.kde.maui 1.0 as Maui Popup { parent: ApplicationWindow.overlay height: parent.height * (isMobile ? 0.8 : 0.7) width: parent.width * (isMobile ? 0.9 : 0.7) property string selectedColor : "#ffffe6" - + signal noteSaved(var note) x: (parent.width / 2) - (width / 2) y: (parent.height /2 ) - (height / 2) padding: 1 Rectangle { id: bg color: selectedColor z: -1 anchors.fill: parent } ColumnLayout { anchors.fill: parent Maui.ToolBar { Layout.fillWidth: true leftContent: [ Maui.ToolButton { iconName: "format-text-bold" }, Maui.ToolButton { iconName: "format-text-italic-symbolic" }, Maui.ToolButton { iconName: "format-text-underline-symbolic" }, Maui.ToolButton { iconName: "format-text-uppercase" } ] rightContent: Row { spacing: space.medium Rectangle { color:"#ffded4" anchors.verticalCenter: parent.verticalCenter height: iconSizes.medium width: height radius: Math.max(height, width) border.color: borderColor MouseArea { anchors.fill: parent onClicked: selectedColor = parent.color } } Rectangle { color:"#d3ffda" anchors.verticalCenter: parent.verticalCenter height: iconSizes.medium width: height radius: Math.max(height, width) border.color: borderColor MouseArea { anchors.fill: parent onClicked: selectedColor = parent.color } } Rectangle { color:"#caf3ff" anchors.verticalCenter: parent.verticalCenter height: iconSizes.medium width: height radius: Math.max(height, width) border.color: borderColor MouseArea { anchors.fill: parent onClicked: selectedColor = parent.color } } Rectangle { color:"#ccc1ff" anchors.verticalCenter: parent.verticalCenter height: iconSizes.medium width: height radius: Math.max(height, width) border.color: borderColor MouseArea { anchors.fill: parent onClicked: selectedColor = parent.color } } Rectangle { color:"#ffcdf4" anchors.verticalCenter: parent.verticalCenter height: iconSizes.medium width: height radius: Math.max(height, width) border.color: borderColor MouseArea { anchors.fill: parent onClicked: selectedColor = parent.color } } Maui.ToolButton { iconName: "overflow-menu" } } } TextField { id: title Layout.fillWidth: true Layout.margins: space.medium height: 24 placeholderText: qsTr("Title") font.weight: Font.Bold font.bold: true background: Rectangle { color: "transparent" } } ScrollView { Layout.fillHeight: true Layout.fillWidth: true Layout.margins: space.medium TextArea { id: body placeholderText: qsTr("Body") background: Rectangle { color: "transparent" } } } Row { Layout.fillWidth: true width: parent.width Layout.margins: space.medium Layout.alignment: Qt.AlignRight spacing: space.medium Button { id: save text: qsTr("Save") onClicked: { - if(owl.insertNote(title.text, body.text)) - close() + close() + noteSaved({ + title: title.text, + body: body.text, + color: selectedColor, + tags: "" + }) + clearNote() + } } Button { id: discard text: qsTr("Discard") onClicked: { - clearNote() close() + clearNote() } } } } - onOpened: clearNote() function clearNote() { title.clear() body.clear() } + + function fill(note) + { + title.text = note.title + body.text = note.body + + open() + } }