diff --git a/buho.pro b/buho.pro index 47c95d5..bf3dfa2 100644 --- a/buho.pro +++ b/buho.pro @@ -1,114 +1,114 @@ QT += qml QT += quick QT += sql -QT += webview +QT += network CONFIG += ordered CONFIG += c++17 TARGET = buho TEMPLATE = app VERSION_MAJOR = 1 -VERSION_MINOR = 0 +VERSION_MINOR = 1 VERSION_BUILD = 0 VERSION = $${VERSION_MAJOR}.$${VERSION_MINOR}.$${VERSION_BUILD} DEFINES += BUHO_VERSION_STRING=\\\"$$VERSION\\\" -DESTDIR = $$OUT_PWD/ - linux:unix:!android { message(Building for Linux KDE) LIBS += -lMauiKit -} else:android { - - message(Building helpers for Android) - - QMAKE_LINK += -nostdlib++ - ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android_files +} else { - DISTFILES += \ -$$PWD/android_files/AndroidManifest.xml + android { + message(Building for Android) + QMAKE_LINK += -nostdlib++ + QT += androidextras + QT += webview - QT += androidextras + ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android_files + DISTFILES += $$PWD/android_files/AndroidManifest.xml + DEFINES *= ANDROID_OPENSSL + } DEFINES *= \ COMPONENT_FM \ COMPONENT_TAGGING \ COMPONENT_ACCOUNTS \ COMPONENT_EDITOR \ - MAUIKIT_STYLE \ - ANDROID_OPENSSL + MAUIKIT_STYLE include($$PWD/3rdparty/kirigami/kirigami.pri) include($$PWD/3rdparty/mauikit/mauikit.pri) DEFINES += STATIC_KIRIGAMI - -} else { - message("Unknown configuration") + win32 { + QT += webengine + RC_ICONS = $$PWD/windows_files/buho.ico + } } DEFINES += QT_DEPRECATED_WARNINGS SOURCES += \ src/main.cpp \ src/db/db.cpp \ src/buho.cpp \ src/syncing/syncer.cpp \ src/syncing/notessyncer.cpp \ src/syncing/bookssyncer.cpp \ src/controllers/notes/notescontroller.cpp \ src/controllers/books/bookscontroller.cpp \ src/models/notes/notes.cpp \ src/models/books/books.cpp \ src/models/books/booklet.cpp \ src/models/links/links.cpp \ src/providers/nextnote.cpp \ RESOURCES += \ - src/qml.qrc \ - src/assets/assets.qrc + src/assets/imgs.qrc \ + src/qml.qrc HEADERS += \ src/db/db.h \ src/buho.h \ src/syncing/notessyncer.h \ src/syncing/bookssyncer.h \ src/syncing/syncer.h \ src/controllers/notes/notescontroller.h \ src/controllers/books/bookscontroller.h \ src/utils/owl.h \ src/models/notes/notes.h \ src/models/books/books.h \ src/models/books/booklet.h \ src/models/links/links.h \ src/providers/nextnote.h \ src/providers/abstractnotesprovider.h INCLUDEPATH += \ src/utils/ \ src/providers/ \ src/syncing/ \ src/controllers/ \ src/ # 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 DISTFILES += \ src/db/script.sql \ include($$PWD/install.pri) + diff --git a/macos_files/nota.icns b/macos_files/nota.icns new file mode 100644 index 0000000..1a51112 Binary files /dev/null and b/macos_files/nota.icns differ diff --git a/src/assets/assets.qrc b/src/assets/imgs.qrc similarity index 100% rename from src/assets/assets.qrc rename to src/assets/imgs.qrc diff --git a/src/main.cpp b/src/main.cpp index 4a757eb..48b5c7e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,75 +1,79 @@ #include #include #ifdef STATIC_KIRIGAMI #include "3rdparty/kirigami/src/kirigamiplugin.h" #endif #ifdef STATIC_MAUIKIT #include "3rdparty/mauikit/src/mauikit.h" #include "mauiapp.h" #else #include #endif #ifdef Q_OS_ANDROID #include #include #else #include #endif +#ifdef Q_OS_WIN +#include +#else #include +#endif #include "buho.h" #include "models/books/booklet.h" #include "models/books/books.h" #include "models/links/links.h" #include "models/notes/notes.h" int Q_DECL_EXPORT main(int argc, char *argv[]) { QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + QtWebEngine::initialize(); #ifdef Q_OS_ANDROID QGuiApplication app(argc, argv); if (!MAUIAndroid::checkRunTimePermissions({"android.permission.WRITE_EXTERNAL_STORAGE"})) return -1; #else QApplication app(argc, argv); #endif - QtWebView::initialize(); app.setApplicationName(OWL::appName); app.setApplicationVersion(OWL::version); app.setApplicationDisplayName(OWL::displayName); app.setOrganizationName(OWL::orgName); app.setOrganizationDomain(OWL::orgDomain); app.setWindowIcon(QIcon(":/buho.png")); MauiApp::instance()->setCredits ({QVariantMap({{"name", "Camilo Higuita"}, {"email", "milo.h@aol.com"}, {"year", "2019-2020"}})}); MauiApp::instance()->setCredits ({QVariantMap({{"name", "Camilo Higuita"}, {"email", "milo.h@aol.com"}, {"year", "2019-2020"}})}); #ifdef STATIC_KIRIGAMI KirigamiPlugin::getInstance().registerTypes(); #endif #ifdef STATIC_MAUIKIT MauiKit::getInstance().registerTypes(); #endif Buho owl; QQmlApplicationEngine engine; qmlRegisterType(); qmlRegisterType("Notes", 1, 0, "Notes"); qmlRegisterType("Books", 1, 0, "Books"); qmlRegisterType("Links", 1, 0, "Links"); engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); if (engine.rootObjects().isEmpty()) return -1; return app.exec(); } diff --git a/src/providers/nextnote.cpp b/src/providers/nextnote.cpp index 21af8d7..cf301cc 100644 --- a/src/providers/nextnote.cpp +++ b/src/providers/nextnote.cpp @@ -1,371 +1,371 @@ #include "nextnote.h" #include -#include +//#include #include #include #include #ifdef STATIC_MAUIKIT #include "fm.h" #else #include #endif const QString NextNote::API = QStringLiteral("/index.php/apps/notes/api/v0.2/"); static const inline QNetworkRequest formRequest(const QUrl &url, const QString &user, const QString &password) { if(!url.isValid() && !user.isEmpty() && !password.isEmpty()) return QNetworkRequest(); const QString concatenated = user + ":" + password; const QByteArray data = concatenated.toLocal8Bit().toBase64(); const QString headerData = "Basic " + data; // QVariantMap headers // { // {"Authorization", headerData.toLocal8Bit()}, // {QString::number(QNetworkRequest::ContentTypeHeader),"application/json"} // }; QNetworkRequest request; request.setUrl(QUrl(url)); request.setHeader(QNetworkRequest::ContentTypeHeader,"application/json"); request.setRawHeader(QString("Authorization").toLocal8Bit(), headerData.toLocal8Bit()); return request; } NextNote::NextNote(QObject *parent) : AbstractNotesProvider(parent) { } NextNote::~NextNote() { } void NextNote::getNote(const QString &id) { QUrl relativeUrl("../.."+NextNote::API+QString("notes/%1").arg(id)); auto url = QUrl(this->m_provider).resolved(relativeUrl); qDebug()<< "THE RESOLVED URL IS" << url << this->m_provider; const auto request = formRequest(url, this->m_user, this->m_password); QString concatenated = this->m_user + ":" + this->m_password; QByteArray data = concatenated.toLocal8Bit().toBase64(); QString headerData = "Basic " + data; QMap header {{"Authorization", headerData.toLocal8Bit()}}; auto downloader = new FMH::Downloader; connect(downloader, &FMH::Downloader::dataReady, [=](QByteArray array) { const auto notes = this->parseNotes(array); emit this->noteReady(notes.isEmpty() ? FMH::MODEL() : notes.first()); downloader->deleteLater(); }); downloader->getArray(url, header); } void NextNote::getBooklet(const QString &id) { } void NextNote::sendNotes(QByteArray array) { // emit this->notesReady(notes); } void NextNote::getNotes() { QUrl relativeUrl("../.."+NextNote::API+QString("notes")); auto url = QUrl(this->m_provider).resolved(relativeUrl); qDebug()<< "THE RESOLVED URL IS" << url << this->m_provider; QString concatenated = this->m_user + ":" + this->m_password; QByteArray data = concatenated.toLocal8Bit().toBase64(); QString headerData = "Basic " + data; QMap header {{"Authorization", headerData.toLocal8Bit()}}; const auto downloader = new FMH::Downloader; connect(downloader, &FMH::Downloader::dataReady, [=](QByteArray array) { //exclude notes that have its own category FMH::MODEL_LIST notes; for(const auto &data : this->parseNotes(array)) { auto item = data; item[FMH::MODEL_KEY::STAMP] = item[FMH::MODEL_KEY::ID]; item[FMH::MODEL_KEY::USER] = this->user (); item[FMH::MODEL_KEY::SERVER] = this->provider (); item[FMH::MODEL_KEY::FORMAT] = ".txt"; if(item[FMH::MODEL_KEY::CATEGORY].isEmpty() || item[FMH::MODEL_KEY::CATEGORY].isNull()) notes << item; } emit this->notesReady(notes); downloader->deleteLater(); }); downloader->getArray(url, header); } void NextNote::getBooklets() { QUrl relativeUrl("../.."+NextNote::API+QString("notes")); auto url = QUrl(this->m_provider).resolved(relativeUrl); qDebug()<< "THE RESOLVED URL IS" << url << this->m_provider; QString concatenated = this->m_user + ":" + this->m_password; QByteArray data = concatenated.toLocal8Bit().toBase64(); QString headerData = "Basic " + data; QMap header {{"Authorization", headerData.toLocal8Bit()}}; const auto downloader = new FMH::Downloader; connect(downloader, &FMH::Downloader::dataReady, [=](QByteArray array) { //exclude notes that do not have their own category FMH::MODEL_LIST booklets; for(const auto &data : this->parseNotes(array)) { auto item = data; item[FMH::MODEL_KEY::STAMP] = item[FMH::MODEL_KEY::ID]; item[FMH::MODEL_KEY::USER] = this->user (); item[FMH::MODEL_KEY::SERVER] = this->provider (); item[FMH::MODEL_KEY::FORMAT] = ".txt"; if(!item[FMH::MODEL_KEY::CATEGORY].isEmpty() && !item[FMH::MODEL_KEY::CATEGORY].isNull()) booklets << item; } emit this->bookletsReady(booklets); downloader->deleteLater(); }); downloader->getArray(url, header); } void NextNote::insertNote(const FMH::MODEL ¬e) { QByteArray payload = QJsonDocument::fromVariant(FMH::toMap(FMH::filterModel(note, {FMH::MODEL_KEY::CONTENT, FMH::MODEL_KEY::FAVORITE}))).toJson(); qDebug() << "UPLOADING NEW NOT" << QVariant(payload).toString(); QUrl relativeUrl("../.."+NextNote::API+QString("notes")); auto url = QUrl(this->m_provider).resolved(relativeUrl); qDebug()<< "THE RESOLVED URL IS" << url << this->m_provider; const auto request = formRequest(url, this->m_user, this->m_password); auto restclient = new QNetworkAccessManager; //constructor QNetworkReply *reply = restclient->post(request,payload); connect(reply, &QNetworkReply::finished, [=, __note = note]() { qDebug() << "Note insertyion finished?"; const auto notes = this->parseNotes(reply->readAll()); emit this->noteInserted([&]() -> FMH::MODEL { FMH::MODEL note; if(!notes.isEmpty()) { note = notes.first(); note[FMH::MODEL_KEY::STAMP] = note[FMH::MODEL_KEY::ID]; //adds the id of the uploaded note as a stamp note[FMH::MODEL_KEY::ID] = __note[FMH::MODEL_KEY::ID]; //adds the url of the original local note note[FMH::MODEL_KEY::SERVER] = this->m_provider; //adds the provider server address note[FMH::MODEL_KEY::USER] = this->m_user; //adds the user name } return note; }()); reply->deleteLater (); restclient->deleteLater(); }); } void NextNote::insertBooklet(const FMH::MODEL &booklet) { QByteArray payload = QJsonDocument::fromVariant(FMH::toMap(FMH::filterModel(booklet, {FMH::MODEL_KEY::CONTENT, FMH::MODEL_KEY::FAVORITE, FMH::MODEL_KEY::CATEGORY}))).toJson(); qDebug() << "UPLOADING NEW BOOKLET" << QVariant(payload).toString(); QUrl relativeUrl("../.."+NextNote::API+QString("notes")); auto url = QUrl(this->m_provider).resolved(relativeUrl); qDebug()<< "THE RESOLVED URL IS" << url << this->m_provider; const auto request = formRequest(url, this->m_user, this->m_password); auto restclient = new QNetworkAccessManager; //constructor QNetworkReply *reply = restclient->post(request,payload); connect(reply, &QNetworkReply::finished, [=, __booklet = booklet]() { qDebug() << "Note insertyion finished?"; const auto booklets = this->parseNotes(reply->readAll()); emit this->bookletInserted([&]() -> FMH::MODEL { FMH::MODEL p_booklet; if(!booklets.isEmpty()) { p_booklet = booklets.first(); p_booklet[FMH::MODEL_KEY::STAMP] = p_booklet[FMH::MODEL_KEY::ID]; //adds the id of the local note as a stamp p_booklet[FMH::MODEL_KEY::ID] = __booklet[FMH::MODEL_KEY::ID]; //adds the id of the local note as a stamp p_booklet[FMH::MODEL_KEY::SERVER] = this->m_provider; //adds the provider server address p_booklet[FMH::MODEL_KEY::USER] = this->m_user; //adds the user name } return p_booklet; }()); restclient->deleteLater(); reply->deleteLater(); }); } void NextNote::updateNote(const QString &id, const FMH::MODEL ¬e) { if(id.isEmpty() || note.isEmpty()) { qWarning()<< "The id or note are empty. Can not proceed. NextNote::update"; return; } QByteArray payload = QJsonDocument::fromVariant(FMH::toMap(FMH::filterModel(note, {FMH::MODEL_KEY::CONTENT, FMH::MODEL_KEY::FAVORITE, FMH::MODEL_KEY::MODIFIED, FMH::MODEL_KEY::CATEGORY}))).toJson(); qDebug() << "UPDATING NOTE" << QVariant(payload).toString(); QUrl relativeUrl("../.."+NextNote::API+QString("notes/%1").arg(id)); auto url = QUrl(this->m_provider).resolved(relativeUrl); qDebug()<< "THE RESOLVED URL IS" << url << this->m_provider; qDebug()<< "tryiong to update note" << url; const auto request = formRequest(url, this->m_user, this->m_password); auto restclient = new QNetworkAccessManager; //constructor QNetworkReply *reply = restclient->put(request, payload); connect(reply, &QNetworkReply::finished, [=, __note = note]() { qDebug() << "Note update finished?" << reply->errorString(); const auto notes = this->parseNotes(reply->readAll()); emit this->noteUpdated([&]() -> FMH::MODEL { FMH::MODEL note; if(notes.isEmpty()) return note; note = notes.first(); note[FMH::MODEL_KEY::STAMP] = note[FMH::MODEL_KEY::ID]; //adds the id of the local note as a stamp note[FMH::MODEL_KEY::ID] = __note[FMH::MODEL_KEY::ID]; //adds the id of the local note as a stamp note[FMH::MODEL_KEY::SERVER] = this->m_provider; //adds the provider server address note[FMH::MODEL_KEY::USER] = this->m_user; //adds the user name return note; }()); restclient->deleteLater(); reply->deleteLater(); }); } void NextNote::updateBooklet(const QString &id, const FMH::MODEL &booklet) { if(id.isEmpty() || booklet.isEmpty()) { qWarning()<< "The id or note are empty. Can not proceed. NextNote::update"; return; } QByteArray payload = QJsonDocument::fromVariant(FMH::toMap(FMH::filterModel(booklet, {FMH::MODEL_KEY::CONTENT, FMH::MODEL_KEY::CATEGORY}))).toJson(); qDebug() << "UPDATING BOOKLET" << QVariant(payload).toString(); QUrl relativeUrl("../.."+NextNote::API+QString("notes/%1").arg(id)); auto url = QUrl(this->m_provider).resolved(relativeUrl); qDebug()<< "THE RESOLVED URL IS" << url << this->m_provider; qDebug()<< "tryiong to update note" << url; const auto request = formRequest(url, this->m_user, this->m_password); auto restclient = new QNetworkAccessManager; //constructor QNetworkReply *reply = restclient->put(request, payload); connect(reply, &QNetworkReply::finished, [=, __booklet = booklet]() { qDebug() << "Note update finished?" << reply->errorString(); const auto booklets = this->parseNotes(reply->readAll()); emit this->bookletUpdated([&]() -> FMH::MODEL { FMH::MODEL booklet; if(booklets.isEmpty()) return booklet; booklet = booklets.first(); booklet[FMH::MODEL_KEY::STAMP] = booklet[FMH::MODEL_KEY::ID]; //adds the stamp to the local note form the remote id booklet[FMH::MODEL_KEY::ID] = __booklet[FMH::MODEL_KEY::ID]; //adds back the id of the local booklet booklet[FMH::MODEL_KEY::SERVER] = this->m_provider; //adds the provider server address booklet[FMH::MODEL_KEY::USER] = this->m_user; //adds the user name return booklet; }()); restclient->deleteLater(); reply->deleteLater(); }); } void NextNote::removeNote(const QString &id) { if(id.isEmpty()) { qWarning()<< "The id is empty. Can not proceed. NextNote::remove"; return; } QUrl relativeUrl("../.."+NextNote::API+QString("notes/%1").arg(id)); auto url = QUrl(this->m_provider).resolved(relativeUrl); qDebug()<< "THE RESOLVED URL IS" << url << this->m_provider; const auto request = formRequest(url, this->m_user, this->m_password); qDebug()<< "trying to remove nextnote <<" << url; auto restclient = new QNetworkAccessManager; //constructor QNetworkReply *reply = restclient->deleteResource(request); connect(reply, &QNetworkReply::finished, [=]() { qDebug() << "Note remove finished?" << reply->errorString(); emit this->noteRemoved(); restclient->deleteLater(); reply->deleteLater(); }); } void NextNote::removeBooklet(const QString &id) { this->removeNote(id); } const FMH::MODEL_LIST NextNote::parseNotes(const QByteArray &array) { FMH::MODEL_LIST res; // qDebug()<< "trying to parse notes" << array; QJsonParseError jsonParseError; QJsonDocument jsonResponse = QJsonDocument::fromJson(static_cast(array).toUtf8(), &jsonParseError); if (jsonParseError.error != QJsonParseError::NoError) { qDebug()<< "ERROR PARSING" << array; return res; } const auto data = jsonResponse.toVariant(); if(data.isNull() || !data.isValid()) return res; if(!data.toList().isEmpty()) res << FMH::toModelList(data.toList()); else res << FMH::toModel(data.toMap()); return res; } diff --git a/src/views/books/NewBookDialog.qml b/src/views/books/NewBookDialog.qml index 4475dfc..a9311a3 100644 --- a/src/views/books/NewBookDialog.qml +++ b/src/views/books/NewBookDialog.qml @@ -1,28 +1,28 @@ import QtQuick 2.9 import QtQuick.Controls 2.3 import QtQuick.Layouts 1.3 import org.kde.mauikit 1.0 as Maui import org.kde.kirigami 2.7 as Kirigami -Maui.Dialog +Maui.NewDialog { id: control signal bookSaved(string title) entryField: true title: qsTr("New Book") message: qsTr("Give a title to your new book. Your new book can contain many notes grouped together") textEntry.placeholderText: qsTr("My Book...") acceptButton.text: qsTr("Create") rejectButton.text: qsTr("Cancel") onAccepted: { control.bookSaved(textEntry.text) close() } } diff --git a/src/widgets/NewLinkDialog.qml b/src/widgets/NewLinkDialog.qml index ab83bf6..2b5df84 100644 --- a/src/widgets/NewLinkDialog.qml +++ b/src/widgets/NewLinkDialog.qml @@ -1,172 +1,172 @@ import QtQuick 2.9 import QtQuick.Controls 2.2 import QtQuick.Layouts 1.0 import org.kde.mauikit 1.0 as Maui import org.kde.kirigami 2.7 as Kirigami -import QtWebView 1.1 +import QtWebEngine 1.5 Maui.Dialog { id: control parent: parent signal linkSaved(var link) property bool previewReady : false heightHint: 0.95 widthHint: 0.95 - maxHeight: previewReady ? 1000 : contentLayout.implicitHeight + maxHeight: previewReady ? 1000 : implicitHeight maxWidth: Maui.Style.unit *700 modal: true page.padding: 0 headBar.visible: previewReady footBar.visible: previewReady headBar.leftContent: [ TextField { id: title visible: previewReady Layout.fillWidth: true Layout.margins: Maui.Style.space.medium height: 24 placeholderText: qsTr("Title") font.weight: Font.Bold font.bold: true font.pointSize: Maui.Style.fontSizes.large text: _webView.title background: Rectangle { color: "transparent" } } ] footBar.leftContent: [ ToolButton { id: favButton icon.name: "love" checkable: true icon.color: checked ? "#ff007f" : Kirigami.Theme.textColor }, ToolButton { icon.name: "document-share" onClicked: isAndroid ? Maui.Android.shareText(link.text) : shareDialog.show(link.text) }, ToolButton { icon.name: "document-export" } ] acceptText: qsTr("Save") rejectText: qsTr("Discard") onAccepted: packLink() onRejected: close() ColumnLayout { id: contentLayout Layout.fillHeight: true Layout.fillWidth: true TextField { id: link Layout.fillWidth: true Layout.margins: Maui.Style.space.medium height: Maui.Style.rowHeight verticalAlignment: Qt.AlignVCenter placeholderText: qsTr("URL") font.weight: Font.Bold font.bold: true font.pointSize: Maui.Style.fontSizes.large Layout.alignment: Qt.AlignCenter text: _webView.url background: Rectangle { color: "transparent" } onAccepted: { _webView.url = link.text control.previewReady = true } } - WebView + WebEngineView { id: _webView Layout.fillHeight: true Layout.fillWidth: true visible: control.previewReady } Maui.TagsBar { id: tagBar position: ToolBar.Footer visible: control.previewReady Layout.fillWidth: visible allowEditMode: true list.abstract: true list.key: "links" list.lot: _webView.url onTagsEdited: list.updateToAbstract(tags) onTagRemovedClicked: list.removeFromAbstract(index) } } onClosed: { control.previewReady = false _webView.stop() link.clear() tagBar.clear() } function fill(link) { tagBar.list.lot= link.url _webView.url = link.url favButton.checked = link.favorite == 1 if(link.url) control.previewReady = true open() } function packLink() { const imgUrl = linksView.list.previewsCachePath() +Math.floor(Math.random() * 100) + ".jpeg"; _webView.grabToImage(function (result) { console.log("save to", imgUrl) result.saveToFile(imgUrl) var data = ({ url : _webView.url, title: title.text, preview: "file://"+imgUrl, tag: tagBar.list.tags.join(","), favorite: favButton.checked ? 1 : 0 }) linkSaved(data) close() }, Qt.size(_webView.width -48,Math.min( _webView.height - 48, _webView.width * 1.2))); } } diff --git a/src/widgets/NewNoteDialog.qml b/src/widgets/NewNoteDialog.qml index c14a92f..b444db4 100644 --- a/src/widgets/NewNoteDialog.qml +++ b/src/widgets/NewNoteDialog.qml @@ -1,141 +1,149 @@ import QtQuick 2.9 import QtQuick.Controls 2.2 import QtQuick.Layouts 1.0 import org.kde.mauikit 1.0 as Maui import org.kde.kirigami 2.7 as Kirigami Maui.Page { id: control property alias editor: _editor property string backgroundColor: note.color ? note.color : Kirigami.Theme.backgroundColor property bool showEditActions : false signal noteSaved(var note) property var note : ({}) + footBar.rightContent: Button + { + text: qsTr("Save") + onClicked: packNote() + } + footBar.leftContent: [ ToolButton { id: favButton icon.name: "love" checkable: true checked: note.favorite == 1 icon.color: checked ? "#ff007f" : Kirigami.Theme.textColor }, ToolButton { icon.name: "document-share" onClicked: isAndroid ? Maui.Android.shareText(editor.body.text) : shareDialog.show(editor.body.text) icon.color: Kirigami.Theme.textColor }, ToolButton { icon.name: "document-export" icon.color: Kirigami.Theme.textColor }, ToolButton { icon.name: "entry-delete" icon.color: Kirigami.Theme.textColor } ] ColumnLayout { anchors.fill: parent spacing: 0 Maui.Editor { id: _editor fileUrl: control.note.url ? control.note.url : "" showLineNumbers: false document.autoReload: true Layout.fillHeight: true Layout.fillWidth: true body.font.pointSize: Maui.Style.fontSizes.big Kirigami.Theme.backgroundColor: control.backgroundColor Kirigami.Theme.textColor: control.backgroundColor.length ? Qt.darker(control.backgroundColor, 2) : control.Kirigami.Theme.textColor document.enableSyntaxHighlighting: false body.placeholderText: qsTr("Title\nBody") footBar.visible: false headBar.leftContent: ToolButton { icon.name: "image" icon.color: control.Kirigami.Theme.textColor } headBar.farLeftContent: ToolButton { icon.name: "go-previous" onClicked: control.parent.pop(StackView.Immediate) } headBar.rightContent: ColorsBar { onColorPicked: control.backgroundColor = color } } Maui.TagsBar { id: tagBar position: ToolBar.Footer Layout.fillWidth: true allowEditMode: true onTagsEdited: { if((editor.fileUrl).toString().length > 0) tagBar.list.updateToAbstract(tags) else tagBar.list.append(tags) } list.strict: true list.abstract: true list.key: "notes" list.lot: control.note.url ? control.note.url : " " // onTagRemovedClicked: list.removeFromAbstract(index) Kirigami.Theme.backgroundColor: "transparent" Kirigami.Theme.textColor: Kirigami.Theme.textColor } } function clear() { editor.body.clear() control.note = ({}) } function fill(note) { } function packNote() { const content = editor.body.text if(content.length == 0) return; control.noteSaved({ url: editor.fileUrl, content: content, color: control.backgroundColor ? control.backgroundColor : "", tag: tagBar.list.tags.join(","), favorite: favButton.checked ? 1 : 0, format: ".txt" //for now only simple txt files }) control.clear() + control.parent.pop(StackView.Immediate) + } } diff --git a/windows_files/README b/windows_files/README new file mode 100644 index 0000000..e211e80 --- /dev/null +++ b/windows_files/README @@ -0,0 +1,6 @@ +Shows how to add an entry to the Windows start menu. + +Generate installer with + +binarycreator --offline-only -c config/config.xml -p packages installer +C:\Qt\QtIFW2.0.1\bin\binarycreator.exe --offline-only -c config\config.xml -p packages VvaveInstaller.exe \ No newline at end of file diff --git a/windows_files/buho.ico b/windows_files/buho.ico new file mode 100644 index 0000000..bc988eb Binary files /dev/null and b/windows_files/buho.ico differ diff --git a/windows_files/config/config.xml b/windows_files/config/config.xml new file mode 100644 index 0000000..6dd3520 --- /dev/null +++ b/windows_files/config/config.xml @@ -0,0 +1,9 @@ + + + Buho + 1.1.0 + Buho Notes Taker + Maui + Buho + @ApplicationsDir@/buho + diff --git a/windows_files/packages/org.maui.buho/meta/installscript.qs b/windows_files/packages/org.maui.buho/meta/installscript.qs new file mode 100644 index 0000000..d4ae807 --- /dev/null +++ b/windows_files/packages/org.maui.buho/meta/installscript.qs @@ -0,0 +1,50 @@ +/************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** +** $QT_END_LICENSE$ +** +**************************************************************************/ + +function Component() +{ + // default constructor +} + +Component.prototype.createOperations = function() +{ + // call default implementation to actually install README.txt! + component.createOperations(); + + if (systemInfo.productType === "windows") { + component.addOperation("CreateShortcut", "@TargetDir@/buho.exe", "@StartMenuDir@/buho.lnk", + "workingDirectory=@TargetDir@", "iconPath=%SystemRoot%/system32/SHELL32.dll", + "iconId=2"); + } +} diff --git a/windows_files/packages/org.maui.buho/meta/package.xml b/windows_files/packages/org.maui.buho/meta/package.xml new file mode 100644 index 0000000..bf4e43c --- /dev/null +++ b/windows_files/packages/org.maui.buho/meta/package.xml @@ -0,0 +1,9 @@ + + + Buho + Buho Notes Taker + 1.1.0-1 + 2020-04-04 + true + + diff --git a/windows_files/packages/package.xml b/windows_files/packages/package.xml new file mode 100644 index 0000000..1919308 --- /dev/null +++ b/windows_files/packages/package.xml @@ -0,0 +1,14 @@ + + + Buho + Buho Notes Taker + 1.1.0-1 + 2020-04-13 + + + + true + + page.ui + +