From 418ab212eaf2990fb62b96c827fcc50951895dba Mon Sep 17 00:00:00 2001 From: Gergely Polonkai Date: Sat, 21 May 2022 06:57:20 +0200 Subject: [PATCH] Make configuration file optional --- README.md | 14 +++ src/main.rs | 295 +++++++++++++++++++++++++++------------------------- 2 files changed, 166 insertions(+), 143 deletions(-) diff --git a/README.md b/README.md index f141725..b07977c 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,20 @@ This is a Rust implementation of cinnamon’s [Seasonal Hours Clock](https://github.com/cinnamon-bun/seasonal-hours-clock), running as a native Wayland application. +## Configuration + +Create a file `$XDG_CONFIG_HOME/seasonal-clock.toml` (where `$XDG_CONFIG_HOME` is `~/.config` on Linux systems) with the following content: + +``` +[seasonal-clock] +latitude = 47.655 +longitude = 19.286 +``` + +(this is a location around Hungary; you may want to change these.) + +If you don’t provide a configuration file, the day parts (day/night time and the golden/blue hours) won’t be visible on the clock face. + ## Features ### Seasonal hours! diff --git a/src/main.rs b/src/main.rs index 8024ef8..439bd4d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -48,7 +48,7 @@ impl fmt::Display for Season { } } -#[derive(Deserialize)] +#[derive(Deserialize, Copy, Clone)] struct Config { latitude: f64, longitude: f64, @@ -256,7 +256,7 @@ fn get_moon_path(image_width: u32, radius: f32, moon_phase: f64) -> Path { Path::new().set("class", "moon").set("d", path_data) } -fn gen_svg(config: &Config) -> Document { +fn gen_svg(config: &Option) -> Document { let local_timestamp = Local::now(); let utc_hour = local_timestamp.with_timezone(&Utc).time().hour(); let local_hour = local_timestamp.time().hour(); @@ -276,40 +276,6 @@ fn gen_svg(config: &Config) -> Document { let moon_radius = image_width as f32 * 0.071428571; let moon_phase = moon_illumination.phase * 28.0; - let sun_times = suncalc::get_times(unixtime, config.latitude, config.longitude, None); - let noon = Utc - .timestamp_millis(sun_times.solar_noon.0) - .time() - .num_seconds_from_midnight() as i32; - let midnight = Utc - .timestamp_millis(sun_times.nadir.0) - .time() - .num_seconds_from_midnight() as i32; - let morning_golden_end = Utc - .timestamp_millis(sun_times.golden_hour_end.0) - .time() - .num_seconds_from_midnight() as i32; - let evening_golden_start = Utc - .timestamp_millis(sun_times.golden_hour.0) - .time() - .num_seconds_from_midnight() as i32; - let sunrise = Utc - .timestamp_millis(sun_times.sunrise.0) - .time() - .num_seconds_from_midnight() as i32; - let sunset = Utc - .timestamp_millis(sun_times.sunset.0) - .time() - .num_seconds_from_midnight() as i32; - let dawn = Utc - .timestamp_millis(sun_times.dawn.0) - .time() - .num_seconds_from_midnight() as i32; - let dusk = Utc - .timestamp_millis(sun_times.dusk.0) - .time() - .num_seconds_from_midnight() as i32; - let local_hour_font_size = image_width as f32 * 0.02357; let hour_name_font_size = image_width as f32 * 0.019109; let utc_hour_font_size = image_width as f32 * 0.021462; @@ -406,102 +372,147 @@ fn gen_svg(config: &Config) -> Document { .set("cy", image_width / 2) .set("r", marker_radius); - let golden_hour_path = get_range_path( - image_width, - marker_radius, - "golden-hour", - morning_golden_end, - evening_golden_start, - ); + let day_parts_group: Option = if config.is_some() { + let sun_times = suncalc::get_times( + unixtime, + config.unwrap().latitude, + config.unwrap().longitude, + None, + ); + let noon = Utc + .timestamp_millis(sun_times.solar_noon.0) + .time() + .num_seconds_from_midnight() as i32; + let midnight = Utc + .timestamp_millis(sun_times.nadir.0) + .time() + .num_seconds_from_midnight() as i32; + let morning_golden_end = Utc + .timestamp_millis(sun_times.golden_hour_end.0) + .time() + .num_seconds_from_midnight() as i32; + let evening_golden_start = Utc + .timestamp_millis(sun_times.golden_hour.0) + .time() + .num_seconds_from_midnight() as i32; + let sunrise = Utc + .timestamp_millis(sun_times.sunrise.0) + .time() + .num_seconds_from_midnight() as i32; + let sunset = Utc + .timestamp_millis(sun_times.sunset.0) + .time() + .num_seconds_from_midnight() as i32; + let dawn = Utc + .timestamp_millis(sun_times.dawn.0) + .time() + .num_seconds_from_midnight() as i32; + let dusk = Utc + .timestamp_millis(sun_times.dusk.0) + .time() + .num_seconds_from_midnight() as i32; - let sun_disc = Circle::new() - .set("class", "sun") - .set("cx", image_width / 2) - .set("cy", image_width as f32 / 2.0 + outer_r / 2.0 + sun_radius) - .set("r", sun_radius) - .set( - "transform", - format!( - "rotate({}, {}, {})", - time_to_degrees(local_time) - utc_rotation, - image_width / 2, - image_width / 2 - ), + let golden_hour_path = get_range_path( + image_width, + marker_radius, + "golden-hour", + morning_golden_end, + evening_golden_start, ); - let blue_hour_path = get_range_path( - image_width, - marker_radius, - "blue-hour", - sunrise, // morning_blue_end - sunset, // evening_blue_start - ); + let sun_disc = Circle::new() + .set("class", "sun") + .set("cx", image_width / 2) + .set("cy", image_width as f32 / 2.0 + outer_r / 2.0 + sun_radius) + .set("r", sun_radius) + .set( + "transform", + format!( + "rotate({}, {}, {})", + time_to_degrees(local_time) - utc_rotation, + image_width / 2, + image_width / 2 + ), + ); - let nighttime_path = get_range_path(image_width, marker_radius, "night-time", dawn, dusk); + let blue_hour_path = get_range_path( + image_width, + marker_radius, + "blue-hour", + sunrise, // morning_blue_end + sunset, // evening_blue_start + ); - let marker_circle = Circle::new() - .set("class", "marker") - .set("cx", image_width / 2) - .set("cy", image_width / 2) - .set("r", marker_radius); + let nighttime_path = get_range_path(image_width, marker_radius, "night-time", dawn, dusk); - let noon_marker = Line::new() - .set("class", "mid-marker") - .set( - "transform", - format!( - "rotate({}, {}, {})", - time_to_degrees(noon), - image_width / 2, - image_width / 2 - ), - ) - .set("x1", image_width / 2) - .set( - "y1", - image_width as f32 / 2.0 + marker_radius - sun_radius as f32, - ) - .set("x2", image_width / 2) - .set("y2", image_width as f32 / 2.0 + marker_radius); + let marker_circle = Circle::new() + .set("class", "marker") + .set("cx", image_width / 2) + .set("cy", image_width / 2) + .set("r", marker_radius); - let midnight_marker = Line::new() - .set("class", "mid-marker") - .set( - "transform", - format!( - "rotate({}, {}, {})", - time_to_degrees(midnight), - image_width / 2, - image_width / 2 - ), - ) - .set("x1", image_width / 2) - .set( - "y1", - image_width as f32 / 2.0 + marker_radius - sun_radius as f32, - ) - .set("x2", image_width / 2) - .set("y2", image_width as f32 / 2.0 + marker_radius); + let noon_marker = Line::new() + .set("class", "mid-marker") + .set( + "transform", + format!( + "rotate({}, {}, {})", + time_to_degrees(noon), + image_width / 2, + image_width / 2 + ), + ) + .set("x1", image_width / 2) + .set( + "y1", + image_width as f32 / 2.0 + marker_radius - sun_radius as f32, + ) + .set("x2", image_width / 2) + .set("y2", image_width as f32 / 2.0 + marker_radius); - let day_parts_group = Group::new() - .set("id", "day-parts") - .set( - "transform", - format!( - "rotate({}, {}, {})", - utc_rotation, - image_width / 2, - image_width / 2 - ), + let midnight_marker = Line::new() + .set("class", "mid-marker") + .set( + "transform", + format!( + "rotate({}, {}, {})", + time_to_degrees(midnight), + image_width / 2, + image_width / 2 + ), + ) + .set("x1", image_width / 2) + .set( + "y1", + image_width as f32 / 2.0 + marker_radius - sun_radius as f32, + ) + .set("x2", image_width / 2) + .set("y2", image_width as f32 / 2.0 + marker_radius); + + Some( + Group::new() + .set("id", "day-parts") + .set( + "transform", + format!( + "rotate({}, {}, {})", + utc_rotation, + image_width / 2, + image_width / 2 + ), + ) + .add(daytime_circle) + .add(golden_hour_path) + .add(sun_disc) + .add(blue_hour_path) + .add(nighttime_path) + .add(marker_circle) + .add(noon_marker) + .add(midnight_marker), ) - .add(daytime_circle) - .add(golden_hour_path) - .add(sun_disc) - .add(blue_hour_path) - .add(nighttime_path) - .add(marker_circle) - .add(noon_marker) - .add(midnight_marker); + } else { + None + }; let moon_circle = Circle::new() .set("class", "moon-background") @@ -588,7 +599,7 @@ fn gen_svg(config: &Config) -> Document { .add(current_hour_name) .add(current_time_text); - Document::new() + let mut document = Document::new() .set("viewBox", (0i32, 0i32, 700i32, 700i32)) .set("width", 700i32) .set("height", 700i32) @@ -596,8 +607,13 @@ fn gen_svg(config: &Config) -> Document { .add(stylesheet) .add(definitions) .add(border) - .add(local_clock) - .add(day_parts_group) + .add(local_clock); + + if let Some(..) = day_parts_group { + document = document.add(day_parts_group.unwrap()); + } + + document .add(seasonal_clock) .add(moon_group) .add(dial) @@ -609,8 +625,13 @@ fn main() { let config_path = xdg_dirs .place_config_file("seasonal-clock.toml") .expect("cannot create configuration directory"); - let data = fs::read_to_string(config_path).expect("Unable to read file"); - let config: CompleteConfig = toml::from_str(&data).unwrap(); + let data: std::io::Result = fs::read_to_string(config_path); + let config: Option = if let Ok(..) = data { + let complete_config: CompleteConfig = toml::from_str(&data.unwrap()).unwrap(); + Some(complete_config.seasonal_clock) + } else { + None + }; let (env, display, mut queue) = sctk::new_default_environment!(SeasonalClock, desktop) .expect("Unable to connect to a Wayland compositor"); @@ -654,13 +675,7 @@ fn main() { let mut dimensions = (700, 700); if !env.get_shell().unwrap().needs_configure() { - redraw( - &mut pool, - window.surface(), - dimensions, - &config.seasonal_clock, - ) - .expect("Failed to draw"); + redraw(&mut pool, window.surface(), dimensions, &config).expect("Failed to draw"); window.refresh() } @@ -708,13 +723,7 @@ fn main() { if need_redraw { need_redraw = false; - redraw( - &mut pool, - window.surface(), - dimensions, - &config.seasonal_clock, - ) - .expect("Failed to draw") + redraw(&mut pool, window.surface(), dimensions, &config).expect("Failed to draw") } if let Err(e) = display.flush() { @@ -744,7 +753,7 @@ fn redraw( pool: &mut AutoMemPool, surface: &wl_surface::WlSurface, (buf_x, buf_y): (u32, u32), - config: &Config, + config: &Option, ) -> Result<(), ::std::io::Error> { let document = gen_svg(config);