aboutsummaryrefslogtreecommitdiff
path: root/src/gui
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/app.rs30
-rw-r--r--src/gui/calendar.rs15
-rw-r--r--src/gui/form/mod.rs245
-rw-r--r--src/gui/form/repetition.rs2
-rw-r--r--src/gui/mod.rs6
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: &gtk::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(&gtk::Label::new(Some("Catégories"))));
// window.set_child(Some(&notebook));
- 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: &gtk::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,