diff --git a/android/android.pri b/android/android.pri index 9c9c307..9881739 100644 --- a/android/android.pri +++ b/android/android.pri @@ -1,18 +1,20 @@ +QT += androidextras webview + DISTFILES += \ $$PWD/qtquickcontrols2.conf DISTFILES += \ $$PWD/AndroidManifest.xml \ $$PWD/gradle/wrapper/gradle-wrapper.jar \ $$PWD/gradlew \ $$PWD/res/values/libs.xml \ $$PWD/build.gradle \ $$PWD/gradle/wrapper/gradle-wrapper.properties \ $$PWD/gradlew.bat ANDROID_PACKAGE_SOURCE_DIR = $$PWD RESOURCES += \ $$PWD/../icons.qrc diff --git a/buho.pro b/buho.pro index a849f1f..c1c0831 100644 --- a/buho.pro +++ b/buho.pro @@ -1,86 +1,88 @@ QT += qml QT += quick QT += sql QT += widgets QT += quickcontrols2 CONFIG += c++11 DEFINES += QT_DEPRECATED_WARNINGS SOURCES += \ main.cpp \ src/db/db.cpp \ src/db/dbactions.cpp \ src/buho.cpp \ src/documenthandler.cpp \ src/linker.cpp \ src/utils/htmlparser.cpp RESOURCES += \ qml.qrc # Additional import path used to resolve QML modules in Qt Creator's code model QML_IMPORT_PATH = # Additional import path used to resolve QML modules just for Qt Quick Designer QML_DESIGNER_IMPORT_PATH = # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target include($$PWD/mauikit/mauikit.pri) include($$PWD/QGumboParser/QGumboParser.pri) linux:unix:!android { message(Building for Linux KDE) + QT += webengine + } else:android { message(Building helpers for Android) include($$PWD/3rdparty/kirigami/kirigami.pri) include($$PWD/android/android.pri) include($$PWD/android/openssl/openssl.pri) DEFINES += STATIC_KIRIGAMI } else { message("Unknown configuration") } DISTFILES += \ src/db/script.sql \ src/utils/owl.js \ android/AndroidManifest.xml \ android/gradle/wrapper/gradle-wrapper.jar \ android/gradlew \ android/res/values/libs.xml \ android/build.gradle \ android/gradle/wrapper/gradle-wrapper.properties \ android/gradlew.bat \ android/AndroidManifest.xml \ android/gradle/wrapper/gradle-wrapper.jar \ android/gradlew \ android/res/values/libs.xml \ android/build.gradle \ android/gradle/wrapper/gradle-wrapper.properties \ android/gradlew.bat HEADERS += \ src/db/db.h \ src/db/dbactions.h \ src/buho.h \ src/utils/owl.h \ src/documenthandler.h \ src/linker.h \ src/utils/htmlparser.h INCLUDEPATH += \ src/utils/ \ src/ ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android diff --git a/main.cpp b/main.cpp index f9b9296..5384421 100644 --- a/main.cpp +++ b/main.cpp @@ -1,59 +1,61 @@ #include #include #include #include #ifdef STATIC_KIRIGAMI #include "3rdparty/kirigami/src/kirigamiplugin.h" #endif #ifdef Q_OS_ANDROID #include #include #else #include #endif #include "mauikit/src/mauikit.h" #include "src/buho.h" #include "src/documenthandler.h" #include "src/linker.h" int main(int argc, char *argv[]) { QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); #ifdef Q_OS_ANDROID QGuiApplication app(argc, argv); QIcon::setThemeName("Luv"); QQuickStyle::setStyle("material"); #else QApplication app(argc, argv); #endif #ifdef STATIC_KIRIGAMI KirigamiPlugin::getInstance().registerTypes(); #endif #ifdef MAUI_APP MauiKit::getInstance().registerTypes(); #endif Buho owl; QQmlApplicationEngine engine; auto context = engine.rootContext(); context->setContextProperty("owl", &owl); Linker linker; + auto tag = owl.getTagging(); context->setContextProperty("linker", &linker); + context->setContextProperty("tag", tag); qmlRegisterType("org.buho.editor", 1, 0, "DocumentHandler"); engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); if (engine.rootObjects().isEmpty()) return -1; return app.exec(); } diff --git a/main.qml b/main.qml index 1827573..bedb0ed 100644 --- a/main.qml +++ b/main.qml @@ -1,174 +1,197 @@ 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" import "src/views/links" +import "src/views/books" Maui.ApplicationWindow { id: root title: qsTr("Buho") /***** PROPS *****/ floatingBar: true property string accentColor : highlightColor property int currentView : views.notes property var views : ({ notes: 0, links: 1, - books: 2 + books: 2, + tags: 3, + search: 4 }) - headBar.middleContent: Row - { - spacing: space.medium + headBar.middleContent: [ Maui.ToolButton { display: root.isWide ? ToolButton.TextBesideIcon : ToolButton.IconOnly onClicked: currentView = views.notes iconColor: currentView === views.notes? accentColor : textColor iconName: "draw-text" text: qsTr("Notes") - } + }, Maui.ToolButton { display: root.isWide ? ToolButton.TextBesideIcon : ToolButton.IconOnly onClicked: currentView = views.links iconColor: currentView === views.links? accentColor : textColor iconName: "link" text: qsTr("Links") - } + }, Maui.ToolButton { display: root.isWide ? ToolButton.TextBesideIcon : ToolButton.IconOnly iconColor: currentView === views.books? accentColor : textColor iconName: "document-new" text: qsTr("Books") + }, + + Maui.ToolButton + { + display: root.isWide ? ToolButton.TextBesideIcon : ToolButton.IconOnly + iconColor: currentView === views.tags? accentColor : textColor + iconName: "tag" + text: qsTr("Tags") } - } + ] footBar.middleContent: [ Maui.ToolButton { iconName: swipeView.currentItem.cardsView.gridView ? "view-list-icons" : "view-list-details" onClicked: { switch(currentView) { case views.notes: notesView.cardsView.gridView = !notesView.cardsView.gridView notesView.cardsView.refresh() break case views.links: linksView.cardsView.gridView = !linksView.cardsView.gridView linksView.cardsView.refresh() break } } }, 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") { currentView = views.notes newNoteDialog.open() } else if(item.mid === "link") { currentView = views.links newLinkDialog.open() } } } - ] /***** COMPONENTS *****/ Connections { target: owl onNoteInserted: notesView.append(note) onLinkInserted: linksView.append(link) } NewNoteDialog { id: newNoteDialog onNoteSaved: owl.insertNote(note.title.trim(), note.body, note.color, note.tags) } NewNoteDialog { id: editNote onNoteSaved: { if(owl.updateNote(notesView.currentNote.id, note.title.trim(), note.body, note.color, note.tags)) notesView.cardsView.currentItem.update(note) } } NewLinkDialog { id: newLinkDialog onLinkSaved: owl.insertLink(note.link, note.title.trim(), note.preview, note.color, note.tags) } /***** VIEWS *****/ SwipeView { id: swipeView anchors.fill: parent currentIndex: currentView onCurrentIndexChanged: currentView = currentIndex - NotesView { id: notesView onNoteClicked: setNote(note) } LinksView { id: linksView + onLinkClicked: previewLink(link) + } + + BooksView + { + id: booksView + } } Component.onCompleted: { notesView.populate() linksView.populate() } function setNote(note) { + var tags = owl.getNoteTags(note.id) + note.tags = tags notesView.currentNote = note editNote.fill(note) } + + function previewLink(link) + { + var tags = owl.getLinkTags(link.link) + link.tags = tags + linksView.previewer.show(link) + } } diff --git a/qml.qrc b/qml.qrc index 03f82ef..6c1325d 100644 --- a/qml.qrc +++ b/qml.qrc @@ -1,13 +1,17 @@ main.qml src/db/script.sql src/widgets/NewNoteDialog.qml src/widgets/CardsView.qml src/views/notes/NotesView.qml src/widgets/CardDelegate.qml src/widgets/NewLinkDialog.qml src/views/links/LinksView.qml utils.js + src/views/links/WebViewAndroid.qml + src/views/links/WebViewLinux.qml + src/views/links/Previewer.qml + src/views/books/BooksView.qml diff --git a/src/buho.cpp b/src/buho.cpp index d2dcc0e..ea7b69f 100644 --- a/src/buho.cpp +++ b/src/buho.cpp @@ -1,22 +1,27 @@ #include "buho.h" Buho::Buho(QObject *parent) : DBActions(parent) { this->setFolders(); } +Tagging *Buho::getTagging() +{ + return this->tag; +} + void Buho::setFolders() { QDir notes_path(OWL::NotesPath); if (!notes_path.exists()) notes_path.mkpath("."); QDir links_path(OWL::LinksPath); if (!links_path.exists()) links_path.mkpath("."); QDir books_path(OWL::BooksPath); if (!books_path.exists()) books_path.mkpath("."); } diff --git a/src/buho.h b/src/buho.h index 27effe8..8f5ea33 100644 --- a/src/buho.h +++ b/src/buho.h @@ -1,21 +1,23 @@ #ifndef BUHO_H #define BUHO_H #include #include "db/dbactions.h" +#include "tagging.h" class Buho : public DBActions { Q_OBJECT public: explicit Buho(QObject *parent = nullptr); + Tagging* getTagging(); private: void setFolders(); signals: public slots: }; #endif // BUHO_H diff --git a/src/db/dbactions.cpp b/src/db/dbactions.cpp index 841e80f..5061fdb 100644 --- a/src/db/dbactions.cpp +++ b/src/db/dbactions.cpp @@ -1,170 +1,179 @@ /*** 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 #include "linker.h" DBActions::DBActions(QObject *parent) : DB(parent) { qDebug() << "Getting collectionDB info from: " << OWL::CollectionDBPath; qDebug()<< "Starting DBActions"; + this->tag = Tagging::getInstance(OWL::App, OWL::version, "org.kde.buho", OWL::comment); + } 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) +bool DBActions::insertNote(const QString &title, const QString &body, const QString &color, const QStringList &tags) { + qDebug()<<"TAGS"<< tags; + auto id = QUuid::createUuid().toString(); QVariantMap note_map = { {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(this->insert(OWL::TABLEMAP[OWL::TABLE::NOTES], note_map)) { + for(auto tg : tags) + this->tag->tagAbstract(tg, OWL::TABLEMAP[OWL::TABLE::NOTES], id, color); + this->noteInserted(note_map); return true; } return false; } -bool DBActions::updateNote(const QString &id, const QString &title, const QString &body, const QString &color, const QString &tags) +bool DBActions::updateNote(const QString &id, const QString &title, const QString &body, const QString &color, const QStringList &tags) { OWL::DB note = { {OWL::KEY::TITLE, title}, {OWL::KEY::BODY, body}, {OWL::KEY::COLOR, color}, {OWL::KEY::UPDATED, QDateTime::currentDateTime().toString()} }; + for(auto tg : tags) + this->tag->tagAbstract(tg, OWL::TABLEMAP[OWL::TABLE::NOTES], id, color); + return this->update(OWL::TABLEMAP[OWL::TABLE::NOTES], note, {{OWL::KEYMAP[OWL::KEY::ID], id}} ); } QVariantList DBActions::getNotes() { return this->get("select * from notes"); } -bool DBActions::insertLink(const QString &link, const QString &title, const QString &preview, const QString &color, const QString &tags) +QVariantList DBActions::getNoteTags(const QString &id) +{ + return this->tag->getAbstractTags(OWL::TABLEMAP[OWL::TABLE::NOTES], id); +} + +bool DBActions::insertLink(const QString &link, const QString &title, const QString &preview, const QString &color, const QStringList &tags) { auto image_path = OWL::saveImage(Linker::getUrl(preview), OWL::LinksPath+QUuid::createUuid().toString()); QVariantMap link_map = { {OWL::KEYMAP[OWL::KEY::LINK], link}, {OWL::KEYMAP[OWL::KEY::TITLE], title}, {OWL::KEYMAP[OWL::KEY::PREVIEW], image_path}, {OWL::KEYMAP[OWL::KEY::COLOR], color}, {OWL::KEYMAP[OWL::KEY::ADD_DATE], QDateTime::currentDateTime()} }; - qDebug()<< link_map; if(this->insert(OWL::TABLEMAP[OWL::TABLE::LINKS], link_map)) { + for(auto tg : tags) + this->tag->tagAbstract(tg, OWL::TABLEMAP[OWL::TABLE::LINKS], link, color); + this->linkInserted(link_map); return true; } return false; } QVariantList DBActions::getLinks() { return this->get("select * from links"); } +QVariantList DBActions::getLinkTags(const QString &link) +{ + return this->tag->getAbstractTags(OWL::TABLEMAP[OWL::TABLE::LINKS], link); +} + 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 46cf69d..6eb82ca 100644 --- a/src/db/dbactions.h +++ b/src/db/dbactions.h @@ -1,54 +1,57 @@ /*** 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" +#include "tagging.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 bool insertNote(const QString &title, const QString &body, const QString &color = QString(), const QStringList &tags = QStringList()); + Q_INVOKABLE bool updateNote(const QString &id, const QString &title, const QString &body, const QString &color = QString(), const QStringList &tags = QStringList()); Q_INVOKABLE QVariantList getNotes(); + Q_INVOKABLE QVariantList getNoteTags(const QString &id); - Q_INVOKABLE bool insertLink(const QString &link, const QString &title, const QString &preview, const QString &color = QString(), const QString &tags = QString()); + Q_INVOKABLE bool insertLink(const QString &link, const QString &title, const QString &preview, const QString &color = QString(), const QStringList &tags = QStringList()); Q_INVOKABLE QVariantList getLinks(); + Q_INVOKABLE QVariantList getLinkTags(const QString &link); protected: OWL::DB_LIST getDBData(const QString &queryTxt); bool execQuery(const QString &queryTxt); - + Tagging *tag; signals: void noteInserted(QVariantMap note); void linkInserted(QVariantMap link); }; #endif // DBACTIONS_H diff --git a/src/utils/owl.h b/src/utils/owl.h index ef10b90..866a478 100644 --- a/src/utils/owl.h +++ b/src/utils/owl.h @@ -1,178 +1,179 @@ #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, PREVIEW, IMAGE, LINK, 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"}, {KEY::PREVIEW, "preview"}, {KEY::IMAGE, "image"}, {KEY::LINK, "link"} }; 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 comment = "Notes taking and link collector manager"; 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(); } inline QString saveImage(QByteArray array, const QString &path) { if(!array.isNull()&&!array.isEmpty()) { QImage img; img.loadFromData(array); QString name = path; name.replace("/", "-"); name.replace("&", "-"); QString format = "JPEG"; if (img.save(path+".jpg", format.toLatin1(), 100)) - return path; + return path+".jpg"; else qDebug() << "couldn't save artwork"; }else qDebug()<<"array is empty"; return QString(); } } #endif // OWL_H diff --git a/src/views/books/BooksView.qml b/src/views/books/BooksView.qml new file mode 100644 index 0000000..30cd52a --- /dev/null +++ b/src/views/books/BooksView.qml @@ -0,0 +1,24 @@ +import QtQuick 2.9 +import "../../widgets" +import org.kde.maui 1.0 as Maui + +Maui.Page +{ + id: control + + property alias cardsView : cardsView + + headBarVisible: false + margins: isMobile ? space.big : space.enormus + + + CardsView + { + id: cardsView + anchors.fill: parent +// onItemClicked: linkClicked(cardsView.model.get(index)) + holder.message: "

