feat: migrate config from INI to TOML format

- Replace configparser with toml crate
- Refactor Monitor struct to hold MonitorType directly
- Fix broken Monitor::Display implementation
- Update wallpaper handlers to use new Monitor API
- Change default config path to .toml
- Suppress dead_code warnings on auto-generated D-Bus code
This commit is contained in:
Benjamyn Love 2026-07-07 11:42:36 +10:00
parent 378e3f46ea
commit 7fbc70bde6
5 changed files with 81 additions and 51 deletions

View File

@ -1,27 +1,28 @@
use configparser::ini::Ini;
use core::fmt; use core::fmt;
use toml::Value;
use crate::enums::*; use crate::enums::*;
use untildify;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Monitor { pub struct Monitor {
pub ratio: MonitorType, pub monitor_type: MonitorType,
pub index: i64,
} }
impl Monitor { impl Monitor {
pub fn new(monitor_type: MonitorType, index: i64) -> Monitor { pub fn new(monitor_type: MonitorType) -> Monitor {
Monitor { Monitor {
ratio: monitor_type, monitor_type,
index: index,
} }
} }
pub fn display(&self) -> String {
format!("Monitor({:?})", self.monitor_type)
}
} }
impl fmt::Display for Monitor { impl fmt::Display for Monitor {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:?}", self) write!(f, "{}", self.display())
} }
} }
@ -39,8 +40,11 @@ impl Monitors {
impl fmt::Display for Monitors { impl fmt::Display for Monitors {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "[")?; write!(f, "[")?;
for v in &self.monitors { for (i, v) in self.monitors.iter().enumerate() {
write!(f, "{}, ", v)?; if i > 0 {
write!(f, ", ")?;
}
write!(f, "{}", v.display())?;
} }
write!(f, "]") write!(f, "]")
} }
@ -54,7 +58,7 @@ pub struct WallpaperDir {
} }
impl WallpaperDir { impl WallpaperDir {
pub fn get(&self, monitor_type: MonitorType) -> String { pub fn get(&self, monitor_type: &MonitorType) -> String {
match monitor_type { match monitor_type {
MonitorType::Ultrawide => self.ultrawide.to_string(), MonitorType::Ultrawide => self.ultrawide.to_string(),
MonitorType::Horizontal => self.horizontal.to_string(), MonitorType::Horizontal => self.horizontal.to_string(),
@ -68,10 +72,8 @@ impl fmt::Display for WallpaperDir {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!( write!(
f, f,
"ultrawide: {ultrawide}, horizontal {horizontal}, vertical {vertical}", "ultrawide: {}, horizontal {}, vertical {}",
ultrawide = self.ultrawide, self.ultrawide, self.horizontal, self.vertical
horizontal = self.horizontal,
vertical = self.vertical
) )
} }
} }
@ -86,58 +88,84 @@ pub struct Config {
impl Config { impl Config {
pub fn from_config(file_path: String) -> Config { pub fn from_config(file_path: String) -> Config {
let mut config = Ini::new(); let toml_str = std::fs::read_to_string(&file_path).expect("Failed to read config file");
let map = config.load(file_path).unwrap(); let value: Value = toml::from_str(&toml_str).expect("Failed to parse TOML config");
// Get the wallpaper engine and parse it // Get the general section
let wallpaper_engine = let general = value
WallpaperHandler::new(config.get("general", "wallpaper_engine").unwrap()); .get("general")
// .and_then(|g| g.as_table())
.expect("Missing [general] section in config");
// Get the wallpaper dirs and parse them // Get the wallpaper engine
let wallpaper_engine_str = general
.get("wallpaper_engine")
.and_then(|v| v.as_str())
.expect("Missing wallpaper_engine in [general] section");
let wallpaper_engine = WallpaperHandler::new(wallpaper_engine_str.to_string());
// Get the wallpaper dirs
let ultrawide_dir = general
.get("ultra_wall_dir")
.and_then(|v| v.as_str())
.map(|s| untildify::untildify(s))
.expect("Missing ultra_wall_dir in [general] section");
let horizontal_dir = general
.get("hor_wall_dir")
.and_then(|v| v.as_str())
.map(|s| untildify::untildify(s))
.expect("Missing hor_wall_dir in [general] section");
let vert_wall_dir = general
.get("vert_wall_dir")
.and_then(|v| v.as_str())
.map(|s| untildify::untildify(s))
.expect("Missing vert_wall_dir in [general] section");
let ultrawide_dir =
untildify::untildify(config.get("general", "ultra_wall_dir").unwrap().as_ref());
let horizontal_dir =
untildify::untildify(config.get("general", "hor_wall_dir").unwrap().as_ref());
let vert_wall_dir =
untildify::untildify(config.get("general", "vert_wall_dir").unwrap().as_ref());
let wallpaper_dir = WallpaperDir { let wallpaper_dir = WallpaperDir {
ultrawide: ultrawide_dir, ultrawide: ultrawide_dir,
horizontal: horizontal_dir, horizontal: horizontal_dir,
vertical: vert_wall_dir, vertical: vert_wall_dir,
}; };
//
// Get the Monitors and parse them // Get the monitors section
let monitors = general
.get("monitors")
.and_then(|m| m.as_array())
.expect("Missing [[monitors]] section in config");
let mut monitors = Monitors { let mut monitors_vec = Monitors {
monitors: Vec::new(), monitors: Vec::new(),
}; };
for mon in map.get("monitors").iter() {
for key in mon.keys() { for monitor_value in monitors {
let monitor = mon.get(key).unwrap().as_ref().unwrap(); let monitor_type_str = monitor_value
// Add monitor type to Monitors vector .get("monitor_type")
monitors.add(Monitor::new( .and_then(|v| v.as_str())
MonitorType::new(monitor.to_string()), .expect("Missing monitor_type in monitors array");
key.parse::<i64>() let monitor_type = MonitorType::new(monitor_type_str.to_string());
.expect("Failed to parse int in motitor config"),
)); monitors_vec.add(Monitor::new(monitor_type));
}
} }
//
Config { Config {
x_server: config.get("general", "x_server").unwrap(), x_server: general
.get("x_server")
.and_then(|v| v.as_str())
.unwrap_or("")
.to_string(),
wallpaper_engine, wallpaper_engine,
wallpaper_dir, wallpaper_dir,
monitors, monitors: monitors_vec,
} }
} }
} }
impl fmt::Display for Config { impl fmt::Display for Config {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Mycelium Config: X Server: {xserv}, Wallpaper Engine: {wallpaper_engine}, Wallpaper Directories: {wallpaper_dirs}, Monitors: {monitors}", xserv = self.x_server, wallpaper_engine = self.wallpaper_engine, wallpaper_dirs = self.wallpaper_dir, monitors = self.monitors) write!(
f,
"Mycelium Config: X Server: {}, Wallpaper Engine: {}, Wallpaper Directories: {}, Monitors: {}",
self.x_server, self.wallpaper_engine, self.wallpaper_dir, self.monitors
)
} }
} }

View File

@ -1,3 +1,5 @@
#![allow(dead_code)]
// This code was autogenerated with `dbus-codegen-rust -g -m None -d org.kde.plasmashell -p /PlasmaShell`, see https://github.com/diwic/dbus-rs // This code was autogenerated with `dbus-codegen-rust -g -m None -d org.kde.plasmashell -p /PlasmaShell`, see https://github.com/diwic/dbus-rs
use dbus; use dbus;
#[allow(unused_imports)] #[allow(unused_imports)]

View File

@ -7,7 +7,7 @@ pub fn change_wallpapers(wallpapers: &Wallpapers) {
command.arg("--no-fehbg").arg("--bg-fill"); command.arg("--no-fehbg").arg("--bg-fill");
for monitor in wallpapers.config.monitors.monitors.iter() { for monitor in wallpapers.config.monitors.monitors.iter() {
command.arg(wallpapers.random_selection(&monitor.ratio).to_string()); command.arg(wallpapers.random_selection(&monitor.monitor_type).to_string());
} }
let result = command.output(); let result = command.output();

View File

@ -30,7 +30,7 @@ pub fn change_wallpapers(wallpapers: &Wallpapers) {
pub fn generate_js(wallpapers: &Wallpapers) -> String { pub fn generate_js(wallpapers: &Wallpapers) -> String {
let mut javascript = String::new(); let mut javascript = String::new();
javascript.push_str("var allDesktops = desktops();\n"); javascript.push_str("var allDesktops = desktops();\n");
for (_count, monitor) in wallpapers.config.monitors.monitors.iter().enumerate() { for (count, monitor) in wallpapers.config.monitors.monitors.iter().enumerate() {
let mut boilerplate = String::new(); let mut boilerplate = String::new();
let _ = write!( let _ = write!(
&mut boilerplate, &mut boilerplate,
@ -39,8 +39,8 @@ pub fn generate_js(wallpapers: &Wallpapers) -> String {
allDesktops[{0}].currentConfigGroup = Array('Wallpaper', 'org.kde.image', 'General'); allDesktops[{0}].currentConfigGroup = Array('Wallpaper', 'org.kde.image', 'General');
allDesktops[{0}].writeConfig('Image', 'file://{1}'); allDesktops[{0}].writeConfig('Image', 'file://{1}');
", ",
monitor.index, count,
wallpapers.random_selection(&monitor.ratio) wallpapers.random_selection(&monitor.monitor_type)
); );
javascript.push_str(&boilerplate); javascript.push_str(&boilerplate);
} }

View File

@ -10,7 +10,7 @@ use untildify::untildify;
fn main() { fn main() {
// Load the config file from the default path // Load the config file from the default path
let path = untildify("~/.config/wallpaperctl/wallpaperctl.ini"); let path = untildify("~/.config/wallpaperctl/wallpaperctl.toml");
let config = Config::from_config(path); let config = Config::from_config(path);
// Initialise the `Wallpapers` struct with a clone of the config // Initialise the `Wallpapers` struct with a clone of the config