@@ -24,112 +24,76 @@ pub type Locale<'a> = Cow<'a, str>;
24
24
pub type LocaleMap < ' a > = BTreeMap < Locale < ' a > , Value < ' a > > ;
25
25
pub type Value < ' a > = Cow < ' a , str > ;
26
26
27
- #[ derive( Debug ) ]
27
+ #[ derive( Debug , Clone ) ]
28
28
pub struct DesktopEntry < ' a > {
29
29
pub appid : Cow < ' a , str > ,
30
30
pub groups : Groups < ' a > ,
31
31
pub path : Cow < ' a , Path > ,
32
32
pub ubuntu_gettext_domain : Option < Cow < ' a , str > > ,
33
33
}
34
34
35
+ impl DesktopEntry < ' _ > {
36
+ /// Construct a new [`DesktopEntry`] from an appid. The name field will be
37
+ /// set to that appid.
38
+ pub fn from_appid < ' a > ( appid : & ' a str ) -> DesktopEntry < ' a > {
39
+ let mut de = DesktopEntry {
40
+ appid : Cow :: Borrowed ( appid) ,
41
+ groups : Groups :: default ( ) ,
42
+ path : Cow :: Owned ( PathBuf :: from ( "" ) ) ,
43
+ ubuntu_gettext_domain : None ,
44
+ } ;
45
+ de. add_desktop_entry ( "Name" , appid) ;
46
+ de
47
+ }
48
+ }
49
+
35
50
impl < ' a > DesktopEntry < ' a > {
36
- pub fn into_owned ( self ) -> DesktopEntry < ' static > {
51
+ // note that we shoudn't implement ToOwned in this case: https://stackoverflow.com/questions/72105604/implement-toowned-for-user-defined-types
52
+ pub fn to_owned ( & self ) -> DesktopEntry < ' static > {
37
53
let mut new_groups = Groups :: new ( ) ;
38
54
39
- for ( group, key_map) in self . groups {
55
+ for ( group, key_map) in & self . groups {
40
56
let mut new_key_map = KeyMap :: new ( ) ;
41
57
42
58
for ( key, ( value, locale_map) ) in key_map {
43
59
let mut new_locale_map = LocaleMap :: new ( ) ;
44
60
45
61
for ( locale, value) in locale_map {
46
62
new_locale_map. insert (
47
- Cow :: Owned ( locale. into_owned ( ) ) ,
48
- Cow :: Owned ( value. into_owned ( ) ) ,
63
+ Cow :: Owned ( locale. to_string ( ) ) ,
64
+ Cow :: Owned ( value. to_string ( ) ) ,
49
65
) ;
50
66
}
51
67
52
68
new_key_map. insert (
53
- Cow :: Owned ( key. into_owned ( ) ) ,
54
- ( Cow :: Owned ( value. into_owned ( ) ) , new_locale_map) ,
69
+ Cow :: Owned ( key. to_string ( ) ) ,
70
+ ( Cow :: Owned ( value. to_string ( ) ) , new_locale_map) ,
55
71
) ;
56
72
}
57
73
58
- new_groups. insert ( Cow :: Owned ( group. into_owned ( ) ) , new_key_map) ;
74
+ new_groups. insert ( Cow :: Owned ( group. to_string ( ) ) , new_key_map) ;
59
75
}
60
76
61
77
DesktopEntry {
62
- appid : Cow :: Owned ( self . appid . into_owned ( ) ) ,
78
+ appid : Cow :: Owned ( self . appid . to_string ( ) ) ,
63
79
groups : new_groups,
64
- ubuntu_gettext_domain : self
65
- . ubuntu_gettext_domain
66
- . map ( |e| Cow :: Owned ( e. into_owned ( ) ) ) ,
67
- path : Cow :: Owned ( self . path . into_owned ( ) ) ,
80
+ ubuntu_gettext_domain : if let Some ( ubuntu_gettext_domain) = & self . ubuntu_gettext_domain
81
+ {
82
+ Some ( Cow :: Owned ( ubuntu_gettext_domain. to_string ( ) ) )
83
+ } else {
84
+ None
85
+ } ,
86
+ path : Cow :: Owned ( self . path . to_path_buf ( ) ) ,
68
87
}
69
88
}
70
89
}
71
90
72
91
impl < ' a > DesktopEntry < ' a > {
73
- /// An action is defined as `[Desktop Action actions-name]` where `action-name`
74
- /// is defined in the `Actions` field of `[Desktop Entry]`.
75
- /// Example: to get the `Name` field of this `new-window` action
76
- /// ```txt
77
- /// [Desktop Action new-window]
78
- /// Name=Open a New Window
79
- /// ```
80
- /// you will need to call
81
- /// ```rust
82
- /// entry.action_entry("new-window", "Name")
83
- /// ```
84
- pub fn action_entry ( & ' a self , action : & str , key : & str ) -> Option < & ' a str > {
85
- let group = self
86
- . groups
87
- . get ( [ "Desktop Action " , action] . concat ( ) . as_str ( ) ) ;
88
-
89
- Self :: entry ( group, key)
90
- }
91
-
92
- pub fn action_entry_localized < L : AsRef < str > > (
93
- & ' a self ,
94
- action : & str ,
95
- key : & str ,
96
- locales : & [ L ] ,
97
- ) -> Option < Cow < ' a , str > > {
98
- let group = self
99
- . groups
100
- . get ( [ "Desktop Action " , action] . concat ( ) . as_str ( ) ) ;
101
-
102
- Self :: localized_entry ( self . ubuntu_gettext_domain . as_deref ( ) , group, key, locales)
103
- }
104
-
105
- pub fn action_exec ( & ' a self , action : & str ) -> Option < & ' a str > {
106
- self . action_entry ( action, "Exec" )
107
- }
108
-
109
- pub fn action_name < L : AsRef < str > > (
110
- & ' a self ,
111
- action : & str ,
112
- locales : & [ L ] ,
113
- ) -> Option < Cow < ' a , str > > {
114
- self . action_entry_localized ( action, "Name" , locales)
115
- }
116
-
117
- /// Return actions separated by `;`
118
- pub fn actions ( & ' a self ) -> Option < & ' a str > {
119
- self . desktop_entry ( "Actions" )
120
- }
121
-
122
- /// Return categories separated by `;`
123
- pub fn categories ( & ' a self ) -> Option < & ' a str > {
124
- self . desktop_entry ( "Categories" )
125
- }
126
-
127
- pub fn comment < L : AsRef < str > > ( & ' a self , locales : & [ L ] ) -> Option < Cow < ' a , str > > {
128
- self . desktop_entry_localized ( "Comment" , locales)
92
+ pub fn id ( & ' a self ) -> & ' a str {
93
+ self . appid . as_ref ( )
129
94
}
130
95
131
- /// A desktop entry field is any field under the
132
- /// `[Desktop Entry]` line
96
+ /// A desktop entry field is any field under the `[Desktop Entry]` section.
133
97
pub fn desktop_entry ( & ' a self , key : & str ) -> Option < & ' a str > {
134
98
Self :: entry ( self . groups . get ( "Desktop Entry" ) , key) . map ( |e| e. as_ref ( ) )
135
99
}
@@ -147,12 +111,30 @@ impl<'a> DesktopEntry<'a> {
147
111
)
148
112
}
149
113
150
- pub fn exec ( & ' a self ) -> Option < & ' a str > {
151
- self . desktop_entry ( "Exec" )
114
+ /// Insert a new field to this [`DesktopEntry`], in the `[Desktop Entry]` section, removing
115
+ /// the previous value and locales in any.
116
+ pub fn add_desktop_entry < ' b > ( & ' b mut self , key : & ' a str , value : & ' a str )
117
+ where
118
+ ' a : ' b ,
119
+ {
120
+ let action_key = "Desktop Entry" ;
121
+ let key = Cow :: Borrowed ( key) ;
122
+ let value = ( Cow :: Borrowed ( value) , LocaleMap :: default ( ) ) ;
123
+
124
+ match self . groups . get_mut ( action_key) {
125
+ Some ( keymap) => {
126
+ keymap. insert ( key, value) ;
127
+ }
128
+ None => {
129
+ let mut keymap = KeyMap :: default ( ) ;
130
+ keymap. insert ( key, value) ;
131
+ self . groups . insert ( Cow :: Borrowed ( action_key) , keymap) ;
132
+ }
133
+ }
152
134
}
153
135
154
- pub fn flatpak ( & ' a self ) -> Option < & ' a str > {
155
- self . desktop_entry ( "X-Flatpak" )
136
+ pub fn name < L : AsRef < str > > ( & ' a self , locales : & [ L ] ) -> Option < Cow < ' a , str > > {
137
+ self . desktop_entry_localized ( "Name" , locales )
156
138
}
157
139
158
140
pub fn generic_name < L : AsRef < str > > ( & ' a self , locales : & [ L ] ) -> Option < Cow < ' a , str > > {
@@ -163,8 +145,18 @@ impl<'a> DesktopEntry<'a> {
163
145
self . desktop_entry ( "Icon" )
164
146
}
165
147
166
- pub fn id ( & ' a self ) -> & ' a str {
167
- self . appid . as_ref ( )
148
+ /// This is an human readable description of the desktop file.
149
+ pub fn comment < L : AsRef < str > > ( & ' a self , locales : & [ L ] ) -> Option < Cow < ' a , str > > {
150
+ self . desktop_entry_localized ( "Comment" , locales)
151
+ }
152
+
153
+ pub fn exec ( & ' a self ) -> Option < & ' a str > {
154
+ self . desktop_entry ( "Exec" )
155
+ }
156
+
157
+ /// Return categories separated by `;`
158
+ pub fn categories ( & ' a self ) -> Option < & ' a str > {
159
+ self . desktop_entry ( "Categories" )
168
160
}
169
161
170
162
/// Return keywords separated by `;`
@@ -177,10 +169,6 @@ impl<'a> DesktopEntry<'a> {
177
169
self . desktop_entry ( "MimeType" )
178
170
}
179
171
180
- pub fn name < L : AsRef < str > > ( & ' a self , locales : & [ L ] ) -> Option < Cow < ' a , str > > {
181
- self . desktop_entry_localized ( "Name" , locales)
182
- }
183
-
184
172
pub fn no_display ( & ' a self ) -> bool {
185
173
self . desktop_entry_bool ( "NoDisplay" )
186
174
}
@@ -189,6 +177,10 @@ impl<'a> DesktopEntry<'a> {
189
177
self . desktop_entry ( "OnlyShowIn" )
190
178
}
191
179
180
+ pub fn flatpak ( & ' a self ) -> Option < & ' a str > {
181
+ self . desktop_entry ( "X-Flatpak" )
182
+ }
183
+
192
184
pub fn prefers_non_default_gpu ( & ' a self ) -> bool {
193
185
self . desktop_entry_bool ( "PrefersNonDefaultGPU" )
194
186
}
@@ -209,6 +201,55 @@ impl<'a> DesktopEntry<'a> {
209
201
self . desktop_entry ( "Type" )
210
202
}
211
203
204
+ /// Return actions separated by `;`
205
+ pub fn actions ( & ' a self ) -> Option < & ' a str > {
206
+ self . desktop_entry ( "Actions" )
207
+ }
208
+
209
+ /// An action is defined as `[Desktop Action actions-name]` where `action-name`
210
+ /// is defined in the `Actions` field of `[Desktop Entry]`.
211
+ /// Example: to get the `Name` field of this `new-window` action
212
+ /// ```txt
213
+ /// [Desktop Action new-window]
214
+ /// Name=Open a New Window
215
+ /// ```
216
+ /// you will need to call
217
+ /// ```rust
218
+ /// entry.action_entry("new-window", "Name")
219
+ /// ```
220
+ pub fn action_entry ( & ' a self , action : & str , key : & str ) -> Option < & ' a str > {
221
+ let group = self
222
+ . groups
223
+ . get ( [ "Desktop Action " , action] . concat ( ) . as_str ( ) ) ;
224
+
225
+ Self :: entry ( group, key)
226
+ }
227
+
228
+ pub fn action_entry_localized < L : AsRef < str > > (
229
+ & ' a self ,
230
+ action : & str ,
231
+ key : & str ,
232
+ locales : & [ L ] ,
233
+ ) -> Option < Cow < ' a , str > > {
234
+ let group = self
235
+ . groups
236
+ . get ( [ "Desktop Action " , action] . concat ( ) . as_str ( ) ) ;
237
+
238
+ Self :: localized_entry ( self . ubuntu_gettext_domain . as_deref ( ) , group, key, locales)
239
+ }
240
+
241
+ pub fn action_name < L : AsRef < str > > (
242
+ & ' a self ,
243
+ action : & str ,
244
+ locales : & [ L ] ,
245
+ ) -> Option < Cow < ' a , str > > {
246
+ self . action_entry_localized ( action, "Name" , locales)
247
+ }
248
+
249
+ pub fn action_exec ( & ' a self , action : & str ) -> Option < & ' a str > {
250
+ self . action_entry ( action, "Exec" )
251
+ }
252
+
212
253
fn desktop_entry_bool ( & ' a self , key : & str ) -> bool {
213
254
self . desktop_entry ( key) . map_or ( false , |v| v == "true" )
214
255
}
0 commit comments