Skip to main content

applications/
action.rs

1use configparser::ini::Ini;
2
3use crate::private_prelude::*;
4
5pub(crate) struct Action {
6    id: String,
7    ini: Ini,
8    name: String,
9}
10
11impl Action {
12    fn get_section(id: &str) -> String {
13        format!("Desktop Action {}", id)
14    }
15
16    pub(crate) fn new(id: String, ini: Ini) -> Option<Self> {
17        Some(Self {
18            name: ini.get(&Self::get_section(&id), "Name")?,
19            id,
20            ini,
21        })
22    }
23}
24
25/// A handle which represents a desktop application action.
26pub struct ActionHandle {
27    pub(crate) inner: Arc<Action>,
28    pub(crate) service: ApplicationService,
29}
30
31impl ActionHandle {
32    fn get_section(&self) -> String {
33        Action::get_section(&self.inner.id)
34    }
35
36    fn get_value(&self, key: &str) -> Option<String> {
37        self.inner.ini.get(&self.get_section(), key)
38    }
39
40    fn get_value_locale(&self, key: &str) -> Option<String> {
41        utils::get_locale_string(
42            &self.inner.ini,
43            &self.get_section(),
44            key,
45            &self.service.inner.locale,
46        )
47    }
48
49    /// Returns the name of the action.
50    ///
51    /// For example: `Launch in new window`.
52    pub fn name(&self) -> String {
53        self.inner.name.clone()
54    }
55
56    /// Returns the localized name of the action.
57    pub fn name_locale(&self) -> String {
58        self.get_value_locale("Name").unwrap_or_else(|| self.name())
59    }
60
61    /// Returns the icon of the action.
62    pub fn icon(&self) -> Option<String> {
63        self.get_value("Icon")
64    }
65
66    /// Returns the localized icon of the action.
67    pub fn icon_locale(&self) -> Option<String> {
68        self.get_value_locale("Icon").or_else(|| self.icon())
69    }
70
71    /// Returns the exec string of the action.
72    pub fn exec(&self) -> Option<String> {
73        self.get_value("Exec")
74    }
75
76    fn terminal(&self) -> bool {
77        self.inner
78            .ini
79            .getbool("Desktop Entry", "Terminal")
80            .ok()
81            .flatten()
82            .unwrap_or(false)
83    }
84
85    /// Launches the action.
86    pub fn launch(&self) -> Result<()> {
87        utils::launch_from_exec_string(self.exec(), self.terminal())
88    }
89}
90
91#[cfg(test)]
92mod tests {
93    use super::*;
94    use configparser::ini::Ini;
95
96    fn new_handle(id: &str, contents: String, locale: &str) -> ActionHandle {
97        let mut ini = Ini::new();
98        ini.read(contents).unwrap();
99
100        ActionHandle {
101            inner: Arc::new(Action::new(String::from(id), ini).unwrap()),
102            service: ApplicationService::new_with_env(vec![], locale),
103        }
104    }
105    #[test]
106    fn test_properties() {
107        let contents = String::from(
108            r#"[Desktop Action Meow]
109Name=Meow
110Name[en]=Meow english
111Icon=some-icon
112Exec=ls"#,
113        );
114
115        let handle = new_handle("Meow", contents, "en");
116
117        assert_eq!(handle.name(), "Meow");
118        assert_eq!(handle.name_locale(), "Meow english");
119        assert_eq!(handle.icon().unwrap(), "some-icon");
120        assert_eq!(handle.exec().unwrap(), "ls");
121    }
122
123    #[test]
124    #[should_panic]
125    fn test_invalid() {
126        // entry without name
127        let contents = String::from(
128            r#"[Desktop Action Meow]
129Icon=some-icon
130Exec=ls"#,
131        );
132
133        new_handle("Meow", contents, "");
134    }
135}