Move Calendar to its own view

This commit is contained in:
Vyn 2025-06-17 17:03:07 +02:00
parent a03e71890c
commit d26f2f5a9f
Signed by: vyn
GPG key ID: E1B2BE34E7A971E7
19 changed files with 407 additions and 137 deletions

2
.gitmodules vendored
View file

@ -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

View file

@ -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

@ -1 +1 @@
Subproject commit 9cba85a21aa6c2eee6101dd38252249283816327 Subproject commit c653e851118c893678762d1aeeac3b995a60b9d4

2
external/slint vendored

@ -1 +1 @@
Subproject commit ca66a6af4a4e9c4c78ff889ba447bcb460d07c91 Subproject commit 37fb91fafced9e117597a9a1825a641a8c3ea541

View file

@ -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);
}
}
}
} }
} }
} }

View file

@ -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;

View file

@ -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 }

View file

@ -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;

View file

@ -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);
} }

View file

@ -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 &currentEvent = eventsForDate.at(eventIndex); auto &currentEvent = 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 &currentEvent = eventsForDate.at(eventIndex); auto &currentEvent = 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);
} }

View file

@ -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_;

View file

@ -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

View 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;
}
}
}

View file

@ -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;
}
} }
} }

View 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();
}

View 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_;
};

View 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

View file

@ -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);

View file

@ -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 {