Logo Search packages:      
Sourcecode: kazehakase version File versions

kz-bookmark-tab-menu.c

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

/*
 *  Copyright (C) 2003-2004 Hiroyuki Ikezoe
 *  Copyright (C) 2003 Takuro Ashie
 *
 *  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, 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.
 *
 *  $Id: kz-bookmark-tab-menu.c,v 1.5 2005/02/13 13:20:34 ikezoe Exp $
 */

#include "kz-bookmark-tab-menu.h"

#include <glib/gi18n.h>

#include "kazehakase.h"
#include "kz-actions.h"
#include "kz-tab-label.h"
#include "kz-favicon.h"
#include "utils.h"

#define KZ_BOOKMARK_TAB_MENU_BOOKMARK_KEY "KzBookmarkTabMenu::Bookmark"
#define KZ_BOOKMARK_TAB_MENU_WINDOW_KEY   "KzBookmarkTabMenu::Window"
#define KZ_BOOKMARK_TAB_MENU_TOOLTIP_KEY  "KzBookmarkTabMenu::ToolTips"
#define KZ_BOOKMARK_TAB_MENU_EMPTY_KEY    "KzBookmarkTabMEnu::Empty"

static void       connect_bookmark_signals       (GtkWidget      *widget,
                                      KzBookmark     *item);
static void       disconnect_bookmark_signals    (GtkWidget      *widget,
                                      KzBookmark     *item);
static void       disconnect_menuitem_signals    (GtkWidget      *widget,
                                      KzBookmark     *item);

static void       connect_folder_signals         (KzBookmark     *folder,
                                      GtkMenuShell   *shell);
static void       disconnect_folder_signals      (KzBookmark     *folder,
                                      GtkMenuShell   *shell);
static void       disconnect_menu_signals        (KzBookmark     *folder,
                                      GtkMenuShell   *shell);

static void       cb_tab_menu_item_activate      (GtkWidget      *widget,
                                      KzWindow       *kz);


GtkWidget *
kz_bookmark_menu_create_tab_menuitem (KzBookmark *bookmark, KzWindow *kz)
{
      GtkWidget *menu_item;
      const gchar *title = NULL, *desc;
      gchar *tooltip_text = NULL;
      GtkTooltips *tooltip = NULL;
      GtkWidget *favicon;
      KzBookmark *cur_page;
      gint cur_pos;
      GList *pages;
      KzFavicon *kzfav;

      g_return_val_if_fail(KZ_IS_BOOKMARK(bookmark), NULL);
      g_return_val_if_fail(kz_bookmark_is_folder(bookmark), NULL);
      g_return_val_if_fail(KZ_IS_WINDOW(kz), NULL);

      cur_pos = kz_bookmark_get_current(bookmark);

      pages = kz_bookmark_get_children(bookmark);
      cur_page = KZ_BOOKMARK(g_list_nth_data(pages, cur_pos));
      g_list_free(pages);
      
      if (!KZ_IS_BOOKMARK(cur_page)) return NULL;
      
      title = kz_bookmark_get_title(cur_page);
      if (!title)
            title = "";

      desc = kz_bookmark_get_description(cur_page);
      if (desc)
            tooltip_text = remove_tag(desc, strlen(desc));
      
      menu_item = gtk_image_menu_item_new_with_label(title);
      g_object_set_data(G_OBJECT(menu_item),
                    KZ_BOOKMARK_TAB_MENU_BOOKMARK_KEY,
                    bookmark);
      g_object_set_data(G_OBJECT(menu_item),
                    KZ_BOOKMARK_TAB_MENU_WINDOW_KEY,
                    kz);

      g_signal_connect(menu_item, "activate",
                   G_CALLBACK(cb_tab_menu_item_activate),
                   kz);

      /* favicon */
      kzfav = kz_favicon_get_instance();
      favicon = kz_favicon_get_widget(kzfav,
                              kz_bookmark_get_link(cur_page),
                              KZ_ICON_SIZE_BOOKMARK_MENU);
      if (favicon)
      {
            gtk_widget_show(favicon);
            gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item),
                                    favicon);
      }
      g_object_unref(kzfav);

      /* tooltips */
      tooltip = gtk_tooltips_new();
      g_object_ref(G_OBJECT(tooltip));
      gtk_object_sink(GTK_OBJECT(tooltip));
      if (tooltip_text)
      {
            gtk_tooltips_set_tip(tooltip, menu_item, tooltip_text, NULL);
            g_free(tooltip_text);
      }
      g_object_set_data_full(G_OBJECT(menu_item),
                         KZ_BOOKMARK_TAB_MENU_TOOLTIP_KEY,
                         tooltip,
                         (GDestroyNotify) g_object_unref);
      connect_bookmark_signals(menu_item, cur_page);

      return menu_item;
}

