Logo Search packages:      
Sourcecode: file-roller version File versions  Download package

egg-recent-view-uimanager.c

/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */

/**
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
 *
 * Authors:
 *   James Willcox <jwillcox@cs.indiana.edu>
 *   Paolo Bacchilega <paobac@cvs.gnome.org>
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <gtk/gtk.h>
#include <libgnomevfs/gnome-vfs.h>
#ifndef USE_STABLE_LIBGNOMEUI
#include <libgnomeui/gnome-icon-theme.h>
#endif
#include <gconf/gconf-client.h>
#include "egg-recent-model.h"
#include "egg-recent-view.h"
#include "egg-recent-view-uimanager.h"
#include "egg-recent-util.h"
#include "egg-recent-item.h"

#define EGG_RECENT_NAME_PREFIX "EggRecentAction"
#define EGG_RECENT_ACTION "EggRecentFile"
#define EGG_RECENT_SEPARATOR (NULL)

struct _EggRecentViewUIManager {
      GObject         parent_instance;

      GCallback       action_callback;
      gpointer        action_user_data;

      gboolean        leading_sep;
      gboolean        trailing_sep;

      GtkUIManager   *uimanager;
      GtkActionGroup *action_group;
      guint           merge_id;
      gulong          changed_cb_id;

      gchar          *path;

      gboolean        show_icons;
      gboolean        show_numbers;
#ifndef USE_STABLE_LIBGNOMEUI
      GnomeIconTheme *theme;
#endif

      EggUIManagerTooltipFunc tooltip_func;
      gpointer        tooltip_func_data;

      EggRecentModel *model;
      GConfClient    *client;
      GtkIconSize     icon_size;
};


struct _EggRecentViewUIManagerMenuData {
      EggRecentViewUIManager *view;
      EggRecentItem *item;
};

typedef struct _EggRecentViewUIManagerMenuData EggRecentViewUIManagerMenuData;

enum {
      ACTIVATE,
      LAST_SIGNAL
};

/* GObject properties */
enum {
      PROP_BOGUS,
      PROP_UIMANAGER,
      PROP_PATH,
      PROP_SHOW_ICONS,
      PROP_SHOW_NUMBERS
};

static guint view_signals[LAST_SIGNAL] = { 0 };

static void
egg_recent_view_uimanager_clear (EggRecentViewUIManager *view)
{
      if (view->merge_id != 0) {
            gtk_ui_manager_remove_ui (view->uimanager, view->merge_id);
            view->merge_id = 0;
      }

      if (view->action_group != NULL) {
            gtk_ui_manager_remove_action_group (view->uimanager, view->action_group);
            g_object_unref (view->action_group);
            view->action_group = NULL;
      }

      gtk_ui_manager_ensure_update (view->uimanager);
}

