No issues found
Tool | Failure ID | Location | Function | Message | Data |
---|---|---|---|---|---|
clang-analyzer | no-output-found | e-ui-manager.c | Message(text='Unable to locate XML output from invoke-clang-analyzer') | None | |
clang-analyzer | no-output-found | e-ui-manager.c | Message(text='Unable to locate XML output from invoke-clang-analyzer') | None |
1 /*
2 * e-ui-manager.c
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) version 3.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with the program; if not, see <http://www.gnu.org/licenses/>
16 *
17 */
18
19 /**
20 * SECTION: e-ui-manager
21 * @short_description: construct menus and toolbars from a UI definition
22 * @include: e-util/e-ui-manager.h
23 *
24 * This is a #GtkUIManager with support for Evolution's "express" mode,
25 * which influences the parsing of UI definitions.
26 **/
27
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31
32 #include "e-ui-manager.h"
33 #include "e-util-private.h"
34
35 #include <string.h>
36
37 #define E_UI_MANAGER_GET_PRIVATE(obj) \
38 (G_TYPE_INSTANCE_GET_PRIVATE \
39 ((obj), E_TYPE_UI_MANAGER, EUIManagerPrivate))
40
41 /*
42 * --- NOTE TO SELF ---
43 *
44 * While creating this class I was tempted to add an "id" property which
45 * EPluginUI could extract from a given EUIManager instead of having the
46 * public EPluginUI functions take a separate "id" argument. Seemed like
47 * a nice cleanup until I remembered that an EUIManager instance can have
48 * multiple IDs ("aliases"), as in the case of EShellWindow's UI manager.
49 * So the UI Manager ID and the instance still need to be kept separate.
50 *
51 * Mentioning it here in case I forget why I didn't go through with it.
52 */
53
54 struct _EUIManagerPrivate {
55 guint express_mode : 1;
56 };
57
58 enum {
59 PROP_0,
60 PROP_EXPRESS_MODE
61 };
62
63 G_DEFINE_TYPE (
64 EUIManager,
65 e_ui_manager,
66 GTK_TYPE_UI_MANAGER)
67
68 static void
69 ui_manager_set_property (GObject *object,
70 guint property_id,
71 const GValue *value,
72 GParamSpec *pspec)
73 {
74 switch (property_id) {
75 case PROP_EXPRESS_MODE:
76 e_ui_manager_set_express_mode (
77 E_UI_MANAGER (object),
78 g_value_get_boolean (value));
79 return;
80 }
81
82 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
83 }
84
85 static void
86 ui_manager_get_property (GObject *object,
87 guint property_id,
88 GValue *value,
89 GParamSpec *pspec)
90 {
91 switch (property_id) {
92 case PROP_EXPRESS_MODE:
93 g_value_set_boolean (
94 value, e_ui_manager_get_express_mode (
95 E_UI_MANAGER (object)));
96 return;
97 }
98
99 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
100 }
101
102 static gchar *
103 ui_manager_filter_ui (EUIManager *ui_manager,
104 const gchar *ui_definition)
105 {
106 gchar **lines;
107 gchar *filtered;
108 gboolean express_mode;
109 gboolean include = TRUE;
110 gint ii;
111
112 express_mode = e_ui_manager_get_express_mode (ui_manager);
113
114 /*
115 * Very simple C style pre-processing in-line in the XML:
116 * #if [!]EXPRESS\n ... \n#endif\n
117 */
118 lines = g_strsplit (ui_definition, "\n", -1);
119
120 for (ii = 0; lines[ii] != NULL; ii++) {
121 if (lines[ii][0] == '#') {
122 if (!strncmp (lines[ii], "#if ", 4)) {
123 gboolean not_express = lines[ii][4] == '!';
124 include = express_mode ^ not_express;
125 lines[ii][0] = '\0';
126 } else if (!strncmp (lines[ii], "#endif", 6)) {
127 lines[ii][0] = '\0';
128 include = TRUE;
129 }
130 }
131 if (!include)
132 lines[ii][0] = '\0';
133 }
134
135 filtered = g_strjoinv ("\n", lines);
136
137 g_strfreev (lines);
138
139 return filtered;
140 }
141
142 static void
143 e_ui_manager_class_init (EUIManagerClass *class)
144 {
145 GObjectClass *object_class;
146
147 g_type_class_add_private (class, sizeof (EUIManagerPrivate));
148
149 object_class = G_OBJECT_CLASS (class);
150 object_class->set_property = ui_manager_set_property;
151 object_class->get_property = ui_manager_get_property;
152
153 class->filter_ui = ui_manager_filter_ui;
154
155 g_object_class_install_property (
156 object_class,
157 PROP_EXPRESS_MODE,
158 g_param_spec_boolean (
159 "express-mode",
160 "Express Mode",
161 NULL,
162 FALSE,
163 G_PARAM_READWRITE |
164 G_PARAM_CONSTRUCT));
165 }
166
167 static void
168 e_ui_manager_init (EUIManager *ui_manager)
169 {
170 ui_manager->priv = E_UI_MANAGER_GET_PRIVATE (ui_manager);
171 }
172
173 /**
174 * e_ui_manager_new:
175 *
176 * Returns a new #EUIManager instance.
177 *
178 * Returns: a new #EUIManager instance
179 **/
180 GtkUIManager *
181 e_ui_manager_new (void)
182 {
183 return g_object_new (E_TYPE_UI_MANAGER, NULL);
184 }
185
186 /**
187 * e_ui_manager_get_express_mode:
188 * @ui_manager: an #EUIManager
189 *
190 * Returns the "express mode" flag in @ui_manager.
191 *
192 * Returns: %TRUE if @ui_manager is set to express mode
193 **/
194 gboolean
195 e_ui_manager_get_express_mode (EUIManager *ui_manager)
196 {
197 g_return_val_if_fail (E_IS_UI_MANAGER (ui_manager), FALSE);
198
199 return ui_manager->priv->express_mode;
200 }
201
202 /**
203 * e_ui_manager_set_express_mode:
204 * @ui_manager: an #EUIManager
205 * @express_mode: express mode flag
206 *
207 * Sets the "express mode" flag in @ui_manager, which influences how
208 * UI definitions are loaded.
209 **/
210 void
211 e_ui_manager_set_express_mode (EUIManager *ui_manager,
212 gboolean express_mode)
213 {
214 g_return_if_fail (E_IS_UI_MANAGER (ui_manager));
215
216 if (ui_manager->priv->express_mode == express_mode)
217 return;
218
219 ui_manager->priv->express_mode = express_mode;
220
221 g_object_notify (G_OBJECT (ui_manager), "express-mode");
222 }
223
224 /**
225 * e_ui_manager_add_ui_from_file:
226 * @ui_manager: an #EUIManager
227 * @basename: basename of the UI definition file
228 *
229 * Loads a UI definition into @ui_manager from Evolution's UI directory.
230 * If the EUIManager:express-mode property is %TRUE, a simplified version
231 * of the UI may be presented.
232 *
233 * Failure here is fatal, since the application can't function without
234 * its core UI definitions.
235 *
236 * Returns: The merge ID for the merged UI. The merge ID can be used to
237 * unmerge the UI with gtk_ui_manager_remove_ui().
238 **/
239 guint
240 e_ui_manager_add_ui_from_file (EUIManager *ui_manager,
241 const gchar *basename)
242 {
243 EUIManagerClass *class;
244 gchar *filename;
245 gchar *contents;
246 guint merge_id = 0;
247 GError *error = NULL;
248
249 g_return_val_if_fail (E_IS_UI_MANAGER (ui_manager), 0);
250 g_return_val_if_fail (basename != NULL, 0);
251
252 class = E_UI_MANAGER_GET_CLASS (ui_manager);
253 g_return_val_if_fail (class->filter_ui != NULL, 0);
254
255 filename = g_build_filename (EVOLUTION_UIDIR, basename, NULL);
256
257 if (g_file_get_contents (filename, &contents, NULL, &error)) {
258 gchar *filtered;
259
260 /* We could call e_ui_manager_add_ui_from_string() here,
261 * but if an error occurs we'd like to include the file
262 * name in the error message. */
263
264 filtered = class->filter_ui (ui_manager, contents);
265
266 merge_id = gtk_ui_manager_add_ui_from_string (
267 GTK_UI_MANAGER (ui_manager), filtered, -1, &error);
268
269 g_free (filtered);
270 g_free (contents);
271 }
272
273 g_free (filename);
274
275 if (error != NULL) {
276 g_error ("%s: %s", basename, error->message);
277 g_assert_not_reached ();
278 }
279
280 return merge_id;
281 }
282
283 /**
284 * e_ui_manager_add_ui_from_string:
285 * @ui_manager: an #EUIManager
286 * @ui_definition: the UI XML in NULL terminated string form
287 * @error: return location for a #GError, or %NULL
288 *
289 * Loads the given UI definition into @ui_manager. If the
290 * EUIManager:express-mode property is %TRUE, a simplified version of
291 * the UI may be presented.
292 *
293 * Failure here is <i>not</i> fatal, since the function is primarily
294 * used to load UI definitions for plugins, which we can get by without.
295 *
296 * Returns: The merge ID for the merged UI. The merge ID can be used to
297 * unmerge the UI with gtk_ui_manager_remove_ui().
298 **/
299 guint
300 e_ui_manager_add_ui_from_string (EUIManager *ui_manager,
301 const gchar *ui_definition,
302 GError **error)
303 {
304 EUIManagerClass *class;
305 gchar *filtered;
306 guint merge_id;
307
308 g_return_val_if_fail (E_IS_UI_MANAGER (ui_manager), 0);
309 g_return_val_if_fail (ui_definition != NULL, 0);
310
311 class = E_UI_MANAGER_GET_CLASS (ui_manager);
312 g_return_val_if_fail (class->filter_ui != NULL, 0);
313
314 filtered = class->filter_ui (ui_manager, ui_definition);
315
316 merge_id = gtk_ui_manager_add_ui_from_string (
317 GTK_UI_MANAGER (ui_manager), filtered, -1, error);
318
319 g_free (filtered);
320
321 return merge_id;
322 }