diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/gui/app.rs | 30 | ||||
-rw-r--r-- | src/gui/calendar.rs | 15 | ||||
-rw-r--r-- | src/gui/form/mod.rs | 245 | ||||
-rw-r--r-- | src/gui/form/repetition.rs | 2 | ||||
-rw-r--r-- | src/gui/mod.rs | 6 |
5 files changed, 157 insertions, 141 deletions
diff --git a/src/gui/app.rs b/src/gui/app.rs index aa8359a..ab3f9c0 100644 --- a/src/gui/app.rs +++ b/src/gui/app.rs @@ -3,8 +3,6 @@ use gtk4 as gtk; use anyhow::Result; use async_channel::Sender; use chrono::{Datelike, Duration, NaiveDate, Weekday}; -use gtk::glib::signal::Inhibit; -use gtk::prelude::*; use rusqlite::Connection; use std::rc::Rc; @@ -31,16 +29,6 @@ pub struct App { impl App { pub fn new(conn: Rc<Connection>, app: >k::Application, tx: Sender<Msg>) -> Result<Self> { - let window = Rc::new( - gtk::ApplicationWindow::builder() - .application(app) - .title("Calendrier") - .default_width(800) - .default_height(600) - .visible(true) - .build(), - ); - let today = chrono::offset::Local::now().naive_local().date(); // TODO: error handling let start_date = @@ -73,14 +61,16 @@ impl App { // notebook.append_page(&categories, Some(>k::Label::new(Some("Catégories")))); // window.set_child(Some(¬ebook)); - window.set_child(Some(&calendar)); - - window.connect_close_request(move |window| { - if let Some(application) = window.application() { - application.remove_window(window); - } - Inhibit(false) - }); + let window = Rc::new( + gtk::ApplicationWindow::builder() + .application(app) + .title("Calendrier") + .default_width(800) + .default_height(600) + .visible(true) + .child(&calendar) + .build(), + ); Ok(Self { conn, diff --git a/src/gui/calendar.rs b/src/gui/calendar.rs index 7a040f5..38f5d55 100644 --- a/src/gui/calendar.rs +++ b/src/gui/calendar.rs @@ -36,14 +36,14 @@ pub fn create( attach_days(tx.clone(), &grid, start_date, today, events, &repetitions, categories, default_color); let event_controller_key = gtk::EventControllerKey::new(); - event_controller_key.connect_key_released(glib::clone!(@strong tx => move |_, _, keycode, _| { + event_controller_key.connect_key_released(glib::clone!(#[strong] tx, move |_, _, keycode, _| { match keycode { 111 => update::send(tx.clone(), Msg::SelectPreviousWeek), // UP 116 => update::send(tx.clone(), Msg::SelectNextWeek), // DOWN _ => () } })); - grid.add_controller(&event_controller_key); + grid.add_controller(event_controller_key); grid } @@ -141,12 +141,12 @@ pub fn day_entry( vbox.add_css_class("g-Calendar__Day"); let gesture = gtk::GestureClick::new(); - gesture.connect_pressed(glib::clone!(@strong tx => move |_, n, _, _| { + gesture.connect_pressed(glib::clone!(#[strong] tx, move |_, n, _, _| { if n == 2 { update::send(tx.clone(), Msg::ShowAddForm { date }); } })); - vbox.add_controller(&gesture); + vbox.add_controller(gesture); if date == today { vbox.add_css_class("g-Calendar__Day--Today"); @@ -236,8 +236,7 @@ fn day_events( }} ", background_color - ) - .as_bytes(), + ).as_str() ); hbox.style_context() .add_provider(&provider, gtk::STYLE_PROVIDER_PRIORITY_APPLICATION); @@ -245,7 +244,7 @@ fn day_events( let gesture = gtk::GestureClick::new(); gesture.connect_pressed( - glib::clone!(@strong event, @strong tx => move |gesture, n, _, _| { + glib::clone!(#[strong] event, #[strong] tx, move |gesture, n, _, _| { gesture.set_state(gtk::EventSequenceState::Claimed); if n == 2 { if event.repetition.is_some() { @@ -256,7 +255,7 @@ fn day_events( } }), ); - hbox.add_controller(&gesture); + hbox.add_controller(gesture); let event_txt = &event.pprint(); let label = gtk::Label::builder() diff --git a/src/gui/form/mod.rs b/src/gui/form/mod.rs index 0b63dea..dbaf879 100644 --- a/src/gui/form/mod.rs +++ b/src/gui/form/mod.rs @@ -39,10 +39,16 @@ pub async fn repetition_dialog(app: &App, date: NaiveDate, event: &Event) { .build(); lines.append(&button); let tx = app.tx.clone(); - button.connect_clicked(glib::clone!(@weak dialog, @strong event => move |_| { - update::send(tx.clone(), Msg::ShowUpdateRepetitionForm { date, event_id: event.id }); - dialog.close() - })); + button.connect_clicked( + glib::clone!( + #[weak] dialog, + #[strong] event, + move |_| { + update::send(tx.clone(), Msg::ShowUpdateRepetitionForm { date, event_id: event.id }); + dialog.close() + } + ) + ); let button = gtk::Button::builder() .label("Toutes les occurences") @@ -50,20 +56,32 @@ pub async fn repetition_dialog(app: &App, date: NaiveDate, event: &Event) { .build(); lines.append(&button); let tx = app.tx.clone(); - button.connect_clicked(glib::clone!(@weak dialog, @strong event => move |_| { - update::send(tx.clone(), Msg::ShowUpdateForm { event_id: event.id }); - dialog.close() - })); + button.connect_clicked( + glib::clone!( + #[weak] dialog, + #[strong] event, + move |_| { + update::send(tx.clone(), Msg::ShowUpdateForm { event_id: event.id }); + dialog.close() + } + ) + ); let button = gtk::Button::builder() .label("À partir de cette occurence") .build(); lines.append(&button); let tx = app.tx.clone(); - button.connect_clicked(glib::clone!(@weak dialog, @strong event => move |_| { - update::send(tx.clone(), Msg::ShowUpdateFromOccurence { date, event_id: event.id }); - dialog.close() - })); + button.connect_clicked( + glib::clone!( + #[weak] dialog, + #[strong] event, + move |_| { + update::send(tx.clone(), Msg::ShowUpdateFromOccurence { date, event_id: event.id }); + dialog.close() + } + ) + ); dialog.run_future().await; } @@ -193,90 +211,97 @@ pub async fn show(app: &App, target: Target) { let conn = app.conn.clone(); let tx = app.tx.clone(); let categories = app.categories.clone(); - button.connect_clicked(glib::clone!(@weak dialog, @strong target, @strong event, @strong categories => move |_| { - let removed_occurences = match &target { - Target::Update { event, .. } => { - event.repetition.as_ref().map(|r| r.removed_occurences.clone()).unwrap_or_default() - }, - _ => HashSet::new(), - }; - match repetition::validate(&repetition_model, removed_occurences) { - Ok(repetition) => { - let id = match &target { - Target::Update {event} => event.id, - _ => Uuid::new_v4(), + button.connect_clicked( + glib::clone!( + #[weak] dialog, + #[strong] target, + #[strong] categories, + move |_| { + let removed_occurences = match &target { + Target::Update { event, .. } => { + event.repetition.as_ref().map(|r| r.removed_occurences.clone()).unwrap_or_default() + }, + _ => HashSet::new(), }; - - // Find category id from selected id - let category = categories.iter().find(|c| c.name == dropdown_categories[category_dropdown.selected() as usize]).map(|c| c.id); - - match event::validate(id, date.buffer().text(), name.buffer().text(), start.buffer().text(), end.buffer().text(), repetition, category) { - Some(new) => { - match &target { - Target::New {..} => { - match db::events::insert(&conn, &new) { - Ok(_) => { - update::send(tx.clone(), Msg::AddEvent { new }); - dialog.close() - }, - Err(err) => eprintln!("Error when inserting event: {}", err) - } - } - Target::Update {event} => { - match db::events::update(&conn, &new) { - Ok(_) => { - update::send(tx.clone(), Msg::UpdateEvent { old: event.clone(), new }); - dialog.close() - }, - Err(err) => eprintln!("Error when updating event: {}", err) - } - } - Target::UpdateRepetition { event, date } => { - // TODO: improve intermediate error state - match delete_repetition_occurence(&conn, event, *date) { - Ok(occurence) => { - match db::events::insert(&conn, &new) { - Ok(_) => { - update::send(tx.clone(), Msg::UpdateEventOccurence { - event: event.clone(), - occurence, - date: *date, - new - }) - } - Err(err) => eprintln!("Error when updating repetition: {}", err) - }; - dialog.close() - }, - Err(err) => eprintln!("Error when updating repetition: {}", err) - } - } - Target::UpdateFromOccurence { date, event } => { - match update_repetition_until(&conn, *date - Duration::days(1), event) { - Ok(updated) => { + match repetition::validate(&repetition_model, removed_occurences) { + Ok(repetition) => { + let id = match &target { + Target::Update {event} => event.id, + _ => Uuid::new_v4(), + }; + + // Find category id from selected id + let category = categories.iter().find(|c| c.name == dropdown_categories[category_dropdown.selected() as usize]).map(|c| c.id); + + match event::validate(id, date.buffer().text().to_string(), name.buffer().text().to_string(), start.buffer().text().to_string(), end.buffer().text().to_string(), repetition, category) { + Some(new) => { + match &target { + Target::New {..} => { match db::events::insert(&conn, &new) { Ok(_) => { - update::send(tx.clone(), Msg::UpdateRepeatedFrom { - old: event.clone(), - updated, - new - }); + update::send(tx.clone(), Msg::AddEvent { new }); dialog.close() }, Err(err) => eprintln!("Error when inserting event: {}", err) } - }, - Err(err) => eprintln!("Error when updating event: {}", err) + } + Target::Update {event} => { + match db::events::update(&conn, &new) { + Ok(_) => { + update::send(tx.clone(), Msg::UpdateEvent { old: event.clone(), new }); + dialog.close() + }, + Err(err) => eprintln!("Error when updating event: {}", err) + } + } + Target::UpdateRepetition { event, date } => { + // TODO: improve intermediate error state + match delete_repetition_occurence(&conn, event, *date) { + Ok(occurence) => { + match db::events::insert(&conn, &new) { + Ok(_) => { + update::send(tx.clone(), Msg::UpdateEventOccurence { + event: event.clone(), + occurence, + date: *date, + new + }) + } + Err(err) => eprintln!("Error when updating repetition: {}", err) + }; + dialog.close() + }, + Err(err) => eprintln!("Error when updating repetition: {}", err) + } + } + Target::UpdateFromOccurence { date, event } => { + match update_repetition_until(&conn, *date - Duration::days(1), event) { + Ok(updated) => { + match db::events::insert(&conn, &new) { + Ok(_) => { + update::send(tx.clone(), Msg::UpdateRepeatedFrom { + old: event.clone(), + updated, + new + }); + dialog.close() + }, + Err(err) => eprintln!("Error when inserting event: {}", err) + } + }, + Err(err) => eprintln!("Error when updating event: {}", err) + } + } } } + None => eprintln!("Event is not valid.") } - } - None => eprintln!("Event is not valid.") + }, + Err(message) => eprintln!("{}", message) } - }, - Err(message) => eprintln!("{}", message) - } - })); + } + ) + ); if let Some(event) = event { let label = match target { @@ -288,37 +313,39 @@ pub async fn show(app: &App, target: Target) { lines.append(&button); let conn = app.conn.clone(); let tx = app.tx.clone(); - button.connect_clicked(glib::clone!(@weak dialog => move |_| { - match target { - Target::UpdateRepetition { date, .. } => { - match delete_repetition_occurence(&conn, &event, date) { - Ok(occurence) => { - update::send(tx.clone(), Msg::DeleteOccurence { event: event.clone(), date, occurence }); - dialog.close() + button.connect_clicked( + glib::clone!(#[weak] dialog, move |_| { + match target { + Target::UpdateRepetition { date, .. } => { + match delete_repetition_occurence(&conn, &event, date) { + Ok(occurence) => { + update::send(tx.clone(), Msg::DeleteOccurence { event: event.clone(), date, occurence }); + dialog.close() + } + Err(err) => { + eprintln!("{:?}", err); + } } - Err(err) => { - eprintln!("{:?}", err); + } + Target::UpdateFromOccurence { date, .. } => { + match update_repetition_until(&conn, date - Duration::days(1), &event) { + Ok(updated) => { + update::send(tx.clone(), Msg::UpdateEvent { old: event.clone(), new: updated }); + dialog.close() + }, + Err(err) => eprintln!("Error when updating event: {}", err) } } - } - Target::UpdateFromOccurence { date, .. } => { - match update_repetition_until(&conn, date - Duration::days(1), &event) { - Ok(updated) => { - update::send(tx.clone(), Msg::UpdateEvent { old: event.clone(), new: updated }); + _ => { + let operation = db::events::delete(&conn, &event.id); + if operation.is_ok() { + update::send(tx.clone(), Msg::DeleteEvent { event: event.clone() }); dialog.close() - }, - Err(err) => eprintln!("Error when updating event: {}", err) - } - } - _ => { - let operation = db::events::delete(&conn, &event.id); - if operation.is_ok() { - update::send(tx.clone(), Msg::DeleteEvent { event: event.clone() }); - dialog.close() + } } } } - })); + )); } dialog.run_future().await; diff --git a/src/gui/form/repetition.rs b/src/gui/form/repetition.rs index a83aea5..ca8379a 100644 --- a/src/gui/form/repetition.rs +++ b/src/gui/form/repetition.rs @@ -197,7 +197,7 @@ pub fn validate( // Check until let until = (if frequency.is_some() { - match validation::non_empty(model.until.buffer().text()) { + match validation::non_empty(model.until.buffer().text().to_string()) { Some(until) => match NaiveDate::parse_from_str(&until, event::DATE_FORMAT) { Ok(until) => Ok(Some(until)), Err(_) => Err(format!("Can’t parse date from {}", until)), diff --git a/src/gui/mod.rs b/src/gui/mod.rs index e7f457f..078c4b2 100644 --- a/src/gui/mod.rs +++ b/src/gui/mod.rs @@ -7,7 +7,7 @@ mod utils; use gtk4 as gtk; use gtk::gdk::Display; -use gtk::prelude::*; +use gtk4::prelude::{ApplicationExt, ApplicationExtManual}; use rusqlite::Connection; use std::rc::Rc; @@ -35,8 +35,8 @@ fn build_ui(conn: Rc<Connection>, app: >k::Application) { fn load_style() { let provider = gtk::CssProvider::new(); - provider.load_from_data(include_bytes!("style.css")); - gtk::StyleContext::add_provider_for_display( + provider.load_from_data(include_str!("style.css")); + gtk::style_context_add_provider_for_display( &Display::default().expect("Error initializing gtk css provider."), &provider, gtk::STYLE_PROVIDER_PRIORITY_APPLICATION, |