post_maker/src/config.rs

254 lines
7.7 KiB
Rust

/*
This file is part of Post Maker.
Post Maker is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Post Maker is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Post Maker. If not, see <https://www.gnu.org/licenses/>
*/
//! load, save configuration and parse cli args
use crate::{config_picker::ConfigPicker, globals};
use clap::{ArgEnum, Parser};
use fltk::dialog;
use fltk_theme::ThemeType;
use lazy_static::lazy_static;
use serde::{Deserialize, Serialize};
use std::{collections::HashMap, fs::File, path::PathBuf};
lazy_static! {
/// Directory where all Configurations are present
static ref CONFIG_DIR: PathBuf = {
let dir = match dirs::config_dir() {
Some(path) => path,
None => std::env::current_exe()
.unwrap()
.parent()
.unwrap()
.to_owned(),
}
.join("post_maker");
if !dir.exists() {
if let Err(e) = std::fs::create_dir(&dir) {
dialog::alert_default("Failed to create config dir!");
panic!("Failed to create config dir!\n{:?}", e);
}
}
dir
};
/// Configuration File
static ref CONFIG_FILE: PathBuf = CONFIG_DIR.join("post_maker.config");
/// Log File
static ref LOG_FILE: PathBuf = CONFIG_DIR.join("post_maker.log");
}
/// Simple program calculate size of stuff in quote image
#[derive(Parser, Debug)]
#[clap(about, version, author)]
pub(crate) struct Args {
/// Theme to use for gui
#[clap(short, long, arg_enum)]
pub(crate) theme: Option<Themes>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, ArgEnum)]
pub(crate) enum Themes {
Classic,
/// Windows 7
Aero,
/// Windows 8
Metro,
/// Classic MacOS
AquaClassic,
/// Xfce
Greybird,
/// Windows 2000
Blue,
/// Dark
Dark,
/// High Contrast
HighContrast,
/// Get from System
System,
}
impl Into<ThemeType> for Themes {
fn into(self) -> ThemeType {
match self {
Self::Classic => ThemeType::Classic,
Self::Aero => ThemeType::Aero,
Self::Metro => ThemeType::Metro,
Self::AquaClassic => ThemeType::AquaClassic,
Self::Greybird => ThemeType::Greybird,
Self::Blue => ThemeType::Blue,
Self::Dark => ThemeType::Dark,
Self::HighContrast => ThemeType::HighContrast,
Self::System => {
if cfg!(windows) {
ThemeType::Metro
} else if cfg!(unix) {
ThemeType::Greybird
} else {
ThemeType::Classic
}
}
}
}
}
pub(crate) fn args() -> Args {
let args = Args::parse();
args
}
/// Configuation file
#[derive(Debug, Clone, Serialize, Deserialize)]
pub(crate) struct ConfigFile {
pub(crate) quote_font: String,
pub(crate) subquote_font: String,
pub(crate) subquote2_font: String,
pub(crate) tag_font: String,
pub(crate) tag2_font: String,
pub(crate) quote_font_ratio: f64,
pub(crate) subquote_font_ratio: f64,
pub(crate) subquote2_font_ratio: f64,
pub(crate) tag_font_ratio: f64,
pub(crate) tag2_font_ratio: f64,
pub(crate) quote_position_ratio: f64,
pub(crate) subquote_position_ratio: f64,
pub(crate) subquote2_position_ratio: f64,
pub(crate) tag_position_ratio: f64,
pub(crate) tag2_position_ratio: f64,
pub(crate) image_ratio: (f64, f64),
pub(crate) color_layer: [u8; 4],
pub(crate) image_format: String,
}
impl Default for ConfigFile {
fn default() -> Self {
Self {
quote_font: String::new(),
subquote_font: String::new(),
subquote2_font: String::new(),
tag_font: String::new(),
tag2_font: String::new(),
quote_font_ratio: 250.0,
subquote_font_ratio: 230.0,
subquote2_font_ratio: 230.0,
tag_font_ratio: 150.0,
tag2_font_ratio: 150.0,
quote_position_ratio: 0.7,
subquote_position_ratio: 0.8,
subquote2_position_ratio: 0.9,
tag_position_ratio: 0.5,
tag2_position_ratio: 0.95,
image_ratio: (4.0, 5.0),
color_layer: [20, 22, 25, 197],
image_format: "png".to_owned(),
}
}
}
impl ConfigFile {
pub(crate) fn load() -> Self {
if CONFIG_FILE.exists() {
let map = get_configs();
let map = match map {
Some(m) => m,
None => HashMap::new(),
};
let default_config = (&*globals::CONFIG_NAME.read().unwrap()).to_string();
let config_name = if (map.len() > 1 || !map.contains_key(&default_config))
&& map.len() != 0
{
let picked = ConfigPicker::new(map.keys().map(|a| a.to_owned()).collect()).selected;
let picked = picked.borrow();
match &*picked {
Some(v) => v.to_owned(),
None => std::process::exit(0),
}
} else {
default_config
};
if let Some(config) = map.get(&config_name) {
*globals::CONFIG_NAME.write().unwrap() = config_name;
return config.to_owned();
}
}
let config = Self::default();
let mut configs = HashMap::new();
configs.insert(
(&*globals::CONFIG_NAME.read().unwrap()).to_owned(),
config.clone(),
);
save_configs(configs);
config
}
}
/// Get parsed configs from file
pub(crate) fn get_configs() -> Option<HashMap<String, ConfigFile>> {
match std::fs::read_to_string(&*CONFIG_FILE) {
Ok(r) => serde_json::from_str::<HashMap<String, ConfigFile>>(&r).ok(),
Err(_) => None,
}
}
/// Save configs
pub(crate) fn save_configs(configs: HashMap<String, ConfigFile>) {
if let Err(e) = std::fs::write(&*CONFIG_FILE, serde_json::to_string(&configs).unwrap()) {
dialog::alert_default("Can't write config!");
error!("Can't write config!\n{:?}", e);
panic!("Can't write config!\n{:?}", e);
}
}
pub(crate) fn log_file() -> File {
// match File::open(&*LOG_FILE) {
// Ok(mut file) => {
// if is_file_30_days_old(&file) {
// match File::create(&*LOG_FILE) {
// Ok(f) => file = f,
// Err(e) => {
// dialog::alert_default("Can't open log file!");
// panic!("{:?}", e);
// }
// }
// }
// file
// }
// Err(_) =>
match File::create(&*LOG_FILE) {
Ok(f) => f,
Err(e) => {
dialog::alert_default("Can't open log file!");
panic!("{:?}", e);
}
}
// }
}
// pub(crate) fn is_file_30_days_old(file: &File) -> bool {
// if let Ok(meta) = file.metadata() {
// if let Ok(time) = meta.created() {
// if let Ok(dur) = SystemTime::now().duration_since(time) {
// if dur > Duration::from_secs(60 * 60 * 24 * 30) {
// return true;
// }
// }
// }
// }
// false
// }