void
kz_bookmark_menu_append_tab_menuitems (GtkMenuShell *shell, KzWindow *kz, 
                               KzBookmark *folder)
{
      KzBookmark *prev_folder;
      GList *children, *node;

      g_return_if_fail(GTK_IS_MENU_SHELL(shell));
      g_return_if_fail(KZ_BOOKMARK(folder));
      g_return_if_fail(kz_bookmark_is_folder(folder));

      prev_folder = g_object_get_data(G_OBJECT(shell),
                              KZ_BOOKMARK_TAB_MENU_BOOKMARK_KEY);
      if (prev_folder)
      {
            disconnect_folder_signals(prev_folder, shell);
            disconnect_menu_signals(prev_folder, shell);
      }

      children = kz_bookmark_get_children(folder);

      /* empty label */
      {
            GtkWidget *widget;

            widget = gtk_image_menu_item_new_with_label(_("Empty Folder"));
            gtk_menu_shell_append(shell, widget);
            if (!children)
                  gtk_widget_show(widget);
            gtk_widget_set_sensitive(widget, FALSE);
            g_object_set_data(G_OBJECT(widget),
                          KZ_BOOKMARK_TAB_MENU_WINDOW_KEY,
                          kz);
            g_object_set_data(G_OBJECT(shell),
                          KZ_BOOKMARK_TAB_MENU_EMPTY_KEY,
                          widget);
      }

      /* tabs */
      for (node = children; node; node = g_list_next(node))
      {
            KzBookmark *tab = node->data;
            GtkWidget *widget;

            widget = kz_bookmark_menu_create_tab_menuitem(tab, kz);
            gtk_menu_shell_append(shell, widget);
            gtk_widget_show(widget);
      }

      g_list_free(children);

      connect_folder_signals(folder, shell);

      g_object_set_data(G_OBJECT(shell),
                    KZ_BOOKMARK_TAB_MENU_BOOKMARK_KEY,
                    folder);
      g_object_set_data(G_OBJECT(shell),
                    KZ_BOOKMARK_TAB_MENU_WINDOW_KEY,
                    kz);
}


void
kz_bookmark_menu_remove_tab_menuitems (GtkMenuShell *shell, KzWindow *kz)
{
      KzBookmark *folder;
      GList *children, *node;

      g_return_if_fail(GTK_IS_MENU_SHELL(shell));

      folder = g_object_get_data(G_OBJECT(shell),
                           KZ_BOOKMARK_TAB_MENU_BOOKMARK_KEY);
      if (KZ_IS_BOOKMARK(folder))
      {
            disconnect_folder_signals(folder, shell);
            disconnect_menu_signals(folder, shell);
      }

      children = g_list_copy(shell->children);

      for (node = children; node; node = g_list_next(node))
      {
            GtkWidget *menuitem = node->data;
            KzWindow *kz;

            kz = g_object_get_data(G_OBJECT(menuitem),
                               KZ_BOOKMARK_TAB_MENU_WINDOW_KEY);
            if (kz)
                  gtk_widget_destroy(menuitem);
      }

      g_list_free(children);

      g_object_set_data(G_OBJECT(shell),
                    KZ_BOOKMARK_TAB_MENU_BOOKMARK_KEY,
                    NULL);
      g_object_set_data(G_OBJECT(shell),
                    KZ_BOOKMARK_TAB_MENU_WINDOW_KEY,
                    NULL);
}


/*****************************************************************************
 *                                                                           *
 *                                Callbacks                                  *
 *                                                                           *
 *****************************************************************************/

