diff options
| author | Joris | 2024-01-20 22:08:44 +0100 | 
|---|---|---|
| committer | Joris | 2024-01-20 22:08:44 +0100 | 
| commit | 36cd29b459bb41bff1cf6d079fd30100bd89cec1 (patch) | |
| tree | 1cd3c0b64ab7dd1c35c580e47cdb5fe3b92f8532 | |
| parent | 44a32d874cb0540aede1adcf3e6ef9bd7a928c90 (diff) | |
Allow to specify week of month for repetition
| -rw-r--r-- | src/gui/form/repetition.rs | 67 | ||||
| -rw-r--r-- | src/model/repetition.rs | 18 | 
2 files changed, 59 insertions, 26 deletions
| diff --git a/src/gui/form/repetition.rs b/src/gui/form/repetition.rs index 4da65ac..a83aea5 100644 --- a/src/gui/form/repetition.rs +++ b/src/gui/form/repetition.rs @@ -12,11 +12,17 @@ use crate::model::{  use crate::validation;  static WEEKDAYS_STR: [&str; 7] = [ -    "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi", "Dimanche", +    "lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi", "dimanche",  ];  static WEEKDAYS: [Weekday; 7] = [Mon, Tue, Wed, Thu, Fri, Sat, Sun]; +static WEEKS_STR: [&str; 4] = [ +    "1er", "2ème", "3ème", "4ème" +]; + +static WEEKS: [u8; 4] = [1, 2, 3, 4]; +  pub struct Model {      pub view: gtk::Box,      no_radio: gtk::CheckButton, @@ -24,8 +30,9 @@ pub struct Model {      day_interval_entry: gtk::Entry,      monthly_radio: gtk::CheckButton,      monthly_entry: gtk::Entry, -    first_day_radio: gtk::CheckButton, -    first_day_dropdown: gtk::DropDown, +    day_of_month_radio: gtk::CheckButton, +    week_of_month: gtk::DropDown, +    day_of_week: gtk::DropDown,      yearly_radio: gtk::CheckButton,      until: gtk::Entry,  } @@ -70,18 +77,19 @@ pub fn view(repetition: Option<&Repetition>) -> Model {          radio_input(&no_radio, !default.is_empty(), &monthly_entry, "Mensuel");      view.append(&monthly_box); -    let (active, default) = match frequency { +    let (active, default_week, default_day) = match frequency {          Some(Frequency::Monthly { -            day: DayOfMonth::Weekday { weekday }, -        }) => (true, weekday), -        _ => (false, Mon), +            day: DayOfMonth::Weekday { week, day }, +        }) => (true, week, day), +        _ => (false, 1, Mon),      }; -    let first_day_dropdown = gtk::DropDown::from_strings(&WEEKDAYS_STR); -    first_day_dropdown -        .set_selected(WEEKDAYS.iter().position(|d| d == &default).unwrap_or(0) as u32); -    let (first_day_of_month_box, first_day_radio) = -        radio_input(&no_radio, active, &first_day_dropdown, "1er jour du mois"); -    view.append(&first_day_of_month_box); +    let week_of_month = gtk::DropDown::from_strings(&WEEKS_STR); +    week_of_month.set_selected(WEEKS.iter().position(|d| d == &default_week).unwrap_or(0) as u32); +    let day_of_week = gtk::DropDown::from_strings(&WEEKDAYS_STR); +    day_of_week.set_selected(WEEKDAYS.iter().position(|d| d == &default_day).unwrap_or(0) as u32); +    let (day_of_month_box, day_of_month_radio) = +        radio_day_of_month(&no_radio, active, &week_of_month, &day_of_week); +    view.append(&day_of_month_box);      let yearly_radio = gtk::CheckButton::builder()          .group(&no_radio) @@ -106,8 +114,9 @@ pub fn view(repetition: Option<&Repetition>) -> Model {          day_interval_entry,          monthly_radio,          monthly_entry, -        first_day_radio, -        first_day_dropdown, +        day_of_month_radio, +        week_of_month, +        day_of_week,          yearly_radio,          until,      } @@ -131,6 +140,27 @@ fn radio_input(      (radio_box, radio)  } +fn radio_day_of_month( +    radio_group: &impl IsA<gtk::CheckButton>, +    active: bool, +    number: &impl IsA<gtk::Widget>, +    day: &impl IsA<gtk::Widget>, +) -> (gtk::Box, gtk::CheckButton) { +    let radio_box = gtk::Box::builder().build(); +    let radio = gtk::CheckButton::builder() +        .group(radio_group) +        .active(active) +        .build(); +    radio_box.append(&radio); +    number.add_css_class("g-Form__RadioInput"); +    radio_box.append(number); +    day.add_css_class("g-Form__RadioInput"); +    radio_box.append(day); +    let text = gtk::Text::builder().text("du mois.").build(); +    radio_box.append(&text); +    (radio_box, radio) +} +  fn label(text: &str) -> gtk::Label {      gtk::Label::builder()          .label(text) @@ -153,10 +183,11 @@ pub fn validate(          Ok(Some(Frequency::Monthly {              day: DayOfMonth::Day { day },          })) -    } else if model.first_day_radio.is_active() { -        let weekday = WEEKDAYS[model.first_day_dropdown.selected() as usize]; +    } else if model.day_of_month_radio.is_active() { +        let week = WEEKS[model.week_of_month.selected() as usize]; +        let day = WEEKDAYS[model.day_of_week.selected() as usize];          Ok(Some(Frequency::Monthly { -            day: DayOfMonth::Weekday { weekday }, +            day: DayOfMonth::Weekday { week, day },          }))      } else if model.yearly_radio.is_active() {          Ok(Some(Frequency::Yearly)) diff --git a/src/model/repetition.rs b/src/model/repetition.rs index 360cf5f..07fc4d4 100644 --- a/src/model/repetition.rs +++ b/src/model/repetition.rs @@ -19,7 +19,7 @@ pub enum Frequency {  #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]  pub enum DayOfMonth {      Day { day: u8 }, -    Weekday { weekday: Weekday }, +    Weekday { week: u8, day: Weekday },  }  pub fn validate_period(str: &str) -> Result<u32, String> { @@ -74,10 +74,10 @@ impl Repetition {                  None => vec![],              },              Frequency::Monthly { -                day: DayOfMonth::Weekday { weekday }, +                day: DayOfMonth::Weekday { week, day },              } => repeat( -                first_weekday_of_month(event, weekday), -                Box::new(|d| first_weekday_of_month(next_month(d), weekday)), +                day_of_month(event, week, day), +                Box::new(|d| day_of_month(next_month(d), week, day)),              ),              Frequency::Yearly => repeat(                  // TODO: error handling @@ -97,9 +97,9 @@ impl Repetition {      }  } -fn first_weekday_of_month(date: NaiveDate, weekday: Weekday) -> NaiveDate { +fn day_of_month(date: NaiveDate, week: u8, day: Weekday) -> NaiveDate {      // TODO: error handling -    NaiveDate::from_weekday_of_month_opt(date.year(), date.month(), weekday, 1).unwrap() +    NaiveDate::from_weekday_of_month_opt(date.year(), date.month(), day, week).unwrap()  }  fn next_month(date: NaiveDate) -> NaiveDate { @@ -177,7 +177,8 @@ mod tests {      fn weekday_of_month() {          let repetition = from_freq(Frequency::Monthly {              day: DayOfMonth::Weekday { -                weekday: Weekday::Tue, +                week: 1, +                day: Weekday::Tue,              },          });          assert_eq!( @@ -228,7 +229,8 @@ mod tests {          let repetition = Repetition {              frequency: Frequency::Monthly {                  day: DayOfMonth::Weekday { -                    weekday: Weekday::Fri, +                    week: 1, +                    day: Weekday::Fri,                  },              },              removed_occurences: HashSet::from([1, 2, 3]), | 
