Add color for events and source tags

This commit is contained in:
Vyn 2025-06-26 10:12:23 +02:00
parent d208fc6ca4
commit 4bca7fac3e
Signed by: vyn
GPG key ID: E1B2BE34E7A971E7
12 changed files with 95 additions and 39 deletions

View file

@ -24,7 +24,8 @@ class Mirai
void addSource(
const std::string &name, const std::string &type, std::unique_ptr<DataProvider> &&source
);
void editSource(int id, const std::string &name, const std::string &path);
void
editSource(int id, const std::string &name, const std::string &color, const std::string &path);
void deleteSource(int id);
void unloadAllSources();
void save();

View file

@ -32,6 +32,7 @@ struct createEventParams {
struct SourceConstructor {
std::string name;
std::string color;
DataProvider *sourceDataProvider;
};
@ -39,7 +40,8 @@ class Source
{
public:
Source(SourceConstructor params)
: data(params.sourceDataProvider), name_(params.name), type_("FileSystemMarkdown")
: data(params.sourceDataProvider), name_(params.name), color_(params.color),
type_("FileSystemMarkdown")
{
}
@ -56,9 +58,11 @@ class Source
std::string name() const;
std::string type() const;
std::string color() const;
DataProvider *dataProvider();
void setName(const std::string &name);
void setColor(const std::string &color);
void createTask(const createTaskParams &task);
void removeTask(const Task &task);
@ -92,6 +96,7 @@ class Source
std::string name_;
std::string type_;
std::string color_;
DataProvider *data;
};
} // namespace mirai

View file