No Books!

You can create new notes
links and books

" + + } + +} diff --git a/src/views/links/LinksView.qml b/src/views/links/LinksView.qml index 768db3b..339b06a 100644 --- a/src/views/links/LinksView.qml +++ b/src/views/links/LinksView.qml @@ -1,40 +1,46 @@ import QtQuick 2.9 import "../../widgets" import org.kde.maui 1.0 as Maui Maui.Page { id: control property alias cardsView : cardsView + property alias previewer : previewer property var currentLink : ({}) - signal linkClicked(var note) + signal linkClicked(var link) headBarVisible: false margins: isMobile ? space.big : space.enormus + Previewer + { + id: previewer + } + CardsView { id: cardsView anchors.fill: parent onItemClicked: linkClicked(cardsView.model.get(index)) holder.message: "

No Links!

You can create new notes
links and books

" } function populate() { var data = owl.getLinks() for(var i in data) { console.log("PREVIEW", data[i].preview) append(data[i]) } } function append(link) { cardsView.model.append(link) } } diff --git a/src/views/links/Previewer.qml b/src/views/links/Previewer.qml new file mode 100644 index 0000000..f1b3de7 --- /dev/null +++ b/src/views/links/Previewer.qml @@ -0,0 +1,98 @@ +import QtQuick 2.0 +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 * 0.9 + width: parent.width * (isMobile ? 0.9 : 0.7) + x: (parent.width / 2) - (width / 2) + y: (parent.height /2 ) - (height / 2) + modal: true + clip: true + padding: isAndroid ? 2 : "undefined" + property alias webView: webViewer.item + + Maui.Page + { + anchors.fill: parent + margins: 0 + padding: 0 + + onExit: close() + + headBar.rightContent: [ + Maui.ToolButton + { + iconName: "entry-delete" + }, + + Maui.ToolButton + { + iconName: "document-save" + }, + + Maui.ToolButton + { + iconName: "view-fullscreen" + } + ] + + headBar.middleContent: Label + { + clip: true + text: webView.title + + horizontalAlignment: Qt.AlignHCenter + font.bold: true + font.pointSize: fontSizes.big + font.weight: Font.Bold + wrapMode: Label.WrapAnywhere + } + + ColumnLayout + { + anchors.fill: parent + + + Loader + { + id: webViewer + Layout.fillWidth: true + Layout.fillHeight: true + source: isAndroid ? "qrc:/src/views/links/WebViewAndroid.qml" : + "qrc:/src/views/links/WebViewLinux.qml" + + onVisibleChanged: + { + if(!visible) webView.url = "about:blank" + + console.log(webView.url, visible) + } + } + + Maui.TagsBar + { + id: tagBar + Layout.fillWidth: true + allowEditMode: true + + onTagsEdited: + { + for(var i in tags) + append({tag : tags[i]}) + } + } + } + } + + function show(link) + { + webView.url = link.link + tagBar.populate(link.tags) + open() + } +} diff --git a/src/views/links/WebViewAndroid.qml b/src/views/links/WebViewAndroid.qml new file mode 100644 index 0000000..3da7e4f --- /dev/null +++ b/src/views/links/WebViewAndroid.qml @@ -0,0 +1,14 @@ +import QtQuick 2.0 +import QtWebView 1.1 + +WebView +{ + id: webView + + clip: true + onLoadingChanged: + { + if (loadRequest.errorString) + console.error(loadRequest.errorString); + } +} diff --git a/src/views/links/WebViewLinux.qml b/src/views/links/WebViewLinux.qml new file mode 100644 index 0000000..c7b74e0 --- /dev/null +++ b/src/views/links/WebViewLinux.qml @@ -0,0 +1,26 @@ +import QtQuick 2.0 +import QtWebEngine 1.5 + +WebEngineView +{ + id: webView + + onLoadingChanged: + { + if (loadRequest.errorString) + console.error(loadRequest.errorString); + } + + onRecentlyAudibleChanged: + { + console.log("is playing", recentlyAudible) + if(recentlyAudible && isPlaying) + { + wasPlaying = isPlaying + Player.pauseTrack() + } + + if(!recentlyAudible && wasPlaying) + Player.resumeTrack() + } +} diff --git a/src/widgets/CardDelegate.qml b/src/widgets/CardDelegate.qml index 419c003..8186118 100644 --- a/src/widgets/CardDelegate.qml +++ b/src/widgets/CardDelegate.qml @@ -1,154 +1,156 @@ import QtQuick 2.9 import QtQuick.Controls 2.2 import QtQuick.Layouts 1.3 import QtGraphicalEffects 1.0 import org.kde.kirigami 2.2 as Kirigami ItemDelegate { id: control property string noteColor : color ? color : "pink" property int cardWidth: Kirigami.Units.devicePixelRatio*200 property int cardHeight: Kirigami.Units.devicePixelRatio*120 property int cardRadius: Kirigami.Units.devicePixelRatio*4 width: cardWidth height: cardHeight hoverEnabled: !isMobile background: Rectangle { color: "transparent" } DropShadow { anchors.fill: card visible: card.visible horizontalOffset: 0 verticalOffset: 3 radius: 8.0 samples: 17 color: "#80000000" source: card } Rectangle { id: card z: -999 anchors.centerIn: control anchors.fill: control border.color: Qt.darker(noteColor, 1.2) color: noteColor radius: cardRadius } Rectangle { anchors.fill: parent color: hovered? "#333" : "transparent" z: 999 opacity: 0.3 } ColumnLayout { anchors.fill: parent spacing: 0 clip: true Label { id: title visible: title.text.length > 0 Layout.leftMargin: space.medium Layout.topMargin: space.medium Layout.rightMargin: space.medium Layout.fillWidth: true text: model.title color: Qt.darker(model.color, 3) elide: Qt.ElideRight font.weight: Font.Bold font.bold: true font.pointSize: fontSizes.large } TextArea { id: body visible: typeof model.body !== 'undefined' Layout.leftMargin: visible ? space.medium : 0 Layout.bottomMargin: visible ? space.medium : 0 Layout.rightMargin: visible ? space.medium : 0 Layout.topMargin: title.visible ? 0 : space.medium Layout.fillHeight: visible Layout.fillWidth: visible enabled: false text: model.body color: Qt.darker(model.color, 3) textFormat: TextEdit.RichText font.pointSize: fontSizes.big background: Rectangle { color: "transparent" } } Item { id: preview Layout.fillHeight: true Layout.fillWidth: true + Layout.margins: unit clip: true Layout.topMargin: space.medium + visible: img.status === Image.Ready Image { id: img visible: status === Image.Ready asynchronous: true anchors.centerIn: parent horizontalAlignment: Qt.AlignHCenter verticalAlignment: Qt.AlignVCenter height: parent.height width: parent.width sourceSize.height: height sourceSize.width: width fillMode: Image.PreserveAspectCrop source: "file://"+encodeURIComponent( model.preview ) || "" layer.enabled: img.visible layer.effect: OpacityMask { maskSource: Item { width: img.width height: img.height Rectangle { anchors.centerIn: parent width: img.width height: img.height radius: cardRadius // radius: Math.min(width, height) } } } } } } function update(note) { title.text = note.title body.text = note.body noteColor = note.color } } diff --git a/src/widgets/CardsView.qml b/src/widgets/CardsView.qml index 19d504c..845238f 100644 --- a/src/widgets/CardsView.qml +++ b/src/widgets/CardsView.qml @@ -1,62 +1,63 @@ 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 bool gridView : true property alias holder : holder - readonly property int defaultSize : Kirigami.Units.devicePixelRatio * 200 + readonly property int defaultSize : unit * 200 property int itemWidth : !gridView ? parent.width : - isMobile? (width-itemSpacing) * 0.42 : Kirigami.Units.devicePixelRatio * 200 - property int itemHeight: Kirigami.Units.devicePixelRatio * 120 + isMobile? (width-itemSpacing) * 0.42 : unit * 200 + property int itemHeight: unit * 120 property int itemSpacing: space.huge signal itemClicked(int index) + boundsBehavior: !isMobile? Flickable.StopAtBounds : Flickable.DragAndOvershootBounds cellWidth: itemWidth + itemSpacing cellHeight: itemHeight + itemSpacing Maui.Holder { id: holder visible: count < 1 message: "