static void
egg_recent_view_uimanager_set_list (EggRecentViewUIManager *view, GList *list)
{
      GList  *scan;
      guint   index = 1;

      g_return_if_fail (view);

      egg_recent_view_uimanager_clear (view);

      if (view->merge_id == 0)
            view->merge_id = gtk_ui_manager_new_merge_id (view->uimanager);

      if (view->action_group == NULL) {
            gchar *group = g_strdup_printf ("EggRecentActions%u", 
                                    view->merge_id);
            view->action_group = gtk_action_group_new (group);
            gtk_ui_manager_insert_action_group (view->uimanager, view->action_group, 0);
            g_free (group);
      }

      if (view->leading_sep) {
            gchar *action = g_strdup_printf ("EggRecentLeadingSeparator%u",
                                     view->merge_id);
            gtk_ui_manager_add_ui (view->uimanager, 
                               view->merge_id, 
                               view->path,
                               action,
                               EGG_RECENT_SEPARATOR,
                               GTK_UI_MANAGER_AUTO, 
                               FALSE);
            g_free (action);
      }

      for (scan = list; scan; scan = scan->next, index++) {
            EggRecentItem *item = scan->data;
            GtkAction     *action;
            gchar         *name;
            gchar         *uri;
            gchar         *basename;
            gchar         *escaped;
            gchar         *label;
            gchar         *tooltip = NULL;

            uri = egg_recent_item_get_uri_for_display (item);
            if (uri == NULL)
                  continue;

            name = g_strdup_printf (EGG_RECENT_NAME_PREFIX"%u-%u", 
                              view->merge_id,
                              index);

            if (view->tooltip_func != NULL)
                  tooltip = (*view->tooltip_func) (item, view->tooltip_func_data);

            basename = g_path_get_basename (uri);
            escaped = egg_recent_util_escape_underlines (basename);
            g_free (basename);
            g_free (uri);

            if (view->show_numbers) {
                  if (index >= 10)
                        label = g_strdup_printf ("%d.  %s", 
                                           index, 
                                           escaped);
                  else
                        label = g_strdup_printf ("_%d.  %s", 
                                           index, 
                                           escaped);
                  g_free (escaped);
            } else 
                  label = escaped;

            action = g_object_new (GTK_TYPE_ACTION,
                               "name", name,
                               "label", label,
                               (view->show_icons)? "stock_id": NULL, 
                               GTK_STOCK_OPEN,
                               NULL);
            if (tooltip != NULL) {
                  g_object_set (action, "tooltip", tooltip, NULL);
                  g_free (tooltip);
            }
            egg_recent_item_ref (item);
            g_object_set_data_full (G_OBJECT (action), 
                              "egg_recent_uri", 
                              item, 
                              (GFreeFunc) egg_recent_item_unref);

            if (view->action_callback != NULL) {
                  GClosure *closure;
                  closure = g_cclosure_new (view->action_callback, view->action_user_data, NULL);
                  g_signal_connect_closure (action, "activate", closure, FALSE);
            }

            gtk_action_group_add_action (view->action_group, action);
            g_object_unref (action);

            gtk_ui_manager_add_ui (view->uimanager, 
                               view->merge_id, 
                               view->path,
                               name,
                               name,
                               GTK_UI_MANAGER_AUTO, 
                               FALSE);

            g_free (name);
            g_free (label);
      }

      if (view->trailing_sep) {
            gchar *action = g_strdup_printf ("EggRecentTrailingSeparator%u",
                                    view->merge_id);
            gtk_ui_manager_add_ui (view->uimanager, 
                               view->merge_id, 
                               view->path,
                               action,
                               EGG_RECENT_SEPARATOR,
                               GTK_UI_MANAGER_AUTO, 
                               FALSE);
            g_free (action);
      }
}

static void
model_changed_cb (EggRecentModel         *model,  
              GList                  *list, 
              EggRecentViewUIManager *view)
{
      if (list != NULL)
            egg_recent_view_uimanager_set_list (view, list);
      else
            egg_recent_view_uimanager_clear (view);
      gtk_ui_manager_ensure_update (view->uimanager);
}

static EggRecentModel *
egg_recent_view_uimanager_get_model (EggRecentView *view_parent)
{
      EggRecentViewUIManager *view;
      
      g_return_val_if_fail (view_parent != NULL, NULL);
      view = EGG_RECENT_VIEW_UIMANAGER (view_parent);
      return view->model;
}

static void
egg_recent_view_uimanager_set_model (EggRecentView  *view_parent,
                             EggRecentModel *model)
{
      EggRecentViewUIManager *view;
      
      g_return_if_fail (view_parent != NULL);
      view = EGG_RECENT_VIEW_UIMANAGER (view_parent);

      if (view->model != NULL) {
            if (view->changed_cb_id != 0)
                  g_signal_handler_disconnect (G_OBJECT (view->model),
                                         view->changed_cb_id);
            g_object_unref (view->model);
      }
      
      view->model = model;
      g_object_ref (view->model);

      view->changed_cb_id = g_signal_connect_object (G_OBJECT (model),
                                           "changed",
                                           G_CALLBACK (model_changed_cb),
                                           view, 0);

      egg_recent_model_changed (view->model);
}

void
egg_recent_view_uimanager_set_leading_sep (EggRecentViewUIManager *view, 
                                 gboolean                val)
{
      view->leading_sep = val;
      egg_recent_view_uimanager_clear (view);
      if (view->model)
            egg_recent_model_changed (view->model);
}

void
egg_recent_view_uimanager_set_trailing_sep (EggRecentViewUIManager *view,
                                  gboolean                val)
{
      view->trailing_sep = val;
      egg_recent_view_uimanager_clear (view);
      if (view->model)
            egg_recent_model_changed (view->model);
}

