1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as
5 * published by the Free Software Foundation; either version 2 of the
6 * License, or (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * James Willcox <jwillcox@cs.indiana.edu>
29 #include <libgnomevfs/gnome-vfs.h>
30 #ifndef USE_STABLE_LIBGNOMEUI
31 #include <libgnomeui/gnome-icon-theme.h>
33 #include <gconf/gconf-client.h>
34 #include "egg-recent-model.h"
35 #include "egg-recent-view.h"
36 #include "egg-recent-view-gtk.h"
37 #include "egg-recent-util.h"
38 #include "egg-recent-item.h"
40 struct _EggRecentViewGtk
{
41 GObject parent_instance
; /* We emit signals */
44 GtkWidget
*start_menu_item
;
47 gboolean trailing_sep
;
54 gboolean show_numbers
;
55 #ifndef USE_STABLE_LIBGNOMEUI
56 GnomeIconTheme
*theme
;
59 GtkTooltips
*tooltips
;
60 EggRecentViewGtkTooltipFunc tooltip_func
;
61 gpointer tooltip_func_data
;
63 EggRecentModel
*model
;
65 GtkIconSize icon_size
;
70 struct _EggRecentViewGtkMenuData
{
71 EggRecentViewGtk
*view
;
75 typedef struct _EggRecentViewGtkMenuData EggRecentViewGtkMenuData
;
82 /* GObject properties */
91 static guint view_signals
[LAST_SIGNAL
] = { 0 };
95 egg_recent_view_gtk_clear (EggRecentViewGtk
*view
)
100 gint
*menu_data
=NULL
;
102 g_return_if_fail (view
->menu
!= NULL
);
104 menu_children
= gtk_container_get_children (GTK_CONTAINER (view
->menu
));
108 menu_item
= (GObject
*)p
->data
;
110 menu_data
= (gint
*)g_object_get_data (menu_item
,
114 gtk_container_remove (GTK_CONTAINER (view
->menu
),
115 GTK_WIDGET (menu_item
));
125 egg_recent_view_gtk_find_menu_offset (EggRecentViewGtk
*view
)
128 GList
*menu_children
;
130 GtkWidget
*menu_item
;
133 g_return_val_if_fail (view
, 0);
135 menu_children
= GTK_MENU_SHELL (view
->menu
)->children
;
140 menu_item
= (GtkWidget
*)p
->data
;
142 if (menu_item
== view
->start_menu_item
) {
155 egg_recent_view_gtk_menu_cb (GtkWidget
*menu
, gpointer data
)
157 EggRecentViewGtkMenuData
*md
= (EggRecentViewGtkMenuData
*) data
;
160 g_return_if_fail (md
);
161 g_return_if_fail (md
->item
);
162 g_return_if_fail (md
->view
);
163 g_return_if_fail (EGG_IS_RECENT_VIEW_GTK (md
->view
));
167 egg_recent_item_ref (item
);
169 g_signal_emit (G_OBJECT(md
->view
), view_signals
[ACTIVATE
], 0,
172 egg_recent_item_unref (item
);
176 egg_recent_view_gtk_destroy_cb (gpointer data
, GClosure
*closure
)
178 EggRecentViewGtkMenuData
*md
= data
;
180 egg_recent_item_unref (md
->item
);
185 egg_recent_view_gtk_new_separator (EggRecentViewGtk
*view
)
189 g_return_val_if_fail (view
, NULL
);
191 retval
= gtk_separator_menu_item_new ();
194 * this is a tag so we can distinguish our menu items
195 * from others that may be in the menu.
197 g_object_set_data (G_OBJECT (retval
),
199 GINT_TO_POINTER (1));
202 gtk_widget_show (retval
);
208 egg_recent_view_gtk_new_menu_item (EggRecentViewGtk
*view
,
212 GtkWidget
*menu_item
;
213 EggRecentViewGtkMenuData
*md
;
221 g_return_val_if_fail (view
, NULL
);
222 g_return_val_if_fail (item
, NULL
);
224 short_name
= egg_recent_item_get_short_name (item
);
228 escaped
= egg_recent_util_escape_underlines (short_name
);
231 if (view
->show_numbers
) {
232 /* avoid having conflicting mnemonics */
234 text
= g_strdup_printf ("%d. %s", index
,
237 text
= g_strdup_printf ("_%d. %s", index
,
244 mime_type
= egg_recent_item_get_mime_type (item
);
245 #ifndef USE_STABLE_LIBGNOMEUI
250 gtk_icon_size_lookup_for_settings
251 (gtk_widget_get_settings (view
->menu
),
255 uri
= egg_recent_item_get_uri (item
);
256 pixbuf
= egg_recent_util_get_icon (view
->theme
, uri
,
264 image
= gtk_image_new_from_pixbuf (pixbuf
);
266 g_object_unref (pixbuf
);
268 if (view
->show_icons
)
269 gtk_widget_show (image
);
271 menu_item
= gtk_image_menu_item_new_with_mnemonic (text
);
272 gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item
),
275 md
= g_new0 (EggRecentViewGtkMenuData
, 1);
277 md
->item
= egg_recent_item_ref (item
);
279 g_signal_connect_data (G_OBJECT (menu_item
), "activate",
280 G_CALLBACK (egg_recent_view_gtk_menu_cb
),
282 (GClosureNotify
)egg_recent_view_gtk_destroy_cb
,
289 * this is a tag so we can distinguish our menu items
290 * from others that may be in the menu.
292 g_object_set_data (G_OBJECT (menu_item
),
294 GINT_TO_POINTER (1));
297 gtk_widget_show (menu_item
);
303 egg_recent_view_gtk_add_to_menu (EggRecentViewGtk
*view
,
308 GtkWidget
*menu_item
;
311 g_return_if_fail (view
);
312 g_return_if_fail (view
->menu
);
314 menu_offset
= egg_recent_view_gtk_find_menu_offset (view
);
317 menu_item
= egg_recent_view_gtk_new_menu_item (view
, item
, display
);
319 menu_item
= egg_recent_view_gtk_new_separator (view
);
321 if (view
->tooltip_func
!= NULL
&& menu_item
!= NULL
) {
322 view
->tooltip_func (view
->tooltips
, menu_item
,
323 item
, view
->tooltip_func_data
);
327 gtk_menu_shell_insert (GTK_MENU_SHELL (view
->menu
), menu_item
,
332 egg_recent_view_gtk_set_list (EggRecentViewGtk
*view
, GList
*list
)
339 g_return_if_fail (view
);
341 egg_recent_view_gtk_clear (view
);
343 if (view
->leading_sep
) {
344 egg_recent_view_gtk_add_to_menu (view
, NULL
, display
, index
);
350 item
= (EggRecentItem
*)p
->data
;
352 egg_recent_view_gtk_add_to_menu (view
, item
, display
, index
);
359 if (view
->trailing_sep
)
360 egg_recent_view_gtk_add_to_menu (view
, NULL
, display
, index
);
364 model_changed_cb (EggRecentModel
*model
, GList
*list
, EggRecentViewGtk
*view
)
367 egg_recent_view_gtk_set_list (view
, list
);
369 egg_recent_view_gtk_clear (view
);
372 static EggRecentModel
*
373 egg_recent_view_gtk_get_model (EggRecentView
*view_parent
)
375 EggRecentViewGtk
*view
;
377 g_return_val_if_fail (view_parent
!= NULL
, NULL
);
378 view
= EGG_RECENT_VIEW_GTK (view_parent
);
383 egg_recent_view_gtk_set_model (EggRecentView
*view_parent
,
384 EggRecentModel
*model
)
386 EggRecentViewGtk
*view
;
388 g_return_if_fail (view_parent
!= NULL
);
389 view
= EGG_RECENT_VIEW_GTK (view_parent
);
391 if (view
->model
!= NULL
) {
392 g_object_unref (view
->model
);
393 g_signal_handler_disconnect (G_OBJECT (model
),
394 view
->changed_cb_id
);
398 g_object_ref (view
->model
);
400 view
->changed_cb_id
= g_signal_connect_object (G_OBJECT (model
),
402 G_CALLBACK (model_changed_cb
),
405 egg_recent_model_changed (view
->model
);
409 egg_recent_view_gtk_set_leading_sep (EggRecentViewGtk
*view
, gboolean val
)
411 view
->leading_sep
= val
;
413 egg_recent_view_gtk_clear (view
);
416 egg_recent_model_changed (view
->model
);
420 egg_recent_view_gtk_set_trailing_sep (EggRecentViewGtk
*view
, gboolean val
)
422 view
->trailing_sep
= val
;
424 egg_recent_view_gtk_clear (view
);
427 egg_recent_model_changed (view
->model
);
431 egg_recent_view_gtk_set_property (GObject
*object
,
436 EggRecentViewGtk
*view
= EGG_RECENT_VIEW_GTK (object
);
441 egg_recent_view_gtk_set_menu (view
,
442 GTK_WIDGET (g_value_get_object (value
)));
444 case PROP_START_MENU_ITEM
:
445 egg_recent_view_gtk_set_start_menu_item (view
,
446 g_value_get_object (value
));
448 case PROP_SHOW_ICONS
:
449 egg_recent_view_gtk_show_icons (view
,
450 g_value_get_boolean (value
));
452 case PROP_SHOW_NUMBERS
:
453 egg_recent_view_gtk_show_numbers (view
,
454 g_value_get_boolean (value
));
457 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
463 egg_recent_view_gtk_get_property (GObject
*object
,
468 EggRecentViewGtk
*view
= EGG_RECENT_VIEW_GTK (object
);
473 g_value_set_object (value
, view
->menu
);
475 case PROP_START_MENU_ITEM
:
476 g_value_set_object (value
, view
->start_menu_item
);
478 case PROP_SHOW_ICONS
:
479 g_value_set_boolean (value
, view
->show_icons
);
481 case PROP_SHOW_NUMBERS
:
482 g_value_set_boolean (value
, view
->show_numbers
);
485 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
491 egg_recent_view_gtk_finalize (GObject
*object
)
493 EggRecentViewGtk
*view
= EGG_RECENT_VIEW_GTK (object
);
495 g_signal_handler_disconnect (G_OBJECT (view
->model
),
496 view
->changed_cb_id
);
500 g_object_unref (view
->menu
);
501 g_object_unref (view
->model
);
502 #ifndef USE_STABLE_LIBGNOMEUI
503 g_object_unref (view
->theme
);
505 g_object_unref (view
->client
);
507 g_object_unref (view
->tooltips
);
511 egg_recent_view_gtk_class_init (EggRecentViewGtkClass
* klass
)
513 GObjectClass
*object_class
;
515 object_class
= G_OBJECT_CLASS (klass
);
517 object_class
->set_property
= egg_recent_view_gtk_set_property
;
518 object_class
->get_property
= egg_recent_view_gtk_get_property
;
519 object_class
->finalize
= egg_recent_view_gtk_finalize
;
521 view_signals
[ACTIVATE
] = g_signal_new ("activate",
522 G_OBJECT_CLASS_TYPE (object_class
),
524 G_STRUCT_OFFSET (EggRecentViewGtkClass
, activate
),
526 g_cclosure_marshal_VOID__BOXED
,
528 EGG_TYPE_RECENT_ITEM
);
530 g_object_class_install_property (object_class
,
532 g_param_spec_object ("menu",
534 "The GtkMenuShell this object will update.",
537 g_object_class_install_property (object_class
,
538 PROP_START_MENU_ITEM
,
539 g_param_spec_object ("start-menu-item",
541 "The menu item that precedes where are menu items will go",
542 gtk_menu_item_get_type (),
545 g_object_class_install_property (object_class
,
547 g_param_spec_boolean ("show-icons",
549 "Whether or not to show icons",
553 g_object_class_install_property (object_class
,
555 g_param_spec_boolean ("show-numbers",
557 "Whether or not to show numbers",
561 klass
->activate
= NULL
;
565 egg_recent_view_init (EggRecentViewClass
*iface
)
567 iface
->do_get_model
= egg_recent_view_gtk_get_model
;
568 iface
->do_set_model
= egg_recent_view_gtk_set_model
;
572 show_menus_changed_cb (GConfClient
*client
,
575 EggRecentViewGtk
*view
)
579 value
= gconf_entry_get_value (entry
);
581 g_return_if_fail (value
->type
== GCONF_VALUE_BOOL
);
583 egg_recent_view_gtk_show_icons (view
,
584 gconf_value_get_bool (value
));
588 #ifndef USE_STABLE_LIBGNOMEUI
590 theme_changed_cb (GnomeIconTheme
*theme
, EggRecentViewGtk
*view
)
592 if (view
->model
!= NULL
)
593 egg_recent_model_changed (view
->model
);
598 egg_recent_view_gtk_init (EggRecentViewGtk
* view
)
600 view
->client
= gconf_client_get_default ();
603 gconf_client_get_bool (view
->client
,
604 "/desktop/gnome/interface/menus_have_icons",
607 gconf_client_add_dir (view
->client
, "/desktop/gnome/interface",
608 GCONF_CLIENT_PRELOAD_NONE
,
610 gconf_client_notify_add (view
->client
,
611 "/desktop/gnome/interface/menus_have_icons",
612 (GConfClientNotifyFunc
)show_menus_changed_cb
,
616 view
->leading_sep
= FALSE
;
617 view
->trailing_sep
= FALSE
;
619 view
->uid
= egg_recent_util_get_unique_id ();
620 #ifndef USE_STABLE_LIBGNOMEUI
621 view
->theme
= gnome_icon_theme_new ();
622 gnome_icon_theme_set_allow_svg (view
->theme
, TRUE
);
623 g_signal_connect_object (view
->theme
, "changed",
624 G_CALLBACK (theme_changed_cb
), view
, 0);
626 view
->tooltips
= gtk_tooltips_new ();
627 g_object_ref (view
->tooltips
);
628 gtk_object_sink (GTK_OBJECT (view
->tooltips
));
629 view
->tooltip_func
= NULL
;
630 view
->tooltip_func_data
= NULL
;
632 view
->icon_size
= GTK_ICON_SIZE_MENU
;
636 egg_recent_view_gtk_set_icon_size (EggRecentViewGtk
*view
,
637 GtkIconSize icon_size
)
639 if (view
->icon_size
!= icon_size
) {
640 view
->icon_size
= icon_size
;
641 egg_recent_model_changed (view
->model
);
643 view
->icon_size
= icon_size
;
648 egg_recent_view_gtk_get_icon_size (EggRecentViewGtk
*view
)
650 return view
->icon_size
;
654 egg_recent_view_gtk_show_icons (EggRecentViewGtk
*view
, gboolean show
)
656 view
->show_icons
= show
;
659 egg_recent_model_changed (view
->model
);
663 egg_recent_view_gtk_show_numbers (EggRecentViewGtk
*view
, gboolean show
)
665 view
->show_numbers
= show
;
668 egg_recent_model_changed (view
->model
);
672 egg_recent_view_gtk_set_tooltip_func (EggRecentViewGtk
*view
,
673 EggRecentViewGtkTooltipFunc func
,
676 view
->tooltip_func
= func
;
677 view
->tooltip_func_data
= user_data
;
680 egg_recent_model_changed (view
->model
);
684 * egg_recent_view_gtk_set_menu:
685 * @view: A EggRecentViewGtk object.
686 * @menu: The GtkMenuShell to put the menu items in.
688 * Use this function to change the GtkMenuShell that the recent
689 * documents appear in.
693 egg_recent_view_gtk_set_menu (EggRecentViewGtk
*view
,
696 g_return_if_fail (view
);
697 g_return_if_fail (EGG_IS_RECENT_VIEW_GTK (view
));
698 g_return_if_fail (menu
);
700 if (view
->menu
!= NULL
)
701 g_object_unref (view
->menu
);
704 g_object_ref (view
->menu
);
708 * egg_recent_view_gtk_set_start_menu_item:
709 * @view: A EggRecentViewGtk object.
710 * @start_menu_item: The menu item that appears just before where our menu
711 * items should appear
715 egg_recent_view_gtk_set_start_menu_item (EggRecentViewGtk
*view
,
716 GtkWidget
*menu_item
)
718 g_return_if_fail (view
);
719 g_return_if_fail (EGG_IS_RECENT_VIEW_GTK (view
));
721 view
->start_menu_item
= menu_item
;
725 * egg_recent_view_gtk_get_menu:
726 * @view: A EggRecentViewGtk object.
730 egg_recent_view_gtk_get_menu (EggRecentViewGtk
*view
)
736 * egg_recent_view_gtk_get_start_menu_item
737 * @view: A EggRecentViewGtk object.
741 egg_recent_view_gtk_get_start_menu_item (EggRecentViewGtk
*view
)
743 return view
->start_menu_item
;
748 * egg_recent_view_gtk_new:
749 * @appname: The name of your application.
750 * @limit: The maximum number of items allowed.
752 * This creates a new EggRecentViewGtk object.
754 * Returns: a EggRecentViewGtk object
757 egg_recent_view_gtk_new (GtkWidget
*menu
, GtkWidget
*start_menu_item
)
759 EggRecentViewGtk
*view
;
761 g_return_val_if_fail (menu
, NULL
);
763 view
= EGG_RECENT_VIEW_GTK (g_object_new (egg_recent_view_gtk_get_type (),
767 "show-numbers", TRUE
, NULL
));
769 g_return_val_if_fail (view
, NULL
);
775 * egg_recent_view_gtk_get_type:
778 * This returns a GType representing a EggRecentViewGtk object.
783 egg_recent_view_gtk_get_type (void)
785 static GType egg_recent_view_gtk_type
= 0;
787 if(!egg_recent_view_gtk_type
) {
788 static const GTypeInfo egg_recent_view_gtk_info
= {
789 sizeof (EggRecentViewGtkClass
),
790 NULL
, /* base init */
791 NULL
, /* base finalize */
792 (GClassInitFunc
)egg_recent_view_gtk_class_init
, /* class init */
793 NULL
, /* class finalize */
794 NULL
, /* class data */
795 sizeof (EggRecentViewGtk
),
797 (GInstanceInitFunc
) egg_recent_view_gtk_init
800 static const GInterfaceInfo view_info
=
802 (GInterfaceInitFunc
) egg_recent_view_init
,
807 egg_recent_view_gtk_type
= g_type_register_static (G_TYPE_OBJECT
,
809 &egg_recent_view_gtk_info
, 0);
810 g_type_add_interface_static (egg_recent_view_gtk_type
,
811 EGG_TYPE_RECENT_VIEW
,
815 return egg_recent_view_gtk_type
;