@ -41,14 +41,15 @@ void Mirai::loadConfig(const std::string &path)
auto &filePath = jsonSources[i];
assert(filePath.isObject());
const auto name = filePath.asObject().getString("name");
const auto color = filePath.asObject().getString("color");
const auto path = filePath.asObject().getString("path");
std::unique_ptr<DataProvider> file = std::make_unique<MarkdownDataProvider>(path);
DataProvider *sourceDataProvider = file.release();
sourceDataProvider->load();
sources_.push_back(
std::make_unique<Source>(
SourceConstructor{.name = name, .sourceDataProvider = sourceDataProvider}
)
std::make_unique<Source>(SourceConstructor{
.name = name, .color = color, .sourceDataProvider = sourceDataProvider
})
);
}
}
@ -67,6 +68,7 @@ void Mirai::saveConfig()
rei::json::JsonObject jsonSource;
jsonSource.set("name", source->name());
jsonSource.set("color", source->color());
auto dataProvider = dynamic_cast<MarkdownDataProvider *>(source->dataProvider());
jsonSource.set("path", dataProvider->path());
jsonSource.set("type", "FileSystemMarkdown");
@ -96,10 +98,13 @@ void Mirai::addSource(
sourceAdded.emit(nullptr);
};
void Mirai::editSource(int id, const std::string &name, const std::string &path)
void Mirai::editSource(
int id, const std::string &name, const std::string &color, const std::string &path
)
{
auto source = getSourceById(id);
source->setName(name);
source->setColor(color);
DataProvider *sourceDataProvider = source->dataProvider();
saveConfig();

View file

@ -52,8 +52,7 @@ std::vector<Day> Source::getDays()
auto daysData = data->getDays();
std::vector<Day> days;
std::transform(
daysData.begin(), daysData.end(), std::back_inserter(days),
[&](const DayData &dayData) {
daysData.begin(), daysData.end(), std::back_inserter(days), [&](const DayData &dayData) {
return Day{data, dayData};
}
);
@ -148,11 +147,21 @@ std::string Source::name() const
return name_;
}
std::string Source::color() const
{
return color_;
}
void Source::setName(const std::string &name)
{
name_ = name;
}
void Source::setColor(const std::string &color)
{
color_ = color;
}
std::string Source::type() const
{
// There is only 1 type for now

2
external/selenite vendored

@ -1 +1 @@
Subproject commit 9592f1b18d149e1cf76a32df419f6ed3db2af3d6
Subproject commit 0fa6be0b1abe9534a8a1252496b7c97219c1559e

View file

@ -1,25 +1,7 @@
import { ScrollView, Date, Time } from "std-widgets.slint";
import { VCheckBox, VButton, VActionButton, Svg, VTag, VPopupIconMenu, VText, Palette } from "@selenite";
import { Utils } from "../shared/Utils.slint";
export struct CalendarDayEvent {
sourceId: int,
id: int,
title: string,
startsAt: Time,
endsAt: Time
}
export struct CalendarDay {
events: [CalendarDayEvent],
date: Date,
header: string,
}
export enum CalendarDateDisplayFormat {
Relative,
Normal
}
import { AppModels, CalendarDay, CalendarDateDisplayFormat } from "../shared/Models.slint";
export component Calendar inherits Rectangle {
in property<[CalendarDay]> days;
@ -65,7 +47,7 @@ export component Calendar inherits Rectangle {
}
Rectangle {
Rectangle {
Rectangle { // Last bar delimiting days
x: parent.width - 1px;
y: header-height - 32px;
width: 1px;
@ -76,7 +58,7 @@ export component Calendar inherits Rectangle {
//background: green;
HorizontalLayout {
for day[day-index] in root.days: Rectangle {
Rectangle {
Rectangle { // Bar delimiting days
x: 0;
y: header-height - 32px;
width: 1px;
@ -103,11 +85,18 @@ export component Calendar inherits Rectangle {
if day.date == root.current-date : Rectangle {
background: Palette.red;
x: 0px;
width: parent.width;
y: day-start-y + hour-spacing * root.current-time.hour + (root.current-time.minute / 60 * hour-spacing);
width: parent.width;
height: 1px;
z: 100;
}
for event[event-index] in day.events : Rectangle {
Rectangle {
width: 100%;
height: 100%;
background: AppModels.get-source-color-from-id-as-color(event.sourceId);
opacity: 0.05;
}
background: Palette.card-background;
border-radius: 4px;
x: 8px;
@ -118,7 +107,7 @@ export component Calendar inherits Rectangle {
HorizontalLayout {
Rectangle {
width: 4px;
background: Palette.accent;
background: AppModels.get-source-color-from-id-as-color(event.sourceId);
}
VerticalLayout {
padding: 16px;

View file

@ -2,6 +2,7 @@ import { ToggleButton } from "@selenite";
import { VPopupIconMenu, VTag, VText, VButton, VActionButton, VCheckBox, Svg, Palette } from "@selenite";
import { TaskEdit } from "./TaskEdit.slint";
import { Date } from "std-widgets.slint";
import { AppModels } from "../shared/Models.slint";
export struct TaskLineEditData {
title: string,
@ -13,6 +14,7 @@ export struct TaskLineEditData {
export component TaskLine inherits VerticalLayout {
in property<string> title;
in property<string> source-name;
in property<color> source-color;
in property<bool> hide-source-name;
in property<bool> scheduled;
in property<Date> date;
@ -91,7 +93,7 @@ export component TaskLine inherits VerticalLayout {
}
}
if !hide-source-name : source-name := VTag {
text-color: Palette.accent;
text-color: root.source-color;
text: "\{root.source-name}";
}
}

View file

@ -8,11 +8,13 @@ import { Modal } from "../../external/selenite/components/Modal.slint";
export component EditSourceModal inherits Modal {
private property <int> source-id-to-edit: -1;
private property <string> name: "";
private property <string> color_: ""; // Well, cannot override 'color'
private property <string> path: "";
public function edit(source-id: int) {
source-id-to-edit = source-id;
root.name = AppModels.get-source-name-from-id(source-id);
root.color_ = AppModels.get-source-color-from-id-as-hex(source-id);
root.path = AppModels.get-source-path-from-id(source-id);
root.show();
}
@ -24,6 +26,10 @@ export component EditSourceModal inherits Modal {
label: "Name";
text <=> root.name;
}
colorInput := VTextInput {
label: "Color";
text <=> root.color_;
}
pathInput := VTextInput {
label: "Path";
text <=> root.path;
@ -31,7 +37,7 @@ export component EditSourceModal inherits Modal {
VButton {
text: "Save";
clicked => {
AppActions.edit-source(source-id-to-edit, name, path);
AppActions.edit-source(source-id-to-edit, name, color_, path);
root.close();
}
}

View file

@ -1,5 +1,5 @@
import { Date, Time } from "std-widgets.slint";
import { CalendarDay } from "../components/Calendar.slint";
import { CalendarDay } from "./Models.slint";
export struct NewTaskData {
sourceId: int,
@ -33,7 +33,7 @@ export global AppActions {
callback task-clicked(int, int);
callback source-clicked(int);
callback add-source(name: string, path: string);
callback edit-source(sourceId: int, name: string, path: string);
callback edit-source(sourceId: int, name: string, color: string, path: string);
callback toggle-show-completed-tasks();
callback delete-task-clicked(int, int);

View file

@ -1,5 +1,4 @@
import { Date, Time } from "std-widgets.slint";
import { CalendarDay } from "../components/Calendar.slint";
export struct Source {
id: int,
@ -37,6 +36,25 @@ export struct Day {
relativeDaysDiff: int
}
export struct CalendarDayEvent {
sourceId: int,
id: int,
title: string,
startsAt: Time,
endsAt: Time
}
export struct CalendarDay {
events: [CalendarDayEvent],
date: Date,
header: string,
}
export enum CalendarDateDisplayFormat {
Relative,
Normal
}
export global AppModels {
in-out property<[Source]> sources-selected;
in-out property<int> default-source-index;
@ -48,5 +66,7 @@ export global AppModels {
callback get-source-id-from-name(string) -> int;
pure callback get-source-name-from-id(int) -> string;
pure callback get-source-color-from-id-as-color(int) -> color;
pure callback get-source-color-from-id-as-hex(int) -> string;
pure callback get-source-path-from-id(int) -> string;
}

View file

@ -12,6 +12,7 @@
#include "mirai-core/MarkdownDataProvider.h"
#include "mirai-core/Mirai.h"
#include "selenite/palette.h"
#include "slint_color.h"
#include "slint_string.h"
#include "ui.h"
#include <bits/chrono.h>
@ -97,6 +98,19 @@ void AppWindow::setupCallbacks()
return slint::SharedString(source->name());
});
models().on_get_source_color_from_id_as_hex([&](int sourceId) {
auto source = miraiInstance_->getSourceById(sourceId);
assert(source);
return slint::SharedString(source->color());
});
models().on_get_source_color_from_id_as_color([&](int sourceId) {
auto source = miraiInstance_->getSourceById(sourceId);
assert(source);
auto color = selenite::hexStringToColor(source->color());
return slint::Color::from_rgb_uint8(color.r, color.g, color.b);
});
models().on_get_source_path_from_id([&](int sourceId) {
auto source = miraiInstance_->getSourceById(sourceId);
assert(source);
@ -150,8 +164,11 @@ void AppWindow::setupCallbacks()
miraiInstance_->addSource(std::string(name), "FileSystemMarkdown", std::move(file));
});
actions().on_edit_source([&](int sourceId, slint::SharedString name, slint::SharedString path) {
miraiInstance_->editSource(sourceId, std::string(name), std::string(path));
actions().on_edit_source([&](int sourceId, slint::SharedString name, slint::SharedString color,
slint::SharedString path) {
miraiInstance_->editSource(
sourceId, std::string(name), std::string(color), std::string(path)
);
});
actions().on_delete_task_clicked([&](int sourceId, int taskId) {

View file

@ -93,6 +93,7 @@ export component MainView inherits Rectangle {
TaskLine {
title: task.title;
source-name: AppModels.get-source-name-from-id(task.sourceId);
source-color: AppModels.get-source-color-from-id-as-color(task.sourceId);
scheduled: task.date.year != 0;
date: day.date;
checked: task.checked;
@ -136,6 +137,7 @@ export component MainView inherits Rectangle {
TaskLine {
title: task.title;
source-name: AppModels.get-source-name-from-id(task.sourceId);
source-color: AppModels.get-source-color-from-id-as-color(task.sourceId);
checked: task.checked;
allow-edit-date: true;
delete => {