Add simple (if ugly) settings dialog
This commit is contained in:
@ -1,8 +1,15 @@
|
||||
use anyhow::anyhow;
|
||||
use std::{fs::File, io::Read, path::PathBuf, time::Duration};
|
||||
use std::{fmt, fs::{self, File}, io::{Read, Write}, path::PathBuf, time::Duration};
|
||||
use toml::Value;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
const CONFIG_FILE_RELATIVE_PATH: &str = "bscreensaver/bscreensaver.toml";
|
||||
|
||||
const LOCK_TIMEOUT: &str = "lock-timeout";
|
||||
const BLANK_BEFORE_LOCKING: &str = "blank-before-locking";
|
||||
const DIALOG_BACKEND: &str = "dialog-backend";
|
||||
const NEW_LOGIN_COMMAND: &str = "new-login-command";
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum DialogBackend {
|
||||
Gtk3,
|
||||
}
|
||||
@ -13,6 +20,20 @@ impl DialogBackend {
|
||||
Self::Gtk3 => "bscreensaver-dialog-gtk3",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn display_name(&self) -> &str {
|
||||
match self {
|
||||
Self::Gtk3 => "GTK3",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for DialogBackend {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::Gtk3 => write!(f, "gtk3"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&str> for DialogBackend {
|
||||
@ -25,7 +46,7 @@ impl TryFrom<&str> for DialogBackend {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct Configuration {
|
||||
pub lock_timeout: Duration,
|
||||
pub blank_before_locking: Duration,
|
||||
@ -38,7 +59,7 @@ impl Configuration {
|
||||
use humantime::parse_duration;
|
||||
|
||||
let config_tomls = xdg::BaseDirectories::new()?
|
||||
.find_config_files("bscreensaver/bscreensaver.toml")
|
||||
.find_config_files(CONFIG_FILE_RELATIVE_PATH)
|
||||
.map(|config_path| parse_config_toml(&config_path))
|
||||
.collect::<Result<Vec<Value>, _>>()?;
|
||||
|
||||
@ -69,16 +90,30 @@ impl Configuration {
|
||||
Ok(config)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_config_toml(config_path: &PathBuf) -> anyhow::Result<Value> {
|
||||
let mut f = File::open(config_path)?;
|
||||
let mut config = String::new();
|
||||
f.read_to_string(&mut config)?;
|
||||
drop(f);
|
||||
pub fn save(&self) -> anyhow::Result<()> {
|
||||
use humantime::format_duration;
|
||||
use toml::map::Map;
|
||||
|
||||
let config_toml = config.parse::<Value>()?;
|
||||
Ok(config_toml)
|
||||
let mut config_map = Map::new();
|
||||
config_map.insert(LOCK_TIMEOUT.to_string(), Value::String(format_duration(self.lock_timeout).to_string()));
|
||||
config_map.insert(BLANK_BEFORE_LOCKING.to_string(), Value::String(format_duration(self.blank_before_locking).to_string()));
|
||||
config_map.insert(DIALOG_BACKEND.to_string(), Value::String(self.dialog_backend.to_string()));
|
||||
if let Some(new_login_command) = &self.new_login_command {
|
||||
config_map.insert(NEW_LOGIN_COMMAND.to_string(), Value::String(new_login_command.clone()));
|
||||
}
|
||||
|
||||
let config_path = xdg::BaseDirectories::new()?.place_config_file(CONFIG_FILE_RELATIVE_PATH)?;
|
||||
let mut tmp_filename = config_path.file_name().unwrap().to_os_string();
|
||||
tmp_filename.push(".new");
|
||||
let tmp_path = config_path.with_file_name(tmp_filename);
|
||||
let mut f = File::create(&tmp_path)?;
|
||||
f.write_all(Value::Table(config_map).to_string().as_bytes())?;
|
||||
drop(f);
|
||||
fs::rename(tmp_path, config_path)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Configuration {
|
||||
@ -92,3 +127,12 @@ impl Default for Configuration {
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_config_toml(config_path: &PathBuf) -> anyhow::Result<Value> {
|
||||
let mut f = File::open(config_path)?;
|
||||
let mut config = String::new();
|
||||
f.read_to_string(&mut config)?;
|
||||
drop(f);
|
||||
|
||||
let config_toml = config.parse::<Value>()?;
|
||||
Ok(config_toml)
|
||||
}
|
||||
|
Reference in New Issue
Block a user