No notes!

You can create new notes
links and books

" } model: ListModel { id: cardsModel} delegate: CardDelegate { id: delegate cardWidth: itemWidth cardHeight: itemHeight onClicked: { currentIndex = index itemClicked(index) } } // onWidthChanged: if(!isMobile && gridView) 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 } function refresh() { model = cardsModel } } diff --git a/src/widgets/NewLinkDialog.qml b/src/widgets/NewLinkDialog.qml index 9f3ebe2..24e2b7b 100644 --- a/src/widgets/NewLinkDialog.qml +++ b/src/widgets/NewLinkDialog.qml @@ -1,285 +1,298 @@ import QtQuick 2.9 import QtQuick.Controls 2.2 import QtQuick.Layouts 1.0 import org.kde.maui 1.0 as Maui import org.buho.editor 1.0 import org.kde.kirigami 2.2 as Kirigami Popup { parent: ApplicationWindow.overlay height: previewReady ? parent.height * (isMobile ? 0.8 : 0.7) : - content.implicitHeight + contentLayout.implicitHeight width: parent.width * (isMobile ? 0.9 : 0.7) signal linkSaved(var note) property string selectedColor : "#ffffe6" property string fgColor: Qt.darker(selectedColor, 2.5) property bool previewReady : false x: (parent.width / 2) - (width / 2) y: (parent.height /2 ) - (height / 2) modal: true - padding: 1 + padding: isAndroid ? 1 : "undefined" Connections { target: linker onPreviewReady: { previewReady = true fill(link) } } - Rectangle - { - id: bg - color: selectedColor - z: -1 - anchors.fill: parent - } - - ColumnLayout + Maui.Page { id: content + margins: 0 anchors.fill: parent + Rectangle + { + id: bg + color: selectedColor + z: -1 + anchors.fill: parent + } - Maui.ToolBar + onExit: clear() + headBarVisible: previewReady + footBarVisible: previewReady + headBar.rightContent: Row { - position: ToolBar.Header - Layout.fillWidth: true - visible: previewReady - middleContent: Row + spacing: space.medium + Rectangle { - spacing: space.medium - Rectangle + color:"#ffded4" + anchors.verticalCenter: parent.verticalCenter + height: iconSizes.medium + width: height + radius: Math.max(height, width) + border.color: borderColor + + MouseArea { - 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 - } + anchors.fill: parent + onClicked: selectedColor = parent.color } + } - Rectangle + Rectangle + { + color:"#d3ffda" + anchors.verticalCenter: parent.verticalCenter + height: iconSizes.medium + width: height + radius: Math.max(height, width) + border.color: borderColor + + MouseArea { - 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 - } + anchors.fill: parent + onClicked: selectedColor = parent.color } + } - Rectangle + Rectangle + { + color:"#caf3ff" + anchors.verticalCenter: parent.verticalCenter + height: iconSizes.medium + width: height + radius: Math.max(height, width) + border.color: borderColor + + MouseArea { - 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 - } + anchors.fill: parent + onClicked: selectedColor = parent.color } + } - Rectangle + Rectangle + { + color:"#ccc1ff" + anchors.verticalCenter: parent.verticalCenter + height: iconSizes.medium + width: height + radius: Math.max(height, width) + border.color: borderColor + + MouseArea { - 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 - } + anchors.fill: parent + onClicked: selectedColor = parent.color } + } - Rectangle + Rectangle + { + color:"#ffcdf4" + anchors.verticalCenter: parent.verticalCenter + height: iconSizes.medium + width: height + radius: Math.max(height, width) + border.color: borderColor + + MouseArea { - 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 - } + anchors.fill: parent + onClicked: selectedColor = parent.color } } } - TextField + ColumnLayout { - id: link - Layout.fillWidth: true - Layout.margins: space.medium - height: 24 - placeholderText: qsTr("URL") - font.weight: Font.Bold - font.bold: true - font.pointSize: fontSizes.large - color: fgColor - Layout.alignment: Qt.AlignCenter - - background: Rectangle - { - color: "transparent" - } - - onAccepted: linker.extract(link.text) - } + id: contentLayout + anchors.fill: parent - TextField - { - id: title - visible: previewReady - Layout.fillWidth: true - Layout.margins: space.medium - height: 24 - placeholderText: qsTr("Title") - font.weight: Font.Bold - font.bold: true - font.pointSize: fontSizes.large - color: fgColor - - background: Rectangle + TextField { - color: "transparent" + id: link + Layout.fillWidth: true + Layout.margins: space.medium + height: rowHeight + verticalAlignment: Qt.AlignVCenter + placeholderText: qsTr("URL") + font.weight: Font.Bold + font.bold: true + font.pointSize: fontSizes.large + color: fgColor + Layout.alignment: Qt.AlignCenter + + background: Rectangle + { + color: "transparent" + } + + onAccepted: linker.extract(link.text) } - } - Item - { - Layout.fillWidth: true - Layout.fillHeight: true - visible: previewReady - ListView + TextField { - id: previewList - anchors.fill: parent - anchors.centerIn: parent - clip: true - snapMode: ListView.SnapOneItem - orientation: ListView.Horizontal - interactive: count > 1 - highlightFollowsCurrentItem: true - model: ListModel{} - onMovementEnded: + id: title + visible: previewReady + Layout.fillWidth: true + Layout.margins: space.medium + height: 24 + placeholderText: qsTr("Title") + font.weight: Font.Bold + font.bold: true + font.pointSize: fontSizes.large + color: fgColor + + background: Rectangle { - var index = indexAt(contentX, contentY) - currentIndex = index + color: "transparent" } - delegate: ItemDelegate - { - height: previewList.height - width: previewList.width + } + + Item + { + Layout.fillWidth: true + Layout.fillHeight: true + visible: previewReady - background: Rectangle + ListView + { + id: previewList + anchors.fill: parent + anchors.centerIn: parent + clip: true + snapMode: ListView.SnapOneItem + orientation: ListView.Horizontal + interactive: count > 1 + highlightFollowsCurrentItem: true + model: ListModel{} + onMovementEnded: { - color: "transparent" + var index = indexAt(contentX, contentY) + currentIndex = index } - - Image + delegate: ItemDelegate { - id: img - source: model.url - fillMode: Image.PreserveAspectFit - asynchronous: true - width: parent.width - height: parent.height - sourceSize.height: height - horizontalAlignment: Qt.AlignHCenter - verticalAlignment: Qt.AlignVCenter + height: previewList.height + width: previewList.width + + background: Rectangle + { + color: "transparent" + } + + Image + { + id: img + source: model.url + fillMode: Image.PreserveAspectFit + asynchronous: true + width: parent.width + height: parent.height + sourceSize.height: height + horizontalAlignment: Qt.AlignHCenter + verticalAlignment: Qt.AlignVCenter + } } } } + + Maui.TagsBar + { + id: tagBar + visible: previewReady + Layout.fillWidth: true + allowEditMode: true + + onTagsEdited: + { + for(var i in tags) + append({tag : tags[i]}) + } + } } - Row - { - Layout.fillWidth: true - width: parent.width - Layout.margins: space.medium - Layout.alignment: Qt.AlignRight - spacing: space.medium - visible: previewReady - layoutDirection: Qt.RightToLeft + + footBar.rightContent: [ Button { id: save text: qsTr("Save") onClicked: { var data = ({ link : link.text, title: title.text, preview: previewList.model.get(previewList.currentIndex).url, - color: selectedColor + color: selectedColor, + tags: tagBar.getTags() }) linkSaved(data) clear() } - } + }, Button { id: discard text: qsTr("Discard") onClicked: clear() } - } + ] } function clear() { title.clear() link.clear() previewList.model.clear() previewReady = false close() } function fill(note) { title.text = note.title[0] populatePreviews(note.image) open() } function populatePreviews(imgs) { for(var i in imgs) previewList.model.append({url : imgs[i]}) } } diff --git a/src/widgets/NewNoteDialog.qml b/src/widgets/NewNoteDialog.qml index 1cbb11b..fd2e277 100644 --- a/src/widgets/NewNoteDialog.qml +++ b/src/widgets/NewNoteDialog.qml @@ -1,288 +1,317 @@ import QtQuick 2.9 import QtQuick.Controls 2.2 import QtQuick.Layouts 1.0 import org.kde.maui 1.0 as Maui import org.buho.editor 1.0 Popup { parent: ApplicationWindow.overlay height: parent.height * (isMobile ? 0.8 : 0.7) width: parent.width * (isMobile ? 0.9 : 0.7) property string selectedColor : "#ffffe6" property string fgColor: Qt.darker(selectedColor, 2.5) + property bool showEditActions : false signal noteSaved(var note) x: (parent.width / 2) - (width / 2) y: (parent.height /2 ) - (height / 2) - padding: 1 modal: true - Rectangle - { - id: bg - color: selectedColor - z: -1 - anchors.fill: parent - } + padding: isAndroid ? 1 : "undefined" - ColumnLayout + Maui.Page { id: content anchors.fill: parent - - Maui.ToolBar + margins: 0 + onExit: clear() + Rectangle { - position: ToolBar.Header - z: 999 - Layout.fillWidth: true + id: bg + color: selectedColor + z: -1 + anchors.fill: parent + } - leftContent: [ - Maui.ToolButton - { - iconName: "format-text-bold" - focusPolicy: Qt.TabFocus - iconColor: checked ? highlightColor : textColor - checkable: true - checked: document.bold - onClicked: document.bold = !document.bold - }, - - Maui.ToolButton - { - iconName: "format-text-italic-symbolic" - iconColor: checked ? highlightColor : textColor - focusPolicy: Qt.TabFocus - checkable: true - checked: document.italic - onClicked: document.italic = !document.italic - }, - - Maui.ToolButton - { - iconName: "format-text-underline-symbolic" - }, + headBar.leftContent: [ - Maui.ToolButton - { - iconName: "format-text-uppercase" - } + Maui.ToolButton + { + iconName: "format-text-bold" + focusPolicy: Qt.TabFocus + iconColor: checked ? highlightColor : textColor + checkable: true + checked: document.bold + onClicked: document.bold = !document.bold + }, + + Maui.ToolButton + { + iconName: "format-text-italic-symbolic" + iconColor: checked ? highlightColor : textColor + focusPolicy: Qt.TabFocus + checkable: true + checked: document.italic + onClicked: document.italic = !document.italic + }, + + Maui.ToolButton + { + iconName: "format-text-underline-symbolic" + }, - ] + Maui.ToolButton + { + iconName: "format-text-uppercase" + }, - rightContent: Row + Maui.ToolButton { - 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 - } - } + iconName: "image" + } + ] - Rectangle + headBar.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 { - 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 - } + anchors.fill: parent + onClicked: selectedColor = parent.color } + } - Rectangle + Rectangle + { + color:"#d3ffda" + anchors.verticalCenter: parent.verticalCenter + height: iconSizes.medium + width: height + radius: Math.max(height, width) + border.color: borderColor + + MouseArea { - 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 - } + anchors.fill: parent + onClicked: selectedColor = parent.color } + } - Rectangle + Rectangle + { + color:"#caf3ff" + anchors.verticalCenter: parent.verticalCenter + height: iconSizes.medium + width: height + radius: Math.max(height, width) + border.color: borderColor + + MouseArea { - 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 - } + anchors.fill: parent + onClicked: selectedColor = parent.color } + } - Rectangle + Rectangle + { + color:"#ccc1ff" + anchors.verticalCenter: parent.verticalCenter + height: iconSizes.medium + width: height + radius: Math.max(height, width) + border.color: borderColor + + MouseArea { - 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 - } + anchors.fill: parent + onClicked: selectedColor = parent.color } + } - Maui.ToolButton - + Rectangle + { + color:"#ffcdf4" + anchors.verticalCenter: parent.verticalCenter + height: iconSizes.medium + width: height + radius: Math.max(height, width) + border.color: borderColor + + MouseArea { - iconName: "overflow-menu" + anchors.fill: parent + onClicked: selectedColor = parent.color } } - } - TextField - { - id: title - Layout.fillWidth: true - Layout.margins: space.medium - height: 24 - placeholderText: qsTr("Title") - font.weight: Font.Bold - font.bold: true - font.pointSize: fontSizes.large - - color: fgColor - background: Rectangle - { - color: "transparent" - } - } + Maui.ToolButton - DocumentHandler - { - id: document - document: body.textDocument - cursorPosition: body.cursorPosition - selectionStart: body.selectionStart - selectionEnd: body.selectionEnd - // textColor: TODO - // onLoaded: { - // body.text = text - // } - onError: { - body.text = message - body.visible = true + iconName: "overflow-menu" } } - ScrollView + ColumnLayout { - Layout.fillHeight: true - Layout.fillWidth: true - Layout.margins: space.medium + anchors.fill: parent - TextArea + TextField { - id: body - width: parent.width - height: parent.height - placeholderText: qsTr("Body") - selectByKeyboard :!isMobile - selectByMouse : !isMobile - textFormat : TextEdit.AutoText - color: fgColor + id: title + Layout.fillWidth: true + Layout.margins: space.medium + height: 24 + placeholderText: qsTr("Title") + font.weight: Font.Bold + font.bold: true font.pointSize: fontSizes.large - wrapMode: TextEdit.WrapAnywhere - + color: fgColor background: Rectangle { color: "transparent" } } + + DocumentHandler + { + id: document + document: body.textDocument + cursorPosition: body.cursorPosition + selectionStart: body.selectionStart + selectionEnd: body.selectionEnd + // textColor: TODO + // onLoaded: { + // body.text = text + // } + onError: + { + body.text = message + body.visible = true + } + } + + ScrollView + { + Layout.fillHeight: true + Layout.fillWidth: true + Layout.margins: space.medium + + TextArea + { + id: body + width: parent.width + height: parent.height + placeholderText: qsTr("Body") + selectByKeyboard :!isMobile + selectByMouse : !isMobile + textFormat : TextEdit.AutoText + color: fgColor + font.pointSize: fontSizes.large + wrapMode: TextEdit.WrapAnywhere + + background: Rectangle + { + color: "transparent" + } + } + } + + Maui.TagsBar + { + id: tagBar + Layout.fillWidth: true + allowEditMode: true + + onTagsEdited: + { + for(var i in tags) + append({tag : tags[i]}) + } + } } - Row - { - Layout.fillWidth: true - width: parent.width - Layout.margins: space.medium - Layout.alignment: Qt.AlignRight - spacing: space.medium - layoutDirection: Qt.RightToLeft + footBar.leftContent: [ + + Maui.ToolButton + { + iconName: "love" + }, + + Maui.ToolButton + { + iconName: "document-share" + + }, + + Maui.ToolButton + { + iconName: "entry-delete" + } + ] + + + footBar.rightContent: [ Button { id: save text: qsTr("Save") onClicked: { if(body.text.length > 0) noteSaved({ title: title.text, body: body.text, color: selectedColor, - tags: "" + tags: tagBar.getTags() }) - clearNote() - close() + clear() } - } + }, Button { id: discard text: qsTr("Discard") - onClicked: - { - close() - clearNote() - } + onClicked: clear() + } - } + ] } onOpened: body.forceActiveFocus() - function clearNote() + function clear() { title.clear() body.clear() + close() } function fill(note) { document.load("qrc:/texteditor.html") title.text = note.title body.text = note.body selectedColor = note.color + tagBar.populate(note.tags) open() } }