cosmic-settings/app/src/pages/desktop/wallpaper/config.rs
2023-12-12 21:43:57 +01:00

194 lines
5.5 KiB
Rust

// Copyright 2023 System76 <info@system76.com>
// SPDX-License-Identifier: GPL-3.0-only
use cosmic::cosmic_config::{self, ConfigGet, ConfigSet};
use cosmic_settings_desktop::wallpaper;
use std::collections::VecDeque;
use std::path::{Path, PathBuf};
const NAME: &str = "com.system76.CosmicSettings.Wallpaper";
const VERSION: u64 = 1;
const CURRENT_FOLDER: &str = "current-folder";
const CUSTOM_COLORS: &str = "custom-colors";
const CUSTOM_IMAGES: &str = "custom-images";
const RECENT_FOLDERS: &str = "recent-folders";
#[derive(Debug, Default)]
pub struct Config {
context: Option<cosmic_config::Config>,
current_folder: Option<PathBuf>,
custom_colors: Vec<wallpaper::Color>,
custom_images: Vec<PathBuf>,
recent_folders: VecDeque<PathBuf>,
}
impl Config {
pub fn new() -> Self {
let mut config = Self::default();
let context = match cosmic_config::Config::new(NAME, VERSION) {
Ok(context) => context,
Err(why) => {
tracing::warn!(?why, "failed to get config");
return Self::default();
}
};
if let Ok(path) = dbg!(context.get::<PathBuf>(CURRENT_FOLDER)) {
config.current_folder = Some(path);
}
if let Ok(colors) = context.get::<Vec<wallpaper::Color>>(CUSTOM_COLORS) {
config.custom_colors = colors;
}
if let Ok(images) = context.get::<Vec<PathBuf>>(CUSTOM_IMAGES) {
config.custom_images = images;
}
if let Ok(folders) = dbg!(context.get::<VecDeque<PathBuf>>(RECENT_FOLDERS)) {
config.recent_folders = folders;
}
config.context = Some(context);
config
}
#[must_use]
pub fn current_folder(&self) -> &Path {
self.current_folder
.as_deref()
.unwrap_or(Path::new("/usr/share/backgrounds/"))
}
/// Sets the current background folder
///
/// # Errors
///
/// Returns an error if the on-disk configuration could not be updated.
pub fn set_current_folder(&mut self, folder: PathBuf) -> Result<(), cosmic_config::Error> {
let result = self.update(CURRENT_FOLDER, &folder);
self.current_folder = Some(folder);
result
}
#[must_use]
pub fn custom_colors(&self) -> &[wallpaper::Color] {
&self.custom_colors
}
/// Adds a custom color
///
/// # Errors
///
/// Returns an error if the on-disk configuration could not be updated.
pub fn add_custom_color(
&mut self,
color: wallpaper::Color,
) -> Result<(), cosmic_config::Error> {
if !self.custom_colors.contains(&color) {
self.custom_colors.push(color);
return self.update_custom_colors();
}
Ok(())
}
/// Removes custom background colors.
///
/// # Errors
///
/// Returns an error if the on-disk configuration could not be updated.
pub fn remove_custom_color(
&mut self,
color: &wallpaper::Color,
) -> Result<(), cosmic_config::Error> {
if let Some(position) = self.custom_colors.iter().position(|c| c == color) {
self.custom_colors.remove(position);
return self.update_custom_colors();
}
Ok(())
}
#[must_use]
pub fn custom_images(&self) -> &[PathBuf] {
&self.custom_images
}
/// Adds a custom background image
///
/// # Errors
///
/// Returns an error if the on-disk configuration could not be updated.
pub fn add_custom_image(&mut self, image: PathBuf) -> Result<(), cosmic_config::Error> {
if !self.custom_images.contains(&image) {
self.custom_images.push(image);
return self.update_custom_images();
}
Ok(())
}
/// Removes custom background images.
///
/// # Errors
///
/// Returns an error if the on-disk configuration could not be updated.
pub fn remove_custom_image(&mut self, image: &Path) -> Result<(), cosmic_config::Error> {
if let Some(position) = self.custom_images.iter().position(|p| p == image) {
self.custom_images.remove(position);
return self.update_custom_images();
}
Ok(())
}
#[must_use]
pub fn recent_folders(&self) -> &VecDeque<PathBuf> {
&self.recent_folders
}
/// Adds a folder to the recent folders list
///
/// # Errors
///
/// Returns an error if the on-disk configuration could not be updated.
pub fn add_recent_folder(&mut self, folder: PathBuf) -> Result<(), cosmic_config::Error> {
while self.recent_folders.len() > 4 {
self.recent_folders.pop_front();
}
if !self.recent_folders.contains(&folder) {
self.recent_folders.push_back(folder);
return self.update_recent_folders();
}
Ok(())
}
fn update<V: serde::Serialize>(
&self,
key: &str,
value: &V,
) -> Result<(), cosmic_config::Error> {
if let Some(context) = self.context.as_ref() {
context.set(key, value)?;
}
Ok(())
}
fn update_custom_colors(&self) -> Result<(), cosmic_config::Error> {
self.update(CUSTOM_COLORS, &self.custom_colors)
}
fn update_custom_images(&self) -> Result<(), cosmic_config::Error> {
self.update(CUSTOM_IMAGES, &self.custom_images)
}
fn update_recent_folders(&self) -> Result<(), cosmic_config::Error> {
self.update(RECENT_FOLDERS, &self.recent_folders)
}
}