static void
egg_recent_view_uimanager_set_property (GObject      *object,
                              guint         prop_id,
                              const GValue *value,
                              GParamSpec   *pspec)
{
      EggRecentViewUIManager *view = EGG_RECENT_VIEW_UIMANAGER (object);

      switch (prop_id) {
      case PROP_UIMANAGER:
            egg_recent_view_uimanager_set_uimanager (view, (GtkUIManager*)g_value_get_object (value));
            break;
      case PROP_PATH:
            egg_recent_view_uimanager_set_path (view, g_value_get_string (value));
            break;
      case PROP_SHOW_ICONS:
            egg_recent_view_uimanager_show_icons (view, g_value_get_boolean (value));
            break;
      case PROP_SHOW_NUMBERS:
            egg_recent_view_uimanager_show_numbers (view, g_value_get_boolean (value));
            break;
      default:
            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
            break;
      }
}

static void
egg_recent_view_uimanager_get_property (GObject    *object,
                              guint       prop_id,
                              GValue     *value,
                              GParamSpec *pspec)
{
      EggRecentViewUIManager *view = EGG_RECENT_VIEW_UIMANAGER (object);

      switch (prop_id) {
      case PROP_UIMANAGER:
            g_value_set_object (value, view->uimanager);
            break;
      case PROP_PATH:
            g_value_set_string (value, view->path);
            break;
      case PROP_SHOW_ICONS:
            g_value_set_boolean (value, view->show_icons);
            break;
      case PROP_SHOW_NUMBERS:
            g_value_set_boolean (value, view->show_numbers);
            break;
      default:
            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
            break;
      }
}

static void
egg_recent_view_uimanager_finalize (GObject *object)
{
      EggRecentViewUIManager *view = EGG_RECENT_VIEW_UIMANAGER (object);

      if (view->changed_cb_id != 0) {
            g_signal_handler_disconnect (G_OBJECT (view->model),
                                   view->changed_cb_id);
            view->changed_cb_id = 0;
      }

      g_free (view->path);

      egg_recent_view_uimanager_clear (view);

      if (view->action_group != NULL) {
            g_object_unref (view->action_group);
            view->action_group = NULL;
      }

      if (view->uimanager != NULL) {
            g_object_unref (view->uimanager);
            view->uimanager = NULL;
      }

      if (view->model != NULL) {
            g_object_unref (view->model);
            view->model = NULL;
      }

#ifndef USE_STABLE_LIBGNOMEUI
      if (view->theme != NULL) {
            g_object_unref (view->theme);
            view->theme = NULL;
      }
#endif

      if (view->client != NULL) {
            g_object_unref (view->client);
            view->client = NULL;
      }
}

static void
egg_recent_view_uimanager_class_init (EggRecentViewUIManagerClass * klass)
{
      GObjectClass *object_class;

      object_class = G_OBJECT_CLASS (klass);

      object_class->set_property = egg_recent_view_uimanager_set_property;
      object_class->get_property = egg_recent_view_uimanager_get_property;
      object_class->finalize     = egg_recent_view_uimanager_finalize;

      view_signals[ACTIVATE] = g_signal_new ("activate",
                                     G_OBJECT_CLASS_TYPE (object_class),
                                     G_SIGNAL_RUN_LAST,
                                     G_STRUCT_OFFSET (EggRecentViewUIManagerClass, activate),
                                     NULL, NULL,
                                     g_cclosure_marshal_VOID__BOXED,
                                     G_TYPE_NONE, 1,
                                     EGG_TYPE_RECENT_ITEM);

      g_object_class_install_property (object_class,
                               PROP_UIMANAGER,
                               g_param_spec_object ("uimanager",
                                                "UI Manager",
                                                "The UI manager this object will use to update.the UI",
                                                GTK_TYPE_UI_MANAGER,
                                                G_PARAM_READWRITE));
      g_object_class_install_property (object_class,
                               PROP_PATH,
                               g_param_spec_string ("path",
                                                "Path",
                                                "The UI path this object will update.",
                                                NULL,
                                                G_PARAM_READWRITE));
      g_object_class_install_property (object_class,
                               PROP_SHOW_ICONS,
                               g_param_spec_boolean ("show-icons",
                                                 "Show Icons",
                                                 "Whether or not to show icons",
                                                 FALSE,
                                                 G_PARAM_READWRITE));
      
      g_object_class_install_property (object_class,
                               PROP_SHOW_NUMBERS,
                               g_param_spec_boolean ("show-numbers",
                                                 "Show Numbers",
                                                 "Whether or not to show numbers",
                                                 TRUE,
                                                 G_PARAM_READWRITE));

      klass->activate = NULL;
}

