initial support for event organizer and category

* add fiedls to event
* parse in ical bridge
* option to show organizer in event bars (on by default)
This commit is contained in:
Fabrizio Iannetti 2024-10-06 18:52:20 +02:00
parent 4e9f195851
commit bc8d662389
6 changed files with 176 additions and 133 deletions

150
Cargo.lock generated
View File

@ -189,11 +189,11 @@ checksum = "175571dd1d178ced59193a6fc02dde1b972eb0bc56c892cde9beeceac5bf0f6b"
[[package]]
name = "ash"
version = "0.37.3+1.3.251"
version = "0.38.0+1.3.281"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39e9c3835d686b0a6084ab4234fcd1b07dbf6e4767dce60874b12356a25ecd4a"
checksum = "0bb44936d800fea8f016d7f2311c6a4f97aebd5dc86f09906139ec848cf3a46f"
dependencies = [
"libloading 0.7.4",
"libloading 0.8.5",
]
[[package]]
@ -377,18 +377,18 @@ dependencies = [
[[package]]
name = "bit-set"
version = "0.5.3"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1"
checksum = "f0481a0e032742109b1133a095184ee93d88f3dc9e0d28a5d033dc77a073f44f"
dependencies = [
"bit-vec",
]
[[package]]
name = "bit-vec"
version = "0.6.3"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"
checksum = "d2c54ff287cfc0a34f38a6b832ea1bd8e448a330b3e40a50859e6488bee07f22"
[[package]]
name = "bitflags"
@ -903,12 +903,12 @@ checksum = "96a6ac251f4a2aca6b3f91340350eab87ae57c3f127ffeb585e92bd336717991"
[[package]]
name = "d3d12"
version = "0.19.0"
version = "22.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e3d747f100290a1ca24b752186f61f6637e1deffe3bf6320de6fcb29510a307"
checksum = "bdbd1f579714e3c809ebd822c81ef148b1ceaeb3d535352afc73fd0c4c6a0017"
dependencies = [
"bitflags 2.6.0",
"libloading 0.8.5",
"libloading 0.7.4",
"winapi",
]
@ -1030,6 +1030,15 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0688c2a7f92e427f44895cd63841bff7b29f8d7a1648b9e7e07a4a365b2e1257"
[[package]]
name = "document-features"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb6969eaabd2421f8a2775cfd2471a2b634372b4a25d41e3bd647b79912850a0"
dependencies = [
"litrs",
]
[[package]]
name = "downcast-rs"
version = "1.2.1"
@ -1438,9 +1447,9 @@ dependencies = [
[[package]]
name = "glutin_wgl_sys"
version = "0.5.0"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c8098adac955faa2d31079b65dc48841251f69efd3ac25477903fc424362ead"
checksum = "0a4e1951bbd9434a81aa496fe59ccc2235af3820d27b85f9314e279609211e2c"
dependencies = [
"gl_generator",
]
@ -1448,7 +1457,7 @@ dependencies = [
[[package]]
name = "glyphon"
version = "0.5.0"
source = "git+https://github.com/hecrj/glyphon.git?rev=feef9f5630c2adb3528937e55f7bfad2da561a65#feef9f5630c2adb3528937e55f7bfad2da561a65"
source = "git+https://github.com/hecrj/glyphon.git?rev=0d7ba1bba4dd71eb88d2cface5ce649db2413cb7#0d7ba1bba4dd71eb88d2cface5ce649db2413cb7"
dependencies = [
"cosmic-text",
"etagere",
@ -1478,9 +1487,9 @@ dependencies = [
[[package]]
name = "gpu-allocator"
version = "0.25.0"
version = "0.26.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f56f6318968d03c18e1bcf4857ff88c61157e9da8e47c5f29055d60e1228884"
checksum = "fdd4240fc91d3433d5e5b0fc5b67672d771850dc19bbee03c1381e19322803d7"
dependencies = [
"log",
"presser",
@ -1491,9 +1500,9 @@ dependencies = [
[[package]]
name = "gpu-descriptor"
version = "0.2.4"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc11df1ace8e7e564511f53af41f3e42ddc95b56fd07b3f4445d2a6048bc682c"
checksum = "9c08c1f623a8d0b722b8b99f821eb0ba672a1618f0d3b16ddbee1cedd2dd8557"
dependencies = [
"bitflags 2.6.0",
"gpu-descriptor-types",
@ -1502,9 +1511,9 @@ dependencies = [
[[package]]
name = "gpu-descriptor-types"
version = "0.1.2"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6bf0b36e6f090b7e1d8a4b49c0cb81c1f8376f72198c65dd3ad9ff3556b8b78c"
checksum = "fdf242682df893b86f33a73828fb09ca4b2d3bb6cc95249707fc684d27484b91"
dependencies = [
"bitflags 2.6.0",
]
@ -1639,7 +1648,7 @@ dependencies = [
[[package]]
name = "iced"
version = "0.13.0-dev"
version = "0.14.0-dev"
dependencies = [
"iced_core",
"iced_futures",
@ -1651,7 +1660,7 @@ dependencies = [
[[package]]
name = "iced_core"
version = "0.13.0-dev"
version = "0.14.0-dev"
dependencies = [
"bitflags 2.6.0",
"bytes",
@ -1669,7 +1678,7 @@ dependencies = [
[[package]]
name = "iced_futures"
version = "0.13.0-dev"
version = "0.14.0-dev"
dependencies = [
"futures",
"iced_core",
@ -1681,7 +1690,7 @@ dependencies = [
[[package]]
name = "iced_graphics"
version = "0.13.0-dev"
version = "0.14.0-dev"
dependencies = [
"bitflags 2.6.0",
"bytemuck",
@ -1699,7 +1708,7 @@ dependencies = [
[[package]]
name = "iced_renderer"
version = "0.13.0-dev"
version = "0.14.0-dev"
dependencies = [
"iced_graphics",
"iced_tiny_skia",
@ -1710,7 +1719,7 @@ dependencies = [
[[package]]
name = "iced_runtime"
version = "0.13.0-dev"
version = "0.14.0-dev"
dependencies = [
"bytes",
"iced_core",
@ -1721,7 +1730,7 @@ dependencies = [
[[package]]
name = "iced_tiny_skia"
version = "0.13.0-dev"
version = "0.14.0-dev"
dependencies = [
"bytemuck",
"cosmic-text",
@ -1735,7 +1744,7 @@ dependencies = [
[[package]]
name = "iced_wgpu"
version = "0.13.0-dev"
version = "0.14.0-dev"
dependencies = [
"bitflags 2.6.0",
"bytemuck",
@ -1753,7 +1762,7 @@ dependencies = [
[[package]]
name = "iced_widget"
version = "0.13.0-dev"
version = "0.14.0-dev"
dependencies = [
"iced_renderer",
"iced_runtime",
@ -1766,7 +1775,7 @@ dependencies = [
[[package]]
name = "iced_winit"
version = "0.13.0-dev"
version = "0.14.0-dev"
dependencies = [
"iced_futures",
"iced_graphics",
@ -1966,6 +1975,12 @@ version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a385b1be4e5c3e362ad2ffa73c392e53f031eaa5b7d648e64cd87f27f6063d7"
[[package]]
name = "litrs"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5"
[[package]]
name = "lock_api"
version = "0.4.12"
@ -2040,9 +2055,9 @@ dependencies = [
[[package]]
name = "metal"
version = "0.27.0"
version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c43f73953f8cbe511f021b58f18c3ce1c3d1ae13fe953293e13345bf83217f25"
checksum = "7ecfd3296f8c56b7c1f6fbac3c71cefa9d78ce009850c45000015f206dc7fa21"
dependencies = [
"bitflags 2.6.0",
"block",
@ -2080,17 +2095,18 @@ dependencies = [
[[package]]
name = "naga"
version = "0.19.2"
version = "22.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50e3524642f53d9af419ab5e8dd29d3ba155708267667c2f3f06c88c9e130843"
checksum = "8bd5a652b6faf21496f2cfd88fc49989c8db0825d1f6746b1a71a6ede24a63ad"
dependencies = [
"arrayvec",
"bit-set",
"bitflags 2.6.0",
"cfg_aliases 0.1.1",
"codespan-reporting",
"hexf-parse",
"indexmap",
"log",
"num-traits",
"rustc-hash 1.1.0",
"spirv",
"termcolor",
@ -2213,7 +2229,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1"
dependencies = [
"malloc_buf",
"objc_exception",
]
[[package]]
@ -2430,15 +2445,6 @@ dependencies = [
"objc2-foundation",
]
[[package]]
name = "objc_exception"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad970fb455818ad6cba4c122ad012fae53ae8b4795f86378bce65e4f6bab2ca4"
dependencies = [
"cc",
]
[[package]]
name = "objc_id"
version = "0.1.1"
@ -2536,17 +2542,7 @@ checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99"
dependencies = [
"instant",
"lock_api",
"parking_lot_core 0.8.6",
]
[[package]]
name = "parking_lot"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
dependencies = [
"lock_api",
"parking_lot_core 0.9.10",
"parking_lot_core",
]
[[package]]
@ -2563,19 +2559,6 @@ dependencies = [
"winapi",
]
[[package]]
name = "parking_lot_core"
version = "0.9.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
dependencies = [
"cfg-if",
"libc",
"redox_syscall 0.5.3",
"smallvec",
"windows-targets 0.52.6",
]
[[package]]
name = "paste"
version = "1.0.15"
@ -3715,7 +3698,7 @@ checksum = "be0ecb0db480561e9a7642b5d3e4187c128914e58aa84330b9493e3eb68c5e7f"
dependencies = [
"futures",
"js-sys",
"parking_lot 0.11.2",
"parking_lot",
"pin-utils",
"wasm-bindgen",
"wasm-bindgen-futures",
@ -3878,17 +3861,17 @@ dependencies = [
[[package]]
name = "wgpu"
version = "0.19.4"
version = "22.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cbd7311dbd2abcfebaabf1841a2824ed7c8be443a0f29166e5d3c6a53a762c01"
checksum = "e1d1c4ba43f80542cf63a0a6ed3134629ae73e8ab51e4b765a67f3aa062eb433"
dependencies = [
"arrayvec",
"cfg-if",
"cfg_aliases 0.1.1",
"document-features",
"js-sys",
"log",
"naga",
"parking_lot 0.12.3",
"parking_lot",
"profiling",
"raw-window-handle",
"smallvec",
@ -3903,35 +3886,34 @@ dependencies = [
[[package]]
name = "wgpu-core"
version = "0.19.4"
version = "22.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28b94525fc99ba9e5c9a9e24764f2bc29bad0911a7446c12f446a8277369bf3a"
checksum = "0348c840d1051b8e86c3bcd31206080c5e71e5933dabd79be1ce732b0b2f089a"
dependencies = [
"arrayvec",
"bit-vec",
"bitflags 2.6.0",
"cfg_aliases 0.1.1",
"codespan-reporting",
"document-features",
"indexmap",
"log",
"naga",
"once_cell",
"parking_lot 0.12.3",
"parking_lot",
"profiling",
"raw-window-handle",
"rustc-hash 1.1.0",
"smallvec",
"thiserror",
"web-sys",
"wgpu-hal",
"wgpu-types",
]
[[package]]
name = "wgpu-hal"
version = "0.19.5"
version = "22.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfabcfc55fd86611a855816326b2d54c3b2fd7972c27ce414291562650552703"
checksum = "f6bbf4b4de8b2a83c0401d9e5ae0080a2792055f25859a02bf9be97952bbed4f"
dependencies = [
"android_system_properties",
"arrayvec",
@ -3951,14 +3933,14 @@ dependencies = [
"js-sys",
"khronos-egl",
"libc",
"libloading 0.8.5",
"libloading 0.7.4",
"log",
"metal",
"naga",
"ndk-sys 0.5.0+25.2.9519653",
"objc",
"once_cell",
"parking_lot 0.12.3",
"parking_lot",
"profiling",
"range-alloc",
"raw-window-handle",
@ -3974,9 +3956,9 @@ dependencies = [
[[package]]
name = "wgpu-types"
version = "0.19.2"
version = "22.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b671ff9fb03f78b46ff176494ee1ebe7d603393f42664be55b64dc8d53969805"
checksum = "bc9d91f0e2c4b51434dfa6db77846f2793149d8e73f800fa2e41f52b8eac3c5d"
dependencies = [
"bitflags 2.6.0",
"js-sys",

View File

@ -17,7 +17,7 @@ use chrono::{NaiveDate, Months, Utc, Days};
use std::path;
use iced::{
widget::{
checkbox, column, container, pane_grid::{self, PaneGrid}, text, Column, Container
checkbox, column, container, pane_grid::{self, PaneGrid}, Column, Container
}, Alignment, Element, Length, Task
};
@ -34,6 +34,7 @@ pub enum Message {
Resized(pane_grid::ResizeEvent),
UpdateEvents,
ToggleCalendar(usize),
ToggleShowOrganizer,
}
#[derive(PartialEq, Eq)]
@ -54,6 +55,7 @@ pub struct CalendarApp {
split_value: f32,
events: EventsCollection,
calendars: std::vec::Vec<CalendarFile>,
calendar_params: CalendarParams,
}
impl Default for CalendarApp {
@ -69,6 +71,7 @@ impl Default for CalendarApp {
split_value: 0.20,
events: EventsCollection::default(),
calendars: std::vec::Vec::new(),
calendar_params: CalendarParams::new(),
}
}
}
@ -139,6 +142,7 @@ impl CalendarApp {
}
return Task::done(Message::UpdateEvents)
},
Message::ToggleShowOrganizer => self.calendar_params.ev_show_organizer = ! self.calendar_params.ev_show_organizer,
}
Task::none()
}
@ -149,7 +153,7 @@ impl CalendarApp {
self.grid_state.close(sidebar_pane);
} else {
// no sidebar: split the main pane (calendar) and move the new pane to the left
if let Some((new_pane, split)) = self.grid_state.split(pane_grid::Axis::Vertical, self.main_pane, PaneGridState{pane_type: PaneType::Sidebar}) {
if let Some((new_pane, _split)) = self.grid_state.split(pane_grid::Axis::Vertical, self.main_pane, PaneGridState{pane_type: PaneType::Sidebar}) {
self.grid_state.move_to_edge(new_pane, pane_grid::Edge::Left);
let root = self.grid_state.layout();
if let pane_grid::Node::Split { id, axis: _, ratio: _, a: _, b: _ } = root {
@ -171,7 +175,7 @@ impl CalendarApp {
fn get_calendar_view(&self) -> CalendarView {
CalendarView::new(
self.controls.mode.unwrap_or(ViewMode::Year),
&CalendarParams::new(),
&self.calendar_params,
self.view_date,
&self.events)
}
@ -183,16 +187,22 @@ impl CalendarApp {
for calendar_file in &self.calendars {
col = col.push(
checkbox(calendar_file.get_name().as_str(), calendar_file.enabled)
.on_toggle(|enable| {Message::ToggleCalendar(calendar_file.index)})
.on_toggle(|_enable| {Message::ToggleCalendar(calendar_file.index)})
);
}
col = col.push("Options:");
col = col.push(
checkbox("show organizer", self.calendar_params.ev_show_organizer)
.on_toggle(|_enable| {Message::ToggleShowOrganizer})
);
container(col)
}
pub fn view(&self) -> Element<Message> {
#[cfg(feature = "tracing")]
tracepoints::calendar::view_entry();
let main_content = PaneGrid::new(&self.grid_state, |id, pane, is_maximized| {
let main_content = PaneGrid::new(&self.grid_state, |_id, pane, _is_maximized| {
match pane.pane_type {
PaneType::Calendar => pane_grid::Content::new(self.get_calendar_view()),
PaneType::Sidebar => pane_grid::Content::new(self.get_sidebar_view()),

View File

@ -1,9 +1,9 @@
use chrono::NaiveDate;
use std::default::Default;
use std::path::{self};
use std::string::String;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::vec::Vec;
use std::default::Default;
use std::string::String;
#[derive(Clone, Debug, PartialEq)]
pub enum EventType {
@ -11,12 +11,20 @@ pub enum EventType {
Background,
}
#[derive(Clone, Debug)]
pub struct Organizer {
pub email: String,
pub common_name: Option<String>,
}
#[derive(Clone, Debug)]
pub struct Event {
pub text: String,
pub ev_type: EventType,
pub begin: NaiveDate,
pub end: NaiveDate,
pub categories: Vec<String>,
pub organizer: Option<Organizer>,
}
impl Event {
@ -28,7 +36,7 @@ impl Event {
let mut day = first_day;
while day <= last_day {
if self.is_in_day(day) {
return true
return true;
}
day = day.succ_opt().unwrap();
}
@ -46,17 +54,30 @@ pub struct EventsCollection {
impl EventsCollection {
pub fn new() -> Self {
EventsCollection {
events: Vec::new(),
}
EventsCollection { events: Vec::new() }
}
pub fn clear(&mut self) {
self.events.clear();
}
pub fn clear(&mut self) {
self.events.clear();
}
pub fn create(self: &mut Self, begin: NaiveDate, end: NaiveDate, text: &str, ev_type: &EventType) {
self.events.push(Event {text: text.to_string(), ev_type: ev_type.clone(), begin, end});
pub fn create(
self: &mut Self,
begin: NaiveDate,
end: NaiveDate,
text: &str,
ev_type: &EventType,
categories: Vec<String>,
organizer: Option<Organizer>,
) {
self.events.push(Event {
text: text.to_string(),
ev_type: ev_type.clone(),
begin,
end,
categories,
organizer,
});
}
pub fn is_any_in_day(&self, day: NaiveDate, ev_type: &EventType) -> Option<Event> {
@ -120,34 +141,34 @@ impl Default for EventsCollection {
}
pub struct CalendarFile {
pub file_path: path::PathBuf,
pub name: String,
pub enabled: bool,
pub index: usize,
pub file_path: path::PathBuf,
pub name: String,
pub enabled: bool,
pub index: usize,
}
impl CalendarFile {
pub fn from_file(file_path: path::PathBuf) -> Self {
static COUNTER: AtomicUsize = AtomicUsize::new(0);
let name = if let Some(oss_name) = file_path.file_name() {
if let Some(str) = oss_name.to_str() {
String::from(str)
} else {
String::new()
}
} else {
String::new()
};
pub fn from_file(file_path: path::PathBuf) -> Self {
static COUNTER: AtomicUsize = AtomicUsize::new(0);
let name = if let Some(oss_name) = file_path.file_name() {
if let Some(str) = oss_name.to_str() {
String::from(str)
} else {
String::new()
}
} else {
String::new()
};
CalendarFile {
file_path,
name,
enabled: true,
index: COUNTER.fetch_add(1, Ordering::Relaxed),
}
}
CalendarFile {
file_path,
name,
enabled: true,
index: COUNTER.fetch_add(1, Ordering::Relaxed),
}
}
pub fn get_name(&self) -> &String {
&self.name
}
pub fn get_name(&self) -> &String {
&self.name
}
}

View File

@ -1,7 +1,7 @@
use icalendar;
use icalendar::{Component, DatePerhapsTime, CalendarDateTime, CalendarComponent};
use chrono::NaiveDate;
use crate::model::events::EventsCollection;
use crate::model::events::{EventsCollection, Organizer};
use std::fs;
use log::{warn, debug};
@ -24,11 +24,26 @@ fn as_date(cal_date: &DatePerhapsTime) -> NaiveDate {
fn create_event(events: &mut EventsCollection, event: &icalendar::Event, ev_type: &EventType) {
debug!(" calendar event: {:?}", event);
let event_property = event.property_value("CATEGORIES").unwrap_or("");
let event_organizer = event.properties().get("ORGANIZER");
let organizer = if let Some(property) = event_organizer {
Some(Organizer{
email: String::from(property.value()),
common_name: property.get_param_as("CN", |p| Some(String::from(p))),
})
} else {
Option::None
};
events.create(
as_date(&event.get_start().unwrap()),
as_date(&event.get_end().unwrap()).pred_opt().unwrap(),
event.get_summary().unwrap(),
ev_type);
ev_type,
event_property.split(',').map(String::from).collect(),
organizer,
);
}
pub fn load_calendar(calendar_path: &std::path::Path, events: &mut EventsCollection) {

View File

@ -12,6 +12,7 @@ use super::basics::CellGrid;
use super::row::CalendarRow;
use super::row::RowDay;
use crate::model::events::EventType;
use crate::model::events::Organizer;
use crate::model::events::{Event, EventsCollection};
use chrono::{
Datelike,
@ -73,6 +74,7 @@ pub struct CalendarParams {
ev_bg: Color,
ev_bg_alt: Color,
ev_fontsize: f32,
pub ev_show_organizer: bool,
}
impl CalendarParams {
@ -91,6 +93,7 @@ impl CalendarParams {
ev_bg: Color::from_rgb8(200, 245, 200),
ev_bg_alt: Color::from_rgb8(215, 215, 215), //Color::from_rgb8(200, 200, 250),
ev_fontsize: 14.0,
ev_show_organizer: true,
}
}
@ -232,9 +235,21 @@ fn render_events_in_row<Renderer>(
x: ev_bar.bounds.x + 1.0,
y: ev_bar.bounds.y,
};
let organizer_name = if params.ev_show_organizer {
if let Some(organizer) = &ev_bar.ev.organizer {
organizer.common_name.clone().unwrap_or(String::from("")) + ":"
} else {
String::from("")
}
} else {
String::from("")
};
let event_label = organizer_name + ev_bar.ev.text.as_str();
renderer.fill_text(
Text {
content: ev_bar.ev.text.as_str().into(),
content: event_label.into(),
bounds: ev_text_size,
size: params.ev_fontsize.into(),
line_height: LineHeight::default(),

View File

@ -8,7 +8,7 @@ pub struct CalendarRow {
pub enum RowDay {
InRange(NaiveDate),
NotInRange(NaiveDate),
NotInRange,
}
impl RowDay {
@ -16,7 +16,7 @@ impl RowDay {
if day >= row.begin && day < row.end {
RowDay::InRange(day)
} else {
RowDay::NotInRange(day)
RowDay::NotInRange
}
}
}