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/notes/notes.cpp b/src/models/notes/notes.cpp index 860f7f9..6773a99 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->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/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) } } } } }