mirror of
https://codeberg.org/vyn/mirai.git
synced 2025-07-02 01:13:19 +00:00
Move Calendar to its own view
This commit is contained in:
parent
a03e71890c
commit
d26f2f5a9f
19 changed files with 407 additions and 137 deletions
2
.gitmodules
vendored
2
.gitmodules
vendored
|
@ -6,7 +6,7 @@
|
||||||
url = https://github.com/slint-ui/slint
|
url = https://github.com/slint-ui/slint
|
||||||
[submodule "external/selenite"]
|
[submodule "external/selenite"]
|
||||||
path = external/selenite
|
path = external/selenite
|
||||||
url = https://codeberg.org/vyn/selenite.git
|
url = https://code.evalyte.net/desktop/selenite.git
|
||||||
[submodule "external/evalyte-cpp-common"]
|
[submodule "external/evalyte-cpp-common"]
|
||||||
path = external/evalyte-cpp-common
|
path = external/evalyte-cpp-common
|
||||||
url = https://codeberg.org/vyn/evalyte-cpp-common.git
|
url = https://codeberg.org/vyn/evalyte-cpp-common.git
|
||||||
|
|
|
@ -34,6 +34,7 @@ add_executable(mirai
|
||||||
src/windows/AddSourceWindow/AddSourceWindow.cpp
|
src/windows/AddSourceWindow/AddSourceWindow.cpp
|
||||||
src/windows/SettingsWindow/SettingsWindow.cpp
|
src/windows/SettingsWindow/SettingsWindow.cpp
|
||||||
src/windows/EditSourceWindow/EditSourceWindow.cpp
|
src/windows/EditSourceWindow/EditSourceWindow.cpp
|
||||||
|
src/windows/EditEventWindow/EditEventWindow.cpp
|
||||||
src/SeleniteSetup.cpp
|
src/SeleniteSetup.cpp
|
||||||
src/shared/Utils.cpp
|
src/shared/Utils.cpp
|
||||||
)
|
)
|
||||||
|
|
2
external/selenite
vendored
2
external/selenite
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit 9cba85a21aa6c2eee6101dd38252249283816327
|
Subproject commit c653e851118c893678762d1aeeac3b995a60b9d4
|
2
external/slint
vendored
2
external/slint
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit ca66a6af4a4e9c4c78ff889ba447bcb460d07c91
|
Subproject commit 37fb91fafced9e117597a9a1825a641a8c3ea541
|
|
@ -3,6 +3,8 @@ import { VCheckBox, VButton, VActionButton, Svg, VTag, VPopupIconMenu, VText, Pa
|
||||||
import { Utils } from "../shared/Utils.slint";
|
import { Utils } from "../shared/Utils.slint";
|
||||||
|
|
||||||
export struct CalendarDayEvent {
|
export struct CalendarDayEvent {
|
||||||
|
sourceId: int,
|
||||||
|
id: int,
|
||||||
title: string,
|
title: string,
|
||||||
startsAt: Time,
|
startsAt: Time,
|
||||||
endsAt: Time
|
endsAt: Time
|
||||||
|
@ -28,7 +30,12 @@ export component Calendar inherits Rectangle {
|
||||||
private property <length> available-day-space: self.height - header-height;
|
private property <length> available-day-space: self.height - header-height;
|
||||||
private property <length> day-start-y: header-height;
|
private property <length> day-start-y: header-height;
|
||||||
private property <length> hour-spacing: available-day-space / 24;
|
private property <length> hour-spacing: available-day-space / 24;
|
||||||
background: Palette.pane;
|
|
||||||
|
private property <int> contextMenuEventSourceId: -1;
|
||||||
|
|
||||||
|
callback delete-event-request(source-id: int, event-id: int);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
HorizontalLayout {
|
HorizontalLayout {
|
||||||
Rectangle {
|
Rectangle {
|
||||||
|
@ -58,6 +65,7 @@ export component Calendar inherits Rectangle {
|
||||||
|
|
||||||
}
|
}
|
||||||
Rectangle {
|
Rectangle {
|
||||||
|
min-width: 400px;
|
||||||
//background: green;
|
//background: green;
|
||||||
HorizontalLayout {
|
HorizontalLayout {
|
||||||
for day[day-index] in root.days: Rectangle {
|
for day[day-index] in root.days: Rectangle {
|
||||||
|
@ -113,6 +121,40 @@ export component Calendar inherits Rectangle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
eventActionsPopup := VPopupIconMenu {
|
||||||
|
//VActionButton {
|
||||||
|
//icon-svg: Svg.pen;
|
||||||
|
//icon-colorize: Colors.grey;
|
||||||
|
//icon-size: 1.5rem;
|
||||||
|
//border-radius: 0;
|
||||||
|
//clicked => {
|
||||||
|
//taskEdit.show({
|
||||||
|
//title: title,
|
||||||
|
//date: date
|
||||||
|
//});
|
||||||
|
//}
|
||||||
|
//}
|
||||||
|
|
||||||
|
VActionButton {
|
||||||
|
icon-svg: Svg.trash;
|
||||||
|
icon-colorize: Colors.pink;
|
||||||
|
icon-size: 1.5rem;
|
||||||
|
border-radius: 0;
|
||||||
|
clicked => {
|
||||||
|
delete-event-request(event.sourceId, event.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ta := TouchArea {
|
||||||
|
pointer-event(e) => {
|
||||||
|
if (e.button == PointerEventButton.right && e.kind == PointerEventKind.up) {
|
||||||
|
debug(ta.mouse-x, " ", ta.mouse-y);
|
||||||
|
eventActionsPopup.show(ta.mouse-x, ta.mouse-y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,38 +8,18 @@ export struct CreateTaskData {
|
||||||
date: Date
|
date: Date
|
||||||
}
|
}
|
||||||
|
|
||||||
export struct CreateEventData {
|
|
||||||
sourceId: int,
|
|
||||||
title: string,
|
|
||||||
date: Date,
|
|
||||||
startsAt: Time,
|
|
||||||
endsAt: Time
|
|
||||||
}
|
|
||||||
|
|
||||||
export component CreateTaskOrEvent inherits Rectangle {
|
export component CreateTaskOrEvent inherits Rectangle {
|
||||||
|
|
||||||
in property <[string]> sources;
|
in property <[string]> sources;
|
||||||
private property <int> task-or-event: 1;
|
|
||||||
|
|
||||||
callback create-task(CreateTaskData);
|
callback create-task(CreateTaskData);
|
||||||
callback create-event(CreateEventData);
|
|
||||||
|
|
||||||
function accepted() {
|
function accepted() {
|
||||||
if (task-or-event == 1) {
|
root.create-task({
|
||||||
root.create-task({
|
sourceId: AppWindowModels.get-source-id-from-name(sourceInput.current-value),
|
||||||
sourceId: AppWindowModels.get-source-id-from-name(sourceInput.current-value),
|
title: newTaskTitleInput.text,
|
||||||
title: newTaskTitleInput.text,
|
date: taskDateInput.date
|
||||||
date: taskDateInput.date
|
});
|
||||||
})
|
|
||||||
} else {
|
|
||||||
root.create-event({
|
|
||||||
sourceId: AppWindowModels.get-source-id-from-name(sourceInput.current-value),
|
|
||||||
title: newTaskTitleInput.text,
|
|
||||||
date: taskDateInput.date,
|
|
||||||
startsAt: eventStartTimeInput.time,
|
|
||||||
endsAt: eventEndTimeInput.time
|
|
||||||
})
|
|
||||||
}
|
|
||||||
newTaskTitleInput.edit-text("");
|
newTaskTitleInput.edit-text("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,13 +55,6 @@ export component CreateTaskOrEvent inherits Rectangle {
|
||||||
HorizontalLayout {
|
HorizontalLayout {
|
||||||
alignment: start;
|
alignment: start;
|
||||||
spacing: 8px;
|
spacing: 8px;
|
||||||
VerticalLayout {
|
|
||||||
alignment: end;
|
|
||||||
VButton {
|
|
||||||
text: task-or-event == 1 ? "Task" : "Event";
|
|
||||||
clicked => { task-or-event = task-or-event == 1 ? 0 : 1 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
VText { text: "for"; vertical-alignment: bottom;}
|
VText { text: "for"; vertical-alignment: bottom;}
|
||||||
VerticalLayout {
|
VerticalLayout {
|
||||||
alignment: end;
|
alignment: end;
|
||||||
|
@ -94,22 +67,6 @@ export component CreateTaskOrEvent inherits Rectangle {
|
||||||
taskDateInput := VDatePicker {
|
taskDateInput := VDatePicker {
|
||||||
enabled: true;
|
enabled: true;
|
||||||
}
|
}
|
||||||
Rectangle {
|
|
||||||
min-width: 0;
|
|
||||||
max-width: task-or-event == 0 ? 9999px : 0px;
|
|
||||||
opacity: task-or-event == 0 ? 1 : 0;
|
|
||||||
clip: true;
|
|
||||||
animate max-width, opacity {
|
|
||||||
duration: 250ms;
|
|
||||||
}
|
|
||||||
HorizontalLayout {
|
|
||||||
spacing: 4px;
|
|
||||||
VText { text: "between"; vertical-alignment: bottom; }
|
|
||||||
eventStartTimeInput := VTimePicker { }
|
|
||||||
VText { text: "and"; vertical-alignment: bottom; }
|
|
||||||
eventEndTimeInput := VTimePicker { }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
VButton {
|
VButton {
|
||||||
text: "Create";
|
text: "Create";
|
||||||
icon-svg: Svg.correct;
|
icon-svg: Svg.correct;
|
||||||
|
|
|
@ -4,7 +4,8 @@ import { AppWindow } from "windows/AppWindow/AppWindow.slint";
|
||||||
import { SettingsWindow } from "windows/SettingsWindow/SettingsWindow.slint";
|
import { SettingsWindow } from "windows/SettingsWindow/SettingsWindow.slint";
|
||||||
import { AddSourceWindow } from "windows/AddSourceWindow//AddSourceWindow.slint";
|
import { AddSourceWindow } from "windows/AddSourceWindow//AddSourceWindow.slint";
|
||||||
import { EditSourceWindow } from "windows/EditSourceWindow/EditSourceWindow.slint";
|
import { EditSourceWindow } from "windows/EditSourceWindow/EditSourceWindow.slint";
|
||||||
|
import { EditEventWindow } from "windows/EditEventWindow/EditEventWindow.slint";
|
||||||
import { Utils } from "shared/Utils.slint";
|
import { Utils } from "shared/Utils.slint";
|
||||||
import { Palette } from "@selenite";
|
import { Palette } from "@selenite";
|
||||||
|
|
||||||
export { Utils, Palette, AppWindow, AppWindowModels, AppWindowActions, SettingsWindow, AddSourceWindow, EditSourceWindow }
|
export { Utils, Palette, AppWindow, AppWindowModels, AppWindowActions, SettingsWindow, AddSourceWindow, EditSourceWindow, EditEventWindow }
|
||||||
|
|
|
@ -13,7 +13,6 @@ export component AddSourceWindow inherits Window {
|
||||||
min-height: 100px;
|
min-height: 100px;
|
||||||
max-height: 4000px; // needed, otherwise the window wants to fit the content (on Swaywm)
|
max-height: 4000px; // needed, otherwise the window wants to fit the content (on Swaywm)
|
||||||
min-width: 400px;
|
min-width: 400px;
|
||||||
default-font-size: 16px;
|
|
||||||
background: Palette.background;
|
background: Palette.background;
|
||||||
|
|
||||||
in-out property <string> default-source-path;
|
in-out property <string> default-source-path;
|
||||||
|
|
|
@ -18,7 +18,6 @@ export struct SaveTaskData {
|
||||||
}
|
}
|
||||||
|
|
||||||
export struct NewEventParams {
|
export struct NewEventParams {
|
||||||
sourceId: int,
|
|
||||||
title: string,
|
title: string,
|
||||||
date: Date,
|
date: Date,
|
||||||
startsAt: Time,
|
startsAt: Time,
|
||||||
|
@ -39,6 +38,13 @@ struct OpenNewTaskFormParams {
|
||||||
eventId: int,
|
eventId: int,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export struct CreateEventParams {
|
||||||
|
title: string,
|
||||||
|
date: Date,
|
||||||
|
startsAt: Time,
|
||||||
|
endsAt: Time
|
||||||
|
}
|
||||||
|
|
||||||
export global AppWindowActions {
|
export global AppWindowActions {
|
||||||
callback task-clicked(int, int);
|
callback task-clicked(int, int);
|
||||||
callback source-clicked(int);
|
callback source-clicked(int);
|
||||||
|
@ -52,10 +58,11 @@ export global AppWindowActions {
|
||||||
callback open-edit-event-form(int, int);
|
callback open-edit-event-form(int, int);
|
||||||
callback toggle-show-completed-tasks();
|
callback toggle-show-completed-tasks();
|
||||||
callback delete-task-clicked(int, int);
|
callback delete-task-clicked(int, int);
|
||||||
callback delete-event-clicked(int, int);
|
|
||||||
|
callback open-add-event-window();
|
||||||
|
|
||||||
callback create-task(NewTaskData);
|
callback create-task(NewTaskData);
|
||||||
callback save-task(SaveTaskData);
|
callback save-task(SaveTaskData);
|
||||||
callback create-event(NewEventParams);
|
callback create-event(CreateEventParams);
|
||||||
callback save-event(SaveEventParams);
|
callback delete-event(sourceId: int, eventId: int);
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,15 +34,15 @@
|
||||||
|
|
||||||
AppWindow::AppWindow(mirai::Mirai *miraiInstance)
|
AppWindow::AppWindow(mirai::Mirai *miraiInstance)
|
||||||
: miraiInstance_(miraiInstance), addSourceWindow_(miraiInstance),
|
: miraiInstance_(miraiInstance), addSourceWindow_(miraiInstance),
|
||||||
editSourceWindow_(miraiInstance), settingsWindow_(miraiInstance), view_(miraiInstance)
|
editSourceWindow_(miraiInstance), settingsWindow_(miraiInstance),
|
||||||
|
editEventWindow_(miraiInstance), view_(miraiInstance)
|
||||||
{
|
{
|
||||||
sources_ = std::make_shared<slint::VectorModel<ui::Source>>();
|
sources_ = std::make_shared<slint::VectorModel<ui::Source>>();
|
||||||
days_ = std::make_shared<slint::VectorModel<ui::Day>>();
|
days_ = std::make_shared<slint::VectorModel<ui::Day>>();
|
||||||
calendar_ = std::make_shared<slint::VectorModel<ui::CalendarDay>>();
|
calendar_ = std::make_shared<slint::VectorModel<ui::CalendarDay>>();
|
||||||
unscheduledTasks_ = std::make_shared<slint::VectorModel<ui::TaskData>>();
|
unscheduledTasks_ = std::make_shared<slint::VectorModel<ui::TaskData>>();
|
||||||
auto sourcesNames = std::make_shared<slint::MapModel<ui::Source, slint::SharedString>>(
|
auto sourcesNames = std::make_shared<slint::MapModel<ui::Source, slint::SharedString>>(
|
||||||
sources_,
|
sources_, [&](const ui::Source &a) {
|
||||||
[&](const ui::Source &a) {
|
|
||||||
return a.name;
|
return a.name;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -125,6 +125,9 @@ void AppWindow::setupCallbacks()
|
||||||
assert(source);
|
assert(source);
|
||||||
editSourceWindow_.open(source);
|
editSourceWindow_.open(source);
|
||||||
});
|
});
|
||||||
|
actions().on_open_add_event_window([&]() {
|
||||||
|
editEventWindow_.open();
|
||||||
|
});
|
||||||
|
|
||||||
actions().on_task_clicked([&](int sourceId, int taskId) {
|
actions().on_task_clicked([&](int sourceId, int taskId) {
|
||||||
auto source = miraiInstance_->getSourceById(sourceId);
|
auto source = miraiInstance_->getSourceById(sourceId);
|
||||||
|
@ -217,7 +220,7 @@ void AppWindow::setupCallbacks()
|
||||||
reloadTasks();
|
reloadTasks();
|
||||||
});
|
});
|
||||||
|
|
||||||
actions().on_delete_event_clicked([&](int sourceId, int eventId) {
|
actions().on_delete_event([&](int sourceId, int eventId) {
|
||||||
auto source = miraiInstance_->getSourceById(sourceId);
|
auto source = miraiInstance_->getSourceById(sourceId);
|
||||||
assert(source);
|
assert(source);
|
||||||
auto event = source->getEventById(eventId);
|
auto event = source->getEventById(eventId);
|
||||||
|
@ -228,10 +231,12 @@ void AppWindow::setupCallbacks()
|
||||||
reloadTasks();
|
reloadTasks();
|
||||||
});
|
});
|
||||||
|
|
||||||
actions().on_create_event([&](ui::NewEventParams newEventParams) {
|
actions().on_create_event([&](ui::CreateEventParams newEventParams) {
|
||||||
|
std::println("okkk");
|
||||||
const ui::Date &date = newEventParams.date;
|
const ui::Date &date = newEventParams.date;
|
||||||
const std::string dateStr = SlintDateToStdString(date);
|
const std::string dateStr = SlintDateToStdString(date);
|
||||||
auto source = miraiInstance_->getSourceById(newEventParams.sourceId);
|
const auto sourceId = models().get_default_source_index();
|
||||||
|
auto source = miraiInstance_->getSourceById(sourceId == -1 ? 0 : sourceId);
|
||||||
|
|
||||||
source->createEvent({
|
source->createEvent({
|
||||||
.title = std::string(newEventParams.title),
|
.title = std::string(newEventParams.title),
|
||||||
|
@ -244,23 +249,23 @@ void AppWindow::setupCallbacks()
|
||||||
reloadTasks();
|
reloadTasks();
|
||||||
});
|
});
|
||||||
|
|
||||||
actions().on_save_event([&](ui::SaveEventParams newEventParams) {
|
/*actions().on_save_event([&](ui::SaveEventParams newEventParams) {*/
|
||||||
const ui::Date &date = newEventParams.date;
|
/*const ui::Date &date = newEventParams.date;*/
|
||||||
const std::string dateStr = SlintDateToStdString(date);
|
/*const std::string dateStr = SlintDateToStdString(date);*/
|
||||||
auto source = miraiInstance_->getSourceById(newEventParams.sourceId);
|
/*auto source = miraiInstance_->getSourceById(newEventParams.sourceId);*/
|
||||||
assert(source);
|
/*assert(source);*/
|
||||||
auto event = source->getEventById(newEventParams.id);
|
/*auto event = source->getEventById(newEventParams.id);*/
|
||||||
assert(event);
|
/*assert(event);*/
|
||||||
event->setTitle(std::string(newEventParams.title));
|
/*event->setTitle(std::string(newEventParams.title));*/
|
||||||
event->setStartTime(SlintTimeToMiraiTime(newEventParams.startsAt));
|
/*event->setStartTime(SlintTimeToMiraiTime(newEventParams.startsAt));*/
|
||||||
event->setEndTime(SlintTimeToMiraiTime(newEventParams.endsAt));
|
/*event->setEndTime(SlintTimeToMiraiTime(newEventParams.endsAt));*/
|
||||||
|
|
||||||
// TODO we can't change the date of the event for now.
|
/*// TODO we can't change the date of the event for now.*/
|
||||||
|
|
||||||
miraiInstance_->save();
|
/*miraiInstance_->save();*/
|
||||||
view_.update();
|
/*view_.update();*/
|
||||||
reloadTasks();
|
/*reloadTasks();*/
|
||||||
});
|
/*});*/
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<slint::VectorModel<slint::SharedString>>
|
std::shared_ptr<slint::VectorModel<slint::SharedString>>
|
||||||
|
@ -291,14 +296,16 @@ void AppWindow::reloadTasks()
|
||||||
std::chrono::sys_days(todayDate.toStdChrono())
|
std::chrono::sys_days(todayDate.toStdChrono())
|
||||||
)
|
)
|
||||||
.count();
|
.count();
|
||||||
slintDays->push_back(ui::Day{
|
slintDays->push_back(
|
||||||
.date = MiraiDateToSlintDate(currentDate),
|
ui::Day{
|
||||||
.events = slintEvents,
|
.date = MiraiDateToSlintDate(currentDate),
|
||||||
.tasks = slintDayTasks,
|
.events = slintEvents,
|
||||||
.isLate = currentDate < todayDate,
|
.tasks = slintDayTasks,
|
||||||
.isToday = currentDate == todayDate,
|
.isLate = currentDate < todayDate,
|
||||||
.relativeDaysDiff = static_cast<int>(relativeDaysDiff)
|
.isToday = currentDate == todayDate,
|
||||||
});
|
.relativeDaysDiff = static_cast<int>(relativeDaysDiff)
|
||||||
|
}
|
||||||
|
);
|
||||||
// Day's tasks
|
// Day's tasks
|
||||||
const std::vector<mirai::Task> tasksForDate = view_.getTasksForDate(currentDate);
|
const std::vector<mirai::Task> tasksForDate = view_.getTasksForDate(currentDate);
|
||||||
for (int taskIndex = 0; taskIndex < tasksForDate.size(); ++taskIndex) {
|
for (int taskIndex = 0; taskIndex < tasksForDate.size(); ++taskIndex) {
|
||||||
|
@ -317,14 +324,16 @@ void AppWindow::reloadTasks()
|
||||||
for (int eventIndex = 0; eventIndex < eventsForDate.size(); ++eventIndex) {
|
for (int eventIndex = 0; eventIndex < eventsForDate.size(); ++eventIndex) {
|
||||||
auto ¤tEvent = eventsForDate.at(eventIndex);
|
auto ¤tEvent = eventsForDate.at(eventIndex);
|
||||||
auto slintTasks = std::make_shared<slint::VectorModel<ui::TaskData>>();
|
auto slintTasks = std::make_shared<slint::VectorModel<ui::TaskData>>();
|
||||||
slintEvents->push_back(ui::Event{
|
slintEvents->push_back(
|
||||||
.sourceId = currentEvent.sourceId(),
|
ui::Event{
|
||||||
.id = currentEvent.id(),
|
.sourceId = currentEvent.sourceId(),
|
||||||
.title = slint::SharedString(currentEvent.title()),
|
.id = currentEvent.id(),
|
||||||
.startsAt = MiraiTimeToSlintTime(currentEvent.startsAt()),
|
.title = slint::SharedString(currentEvent.title()),
|
||||||
.endsAt = MiraiTimeToSlintTime(currentEvent.endsAt()),
|
.startsAt = MiraiTimeToSlintTime(currentEvent.startsAt()),
|
||||||
.tasks = slintTasks,
|
.endsAt = MiraiTimeToSlintTime(currentEvent.endsAt()),
|
||||||
});
|
.tasks = slintTasks,
|
||||||
|
}
|
||||||
|
);
|
||||||
auto eventTasks = currentEvent.queryTasks();
|
auto eventTasks = currentEvent.queryTasks();
|
||||||
for (int taskIndex = 0; taskIndex < eventTasks.size(); ++taskIndex) {
|
for (int taskIndex = 0; taskIndex < eventTasks.size(); ++taskIndex) {
|
||||||
auto &task = eventTasks.at(taskIndex);
|
auto &task = eventTasks.at(taskIndex);
|
||||||
|
@ -370,25 +379,29 @@ void AppWindow::reloadTasks()
|
||||||
std::chrono::sys_days(todayDate.toStdChrono())
|
std::chrono::sys_days(todayDate.toStdChrono())
|
||||||
)
|
)
|
||||||
.count();
|
.count();
|
||||||
if (relativeDaysDiff < 0 || relativeDaysDiff >= 3) {
|
if (relativeDaysDiff < 0 || relativeDaysDiff >= 7) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const std::vector<mirai::Event> eventsForDate = view_.getEventsForDate(currentDate);
|
const std::vector<mirai::Event> eventsForDate = view_.getEventsForDate(currentDate);
|
||||||
for (int eventIndex = 0; eventIndex < eventsForDate.size(); ++eventIndex) {
|
for (int eventIndex = 0; eventIndex < eventsForDate.size(); ++eventIndex) {
|
||||||
auto ¤tEvent = eventsForDate.at(eventIndex);
|
auto ¤tEvent = eventsForDate.at(eventIndex);
|
||||||
slintEvents->push_back(ui::CalendarDayEvent{
|
slintEvents->push_back(
|
||||||
.title = slint::SharedString(currentEvent.title()),
|
ui::CalendarDayEvent{
|
||||||
.startsAt = MiraiTimeToSlintTime(currentEvent.startsAt()),
|
.sourceId = currentEvent.sourceId(),
|
||||||
.endsAt = MiraiTimeToSlintTime(currentEvent.endsAt()),
|
.id = currentEvent.id(),
|
||||||
});
|
.title = slint::SharedString(currentEvent.title()),
|
||||||
|
.startsAt = MiraiTimeToSlintTime(currentEvent.startsAt()),
|
||||||
|
.endsAt = MiraiTimeToSlintTime(currentEvent.endsAt()),
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto calendarDay = ui::CalendarDay{
|
auto calendarDay = ui::CalendarDay{
|
||||||
.events = slintEvents,
|
.events = slintEvents,
|
||||||
.date = MiraiDateToSlintDate(currentDate),
|
.date = MiraiDateToSlintDate(currentDate),
|
||||||
.header =
|
.header = slint::SharedString(
|
||||||
slint::SharedString(capitalize(formatDateRelative(MiraiDateToSlintDate(currentDate))
|
capitalize(formatDateRelative(MiraiDateToSlintDate(currentDate)))
|
||||||
))
|
)
|
||||||
};
|
};
|
||||||
calendar_->push_back(calendarDay);
|
calendar_->push_back(calendarDay);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../AddSourceWindow/AddSourceWindow.h"
|
#include "../AddSourceWindow/AddSourceWindow.h"
|
||||||
|
#include "../EditEventWindow/EditEventWindow.h"
|
||||||
#include "../EditSourceWindow/EditSourceWindow.h"
|
#include "../EditSourceWindow/EditSourceWindow.h"
|
||||||
#include "../SettingsWindow/SettingsWindow.h"
|
#include "../SettingsWindow/SettingsWindow.h"
|
||||||
#include "mirai-core/Mirai.h"
|
#include "mirai-core/Mirai.h"
|
||||||
|
@ -40,6 +41,7 @@ class AppWindow
|
||||||
SettingsWindow settingsWindow_;
|
SettingsWindow settingsWindow_;
|
||||||
AddSourceWindow addSourceWindow_;
|
AddSourceWindow addSourceWindow_;
|
||||||
EditSourceWindow editSourceWindow_;
|
EditSourceWindow editSourceWindow_;
|
||||||
|
EditEventWindow editEventWindow_;
|
||||||
|
|
||||||
mirai::Mirai *miraiInstance_;
|
mirai::Mirai *miraiInstance_;
|
||||||
mirai::View view_;
|
mirai::View view_;
|
||||||
|
|
|
@ -6,21 +6,46 @@ import { SettingsWindow } from "../SettingsWindow/SettingsWindow.slint";
|
||||||
import { AddSourceWindow } from "../AddSourceWindow//AddSourceWindow.slint";
|
import { AddSourceWindow } from "../AddSourceWindow//AddSourceWindow.slint";
|
||||||
import { EditSourceWindow } from "../EditSourceWindow/EditSourceWindow.slint";
|
import { EditSourceWindow } from "../EditSourceWindow/EditSourceWindow.slint";
|
||||||
import { Palette } from "@selenite";
|
import { Palette } from "@selenite";
|
||||||
|
import { CalendarView } from "views/CalendarView.slint";
|
||||||
|
import { VButton } from "../../../external/selenite/components/Button.slint";
|
||||||
|
|
||||||
export component AppWindow inherits Window {
|
export component AppWindow inherits Window {
|
||||||
|
|
||||||
title: "Mirai";
|
title: "Mirai";
|
||||||
min-height: 100px;
|
min-height: 100px;
|
||||||
max-height: 4000px; // needed, otherwise the window wants to fit the content (on Swaywm)
|
max-height: 4000px; // needed, otherwise the window wants to fit the content (on Swaywm)
|
||||||
default-font-size: 16px;
|
background: Palette.pane;
|
||||||
|
|
||||||
|
private property<bool> show-tasks: false;
|
||||||
|
|
||||||
HorizontalLayout {
|
HorizontalLayout {
|
||||||
SideBar {}
|
VerticalLayout {
|
||||||
MainView {
|
HorizontalLayout {
|
||||||
horizontal-stretch: 1;
|
padding: 16px;
|
||||||
}
|
alignment: LayoutAlignment.stretch;
|
||||||
|
spacing: 8px;
|
||||||
|
VButton {
|
||||||
|
text: "Calendar";
|
||||||
|
clicked => { show-tasks = false }
|
||||||
|
}
|
||||||
|
|
||||||
|
VButton {
|
||||||
|
text: "Tasks";
|
||||||
|
clicked => { show-tasks = true }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SideBar {}
|
||||||
|
}
|
||||||
|
VerticalLayout {
|
||||||
|
|
||||||
|
if show-tasks : MainView {
|
||||||
|
horizontal-stretch: 1;
|
||||||
|
}
|
||||||
|
if !show-tasks : CalendarView {
|
||||||
|
horizontal-stretch: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export { AppWindowModels, Palette, SettingsWindow, AddSourceWindow, EditSourceWindow } // Export to make it visible to the C++ backend
|
export { AppWindowModels, Palette, SettingsWindow, AddSourceWindow, EditSourceWindow } // Export to make it visible to the C++ backend
|
||||||
|
|
90
src/windows/AppWindow/views/CalendarView.slint
Normal file
90
src/windows/AppWindow/views/CalendarView.slint
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
import { AppWindowModels, TaskData } from "../Models.slint";
|
||||||
|
import { AppWindowActions, NewTaskData, SaveTaskData } from "../Actions.slint";
|
||||||
|
import { Button, VerticalBox, CheckBox, ScrollView, ComboBox } from "std-widgets.slint";
|
||||||
|
import { TaskLine } from "../../../components/TaskLine.slint";
|
||||||
|
import { EventGroup } from "../../../components/EventGroup.slint";
|
||||||
|
import { Calendar } from "../../../components/Calendar.slint";
|
||||||
|
import { VPopupIconMenu, VDatePicker, VTimePicker, VCheckBox, VButton, VTag, VText, VTextInput, Svg, Palette } from "@selenite";
|
||||||
|
import { CreateTaskOrEvent } from "../../../components/CreateTaskOrEvent.slint";
|
||||||
|
import { Utils } from "../../../shared/Utils.slint";
|
||||||
|
import { VActionButton } from "../../../../external/selenite/components/index.slint";
|
||||||
|
|
||||||
|
export component CalendarView inherits Rectangle {
|
||||||
|
|
||||||
|
background: Palette.background;
|
||||||
|
private property<string> icon-visible: Svg.visible;
|
||||||
|
private property<string> icon-not-visible: Svg.not-visible;
|
||||||
|
private property<bool> completed-tasks-visible: false;
|
||||||
|
|
||||||
|
createEventPopup := PopupWindow {
|
||||||
|
x: parent.width / 2 - 200px;
|
||||||
|
y: parent.height / 2 - 300px;
|
||||||
|
close-policy: close-on-click-outside;
|
||||||
|
background := Rectangle {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
background: Palette.background1;
|
||||||
|
border-color: Palette.popup-border;
|
||||||
|
border-width: 1px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
VerticalLayout {
|
||||||
|
padding: 16px;
|
||||||
|
spacing: 8px;
|
||||||
|
titleInput := VTextInput {
|
||||||
|
label: "title";
|
||||||
|
}
|
||||||
|
VText { text: "on"; vertical-alignment: bottom;}
|
||||||
|
dateInput := VDatePicker {
|
||||||
|
enabled: true;
|
||||||
|
}
|
||||||
|
HorizontalLayout {
|
||||||
|
spacing: 4px;
|
||||||
|
VText { text: "between"; vertical-alignment: bottom; }
|
||||||
|
startTimeInput := VTimePicker { }
|
||||||
|
VText { text: "and"; vertical-alignment: bottom; }
|
||||||
|
endTimeInput := VTimePicker { }
|
||||||
|
}
|
||||||
|
VButton {
|
||||||
|
text: "Create";
|
||||||
|
clicked => {
|
||||||
|
debug("clicked OK");
|
||||||
|
debug(createEventPopup.width);
|
||||||
|
debug(createEventPopup.height);
|
||||||
|
AppWindowActions.create-event({
|
||||||
|
title: titleInput.text,
|
||||||
|
date: dateInput.date,
|
||||||
|
startsAt: startTimeInput.time,
|
||||||
|
endsAt: endTimeInput.time
|
||||||
|
});
|
||||||
|
debug("Event sent");
|
||||||
|
createEventPopup.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
VerticalLayout {
|
||||||
|
HorizontalLayout {
|
||||||
|
alignment: start;
|
||||||
|
padding: 16px;
|
||||||
|
VButton {
|
||||||
|
text: "New event";
|
||||||
|
icon-svg: Svg.plus;
|
||||||
|
icon-colorize: greenyellow;
|
||||||
|
clicked => {
|
||||||
|
createEventPopup.show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Calendar {
|
||||||
|
delete-event-request(source-id, event-id) => { debug("DEELTE", source-id);AppWindowActions.delete-event(source-id, event-id) }
|
||||||
|
init => { debug("cal len", AppWindowModels.calendar.length) }
|
||||||
|
days: AppWindowModels.calendar;
|
||||||
|
current-date: Utils.current-date;
|
||||||
|
current-time: Utils.current-time;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -52,16 +52,6 @@ export component MainView inherits Rectangle {
|
||||||
date: data.date
|
date: data.date
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
create-event(data) => {
|
|
||||||
AppWindowActions.create-event({
|
|
||||||
sourceId: data.sourceId,
|
|
||||||
title: data.title,
|
|
||||||
date: data.date,
|
|
||||||
startsAt: data.startsAt,
|
|
||||||
endsAt: data.endsAt,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Flickable {
|
Flickable {
|
||||||
|
@ -125,17 +115,17 @@ export component MainView inherits Rectangle {
|
||||||
AppWindowActions.task-clicked(event.sourceId, taskId);
|
AppWindowActions.task-clicked(event.sourceId, taskId);
|
||||||
}
|
}
|
||||||
delete => {
|
delete => {
|
||||||
AppWindowActions.delete-event-clicked(event.sourceId, event.id)
|
//AppWindowActions.delete-event-clicked(event.sourceId, event.id)
|
||||||
}
|
}
|
||||||
edit(data) => {
|
edit(data) => {
|
||||||
AppWindowActions.save-event({
|
//AppWindowActions.save-event({
|
||||||
sourceId: event.sourceId,
|
//sourceId: event.sourceId,
|
||||||
id: event.id,
|
//id: event.id,
|
||||||
title: data.title,
|
//title: data.title,
|
||||||
//date: event.date,
|
////date: event.date,
|
||||||
startsAt: event.startsAt,
|
//startsAt: event.startsAt,
|
||||||
endsAt: event.endsAt,
|
//endsAt: event.endsAt,
|
||||||
});
|
//});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -214,12 +204,6 @@ export component MainView inherits Rectangle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Calendar {
|
|
||||||
init => { debug("cal len", AppWindowModels.calendar.length) }
|
|
||||||
days: AppWindowModels.calendar;
|
|
||||||
current-date: Utils.current-date;
|
|
||||||
current-time: Utils.current-time;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
50
src/windows/EditEventWindow/EditEventWindow.cpp
Normal file
50
src/windows/EditEventWindow/EditEventWindow.cpp
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* 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 "EditEventWindow.h"
|
||||||
|
#include "../../SeleniteSetup.h"
|
||||||
|
#include "evalyte-cpp-common/evalyte.h"
|
||||||
|
#include "mirai-core/DataProvider.h"
|
||||||
|
#include "mirai-core/MarkdownDataProvider.h"
|
||||||
|
#include "mirai-core/Mirai.h"
|
||||||
|
#include "slint.h"
|
||||||
|
#include "slint_string.h"
|
||||||
|
#include <bits/chrono.h>
|
||||||
|
#include <cassert>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <ctime>
|
||||||
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
|
#include <print>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
EditEventWindow::EditEventWindow(mirai::Mirai *miraiInstance) : miraiInstance_(miraiInstance)
|
||||||
|
{
|
||||||
|
|
||||||
|
const auto palettePath = std::string(getenv("HOME")) + "/.config/evalyte/theme.json";
|
||||||
|
const auto palette = selenite::parseJson(palettePath);
|
||||||
|
|
||||||
|
if (palette.has_value()) {
|
||||||
|
setSelenitePalette(window_->global<ui::Palette>(), palette.value());
|
||||||
|
}
|
||||||
|
|
||||||
|
setupCallbacks();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditEventWindow::setupCallbacks()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditEventWindow::open()
|
||||||
|
{
|
||||||
|
window_->show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditEventWindow::close()
|
||||||
|
{
|
||||||
|
window_->hide();
|
||||||
|
}
|
33
src/windows/EditEventWindow/EditEventWindow.h
Normal file
33
src/windows/EditEventWindow/EditEventWindow.h
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "mirai-core/Mirai.h"
|
||||||
|
#include "slint.h"
|
||||||
|
#include "ui.h"
|
||||||
|
|
||||||
|
class EditEventWindow
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
EditEventWindow(mirai::Mirai *mirai);
|
||||||
|
|
||||||
|
void open();
|
||||||
|
void close();
|
||||||
|
|
||||||
|
auto getHandle()
|
||||||
|
{
|
||||||
|
return this->window_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setupCallbacks();
|
||||||
|
|
||||||
|
std::shared_ptr<slint::VectorModel<ui::Source>> sources_;
|
||||||
|
slint::ComponentHandle<ui::EditEventWindow> window_ = ui::EditEventWindow::create();
|
||||||
|
mirai::Mirai *miraiInstance_;
|
||||||
|
};
|
68
src/windows/EditEventWindow/EditEventWindow.slint
Normal file
68
src/windows/EditEventWindow/EditEventWindow.slint
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
import { AppWindowModels } from "../AppWindow/Models.slint";
|
||||||
|
import { Button, VerticalBox, CheckBox } from "std-widgets.slint";
|
||||||
|
import { VText, VTextInput, Palette } from "@selenite";
|
||||||
|
import { VButton } from "../../../external/selenite/components/index.slint";
|
||||||
|
import { Date, Time, Button, VerticalBox, CheckBox, ScrollView, ComboBox } from "std-widgets.slint";
|
||||||
|
import { VDatePicker } from "../../../external/selenite/components/DatePicker.slint";
|
||||||
|
import { VTimePicker } from "../../../external/selenite/components/TimePicker.slint";
|
||||||
|
|
||||||
|
export struct CreateEventParams {
|
||||||
|
title: string,
|
||||||
|
date: Date,
|
||||||
|
startsAt: Time,
|
||||||
|
endsAt: Time
|
||||||
|
}
|
||||||
|
|
||||||
|
export component EditEventWindow inherits Window {
|
||||||
|
|
||||||
|
title: "Mirai - Event";
|
||||||
|
min-height: 100px;
|
||||||
|
max-height: 500px; // needed, otherwise the window wants to fit the content (on Swaywm)
|
||||||
|
max-width: 500px; // needed, otherwise the window wants to fit the content (on Swaywm)
|
||||||
|
background: Palette.background;
|
||||||
|
in-out property <int> sourceId;
|
||||||
|
|
||||||
|
callback create-event(CreateEventParams);
|
||||||
|
callback delete-event(int);
|
||||||
|
|
||||||
|
VerticalLayout {
|
||||||
|
padding: 16px;
|
||||||
|
spacing: 8px;
|
||||||
|
titleInput := VTextInput {
|
||||||
|
label: "title";
|
||||||
|
}
|
||||||
|
VText { text: "on"; vertical-alignment: bottom;}
|
||||||
|
dateInput := VDatePicker {
|
||||||
|
enabled: true;
|
||||||
|
}
|
||||||
|
HorizontalLayout {
|
||||||
|
spacing: 4px;
|
||||||
|
VText { text: "between"; vertical-alignment: bottom; }
|
||||||
|
startTimeInput := VTimePicker { }
|
||||||
|
VText { text: "and"; vertical-alignment: bottom; }
|
||||||
|
endTimeInput := VTimePicker { }
|
||||||
|
}
|
||||||
|
VButton {
|
||||||
|
text: "Create";
|
||||||
|
clicked => {
|
||||||
|
debug("clicked");
|
||||||
|
root.create-event({
|
||||||
|
title: titleInput.text,
|
||||||
|
date: dateInput.date,
|
||||||
|
startsAt: startTimeInput.time,
|
||||||
|
endsAt: endTimeInput.time
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
VButton {
|
||||||
|
text: "Delete";
|
||||||
|
background-color: Palette.red;
|
||||||
|
double-clicked => {
|
||||||
|
//root.delete-event(root.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export { AppWindowModels, Palette } // Export to make it visible to the C++ backend
|
|
@ -16,7 +16,6 @@ export component EditSourceWindow inherits Window {
|
||||||
min-height: 100px;
|
min-height: 100px;
|
||||||
max-height: 4000px; // needed, otherwise the window wants to fit the content (on Swaywm)
|
max-height: 4000px; // needed, otherwise the window wants to fit the content (on Swaywm)
|
||||||
min-width: 400px;
|
min-width: 400px;
|
||||||
default-font-size: 16px;
|
|
||||||
background: Palette.background;
|
background: Palette.background;
|
||||||
|
|
||||||
callback modify-source(ModifySourceParam);
|
callback modify-source(ModifySourceParam);
|
||||||
|
|
|
@ -7,7 +7,6 @@ export component SettingsWindow inherits Window {
|
||||||
title: "Mirai - Settings";
|
title: "Mirai - Settings";
|
||||||
min-height: 100px;
|
min-height: 100px;
|
||||||
max-height: 4000px; // needed, otherwise the window wants to fit the content (on Swaywm)
|
max-height: 4000px; // needed, otherwise the window wants to fit the content (on Swaywm)
|
||||||
default-font-size: 16px;
|
|
||||||
background: Palette.background;
|
background: Palette.background;
|
||||||
|
|
||||||
VerticalLayout {
|
VerticalLayout {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue