No issues found
Tool | Failure ID | Location | Function | Message | Data |
---|---|---|---|---|---|
clang-analyzer | no-output-found | evolution-plugin-manager.c | Message(text='Unable to locate XML output from invoke-clang-analyzer') | None | |
clang-analyzer | no-output-found | evolution-plugin-manager.c | Message(text='Unable to locate XML output from invoke-clang-analyzer') | None |
1 /*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU Lesser General Public
4 * License as published by the Free Software Foundation; either
5 * version 2 of the License, or (at your option) version 3.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * Lesser General Public License for more details.
11 *
12 * You should have received a copy of the GNU Lesser General Public
13 * License along with the program; if not, see <http://www.gnu.org/licenses/>
14 *
15 */
16
17 /* A plugin manager ui */
18
19 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
22
23 #include <string.h>
24 #include <stdio.h>
25 #include <glib/gi18n-lib.h>
26 #include <libebackend/libebackend.h>
27
28 #include <e-util/e-plugin.h>
29 #include <shell/e-shell-window.h>
30 #include <shell/e-shell-window-actions.h>
31
32 /* Standard GObject macros */
33 #define E_TYPE_PLUGIN_MANAGER \
34 (e_plugin_manager_get_type ())
35 #define E_PLUGIN_MANAGER(obj) \
36 (G_TYPE_CHECK_INSTANCE_CAST \
37 ((obj), E_TYPE_PLUGIN_MANAGER, EPluginManager))
38
39 typedef struct _EPluginManager EPluginManager;
40 typedef struct _EPluginManagerClass EPluginManagerClass;
41
42 struct _EPluginManager {
43 EExtension parent;
44 };
45
46 struct _EPluginManagerClass {
47 EExtensionClass parent_class;
48 };
49
50 enum {
51 LABEL_NAME,
52 LABEL_AUTHOR,
53 LABEL_DESCRIPTION,
54 LABEL_LAST
55 };
56
57 enum
58 {
59 COL_PLUGIN_ENABLED = 0,
60 COL_PLUGIN_NAME,
61 COL_PLUGIN_DATA,
62 COL_PLUGIN_CFG_WIDGET
63 };
64
65 static struct {
66 const gchar *label;
67 } label_info[LABEL_LAST] = {
68 { N_("Name"), },
69 { N_("Author(s)"), },
70 { N_("Description"), },
71 };
72
73 typedef struct _Manager Manager;
74 struct _Manager {
75 GtkLabel *labels[LABEL_LAST];
76 GtkLabel *items[LABEL_LAST];
77
78 GtkWidget *config_plugin_label;
79 GtkWidget *active_cfg_widget;
80 };
81
82 /* for tracking if we're shown */
83 static GtkWidget *notebook;
84 static GtkWidget *configure_page;
85 static gint last_selected_page;
86 static gulong switch_page_handler_id;
87
88 /* Module Entry Points */
89 void e_module_load (GTypeModule *type_module);
90 void e_module_unload (GTypeModule *type_module);
91
92 /* Forward Declarations */
93 GType e_plugin_manager_get_type (void);
94
95 G_DEFINE_DYNAMIC_TYPE (EPluginManager, e_plugin_manager, E_TYPE_EXTENSION)
96
97 static void
98 eppm_set_label (GtkLabel *l,
99 const gchar *v)
100 {
101 gtk_label_set_label (l, v ? v:_("Unknown"));
102 }
103
104 static void
105 eppm_switch_page_cb (GtkNotebook *notebook,
106 GtkWidget *page,
107 guint page_num)
108 {
109 last_selected_page = page_num;
110 }
111
112 static void
113 eppm_show_plugin (Manager *m,
114 EPlugin *ep,
115 GtkWidget *cfg_widget)
116 {
117 if (ep) {
118 gchar *string;
119
120 string = g_markup_printf_escaped ("<b>%s</b>", ep->name);
121 gtk_label_set_markup (GTK_LABEL (m->items[LABEL_NAME]), string);
122 gtk_label_set_markup (GTK_LABEL (m->config_plugin_label), string);
123 g_free (string);
124
125 if (ep->authors) {
126 GSList *l = ep->authors;
127 GString *out = g_string_new ("");
128
129 for (; l; l = g_slist_next (l)) {
130 EPluginAuthor *epa = l->data;
131
132 if (l != ep->authors)
133 g_string_append (out, ",\n");
134 if (epa->name)
135 g_string_append (out, epa->name);
136 if (epa->email) {
137 g_string_append (out, " <");
138 g_string_append (out, epa->email);
139 g_string_append (out, ">");
140 }
141 }
142 gtk_label_set_label (m->items[LABEL_AUTHOR], out->str);
143 g_string_free (out, TRUE);
144 } else {
145 eppm_set_label (m->items[LABEL_AUTHOR], NULL);
146 }
147
148 eppm_set_label (m->items[LABEL_DESCRIPTION], ep->description);
149 } else {
150 gint i;
151
152 gtk_label_set_markup (GTK_LABEL (m->config_plugin_label), "");
153 for (i = 0; i < LABEL_LAST; i++)
154 gtk_label_set_label (m->items[i], "");
155 }
156
157 if (cfg_widget != NULL)
158 gtk_notebook_append_page_menu (
159 GTK_NOTEBOOK (notebook), configure_page,
160 gtk_label_new (_("Configuration")), NULL);
161
162 if (m->active_cfg_widget != cfg_widget) {
163 if (m->active_cfg_widget)
164 gtk_widget_hide (m->active_cfg_widget);
165
166 if (cfg_widget)
167 gtk_widget_show (cfg_widget);
168
169 m->active_cfg_widget = cfg_widget;
170 }
171 }
172
173 static void
174 eppm_selection_changed (GtkTreeSelection *selection,
175 Manager *m)
176 {
177 GtkTreeModel *model;
178 GtkTreeIter iter;
179
180 g_signal_handler_block (notebook, switch_page_handler_id);
181 gtk_notebook_remove_page (GTK_NOTEBOOK (notebook), 1);
182 g_signal_handler_unblock (notebook, switch_page_handler_id);
183
184 if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
185 EPlugin *ep;
186 GtkWidget *cfg_widget = NULL;
187
188 gtk_tree_model_get (
189 model, &iter,
190 COL_PLUGIN_DATA, &ep,
191 COL_PLUGIN_CFG_WIDGET, &cfg_widget, -1);
192 eppm_show_plugin (m, ep, cfg_widget);
193
194 } else {
195 eppm_show_plugin (m, NULL, NULL);
196 }
197
198 g_signal_handler_block (notebook, switch_page_handler_id);
199 gtk_notebook_set_current_page (
200 GTK_NOTEBOOK (notebook), last_selected_page);
201 g_signal_handler_unblock (notebook, switch_page_handler_id);
202 }
203
204 static void
205 eppm_enable_toggled (GtkCellRendererToggle *renderer,
206 const gchar *path_string,
207 GtkTreeModel *model)
208 {
209 GtkTreePath *path;
210 GtkTreeIter iter;
211 EPlugin *plugin;
212
213 path = gtk_tree_path_new_from_string (path_string);
214
215 if (gtk_tree_model_get_iter (model, &iter, path)) {
216 gtk_tree_model_get (
217 model, &iter, COL_PLUGIN_DATA, &plugin, -1);
218
219 e_plugin_enable (plugin, !plugin->enabled);
220
221 gtk_list_store_set (
222 GTK_LIST_STORE (model), &iter,
223 COL_PLUGIN_ENABLED, plugin->enabled, -1);
224 }
225
226 gtk_tree_path_free (path);
227 }
228
229 static void
230 action_plugin_manager_cb (GtkAction *action,
231 EExtension *extension)
232 {
233 Manager *m;
234 gint i;
235 GtkWidget *dialog;
236 GtkWidget *hbox, *w;
237 GtkWidget *overview_page;
238 GtkWidget *content_area;
239 GtkListStore *store;
240 GtkTreeView *tree_view;
241 GtkTreeSelection *selection;
242 GtkCellRenderer *renderer;
243 GSList *plugins, *link;
244 gchar *string;
245 GtkWidget *subvbox;
246 EExtensible *extensible;
247
248 m = g_malloc0 (sizeof (*m));
249
250 /* Retrieve the parent EShellWindow. */
251 extensible = e_extension_get_extensible (extension);
252
253 /* Setup the ui */
254 dialog = gtk_dialog_new_with_buttons (
255 _("Plugin Manager"),
256 GTK_WINDOW (extensible),
257 GTK_DIALOG_DESTROY_WITH_PARENT,
258 GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, NULL);
259
260 content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
261
262 gtk_window_set_default_size (GTK_WINDOW (dialog), 640, 400);
263 gtk_container_set_border_width (GTK_CONTAINER (dialog), 6);
264
265 hbox = gtk_hbox_new (FALSE, 12);
266 gtk_container_set_border_width (GTK_CONTAINER (hbox), 6);
267 gtk_box_pack_start (GTK_BOX (content_area), hbox, TRUE, TRUE, 0);
268
269 string = g_markup_printf_escaped (
270 "<i>%s</i>", _("Note: Some changes "
271 "will not take effect until restart"));
272
273 w = g_object_new (
274 GTK_TYPE_LABEL,
275 "label", string,
276 "wrap", FALSE,
277 "use_markup", TRUE, NULL);
278 gtk_widget_show (w);
279 g_free (string);
280
281 gtk_box_pack_start (GTK_BOX (content_area), w, FALSE, TRUE, 12);
282
283 notebook = gtk_notebook_new ();
284 gtk_notebook_set_show_tabs (GTK_NOTEBOOK (notebook), TRUE);
285 gtk_notebook_set_show_border (GTK_NOTEBOOK (notebook), FALSE);
286 gtk_notebook_set_scrollable (GTK_NOTEBOOK (notebook), TRUE);
287
288 switch_page_handler_id = g_signal_connect (
289 notebook, "switch-page",
290 G_CALLBACK (eppm_switch_page_cb), NULL);
291
292 overview_page = gtk_vbox_new (FALSE, 0);
293 configure_page = gtk_vbox_new (FALSE, 0);
294 g_object_ref_sink (configure_page);
295 gtk_container_set_border_width (GTK_CONTAINER (overview_page), 12);
296 gtk_container_set_border_width (GTK_CONTAINER (configure_page), 12);
297 gtk_notebook_append_page_menu (
298 GTK_NOTEBOOK (notebook), overview_page,
299 gtk_label_new (_("Overview")), NULL);
300
301 gtk_widget_show (notebook);
302 gtk_widget_show (overview_page);
303 gtk_widget_show (configure_page);
304
305 /* name of plugin on "Configuration" tab */
306 m->config_plugin_label = g_object_new (
307 GTK_TYPE_LABEL,
308 "wrap", TRUE,
309 "selectable", FALSE,
310 "xalign", 0.0,
311 "yalign", 0.0, NULL);
312 gtk_widget_show (m->config_plugin_label);
313 gtk_box_pack_start (
314 GTK_BOX (configure_page),
315 m->config_plugin_label, FALSE, FALSE, 0);
316
317 store = gtk_list_store_new (
318 4, G_TYPE_BOOLEAN, G_TYPE_STRING,
319 G_TYPE_POINTER, G_TYPE_POINTER);
320
321 /* fill store */
322 plugins = e_plugin_list_plugins ();
323
324 for (link = plugins; link != NULL; link = g_slist_next (link)) {
325 EPlugin *ep = E_PLUGIN (link->data);
326 GtkTreeIter iter;
327 GtkWidget *cfg_widget;
328
329 if (!g_getenv ("EVO_SHOW_ALL_PLUGINS")) {
330 if (ep->flags & E_PLUGIN_FLAGS_SYSTEM_PLUGIN)
331 continue;
332 }
333
334 cfg_widget = e_plugin_get_configure_widget (ep);
335 if (cfg_widget) {
336 gtk_widget_hide (cfg_widget);
337 gtk_box_pack_start (
338 GTK_BOX (configure_page),
339 cfg_widget, TRUE, TRUE, 12);
340 }
341
342 gtk_list_store_append (store, &iter);
343 gtk_list_store_set (
344 store, &iter,
345 COL_PLUGIN_ENABLED, ep->enabled,
346 COL_PLUGIN_NAME, ep->name ? ep->name : ep->id,
347 COL_PLUGIN_DATA, ep,
348 COL_PLUGIN_CFG_WIDGET, cfg_widget, -1);
349 }
350
351 /* setup the treeview */
352 tree_view = GTK_TREE_VIEW (gtk_tree_view_new ());
353 gtk_tree_view_set_reorderable (tree_view, FALSE);
354 gtk_tree_view_set_model (tree_view, GTK_TREE_MODEL (store));
355 gtk_tree_view_set_search_column (tree_view, COL_PLUGIN_NAME);
356 gtk_tree_view_set_headers_visible (tree_view, TRUE);
357
358 renderer = gtk_cell_renderer_toggle_new ();
359 gtk_tree_view_insert_column_with_attributes (
360 tree_view, COL_PLUGIN_ENABLED, _("Enabled"),
361 renderer, "active", COL_PLUGIN_ENABLED, NULL);
362 g_signal_connect (
363 renderer, "toggled",
364 G_CALLBACK (eppm_enable_toggled), store),
365
366 renderer = gtk_cell_renderer_text_new ();
367 gtk_tree_view_insert_column_with_attributes (
368 tree_view, COL_PLUGIN_NAME, _("Plugin"),
369 renderer, "text", COL_PLUGIN_NAME, NULL);
370
371 /* set sort column */
372 gtk_tree_sortable_set_sort_column_id (
373 GTK_TREE_SORTABLE (store),
374 COL_PLUGIN_NAME, GTK_SORT_ASCENDING);
375
376 w = gtk_scrolled_window_new (NULL, NULL);
377 gtk_scrolled_window_set_policy (
378 GTK_SCROLLED_WINDOW (w),
379 GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
380 gtk_scrolled_window_set_shadow_type (
381 GTK_SCROLLED_WINDOW (w), GTK_SHADOW_IN);
382 gtk_container_add (GTK_CONTAINER (w), GTK_WIDGET (tree_view));
383
384 gtk_box_pack_start (GTK_BOX (hbox), GTK_WIDGET (w), FALSE, TRUE, 0);
385
386 /* Show all widgets in hbox before we pack the notebook, because not
387 * all widgets in notebook are going to be visible at one moment. */
388 gtk_widget_show_all (hbox);
389
390 gtk_box_pack_start (GTK_BOX (hbox), notebook, TRUE, TRUE, 0);
391
392 /* this is plugin's name label */
393 subvbox = gtk_vbox_new (FALSE, 6);
394 m->items[0] = g_object_new (
395 GTK_TYPE_LABEL,
396 "wrap", TRUE,
397 "selectable", FALSE,
398 "xalign", 0.0,
399 "yalign", 0.0, NULL);
400 gtk_box_pack_start (
401 GTK_BOX (subvbox),
402 GTK_WIDGET (m->items[0]), TRUE, TRUE, 0);
403 gtk_box_pack_start (
404 GTK_BOX (overview_page), subvbox, FALSE, TRUE, 0);
405
406 /* this is every other data */
407 for (i = 1; i < LABEL_LAST; i++) {
408 gchar *markup;
409
410 subvbox = gtk_vbox_new (FALSE, 6);
411
412 markup = g_markup_printf_escaped (
413 "<span weight=\"bold\">%s:</span>",
414 _(label_info[i].label));
415 m->labels[i] = g_object_new (
416 GTK_TYPE_LABEL,
417 "label", markup,
418 "use_markup", TRUE,
419 "xalign", 0.0,
420 "yalign", 0.0, NULL);
421 gtk_box_pack_start (
422 GTK_BOX (subvbox),
423 GTK_WIDGET (m->labels[i]), FALSE, TRUE, 0);
424 g_free (markup);
425
426 m->items[i] = g_object_new (
427 GTK_TYPE_LABEL,
428 "wrap", TRUE,
429 "selectable", TRUE,
430 "can-focus", FALSE,
431 "xalign", 0.0,
432 "yalign", 0.0, NULL);
433 gtk_box_pack_start (
434 GTK_BOX (subvbox),
435 GTK_WIDGET (m->items[i]), TRUE, TRUE, 0);
436
437 gtk_box_pack_start (
438 GTK_BOX (overview_page), subvbox, FALSE, TRUE, 12);
439 }
440
441 gtk_widget_show_all (overview_page);
442
443 selection = gtk_tree_view_get_selection (tree_view);
444 gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
445 g_signal_connect (
446 selection, "changed",
447 G_CALLBACK (eppm_selection_changed), m);
448
449 atk_object_set_name (
450 gtk_widget_get_accessible (
451 GTK_WIDGET (tree_view)), _("Plugin"));
452
453 gtk_dialog_run (GTK_DIALOG (dialog));
454
455 gtk_widget_destroy (dialog);
456
457 g_slist_foreach (plugins, (GFunc) g_object_unref, NULL);
458 g_slist_free (plugins);
459
460 g_object_unref (store);
461
462 g_free (m);
463 }
464
465 static void
466 plugin_manager_constructed (GObject *object)
467 {
468 EExtensible *extensible;
469 EPluginManager *extension;
470 EShellWindow *shell_window;
471 GtkActionGroup *action_group;
472 GtkUIManager *ui_manager;
473 GtkAction *action;
474 const gchar *action_name;
475 const gchar *action_label;
476 const gchar *action_tooltip;
477 const gchar *widget_path;
478 guint merge_id;
479
480 extension = E_PLUGIN_MANAGER (object);
481 extensible = e_extension_get_extensible (E_EXTENSION (extension));
482
483 shell_window = E_SHELL_WINDOW (extensible);
484 action_group = E_SHELL_WINDOW_ACTION_GROUP_SHELL (shell_window);
485 ui_manager = e_shell_window_get_ui_manager (shell_window);
486 merge_id = gtk_ui_manager_new_merge_id (ui_manager);
487
488 action_name = "plugin-manager";
489 action_label = _("_Plugins");
490 action_tooltip = _("Enable and disable plugins");
491 widget_path = "/main-menu/edit-menu/administrative-actions";
492
493 action = gtk_action_new (
494 action_name, action_label, action_tooltip, NULL);
495
496 g_signal_connect (
497 action, "activate",
498 G_CALLBACK (action_plugin_manager_cb), extension);
499
500 gtk_action_group_add_action (action_group, action);
501
502 gtk_ui_manager_add_ui (
503 ui_manager, merge_id, widget_path, action_name,
504 action_name, GTK_UI_MANAGER_AUTO, FALSE);
505
506 g_object_unref (action);
507
508 /* Chain up to parent's constructed() method. */
509 G_OBJECT_CLASS (e_plugin_manager_parent_class)->constructed (object);
510 }
511
512 static void
513 e_plugin_manager_class_init (EPluginManagerClass *class)
514 {
515 GObjectClass *object_class;
516 EExtensionClass *extension_class;
517
518 object_class = G_OBJECT_CLASS (class);
519 object_class->constructed = plugin_manager_constructed;
520
521 extension_class = E_EXTENSION_CLASS (class);
522 extension_class->extensible_type = E_TYPE_SHELL_WINDOW;
523 }
524
525 static void
526 e_plugin_manager_class_finalize (EPluginManagerClass *class)
527 {
528 }
529
530 static void
531 e_plugin_manager_init (EPluginManager *extension)
532 {
533 }
534
535 G_MODULE_EXPORT void
536 e_module_load (GTypeModule *type_module)
537 {
538 e_plugin_manager_register_type (type_module);
539 }
540
541 G_MODULE_EXPORT void
542 e_module_unload (GTypeModule *type_module)
543 {
544 }