Make configuration file optional
This commit is contained in:
parent
98e5f3c06d
commit
418ab212ea
14
README.md
14
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.
|
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
|
## Features
|
||||||
|
|
||||||
### Seasonal hours!
|
### Seasonal hours!
|
||||||
|
295
src/main.rs
295
src/main.rs
@ -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);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user