256 lines
7.6 KiB
Rust
256 lines
7.6 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,
|
|
time::{Duration, SystemTime},
|
|
};
|
|
|
|
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],
|
|
}
|
|
|
|
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: 230.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],
|
|
}
|
|
}
|
|
}
|
|
|
|
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
|
|
}
|