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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
18 * James Willcox <jwillcox@cs.indiana.edu>
29 #include <libbonoboui.h>
30 #include <libgnomevfs/gnome-vfs.h>
31 #ifndef USE_STABLE_LIBGNOMEUI
32 #include <libgnomeui/gnome-icon-theme.h>
34 #include <gconf/gconf-client.h>
35 #include "egg-recent-model.h"
36 #include "egg-recent-view.h"
37 #include "egg-recent-view-bonobo.h"
38 #include "egg-recent-util.h"
39 #include "egg-recent-item.h"
41 struct _EggRecentViewBonobo {
42 GObject parent_instance; /* We emit signals */
44 BonoboUIComponent *uic;
45 gchar *path; /* The menu path where our stuff
51 gchar *uid; /* unique id used for the verb name */
54 gboolean show_numbers;
55 #ifndef USE_STABLE_LIBGNOMEUI
56 GnomeIconTheme *theme;
58 EggRecentViewBonoboTooltipFunc tooltip_func;
59 gpointer tooltip_func_data;
61 EggRecentModel *model;
63 GtkIconSize icon_size;
67 struct _EggRecentViewBonoboMenuData {
68 EggRecentViewBonobo *view;
72 typedef struct _EggRecentViewBonoboMenuData EggRecentViewBonoboMenuData;
79 /* GObject properties */
88 static guint egg_recent_view_bonobo_signals[LAST_SIGNAL] = { 0 };
91 egg_recent_view_bonobo_clear (EggRecentViewBonobo *view)
95 EggRecentModel *model;
97 g_return_if_fail (view->uic);
99 model = egg_recent_view_get_model (EGG_RECENT_VIEW (view));
103 gchar *verb_name = g_strdup_printf ("%s-%d", view->uid, i);
104 gchar *item_path = g_strconcat (view->path, "/", verb_name, NULL);
105 if (bonobo_ui_component_path_exists (view->uic, item_path, NULL))
106 bonobo_ui_component_rm (view->uic, item_path, NULL);
118 egg_recent_view_bonobo_menu_cb (BonoboUIComponent *uic, gpointer data, const char *cname)
120 EggRecentViewBonoboMenuData *md = (EggRecentViewBonoboMenuData *) data;
123 g_return_if_fail (md);
124 g_return_if_fail (md->item);
125 g_return_if_fail (md->view);
126 g_return_if_fail (EGG_IS_RECENT_VIEW_BONOBO (md->view));
129 egg_recent_item_ref (item);
131 g_signal_emit (G_OBJECT(md->view),
132 egg_recent_view_bonobo_signals[ACTIVATE], 0,
135 egg_recent_item_unref (item);
139 egg_recent_view_bonobo_menu_data_destroy_cb (gpointer data, GClosure *closure)
141 EggRecentViewBonoboMenuData *md = data;
143 egg_recent_item_unref (md->item);
149 egg_recent_view_bonobo_set_list (EggRecentViewBonobo *view, GList *list)
151 BonoboUIComponent* ui_component;
154 gchar *verb_name = NULL;
156 gchar *escaped_name = NULL;
157 gchar *item_path = NULL;
161 gchar *xml_escaped_name;
162 EggRecentViewBonoboMenuData *md;
163 EggRecentModel *model;
166 g_return_if_fail (view);
168 ui_component = view->uic;
169 g_return_if_fail (BONOBO_IS_UI_COMPONENT (ui_component));
172 model = egg_recent_view_get_model (EGG_RECENT_VIEW (view));
174 egg_recent_view_bonobo_clear (view);
177 bonobo_ui_component_freeze (ui_component, NULL);
179 for (i = 1; i <= g_list_length (list); ++i)
181 EggRecentItem *item = (EggRecentItem *)g_list_nth_data (list, i-1);
183 utf8_uri = egg_recent_item_get_uri_for_display (item);
184 if (utf8_uri == NULL)
187 /* this is what gets passed to our private "activate" callback */
188 md = (EggRecentViewBonoboMenuData *)g_malloc (sizeof (EggRecentViewBonoboMenuData));
192 egg_recent_item_ref (md->item);
194 base_uri = g_path_get_basename (utf8_uri);
195 xml_escaped_name = g_markup_escape_text (base_uri,
198 escaped_name = egg_recent_util_escape_underlines (xml_escaped_name);
199 g_free (xml_escaped_name);
202 if (view->tooltip_func != NULL) {
204 tip = view->tooltip_func (item,
205 view->tooltip_func_data);
206 tmp_tip = g_markup_escape_text (tip, strlen (tip));
214 verb_name = g_strdup_printf ("%s-%d", view->uid, i);
216 if (view->show_icons) {
221 mime_type = egg_recent_item_get_mime_type (item);
222 uri = egg_recent_item_get_uri (item);
223 #ifndef USE_STABLE_LIBGNOMEUI
227 gtk_icon_size_lookup_for_settings
228 (gtk_settings_get_default (),
231 pixbuf = egg_recent_util_get_icon
241 if (pixbuf != NULL) {
245 pixbuf_xml = bonobo_ui_util_pixbuf_to_xml (pixbuf);
247 cmd = g_strdup_printf ("<cmd name=\"%s\" pixtype=\"pixbuf\" pixname=\"%s\"/>", verb_name, pixbuf_xml);
250 g_object_unref (pixbuf);
252 cmd = g_strdup_printf ("<cmd name=\"%s\"/> ",
259 cmd = g_strdup_printf ("<cmd name=\"%s\"/> ",
261 bonobo_ui_component_set_translate (ui_component, "/commands/", cmd, NULL);
263 closure = g_cclosure_new (G_CALLBACK (egg_recent_view_bonobo_menu_cb),
264 md, egg_recent_view_bonobo_menu_data_destroy_cb);
266 bonobo_ui_component_add_verb_full (ui_component, verb_name,
269 if (view->show_numbers) {
271 label = g_strdup_printf ("_%d. %s", i,
274 label = g_strdup_printf ("%d. %s", i, escaped_name);
276 label = g_strdup (escaped_name);
281 item_path = g_strconcat (view->path, "/", verb_name, NULL);
283 if (bonobo_ui_component_path_exists (ui_component, item_path, NULL))
285 bonobo_ui_component_set_prop (ui_component, item_path,
286 "label", label, NULL);
288 bonobo_ui_component_set_prop (ui_component, item_path,
295 xml = g_strdup_printf ("<menuitem name=\"%s\" "
297 " _label=\"%s\" _tip=\"%s\" "
299 verb_name, verb_name, label,
302 bonobo_ui_component_set_translate (ui_component, view->path, xml, NULL);
310 g_free (escaped_name);
319 bonobo_ui_component_thaw (ui_component, NULL);
323 model_changed_cb (EggRecentModel *model, GList *list, EggRecentViewBonobo *view)
326 egg_recent_view_bonobo_set_list (view, list);
328 egg_recent_view_bonobo_clear (view);
332 static EggRecentModel *
333 egg_recent_view_bonobo_get_model (EggRecentView *view_parent)
335 EggRecentViewBonobo *view;
337 g_return_val_if_fail (view_parent, NULL);
338 view = EGG_RECENT_VIEW_BONOBO (view_parent);
344 egg_recent_view_bonobo_set_model (EggRecentView *view_parent, EggRecentModel *model)
346 EggRecentViewBonobo *view;
348 g_return_if_fail (view_parent);
349 view = EGG_RECENT_VIEW_BONOBO (view_parent);
352 g_signal_handler_disconnect (G_OBJECT (view->model),
353 view->changed_cb_id);
356 g_object_ref (view->model);
357 view->changed_cb_id = g_signal_connect_object (G_OBJECT (model),
359 G_CALLBACK (model_changed_cb),
362 egg_recent_model_changed (view->model);
366 egg_recent_view_bonobo_set_property (GObject *object,
371 EggRecentViewBonobo *view = EGG_RECENT_VIEW_BONOBO (object);
375 case PROP_UI_COMPONENT:
376 egg_recent_view_bonobo_set_ui_component (EGG_RECENT_VIEW_BONOBO (view),
377 BONOBO_UI_COMPONENT (g_value_get_object (value)));
380 view->path = g_strdup (g_value_get_string (value));
382 case PROP_SHOW_ICONS:
383 egg_recent_view_bonobo_show_icons (view,
384 g_value_get_boolean (value));
386 case PROP_SHOW_NUMBERS:
387 egg_recent_view_bonobo_show_numbers (view,
388 g_value_get_boolean (value));
395 egg_recent_view_bonobo_get_property (GObject *object,
400 EggRecentViewBonobo *view = EGG_RECENT_VIEW_BONOBO (object);
404 case PROP_UI_COMPONENT:
405 g_value_set_pointer (value, view->uic);
408 g_value_set_string (value, g_strdup (view->path));
410 case PROP_SHOW_ICONS:
411 g_value_set_boolean (value, view->show_icons);
413 case PROP_SHOW_NUMBERS:
414 g_value_set_boolean (value, view->show_numbers);
417 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
422 egg_recent_view_bonobo_finalize (GObject *object)
424 EggRecentViewBonobo *view = EGG_RECENT_VIEW_BONOBO (object);
429 g_object_unref (view->model);
430 g_object_unref (view->uic);
431 #ifndef USE_STABLE_LIBGNOMEUI
432 g_object_unref (view->theme);
434 g_object_unref (view->client);
438 egg_recent_view_bonobo_class_init (EggRecentViewBonoboClass * klass)
440 GObjectClass *object_class;
443 object_class = G_OBJECT_CLASS (klass);
445 object_class->set_property = egg_recent_view_bonobo_set_property;
446 object_class->get_property = egg_recent_view_bonobo_get_property;
447 object_class->finalize = egg_recent_view_bonobo_finalize;
449 egg_recent_view_bonobo_signals[ACTIVATE] = g_signal_new ("activate",
450 G_OBJECT_CLASS_TYPE (object_class),
452 G_STRUCT_OFFSET (EggRecentViewBonoboClass, activate),
454 g_cclosure_marshal_VOID__BOXED,
456 EGG_TYPE_RECENT_ITEM);
458 g_object_class_install_property (object_class,
460 g_param_spec_object ("ui-component",
462 "BonoboUIComponent for menus.",
463 bonobo_ui_component_get_type(),
466 g_object_class_install_property (object_class,
468 g_param_spec_string ("ui-path",
470 "The path to put the menu items.",
471 "/menus/File/EggRecentDocuments",
474 g_object_class_install_property (object_class,
476 g_param_spec_boolean ("show-icons",
478 "Whether or not to show icons",
482 g_object_class_install_property (object_class,
484 g_param_spec_boolean ("show-numbers",
486 "Whether or not to show numbers",
492 klass->activate = NULL;
496 egg_recent_view_init (EggRecentViewClass *iface)
498 iface->do_get_model = egg_recent_view_bonobo_get_model;
499 iface->do_set_model = egg_recent_view_bonobo_set_model;
503 show_menus_changed_cb (GConfClient *client,
506 EggRecentViewBonobo *view)
510 value = gconf_entry_get_value (entry);
512 g_return_if_fail (value->type == GCONF_VALUE_BOOL);
514 egg_recent_view_bonobo_show_icons (view,
515 gconf_value_get_bool (value));
519 #ifndef USE_STABLE_LIBGNOMEUI
521 theme_changed_cb (GnomeIconTheme *theme, EggRecentViewBonobo *view)
523 if (view->model != NULL)
524 egg_recent_model_changed (view->model);
529 egg_recent_view_bonobo_init (EggRecentViewBonobo *view)
531 view->uid = egg_recent_util_get_unique_id ();
532 #ifndef USE_STABLE_LIBGNOMEUI
533 view->theme = gnome_icon_theme_new ();
534 gnome_icon_theme_set_allow_svg (view->theme, TRUE);
535 g_signal_connect_object (view->theme, "changed",
536 G_CALLBACK (theme_changed_cb), view, 0);
539 view->client = gconf_client_get_default ();
541 gconf_client_get_bool (view->client,
542 "/desktop/gnome/interface/menus_have_icons",
545 gconf_client_add_dir (view->client, "/desktop/gnome/interface",
546 GCONF_CLIENT_PRELOAD_NONE,
548 gconf_client_notify_add (view->client,
549 "/desktop/gnome/interface/menus_have_icons",
550 (GConfClientNotifyFunc)show_menus_changed_cb,
553 view->tooltip_func = NULL;
554 view->tooltip_func_data = NULL;
556 view->icon_size = GTK_ICON_SIZE_MENU;
560 egg_recent_view_bonobo_set_icon_size (EggRecentViewBonobo *view,
561 GtkIconSize icon_size)
563 if (view->icon_size != icon_size) {
564 view->icon_size = icon_size;
565 egg_recent_model_changed (view->model);
567 view->icon_size = icon_size;
572 egg_recent_view_bonobo_get_icon_size (EggRecentViewBonobo *view)
574 return view->icon_size;
578 egg_recent_view_bonobo_show_icons (EggRecentViewBonobo *view, gboolean show)
580 view->show_icons = show;
583 egg_recent_model_changed (view->model);
587 egg_recent_view_bonobo_show_numbers (EggRecentViewBonobo *view, gboolean show)
589 view->show_numbers = show;
592 egg_recent_model_changed (view->model);
596 egg_recent_view_bonobo_set_ui_component (EggRecentViewBonobo *view, BonoboUIComponent *uic)
598 g_return_if_fail (view);
599 g_return_if_fail (uic);
603 g_object_ref (view->uic);
607 egg_recent_view_bonobo_set_ui_path (EggRecentViewBonobo *view, const gchar *path)
609 g_return_if_fail (view);
610 g_return_if_fail (path);
612 view->path = g_strdup (path);
615 const BonoboUIComponent *
616 egg_recent_view_bonobo_get_ui_component (EggRecentViewBonobo *view)
618 g_return_val_if_fail (view, NULL);
624 egg_recent_view_bonobo_get_ui_path (EggRecentViewBonobo *view)
626 g_return_val_if_fail (view, NULL);
628 return g_strdup (view->path);
632 egg_recent_view_bonobo_set_tooltip_func (EggRecentViewBonobo *view,
633 EggRecentViewBonoboTooltipFunc func,
636 view->tooltip_func = func;
637 view->tooltip_func_data = user_data;
640 egg_recent_model_changed (view->model);
644 * egg_recent_view_bonobo_new:
645 * @appname: The name of your application.
646 * @limit: The maximum number of items allowed.
648 * This creates a new EggRecentViewBonobo object.
650 * Returns: a EggRecentViewBonobo object
652 EggRecentViewBonobo *
653 egg_recent_view_bonobo_new (BonoboUIComponent *uic, const gchar *path)
655 EggRecentViewBonobo *view;
657 g_return_val_if_fail (uic, NULL);
658 g_return_val_if_fail (path, NULL);
660 view = EGG_RECENT_VIEW_BONOBO (g_object_new (egg_recent_view_bonobo_get_type (),
664 "show-numbers", TRUE, NULL));
666 g_return_val_if_fail (view, NULL);
672 * egg_recent_view_bonobo_get_type:
675 * This returns a GType representing a EggRecentViewBonobo object.
680 egg_recent_view_bonobo_get_type (void)
682 static GType egg_recent_view_bonobo_type = 0;
684 if(!egg_recent_view_bonobo_type) {
685 static const GTypeInfo egg_recent_view_bonobo_info = {
686 sizeof (EggRecentViewBonoboClass),
687 NULL, /* base init */
688 NULL, /* base finalize */
689 (GClassInitFunc)egg_recent_view_bonobo_class_init, /* class init */
690 NULL, /* class finalize */
691 NULL, /* class data */
692 sizeof (EggRecentViewBonobo),
694 (GInstanceInitFunc) egg_recent_view_bonobo_init
697 static const GInterfaceInfo view_info =
699 (GInterfaceInitFunc) egg_recent_view_init,
704 egg_recent_view_bonobo_type = g_type_register_static (G_TYPE_OBJECT,
705 "EggRecentViewBonobo",
706 &egg_recent_view_bonobo_info, 0);
707 g_type_add_interface_static (egg_recent_view_bonobo_type,
708 EGG_TYPE_RECENT_VIEW,
712 return egg_recent_view_bonobo_type;