Make configuration file optional

This commit is contained in:
Gergely Polonkai 2022-05-21 06:57:20 +02:00
parent 98e5f3c06d
commit 418ab212ea
No known key found for this signature in database
GPG Key ID: 2D2885533B869ED4
2 changed files with 166 additions and 143 deletions

View File

@ -2,6 +2,20 @@
This is a Rust implementation of cinnamons [Seasonal Hours Clock](https://github.com/cinnamon-bun/seasonal-hours-clock), running as a native Wayland application. This is a Rust implementation of cinnamons [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 dont provide a configuration file, the day parts (day/night time and the golden/blue hours) wont be visible on the clock face.
## Features ## Features
### Seasonal hours! ### Seasonal hours!

View File

@ -48,7 +48,7 @@ impl fmt::Display for Season {
} }
} }
#[derive(Deserialize)] #[derive(Deserialize, Copy, Clone)]
struct Config { struct Config {
latitude: f64, latitude: f64,
longitude: 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) Path::new().set("class", "moon").set("d", path_data)
} }
fn gen_svg(config: &Config) -> Document { fn gen_svg(config: &Option<Config>) -> Document {
let local_timestamp = Local::now(); let local_timestamp = Local::now();
let utc_hour = local_timestamp.with_timezone(&Utc).time().hour(); let utc_hour = local_timestamp.with_timezone(&Utc).time().hour();
let local_hour = local_timestamp.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_radius = image_width as f32 * 0.071428571;
let moon_phase = moon_illumination.phase * 28.0; 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 local_hour_font_size = image_width as f32 * 0.02357;
let hour_name_font_size = image_width as f32 * 0.019109; let hour_name_font_size = image_width as f32 * 0.019109;
let utc_hour_font_size = image_width as f32 * 0.021462; 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("cy", image_width / 2)
.set("r", marker_radius); .set("r", marker_radius);
let golden_hour_path = get_range_path( let day_parts_group: Option<Group> = if config.is_some() {
image_width, let sun_times = suncalc::get_times(
marker_radius, unixtime,
"golden-hour", config.unwrap().latitude,
morning_golden_end, config.unwrap().longitude,
evening_golden_start, 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() let golden_hour_path = get_range_path(
.set("class", "sun") image_width,
.set("cx", image_width / 2) marker_radius,
.set("cy", image_width as f32 / 2.0 + outer_r / 2.0 + sun_radius) "golden-hour",
.set("r", sun_radius) morning_golden_end,
.set( evening_golden_start,
"transform",
format!(
"rotate({}, {}, {})",
time_to_degrees(local_time) - utc_rotation,
image_width / 2,
image_width / 2
),
); );
let blue_hour_path = get_range_path( let sun_disc = Circle::new()
image_width, .set("class", "sun")
marker_radius, .set("cx", image_width / 2)
"blue-hour", .set("cy", image_width as f32 / 2.0 + outer_r / 2.0 + sun_radius)
sunrise, // morning_blue_end .set("r", sun_radius)
sunset, // evening_blue_start .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() let nighttime_path = get_range_path(image_width, marker_radius, "night-time", dawn, dusk);
.set("class", "marker")
.set("cx", image_width / 2)
.set("cy", image_width / 2)
.set("r", marker_radius);
let noon_marker = Line::new() let marker_circle = Circle::new()
.set("class", "mid-marker") .set("class", "marker")
.set( .set("cx", image_width / 2)
"transform", .set("cy", image_width / 2)
format!( .set("r", marker_radius);
"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 midnight_marker = Line::new() let noon_marker = Line::new()
.set("class", "mid-marker") .set("class", "mid-marker")
.set( .set(
"transform", "transform",
format!( format!(
"rotate({}, {}, {})", "rotate({}, {}, {})",
time_to_degrees(midnight), time_to_degrees(noon),
image_width / 2, image_width / 2,
image_width / 2 image_width / 2
), ),
) )
.set("x1", image_width / 2) .set("x1", image_width / 2)
.set( .set(
"y1", "y1",
image_width as f32 / 2.0 + marker_radius - sun_radius as f32, image_width as f32 / 2.0 + marker_radius - sun_radius as f32,
) )
.set("x2", image_width / 2) .set("x2", image_width / 2)
.set("y2", image_width as f32 / 2.0 + marker_radius); .set("y2", image_width as f32 / 2.0 + marker_radius);
let day_parts_group = Group::new() let midnight_marker = Line::new()
.set("id", "day-parts") .set("class", "mid-marker")
.set( .set(
"transform", "transform",
format!( format!(
"rotate({}, {}, {})", "rotate({}, {}, {})",
utc_rotation, time_to_degrees(midnight),
image_width / 2, image_width / 2,
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) } else {
.add(golden_hour_path) None
.add(sun_disc) };
.add(blue_hour_path)
.add(nighttime_path)
.add(marker_circle)
.add(noon_marker)
.add(midnight_marker);
let moon_circle = Circle::new() let moon_circle = Circle::new()
.set("class", "moon-background") .set("class", "moon-background")
@ -588,7 +599,7 @@ fn gen_svg(config: &Config) -> Document {
.add(current_hour_name) .add(current_hour_name)
.add(current_time_text); .add(current_time_text);
Document::new() let mut document = Document::new()
.set("viewBox", (0i32, 0i32, 700i32, 700i32)) .set("viewBox", (0i32, 0i32, 700i32, 700i32))
.set("width", 700i32) .set("width", 700i32)
.set("height", 700i32) .set("height", 700i32)
@ -596,8 +607,13 @@ fn gen_svg(config: &Config) -> Document {
.add(stylesheet) .add(stylesheet)
.add(definitions) .add(definitions)
.add(border) .add(border)
.add(local_clock) .add(local_clock);
.add(day_parts_group)
if let Some(..) = day_parts_group {
document = document.add(day_parts_group.unwrap());
}
document
.add(seasonal_clock) .add(seasonal_clock)
.add(moon_group) .add(moon_group)
.add(dial) .add(dial)
@ -609,8 +625,13 @@ fn main() {
let config_path = xdg_dirs let config_path = xdg_dirs
.place_config_file("seasonal-clock.toml") .place_config_file("seasonal-clock.toml")
.expect("cannot create configuration directory"); .expect("cannot create configuration directory");
let data = fs::read_to_string(config_path).expect("Unable to read file"); let data: std::io::Result<String> = fs::read_to_string(config_path);
let config: CompleteConfig = toml::from_str(&data).unwrap(); let config: Option<Config> = 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) let (env, display, mut queue) = sctk::new_default_environment!(SeasonalClock, desktop)
.expect("Unable to connect to a Wayland compositor"); .expect("Unable to connect to a Wayland compositor");
@ -654,13 +675,7 @@ fn main() {
let mut dimensions = (700, 700); let mut dimensions = (700, 700);
if !env.get_shell().unwrap().needs_configure() { if !env.get_shell().unwrap().needs_configure() {
redraw( redraw(&mut pool, window.surface(), dimensions, &config).expect("Failed to draw");
&mut pool,
window.surface(),
dimensions,
&config.seasonal_clock,
)
.expect("Failed to draw");
window.refresh() window.refresh()
} }
@ -708,13 +723,7 @@ fn main() {
if need_redraw { if need_redraw {
need_redraw = false; need_redraw = false;
redraw( redraw(&mut pool, window.surface(), dimensions, &config).expect("Failed to draw")
&mut pool,
window.surface(),
dimensions,
&config.seasonal_clock,
)
.expect("Failed to draw")
} }
if let Err(e) = display.flush() { if let Err(e) = display.flush() {
@ -744,7 +753,7 @@ fn redraw(
pool: &mut AutoMemPool, pool: &mut AutoMemPool,
surface: &wl_surface::WlSurface, surface: &wl_surface::WlSurface,
(buf_x, buf_y): (u32, u32), (buf_x, buf_y): (u32, u32),
config: &Config, config: &Option<Config>,
) -> Result<(), ::std::io::Error> { ) -> Result<(), ::std::io::Error> {
let document = gen_svg(config); let document = gen_svg(config);