Add simple (if ugly) settings dialog
This commit is contained in:
		
							
								
								
									
										11
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										11
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							| @@ -308,6 +308,17 @@ dependencies = [ | |||||||
|  "shell-words", |  "shell-words", | ||||||
| ] | ] | ||||||
|  |  | ||||||
|  | [[package]] | ||||||
|  | name = "bscreensaver-settings" | ||||||
|  | version = "0.1.0" | ||||||
|  | dependencies = [ | ||||||
|  |  "anyhow", | ||||||
|  |  "bscreensaver-util", | ||||||
|  |  "glib", | ||||||
|  |  "gtk", | ||||||
|  |  "log", | ||||||
|  | ] | ||||||
|  |  | ||||||
| [[package]] | [[package]] | ||||||
| name = "bscreensaver-systemd" | name = "bscreensaver-systemd" | ||||||
| version = "0.1.0" | version = "0.1.0" | ||||||
|   | |||||||
| @@ -6,6 +6,7 @@ members = [ | |||||||
|     "dbus-service", |     "dbus-service", | ||||||
|     "dialog-gtk3", |     "dialog-gtk3", | ||||||
|     "util", |     "util", | ||||||
|  |     "settings", | ||||||
|     "systemd", |     "systemd", | ||||||
|     "xcb-xembed", |     "xcb-xembed", | ||||||
| ] | ] | ||||||
|   | |||||||
							
								
								
									
										9
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										9
									
								
								Makefile
									
									
									
									
									
								
							| @@ -4,7 +4,9 @@ PREFIX ?= /usr/local | |||||||
| BINDIR ?= $(PREFIX)/bin | BINDIR ?= $(PREFIX)/bin | ||||||
| LIBEXECDIR ?= $(PREFIX)/libexec | LIBEXECDIR ?= $(PREFIX)/libexec | ||||||
| SYSCONFDIR ?= $(PREFIX)/etc | SYSCONFDIR ?= $(PREFIX)/etc | ||||||
|  | DATADIR ?= $(PREFIX)/share | ||||||
|  |  | ||||||
|  | APPLICATIONS_DIR = $(DATADIR)/applications | ||||||
| CONFIG_DIR = $(SYSCONFDIR)/xdg/bscreensaver | CONFIG_DIR = $(SYSCONFDIR)/xdg/bscreensaver | ||||||
| HELPER_DIR = $(LIBEXECDIR)/bscreensaver | HELPER_DIR = $(LIBEXECDIR)/bscreensaver | ||||||
| HELPERS = \ | HELPERS = \ | ||||||
| @@ -26,16 +28,17 @@ dev: | |||||||
| 	HELPER_DIR=target/debug cargo build | 	HELPER_DIR=target/debug cargo build | ||||||
|  |  | ||||||
| install: release | install: release | ||||||
| 	$(INSTALL) -m 0755 -d $(BINDIR) $(HELPER_DIR) $(CONFIG_DIR) | 	$(INSTALL) -m 0755 -d $(BINDIR) $(HELPER_DIR) $(CONFIG_DIR) $(APPLICATIONS_DIR) | ||||||
| 	$(INSTALL) -m 0755 target/release/bscreensaver target/release/bscreensaver-command $(BINDIR) | 	$(INSTALL) -m 0755 target/release/bscreensaver target/release/bscreensaver-command target/release/bscreensaver-settings $(BINDIR) | ||||||
| 	$(INSTALL) -m 0755 $(addprefix target/release/,$(HELPERS)) $(HELPER_DIR) | 	$(INSTALL) -m 0755 $(addprefix target/release/,$(HELPERS)) $(HELPER_DIR) | ||||||
| 	$(INSTALL) -m 0644 bscreensaver.toml.example $(CONFIG_DIR) | 	$(INSTALL) -m 0644 bscreensaver.toml.example $(CONFIG_DIR) | ||||||
|  | 	$(INSTALL) -m 0644 settings/bscreensaver-settings.desktop $(APPLICATIONS_DIR) | ||||||
|  |  | ||||||
| clean: | clean: | ||||||
| 	cargo clean | 	cargo clean | ||||||
|  |  | ||||||
| uninstall: | uninstall: | ||||||
| 	rm -f $(BINDIR)/bscreensaver $(BINDIR)/bscreensaver-command $(addprefix $(HELPER_DIR)/,$(HELPERS)) || true | 	rm -f $(BINDIR)/bscreensaver $(BINDIR)/bscreensaver-command $(BINDIR)/bscreensaver-settings $(addprefix $(HELPER_DIR)/,$(HELPERS)) || true | ||||||
| 	rmdir -p $(BINDIR) $(HELPER_DIR) || true | 	rmdir -p $(BINDIR) $(HELPER_DIR) || true | ||||||
| 	rmdir -p $(PREFIX) || true | 	rmdir -p $(PREFIX) || true | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										11
									
								
								settings/Cargo.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								settings/Cargo.toml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | |||||||