static void
egg_recent_view_init (EggRecentViewClass *iface)
{
      iface->do_get_model = egg_recent_view_uimanager_get_model;
      iface->do_set_model = egg_recent_view_uimanager_set_model;
}

static void
show_menus_changed_cb (GConfClient            *client,
                   guint                   cnxn_id,
                   GConfEntry             *entry,
                   EggRecentViewUIManager *view)
{
      GConfValue *value;

      value = gconf_entry_get_value (entry);
      g_return_if_fail (value->type == GCONF_VALUE_BOOL);

      egg_recent_view_uimanager_show_icons (view, gconf_value_get_bool (value));
}

#ifndef USE_STABLE_LIBGNOMEUI
static void
theme_changed_cb (GnomeIconTheme         *theme, 
              EggRecentViewUIManager *view)
{
      if (view->model != NULL)
            egg_recent_model_changed (view->model);
}
#endif

static void
egg_recent_view_uimanager_init (EggRecentViewUIManager * view)
{
      view->client = gconf_client_get_default ();

      view->show_icons = gconf_client_get_bool (view->client,
                                      "/desktop/gnome/interface/menus_have_icons",
                                      NULL);
      
      gconf_client_add_dir (view->client, "/desktop/gnome/interface",
                        GCONF_CLIENT_PRELOAD_NONE,
                        NULL);
      gconf_client_notify_add (view->client,
                         "/desktop/gnome/interface/menus_have_icons",
                         (GConfClientNotifyFunc)show_menus_changed_cb,
                         view, NULL, NULL);


      view->leading_sep = FALSE;
      view->trailing_sep = FALSE;
      view->show_numbers = TRUE;

      view->uimanager = NULL;
      view->action_group = NULL;
      view->merge_id = 0;
      view->changed_cb_id = 0;

      view->path = NULL;

#ifndef USE_STABLE_LIBGNOMEUI
      view->theme = gnome_icon_theme_new ();
      gnome_icon_theme_set_allow_svg (view->theme, TRUE);
      g_signal_connect_object (view->theme, "changed",
                         G_CALLBACK (theme_changed_cb), view, 0);
#endif

      view->tooltip_func = NULL;
      view->tooltip_func_data = NULL;

      view->icon_size = GTK_ICON_SIZE_MENU;
}

void
egg_recent_view_uimanager_set_icon_size (EggRecentViewUIManager *view,
                               GtkIconSize             icon_size)
{
      if (view->icon_size != icon_size) {
            view->icon_size = icon_size;
            egg_recent_model_changed (view->model);
      } else {
            view->icon_size = icon_size;
      }
}

GtkIconSize
egg_recent_view_uimanager_get_icon_size (EggRecentViewUIManager *view)
{
      return view->icon_size;
}

void
egg_recent_view_uimanager_show_icons (EggRecentViewUIManager *view,
                              gboolean                show)
{
      view->show_icons = show;
      if (view->model != NULL)
            egg_recent_model_changed (view->model);
}

void
egg_recent_view_uimanager_show_numbers (EggRecentViewUIManager *view, 
                              gboolean                show)
{
      view->show_numbers = show;
      if (view->model != NULL)
            egg_recent_model_changed (view->model);
}

void
egg_recent_view_uimanager_set_tooltip_func (EggRecentViewUIManager   *view,
                                  EggUIManagerTooltipFunc   func,
                                  gpointer                  user_data)
{
      view->tooltip_func = func;
      view->tooltip_func_data = user_data;
      if (view->model)
            egg_recent_model_changed (view->model);
}

/**
 * egg_recent_view_uimanager_set_uimanager:
 * @view: A EggRecentViewUIManager object.
 * @uimanager: The ui manager used to put the menu items in.
 *
 * Use this function to change the ui manager used to update the menu.
 *
 */
void
egg_recent_view_uimanager_set_uimanager (EggRecentViewUIManager *view,
                               GtkUIManager           *uimanager)
{
      g_return_if_fail (EGG_IS_RECENT_VIEW_UIMANAGER (view));
      g_return_if_fail (uimanager != NULL);

      if (view->uimanager != NULL)
            g_object_unref (view->uimanager);
      view->uimanager = uimanager;
      g_object_ref (view->uimanager);
}

