2022-08-02 08:04:48 +02:00
|
|
|
//! Simple calendar applications.
|
2022-11-23 21:54:17 +01:00
|
|
|
mod ui;
|
2023-01-15 15:38:41 +01:00
|
|
|
mod model;
|
|
|
|
|
2022-11-23 21:54:17 +01:00
|
|
|
use ui::calendar;
|
2023-01-15 15:38:41 +01:00
|
|
|
use model::events::EventsCollection;
|
2023-07-09 18:49:42 +02:00
|
|
|
use model::ical_bridge::load_calendar;
|
2022-08-02 08:04:48 +02:00
|
|
|
|
2022-09-25 08:23:14 +02:00
|
|
|
use chrono::{Datelike, NaiveDate, Months, Utc};
|
2022-11-23 21:54:17 +01:00
|
|
|
use calendar::{CalendarMonthView, CalendarYearView, CalendarParams };
|
2022-08-02 08:04:48 +02:00
|
|
|
|
2023-07-09 18:49:42 +02:00
|
|
|
use std::path;
|
|
|
|
use clap;
|
|
|
|
use clap::Parser;
|
|
|
|
|
2022-08-02 08:04:48 +02:00
|
|
|
use iced::{
|
2023-05-21 13:41:16 +02:00
|
|
|
alignment,
|
2022-12-25 12:14:01 +01:00
|
|
|
executor,
|
|
|
|
Alignment, Application, Command,
|
|
|
|
Element, Length, Settings,
|
2022-08-15 12:05:00 +02:00
|
|
|
};
|
|
|
|
use iced::widget::{
|
|
|
|
Column, Row,
|
|
|
|
Container,
|
2022-08-02 08:04:48 +02:00
|
|
|
Button, Text,
|
2022-10-16 14:51:37 +02:00
|
|
|
pick_list,
|
2022-08-02 08:04:48 +02:00
|
|
|
};
|
2022-08-15 12:05:00 +02:00
|
|
|
//use iced::button;
|
2022-08-02 08:04:48 +02:00
|
|
|
use iced::theme;
|
|
|
|
|
2023-09-10 11:01:05 +02:00
|
|
|
#[cfg(feature = "tracing")]
|
|
|
|
extern crate lttng_ust;
|
|
|
|
|
|
|
|
#[cfg(feature = "tracing")]
|
|
|
|
use lttng_ust::import_tracepoints;
|
|
|
|
|
|
|
|
#[cfg(feature = "tracing")]
|
|
|
|
import_tracepoints!(
|
|
|
|
concat!(env!("OUT_DIR"), "/tracepoints.rs"),
|
|
|
|
tracepoints
|
|
|
|
);
|
|
|
|
|
2023-07-09 18:49:42 +02:00
|
|
|
struct CalendarFlags {
|
|
|
|
calendar_paths: std::vec::Vec<path::PathBuf>,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Parser, Debug)]
|
|
|
|
#[command(version, about)]
|
|
|
|
struct CliArgs {
|
|
|
|
files: Vec<String>,
|
|
|
|
}
|
|
|
|
|
2022-08-02 08:04:48 +02:00
|
|
|
pub fn main() -> iced::Result {
|
2023-07-09 18:49:42 +02:00
|
|
|
let args = CliArgs::parse();
|
|
|
|
let calendar_files = args.files.iter().map(|arg| path::PathBuf::from(arg)).collect();
|
|
|
|
//let calendar_files = vec![path::PathBuf::from("/home/fab/calendario.ics")];
|
|
|
|
CalendarApp::run(Settings::with_flags(CalendarFlags {calendar_paths: calendar_files}))
|
2022-08-02 08:04:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Default)]
|
|
|
|
struct CalendarApp {
|
2022-09-25 08:23:14 +02:00
|
|
|
month: NaiveDate,
|
2022-08-02 08:04:48 +02:00
|
|
|
controls: Controls,
|
2023-01-15 15:38:41 +01:00
|
|
|
events: EventsCollection,
|
2022-08-02 08:04:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Copy)]
|
|
|
|
enum Message {
|
|
|
|
NextMonth,
|
|
|
|
PrevMonth,
|
2023-09-11 07:49:01 +02:00
|
|
|
NextYear,
|
|
|
|
PrevYear,
|
2022-10-16 14:51:37 +02:00
|
|
|
ViewModeSelected(ViewMode),
|
2022-08-02 08:04:48 +02:00
|
|
|
}
|
|
|
|
|
2022-10-16 14:51:37 +02:00
|
|
|
//#[derive(Default)]
|
2022-08-02 08:04:48 +02:00
|
|
|
struct Controls {
|
2022-10-16 14:51:37 +02:00
|
|
|
mode: Option<ViewMode>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for Controls {
|
|
|
|
fn default() -> Controls {
|
|
|
|
Controls {
|
2022-11-23 21:54:17 +01:00
|
|
|
mode : Some(ViewMode::Year)
|
2022-10-16 14:51:37 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
|
|
pub enum ViewMode {
|
|
|
|
Month,
|
|
|
|
Year,
|
2022-08-02 08:04:48 +02:00
|
|
|
}
|
|
|
|
|
2022-10-16 14:51:37 +02:00
|
|
|
impl std::fmt::Display for ViewMode {
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
|
write!(
|
|
|
|
f,
|
|
|
|
"{}",
|
|
|
|
match self {
|
|
|
|
ViewMode::Month => "Month",
|
|
|
|
ViewMode::Year => "Year",
|
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
2022-12-25 12:14:01 +01:00
|
|
|
|
2022-08-02 08:04:48 +02:00
|
|
|
impl Controls {
|
2022-11-23 21:54:17 +01:00
|
|
|
const MODES : [ViewMode; 2] = [ViewMode::Month, ViewMode::Year];
|
2022-10-16 14:51:37 +02:00
|
|
|
|
|
|
|
fn view<'a>(&'a self, month_name: &'a str, year: i32) -> Element<Message> {
|
2023-09-11 07:49:01 +02:00
|
|
|
let description = match self.mode {
|
|
|
|
Some(ViewMode::Month) => month_name,
|
|
|
|
_ => ""
|
|
|
|
};
|
2022-08-02 08:04:48 +02:00
|
|
|
Row::new()
|
|
|
|
.align_items(Alignment::Center)
|
|
|
|
.padding(5)
|
|
|
|
.spacing(10)
|
2022-10-16 14:51:37 +02:00
|
|
|
.push(
|
|
|
|
pick_list(
|
|
|
|
&Controls::MODES[..],
|
|
|
|
self.mode,
|
|
|
|
Message::ViewModeSelected,
|
|
|
|
).placeholder("mode")
|
|
|
|
)
|
2022-08-02 08:04:48 +02:00
|
|
|
.push(
|
2022-09-25 08:23:14 +02:00
|
|
|
Button::new(Text::new("<"))
|
2023-09-11 07:49:01 +02:00
|
|
|
.on_press(self.get_msg_prev())
|
2022-08-02 08:04:48 +02:00
|
|
|
.style(theme::Button::Secondary),
|
|
|
|
)
|
2022-09-25 08:23:14 +02:00
|
|
|
.push(
|
|
|
|
Button::new(Text::new(">"))
|
2023-09-11 07:49:01 +02:00
|
|
|
.on_press(self.get_msg_next())
|
2022-09-25 08:23:14 +02:00
|
|
|
.style(theme::Button::Secondary),
|
|
|
|
)
|
2022-08-02 08:04:48 +02:00
|
|
|
.push(
|
2023-09-11 07:49:01 +02:00
|
|
|
Text::new(description)
|
2022-08-15 12:05:00 +02:00
|
|
|
.width(Length::Fill)
|
2023-05-21 13:41:16 +02:00
|
|
|
.horizontal_alignment(alignment::Horizontal::Left)
|
2022-09-25 08:23:14 +02:00
|
|
|
.size(40),
|
2022-08-02 08:04:48 +02:00
|
|
|
)
|
|
|
|
.push(
|
2022-10-16 14:51:37 +02:00
|
|
|
Text::new(year.to_string())
|
2022-09-25 08:23:14 +02:00
|
|
|
.width(Length::Fill)
|
2023-05-21 13:41:16 +02:00
|
|
|
.horizontal_alignment(alignment::Horizontal::Right)
|
2022-09-25 08:23:14 +02:00
|
|
|
.size(40),
|
2022-08-02 08:04:48 +02:00
|
|
|
)
|
|
|
|
.into()
|
|
|
|
}
|
2023-09-11 07:49:01 +02:00
|
|
|
|
|
|
|
fn get_msg_next(&self) -> Message {
|
|
|
|
match self.mode {
|
|
|
|
Some(ViewMode::Month) => Message::NextMonth,
|
|
|
|
_ => Message::NextYear
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get_msg_prev(&self) -> Message {
|
|
|
|
match self.mode {
|
|
|
|
Some(ViewMode::Month) => Message::PrevMonth,
|
|
|
|
_ => Message::PrevYear
|
|
|
|
}
|
|
|
|
}
|
2022-08-02 08:04:48 +02:00
|
|
|
}
|
|
|
|
|
2022-12-25 12:14:01 +01:00
|
|
|
impl Application for CalendarApp {
|
|
|
|
type Executor = executor::Default;
|
2022-08-02 08:04:48 +02:00
|
|
|
type Message = Message;
|
2022-12-25 12:14:01 +01:00
|
|
|
type Theme = iced::Theme;
|
2023-07-09 18:49:42 +02:00
|
|
|
type Flags = CalendarFlags;
|
2022-08-02 08:04:48 +02:00
|
|
|
|
2023-07-09 18:49:42 +02:00
|
|
|
fn new(flags: Self::Flags) -> (Self, Command<Message>) {
|
|
|
|
let month = Utc::now().date_naive();
|
|
|
|
let mut ret = (CalendarApp {
|
2022-09-25 08:23:14 +02:00
|
|
|
month,
|
2023-01-15 15:38:41 +01:00
|
|
|
events: EventsCollection::new(),
|
2022-08-02 08:04:48 +02:00
|
|
|
..CalendarApp::default()
|
2023-07-09 18:49:42 +02:00
|
|
|
}, Command::none());
|
|
|
|
for calendar_path in flags.calendar_paths {
|
|
|
|
load_calendar(&calendar_path, &mut ret.0.events);
|
|
|
|
}
|
|
|
|
ret
|
2022-08-02 08:04:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
fn title(&self) -> String {
|
|
|
|
String::from("Calendar")
|
|
|
|
}
|
|
|
|
|
2022-12-25 12:14:01 +01:00
|
|
|
fn update(&mut self, message: Message) -> Command<Message> {
|
2022-08-02 08:04:48 +02:00
|
|
|
match message {
|
|
|
|
Message::PrevMonth => {
|
2022-09-25 08:23:14 +02:00
|
|
|
self.month = self.month - Months::new(1);
|
2022-08-02 08:04:48 +02:00
|
|
|
}
|
|
|
|
Message::NextMonth => {
|
2022-09-25 08:23:14 +02:00
|
|
|
self.month = self.month + Months::new(1);
|
2022-08-02 08:04:48 +02:00
|
|
|
}
|
2023-09-11 07:49:01 +02:00
|
|
|
Message::PrevYear => {
|
|
|
|
self.month = self.month - Months::new(12);
|
|
|
|
}
|
|
|
|
Message::NextYear => {
|
|
|
|
self.month = self.month + Months::new(12);
|
|
|
|
}
|
2022-10-16 14:51:37 +02:00
|
|
|
Message::ViewModeSelected(mode) => {
|
|
|
|
self.controls.mode = Some(mode);
|
|
|
|
}
|
2022-08-02 08:04:48 +02:00
|
|
|
}
|
2022-12-25 12:14:01 +01:00
|
|
|
Command::none()
|
2022-08-02 08:04:48 +02:00
|
|
|
}
|
|
|
|
|
2022-08-15 12:05:00 +02:00
|
|
|
fn view(&self) -> Element<Message> {
|
2023-09-10 11:01:05 +02:00
|
|
|
#[cfg(feature = "tracing")]
|
|
|
|
tracepoints::calendar::view_entry();
|
2022-08-02 08:04:48 +02:00
|
|
|
const MONTH_NAMES: [&str;12] = [
|
2022-09-25 08:23:14 +02:00
|
|
|
"gennaio",
|
|
|
|
"febbraio",
|
|
|
|
"marzo",
|
|
|
|
"aprile",
|
|
|
|
"maggio",
|
|
|
|
"giugno",
|
|
|
|
"luglio",
|
|
|
|
"agosto",
|
|
|
|
"settembre",
|
|
|
|
"ottobre",
|
|
|
|
"novembre",
|
|
|
|
"dicembre",
|
2022-08-02 08:04:48 +02:00
|
|
|
];
|
2022-11-23 21:54:17 +01:00
|
|
|
let mut content = Column::new()
|
2023-03-05 08:21:38 +01:00
|
|
|
.align_items(Alignment::Center)
|
2022-10-16 14:51:37 +02:00
|
|
|
.push(self.controls.view(MONTH_NAMES[self.month.month0() as usize], self.month.year()))
|
2022-08-02 08:04:48 +02:00
|
|
|
;
|
|
|
|
|
2022-11-23 21:54:17 +01:00
|
|
|
match self.controls.mode {
|
2023-01-15 15:38:41 +01:00
|
|
|
Some(ViewMode::Year) => content = content.push(CalendarYearView::new(&CalendarParams::new(), self.month, &self.events)),
|
2023-05-21 13:41:16 +02:00
|
|
|
Some(ViewMode::Month) | None => content = content.push(CalendarMonthView::new(&CalendarParams::new(), self.month, &self.events)),
|
2022-11-23 21:54:17 +01:00
|
|
|
};
|
2022-12-25 12:14:01 +01:00
|
|
|
|
2023-09-10 11:01:05 +02:00
|
|
|
let container = Container::new(content)
|
2022-08-02 08:04:48 +02:00
|
|
|
.width(Length::Fill)
|
|
|
|
.height(Length::Fill)
|
|
|
|
.center_x()
|
|
|
|
.center_y()
|
2023-09-10 11:01:05 +02:00
|
|
|
.into();
|
|
|
|
|
|
|
|
#[cfg(feature = "tracing")]
|
|
|
|
tracepoints::calendar::view_exit();
|
|
|
|
|
|
|
|
container
|
2022-08-02 08:04:48 +02:00
|
|
|
}
|
2022-11-23 21:54:17 +01:00
|
|
|
}
|