static gint
find_menu_item (gconstpointer a, gconstpointer b)
{
      const KzBookmark *bookmark1, *bookmark2 = b;

      bookmark1 = g_object_get_data(G_OBJECT(a),
                              KZ_BOOKMARK_TAB_MENU_BOOKMARK_KEY);

      return bookmark1 - bookmark2;
}


static void
cb_notify_title (GObject *object, GParamSpec *pspec,
             GtkWidget *widget)
{
      const gchar *title;

      title = kz_bookmark_get_title(KZ_BOOKMARK(object));
      if (GTK_IS_LABEL(GTK_BIN(widget)->child))
            gtk_label_set_text(GTK_LABEL(GTK_BIN(widget)->child), title);
}


static void
cb_notify_desc (GObject *object, GParamSpec *pspec,
            GtkWidget *widget)
{
      GtkTooltips *tooltip;
      const gchar *desc;
      gchar *tooltip_text = NULL;
      
      desc = kz_bookmark_get_description(KZ_BOOKMARK(object));
      if (desc)
            tooltip_text = remove_tag(desc, strlen(desc));
      tooltip = g_object_get_data(G_OBJECT(widget),
                            KZ_BOOKMARK_TAB_MENU_TOOLTIP_KEY);
      if (GTK_IS_TOOLTIPS(tooltip) && tooltip_text)
      {
            gtk_tooltips_set_tip(tooltip, widget, tooltip_text, NULL);
            g_free(tooltip_text);
      }
}


static void
bookmark_weak_ref (gpointer data, GObject *obj)
{
      KzBookmark *item = KZ_BOOKMARK(obj);
      GtkWidget *widget = data;

      if (!widget) return;

      disconnect_menuitem_signals (widget, item);
}


static void
cb_menuitem_destroy(GtkWidget *widget, KzBookmark *item)
{
      disconnect_bookmark_signals(widget, item);
}


static void
connect_bookmark_signals (GtkWidget *widget, KzBookmark *item)
{
      g_signal_connect(item, "notify::title",
                   G_CALLBACK(cb_notify_title),
                   widget);
      g_signal_connect(item, "notify::description",
                   G_CALLBACK(cb_notify_desc),
                   widget);

      g_signal_connect(widget, "destroy",
                   G_CALLBACK(cb_menuitem_destroy), item);
      g_object_weak_ref(G_OBJECT(item), bookmark_weak_ref, widget);
}


static void
disconnect_bookmark_signals (GtkWidget *widget, KzBookmark *item)
{
      g_signal_handlers_disconnect_by_func(item,
                                   G_CALLBACK(cb_notify_title),
                                   widget);
      g_signal_handlers_disconnect_by_func(item,
                                   G_CALLBACK(cb_notify_desc),
                                   widget);

      g_object_weak_unref(G_OBJECT(item), bookmark_weak_ref, widget);
}


static void
disconnect_menuitem_signals (GtkWidget *widget, KzBookmark *item)
{
      g_signal_handlers_disconnect_by_func(widget,
                                   G_CALLBACK(cb_menuitem_destroy),
                                   item);
}


/*****************************************************************************
 *                                                                           *
 *                               for  menu                                   *
 *                                                                           *
 *****************************************************************************/
static void
cb_folder_insert_child (KzBookmark *item,
                  KzBookmark *child, KzBookmark *sibling,
                  GtkMenuShell *shell)
{
      KzWindow *kz;
      GtkWidget *menuitem, *empty_label;
      GList *list;

      kz = g_object_get_data(G_OBJECT(shell), KZ_BOOKMARK_TAB_MENU_WINDOW_KEY);
      list = shell->children;

      menuitem = kz_bookmark_menu_create_tab_menuitem(child, kz);
      if (!menuitem) return;
      
      gtk_widget_show(menuitem);

      gtk_menu_shell_prepend(shell, menuitem);

      empty_label = g_object_get_data(G_OBJECT(shell),
                              KZ_BOOKMARK_TAB_MENU_EMPTY_KEY);
      if (GTK_IS_WIDGET(empty_label))
            gtk_widget_hide(empty_label);
}


