1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
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
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
19 * James Willcox <jwillcox@cs.indiana.edu>
20 * Paolo Bacchilega <paobac@cvs.gnome.org>
31 #include <libgnomevfs/gnome-vfs.h>
32 #ifndef USE_STABLE_LIBGNOMEUI
33 #include <libgnomeui/gnome-icon-theme.h>
35 #include <gconf/gconf-client.h>
36 #include "egg-recent-model.h"
37 #include "egg-recent-view.h"
38 #include "egg-recent-view-uimanager.h"
39 #include "egg-recent-util.h"
40 #include "egg-recent-item.h"
42 #define EGG_RECENT_NAME_PREFIX "EggRecentAction"
43 #define EGG_RECENT_ACTION "EggRecentFile"
44 #define EGG_RECENT_SEPARATOR (NULL)
46 #define LABEL_WIDTH_CHARS 32
48 struct _EggRecentViewUIManager {
49 GObject parent_instance;
51 GCallback action_callback;
52 gpointer action_user_data;
55 gboolean trailing_sep;
57 GtkUIManager *uimanager;
58 GtkActionGroup *action_group;
65 gboolean show_numbers;
66 #ifndef USE_STABLE_LIBGNOMEUI
67 GnomeIconTheme *theme;
70 EggUIManagerTooltipFunc tooltip_func;
71 gpointer tooltip_func_data;
73 EggRecentModel *model;
75 GtkIconSize icon_size;
79 struct _EggRecentViewUIManagerMenuData {
80 EggRecentViewUIManager *view;
84 typedef struct _EggRecentViewUIManagerMenuData EggRecentViewUIManagerMenuData;
91 /* GObject properties */
100 static guint view_signals[LAST_SIGNAL] = { 0 };
103 egg_recent_view_uimanager_clear (EggRecentViewUIManager *view)
105 if (view->merge_id != 0) {
106 gtk_ui_manager_remove_ui (view->uimanager, view->merge_id);
110 if (view->action_group != NULL) {
111 gtk_ui_manager_remove_action_group (view->uimanager, view->action_group);
112 g_object_unref (view->action_group);
113 view->action_group = NULL;
116 gtk_ui_manager_ensure_update (view->uimanager);
120 connect_proxy_cb (GtkActionGroup *action_group,
124 if (GTK_IS_MENU_ITEM (proxy))
128 label = (GtkLabel *) ((GtkBin *) proxy)->child;
130 gtk_label_set_ellipsize (label, PANGO_ELLIPSIZE_END);
131 gtk_label_set_max_width_chars (label, LABEL_WIDTH_CHARS);
137 egg_recent_view_uimanager_set_list (EggRecentViewUIManager *view, GList *list)
142 g_return_if_fail (view);
144 egg_recent_view_uimanager_clear (view);
146 if (view->merge_id == 0)
147 view->merge_id = gtk_ui_manager_new_merge_id (view->uimanager);
149 if (view->action_group == NULL) {
150 gchar *group = g_strdup_printf ("EggRecentActions%u",
152 view->action_group = gtk_action_group_new (group);
153 g_signal_connect (view->action_group, "connect-proxy",
154 G_CALLBACK (connect_proxy_cb), view);
155 gtk_ui_manager_insert_action_group (view->uimanager, view->action_group, -1);
159 if (view->leading_sep) {
160 gchar *action = g_strdup_printf ("EggRecentLeadingSeparator%u",
162 gtk_ui_manager_add_ui (view->uimanager,
166 EGG_RECENT_SEPARATOR,
172 for (scan = list; scan; scan = scan->next, index++) {
173 EggRecentItem *item = scan->data;
180 gchar *tooltip = NULL;
182 uri = egg_recent_item_get_uri_for_display (item);
186 name = g_strdup_printf (EGG_RECENT_NAME_PREFIX"%u-%u",
190 if (view->tooltip_func != NULL)
191 tooltip = (*view->tooltip_func) (item, view->tooltip_func_data);
193 basename = g_path_get_basename (uri);
194 escaped = egg_recent_util_escape_underlines (basename);
198 if (view->show_numbers) {
200 label = g_strdup_printf ("%d. %s",
204 label = g_strdup_printf ("_%d. %s",
211 action = g_object_new (GTK_TYPE_ACTION,
214 (view->show_icons)? "stock_id": NULL,
217 if (tooltip != NULL) {
218 g_object_set (action, "tooltip", tooltip, NULL);
221 egg_recent_item_ref (item);
222 g_object_set_data_full (G_OBJECT (action),
225 (GFreeFunc) egg_recent_item_unref);
227 if (view->action_callback != NULL) {
229 closure = g_cclosure_new (view->action_callback, view->action_user_data, NULL);
230 g_signal_connect_closure (action, "activate", closure, FALSE);
233 gtk_action_group_add_action (view->action_group, action);
234 g_object_unref (action);
236 gtk_ui_manager_add_ui (view->uimanager,
248 if (view->trailing_sep) {
249 gchar *action = g_strdup_printf ("EggRecentTrailingSeparator%u",
251 gtk_ui_manager_add_ui (view->uimanager,
255 EGG_RECENT_SEPARATOR,
263 model_changed_cb (EggRecentModel *model,
265 EggRecentViewUIManager *view)
268 egg_recent_view_uimanager_set_list (view, list);
270 egg_recent_view_uimanager_clear (view);
271 gtk_ui_manager_ensure_update (view->uimanager);
274 static EggRecentModel *
275 egg_recent_view_uimanager_get_model (EggRecentView *view_parent)
277 EggRecentViewUIManager *view;
279 g_return_val_if_fail (view_parent != NULL, NULL);
280 view = EGG_RECENT_VIEW_UIMANAGER (view_parent);
285 egg_recent_view_uimanager_set_model (EggRecentView *view_parent,
286 EggRecentModel *model)
288 EggRecentViewUIManager *view;
290 g_return_if_fail (view_parent != NULL);
291 view = EGG_RECENT_VIEW_UIMANAGER (view_parent);
293 if (view->model != NULL) {
294 if (view->changed_cb_id != 0)
295 g_signal_handler_disconnect (G_OBJECT (view->model),
296 view->changed_cb_id);
297 g_object_unref (view->model);
301 g_object_ref (view->model);
303 view->changed_cb_id = g_signal_connect_object (G_OBJECT (model),
305 G_CALLBACK (model_changed_cb),
308 egg_recent_model_changed (view->model);
312 egg_recent_view_uimanager_set_leading_sep (EggRecentViewUIManager *view,
315 view->leading_sep = val;
316 egg_recent_view_uimanager_clear (view);
318 egg_recent_model_changed (view->model);
322 egg_recent_view_uimanager_set_trailing_sep (EggRecentViewUIManager *view,
325 view->trailing_sep = val;
326 egg_recent_view_uimanager_clear (view);
328 egg_recent_model_changed (view->model);
332 egg_recent_view_uimanager_set_property (GObject *object,
337 EggRecentViewUIManager *view = EGG_RECENT_VIEW_UIMANAGER (object);
341 egg_recent_view_uimanager_set_uimanager (view, (GtkUIManager*)g_value_get_object (value));
344 egg_recent_view_uimanager_set_path (view, g_value_get_string (value));
346 case PROP_SHOW_ICONS:
347 egg_recent_view_uimanager_show_icons (view, g_value_get_boolean (value));
349 case PROP_SHOW_NUMBERS:
350 egg_recent_view_uimanager_show_numbers (view, g_value_get_boolean (value));
353 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
359 egg_recent_view_uimanager_get_property (GObject *object,
364 EggRecentViewUIManager *view = EGG_RECENT_VIEW_UIMANAGER (object);
368 g_value_set_object (value, view->uimanager);
371 g_value_set_string (value, view->path);
373 case PROP_SHOW_ICONS:
374 g_value_set_boolean (value, view->show_icons);
376 case PROP_SHOW_NUMBERS:
377 g_value_set_boolean (value, view->show_numbers);
380 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
386 egg_recent_view_uimanager_finalize (GObject *object)
388 EggRecentViewUIManager *view = EGG_RECENT_VIEW_UIMANAGER (object);
390 if (view->changed_cb_id != 0) {
391 g_signal_handler_disconnect (G_OBJECT (view->model),
392 view->changed_cb_id);
393 view->changed_cb_id = 0;
398 egg_recent_view_uimanager_clear (view);
400 if (view->action_group != NULL) {
401 g_object_unref (view->action_group);
402 view->action_group = NULL;
405 if (view->uimanager != NULL) {
406 g_object_unref (view->uimanager);
407 view->uimanager = NULL;
410 if (view->model != NULL) {
411 g_object_unref (view->model);
415 #ifndef USE_STABLE_LIBGNOMEUI
416 if (view->theme != NULL) {
417 g_object_unref (view->theme);
422 if (view->client != NULL) {
423 g_object_unref (view->client);
429 egg_recent_view_uimanager_class_init (EggRecentViewUIManagerClass * klass)
431 GObjectClass *object_class;
433 object_class = G_OBJECT_CLASS (klass);
435 object_class->set_property = egg_recent_view_uimanager_set_property;
436 object_class->get_property = egg_recent_view_uimanager_get_property;
437 object_class->finalize = egg_recent_view_uimanager_finalize;
439 view_signals[ACTIVATE] = g_signal_new ("activate",
440 G_OBJECT_CLASS_TYPE (object_class),
442 G_STRUCT_OFFSET (EggRecentViewUIManagerClass, activate),
444 g_cclosure_marshal_VOID__BOXED,
446 EGG_TYPE_RECENT_ITEM);
448 g_object_class_install_property (object_class,
450 g_param_spec_object ("uimanager",
452 "The UI manager this object will use to update.the UI",
455 g_object_class_install_property (object_class,
457 g_param_spec_string ("path",
459 "The UI path this object will update.",
462 g_object_class_install_property (object_class,
464 g_param_spec_boolean ("show-icons",
466 "Whether or not to show icons",
470 g_object_class_install_property (object_class,
472 g_param_spec_boolean ("show-numbers",
474 "Whether or not to show numbers",
478 klass->activate = NULL;
482 egg_recent_view_init (EggRecentViewClass *iface)
484 iface->do_get_model = egg_recent_view_uimanager_get_model;
485 iface->do_set_model = egg_recent_view_uimanager_set_model;
489 show_menus_changed_cb (GConfClient *client,
492 EggRecentViewUIManager *view)
496 value = gconf_entry_get_value (entry);
497 g_return_if_fail (value->type == GCONF_VALUE_BOOL);
499 egg_recent_view_uimanager_show_icons (view, gconf_value_get_bool (value));
502 #ifndef USE_STABLE_LIBGNOMEUI
504 theme_changed_cb (GnomeIconTheme *theme,
505 EggRecentViewUIManager *view)
507 if (view->model != NULL)
508 egg_recent_model_changed (view->model);
513 egg_recent_view_uimanager_init (EggRecentViewUIManager * view)
515 view->client = gconf_client_get_default ();
517 view->show_icons = gconf_client_get_bool (view->client,
518 "/desktop/gnome/interface/menus_have_icons",
521 gconf_client_add_dir (view->client, "/desktop/gnome/interface",
522 GCONF_CLIENT_PRELOAD_NONE,
524 gconf_client_notify_add (view->client,
525 "/desktop/gnome/interface/menus_have_icons",
526 (GConfClientNotifyFunc)show_menus_changed_cb,
530 view->leading_sep = FALSE;
531 view->trailing_sep = FALSE;
532 view->show_numbers = TRUE;
534 view->uimanager = NULL;
535 view->action_group = NULL;
537 view->changed_cb_id = 0;
541 #ifndef USE_STABLE_LIBGNOMEUI
542 view->theme = gnome_icon_theme_new ();
543 gnome_icon_theme_set_allow_svg (view->theme, TRUE);
544 g_signal_connect_object (view->theme, "changed",
545 G_CALLBACK (theme_changed_cb), view, 0);
548 view->tooltip_func = NULL;
549 view->tooltip_func_data = NULL;
551 view->icon_size = GTK_ICON_SIZE_MENU;
555 egg_recent_view_uimanager_set_icon_size (EggRecentViewUIManager *view,
556 GtkIconSize icon_size)
558 if (view->icon_size != icon_size) {
559 view->icon_size = icon_size;
560 egg_recent_model_changed (view->model);
562 view->icon_size = icon_size;
567 egg_recent_view_uimanager_get_icon_size (EggRecentViewUIManager *view)
569 return view->icon_size;
573 egg_recent_view_uimanager_show_icons (EggRecentViewUIManager *view,
576 view->show_icons = show;
577 if (view->model != NULL)
578 egg_recent_model_changed (view->model);
582 egg_recent_view_uimanager_show_numbers (EggRecentViewUIManager *view,
585 view->show_numbers = show;
586 if (view->model != NULL)
587 egg_recent_model_changed (view->model);
591 egg_recent_view_uimanager_set_tooltip_func (EggRecentViewUIManager *view,
592 EggUIManagerTooltipFunc func,
595 view->tooltip_func = func;
596 view->tooltip_func_data = user_data;
598 egg_recent_model_changed (view->model);
602 * egg_recent_view_uimanager_set_uimanager:
603 * @view: A EggRecentViewUIManager object.
604 * @uimanager: The ui manager used to put the menu items in.
606 * Use this function to change the ui manager used to update the menu.
610 egg_recent_view_uimanager_set_uimanager (EggRecentViewUIManager *view,
611 GtkUIManager *uimanager)
613 g_return_if_fail (EGG_IS_RECENT_VIEW_UIMANAGER (view));
614 g_return_if_fail (uimanager != NULL);
616 if (view->uimanager != NULL)
617 g_object_unref (view->uimanager);
618 view->uimanager = uimanager;
619 g_object_ref (view->uimanager);
623 * egg_recent_view_uimanager_get_uimanager:
624 * @view: A EggRecentViewUIManager object.
628 egg_recent_view_uimanager_get_uimanager (EggRecentViewUIManager *view)
630 g_return_val_if_fail (EGG_IS_RECENT_VIEW_UIMANAGER (view), NULL);
631 return view->uimanager;
635 * egg_recent_view_uimanager_set_path:
636 * @view: A EggRecentViewUIManager object.
637 * @path: The path to put the menu items in.
639 * Use this function to change the path where the recent
640 * documents appear in.
644 egg_recent_view_uimanager_set_path (EggRecentViewUIManager *view,
647 g_return_if_fail (EGG_IS_RECENT_VIEW_UIMANAGER (view));
648 g_return_if_fail (path);
651 view->path = g_strdup (path);
655 * egg_recent_view_uimanager_get_path:
656 * @view: A EggRecentViewUIManager object.
659 G_CONST_RETURN gchar*
660 egg_recent_view_uimanager_get_path (EggRecentViewUIManager *view)
662 g_return_val_if_fail (EGG_IS_RECENT_VIEW_UIMANAGER (view), NULL);
667 egg_recent_view_uimanager_set_action_func (EggRecentViewUIManager *view,
671 g_return_if_fail (EGG_IS_RECENT_VIEW_UIMANAGER (view));
672 view->action_callback = callback;
673 view->action_user_data = user_data;
677 * egg_recent_view_uimanager_new:
678 * @appname: The name of your application.
679 * @limit: The maximum number of items allowed.
681 * This creates a new EggRecentViewUIManager object.
683 * Returns: a EggRecentViewUIManager object
685 EggRecentViewUIManager *
686 egg_recent_view_uimanager_new (GtkUIManager *uimanager,
693 g_return_val_if_fail (uimanager, NULL);
694 g_return_val_if_fail (path, NULL);
696 view = g_object_new (egg_recent_view_uimanager_get_type (),
697 "uimanager", uimanager,
701 g_return_val_if_fail (view, NULL);
703 egg_recent_view_uimanager_set_action_func (EGG_RECENT_VIEW_UIMANAGER (view),
707 return EGG_RECENT_VIEW_UIMANAGER (view);
711 * egg_recent_view_uimanager_get_type:
714 * This returns a GType representing a EggRecentViewUIManager object.
719 egg_recent_view_uimanager_get_type (void)
721 static GType egg_recent_view_uimanager_type = 0;
723 if(!egg_recent_view_uimanager_type) {
724 static const GTypeInfo egg_recent_view_uimanager_info = {
725 sizeof (EggRecentViewUIManagerClass),
726 NULL, /* base init */
727 NULL, /* base finalize */
728 (GClassInitFunc)egg_recent_view_uimanager_class_init, /* class init */
729 NULL, /* class finalize */
730 NULL, /* class data */
731 sizeof (EggRecentViewUIManager),
733 (GInstanceInitFunc) egg_recent_view_uimanager_init
736 static const GInterfaceInfo view_info =
738 (GInterfaceInitFunc) egg_recent_view_init,
743 egg_recent_view_uimanager_type = g_type_register_static (G_TYPE_OBJECT,
744 "EggRecentViewUIManager",
745 &egg_recent_view_uimanager_info, 0);
746 g_type_add_interface_static (egg_recent_view_uimanager_type,
747 EGG_TYPE_RECENT_VIEW,
751 return egg_recent_view_uimanager_type;
755 egg_recent_view_uimanager_get_item (EggRecentViewUIManager *view,
758 return g_object_get_data (G_OBJECT(action), "egg_recent_uri");