1 /*
2 * xfce4-settings-manager
3 *
4 * Copyright (c) 2008 Brian Tarricone <bjt23@cornell.edu>
5 * Jannis Pohlmann <jannis@xfce.org>
6 * Copyright (c) 2012 Nick Schermer <nick@xfce.org>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License ONLY.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #ifdef HAVE_UNISTD_H
27 #include <unistd.h>
28 #endif
29 #ifdef HAVE_STRING_H
30 #include <string.h>
31 #endif
32
33 #include <gtk/gtk.h>
34 #include <gtk/gtkx.h>
35 #include <gdk/gdkkeysyms.h>
36
37 #include <libxfce4util/libxfce4util.h>
38 #include <libxfce4ui/libxfce4ui.h>
39 #include <xfconf/xfconf.h>
40 #include <garcon/garcon.h>
41 #include <exo/exo.h>
42
43 #include "xfce-settings-manager-dialog.h"
44
45 #define TEXT_WIDTH (128)
46 #define ICON_WIDTH (48)
47
48
49
50 struct _XfceSettingsManagerDialogClass
51 {
52 XfceTitledDialogClass __parent__;
53 };
54
55 struct _XfceSettingsManagerDialog
56 {
57 XfceTitledDialog __parent__;
58
59 XfconfChannel *channel;
60 GarconMenu *menu;
61
62 GtkListStore *store;
63
64 GtkWidget *revealer;
65 GtkWidget *filter_button;
66 GtkWidget *filter_entry;
67 gchar *filter_text;
68
69 GtkWidget *category_viewport;
70 GtkWidget *category_scroll;
71 GtkWidget *category_box;
72
73 GList *categories;
74
75 GtkCssProvider *css_provider;
76
77 GtkWidget *socket_scroll;
78 GtkWidget *socket_viewport;
79 GarconMenuItem *socket_item;
80
81 GtkWidget *button_back;
82 GtkWidget *button_help;
83
84 gchar *help_page;
85 gchar *help_component;
86 gchar *help_version;
87 };
88
89 typedef struct
90 {
91 GarconMenuDirectory *directory;
92 XfceSettingsManagerDialog *dialog;
93 GtkWidget *iconview;
94 GtkWidget *box;
95 }
96 DialogCategory;
97
98
99
100 enum
101 {
102 COLUMN_NAME,
103 COLUMN_ICON_NAME,
104 COLUMN_TOOLTIP,
105 COLUMN_MENU_ITEM,
106 COLUMN_MENU_DIRECTORY,
107 COLUMN_FILTER_TEXT,
108 N_COLUMNS
109 };
110
111
112
113 static void xfce_settings_manager_dialog_finalize (GObject *object);
114 static void xfce_settings_manager_dialog_style_updated (GtkWidget *widget);
115 static void xfce_settings_manager_dialog_set_hover_style (XfceSettingsManagerDialog *dialog);
116 static void xfce_settings_manager_dialog_response (GtkDialog *widget,
117 gint response_id);
118 static void xfce_settings_manager_dialog_set_title (XfceSettingsManagerDialog *dialog,
119 const gchar *title,
120 const gchar *icon_name);
121 static void xfce_settings_manager_dialog_go_back (XfceSettingsManagerDialog *dialog);
122 static void xfce_settings_manager_show_filter_toggled (GtkToggleButton *button,
123 gpointer user_data);
124 static void xfce_settings_manager_dialog_entry_changed (GtkWidget *entry,
125 XfceSettingsManagerDialog *dialog);
126 static gboolean xfce_settings_manager_dialog_entry_key_press (GtkWidget *entry,
127 GdkEventKey *event,
128 XfceSettingsManagerDialog *dialog);
129 static void xfce_settings_manager_dialog_menu_reload (XfceSettingsManagerDialog *dialog);
130 static void xfce_settings_manager_dialog_scroll_to_item (GtkWidget *iconview,
131 XfceSettingsManagerDialog *dialog);
132
133
134
G_DEFINE_TYPE(XfceSettingsManagerDialog,xfce_settings_manager_dialog,XFCE_TYPE_TITLED_DIALOG)135 G_DEFINE_TYPE (XfceSettingsManagerDialog, xfce_settings_manager_dialog, XFCE_TYPE_TITLED_DIALOG)
136
137
138
139 static void
140 xfce_settings_manager_dialog_class_init (XfceSettingsManagerDialogClass *klass)
141 {
142 GObjectClass *gobject_class;
143 GtkDialogClass *gtkdialog_class;
144 GtkWidgetClass *gtkwiget_class;
145
146 gobject_class = G_OBJECT_CLASS (klass);
147 gobject_class->finalize = xfce_settings_manager_dialog_finalize;
148
149 gtkwiget_class = GTK_WIDGET_CLASS (klass);
150 gtkwiget_class->style_updated = xfce_settings_manager_dialog_style_updated;
151
152 gtkdialog_class = GTK_DIALOG_CLASS (klass);
153 gtkdialog_class->response = xfce_settings_manager_dialog_response;
154 }
155
156
157
158 static void
xfce_settings_manager_queue_resize(XfceSettingsManagerDialog * dialog)159 xfce_settings_manager_queue_resize (XfceSettingsManagerDialog *dialog)
160 {
161 GList *li;
162 DialogCategory *category;
163
164 for (li = dialog->categories; li != NULL; li = li->next)
165 {
166 category = li->data;
167 gtk_widget_queue_resize (GTK_WIDGET (category->iconview));
168 }
169 }
170
171 static gboolean
xfce_settings_manager_queue_resize_cb(gpointer user_data)172 xfce_settings_manager_queue_resize_cb (gpointer user_data)
173 {
174 XfceSettingsManagerDialog *dialog = user_data;
175
176 xfce_settings_manager_queue_resize (dialog);
177 return FALSE;
178 }
179
180
181
182 static void
xfce_settings_manager_dialog_check_resize(GtkWidget * widget,gpointer * user_data)183 xfce_settings_manager_dialog_check_resize (GtkWidget *widget, gpointer *user_data)
184 {
185 XfceSettingsManagerDialog *dialog = XFCE_SETTINGS_MANAGER_DIALOG (user_data);
186 xfce_settings_manager_queue_resize (dialog);
187 }
188
189
190
191 static void
xfce_settings_manager_dialog_init(XfceSettingsManagerDialog * dialog)192 xfce_settings_manager_dialog_init (XfceSettingsManagerDialog *dialog)
193 {
194 GtkWidget *dialog_vbox;
195 GtkWidget *box;
196 GtkWidget *entry;
197 GtkWidget *scroll;
198 GtkWidget *viewport;
199 GtkWidget *image;
200 GtkWidget *button;
201 gchar *path;
202
203 dialog->channel = xfconf_channel_get ("xfce4-settings-manager");
204
205 dialog->store = gtk_list_store_new (N_COLUMNS,
206 G_TYPE_STRING,
207 G_TYPE_STRING,
208 G_TYPE_STRING,
209 GARCON_TYPE_MENU_ITEM,
210 GARCON_TYPE_MENU_DIRECTORY,
211 G_TYPE_STRING);
212
213 path = xfce_resource_lookup (XFCE_RESOURCE_CONFIG, "menus/xfce-settings-manager.menu");
214 dialog->menu = garcon_menu_new_for_path (path != NULL ? path : MENUFILE);
215 g_free (path);
216
217 gtk_window_set_default_size (GTK_WINDOW (dialog),
218 xfconf_channel_get_int (dialog->channel, "/last/window-width", 640),
219 xfconf_channel_get_int (dialog->channel, "/last/window-height", 500));
220 xfce_settings_manager_dialog_set_title (dialog, NULL, NULL);
221
222 /* Add a buttonbox (Help, All Settings, Close) at bottom of the main box */
223 xfce_titled_dialog_create_action_area (XFCE_TITLED_DIALOG (dialog));
224
225 dialog->button_help = xfce_titled_dialog_add_button (XFCE_TITLED_DIALOG (dialog), _("_Help"), GTK_RESPONSE_HELP);
226 image = gtk_image_new_from_icon_name ("help-browser", GTK_ICON_SIZE_BUTTON);
227 gtk_button_set_image (GTK_BUTTON (dialog->button_help), image);
228
229 dialog->button_back = xfce_titled_dialog_add_button (XFCE_TITLED_DIALOG (dialog), _("All _Settings"), GTK_RESPONSE_NONE);
230 image = gtk_image_new_from_icon_name ("go-previous-symbolic", GTK_ICON_SIZE_BUTTON);
231 gtk_button_set_image (GTK_BUTTON (dialog->button_back), image);
232 gtk_widget_set_sensitive (dialog->button_back, FALSE);
233 g_signal_connect_swapped (G_OBJECT (dialog->button_back), "clicked",
234 G_CALLBACK (xfce_settings_manager_dialog_go_back), dialog);
235
236 button = xfce_titled_dialog_add_button (XFCE_TITLED_DIALOG (dialog), _("_Close"), GTK_RESPONSE_CLOSE);
237 image = gtk_image_new_from_icon_name ("window-close-symbolic", GTK_ICON_SIZE_BUTTON);
238 gtk_button_set_image (GTK_BUTTON (button), image);
239
240 /* Add the filter bar */
241 box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
242 dialog->revealer = gtk_revealer_new ();
243 gtk_revealer_set_transition_type (GTK_REVEALER (dialog->revealer), GTK_REVEALER_TRANSITION_TYPE_SLIDE_DOWN);
244 gtk_widget_set_margin_top (box, 4);
245 gtk_container_add (GTK_CONTAINER (dialog->revealer), box);
246 gtk_widget_show (dialog->revealer);
247
248 dialog->filter_button = button = gtk_toggle_button_new ();
249 image = gtk_image_new_from_icon_name ("edit-find-symbolic", GTK_ICON_SIZE_BUTTON);
250 gtk_button_set_image (GTK_BUTTON (button), image);
251 gtk_header_bar_pack_end (GTK_HEADER_BAR (gtk_dialog_get_header_bar (GTK_DIALOG (dialog))), button);
252 gtk_widget_show (button);
253 g_signal_connect (G_OBJECT (button), "toggled", G_CALLBACK (xfce_settings_manager_show_filter_toggled), dialog);
254 xfconf_g_property_bind (dialog->channel, "/last/filter-visible", G_TYPE_BOOLEAN, G_OBJECT (button), "active");
255
256 dialog->filter_entry = entry = gtk_search_entry_new ();
257 gtk_box_pack_start (GTK_BOX (box), entry, TRUE, FALSE, 0);
258 gtk_widget_set_valign (entry, GTK_ALIGN_CENTER);
259 g_signal_connect (G_OBJECT (entry), "changed",
260 G_CALLBACK (xfce_settings_manager_dialog_entry_changed), dialog);
261 g_signal_connect (G_OBJECT (entry), "key-press-event",
262 G_CALLBACK (xfce_settings_manager_dialog_entry_key_press), dialog);
263 gtk_widget_show_all (box);
264
265 dialog_vbox = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
266
267 gtk_box_pack_start (GTK_BOX (dialog_vbox), dialog->revealer, FALSE, TRUE, 0);
268
269 dialog->category_scroll = scroll = gtk_scrolled_window_new (NULL, NULL);
270 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scroll), GTK_SHADOW_ETCHED_IN);
271 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
272 gtk_box_pack_start (GTK_BOX (dialog_vbox), scroll, TRUE, TRUE, 0);
273 gtk_container_set_border_width (GTK_CONTAINER (scroll), 6);
274 gtk_widget_show (scroll);
275
276 viewport = dialog->category_viewport = gtk_viewport_new (NULL, NULL);
277 gtk_container_add (GTK_CONTAINER (scroll), viewport);
278 gtk_viewport_set_shadow_type (GTK_VIEWPORT (viewport), GTK_SHADOW_NONE);
279 gtk_widget_show (viewport);
280
281 dialog->category_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
282 gtk_container_add (GTK_CONTAINER (viewport), dialog->category_box);
283 gtk_container_set_border_width (GTK_CONTAINER (dialog->category_box), 6);
284 gtk_widget_show (dialog->category_box);
285 gtk_widget_set_size_request (dialog->category_box,
286 TEXT_WIDTH /* text */
287 + ICON_WIDTH /* icon */
288 + (5 * 6) /* borders */, -1);
289
290 /* pluggable dialog scrolled window and viewport */
291 dialog->socket_scroll = scroll = gtk_scrolled_window_new (NULL, NULL);
292 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scroll), GTK_SHADOW_NONE);
293 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
294 gtk_box_pack_start (GTK_BOX (dialog_vbox), scroll, TRUE, TRUE, 0);
295 gtk_container_set_border_width (GTK_CONTAINER (scroll), 0);
296
297 dialog->socket_viewport = viewport = gtk_viewport_new (NULL, NULL);
298 gtk_container_add (GTK_CONTAINER (scroll), viewport);
299 gtk_viewport_set_shadow_type (GTK_VIEWPORT (viewport), GTK_SHADOW_NONE);
300 gtk_widget_show (viewport);
301
302 dialog->css_provider = gtk_css_provider_new ();
303
304 xfce_settings_manager_dialog_menu_reload (dialog);
305
306 g_signal_connect_swapped (G_OBJECT (dialog->menu), "reload-required",
307 G_CALLBACK (xfce_settings_manager_dialog_menu_reload), dialog);
308
309 g_signal_connect (G_OBJECT (dialog), "check-resize", G_CALLBACK (xfce_settings_manager_dialog_check_resize), dialog);
310 }
311
312
313
314 static void
xfce_settings_manager_dialog_finalize(GObject * object)315 xfce_settings_manager_dialog_finalize (GObject *object)
316 {
317 XfceSettingsManagerDialog *dialog = XFCE_SETTINGS_MANAGER_DIALOG (object);
318
319 g_free (dialog->help_page);
320 g_free (dialog->help_component);
321 g_free (dialog->help_version);
322
323 g_free (dialog->filter_text);
324
325 if (dialog->socket_item != NULL)
326 g_object_unref (G_OBJECT (dialog->socket_item));
327
328 g_object_unref (G_OBJECT (dialog->menu));
329 g_object_unref (G_OBJECT (dialog->store));
330
331 G_OBJECT_CLASS (xfce_settings_manager_dialog_parent_class)->finalize (object);
332 }
333
334
335
336 static void
xfce_settings_manager_dialog_style_updated(GtkWidget * widget)337 xfce_settings_manager_dialog_style_updated (GtkWidget *widget)
338 {
339 XfceSettingsManagerDialog *dialog = XFCE_SETTINGS_MANAGER_DIALOG (widget);
340 GtkStyleContext *context;
341
342 context = gtk_widget_get_style_context (dialog->category_viewport);
343 gtk_style_context_add_class (context, "view");
344 gtk_style_context_add_class (context, "exoiconview");
345 xfce_settings_manager_dialog_set_hover_style (dialog);
346 }
347
348
349
350 static void
xfce_settings_manager_dialog_set_hover_style(XfceSettingsManagerDialog * dialog)351 xfce_settings_manager_dialog_set_hover_style (XfceSettingsManagerDialog *dialog)
352 {
353 GtkStyleContext *context;
354 GdkRGBA color;
355 gchar *css_string;
356 gchar *color_text;
357 GdkScreen *screen;
358
359 context = gtk_widget_get_style_context (GTK_WIDGET (dialog));
360 /* Reset the provider to make sure we drop the previous Gtk theme style */
361 gtk_style_context_remove_provider (context,
362 GTK_STYLE_PROVIDER (dialog->css_provider));
363 /* Get the foreground color for the underline */
364 gtk_style_context_get_color (context, GTK_STATE_FLAG_NORMAL, &color);
365 color_text = gdk_rgba_to_string (&color);
366 /* Set a fake underline with box-shadow and use gtk to highlight the icon of the cell renderer */
367 css_string = g_strdup_printf (".exoiconview.view *:hover { -gtk-icon-effect: highlight; box-shadow: inset 0 -1px 1px %s;"
368 " border-left: 1px solid transparent; border-right: 1px solid transparent; }",
369 color_text);
370 gtk_css_provider_load_from_data (dialog->css_provider, css_string, -1, NULL);
371 screen = gdk_screen_get_default ();
372 /* As we don't have the individual ExoIconView widgets here, we set this provider for the whole screen.
373 This is fairly unproblematic as nobody uses the CSS class exiconview. */
374 gtk_style_context_add_provider_for_screen (screen, GTK_STYLE_PROVIDER (dialog->css_provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
375 g_free (css_string);
376 g_free (color_text);
377 }
378
379
380
381 static void
xfce_settings_manager_dialog_response(GtkDialog * widget,gint response_id)382 xfce_settings_manager_dialog_response (GtkDialog *widget,
383 gint response_id)
384 {
385 XfceSettingsManagerDialog *dialog = XFCE_SETTINGS_MANAGER_DIALOG (widget);
386 const gchar *help_component;
387
388 if (response_id == GTK_RESPONSE_NONE)
389 return;
390
391 if (response_id == GTK_RESPONSE_HELP)
392 {
393 if (dialog->help_component != NULL)
394 help_component = dialog->help_component;
395 else
396 help_component = "xfce4-settings";
397
398 xfce_dialog_show_help_with_version (GTK_WINDOW (widget),
399 help_component,
400 dialog->help_page,
401 NULL,
402 dialog->help_version);
403 }
404 else
405 {
406 GdkWindowState state;
407 gint width, height;
408
409 /* Don't save the state for full-screen windows */
410 state = gdk_window_get_state (gtk_widget_get_window(GTK_WIDGET(widget)));
411
412 if ((state & (GDK_WINDOW_STATE_MAXIMIZED | GDK_WINDOW_STATE_FULLSCREEN)) == 0)
413 {
414 /* Save window size */
415 gtk_window_get_size (GTK_WINDOW (widget), &width, &height);
416 xfconf_channel_set_int (dialog->channel, "/last/window-width", width),
417 xfconf_channel_set_int (dialog->channel, "/last/window-height", height);
418 }
419
420 g_object_unref (dialog->css_provider);
421 gtk_widget_destroy (GTK_WIDGET (widget));
422 gtk_main_quit ();
423 }
424 }
425
426
427
428 static void
xfce_settings_manager_dialog_set_title(XfceSettingsManagerDialog * dialog,const gchar * title,const gchar * icon_name)429 xfce_settings_manager_dialog_set_title (XfceSettingsManagerDialog *dialog,
430 const gchar *title,
431 const gchar *icon_name)
432 {
433 g_return_if_fail (XFCE_IS_SETTINGS_MANAGER_DIALOG (dialog));
434
435 if (icon_name == NULL)
436 icon_name = "org.xfce.settings.manager";
437 if (title == NULL)
438 title = _("Settings");
439
440 gtk_window_set_title (GTK_WINDOW (dialog), title);
441 gtk_window_set_icon_name (GTK_WINDOW (dialog), icon_name);
442 }
443
444
445
446 static gint
xfce_settings_manager_dialog_iconview_find(gconstpointer a,gconstpointer b)447 xfce_settings_manager_dialog_iconview_find (gconstpointer a,
448 gconstpointer b)
449 {
450 const DialogCategory *category = a;
451
452 return category->iconview == b ? 0 : 1;
453 }
454
455
456
457 static gboolean
xfce_settings_manager_dialog_iconview_keynav_failed(ExoIconView * current_view,GtkDirectionType direction,XfceSettingsManagerDialog * dialog)458 xfce_settings_manager_dialog_iconview_keynav_failed (ExoIconView *current_view,
459 GtkDirectionType direction,
460 XfceSettingsManagerDialog *dialog)
461 {
462 GList *li;
463 GtkTreePath *path;
464 ExoIconView *new_view;
465 gboolean result = FALSE;
466 GtkTreeModel *model;
467 GtkTreeIter iter;
468 gint col_old, col_new;
469 gint dist_prev, dist_new;
470 GtkTreePath *sel_path;
471 DialogCategory *category;
472
473 if (direction == GTK_DIR_UP || direction == GTK_DIR_DOWN)
474 {
475 /* find this category in the list */
476 li = g_list_find_custom (dialog->categories, current_view,
477 xfce_settings_manager_dialog_iconview_find);
478
479 /* find the next of previous visible item */
480 for (; li != NULL; )
481 {
482 if (direction == GTK_DIR_DOWN)
483 li = g_list_next (li);
484 else
485 li = g_list_previous (li);
486
487 if (li != NULL)
488 {
489 category = li->data;
490 if (gtk_widget_get_visible (category->box))
491 break;
492 }
493 }
494
495 /* leave there is no view above or below this one */
496 if (li == NULL)
497 return FALSE;
498
499 category = li->data;
500 new_view = EXO_ICON_VIEW (category->iconview);
501
502 if (exo_icon_view_get_cursor (current_view, &path, NULL))
503 {
504 col_old = exo_icon_view_get_item_column (current_view, path);
505 gtk_tree_path_free (path);
506
507 dist_prev = 1000;
508 sel_path = NULL;
509
510 model = exo_icon_view_get_model (new_view);
511 if (gtk_tree_model_get_iter_first (model, &iter))
512 {
513 do
514 {
515 path = gtk_tree_model_get_path (model, &iter);
516 col_new = exo_icon_view_get_item_column (new_view, path);
517 dist_new = ABS (col_new - col_old);
518
519 if ((direction == GTK_DIR_UP && dist_new <= dist_prev)
520 || (direction == GTK_DIR_DOWN && dist_new < dist_prev))
521 {
522 if (sel_path != NULL)
523 gtk_tree_path_free (sel_path);
524
525 sel_path = path;
526 dist_prev = dist_new;
527 }
528 else
529 {
530 gtk_tree_path_free (path);
531 }
532 }
533 while (gtk_tree_model_iter_next (model, &iter));
534 }
535
536 if (G_LIKELY (sel_path != NULL))
537 {
538 /* move cursor, grab-focus will handle the selection */
539 exo_icon_view_set_cursor (new_view, sel_path, NULL, FALSE);
540 xfce_settings_manager_dialog_scroll_to_item (GTK_WIDGET (new_view), dialog);
541 gtk_tree_path_free (sel_path);
542
543 gtk_widget_grab_focus (GTK_WIDGET (new_view));
544
545 result = TRUE;
546 }
547 }
548 }
549
550 return result;
551 }
552
553
554
555 static gboolean
xfce_settings_manager_dialog_query_tooltip(GtkWidget * iconview,gint x,gint y,gboolean keyboard_mode,GtkTooltip * tooltip,XfceSettingsManagerDialog * dialog)556 xfce_settings_manager_dialog_query_tooltip (GtkWidget *iconview,
557 gint x,
558 gint y,
559 gboolean keyboard_mode,
560 GtkTooltip *tooltip,
561 XfceSettingsManagerDialog *dialog)
562 {
563 GtkTreePath *path;
564 GValue value = { 0, };
565 GtkTreeModel *model;
566 GtkTreeIter iter;
567 GarconMenuItem *item;
568 const gchar *comment;
569
570 if (keyboard_mode)
571 {
572 if (!exo_icon_view_get_cursor (EXO_ICON_VIEW (iconview), &path, NULL))
573 return FALSE;
574 }
575 else
576 {
577 path = exo_icon_view_get_path_at_pos (EXO_ICON_VIEW (iconview), x, y);
578 if (G_UNLIKELY (path == NULL))
579 return FALSE;
580 }
581
582 model = exo_icon_view_get_model (EXO_ICON_VIEW (iconview));
583 if (gtk_tree_model_get_iter (model, &iter, path))
584 {
585 gtk_tree_model_get_value (model, &iter, COLUMN_MENU_ITEM, &value);
586 item = g_value_get_object (&value);
587 g_assert (GARCON_IS_MENU_ITEM (item));
588
589 comment = garcon_menu_item_get_comment (item);
590 if (!exo_str_is_empty (comment))
591 gtk_tooltip_set_text (tooltip, comment);
592
593 g_value_unset (&value);
594 }
595
596 gtk_tree_path_free (path);
597
598 return TRUE;
599 }
600
601
602
603 static gboolean
xfce_settings_manager_dialog_iconview_focus(GtkWidget * iconview,GdkEventFocus * event,XfceSettingsManagerDialog * dialog)604 xfce_settings_manager_dialog_iconview_focus (GtkWidget *iconview,
605 GdkEventFocus *event,
606 XfceSettingsManagerDialog *dialog)
607 {
608 GtkTreePath *path;
609
610 if (event->in)
611 {
612 /* a mouse click will have focus, tab events not */
613 if (!exo_icon_view_get_cursor (EXO_ICON_VIEW (iconview), &path, NULL))
614 {
615 path = gtk_tree_path_new_from_indices (0, -1);
616 exo_icon_view_set_cursor (EXO_ICON_VIEW (iconview), path, NULL, FALSE);
617 xfce_settings_manager_dialog_scroll_to_item (iconview, dialog);
618 }
619
620 exo_icon_view_select_path (EXO_ICON_VIEW (iconview), path);
621 gtk_tree_path_free (path);
622 }
623 else
624 {
625 exo_icon_view_unselect_all (EXO_ICON_VIEW (iconview));
626 }
627
628 return FALSE;
629 }
630
631
632
633 static void
xfce_settings_manager_dialog_remove_socket(XfceSettingsManagerDialog * dialog)634 xfce_settings_manager_dialog_remove_socket (XfceSettingsManagerDialog *dialog)
635 {
636 GtkWidget *socket;
637
638 socket = gtk_bin_get_child (GTK_BIN (dialog->socket_viewport));
639 if (G_UNLIKELY (socket != NULL))
640 gtk_container_remove (GTK_CONTAINER (dialog->socket_viewport), socket);
641
642 if (dialog->socket_item != NULL)
643 {
644 g_object_unref (G_OBJECT (dialog->socket_item));
645 dialog->socket_item = NULL;
646 }
647 }
648
649
650
651 static void
xfce_settings_manager_dialog_go_back(XfceSettingsManagerDialog * dialog)652 xfce_settings_manager_dialog_go_back (XfceSettingsManagerDialog *dialog)
653 {
654 /* make sure no cursor is shown */
655 gdk_window_set_cursor (gtk_widget_get_window (GTK_WIDGET(dialog)), NULL);
656
657 /* reset dialog info */
658 xfce_settings_manager_dialog_set_title (dialog, NULL, NULL);
659
660 gtk_widget_show (dialog->category_scroll);
661 gtk_widget_hide (dialog->socket_scroll);
662
663 g_free (dialog->help_page);
664 dialog->help_page = NULL;
665 g_free (dialog->help_component);
666 dialog->help_component = NULL;
667 g_free (dialog->help_version);
668 dialog->help_version = NULL;
669
670 gtk_widget_set_sensitive (dialog->button_back, FALSE);
671 gtk_widget_set_sensitive (dialog->button_help, TRUE);
672
673 gtk_widget_show (dialog->filter_button);
674 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->filter_button)))
675 gtk_widget_show (dialog->revealer);
676 gtk_entry_set_text (GTK_ENTRY (dialog->filter_entry), "");
677 gtk_widget_grab_focus (dialog->filter_entry);
678
679 xfce_settings_manager_dialog_remove_socket (dialog);
680 }
681
682
683
684 static void
xfce_settings_manager_dialog_entry_changed(GtkWidget * entry,XfceSettingsManagerDialog * dialog)685 xfce_settings_manager_dialog_entry_changed (GtkWidget *entry,
686 XfceSettingsManagerDialog *dialog)
687 {
688 const gchar *text;
689 gchar *normalized;
690 gchar *filter_text;
691 GList *li;
692 GtkTreeModel *model;
693 gint n_children;
694 DialogCategory *category;
695
696 text = gtk_entry_get_text (GTK_ENTRY (entry));
697 if (text == NULL || *text == '\0')
698 {
699 filter_text = NULL;
700 }
701 else
702 {
703 /* create independent search string */
704 normalized = g_utf8_normalize (text, -1, G_NORMALIZE_DEFAULT);
705 filter_text = g_utf8_casefold (normalized, -1);
706 g_free (normalized);
707 }
708
709 /* check if we need to update */
710 if (g_strcmp0 (dialog->filter_text, filter_text) != 0)
711 {
712 /* set new filter */
713 g_free (dialog->filter_text);
714 dialog->filter_text = filter_text;
715
716 /* update the category models */
717 for (li = dialog->categories; li != NULL; li = li->next)
718 {
719 category = li->data;
720
721 /* update model filters */
722 model = exo_icon_view_get_model (EXO_ICON_VIEW (category->iconview));
723 gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (model));
724
725 /* set visibility of the category */
726 n_children = gtk_tree_model_iter_n_children (model, NULL);
727 gtk_widget_set_visible (category->box, n_children > 0);
728 }
729
730 g_idle_add (xfce_settings_manager_queue_resize_cb, dialog);
731 }
732 else
733 {
734 g_free (dialog->filter_text);
735 dialog->filter_text = NULL;
736 g_free (filter_text);
737 }
738 }
739
740
741
742 static void
xfce_settings_manager_show_filter_toggled(GtkToggleButton * button,gpointer user_data)743 xfce_settings_manager_show_filter_toggled (GtkToggleButton *button,
744 gpointer user_data)
745 {
746 XfceSettingsManagerDialog *dialog = XFCE_SETTINGS_MANAGER_DIALOG (user_data);
747 gboolean state;
748
749 state = gtk_toggle_button_get_active (button);
750 gtk_widget_show (dialog->revealer);
751 gtk_revealer_set_reveal_child (GTK_REVEALER (dialog->revealer), state);
752 if (state && GTK_IS_WIDGET (dialog->filter_entry))
753 gtk_widget_grab_focus (dialog->filter_entry);
754 }
755
756
757
758 static gboolean
xfce_settings_manager_dialog_entry_key_press(GtkWidget * entry,GdkEventKey * event,XfceSettingsManagerDialog * dialog)759 xfce_settings_manager_dialog_entry_key_press (GtkWidget *entry,
760 GdkEventKey *event,
761 XfceSettingsManagerDialog *dialog)
762 {
763 GList *li;
764 DialogCategory *category;
765 GtkTreePath *path;
766 gint n_visible_items;
767 GtkTreeModel *model;
768 const gchar *text;
769
770 if (event->keyval == GDK_KEY_Escape)
771 {
772 text = gtk_entry_get_text (GTK_ENTRY (entry));
773 if (text != NULL && *text != '\0')
774 {
775 gtk_entry_set_text (GTK_ENTRY (entry), "");
776 return TRUE;
777 }
778 }
779 else if (event->keyval == GDK_KEY_Return)
780 {
781 /* count visible children */
782 n_visible_items = 0;
783 for (li = dialog->categories; li != NULL; li = li->next)
784 {
785 category = li->data;
786 if (gtk_widget_get_visible (category->box))
787 {
788 model = exo_icon_view_get_model (EXO_ICON_VIEW (category->iconview));
789 n_visible_items += gtk_tree_model_iter_n_children (model, NULL);
790
791 /* stop searching if there are more then 1 items */
792 if (n_visible_items > 1)
793 break;
794 }
795 }
796
797 for (li = dialog->categories; li != NULL; li = li->next)
798 {
799 category = li->data;
800
801 /* find the first visible category */
802 if (!gtk_widget_get_visible (category->box))
803 continue;
804
805 path = gtk_tree_path_new_first ();
806 if (n_visible_items == 1)
807 {
808 /* activate this one item */
809 exo_icon_view_item_activated (EXO_ICON_VIEW (category->iconview), path);
810 }
811 else
812 {
813 /* select first item in view */
814 exo_icon_view_set_cursor (EXO_ICON_VIEW (category->iconview),
815 path, NULL, FALSE);
816 gtk_widget_grab_focus (category->iconview);
817 }
818 gtk_tree_path_free (path);
819 break;
820 }
821
822 return TRUE;
823 }
824
825 return FALSE;
826 }
827
828
829
830 static void
xfce_settings_manager_dialog_plug_added(GtkWidget * socket,XfceSettingsManagerDialog * dialog)831 xfce_settings_manager_dialog_plug_added (GtkWidget *socket,
832 XfceSettingsManagerDialog *dialog)
833 {
834 /* set dialog information from desktop file */
835 xfce_settings_manager_dialog_set_title (dialog,
836 garcon_menu_item_get_name (dialog->socket_item),
837 garcon_menu_item_get_icon_name (dialog->socket_item));
838
839 /* show socket and hide the categories view */
840 gtk_widget_show (dialog->socket_scroll);
841 gtk_widget_hide (dialog->category_scroll);
842
843 /* button sensitivity */
844 gtk_widget_set_sensitive (dialog->button_back, TRUE);
845 gtk_widget_set_sensitive (dialog->button_help, dialog->help_page != NULL);
846 gtk_widget_hide (dialog->filter_button);
847 gtk_widget_hide (dialog->revealer);
848
849 /* plug startup complete */
850 gdk_window_set_cursor (gtk_widget_get_window (GTK_WIDGET(dialog)), NULL);
851 }
852
853
854
855 static void
xfce_settings_manager_dialog_plug_removed(GtkWidget * socket,XfceSettingsManagerDialog * dialog)856 xfce_settings_manager_dialog_plug_removed (GtkWidget *socket,
857 XfceSettingsManagerDialog *dialog)
858 {
859 /* this shouldn't happen */
860 g_critical ("pluggable dialog \"%s\" crashed",
861 garcon_menu_item_get_command (dialog->socket_item));
862
863 /* restore dialog */
864 xfce_settings_manager_dialog_go_back (dialog);
865 }
866
867
868
869 static void
xfce_settings_manager_dialog_spawn(XfceSettingsManagerDialog * dialog,GarconMenuItem * item)870 xfce_settings_manager_dialog_spawn (XfceSettingsManagerDialog *dialog,
871 GarconMenuItem *item)
872 {
873 gchar *command;
874 gboolean snotify;
875 GdkScreen *screen;
876 GdkDisplay *display;
877 GError *error = NULL;
878 GFile *desktop_file;
879 gchar *filename;
880 XfceRc *rc;
881 gboolean pluggable = FALSE;
882 gchar *cmd;
883 gchar *uri;
884 GtkWidget *socket;
885 GdkCursor *cursor;
886
887 g_return_if_fail (GARCON_IS_MENU_ITEM (item));
888
889 screen = gtk_window_get_screen (GTK_WINDOW (dialog));
890
891 /* expand the field codes */
892 uri = garcon_menu_item_get_uri (item);
893 command = xfce_expand_desktop_entry_field_codes (garcon_menu_item_get_command (item),
894 NULL,
895 garcon_menu_item_get_icon_name (item),
896 garcon_menu_item_get_name (item),
897 uri, FALSE);
898 g_free (uri);
899
900 /* we need to read some more info from the desktop
901 * file that is not supported by garcon */
902 desktop_file = garcon_menu_item_get_file (item);
903 filename = g_file_get_path (desktop_file);
904 g_object_unref (desktop_file);
905
906 rc = xfce_rc_simple_open (filename, TRUE);
907 g_free (filename);
908 if (G_LIKELY (rc != NULL))
909 {
910 pluggable = xfce_rc_read_bool_entry (rc, "X-XfcePluggable", FALSE);
911 if (pluggable)
912 {
913 dialog->help_page = g_strdup (xfce_rc_read_entry (rc, "X-XfceHelpPage", NULL));
914 dialog->help_component = g_strdup (xfce_rc_read_entry (rc, "X-XfceHelpComponent", NULL));
915 dialog->help_version = g_strdup (xfce_rc_read_entry (rc, "X-XfceHelpVersion", NULL));
916 }
917
918 xfce_rc_close (rc);
919 }
920
921 if (pluggable)
922 {
923 /* fake startup notification */
924 display = gdk_display_get_default ();
925 cursor = gdk_cursor_new_for_display (display, GDK_WATCH);
926 gdk_window_set_cursor (gtk_widget_get_window (GTK_WIDGET(dialog)), cursor);
927 g_object_unref (cursor);
928
929 xfce_settings_manager_dialog_remove_socket (dialog);
930
931 /* create fresh socket */
932 socket = gtk_socket_new ();
933 gtk_container_add (GTK_CONTAINER (dialog->socket_viewport), socket);
934 g_signal_connect (G_OBJECT (socket), "plug-added",
935 G_CALLBACK (xfce_settings_manager_dialog_plug_added), dialog);
936 g_signal_connect (G_OBJECT (socket), "plug-removed",
937 G_CALLBACK (xfce_settings_manager_dialog_plug_removed), dialog);
938 gtk_widget_show (socket);
939
940 /* for info when the plug is attached */
941 dialog->socket_item = g_object_ref (item);
942
943 /* spawn dialog with socket argument */
944 cmd = g_strdup_printf ("%s --socket-id=%d", command, (gint)gtk_socket_get_id (GTK_SOCKET (socket)));
945 if (!xfce_spawn_command_line_on_screen (screen, cmd, FALSE, FALSE, &error))
946 {
947 gdk_window_set_cursor (gtk_widget_get_window (GTK_WIDGET(dialog)), NULL);
948
949 xfce_dialog_show_error (GTK_WINDOW (dialog), error,
950 _("Unable to start \"%s\""), command);
951 g_error_free (error);
952 }
953 g_free (cmd);
954 }
955 else
956 {
957 snotify = garcon_menu_item_supports_startup_notification (item);
958 if (!xfce_spawn_command_line_on_screen (screen, command, FALSE, snotify, &error))
959 {
960 xfce_dialog_show_error (GTK_WINDOW (dialog), error,
961 _("Unable to start \"%s\""), command);
962 g_error_free (error);
963 }
964 }
965
966 g_free (command);
967 }
968
969
970
971 static void
xfce_settings_manager_dialog_item_activated(ExoIconView * iconview,GtkTreePath * path,XfceSettingsManagerDialog * dialog)972 xfce_settings_manager_dialog_item_activated (ExoIconView *iconview,
973 GtkTreePath *path,
974 XfceSettingsManagerDialog *dialog)
975 {
976 GtkTreeModel *model;
977 GtkTreeIter iter;
978 GarconMenuItem *item;
979
980 model = exo_icon_view_get_model (iconview);
981 if (gtk_tree_model_get_iter (model, &iter, path))
982 {
983 gtk_tree_model_get (model, &iter, COLUMN_MENU_ITEM, &item, -1);
984 g_assert (GARCON_IS_MENU_ITEM (item));
985
986 xfce_settings_manager_dialog_spawn (dialog, item);
987
988 g_object_unref (G_OBJECT (item));
989 }
990 }
991
992
993
994 static gboolean
xfce_settings_manager_dialog_filter_category(GtkTreeModel * model,GtkTreeIter * iter,gpointer data)995 xfce_settings_manager_dialog_filter_category (GtkTreeModel *model,
996 GtkTreeIter *iter,
997 gpointer data)
998 {
999 GValue cat_val = { 0, };
1000 GValue filter_val = { 0, };
1001 gboolean visible;
1002 DialogCategory *category = data;
1003 const gchar *filter_text;
1004
1005 /* filter only the active category */
1006 gtk_tree_model_get_value (model, iter, COLUMN_MENU_DIRECTORY, &cat_val);
1007 visible = g_value_get_object (&cat_val) == G_OBJECT (category->directory);
1008 g_value_unset (&cat_val);
1009
1010 /* filter search string */
1011 if (visible && category->dialog->filter_text != NULL)
1012 {
1013 gtk_tree_model_get_value (model, iter, COLUMN_FILTER_TEXT, &filter_val);
1014 filter_text = g_value_get_string (&filter_val);
1015 visible = strstr (filter_text, category->dialog->filter_text) != NULL;
1016 g_value_unset (&filter_val);
1017 }
1018
1019 return visible;
1020 }
1021
1022
1023
1024 static void
xfce_settings_manager_dialog_scroll_to_item(GtkWidget * iconview,XfceSettingsManagerDialog * dialog)1025 xfce_settings_manager_dialog_scroll_to_item (GtkWidget *iconview,
1026 XfceSettingsManagerDialog *dialog)
1027 {
1028 GtkAllocation *alloc = g_new0 (GtkAllocation, 1);
1029 GtkTreePath *path;
1030 gint row, row_height;
1031 gdouble rows;
1032 GtkAdjustment *adjustment;
1033 gdouble lower, upper;
1034
1035 if (exo_icon_view_get_cursor (EXO_ICON_VIEW (iconview), &path, NULL))
1036 {
1037 /* get item row */
1038 row = exo_icon_view_get_item_row (EXO_ICON_VIEW (iconview), path);
1039 gtk_tree_path_free (path);
1040
1041 /* estimated row height */
1042 gtk_widget_get_allocation(GTK_WIDGET(iconview), alloc);
1043 rows = alloc->height / 56;
1044 row_height = alloc->height / MAX (1.0, (gint) rows);
1045
1046 /* selected item boundries */
1047 lower = alloc->y + row_height * row;
1048 upper = alloc->y + row_height * (row + 1);
1049
1050 /* scroll so item is visible */
1051 adjustment = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (dialog->category_viewport));
1052 gtk_adjustment_clamp_page (adjustment, lower, upper);
1053 }
1054
1055 g_free (alloc);
1056 }
1057
1058
1059
1060 static gboolean
xfce_settings_manager_dialog_key_press_event(GtkWidget * iconview,GdkEventKey * event,XfceSettingsManagerDialog * dialog)1061 xfce_settings_manager_dialog_key_press_event (GtkWidget *iconview,
1062 GdkEventKey *event,
1063 XfceSettingsManagerDialog *dialog)
1064 {
1065 gboolean result;
1066
1067 /* let exo handle the selection first */
1068 result = GTK_WIDGET_CLASS (G_OBJECT_GET_CLASS (iconview))->key_press_event (iconview, event);
1069
1070 /* make sure the selected item is visible */
1071 if (result)
1072 xfce_settings_manager_dialog_scroll_to_item (iconview, dialog);
1073
1074 return result;
1075 }
1076
1077
1078
1079 static gboolean
xfce_settings_manager_start_search(GtkWidget * iconview,XfceSettingsManagerDialog * dialog)1080 xfce_settings_manager_start_search (GtkWidget *iconview,
1081 XfceSettingsManagerDialog *dialog)
1082 {
1083 gtk_widget_grab_focus (dialog->filter_entry);
1084 return TRUE;
1085 }
1086
1087
1088
1089 static void
xfce_settings_manager_dialog_category_free(gpointer data)1090 xfce_settings_manager_dialog_category_free (gpointer data)
1091 {
1092 DialogCategory *category = data;
1093 XfceSettingsManagerDialog *dialog = category->dialog;
1094
1095 dialog->categories = g_list_remove (dialog->categories, category);
1096
1097 g_object_unref (G_OBJECT (category->directory));
1098 g_slice_free (DialogCategory, category);
1099 }
1100
1101
1102
1103 static void
xfce_settings_manager_dialog_add_category(XfceSettingsManagerDialog * dialog,GarconMenuDirectory * directory)1104 xfce_settings_manager_dialog_add_category (XfceSettingsManagerDialog *dialog,
1105 GarconMenuDirectory *directory)
1106 {
1107 GtkTreeModel *filter;
1108 GtkWidget *iconview;
1109 GtkWidget *label;
1110 GtkWidget *separator;
1111 GtkWidget *vbox;
1112 PangoAttrList *attrs;
1113 GtkCellRenderer *render;
1114 DialogCategory *category;
1115
1116 category = g_slice_new0 (DialogCategory);
1117 category->directory = (GarconMenuDirectory *) g_object_ref (G_OBJECT (directory));
1118 category->dialog = dialog;
1119
1120 /* filter category from main store */
1121 filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (dialog->store), NULL);
1122 gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
1123 xfce_settings_manager_dialog_filter_category,
1124 category, xfce_settings_manager_dialog_category_free);
1125
1126 category->box = vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
1127 gtk_box_pack_start (GTK_BOX (dialog->category_box), vbox, FALSE, TRUE, 0);
1128 gtk_widget_show (vbox);
1129
1130 /* create a label for the category title */
1131 label = gtk_label_new (garcon_menu_directory_get_name (directory));
1132 attrs = pango_attr_list_new ();
1133 pango_attr_list_insert (attrs, pango_attr_weight_new (PANGO_WEIGHT_BOLD));
1134 gtk_label_set_attributes (GTK_LABEL (label), attrs);
1135 pango_attr_list_unref (attrs);
1136 gtk_widget_set_halign (label, GTK_ALIGN_START);
1137 gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
1138 gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 0);
1139 gtk_widget_show (label);
1140
1141 /* separate title and content using a horizontal line */
1142 separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
1143 gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, TRUE, 0);
1144 gtk_widget_show (separator);
1145
1146 category->iconview = iconview = exo_icon_view_new_with_model (GTK_TREE_MODEL (filter));
1147 gtk_container_add (GTK_CONTAINER (vbox), iconview);
1148 exo_icon_view_set_orientation (EXO_ICON_VIEW (iconview), GTK_ORIENTATION_HORIZONTAL);
1149 exo_icon_view_set_margin (EXO_ICON_VIEW (iconview), 0);
1150 exo_icon_view_set_single_click (EXO_ICON_VIEW (iconview), TRUE);
1151 exo_icon_view_set_enable_search (EXO_ICON_VIEW (iconview), FALSE);
1152 exo_icon_view_set_item_width (EXO_ICON_VIEW (iconview), TEXT_WIDTH + ICON_WIDTH);
1153 xfce_settings_manager_dialog_set_hover_style (dialog);
1154 gtk_widget_show (iconview);
1155
1156 /* list used for unselecting */
1157 dialog->categories = g_list_append (dialog->categories, category);
1158
1159 gtk_widget_set_has_tooltip (iconview, TRUE);
1160 g_signal_connect (G_OBJECT (iconview), "query-tooltip",
1161 G_CALLBACK (xfce_settings_manager_dialog_query_tooltip), dialog);
1162 g_signal_connect (G_OBJECT (iconview), "focus-in-event",
1163 G_CALLBACK (xfce_settings_manager_dialog_iconview_focus), dialog);
1164 g_signal_connect (G_OBJECT (iconview), "focus-out-event",
1165 G_CALLBACK (xfce_settings_manager_dialog_iconview_focus), dialog);
1166 g_signal_connect (G_OBJECT (iconview), "keynav-failed",
1167 G_CALLBACK (xfce_settings_manager_dialog_iconview_keynav_failed), dialog);
1168 g_signal_connect (G_OBJECT (iconview), "item-activated",
1169 G_CALLBACK (xfce_settings_manager_dialog_item_activated), dialog);
1170 g_signal_connect (G_OBJECT (iconview), "key-press-event",
1171 G_CALLBACK (xfce_settings_manager_dialog_key_press_event), dialog);
1172 g_signal_connect (G_OBJECT (iconview), "start-interactive-search",
1173 G_CALLBACK (xfce_settings_manager_start_search), dialog);
1174
1175 render = gtk_cell_renderer_pixbuf_new ();
1176 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (iconview), render, FALSE);
1177 gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (iconview), render, "icon-name", COLUMN_ICON_NAME);
1178 g_object_set (G_OBJECT (render),
1179 "stock-size", GTK_ICON_SIZE_DIALOG,
1180 "follow-state", TRUE,
1181 NULL);
1182
1183 render = gtk_cell_renderer_text_new ();
1184 gtk_cell_layout_pack_end (GTK_CELL_LAYOUT (iconview), render, FALSE);
1185 gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (iconview), render, "text", COLUMN_NAME);
1186 g_object_set (G_OBJECT (render),
1187 "wrap-mode", PANGO_WRAP_WORD,
1188 "wrap-width", TEXT_WIDTH,
1189 NULL);
1190
1191 g_object_unref (G_OBJECT (filter));
1192 }
1193
1194
1195
1196 static void
xfce_settings_manager_dialog_menu_collect(GarconMenu * menu,GList ** items)1197 xfce_settings_manager_dialog_menu_collect (GarconMenu *menu,
1198 GList **items)
1199 {
1200 GList *elements, *li;
1201
1202 g_return_if_fail (GARCON_IS_MENU (menu));
1203
1204 elements = garcon_menu_get_elements (menu);
1205
1206 for (li = elements; li != NULL; li = li->next)
1207 {
1208 if (GARCON_IS_MENU_ITEM (li->data))
1209 {
1210 /* only add visible items */
1211 if (garcon_menu_element_get_visible (li->data))
1212 *items = g_list_prepend (*items, li->data);
1213 }
1214 else if (GARCON_IS_MENU (li->data))
1215 {
1216 /* we collect only 1 level deep in a category, so
1217 * add the submenu items too (should never happen tho) */
1218 xfce_settings_manager_dialog_menu_collect (li->data, items);
1219 }
1220 }
1221
1222 g_list_free (elements);
1223 }
1224
1225
1226
1227 static gint
xfce_settings_manager_dialog_menu_sort(gconstpointer a,gconstpointer b)1228 xfce_settings_manager_dialog_menu_sort (gconstpointer a,
1229 gconstpointer b)
1230 {
1231 return g_utf8_collate (garcon_menu_item_get_name (GARCON_MENU_ITEM (a)),
1232 garcon_menu_item_get_name (GARCON_MENU_ITEM (b)));
1233 }
1234
1235
1236
1237 static void
xfce_settings_manager_dialog_menu_reload(XfceSettingsManagerDialog * dialog)1238 xfce_settings_manager_dialog_menu_reload (XfceSettingsManagerDialog *dialog)
1239 {
1240 GError *error = NULL;
1241 GList *elements, *li;
1242 GList *lnext;
1243 GarconMenuDirectory *directory;
1244 GList *items, *lp;
1245 GList *keywords, *kli;
1246 gint i = 0;
1247 gchar *item_text;
1248 gchar *normalized;
1249 gchar *filter_text;
1250 GString *item_keywords;
1251 DialogCategory *category;
1252
1253 g_return_if_fail (XFCE_IS_SETTINGS_MANAGER_DIALOG (dialog));
1254 g_return_if_fail (GARCON_IS_MENU (dialog->menu));
1255
1256 if (dialog->categories != NULL)
1257 {
1258 for (li = dialog->categories; li != NULL; li = lnext)
1259 {
1260 lnext = li->next;
1261 category = li->data;
1262
1263 gtk_widget_destroy (category->box);
1264 }
1265
1266 g_assert (dialog->categories == NULL);
1267
1268 gtk_list_store_clear (GTK_LIST_STORE (dialog->store));
1269 }
1270
1271 if (garcon_menu_load (dialog->menu, NULL, &error))
1272 {
1273 /* get all menu elements (preserve layout) */
1274 elements = garcon_menu_get_elements (dialog->menu);
1275 for (li = elements; li != NULL; li = li->next)
1276 {
1277 /* only accept toplevel menus */
1278 if (!GARCON_IS_MENU (li->data))
1279 continue;
1280
1281 directory = garcon_menu_get_directory (li->data);
1282 if (G_UNLIKELY (directory == NULL))
1283 continue;
1284
1285 items = NULL;
1286
1287 xfce_settings_manager_dialog_menu_collect (li->data, &items);
1288
1289 /* add the new category if it has visible items */
1290 if (G_LIKELY (items != NULL))
1291 {
1292 /* insert new items in main store */
1293 items = g_list_sort (items, xfce_settings_manager_dialog_menu_sort);
1294 for (lp = items; lp != NULL; lp = lp->next)
1295 {
1296 /* create independent search string based on name, comment and keywords */
1297 keywords = garcon_menu_item_get_keywords (lp->data);
1298 item_keywords = g_string_new (NULL);
1299 for (kli = keywords; kli != NULL; kli = kli->next)
1300 {
1301 g_string_append (item_keywords, kli->data);
1302 }
1303 item_text = g_strdup_printf ("%s\n%s\n%s",
1304 garcon_menu_item_get_name (lp->data),
1305 garcon_menu_item_get_comment (lp->data),
1306 item_keywords->str);
1307 g_string_free (item_keywords, TRUE);
1308 g_list_free (kli);
1309 normalized = g_utf8_normalize (item_text, -1, G_NORMALIZE_DEFAULT);
1310 g_free (item_text);
1311 filter_text = g_utf8_casefold (normalized, -1);
1312 g_free (normalized);
1313
1314 gtk_list_store_insert_with_values (dialog->store, NULL, i++,
1315 COLUMN_NAME, garcon_menu_item_get_name (lp->data),
1316 COLUMN_ICON_NAME, garcon_menu_item_get_icon_name (lp->data),
1317 COLUMN_TOOLTIP, garcon_menu_item_get_comment (lp->data),
1318 COLUMN_MENU_ITEM, lp->data,
1319 COLUMN_MENU_DIRECTORY, directory,
1320 COLUMN_FILTER_TEXT, filter_text, -1);
1321
1322 g_free (filter_text);
1323 }
1324 g_list_free (items);
1325
1326 /* add the new category to the box */
1327 xfce_settings_manager_dialog_add_category (dialog, directory);
1328 }
1329 }
1330
1331 g_list_free (elements);
1332 }
1333 else
1334 {
1335 g_critical ("Failed to load menu: %s", error->message);
1336 g_error_free (error);
1337 }
1338
1339 g_idle_add (xfce_settings_manager_queue_resize_cb, dialog);
1340 }
1341
1342
1343 GtkWidget *
xfce_settings_manager_dialog_new(void)1344 xfce_settings_manager_dialog_new (void)
1345 {
1346 return g_object_new (XFCE_TYPE_SETTINGS_MANAGER_DIALOG, NULL);
1347 }
1348
1349
1350
1351 gboolean
xfce_settings_manager_dialog_show_dialog(XfceSettingsManagerDialog * dialog,const gchar * dialog_name)1352 xfce_settings_manager_dialog_show_dialog (XfceSettingsManagerDialog *dialog,
1353 const gchar *dialog_name)
1354 {
1355 GtkTreeModel *model = GTK_TREE_MODEL (dialog->store);
1356 GtkTreeIter iter;
1357 GarconMenuItem *item;
1358 const gchar *desktop_id;
1359 gchar *name;
1360 gboolean found = FALSE;
1361
1362 g_return_val_if_fail (XFCE_IS_SETTINGS_MANAGER_DIALOG (dialog), FALSE);
1363
1364 name = g_strdup_printf ("%s.desktop", dialog_name);
1365
1366 if (gtk_tree_model_get_iter_first (model, &iter))
1367 {
1368 do
1369 {
1370 gtk_tree_model_get (model, &iter, COLUMN_MENU_ITEM, &item, -1);
1371 g_assert (GARCON_IS_MENU_ITEM (item));
1372
1373 desktop_id = garcon_menu_item_get_desktop_id (item);
1374 if (g_strcmp0 (desktop_id, name) == 0)
1375 {
1376 xfce_settings_manager_dialog_spawn (dialog, item);
1377 found = TRUE;
1378 }
1379
1380 g_object_unref (G_OBJECT (item));
1381 }
1382 while (!found && gtk_tree_model_iter_next (model, &iter));
1383 }
1384
1385 g_free (name);
1386
1387 return found;
1388 }
1389