|  | [package] | ||||||
|  | name = "bscreensaver-settings" | ||||||
|  | version = "0.1.0" | ||||||
|  | edition = "2021" | ||||||
|  |  | ||||||
|  | [dependencies] | ||||||
|  | anyhow = "1" | ||||||
|  | bscreensaver-util = { path = "../util" } | ||||||
|  | glib = { version = "0.15", features = ["v2_68"] } | ||||||
|  | gtk = { version = "0.15", features = ["v3_24"] } | ||||||
|  | log = "0.4" | ||||||
							
								
								
									
										10
									
								
								settings/bscreensaver-settings.desktop
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								settings/bscreensaver-settings.desktop
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | |||||||
|  | [Desktop Entry] | ||||||
|  | Version=1.0 | ||||||
|  | Name=Screensaver Settings | ||||||
|  | Comment=Customize screensaver settings | ||||||
|  | Exec=bscreensaver-settings | ||||||
|  | Icon=screensaver | ||||||
|  | Terminal=false | ||||||
|  | StartupNotify=true | ||||||
|  | Type=Application | ||||||
|  | Categories=GTK;Settings;DesktopSettings; | ||||||
							
								
								
									
										249
									
								
								settings/src/main.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										249
									
								
								settings/src/main.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,249 @@ | |||||||