/**
 * egg_recent_view_uimanager_get_uimanager:
 * @view: A EggRecentViewUIManager object.
 *
 */
GtkUIManager*
egg_recent_view_uimanager_get_uimanager (EggRecentViewUIManager *view)
{
      g_return_val_if_fail (EGG_IS_RECENT_VIEW_UIMANAGER (view), NULL);
      return view->uimanager;
}

/**
 * egg_recent_view_uimanager_set_path:
 * @view: A EggRecentViewUIManager object.
 * @path: The path to put the menu items in.
 *
 * Use this function to change the path where the recent
 * documents appear in.
 *
 */
void
egg_recent_view_uimanager_set_path (EggRecentViewUIManager *view,
                            const gchar            *path)
{
      g_return_if_fail (EGG_IS_RECENT_VIEW_UIMANAGER (view));
      g_return_if_fail (path);

      g_free (view->path);
      view->path = g_strdup (path);
}

/**
 * egg_recent_view_uimanager_get_path:
 * @view: A EggRecentViewUIManager object.
 *
 */
G_CONST_RETURN gchar*
egg_recent_view_uimanager_get_path (EggRecentViewUIManager *view)
{
      g_return_val_if_fail (EGG_IS_RECENT_VIEW_UIMANAGER (view), NULL);
      return view->path;
}

void
egg_recent_view_uimanager_set_action_func (EggRecentViewUIManager   *view,
                                 GCallback                 callback,
                                 gpointer                  user_data)
{
      g_return_if_fail (EGG_IS_RECENT_VIEW_UIMANAGER (view));
      view->action_callback = callback;
      view->action_user_data = user_data;
}

/**
 * egg_recent_view_uimanager_new:
 * @appname: The name of your application.
 * @limit:  The maximum number of items allowed.
 *
 * This creates a new EggRecentViewUIManager object.
 *
 * Returns: a EggRecentViewUIManager object
 */
EggRecentViewUIManager *
egg_recent_view_uimanager_new (GtkUIManager  *uimanager,
                         const gchar   *path,
                         GCallback      callback,
                         gpointer       user_data)
{
      GObject *view;

      g_return_val_if_fail (uimanager, NULL);
      g_return_val_if_fail (path, NULL);

      view = g_object_new (egg_recent_view_uimanager_get_type (),
                       "uimanager", uimanager,
                       "path", path,
                       NULL);

      g_return_val_if_fail (view, NULL);
      
      egg_recent_view_uimanager_set_action_func (EGG_RECENT_VIEW_UIMANAGER (view),
                                       callback,
                                       user_data);

      return EGG_RECENT_VIEW_UIMANAGER (view);
}

/**
 * egg_recent_view_uimanager_get_type:
 * @:
 *
 * This returns a GType representing a EggRecentViewUIManager object.
 *
 * Returns: a GType
 */
GType
egg_recent_view_uimanager_get_type (void)
{
      static GType egg_recent_view_uimanager_type = 0;

      if(!egg_recent_view_uimanager_type) {
            static const GTypeInfo egg_recent_view_uimanager_info = {
                  sizeof (EggRecentViewUIManagerClass),
                  NULL, /* base init */
                  NULL, /* base finalize */
                  (GClassInitFunc)egg_recent_view_uimanager_class_init, /* class init */
                  NULL, /* class finalize */
                  NULL, /* class data */
                  sizeof (EggRecentViewUIManager),
                  0,
                  (GInstanceInitFunc) egg_recent_view_uimanager_init
            };

            static const GInterfaceInfo view_info =
            {
                  (GInterfaceInitFunc) egg_recent_view_init,
                  NULL,
                  NULL
            };

            egg_recent_view_uimanager_type = g_type_register_static (G_TYPE_OBJECT,
                                                       "EggRecentViewUIManager",
                                                       &egg_recent_view_uimanager_info, 0);
            g_type_add_interface_static (egg_recent_view_uimanager_type,
                                   EGG_TYPE_RECENT_VIEW,
                                   &view_info);
      }

      return egg_recent_view_uimanager_type;
}

EggRecentItem*
egg_recent_view_uimanager_get_item (EggRecentViewUIManager   *view,
                            GtkAction                *action)
{
      return g_object_get_data (G_OBJECT(action), "egg_recent_uri");
}

Generated by  Doxygen 1.6.0   Back to index