diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..93b7d73 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,39 @@ +sudo: required + +services: + - docker + +addons: + apt: + packages: + - realpath + +install: + - docker pull ubuntu:bionic + - wget https://raw.githubusercontent.com/nomad-desktop/nxos-repository-util/master/nxos-repository-util.sh -O nxos-repository-util.sh + - chmod +x nxos-repository-util.sh + +script: + - docker run --rm -v $(pwd)/:/build/ -w /build/ ubuntu:bionic /bin/bash travis-build.sh + +branches: + only: + - master + - development + +deploy: + - provider: script + script: ./source/nxos-repository-util.sh upload testing *.deb + skip_cleanup: true + on: + branch: master + + - provider: script + script: ./source/nxos-repository-util.sh upload development *.deb + skip_cleanup: true + on: + branch: development + +notifications: + email: false + slack: nitrux:LgpKKPnWky7IWShmzXsyVDWu diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..c15b73d --- /dev/null +++ b/debian/changelog @@ -0,0 +1,5 @@ +buho (1.0-1) unstable; urgency=medium + + * Initial release (Closes: #nnnn) + + -- Bruno Queiros Sat, 01 Dec 2018 16:08:24 +0000 diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000..f599e28 --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +10 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..b0019c5 --- /dev/null +++ b/debian/control @@ -0,0 +1,15 @@ +Source: buho +Section: unknown +Priority: optional +Maintainer: Bruno Queiros +Build-Depends: debhelper (>= 10) +Standards-Version: 4.1.2 +Homepage: +#Vcs-Git: https://anonscm.debian.org/git/collab-maint/buho.git +#Vcs-Browser: https://anonscm.debian.org/cgit/collab-maint/buho.git + +Package: buho +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends} +Description: + diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..ca92cc6 --- /dev/null +++ b/debian/copyright @@ -0,0 +1,38 @@ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: buho +Source: + +Files: * +Copyright: + +License: + + + . + + +# If you want to use GPL v2 or later for the /debian/* files use +# the following clauses, or change it to suit. Delete these two lines +Files: debian/* +Copyright: 2018 Bruno Queiros +License: GPL-2+ + This package 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 2 of the License, or + (at your option) any later version. + . + This package 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 + . + On Debian systems, the complete text of the GNU General + Public License version 2 can be found in "/usr/share/common-licenses/GPL-2". + +# Please also look if there are files or directories which have a +# different copyright/license attached and list them here. +# Please avoid picking licenses with terms that are more restrictive than the +# packaged work, as it may make Debian's contributions unacceptable upstream. diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..e1c367c --- /dev/null +++ b/debian/rules @@ -0,0 +1,25 @@ +#!/usr/bin/make -f +# See debhelper(7) (uncomment to enable) +# output every command that modifies files on the build system. +#export DH_VERBOSE = 1 + + +# see FEATURE AREAS in dpkg-buildflags(1) +#export DEB_BUILD_MAINT_OPTIONS = hardening=+all + +# see ENVIRONMENT in dpkg-buildflags(1) +# package maintainers to append CFLAGS +#export DEB_CFLAGS_MAINT_APPEND = -Wall -pedantic +# package maintainers to append LDFLAGS +#export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed + + +%: + dh $@ + + +# dh_make generated override targets +# This is example for Cmake (See https://bugs.debian.org/641051 ) +#override_dh_auto_configure: +# dh_auto_configure -- # -DCMAKE_LIBRARY_PATH=$(DEB_HOST_MULTIARCH) + diff --git a/debian/source/format b/debian/source/format new file mode 100644 index 0000000..163aaf8 --- /dev/null +++ b/debian/source/format @@ -0,0 +1 @@ +3.0 (quilt) diff --git a/main.cpp b/main.cpp index f7bccf4..58f427b 100644 --- a/main.cpp +++ b/main.cpp @@ -1,80 +1,80 @@ #include #include #include #include #ifdef STATIC_KIRIGAMI #include "3rdparty/kirigami/src/kirigamiplugin.h" #endif #ifdef STATIC_MAUIKIT #include "./mauikit/src/mauikit.h" #endif #ifdef Q_OS_ANDROID #include #include #include #else #include #include #endif -#include "src/buho.h" -#include "src/linker.h" +#include "./src/buho.h" +#include "./src/linker.h" -#include "models/basemodel.h" -#include "models/baselist.h" +#include "./src/models/basemodel.h" +#include "./src/models/baselist.h" -#include "models/notes/notes.h" -#include "models/links/links.h" +#include "./src/models/notes/notes.h" +#include "./src/models/links/links.h" int main(int argc, char *argv[]) { QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); #ifdef Q_OS_ANDROID QGuiApplication app(argc, argv); QtWebView::initialize(); #else QApplication app(argc, argv); // QtWebEngine::initialize(); #endif app.setApplicationName(OWL::App); app.setApplicationVersion(OWL::version); app.setApplicationDisplayName(OWL::App); app.setWindowIcon(QIcon(":/buho.png")); #ifdef STATIC_KIRIGAMI KirigamiPlugin::getInstance().registerTypes(); #endif #ifdef STATIC_MAUIKIT MauiKit::getInstance().registerTypes(); #endif Buho owl; QQmlApplicationEngine engine; auto context = engine.rootContext(); context->setContextProperty("owl", &owl); Linker linker; context->setContextProperty("linker", &linker); qmlRegisterUncreatableMetaObject(OWL::staticMetaObject, "OWL", 1, 0, "KEY", "Error"); qmlRegisterUncreatableType("BaseList", 1, 0, "BaseList", QStringLiteral("BaseList should not be created in QML")); qmlRegisterType("BuhoModel", 1, 0, "BuhoModel"); qmlRegisterType("Notes", 1, 0, "Notes"); 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/db/db.h b/src/db/db.h index 182a946..4ea53f0 100644 --- a/src/db/db.h +++ b/src/db/db.h @@ -1,75 +1,74 @@ /*** Pix 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 DB_H #define DB_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../utils/owl.h" - class DB : public QObject { Q_OBJECT private: explicit DB(QObject *parent = nullptr); ~DB(); static DB* instance; QString name; QSqlDatabase m_db; public: static DB *getInstance(); /* utils*/ bool checkExistance(const QString &tableName, const QString &searchId, const QString &search); OWL::DB_LIST getDBData(const QString &queryTxt); QSqlQuery getQuery(const QString &queryTxt); bool insert(const QString &tableName, const QVariantMap &insertData); bool update(const QString &tableName, const QVariantMap &updateData, const QVariantMap &where); bool update(const QString &table, const QString &column, const QVariant &newValue, const QVariant &op, const QString &id); bool remove(const QString &tableName, const QVariantMap &removeData); protected: void init(); void openDB(const QString &name); void prepareCollectionDB() const; signals: public slots: }; #endif // DB_H diff --git a/src/models/basemodel.cpp b/src/models/basemodel.cpp index 4850899..bf35301 100644 --- a/src/models/basemodel.cpp +++ b/src/models/basemodel.cpp @@ -1,110 +1,109 @@ #include "basemodel.h" #include "baselist.h" #include "notes/notes.h" BaseModel::BaseModel(QObject *parent) : QAbstractListModel(parent), mList(nullptr) {} int BaseModel::rowCount(const QModelIndex &parent) const { if (parent.isValid() || !mList) return 0; return mList->items().size(); } QVariant BaseModel::data(const QModelIndex &index, int role) const { if (!index.isValid() || !mList) return QVariant(); - return mList->items().at(index.row())[static_cast(role)]; } bool BaseModel::setData(const QModelIndex &index, const QVariant &value, int role) { if (!mList) return false; if (mList->update(index.row(), value, role)) { emit dataChanged(index, index, QVector() << role); return true; } return false; } Qt::ItemFlags BaseModel::flags(const QModelIndex &index) const { if (!index.isValid()) return Qt::NoItemFlags; return Qt::ItemIsEditable; // FIXME: Implement me! } QHash BaseModel::roleNames() const { QHash names; for(auto key : OWL::KEYMAP.keys()) names[key] = QString(OWL::KEYMAP[key]).toUtf8(); return names; } BaseList *BaseModel::getList() const { return this->mList; } void BaseModel::setList(BaseList *value) { beginResetModel(); if(mList) mList->disconnect(this); mList = value; if(mList) { connect(this->mList, &BaseList::preItemAppended, this, [=]() { const int index = mList->items().size(); beginInsertRows(QModelIndex(), index, index); }); connect(this->mList, &BaseList::postItemAppended, this, [=]() { endInsertRows(); }); connect(this->mList, &BaseList::preItemRemoved, this, [=](int index) { beginRemoveRows(QModelIndex(), index, index); }); connect(this->mList, &BaseList::postItemRemoved, this, [=]() { endRemoveRows(); }); connect(this->mList, &BaseList::updateModel, this, [=](int index, QVector roles) { emit this->dataChanged(this->index(index), this->index(index), roles); }); connect(this->mList, &BaseList::preListChanged, this, [=]() { beginResetModel(); }); connect(this->mList, &BaseList::postListChanged, this, [=]() { endResetModel(); }); } endResetModel(); } diff --git a/src/models/links/links.cpp b/src/models/links/links.cpp index ca9df59..84d1af8 100644 --- a/src/models/links/links.cpp +++ b/src/models/links/links.cpp @@ -1,200 +1,200 @@ #include "links.h" #include #include "db/db.h" #include "linker.h" #ifdef STATIC_MAUIKIT #include "tagging.h" #else #include #endif Links::Links(QObject *parent) : BaseList(parent) { this->db = DB::getInstance(); - this->tag = Tagging::getInstance(OWL::App, OWL::version, "org.kde.buho", OWL::comment); + this->tag = Tagging::getInstance(); this->sortList(); connect(this, &Links::sortByChanged, this, &Links::sortList); connect(this, &Links::orderChanged, this, &Links::sortList); } void Links::sortList() { emit this->preListChanged(); this->links = this->db->getDBData(QString("select * from links ORDER BY %1 %2").arg( OWL::KEYMAP[this->sort], this->order == ORDER::ASC ? "asc" : "desc")); emit this->postListChanged(); } QVariantMap Links::get(const int &index) const { if(index >= this->links.size() || index < 0) return QVariantMap(); QVariantMap res; const auto note = this->links.at(index); for(auto key : note.keys()) res.insert(OWL::KEYMAP[key], note[key]); return res; } OWL::DB_LIST Links::items() const { return this->links; } bool Links::insert(const QVariantMap &link) { emit this->preItemAppended(); auto url = link[OWL::KEYMAP[OWL::KEY::LINK]].toString(); auto color = link[OWL::KEYMAP[OWL::KEY::COLOR]].toString(); auto pin = link[OWL::KEYMAP[OWL::KEY::PIN]].toInt(); auto fav = link[OWL::KEYMAP[OWL::KEY::FAV]].toInt(); auto tags = link[OWL::KEYMAP[OWL::KEY::TAG]].toStringList(); auto preview = link[OWL::KEYMAP[OWL::KEY::PREVIEW]].toString(); auto title = link[OWL::KEYMAP[OWL::KEY::TITLE]].toString(); auto image_path = OWL::saveImage(Linker::getUrl(preview), OWL::LinksPath+QUuid::createUuid().toString()); QVariantMap link_map = { {OWL::KEYMAP[OWL::KEY::LINK], url}, {OWL::KEYMAP[OWL::KEY::TITLE], title}, {OWL::KEYMAP[OWL::KEY::PIN], pin}, {OWL::KEYMAP[OWL::KEY::FAV], fav}, {OWL::KEYMAP[OWL::KEY::PREVIEW], image_path}, {OWL::KEYMAP[OWL::KEY::COLOR], color}, {OWL::KEYMAP[OWL::KEY::ADD_DATE], QDateTime::currentDateTime().toString()}, {OWL::KEYMAP[OWL::KEY::UPDATED], QDateTime::currentDateTime().toString()} }; if(this->db->insert(OWL::TABLEMAP[OWL::TABLE::LINKS], link_map)) { for(auto tg : tags) this->tag->tagAbstract(tg, OWL::TABLEMAP[OWL::TABLE::LINKS], url, color); this->links << OWL::DB ({ {OWL::KEY::LINK, url}, {OWL::KEY::TITLE, title}, {OWL::KEY::COLOR, color}, {OWL::KEY::PREVIEW, image_path}, {OWL::KEY::PIN, QString::number(pin)}, {OWL::KEY::FAV, QString::number(fav)}, {OWL::KEY::UPDATED, QDateTime::currentDateTime().toString()}, {OWL::KEY::ADD_DATE, QDateTime::currentDateTime().toString()} }); emit postItemAppended(); return true; } else qDebug()<< "LINK COULD NOT BE INSTED"; return false; } bool Links::update(const int &index, const QVariant &value, const int &role) { if(index < 0 || index >= links.size()) return false; const auto oldValue = this->links[index][static_cast(role)]; if(oldValue == value.toString()) return false; qDebug()<< "VALUE TO UPDATE"<< OWL::KEYMAP[static_cast(role)] << oldValue; this->links[index].insert(static_cast(role), value.toString()); this->update(this->links[index]); return true; } bool Links::update(const QVariantMap &data, const int &index) { if(index < 0 || index >= this->links.size()) return false; auto newData = this->links[index]; QVector roles; for(auto key : data.keys()) if(newData[OWL::MAPKEY[key]] != data[key].toString()) { newData.insert(OWL::MAPKEY[key], data[key].toString()); roles << OWL::MAPKEY[key]; } this->links[index] = newData; if(this->update(newData)) { qDebug() << "update link" << newData; emit this->updateModel(index, roles); return true; } return false; } bool Links::update(const OWL::DB &link) { auto url = link[OWL::KEY::LINK]; auto color = link[OWL::KEY::COLOR]; auto pin = link[OWL::KEY::PIN].toInt(); auto fav = link[OWL::KEY::FAV].toInt(); auto tags = link[OWL::KEY::TAG].split(",", QString::SkipEmptyParts); auto updated = link[OWL::KEY::UPDATED]; QVariantMap link_map = { {OWL::KEYMAP[OWL::KEY::COLOR], color}, {OWL::KEYMAP[OWL::KEY::PIN], pin}, {OWL::KEYMAP[OWL::KEY::FAV], fav}, {OWL::KEYMAP[OWL::KEY::UPDATED], updated} }; for(auto tg : tags) this->tag->tagAbstract(tg, OWL::TABLEMAP[OWL::TABLE::LINKS], url, color); return this->db->update(OWL::TABLEMAP[OWL::TABLE::LINKS], link_map, {{OWL::KEYMAP[OWL::KEY::LINK], url}} ); } bool Links::remove(const int &index) { emit this->preItemRemoved(index); auto linkUrl = this->links.at(index)[OWL::KEY::LINK]; QVariantMap link = {{OWL::KEYMAP[OWL::KEY::LINK], linkUrl}}; if(this->db->remove(OWL::TABLEMAP[OWL::TABLE::LINKS], link)) { this->links.removeAt(index); emit this->postItemRemoved(); return true; } return false; } QVariantList Links::getTags(const int &index) { if(index < 0 || index >= this->links.size()) return QVariantList(); auto link = this->links.at(index)[OWL::KEY::LINK]; return this->tag->getAbstractTags(OWL::TABLEMAP[OWL::TABLE::LINKS], link); } diff --git a/src/models/notes/notes.cpp b/src/models/notes/notes.cpp index 860f7f9..670a117 100644 --- a/src/models/notes/notes.cpp +++ b/src/models/notes/notes.cpp @@ -1,198 +1,196 @@ #include "notes.h" #include - #include "db/db.h" #ifdef STATIC_MAUIKIT #include "tagging.h" #else #include #endif Notes::Notes(QObject *parent) : BaseList(parent) { qDebug()<< "CREATING NOTES LIST"; this->db = DB::getInstance(); - this->tag = Tagging::getInstance(OWL::App, OWL::version, "org.kde.buho", OWL::comment); + this->tag = Tagging::getInstance(); this->sortList(); connect(this, &Notes::sortByChanged, this, &Notes::sortList); connect(this, &Notes::orderChanged, this, &Notes::sortList); - } void Notes::sortList() { emit this->preListChanged(); this->notes = this->db->getDBData(QString("select * from notes ORDER BY %1 %2").arg( OWL::KEYMAP[this->sort], this->order == ORDER::ASC ? "asc" : "desc")); emit this->postListChanged(); } OWL::DB_LIST Notes::items() const { return this->notes; } bool Notes::insert(const QVariantMap ¬e) { qDebug()<<"TAGS"<< note[OWL::KEYMAP[OWL::KEY::TAG]].toStringList(); emit this->preItemAppended(); auto title = note[OWL::KEYMAP[OWL::KEY::TITLE]].toString(); auto body = note[OWL::KEYMAP[OWL::KEY::BODY]].toString(); auto color = note[OWL::KEYMAP[OWL::KEY::COLOR]].toString(); auto pin = note[OWL::KEYMAP[OWL::KEY::PIN]].toInt(); auto fav = note[OWL::KEYMAP[OWL::KEY::FAV]].toInt(); auto tags = note[OWL::KEYMAP[OWL::KEY::TAG]].toStringList(); 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::PIN], pin}, {OWL::KEYMAP[OWL::KEY::FAV], fav}, {OWL::KEYMAP[OWL::KEY::UPDATED], QDateTime::currentDateTime().toString()}, {OWL::KEYMAP[OWL::KEY::ADD_DATE], QDateTime::currentDateTime().toString()} }; if(this->db->insert(OWL::TABLEMAP[OWL::TABLE::NOTES], note_map)) { for(auto tg : tags) this->tag->tagAbstract(tg, OWL::TABLEMAP[OWL::TABLE::NOTES], id, color); this->notes << OWL::DB ({ {OWL::KEY::ID, id}, {OWL::KEY::TITLE, title}, {OWL::KEY::BODY, body}, {OWL::KEY::COLOR, color}, {OWL::KEY::PIN, QString::number(pin)}, {OWL::KEY::FAV, QString::number(fav)}, {OWL::KEY::UPDATED, QDateTime::currentDateTime().toString()}, {OWL::KEY::ADD_DATE, QDateTime::currentDateTime().toString()} }); emit postItemAppended(); return true; } else qDebug()<< "NOTE COULD NOT BE INSTED"; return false; } bool Notes::update(const int &index, const QVariant &value, const int &role) { if(index < 0 || index >= notes.size()) return false; const auto oldValue = this->notes[index][static_cast(role)]; if(oldValue == value.toString()) return false; this->notes[index].insert(static_cast(role), value.toString()); this->update(this->notes[index]); return true; } bool Notes::update(const QVariantMap &data, const int &index) { if(index < 0 || index >= this->notes.size()) return false; auto newData = this->notes[index]; QVector roles; for(auto key : data.keys()) if(newData[OWL::MAPKEY[key]] != data[key].toString()) { newData.insert(OWL::MAPKEY[key], data[key].toString()); roles << OWL::MAPKEY[key]; } this->notes[index] = newData; if(this->update(newData)) { emit this->updateModel(index, roles); return true; } return false; } bool Notes::update(const OWL::DB ¬e) { auto id = note[OWL::KEY::ID]; auto title = note[OWL::KEY::TITLE]; auto body = note[OWL::KEY::BODY]; auto color = note[OWL::KEY::COLOR]; auto pin = note[OWL::KEY::PIN].toInt(); auto fav = note[OWL::KEY::FAV].toInt(); auto tags = note[OWL::KEY::TAG].split(",", QString::SkipEmptyParts); auto updated =note[OWL::KEY::UPDATED]; QVariantMap note_map = { {OWL::KEYMAP[OWL::KEY::TITLE], title}, {OWL::KEYMAP[OWL::KEY::BODY], body}, {OWL::KEYMAP[OWL::KEY::COLOR], color}, {OWL::KEYMAP[OWL::KEY::PIN], pin}, {OWL::KEYMAP[OWL::KEY::FAV], fav}, {OWL::KEYMAP[OWL::KEY::UPDATED], updated} }; for(auto tg : tags) this->tag->tagAbstract(tg, OWL::TABLEMAP[OWL::TABLE::NOTES], id, color); return this->db->update(OWL::TABLEMAP[OWL::TABLE::NOTES], note_map, {{OWL::KEYMAP[OWL::KEY::ID], id}} ); } bool Notes::remove(const int &index) { emit this->preItemRemoved(index); auto id = this->notes.at(index)[OWL::KEY::ID]; QVariantMap note = {{OWL::KEYMAP[OWL::KEY::ID], id}}; if(this->db->remove(OWL::TABLEMAP[OWL::TABLE::NOTES], note)) { this->notes.removeAt(index); emit this->postItemRemoved(); return true; } return false; } QVariantList Notes::getTags(const int &index) { if(index < 0 || index >= this->notes.size()) return QVariantList(); auto id = this->notes.at(index)[OWL::KEY::ID]; return this->tag->getAbstractTags(OWL::TABLEMAP[OWL::TABLE::NOTES], id); } QVariantMap Notes::get(const int &index) const { if(index >= this->notes.size() || index < 0) return QVariantMap(); QVariantMap res; const auto note = this->notes.at(index); for(auto key : note.keys()) res.insert(OWL::KEYMAP[key], note[key]); return res; } diff --git a/src/models/notes/notes.h b/src/models/notes/notes.h index b0943b7..091d1c6 100644 --- a/src/models/notes/notes.h +++ b/src/models/notes/notes.h @@ -1,39 +1,38 @@ #ifndef NOTES_H #define NOTES_H #include #include "./../baselist.h" #include "owl.h" class DB; class Tagging; - class Notes : public BaseList { Q_OBJECT public: explicit Notes(QObject *parent = nullptr); OWL::DB_LIST items() const override; private: Tagging *tag; DB *db; OWL::DB_LIST notes; void sortList(); signals: public slots: QVariantList getTags(const int &index); QVariantMap get(const int &index) const override; bool insert(const QVariantMap ¬e) override; bool update(const int &index, const QVariant &value, const int &role) override; //deprecrated bool update(const QVariantMap &data, const int &index) override; bool update(const OWL::DB ¬e) override; bool remove(const int &index) override; }; #endif // NOTES_H diff --git a/src/views/books/BooksView.qml b/src/views/books/BooksView.qml index 3afb109..21e03ee 100644 --- a/src/views/books/BooksView.qml +++ b/src/views/books/BooksView.qml @@ -1,27 +1,27 @@ import QtQuick 2.9 import "../../widgets" import org.kde.mauikit 1.0 as Maui Maui.Page { id: control property alias cardsView : cardsView - headBarVisible: false + headBar.visible: false margins: isMobile ? space.big : space.enormous CardsView { id: cardsView anchors.fill: parent // onItemClicked: linkClicked(cardsView.model.get(index)) holder.emoji: "qrc:/E-reading.png" holder.isMask: false holder.title : "No Books!" holder.body: "Click here to save a new link" holder.emojiSize: iconSizes.huge } } diff --git a/src/views/links/LinksView.qml b/src/views/links/LinksView.qml index 6c80474..9035a59 100644 --- a/src/views/links/LinksView.qml +++ b/src/views/links/LinksView.qml @@ -1,214 +1,214 @@ import QtQuick 2.9 import QtQuick.Controls 2.3 import org.kde.mauikit 1.0 as Maui import org.kde.kirigami 2.2 as Kirigami import BuhoModel 1.0 import Links 1.0 import OWL 1.0 import "../../widgets" Maui.Page { id: control property alias cardsView : cardsView property alias previewer : previewer property alias model : linksModel property alias list : linksList property alias currentIndex : cardsView.currentIndex property var currentLink : ({}) signal linkClicked(var link) - headBarVisible: !cardsView.holder.visible + headBar.visible: !cardsView.holder.visible margins: space.big headBarExit: false headBarTitle : cardsView.count + " links" headBar.leftContent: [ Maui.ToolButton { iconName: cardsView.gridView ? "view-list-icons" : "view-list-details" onClicked: cardsView.gridView = !cardsView.gridView }, Maui.ToolButton { iconName: "view-sort" onClicked: sortMenu.open(); Menu { id: sortMenu Maui.MenuItem { text: qsTr("Ascedent") checkable: true checked: linksList.order === Links.ASC onTriggered: linksList.order = Links.ASC } Maui.MenuItem { text: qsTr("Descendent") checkable: true checked: linksList.order === Links.DESC onTriggered: linksList.order = Links.DESC } MenuSeparator{} Maui.MenuItem { text: qsTr("Title") onTriggered: KEY.TITLE } Maui.MenuItem { text: qsTr("Color") onTriggered: linksList.sortBy = KEY.COLOR } Maui.MenuItem { text: qsTr("Add date") onTriggered: linksList.sortBy = KEY.ADD_DATE } Maui.MenuItem { text: qsTr("Updated") onTriggered: linksList.sortBy = KEY.UPDATED } Maui.MenuItem { text: qsTr("Fav") onTriggered: linksList.sortBy = KEY.FAV } } } ] headBar.rightContent: [ Maui.ToolButton { iconName: "tag-recents" }, Maui.ToolButton { iconName: "edit-pin" }, Maui.ToolButton { iconName: "view-calendar" } ] Previewer { id: previewer onLinkSaved: linksList.update(link, linksView.currentIndex) } Links { id: linksList } BuhoModel { id: linksModel list: linksList } CardsView { id: cardsView anchors.fill: parent holder.emoji: "qrc:/Astronaut.png" holder.isMask: false holder.title : "No Links!" holder.body: "Click here to save a new link" holder.emojiSize: iconSizes.huge itemHeight: unit * 250 model: linksModel delegate: LinkCardDelegate { id: delegate cardWidth: Math.min(cardsView.cellWidth, cardsView.itemWidth) - Kirigami.Units.largeSpacing * 2 cardHeight: cardsView.itemHeight anchors.left: parent.left anchors.leftMargin: cardsView.width <= cardsView.itemWidth ? 0 : (index % 2 === 0 ? Math.max(0, cardsView.cellWidth - cardsView.itemWidth) : cardsView.cellWidth) onClicked: { currentIndex = index currentLink = linksList.get(index) linkClicked(linksList.get(index)) } onRightClicked: { currentIndex = index currentLink = linksList.get(index) cardsView.menu.popup() } onPressAndHold: { currentIndex = index currentLink = linksList.get(index) cardsView.menu.popup() } } Connections { target: cardsView.holder onActionTriggered: newLink() } Connections { target: cardsView.menu onDeleteClicked: linksList.remove(cardsView.currentIndex) onOpened: { cardsView.menu.isFav = currentLink.fav == 1 ? true : false cardsView.menu.isPin = currentLink.pin == 1 ? true : false } onColorClicked: { linksList.update(({"color": color}), cardsView.currentIndex) } onFavClicked: { linksList.update(({"fav": fav}), cardsView.currentIndex) } onPinClicked: { linksList.update(({"pin": pin}), cardsView.currentIndex) } onCopyClicked: { Maui.Handy.copyToClipboard(currentLink.title+"\n"+currentLink.link) } } } } diff --git a/src/views/links/Previewer.qml b/src/views/links/Previewer.qml index 77d85e7..0e4cf46 100644 --- a/src/views/links/Previewer.qml +++ b/src/views/links/Previewer.qml @@ -1,166 +1,164 @@ import QtQuick 2.0 import QtQuick.Controls 2.2 import QtQuick.Layouts 1.0 import org.kde.mauikit 1.0 as Maui import "../../widgets" Maui.Dialog { parent: parent heightHint: 0.97 widthHint: 0.97 maxWidth: 800*unit maxHeight: maxWidth page.margins: 0 property color selectedColor : "transparent" property alias webView: webViewer.item signal linkSaved(var link) headBar.leftContent: [ Maui.ToolButton { id: pinButton iconName: "edit-pin" checkable: true iconColor: checked ? highlightColor : textColor // onClicked: checked = !checked }, Maui.ToolButton { iconName: "document-save" }, Maui.ToolButton { iconName: "document-launch" onClicked: Maui.FM.openUrl(webView.url) } ] headBar.rightContent: ColorsBar { id: colorBar onColorPicked: selectedColor = color } footBar.leftContent: [ Maui.ToolButton { id: favButton iconName: "love" checkable: true iconColor: checked ? "#ff007f" : textColor }, Maui.ToolButton { iconName: "document-share" onClicked: isAndroid ? Maui.Android.shareLink(webView.url) : shareDialog.show(webView.url) }, Maui.ToolButton { iconName: "document-export" }, Maui.ToolButton { iconName: "entry-delete" } ] onAccepted: { packLink() close() } onRejected: close() acceptText: qsTr("Save") rejectText: qsTr("Discard") colorScheme.backgroundColor: selectedColor ColumnLayout { anchors.fill: parent // Item // { // Layout.fillWidth: true // height: rowHeightAlt // Label // { // clip: true // text: webView.title // width: parent.width // height: parent.height // horizontalAlignment: Qt.AlignHCenter // verticalAlignment: Qt.AlignVCenter // font.bold: true // font.pointSize: fontSizes.big // font.weight: Font.Bold // elide: Label.ElideRight // } // } Loader { id: webViewer Layout.fillWidth: true Layout.fillHeight: true Layout.margins: 0 source: isAndroid ? "qrc:/src/views/links/WebViewAndroid.qml" : "qrc:/src/views/links/WebViewLinux.qml" onVisibleChanged: { if(!visible) webView.url = "about:blank" } } Maui.TagsBar { id: tagBar Layout.fillWidth: true allowEditMode: true - - onTagsEdited: - { - for(var i in tags) - append({tag : tags[i]}) - } + list.abstract: true + list.key: "links" + onTagsEdited: list.updateToAbstract(tags) + onTagRemovedClicked: list.removeFromAbstract(index) } } function show(link) { console.log("STATE:" , link.fav) webView.url = link.link - tagBar.populate(link.tags) + tagBar.list.lot = link.link pinButton.checked = link.pin == 1 favButton.checked = link.fav == 1 selectedColor = link.color open() } function packLink() { console.log(favButton.checked) linkSaved({ title: webView.title, link: webView.url, color: selectedColor, tag: tagBar.getTags(), pin: pinButton.checked ? 1 : 0, fav: favButton.checked ? 1 : 0, updated: new Date() }) } } diff --git a/src/views/notes/NotesView.qml b/src/views/notes/NotesView.qml index e8d2367..7f23e8e 100644 --- a/src/views/notes/NotesView.qml +++ b/src/views/notes/NotesView.qml @@ -1,247 +1,247 @@ 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.2 as Kirigami import BuhoModel 1.0 import Notes 1.0 import OWL 1.0 //To get the enums import "../../widgets" Maui.Page { property var currentNote : ({}) property alias cardsView : cardsView property alias model : notesModel property alias list : notesList property alias currentIndex : cardsView.currentIndex signal noteClicked(var note) margins: space.big headBarExit : false - headBarVisible: !cardsView.holder.visible + headBar.visible: !cardsView.holder.visible headBarTitle : cardsView.count + " notes" headBar.leftContent: [ Maui.ToolButton { iconName: cardsView.gridView ? "view-list-icons" : "view-list-details" onClicked: { cardsView.gridView = !cardsView.gridView } }, Maui.ToolButton { iconName: "view-sort" onClicked: sortMenu.open(); Maui.Menu { id: sortMenu parent: parent Maui.MenuItem { text: qsTr("Ascedent") checkable: true checked: notesList.order === Notes.ASC onTriggered: notesList.order = Notes.ASC } Maui.MenuItem { text: qsTr("Descendent") checkable: true checked: notesList.order === Notes.DESC onTriggered: notesList.order = Notes.DESC } MenuSeparator{} Maui.MenuItem { text: qsTr("Title") onTriggered: notesList.sortBy = KEY.TITLE } Maui.MenuItem { text: qsTr("Color") onTriggered: notesList.sortBy = KEY.COLOR } Maui.MenuItem { text: qsTr("Add date") onTriggered: notesList.sortBy = KEY.ADD_DATE } Maui.MenuItem { text: qsTr("Updated") onTriggered: notesList.sortBy = KEY.UPDATED } Maui.MenuItem { text: qsTr("Fav") onTriggered: notesList.sortBy = KEY.FAV } } } ] headBar.rightContent: [ Maui.ToolButton { iconName: "tag-recents" }, Maui.ToolButton { id: pinButton iconName: "edit-pin" checkable: true iconColor: checked ? highlightColor : textColor }, Maui.ToolButton { iconName: "view-calendar" } ] Notes { id: notesList } BuhoModel { id: notesModel list: notesList } ColumnLayout { anchors.fill: parent spacing: 0 Rectangle { visible: pinButton.checked Layout.alignment: Qt.AlignVCenter Layout.fillWidth: true height: cardsView.itemHeight CardsList { id: pinnedList height: parent.height *0.9 width: parent.width * 0.9 anchors.centerIn: parent itemHeight: cardsView.itemHeight * 0.9 itemWidth: itemHeight * 1.5 onItemClicked: noteClicked(cardsView.model.get(index)) } color: altColor radius: radiusV border.color: Qt.darker(altColor, 1.4) } CardsView { id: cardsView Layout.fillHeight: true Layout.fillWidth: true width: parent.width holder.emoji: "qrc:/Type.png" holder.emojiSize: iconSizes.huge holder.isMask: false holder.title : "No notes!" holder.body: "Click here to create a new note" model: notesModel delegate: CardDelegate { id: delegate cardWidth: Math.min(cardsView.cellWidth, cardsView.itemWidth) - Kirigami.Units.largeSpacing * 2 cardHeight: cardsView.itemHeight anchors.left: parent.left anchors.leftMargin: cardsView.width <= cardsView.itemWidth ? 0 : (index % 2 === 0 ? Math.max(0, cardsView.cellWidth - cardsView.itemWidth) : cardsView.cellWidth) onClicked: { currentIndex = index currentNote = notesList.get(index) noteClicked(currentNote) } onRightClicked: { currentIndex = index currentNote = notesList.get(index) cardsView.menu.popup() } onPressAndHold: { currentIndex = index currentNote = notesList.get(index) cardsView.menu.popup() } } Connections { target: cardsView.holder onActionTriggered: newNote() } Connections { target: cardsView.menu onOpened: { cardsView.menu.isFav = currentNote.fav == 1 cardsView.menu.isPin = currentNote.pin == 1 } onDeleteClicked: notesList.remove(cardsView.currentIndex) onColorClicked: { notesList.update(({"color": color}), cardsView.currentIndex) } onFavClicked: { notesList.update(({"fav": fav}), cardsView.currentIndex) } onPinClicked: { notesList.update(({"pin": pin}), cardsView.currentIndex) } onCopyClicked: { Maui.Handy.copyToClipboard(currentNote.title+"\n"+currentNote.body) } } } } } diff --git a/src/widgets/NewLinkDialog.qml b/src/widgets/NewLinkDialog.qml index aedf296..6f36fd9 100644 --- a/src/widgets/NewLinkDialog.qml +++ b/src/widgets/NewLinkDialog.qml @@ -1,235 +1,234 @@ 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.2 as Kirigami Maui.Dialog { parent: parent heightHint: 0.95 widthHint: 0.95 maxHeight: previewReady ? unit * 800 : contentLayout.implicitHeight maxWidth: unit *700 signal linkSaved(var link) 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: isAndroid ? 1 : undefined Connections { target: linker onPreviewReady: { previewReady = true fill(link) } } headBar.visible: previewReady footBar.visible: previewReady headBar.leftContent: Maui.ToolButton { id: pinButton iconName: "window-pin" checkable: true iconColor: checked ? highlightColor : textColor // onClicked: checked = !checked } headBar.rightContent: ColorsBar { onColorPicked: selectedColor = color } footBar.leftContent: [ Maui.ToolButton { id: favButton iconName: "love" checkable: true iconColor: checked ? "#ff007f" : textColor }, Maui.ToolButton { iconName: "document-share" onClicked: isAndroid ? Maui.Android.shareText(link.text) : shareDialog.show(link.text) }, Maui.ToolButton { iconName: "document-export" } ] acceptText: qsTr("Save") rejectText: qsTr("Discard") onAccepted: { packLink() clear() } onRejected: clear() ColumnLayout { id: contentLayout anchors.fill: parent TextField { 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) } 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 { color: "transparent" } } Item { Layout.fillWidth: true Layout.fillHeight: true visible: previewReady ListView { id: previewList anchors.fill: parent anchors.centerIn: parent visible: count > 0 clip: true snapMode: ListView.SnapOneItem orientation: ListView.Horizontal interactive: count > 1 highlightFollowsCurrentItem: true model: ListModel{} onMovementEnded: { var index = indexAt(contentX, contentY) currentIndex = index } delegate: ItemDelegate { 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]}) - } + list.abstract: true + list.key: "links" + onTagsEdited: list.updateToAbstract(tags) + onTagRemovedClicked: list.removeFromAbstract(index) } } function clear() { title.clear() link.clear() previewList.model.clear() tagBar.clear() previewReady = false close() } function fill(link) { title.text = link.title populatePreviews(link.image) + tagBar.list.lot= link.url open() } function populatePreviews(imgs) { for(var i in imgs) { console.log("PREVIEW:", imgs[i]) previewList.model.append({url : imgs[i]}) } } function packLink() { var data = ({ link : link.text, title: title.text, preview: previewList.count > 0 ? previewList.model.get(previewList.currentIndex).url : "", color: selectedColor, tag: tagBar.getTags(), pin: pinButton.checked, fav: favButton.checked }) linkSaved(data) } } diff --git a/src/widgets/NewNoteDialog.qml b/src/widgets/NewNoteDialog.qml index 2505841..0a85b23 100644 --- a/src/widgets/NewNoteDialog.qml +++ b/src/widgets/NewNoteDialog.qml @@ -1,219 +1,218 @@ import QtQuick 2.9 import QtQuick.Controls 2.2 import QtQuick.Layouts 1.0 import org.kde.mauikit 1.0 as Maui Maui.Dialog { parent: parent heightHint: 0.95 widthHint: 0.95 maxWidth: 700*unit maxHeight: maxWidth property string selectedColor : "#ffffe6" property string fgColor: Qt.darker(selectedColor, 2.5) property bool showEditActions : false rejectButton.visible: false signal noteSaved(var note) page.margins: 0 colorScheme.backgroundColor: selectedColor headBar.leftContent: [ Maui.ToolButton { iconName: "edit-undo" enabled: editor.body.canUndo onClicked: editor.body.undo() opacity: enabled ? 1 : 0.5 }, Maui.ToolButton { iconName: "edit-redo" enabled: editor.body.canRedo onClicked: editor.body.redo() opacity: enabled ? 1 : 0.5 }, Maui.ToolButton { iconName: "format-text-bold" focusPolicy: Qt.TabFocus iconColor: checked ? highlightColor : textColor checkable: true checked: editor.document.bold onClicked: editor.document.bold = !editor.document.bold }, Maui.ToolButton { iconName: "format-text-italic" iconColor: checked ? highlightColor : textColor focusPolicy: Qt.TabFocus checkable: true checked: editor.document.italic onClicked: editor.document.italic = !editor.document.italic }, Maui.ToolButton { iconName: "format-text-underline" iconColor: checked ? highlightColor : textColor focusPolicy: Qt.TabFocus checkable: true checked: editor.document.underline onClicked: editor.document.underline = !editor.document.underline }, Maui.ToolButton { iconName: "format-text-uppercase" iconColor: checked ? highlightColor : textColor focusPolicy: Qt.TabFocus checkable: true checked: editor.document.uppercase onClicked: editor.document.uppercase = !editor.document.uppercase }, Maui.ToolButton { iconName: "image" } ] headBar.rightContent: ColorsBar { onColorPicked: selectedColor = color } footBar.leftContent: [ Maui.ToolButton { id: pinButton iconName: "edit-pin" checkable: true iconColor: checked ? highlightColor : textColor // onClicked: checked = !checked }, Maui.ToolButton { id: favButton iconName: "love" checkable: true iconColor: checked ? "#ff007f" : textColor }, Maui.ToolButton { iconName: "document-share" onClicked: isAndroid ? Maui.Android.shareText(editor.body.text) : shareDialog.show(editor.body.text) }, Maui.ToolButton { iconName: "document-export" }, Maui.ToolButton { iconName: "entry-delete" } ] acceptText: qsTr("Save") rejectText: qsTr("Discard") onAccepted: { if(editor.body.text.length > 0) packNote() clear() } onRejected: clear() ColumnLayout { anchors.fill: parent 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.Editor { id: editor Layout.fillHeight: true Layout.fillWidth: true colorScheme.backgroundColor: selectedColor headBar.visible: false } Maui.TagsBar { id: tagBar Layout.fillWidth: true allowEditMode: true - - onTagsEdited: - { - for(var i in tags) - append({tag : tags[i]}) - } + list.abstract: true + list.key: "notes" + onTagsEdited: list.updateToAbstract(tags) + onTagRemovedClicked: list.removeFromAbstract(index) } } onOpened: if(isMobile) editor.body.forceActiveFocus() function clear() { title.clear() editor.body.clear() close() } function fill(note) { title.text = note.title editor.body.text = note.body selectedColor = note.color pinButton.checked = note.pin == 1 favButton.checked = note.fav == 1 - tagBar.populate(note.tags) + + tagBar.list.lot= note.id open() } function packNote() { noteSaved({ id: notesView.currentNote.id, title: title.text.trim(), body: editor.body.text, color: selectedColor, tag: tagBar.getTags(), pin: pinButton.checked ? 1 : 0, fav: favButton.checked ? 1 : 0, updated: new Date() }) } } diff --git a/travis-build.sh b/travis-build.sh new file mode 100755 index 0000000..df9eddc --- /dev/null +++ b/travis-build.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +apt-get --yes update +apt-get --yes install wget + +### Add KDENeon Repository +echo 'deb http://archive.neon.kde.org/dev/stable/ bionic main' | tee /etc/apt/sources.list.d/neon-stable.list +wget -qO - 'http://archive.neon.kde.org/public.key' | apt-key add - + +### Install Dependencies +apt-get --yes update +apt-get --yes dist-upgrade +apt-get --yes install devscripts lintian build-essential automake autotools-dev equivs qt5-default qtdeclarative5-dev qtquickcontrols2-5-dev qtwebengine5-dev +mk-build-deps -i -t "apt-get --yes" -r + +### Build Deb +mkdir source +mv ./* source/ # Hack for debuild +cd source +debuild -b -uc -us