|  | use gtk::{glib, prelude::*}; | ||||||
|  | use glib::clone; | ||||||
|  | use std::{env, process::exit, time::Duration}; | ||||||
|  |  | ||||||
|  | use bscreensaver_util::settings::Configuration; | ||||||
|  |  | ||||||
|  | #[derive(Clone)] | ||||||
|  | struct Widgets { | ||||||
|  |     lock_timeout: gtk::SpinButton, | ||||||
|  |     blank_before_locking: gtk::SpinButton, | ||||||
|  |     new_login_command: gtk::Entry, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | fn main() -> anyhow::Result<()> { | ||||||
|  |     let config = Configuration::load()?; | ||||||
|  |  | ||||||
|  |     let app = gtk::Application::builder() | ||||||
|  |         .application_id("org.spurint.bscreensaver-settings") | ||||||
|  |         .build(); | ||||||
|  |     app.connect_activate(move |app| show_ui(&app, &config)); | ||||||
|  |  | ||||||
|  |     exit(app.run_with_args(&env::args().into_iter().collect::<Vec<String>>())); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | fn show_ui(app: >k::Application, config: &Configuration) { | ||||||
|  |     let mainwin = gtk::ApplicationWindow::builder() | ||||||
|  |         .application(app) | ||||||
|  |         .name("BScreensaver Settings") | ||||||
|  |         .title("Screensaver Settings") | ||||||
|  |         .type_(gtk::WindowType::Toplevel) | ||||||
|  |         .resizable(false) | ||||||
|  |         .build(); | ||||||
|  |  | ||||||
|  |     let label_sg = gtk::SizeGroup::builder() | ||||||
|  |         .mode(gtk::SizeGroupMode::Horizontal) | ||||||
|  |         .build(); | ||||||
|  |  | ||||||
|  |     let topvbox = gtk::Box::builder() | ||||||
|  |         .orientation(gtk::Orientation::Vertical) | ||||||
|  |         .spacing(8) | ||||||
|  |         .margin(4) | ||||||
|  |         .build(); | ||||||
|  |     mainwin.add(&topvbox); | ||||||
|  |  | ||||||
|  |     let hbox = gtk::Box::builder() | ||||||
|  |         .orientation(gtk::Orientation::Horizontal) | ||||||
|  |         .spacing(8) | ||||||
|  |         .build(); | ||||||
|  |     topvbox.pack_start(&hbox, false, false, 0); | ||||||
|  |  | ||||||
|  |     let label = gtk::Label::builder() | ||||||
|  |         .label("Lock screen after") | ||||||
|  |         .xalign(0.0) | ||||||
|  |         .build(); | ||||||
|  |     label_sg.add_widget(&label); | ||||||
|  |     hbox.pack_start(&label, false, false, 0); | ||||||
|  |  | ||||||
|  |     let lock_timeout_spinbutton = gtk::SpinButton::builder() | ||||||
|  |         .adjustment(>k::Adjustment::builder() | ||||||
|  |             .lower(1.0) | ||||||
|  |             .upper(f64::MAX as u32 as f64) | ||||||
|  |             .step_increment(1.0) | ||||||
|  |             .page_increment(5.0) | ||||||
|  |             .value((config.lock_timeout.as_secs() / 60) as f64) | ||||||
|  |             .build() | ||||||
|  |         ) | ||||||
|  |         .tooltip_text("Minutes before the screen locks") | ||||||
|  |         .activates_default(true) | ||||||
|  |         .build(); | ||||||
|  |     hbox.pack_start(&lock_timeout_spinbutton, false, false, 0); | ||||||
|  |  | ||||||
|  |     let label = gtk::Label::builder() | ||||||
|  |         .label("minutes") | ||||||
|  |         .xalign(0.0) | ||||||
|  |         .build(); | ||||||
|  |     hbox.pack_start(&label, false, false, 0); | ||||||
|  |  | ||||||
|  |     let hbox = gtk::Box::builder() | ||||||
|  |         .orientation(gtk::Orientation::Horizontal) | ||||||
|  |         .spacing(8) | ||||||
|  |         .build(); | ||||||
|  |     topvbox.pack_start(&hbox, false, false, 0); | ||||||
|  |  | ||||||
|  |     let label = gtk::Label::builder() | ||||||
|  |         .label("Blank screen") | ||||||
|  |         .xalign(0.0) | ||||||
|  |         .build(); | ||||||
|  |     label_sg.add_widget(&label); | ||||||
|  |     hbox.pack_start(&label, false, false, 0); | ||||||
|  |  | ||||||
|  |     let blank_before_locking_spinbutton = gtk::SpinButton::builder() | ||||||
|  |         .adjustment(>k::Adjustment::builder() | ||||||
|  |             .lower(0.0) | ||||||
|  |             .upper(f64::MAX as u32 as f64) | ||||||
|  |             .step_increment(1.0) | ||||||
|  |             .page_increment(5.0) | ||||||
|  |             .value((config.blank_before_locking.as_secs() / 60) as f64) | ||||||
|  |             .build() | ||||||
|  |         ) | ||||||
|  |         .tooltip_text("Minutes before screen locks to blank the screen") | ||||||
|  |         .activates_default(true) | ||||||
|  |         .build(); | ||||||
|  |     hbox.pack_start(&blank_before_locking_spinbutton, false, false, 0); | ||||||
|  |  | ||||||
|  |     let label = gtk::Label::builder() | ||||||
|  |         .label("minutes before locking") | ||||||
|  |         .xalign(0.0) | ||||||
|  |         .build(); | ||||||
|  |     hbox.pack_start(&label, false, false, 0); | ||||||
|  |  | ||||||
|  |     let hbox = gtk::Box::builder() | ||||||
|  |         .orientation(gtk::Orientation::Horizontal) | ||||||
|  |         .spacing(8) | ||||||
|  |         .build(); | ||||||
|  |     topvbox.pack_start(&hbox, false, false, 0); | ||||||
|  |  | ||||||
|  |     let label = gtk::Label::builder() | ||||||
|  |         .label("New Login Command:") | ||||||
|  |         .tooltip_text("Command to run when the 'New Login' button is clicked in the unlock dialog") | ||||||
|  |         .xalign(0.0) | ||||||
|  |         .build(); | ||||||
|  |     label_sg.add_widget(&label); | ||||||
|  |     hbox.pack_start(&label, false, false, 0); | ||||||
|  |  | ||||||
|  |     let new_login_command_entry = gtk::Entry::builder() | ||||||
|  |         .text(config.new_login_command.as_ref().unwrap_or(&"".to_string())) | ||||||
|  |         .width_chars(30) | ||||||
|  |         .activates_default(true) | ||||||
|  |         .build(); | ||||||
|  |     hbox.pack_start(&new_login_command_entry, false, false, 0); | ||||||
|  |  | ||||||
|  |     let widgets = Widgets { | ||||||
|  |         lock_timeout: lock_timeout_spinbutton.clone(), | ||||||
|  |         blank_before_locking: blank_before_locking_spinbutton.clone(), | ||||||
|  |         new_login_command: new_login_command_entry.clone(), | ||||||
|  |     }; | ||||||
|  |     mainwin.connect_delete_event(clone!(@strong config, @strong widgets, @strong app, @strong mainwin => move |_,_| { | ||||||
|  |         Inhibit(!confirm_cancel(&config, &widgets, &mainwin)) | ||||||
|  |     })); | ||||||
|  |  | ||||||
|  |     let button = gtk::Button::from_icon_name(Some("folder-open"), gtk::IconSize::Button); | ||||||
|  |     button.connect_clicked(clone!(@strong mainwin, @strong widgets => move |_| { | ||||||
|  |         run_file_chooser(&mainwin, &widgets); | ||||||
|  |     })); | ||||||
|  |     hbox.pack_start(&button, false, false, 0); | ||||||
|  |  | ||||||
|  |     let button_box = gtk::ButtonBox::builder() | ||||||
|  |         .spacing(8) | ||||||
|  |         .layout_style(gtk::ButtonBoxStyle::End) | ||||||
|  |         .build(); | ||||||
|  |     topvbox.pack_end(&button_box, false, false, 0); | ||||||
|  |  | ||||||
|  |     let close_button = gtk::Button::builder() | ||||||
|  |         .label("Close") | ||||||
|  |         .build(); | ||||||
|  |     close_button.connect_clicked(clone!(@strong config, @strong widgets, @strong app, @strong mainwin => move |_| { | ||||||
|  |         if confirm_cancel(&config, &widgets, &mainwin) { | ||||||
|  |             app.quit(); | ||||||
|  |         } | ||||||
|  |     })); | ||||||
|  |     button_box.pack_end(&close_button, false, false, 0); | ||||||
|  |  | ||||||
|  |     let save_button = gtk::Button::builder() | ||||||
|  |         .label("Save") | ||||||
|  |         .build(); | ||||||
|  |     save_button.connect_clicked(clone!(@strong config, @strong widgets, @strong app, @strong mainwin => move |_| { | ||||||
|  |         if save_config(&config, &widgets, &mainwin) { | ||||||
|  |             app.quit(); | ||||||
|  |         } | ||||||
|  |     })); | ||||||
|  |     button_box.pack_end(&save_button, false, false, 0); | ||||||
|  |     save_button.set_can_default(true); | ||||||
|  |     save_button.set_has_default(true); | ||||||
|  |  | ||||||
|  |     mainwin.show_all(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | fn run_file_chooser(mainwin: >k::ApplicationWindow, widgets: &Widgets) { | ||||||
|  |     let file_chooser = gtk::FileChooserNative::new( | ||||||
|  |         Some("New Login Command"), | ||||||
|  |         Some(mainwin), | ||||||
|  |         gtk::FileChooserAction::Open, | ||||||
|  |         Some("Select"), | ||||||
|  |         Some("Cancel"), | ||||||
|  |     ); | ||||||
|  |     let response = file_chooser.run(); | ||||||
|  |     file_chooser.hide(); | ||||||
|  |     if response == gtk::ResponseType::Accept { | ||||||
|  |         if let Some(filename) = file_chooser.filename() { | ||||||
|  |             widgets.new_login_command.set_text(&filename.to_string_lossy()); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | fn save_config(config: &Configuration, widgets: &Widgets, mainwin: >k::ApplicationWindow) -> bool{ | ||||||
|  |     let (new_config, changed) = build_new_configuration(&config, &widgets); | ||||||
|  |     if changed { | ||||||
|  |         if let Err(err) = new_config.save() { | ||||||
|  |             let error_dialog = gtk::MessageDialog::new( | ||||||
|  |                 Some(mainwin), | ||||||
|  |                 gtk::DialogFlags::MODAL | gtk::DialogFlags::DESTROY_WITH_PARENT, | ||||||
|  |                 gtk::MessageType::Error, | ||||||
|  |                 gtk::ButtonsType::Close, | ||||||
|  |                 &format!("Failed to save configuration: {}", err), | ||||||
|  |             ); | ||||||
|  |             error_dialog.set_title("Screensaver Settings"); | ||||||
|  |             error_dialog.run(); | ||||||
|  |             error_dialog.hide(); | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     true | ||||||
|  | } | ||||||
|  |  | ||||||
|  | fn confirm_cancel(config: &Configuration, widgets: &Widgets, mainwin: >k::ApplicationWindow) -> bool { | ||||||
|  |     let (_, changed) = build_new_configuration(&config, &widgets); | ||||||
|  |     if changed { | ||||||
|  |         let dialog = gtk::MessageDialog::new( | ||||||
|  |             Some(mainwin), | ||||||
|  |             gtk::DialogFlags::MODAL | gtk::DialogFlags::DESTROY_WITH_PARENT, | ||||||
|  |             gtk::MessageType::Warning, | ||||||
|  |             gtk::ButtonsType::None, | ||||||
|  |             "You have unsaved changes. Are you sure you want to close?", | ||||||
|  |         ); | ||||||
|  |         dialog.set_title("Screensaver Settings"); | ||||||
|  |         dialog.add_buttons(&[ | ||||||
|  |             ("Close Window", gtk::ResponseType::Close), | ||||||
|  |             ("Cancel", gtk::ResponseType::Cancel), | ||||||
|  |         ]); | ||||||
|  |         dialog.set_default_response(gtk::ResponseType::Cancel); | ||||||
|  |         let response = dialog.run(); | ||||||
|  |         dialog.hide(); | ||||||
|  |         match response { | ||||||
|  |             gtk::ResponseType::Close => true, | ||||||
|  |             _ => false, | ||||||
|  |         } | ||||||
|  |     } else { | ||||||
|  |         true | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | fn build_new_configuration(old_config: &Configuration, widgets: &Widgets) -> (Configuration, bool) { | ||||||
|  |     let mut new_config = old_config.clone(); | ||||||
|  |     new_config.lock_timeout = Duration::from_secs(widgets.lock_timeout.adjustment().value() as u64 * 60); | ||||||
|  |     new_config.blank_before_locking = Duration::from_secs(widgets.blank_before_locking.adjustment().value() as u64 * 60); | ||||||
|  |     new_config.new_login_command = Some(widgets.new_login_command.text()).filter(|s| !s.is_empty()).map(|s| s.to_string()); | ||||||
|  |     let changed = old_config != &new_config; | ||||||
|  |     (new_config, changed) | ||||||
|  | } | ||||||
| @@ -1,8 +1,15 @@ | |||||||
| use anyhow::anyhow; | 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; | 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 { | pub enum DialogBackend { | ||||||
|     Gtk3, |     Gtk3, | ||||||
| } | } | ||||||
| @@ -13,6 +20,20 @@ impl DialogBackend { | |||||||
|             Self::Gtk3 => "bscreensaver-dialog-gtk3", |             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 { | 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 struct Configuration { | ||||||
|     pub lock_timeout: Duration, |     pub lock_timeout: Duration, | ||||||
|     pub blank_before_locking: Duration, |     pub blank_before_locking: Duration, | ||||||
| @@ -38,7 +59,7 @@ impl Configuration { | |||||||
|         use humantime::parse_duration; |         use humantime::parse_duration; | ||||||
|  |  | ||||||
|         let config_tomls = xdg::BaseDirectories::new()? |         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)) |             .map(|config_path| parse_config_toml(&config_path)) | ||||||
|             .collect::<Result<Vec<Value>, _>>()?; |             .collect::<Result<Vec<Value>, _>>()?; | ||||||
|  |  | ||||||
| @@ -69,16 +90,30 @@ impl Configuration { | |||||||
|             Ok(config) |             Ok(config) | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } |  | ||||||
|  |  | ||||||
| fn parse_config_toml(config_path: &PathBuf) -> anyhow::Result<Value> { |     pub fn save(&self) -> anyhow::Result<()> { | ||||||
|     let mut f = File::open(config_path)?; |         use humantime::format_duration; | ||||||
|     let mut config = String::new(); |         use toml::map::Map; | ||||||
|     f.read_to_string(&mut config)?; |  | ||||||
|  |         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); |         drop(f); | ||||||
|  |         fs::rename(tmp_path, config_path)?; | ||||||
|  |  | ||||||
|     let config_toml = config.parse::<Value>()?; |         Ok(()) | ||||||
|     Ok(config_toml) |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| impl Default for Configuration { | 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