From e5328c15d425b97b9c2cbd99a30e7444866dbbc5 Mon Sep 17 00:00:00 2001 From: Vyn Date: Mon, 22 Apr 2024 14:34:24 +0200 Subject: [PATCH] Add tags settings in UI --- CMakeLists.txt | 3 ++ src/Backend.cpp | 47 ++++++++++++++++++- src/Backend.h | 8 +++- src/Tag.cpp | 17 +++++++ src/Tag.h | 29 ++++++++++++ src/images/settings.png | Bin 0 -> 3784 bytes src/qml/AppIcon.qml | 9 +++- src/qml/SideMenu.qml | 62 ++++++++++++++++++------- src/qml/components/Tag.qml | 3 +- src/qml/forms/TagsConfigForm.qml | 77 +++++++++++++++++++++++++++++++ 10 files changed, 233 insertions(+), 22 deletions(-) create mode 100644 src/Tag.cpp create mode 100644 src/Tag.h create mode 100644 src/images/settings.png create mode 100644 src/qml/forms/TagsConfigForm.qml diff --git a/CMakeLists.txt b/CMakeLists.txt index 4ba2f8d..15aca42 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,6 +51,7 @@ qt_add_qml_module(mirai src/qml/TaskItem.qml src/qml/forms/TaskForm.qml src/qml/forms/FilesForm.qml + src/qml/forms/TagsConfigForm.qml src/qml/components/TabSelector.qml src/qml/components/Tag.qml src/qml/components/Calendar.qml @@ -61,10 +62,12 @@ qt_add_qml_module(mirai SOURCES src/Backend.h src/Backend.cpp src/TaskItem.h src/TaskItem.cpp + src/Tag.h src/Tag.cpp src/TasksFile.h src/TasksFile.cpp RESOURCES src/images/calendar.png src/images/add.png + src/images/settings.png ) target_link_libraries(mirai PRIVATE Qt6::Quick) diff --git a/src/Backend.cpp b/src/Backend.cpp index 26bdde1..9a9625b 100644 --- a/src/Backend.cpp +++ b/src/Backend.cpp @@ -197,7 +197,10 @@ void Backend::rebuildQMLTasksList() QMLTags.clear(); for (auto &tag : mirai.getTags()) { - QMLTags.push_back(QString::fromStdString(tag)); + QMLTags.push_back({ + .name = QString::fromStdString(tag), + .color = getTagColor(QString::fromStdString(tag)), + }); } QMLActiveTagsFilter.clear(); @@ -248,3 +251,45 @@ QString Backend::getTagColor(QString tag) } return tagsConfig[tag]; } + +void Backend::saveTagsColor(QVariant modifiedTags) +{ + auto aa = modifiedTags.toList(); + for (auto bb : aa) { + auto cc = bb.toMap(); + std::cout << cc["name"].toString().toStdString() << ": " + << cc["color"].toString().toStdString() << std::endl; + tagsConfig[cc["name"].toString()] = cc["color"].toString(); + } + rebuildQMLTasksList(); + emit tagsChanged(); + emit tasksChanged(); + saveConfig(); +} + +void Backend::saveConfig() +{ + QJsonObject rootJson; + + QJsonArray filesJson; + for (auto &file : mirai.getFiles()) { + filesJson.append(QString::fromStdString(file->getPath())); + } + rootJson["files"] = filesJson; + + QJsonObject tagsJson; + for (auto &tag : tagsConfig.keys()) { + QJsonObject tagConfig; + tagConfig["color"] = getTagColor(tag); + tagsJson[tag] = tagConfig; + } + rootJson["tags"] = tagsJson; + + QFile configFile(QDir::homePath() + "/.config/mirai/config.json"); + if (!configFile.open(QIODevice::WriteOnly)) { + qWarning() << "Cannot save config"; + return; + } + configFile.write(QJsonDocument(rootJson).toJson()); + configFile.close(); +} diff --git a/src/Backend.h b/src/Backend.h index 02906bd..28a3596 100644 --- a/src/Backend.h +++ b/src/Backend.h @@ -10,6 +10,7 @@ #include "QtCore/qcontainerfwd.h" #include "QtCore/qtmetamacros.h" #include "QtCore/qvariant.h" +#include "Tag.h" #include "TasksFile.h" #include "core/Mirai.h" #include "core/TasksView.h" @@ -33,7 +34,7 @@ class Backend : public QObject QML_ELEMENT Q_PROPERTY(QVariant tasks READ getTasks NOTIFY tasksChanged) Q_PROPERTY(QVariant files READ getFiles NOTIFY filesChanged) - Q_PROPERTY(QVariant tags READ getTags NOTIFY tasksChanged) + Q_PROPERTY(QVariant tags READ getTags NOTIFY tagsChanged) Q_PROPERTY(QVariant activeTagsFilter READ getActiveTagsFilter NOTIFY tasksChanged) Q_PROPERTY(QVariant activeFilesFilter READ getActiveFilesFilter NOTIFY tasksChanged) Q_PROPERTY(bool shouldHideCompletedTasks READ shouldHideCompletedTasks WRITE hideCompletedTasks @@ -54,6 +55,7 @@ class Backend : public QObject Q_INVOKABLE void removeTodo(int todoIndex); Q_INVOKABLE void hideCompletedTasks(bool shouldHide); Q_INVOKABLE QString getTagColor(QString tag); + Q_INVOKABLE void saveTagsColor(QVariant tags); private: void rebuildQMLTasksList(); @@ -64,13 +66,14 @@ class Backend : public QObject QVariant getActiveTagsFilter(); QVariant getActiveFilesFilter(); bool shouldHideCompletedTasks(); + void saveConfig(); mirai::Mirai mirai; mirai::TasksView view; QList QMLTasks; QList QMLTasksFiles; - QList QMLTags; + QList QMLTags; QList QMLActiveTagsFilter; QList QMLActiveFilesFilter; QMap tagsConfig; @@ -80,6 +83,7 @@ class Backend : public QObject signals: void tasksChanged(); + void tagsChanged(); void filesChanged(); }; diff --git a/src/Tag.cpp b/src/Tag.cpp new file mode 100644 index 0000000..17ea211 --- /dev/null +++ b/src/Tag.cpp @@ -0,0 +1,17 @@ +/* + * Mirai. Copyright (C) 2024 Vyn + * This file is licensed under version 3 of the GNU General Public License (GPL-3.0-only) + * The license can be found in the LICENSE file or at https://www.gnu.org/licenses/gpl-3.0.txt + */ + +#include "Tag.h" + +QString QMLTag::getName() +{ + return name; +} + +QString QMLTag::getColor() +{ + return color; +} diff --git a/src/Tag.h b/src/Tag.h new file mode 100644 index 0000000..7945c2a --- /dev/null +++ b/src/Tag.h @@ -0,0 +1,29 @@ +/* + * Mirai. Copyright (C) 2024 Vyn + * This file is licensed under version 3 of the GNU General Public License (GPL-3.0-only) + * The license can be found in the LICENSE file or at https://www.gnu.org/licenses/gpl-3.0.txt + */ + +#ifndef QML_TAG_H +#define QML_TAG_H + +#include +#include +#include + +struct QMLTag { + + Q_GADGET + Q_PROPERTY(QString name READ getName) + Q_PROPERTY(QString color READ getColor) + QML_VALUE_TYPE(tag) + + public: + QString getName(); + QString getColor(); + + QString name; + QString color; +}; + +#endif diff --git a/src/images/settings.png b/src/images/settings.png new file mode 100644 index 0000000000000000000000000000000000000000..ead59069cb6ce6866926add98da4e10b535bb402 GIT binary patch literal 3784 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 { + tagsFormPopup.close() + backend.saveTagsColor(tags) + } + } + } } diff --git a/src/qml/components/Tag.qml b/src/qml/components/Tag.qml index 6e75877..85ed919 100644 --- a/src/qml/components/Tag.qml +++ b/src/qml/components/Tag.qml @@ -20,11 +20,10 @@ Rectangle { QtObject { id: internal - property string configTagColor: backend.getTagColor(control.text) } AppText { - color: internal.configTagColor != "" ? internal.configTagColor : control.textColor + color: backend.getTagColor(control.text) padding: 2 leftPadding: 6 rightPadding: 6 diff --git a/src/qml/forms/TagsConfigForm.qml b/src/qml/forms/TagsConfigForm.qml new file mode 100644 index 0000000..f4323dc --- /dev/null +++ b/src/qml/forms/TagsConfigForm.qml @@ -0,0 +1,77 @@ +/* + * Mirai. Copyright (C) 2024 Vyn + * This file is licensed under version 3 of the GNU General Public License (GPL-3.0-only) + * The license can be found in the LICENSE file or at https://www.gnu.org/licenses/gpl-3.0.txt + */ + +import QtQuick +import QtQuick.Window +import QtQuick.Controls +import QtQuick.Layouts +import QtQuick.Dialogs +import Mirai + +ColumnLayout { + id: form + spacing: 6 + signal confirmed(tags: var) + + function reset() { + internal.tags = Qt.binding(function () { return [] }) + internal.tags = Qt.binding(function () { return backend.tags.map(tag => { + return {name: tag.name, color: tag.color} + })}) + } + + QtObject { + id: internal + property var tags: [] + } + + Repeater { + id: tagsList + model: internal.tags + RowLayout { + Rectangle { + id: newTagColor + color: colorDialog.selectedColor + Layout.fillHeight: true + Layout.preferredWidth: 32 + + MouseArea { + anchors.fill: parent + onClicked: { + colorDialog.open() + } + HoverHandler { + id: mouse + acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad + cursorShape: Qt.PointingHandCursor + } + } + } + + ColorDialog { + id: colorDialog + selectedColor: modelData.color + onAccepted: { + colorDialog.selectedColor = selectedColor + internal.tags[index].color = selectedColor + } + } + + AppText { + text: modelData.name + color: colorDialog.selectedColor + } + } + } + + AppButton { + text: "Save" + onClicked: { + form.confirmed(internal.tags) + } + } +} +