1use std::rc::{Rc, Weak};
2use std::cell::RefCell;
3
4use crate::shell::Shell;
5#[cfg(unix)]
6use gio;
7#[cfg(unix)]
8use gio::SettingsExt;
9
10#[derive(PartialEq)]
11pub enum FontSource {
12 Rpc,
13 #[cfg(unix)]
14 Gnome,
15 Default,
16}
17
18struct State {
19 font_source: FontSource,
20
21 #[cfg(unix)]
22 gnome_interface_settings: gio::Settings,
23}
24
25impl State {
26 #[cfg(unix)]
27 pub fn new() -> State {
28 State {
29 font_source: FontSource::Default,
30 gnome_interface_settings: gio::Settings::new("org.gnome.desktop.interface"),
31 }
32 }
33
34 #[cfg(target_os = "windows")]
35 pub fn new() -> State {
36 State { font_source: FontSource::Default }
37 }
38
39 #[cfg(unix)]
40 fn update_font(&mut self, shell: &mut Shell) {
41 if self.font_source == FontSource::Rpc {
43 return;
44 }
45
46 if let Some(ref font_name) =
47 self.gnome_interface_settings.get_string(
48 "monospace-font-name",
49 )
50 {
51 shell.set_font_desc(font_name);
52 self.font_source = FontSource::Gnome;
53 }
54 }
55}
56
57pub struct Settings {
58 shell: Option<Weak<RefCell<Shell>>>,
59 state: Rc<RefCell<State>>,
60}
61
62impl Settings {
63 pub fn new() -> Settings {
64 Settings {
65 shell: None,
66 state: Rc::new(RefCell::new(State::new())),
67 }
68 }
69
70 pub fn set_shell(&mut self, shell: Weak<RefCell<Shell>>) {
71 self.shell = Some(shell);
72 }
73
74 #[cfg(unix)]
75 pub fn init(&mut self) {
76 let shell = Weak::upgrade(self.shell.as_ref().unwrap()).unwrap();
77 let state = self.state.clone();
78 self.state.borrow_mut().update_font(
79 &mut *shell.borrow_mut(),
80 );
81 self.state
82 .borrow()
83 .gnome_interface_settings
84 .connect_changed(move |_, _| {
85 monospace_font_changed(&mut *shell.borrow_mut(), &mut *state.borrow_mut())
86 });
87 }
88
89 #[cfg(target_os = "windows")]
90 pub fn init(&mut self) {}
91
92 pub fn set_font_source(&mut self, src: FontSource) {
93 self.state.borrow_mut().font_source = src;
94 }
95}
96
97#[cfg(unix)]
98fn monospace_font_changed(mut shell: &mut Shell, state: &mut State) {
99 if state.font_source != FontSource::Rpc {
101 state.update_font(&mut shell);
102 }
103}
104
105use std::path::Path;
106use std::fs::File;
107use std::io::prelude::*;
108
109use toml;
110use serde;
111
112use crate::dirs;
113
114pub trait SettingsLoader: Sized + serde::Serialize + Default {
115 const SETTINGS_FILE: &'static str;
116
117 fn from_str(s: &str) -> Result<Self, String>;
118
119 fn load() -> Self {
120 match load_err() {
121 Ok(settings) => settings,
122 Err(e) => {
123 error!("{}", e);
124 Default::default()
125 }
126 }
127 }
128
129 fn is_file_exists() -> bool {
130 if let Ok(mut toml_path) = dirs::get_app_config_dir() {
131 toml_path.push(Self::SETTINGS_FILE);
132 toml_path.is_file()
133 } else {
134 false
135 }
136 }
137
138 fn save(&self) {
139 match save_err(self) {
140 Ok(()) => (),
141 Err(e) => error!("{}", e),
142 }
143 }
144}
145
146fn load_from_file<T: SettingsLoader>(path: &Path) -> Result<T, String> {
147 if path.exists() {
148 let mut file = File::open(path).map_err(|e| format!("{}", e))?;
149 let mut contents = String::new();
150 file.read_to_string(&mut contents).map_err(
151 |e| format!("{}", e),
152 )?;
153 T::from_str(&contents)
154 } else {
155 Ok(Default::default())
156 }
157}
158
159fn load_err<T: SettingsLoader>() -> Result<T, String> {
160 let mut toml_path = dirs::get_app_config_dir_create()?;
161 toml_path.push(T::SETTINGS_FILE);
162 load_from_file(&toml_path)
163}
164
165
166fn save_err<T: SettingsLoader>(sl: &T) -> Result<(), String> {
167 let mut toml_path = dirs::get_app_config_dir_create()?;
168 toml_path.push(T::SETTINGS_FILE);
169 let mut file = File::create(toml_path).map_err(|e| format!("{}", e))?;
170
171 let contents = toml::to_vec::<T>(sl).map_err(|e| format!("{}", e))?;
172
173 file.write_all(&contents).map_err(|e| format!("{}", e))?;
174
175 Ok(())
176}