static void
cb_folder_remove_child (KzBookmark *item,
                  KzBookmark *child, GtkMenuShell *shell)
{
      KzWindow *kz;
      GList *list, *node;
      GtkWidget *empty_label;

      kz = g_object_get_data(G_OBJECT(shell), KZ_BOOKMARK_TAB_MENU_WINDOW_KEY);
      list = shell->children;

      node = g_list_find_custom(list, child, find_menu_item);
      g_return_if_fail(node);
      gtk_widget_destroy(node->data);

      if (kz_bookmark_has_children(item)) return;

      empty_label = g_object_get_data(G_OBJECT(shell),
                              KZ_BOOKMARK_TAB_MENU_EMPTY_KEY);
      if (GTK_IS_WIDGET(empty_label))
            gtk_widget_show(empty_label);
}


static void
cb_folder_reordered (KzBookmark *item, GtkMenuShell *shell)
{
      KzWindow *kz;

      kz = g_object_get_data(G_OBJECT(shell), KZ_BOOKMARK_TAB_MENU_WINDOW_KEY);
      kz_bookmark_menu_remove_tab_menuitems(shell, kz);
      kz_bookmark_menu_append_tab_menuitems(shell, kz, item);
}


static void
folder_weak_ref (gpointer data, GObject *obj)
{
      KzBookmark *folder = KZ_BOOKMARK(obj);
      GtkMenuShell *shell = data;

      disconnect_menu_signals(folder, GTK_MENU_SHELL(shell));
}


static void
cb_root_menu_destroy(GtkWidget *widget, KzBookmark *folder)
{
      disconnect_folder_signals(folder, GTK_MENU_SHELL(widget));
}


static void
connect_folder_signals (KzBookmark *folder, GtkMenuShell *shell)
{
      g_signal_connect_after(folder, "insert-child",
                         G_CALLBACK(cb_folder_insert_child),
                         shell);
      g_signal_connect_after(folder, "remove-child",
                         G_CALLBACK(cb_folder_remove_child),
                         shell);
      g_signal_connect_after(folder, "children-reordered",
                         G_CALLBACK(cb_folder_reordered),
                         shell);

      g_signal_connect(shell, "destroy",
                   G_CALLBACK(cb_root_menu_destroy), folder);
      g_object_weak_ref(G_OBJECT(folder), folder_weak_ref, shell);
}


static void
disconnect_folder_signals (KzBookmark *folder, GtkMenuShell *shell)
{
      g_signal_handlers_disconnect_by_func
            (folder,
             G_CALLBACK(cb_folder_insert_child),
             shell);
      g_signal_handlers_disconnect_by_func
            (folder,
             G_CALLBACK(cb_folder_remove_child),
             shell);
      g_signal_handlers_disconnect_by_func
            (folder,
             G_CALLBACK(cb_folder_reordered),
             shell);

      g_object_weak_unref(G_OBJECT(folder), folder_weak_ref, shell);
}


static void
disconnect_menu_signals (KzBookmark *folder, GtkMenuShell *shell)
{
      g_signal_handlers_disconnect_by_func
            (shell,
             G_CALLBACK(cb_root_menu_destroy),
             folder);
}

/* for closed tab menu */
static void 
cb_tab_menu_item_activate (GtkWidget *widget, KzWindow *kz)
{
      KzBookmark *item, *parent;
      GtkWidget *kzembed;
      KzTabLabel *kztab;

      g_return_if_fail(KZ_IS_WINDOW(kz));

      item = g_object_get_data(G_OBJECT(widget),
                         KZ_BOOKMARK_TAB_MENU_BOOKMARK_KEY);
      g_return_if_fail(item);

      kzembed = kz_window_open_new_tab(kz, NULL);
      kztab = KZ_TAB_LABEL(gtk_notebook_get_tab_label(
                       GTK_NOTEBOOK(kz->notebook),
                       kzembed));
      kz_tab_label_set_history(KZ_TAB_LABEL(kztab), item);

      /* FIXME! should use parent bookmark */ 
      kz_bookmark_remove(kz->closed_tabs, item);
}


Generated by  Doxygen 1.6.0   Back to index