Logo Search packages:      
Sourcecode: kazehakase version File versions

kz-tab-label.c

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

/*
 *  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.
 */

#include "kz-tab-label.h"

#include <stdlib.h>
#include <string.h>
#include <glib/gi18n.h>
#include "gobject-utils.h"
#include "gtk-utils.h"
#include "kazehakase.h"
#include "kz-actions.h"
#include "kz-actions-tab.h"
#include "kz-icons.h"
#include "kz-favicon.h"
#include "kz-input-event-box.h"
#include "kz-bookmark-file.h"

enum {
      PROP_0,
      PROP_KZ_WINDOW,
      PROP_KZ_EMBED
};


struct _KzTabLabelPriv
{
      gint width;
      gint start_x, start_y;
      gboolean moved;
      gboolean lock;
      gboolean auto_refresh;
      guint auto_refresh_id;
      gulong favicon_signal;
};

static gchar *label_color[KZ_TAB_LABEL_N_STATE];

#define DEFAULT_AUTO_REFRESH_INTERVAL_SEC 300

/* object class */
static void     kz_tab_label_class_init         (KzTabLabelClass *klass);
static void     kz_tab_label_init               (KzTabLabel *kztab);
static GObject *kz_tab_label_constructor        (GType type,
                                     guint n_props,
                                     GObjectConstructParam *props);
static void     kz_tab_label_dispose            (GObject *object);
static void     kz_tab_label_finalize           (GObject *object);
static void     kz_tab_label_set_property       (GObject *object,
                                     guint prop_id,
                                     const GValue *value,
                                     GParamSpec *pspec);
static void     kz_tab_label_get_property       (GObject *object,
                                     guint prop_id,
                                     GValue *value,
                                     GParamSpec *pspec);

/* widget class */
static void     kz_tab_label_realize            (GtkWidget *widget);
#if 0
static void     kz_tab_label_unrealize          (GtkWidget *widget);
#endif
static gboolean kz_tab_label_button_press       (GtkWidget *widget,
                                     GdkEventButton *event);
static gboolean kz_tab_label_motion_notify      (GtkWidget *widget,
                                     GdkEventMotion *event);
static gboolean kz_tab_label_button_release     (GtkWidget *widget,
                                     GdkEventButton *event);
static gboolean kz_tab_label_scroll_event       (GtkWidget *widget,
                                     GdkEventScroll *event);
static gboolean kz_tab_label_drag_motion        (GtkWidget *widget,
                                     GdkDragContext *drag_context,
                                     gint x, gint y,
                                     guint time);
static void     kz_tab_label_drag_data_get      (GtkWidget        *widget,
                                     GdkDragContext   *context,
                                     GtkSelectionData *seldata,
                                     guint             info,
                                     guint             time);
static void     kz_tab_label_drag_data_received (GtkWidget *widget,
                                     GdkDragContext *drag_context,
                                     gint x, gint y,
                                     GtkSelectionData *data,
                                     guint info,
                                     guint time);

static void     kz_tab_label_sync_to_profile    (KzTabLabel *kztab);
static void     kz_tab_label_move_page          (KzTabLabel *kztab,
                                     KzTabLabel *dest_kztab);

static void kz_tab_label_set_visited        (KzTabLabel *kztab);

static void     cb_close_button_clicked         (GtkWidget *button,
                                     KzTabLabel *kztab);

static void     cb_profile_changed              (KzProfile *profile,
                                     const gchar *section,
                                     const gchar *key,
                                     const gchar *old_value,
                                     KzTabLabel *kztab);

/* callbacks for embed */
static void cb_title_changed (KzEmbed *embed, KzTabLabel *kztab);
static void cb_net_start     (KzEmbed *embed, KzTabLabel *kztab);
static void cb_net_stop      (KzEmbed *embed, KzTabLabel *kztab);
static void cb_progress      (KzEmbed *embed, KzTabLabel *kztab);
static void cb_destroy       (GtkObject *object,  KzTabLabel *kztab);

static void make_progress_circle (GtkWidget *widget);

static GtkHBoxClass *parent_class = NULL;

enum {
      TARGET_KAZEHAKASE_TAB,
      TARGET_NETSCAPE_URL,
      TARGET_TEXT_URI_LIST,
      TARGET_TEXT_PLAIN,
      TARGET_STRING
};

static GtkTargetEntry url_drag_types [] = 
{
        { "_KAZEHAKASE_TAB", 0, TARGET_KAZEHAKASE_TAB},
        { "_NETSCAPE_URL",   0, TARGET_NETSCAPE_URL},
      { "text/uri-list",   0, TARGET_TEXT_URI_LIST},
      { "text/plain",      0, TARGET_TEXT_PLAIN},
      { "STRING",          0, TARGET_STRING}
};
static guint n_url_drag_types = G_N_ELEMENTS (url_drag_types);

static GdkColor red = { 0, 0xffff, 0x0000, 0x0000 };

KZ_OBJECT_GET_TYPE(kz_tab_label, "KzTabLabel", KzTabLabel,
               kz_tab_label_class_init, kz_tab_label_init,
               GTK_TYPE_HBOX)
KZ_OBJECT_FINALIZE (kz_tab_label, KzTabLabel)

static void
kz_tab_label_class_init (KzTabLabelClass *klass)
{
      GObjectClass *gobject_class;
      GtkWidgetClass *widget_class;

      parent_class = g_type_class_peek_parent (klass);

      gobject_class = (GObjectClass *) klass;
      widget_class  = (GtkWidgetClass *) klass;

      /* GtkObject signals */
      gobject_class->constructor  = kz_tab_label_constructor;
      gobject_class->dispose      = kz_tab_label_dispose;
      gobject_class->finalize     = kz_tab_label_finalize;
      gobject_class->set_property = kz_tab_label_set_property;
      gobject_class->get_property = kz_tab_label_get_property;

      /* GtkWidget signales */
      widget_class->realize              = kz_tab_label_realize;
#if 0
      widget_class->unrealize            = kz_tab_label_unrealize;
#endif
      widget_class->button_press_event   = kz_tab_label_button_press;
      widget_class->scroll_event         = kz_tab_label_scroll_event;
      widget_class->motion_notify_event  = kz_tab_label_motion_notify;
      widget_class->button_release_event = kz_tab_label_button_release;
      widget_class->drag_motion          = kz_tab_label_drag_motion;
      widget_class->drag_data_get        = kz_tab_label_drag_data_get;
      widget_class->drag_data_received   = kz_tab_label_drag_data_received;

      g_object_class_install_property
            (gobject_class,
             PROP_KZ_WINDOW,
             g_param_spec_object ("kz-window",
                              _("KzWindow"),
                              _("The parent kazehakase window"),
                              KZ_TYPE_WINDOW,
                              G_PARAM_READWRITE |
                              G_PARAM_CONSTRUCT_ONLY));

      g_object_class_install_property
            (gobject_class,
             PROP_KZ_EMBED,
             g_param_spec_object ("kz-embed",
                              _("KzEmbed"),
                              _("The KzEmbed object to observe"),
                              KZ_TYPE_EMBED,
                              G_PARAM_READWRITE |
                              G_PARAM_CONSTRUCT_ONLY));
}

static void
kz_tab_label_init (KzTabLabel *kztab)
{
      GtkWidget *close_image, *hbox;
      GtkRcStyle *style;
      GtkRequisition size;
      gint width, height;

      kztab->kz           = NULL;
      kztab->kzembed      = NULL;
      kztab->state        = KZ_TAB_LABEL_STATE_NORMAL;
      kztab->favicon      = gtk_image_new();
      kztab->eventbox     = kz_input_event_box_new();
      kztab->label        = gtk_label_new(NULL);
      kztab->close_button = gtk_button_new();
      kztab->lock_button  = gtk_image_new_from_stock(KZ_STOCK_ANCHOR,
                                           GTK_ICON_SIZE_MENU);
      kztab->tooltips     = gtk_tooltips_new();

      kztab->priv = g_new0(KzTabLabelPriv, 1);
      kztab->priv->width             = 80;
      kztab->priv->start_x           = 0;
      kztab->priv->start_y           = 0;
      kztab->priv->moved             = FALSE;
      kztab->priv->lock              = FALSE;
      kztab->priv->auto_refresh      = FALSE;
      kztab->priv->auto_refresh_id   = 0;
      kztab->priv->favicon_signal    = 0;
      
      kztab->favicon_pixbuf   = NULL;
      kztab->circle           = NULL;
      kztab->mask             = NULL;

      kztab->history    = kz_bookmark_pure_folder_new();
      kz_bookmark_set_title(kztab->history, _("Tab"));

      hbox = gtk_hbox_new(FALSE, 0);
      gtk_container_add(GTK_CONTAINER(kztab->eventbox), hbox);
      gtk_widget_show(hbox);
      /* 
       * input only event box 
       * this widget have a effect widget background display correctly.
       * See http://bugzilla.gnome.org/show_bug.cgi?id=103206
       */
      gtk_container_add (GTK_CONTAINER(kztab), kztab->eventbox);
      gtk_widget_show(kztab->eventbox);

      /* label */
      gtk_widget_set_size_request(kztab->label, -1, -1);
      gtk_widget_show (kztab->label);

      /* favicon */
      gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &width, &height);
      gtk_widget_set_size_request(kztab->favicon, width, height);

      /* close button */
      gtk_button_set_relief(GTK_BUTTON(kztab->close_button), GTK_RELIEF_NONE);
      g_signal_connect(kztab->close_button, "clicked", 
                   G_CALLBACK(cb_close_button_clicked), kztab);

      close_image = gtk_image_new_from_stock(GTK_STOCK_CLOSE,
                                     GTK_ICON_SIZE_MENU);
      gtk_widget_size_request(close_image, &size);
      gtk_widget_set_size_request(kztab->close_button,
                            size.width, size.height);
      gtk_container_add(GTK_CONTAINER(kztab->close_button), close_image);
      gtk_widget_show(close_image);

      style = gtk_rc_style_new ();
      style->xthickness = style->ythickness = 0;
      gtk_widget_modify_style (kztab->close_button, style);
      gtk_widget_modify_style (kztab->lock_button, style);
      gtk_rc_style_unref (style),

      gtk_box_pack_start(GTK_BOX(hbox), kztab->favicon,
                     FALSE, FALSE, 0);
      gtk_box_pack_start(GTK_BOX(hbox), kztab->label,
                     TRUE, TRUE, 0);
      /* 
       * close button (and other widget want to accept event signals)
       * must be outside the eel-input-event-box
       */ 
      gtk_box_pack_start(GTK_BOX(kztab), kztab->close_button,
                     FALSE, FALSE, 0);
      gtk_box_pack_start(GTK_BOX(kztab), kztab->lock_button,
                     FALSE, FALSE, 0);

      gtk_widget_show (kztab->close_button);

      gtk_drag_source_set(GTK_WIDGET(kztab),
                      GDK_BUTTON1_MASK |
                      GDK_BUTTON2_MASK |
                      GDK_BUTTON3_MASK,
                      url_drag_types, n_url_drag_types,
                      GDK_ACTION_ASK  | GDK_ACTION_COPY
                      | GDK_ACTION_MOVE | GDK_ACTION_LINK);
      gtk_drag_dest_set(GTK_WIDGET(kztab), 
                    GTK_DEST_DEFAULT_HIGHLIGHT |
                    GTK_DEST_DEFAULT_MOTION | 
                    GTK_DEST_DEFAULT_DROP,
                          url_drag_types,n_url_drag_types,
                    GDK_ACTION_MOVE);

      g_signal_connect(kz_global_profile, "changed::Tab",
                   G_CALLBACK(cb_profile_changed), kztab);
      kz_tab_label_sync_to_profile(kztab);
      kz_tab_label_set_text(kztab, NULL);
}


static GObject*
kz_tab_label_constructor (GType                  type,
                    guint                  n_props,
                    GObjectConstructParam *props)
{
      KzTabLabel *kztab;
      GObject *object;
      GObjectClass *klass = G_OBJECT_CLASS(parent_class);
      gchar *title;

      object = klass->constructor(type, n_props, props);

      kztab = KZ_TAB_LABEL(object);

      /* set signals */
      g_signal_connect(kztab->kzembed, "kz-title",
                   G_CALLBACK(cb_title_changed), kztab);
      g_signal_connect(kztab->kzembed, "kz-net-start",
                   G_CALLBACK(cb_net_start), kztab);
      g_signal_connect(kztab->kzembed, "kz-net-stop",
                   G_CALLBACK(cb_net_stop), kztab);
      g_signal_connect(kztab->kzembed, "kz-progress",
                   G_CALLBACK(cb_progress), kztab);
      g_signal_connect(kztab->kzembed, "destroy",
                   G_CALLBACK(cb_destroy), kztab);

      /* set label text */
      title = kz_embed_ensure_title(kztab->kzembed);
      kz_tab_label_set_text(kztab, title);
      g_free(title);

      return object;
}


static void
kz_tab_label_dispose (GObject *object)
{
      KzTabLabel *kztab;

      kztab = KZ_TAB_LABEL(object);

      g_signal_handlers_disconnect_by_func(kz_global_profile,
                                   G_CALLBACK(cb_profile_changed),
                                   kztab);
      if (kztab->kzembed)
      {
      
            g_signal_handlers_disconnect_by_func(kztab->kzembed,
                                         cb_net_start, kztab);
            g_signal_handlers_disconnect_by_func(kztab->kzembed,
                                         cb_net_stop, kztab);
            g_signal_handlers_disconnect_by_func(kztab->kzembed,
                                         cb_title_changed, kztab);
            g_signal_handlers_disconnect_by_func(kztab->kzembed,
                                         cb_progress, kztab);
            g_signal_handlers_disconnect_by_func(kztab->kzembed,
                                         cb_destroy, kztab);
            g_object_unref(kztab->kzembed);
            kztab->kzembed = NULL;
      }


      /* if connected signal exists, disconnect it. */
      if (kztab->priv->favicon_signal)
      {
            g_signal_handler_disconnect(kztab->kz->kzfav,
                                  kztab->priv->favicon_signal);
            kztab->priv->favicon_signal = 0;
      }

      if (kztab->history)
      {
            gboolean save_session = FALSE;
            
            kz_window_append_closed_tab(kztab->kz, kztab->history);
      
            kz_bookmark_remove(kztab->kz->tabs, kztab->history);
            g_object_unref(kztab->history);
            kztab->history = NULL;
            
            KZ_CONF_GET("Session", "save", save_session, BOOL);
            if (save_session && !kztab->kz->is_closing_all)
                  kz_bookmark_file_save(KZ_BOOKMARK_FILE(kz_bookmarks->current_session));
      }

      if (kztab->kz)
      {
            g_object_unref(kztab->kz);
            kztab->kz = NULL;
      }

      if (kztab->tooltips)
      {
            gtk_object_sink(GTK_OBJECT(kztab->tooltips));
            kztab->tooltips = NULL;
      }
      
      if (kztab->favicon_pixbuf)
      {
            g_object_unref(kztab->favicon_pixbuf);
            kztab->favicon_pixbuf = NULL;
      }
      if (kztab->circle)
      {
            g_object_unref(kztab->circle);
            kztab->circle = NULL;
      }
      if (kztab->mask)
      {
            g_object_unref(kztab->mask);
            kztab->mask = NULL;
      }

      if (G_OBJECT_CLASS (parent_class)->dispose)
            G_OBJECT_CLASS (parent_class)->dispose(object);
}


static void
kz_tab_label_set_property (GObject         *object,
                     guint            prop_id,
                     const GValue    *value,
                     GParamSpec      *pspec)
{
      KzTabLabel *tablabel = KZ_TAB_LABEL(object);
  
      switch (prop_id)
      {
      case PROP_KZ_WINDOW:
            tablabel->kz = g_object_ref(g_value_get_object(value));
            break;
      case PROP_KZ_EMBED:
            tablabel->kzembed = g_object_ref(g_value_get_object(value));
            break;
      default:
            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
            break;
      }
}


static void
kz_tab_label_get_property (GObject         *object,
                     guint            prop_id,
                     GValue          *value,
                     GParamSpec      *pspec)
{
      KzTabLabel *tablabel = KZ_TAB_LABEL(object);

      switch (prop_id)
      {
      case PROP_KZ_WINDOW:
            g_value_set_object(value, tablabel->kz);
            break;
      case PROP_KZ_EMBED:
            g_value_set_object(value, tablabel->kzembed);
            break;
      default:
            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
            break;
      }
}


GtkWidget *
kz_tab_label_new (KzWindow *kz, KzEmbed *kzembed)
{
      KzTabLabel *kztab;

      g_return_val_if_fail(KZ_IS_WINDOW(kz), NULL);
      g_return_val_if_fail(KZ_IS_EMBED(kzembed), NULL);

      kztab = g_object_new(KZ_TYPE_TAB_LABEL,
                       "kz-window", kz,
                       "kz-embed",  kzembed,
                       NULL);

      return GTK_WIDGET(kztab);
}


void
kz_tab_label_set_text(KzTabLabel *kztab, const gchar *text)
{
      gchar *escaped, *markup;
      g_return_if_fail(KZ_IS_TAB_LABEL(kztab));

      if (!text || !*text) text = _("No title");
      
      escaped = g_markup_escape_text(text, strlen(text));
      markup = g_strdup_printf("<span foreground=\"%s\">%s</span>",
                         label_color[kztab->state],
                         escaped);

      gtk_label_set_markup(GTK_LABEL(kztab->label), markup);
      gtk_tooltips_set_tip(kztab->tooltips, GTK_WIDGET(kztab->eventbox),
                       text, NULL);
      g_free(markup);
      g_free(escaped);
}

void
kz_tab_label_set_state (KzTabLabel *kztab,
                  KzTabLabelState state)
{
      gchar *title;
      
      g_return_if_fail(KZ_IS_TAB_LABEL(kztab));

      if (!GTK_WIDGET_REALIZED(kztab)) return;

      kztab->state = state;
      if (state == KZ_TAB_LABEL_STATE_NORMAL)
      {
            kz_tab_label_set_visited(kztab);
      }
      
      title = kz_embed_ensure_title(kztab->kzembed);
      kz_tab_label_set_text(kztab, title);
      g_free(title);
}

KzTabLabelState
kz_tab_label_get_state (KzTabLabel *kztab)
{
      g_return_val_if_fail(KZ_IS_TAB_LABEL(kztab), KZ_TAB_LABEL_STATE_NORMAL);
      return kztab->state;
}

void
kz_tab_label_set_width (KzTabLabel *kztab, gint width)
{
      g_return_if_fail(KZ_IS_TAB_LABEL(kztab));

      gtk_widget_set_size_request(GTK_WIDGET(kztab), width, -1);
      if (width < 0)
      {
            gtk_widget_set_size_request(kztab->label, -1, -1);
            gtk_widget_queue_resize(GTK_WIDGET(kztab));
            gtk_widget_queue_resize(kztab->label);
      }
      kztab->priv->width = width;
}

void
kz_tab_label_set_show_close_button (KzTabLabel *kztab, gboolean show)
{
      g_return_if_fail(KZ_IS_TAB_LABEL(kztab));

      if (show)
            gtk_widget_show(kztab->close_button);
      else
            gtk_widget_hide(kztab->close_button);
}


void
kz_tab_label_set_show_lock_button (KzTabLabel *kztab, gboolean show)
{
      g_return_if_fail(KZ_IS_TAB_LABEL(kztab));

      if (show)
            gtk_widget_show(kztab->lock_button);
      else
            gtk_widget_hide(kztab->lock_button);
}


void
kz_tab_label_set_show_favicon (KzTabLabel *kztab, gboolean show)
{
      g_return_if_fail(KZ_IS_TAB_LABEL(kztab));

      if (show && kztab->favicon_pixbuf)
            gtk_widget_show(kztab->favicon);
      else
            gtk_widget_hide(kztab->favicon);
}


static void
kz_tab_label_realize (GtkWidget *widget)
{
      KzTabLabel *kztab = KZ_TAB_LABEL(widget);

      if (GTK_WIDGET_CLASS (parent_class)->realize)
            GTK_WIDGET_CLASS (parent_class)->realize(widget);

      widget->window = gtk_widget_get_parent_window (widget);
      g_object_ref (widget->window);

      make_progress_circle(widget);

      if (kz_embed_is_loading(kztab->kzembed))
            kz_tab_label_set_state (kztab, KZ_TAB_LABEL_STATE_LOADING);
}
#if 0
static void
kz_tab_label_unrealize (GtkWidget *widget)
{
      if (GTK_WIDGET_CLASS (parent_class)->unrealize)
            return GTK_WIDGET_CLASS (parent_class)->unrealize(widget);
}
#endif
static gboolean
kz_tab_label_button_press (GtkWidget *widget, GdkEventButton *event)
{
      KzTabLabel *kztab = KZ_TAB_LABEL(widget);

      kztab->priv->start_x = event->x;
      kztab->priv->start_y = event->y;
      kztab->priv->moved = FALSE;

#if 0
      if (event->button == 3)
      {
            kz_actions_tab_popup_menu_modal(kztab,
                                    event->button,
                                    event->time);
      }
#endif
      if (event->button == 2)
      {
            kz_window_close_tab(kztab->kz, GTK_WIDGET(kztab->kzembed));
      }
      if (event->type == GDK_2BUTTON_PRESS)
      {
            kz_embed_reload(kztab->kzembed,
                        (event->state & GDK_SHIFT_MASK) ?
                        KZ_EMBED_RELOAD_BYPASS_PROXY_AND_CACHE : 
                        KZ_EMBED_RELOAD_NORMAL);
      }
      if (GTK_WIDGET_CLASS(parent_class)->button_press_event)
            GTK_WIDGET_CLASS(parent_class)->button_press_event(widget, event);
      return FALSE;
}

static gboolean
kz_tab_label_motion_notify (GtkWidget *widget, GdkEventMotion *event)
{
      KzTabLabel *kztab = KZ_TAB_LABEL(widget);

      if (abs(event->x - kztab->priv->start_x) > 2 ||
          abs(event->y - kztab->priv->start_y) > 2)
      {
            kztab->priv->moved = TRUE;
      }

      if (GTK_WIDGET_CLASS(parent_class)->motion_notify_event)
            return GTK_WIDGET_CLASS(parent_class)->motion_notify_event(widget, event);
      return FALSE;
}

static gboolean
kz_tab_label_button_release (GtkWidget *widget, GdkEventButton *event)
{
      KzTabLabel *kztab = KZ_TAB_LABEL(widget);

      if (event->button == 2 && !kztab->priv->moved)
      {
            /* Load URL in clipboard */
            /* return TRUE; */
      }
      else if (event->button == 3 && !kztab->priv->moved)
      {
            kz_actions_tab_popup_menu_modal(kztab,
                                    event->button,
                                    event->time);
            return TRUE;
      }

      kztab->priv->start_x = 0;
      kztab->priv->start_y = 0;
      kztab->priv->moved = FALSE;

      if (GTK_WIDGET_CLASS(parent_class)->button_release_event)
            return GTK_WIDGET_CLASS(parent_class)->button_release_event(widget, event);
      return FALSE;
}


static gboolean
kz_tab_label_scroll_event (GtkWidget *widget, GdkEventScroll *event)
{
      KzTabLabel *kztab;
      GtkNotebook *notebook;
      gboolean retval = FALSE;

      kztab = KZ_TAB_LABEL(widget);
      notebook = GTK_NOTEBOOK(kztab->kz->notebook);

      switch (event->direction) {
      case GDK_SCROLL_UP:
      case GDK_SCROLL_LEFT:
            gtk_notebook_prev_page(notebook);
            retval = TRUE;
            break;
      case GDK_SCROLL_DOWN:
      case GDK_SCROLL_RIGHT:
            gtk_notebook_next_page(notebook);
            retval = TRUE;
            break;
      default:
            g_warning ("Invalid scroll direction!");
            break;
      }

      if (GTK_WIDGET_CLASS(parent_class)->scroll_event)
            return GTK_WIDGET_CLASS(parent_class)->scroll_event(widget, event)
                  || retval;
      return retval;
}


static gboolean
kz_tab_label_drag_motion (GtkWidget *widget,
                    GdkDragContext *drag_context,
                    gint x, gint y,
                    guint time)
{
      KzTabLabel *kztab;
      KzEmbed *current_kzembed;
      gint page_num;

      kztab = KZ_TAB_LABEL(widget);

      g_return_val_if_fail (KZ_IS_EMBED(kztab->kzembed), FALSE);

      current_kzembed = KZ_EMBED(KZ_WINDOW_CURRENT_PAGE(kztab->kz));

      if (KZ_EMBED(kztab->kzembed) == current_kzembed)
            return FALSE;

      page_num = gtk_notebook_page_num(GTK_NOTEBOOK(kztab->kz->notebook),
                               GTK_WIDGET(kztab->kzembed));
      gtk_notebook_set_current_page(GTK_NOTEBOOK(kztab->kz->notebook),
                              page_num);
      return FALSE;
}

static void
kz_tab_label_drag_data_get (GtkWidget        *widget,
                      GdkDragContext   *context,
                      GtkSelectionData *data,
                      guint             info,
                      guint             time)
{
      KzTabLabel *kztab;
      const gchar *uri, *title;

      kztab = KZ_TAB_LABEL(widget);

      g_return_if_fail (KZ_IS_EMBED(kztab->kzembed));

      uri   = kz_embed_get_location(kztab->kzembed);
      title = kz_embed_get_title(kztab->kzembed);

      if (!uri || !*uri) return;

      switch (info)
      {
      case TARGET_KAZEHAKASE_TAB:
            gtk_selection_data_set(data, data->target,
                               8, "dummy", strlen("dummy"));
            break;
      case TARGET_NETSCAPE_URL:
      {
            gchar *str;
            if (title && *title)
            {
                  gchar *title_locale;
                  gsize bytes_read, bytes_written;
                  GError *error = NULL;

                  title_locale = g_locale_from_utf8(title, -1,
                                            &bytes_read,
                                            &bytes_written,
                                            &error);
                  if (error)
                  {
                        g_warning("kz_tab_label_drag_data_get(): %s",
                               error->message);
                        g_error_free(error);
                  }
                  if (title_locale && *title_locale)
                  {
                        str = g_strconcat(uri, "\n", title_locale,
                                      NULL);
                        g_free(title_locale);
                  }
                  else
                  {
                        str = g_strdup (uri);
                  }
            }
            else
            {
                  str = g_strdup (uri);
            }
            gtk_selection_data_set(data, data->target,
                               8, str, strlen(str));
            g_free(str);
            break;
      }
      case TARGET_TEXT_URI_LIST:
      case TARGET_TEXT_PLAIN:
      case TARGET_STRING:
            gtk_selection_data_set(data, data->target,
                               8, uri, strlen(uri));
            break;
      default:
            break;
      }
}

static void
kz_tab_label_drag_data_received (GtkWidget *widget,
                         GdkDragContext *drag_context,
                         gint x, gint y,
                         GtkSelectionData *data,
                         guint info,
                         guint time)
{
      KzTabLabel *kztab;

      kztab = KZ_TAB_LABEL(widget);

      g_return_if_fail (KZ_IS_EMBED(kztab->kzembed));

      switch (info)
      {
      case TARGET_KAZEHAKASE_TAB:
      {
            GtkWidget *src_widget = gtk_drag_get_source_widget(drag_context);
            KzTabLabel *src_kztab;

            if (!KZ_IS_TAB_LABEL(src_widget)) return;
            src_kztab = KZ_TAB_LABEL(src_widget);

            kz_tab_label_move_page(src_kztab, kztab);
            return;
      }

      case TARGET_NETSCAPE_URL:
      case TARGET_TEXT_URI_LIST:
      case TARGET_TEXT_PLAIN:
      case TARGET_STRING:
      {
            gchar **strings;

            if (data->length < 0) return;

            strings = g_strsplit(data->data, "\n", 2);
            kz_embed_load_url(kztab->kzembed,
                              strings[0]);
            g_strfreev(strings);
            break;
      }

      default:
            break;
      }
}

static void
kz_tab_label_sync_to_profile (KzTabLabel *kztab)
{
      gint width = 80;
      gboolean fix = TRUE;
      gboolean show_close = TRUE;
      gboolean show_favicon = TRUE;
      gchar *color;

      /* width */
      KZ_CONF_GET("Tab", "fix_width", fix, BOOL);
      KZ_CONF_GET("Tab", "fixed_width", width, INT);

      if (fix)
            kz_tab_label_set_width(kztab, width);
      else
            kz_tab_label_set_width(kztab, -1);

      /* close button */
      KZ_CONF_GET("Tab", "show_close_button", show_close, BOOL);
      kz_tab_label_set_show_close_button(kztab, show_close && !kztab->priv->lock);

      /* lock button */
      kz_tab_label_set_show_lock_button(kztab, kztab->priv->lock);

      /* favicon */
      KZ_CONF_GET("Tab", "show_favicon", show_favicon, BOOL);
      kz_tab_label_set_show_favicon(kztab, show_favicon);

      /* label color */
      color = KZ_CONF_GET_STR("Tab" , "normal_color");
      if (!color)
            color = g_strdup("#000000");

      if (label_color[KZ_TAB_LABEL_STATE_NORMAL])
            g_free(label_color[KZ_TAB_LABEL_STATE_NORMAL]);
      label_color[KZ_TAB_LABEL_STATE_NORMAL] = g_strdup(color);
      g_free(color);

      color = KZ_CONF_GET_STR("Tab" , "loading_color");
      if (!color)
            color = g_strdup("#ff0000");
      if (label_color[KZ_TAB_LABEL_STATE_LOADING])
            g_free(label_color[KZ_TAB_LABEL_STATE_LOADING]);
      label_color[KZ_TAB_LABEL_STATE_LOADING] = g_strdup(color);
      g_free(color);

      color = KZ_CONF_GET_STR("Tab" , "loaded_color");
      if (!color)
            color = g_strdup("#22aa44");
      if (label_color[KZ_TAB_LABEL_STATE_LOADED])
            g_free(label_color[KZ_TAB_LABEL_STATE_LOADED]);
      label_color[KZ_TAB_LABEL_STATE_LOADED] = g_strdup(color);
      g_free(color);
}

/* move kztab to dest_kztab's position */
static void
kz_tab_label_move_page(KzTabLabel *kztab, KzTabLabel *dest_kztab)
{
      GtkWidget *src_page;
      GtkNotebook *notebook;
      gint dest_pos;

      g_return_if_fail(dest_kztab->kz && dest_kztab->kzembed);
      g_return_if_fail(kztab->kz && kztab->kzembed);

      notebook = GTK_NOTEBOOK(dest_kztab->kz->notebook);
      dest_pos = gtk_notebook_page_num(notebook,
                               GTK_WIDGET(dest_kztab->kzembed));

      src_page = GTK_WIDGET(kztab->kzembed);
      if (dest_kztab->kz != kztab->kz)
            kz_window_move_tab(dest_kztab->kz, src_page);
      
      kz_window_reorder_tab(dest_kztab->kz, src_page, dest_pos);
      kz_actions_set_sensitive
            (kztab->kz, KZ_EMBED(KZ_WINDOW_CURRENT_PAGE(kztab->kz)));

      if (dest_kztab->kz != kztab->kz)
            gtk_widget_destroy(GTK_WIDGET(kztab));
}


static void
make_progress_circle(GtkWidget *widget)
{
      GdkGC *gc;
      gint width, height;
      GdkColormap *colormap;
      KzTabLabel *kztab = KZ_TAB_LABEL(widget);

      gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &width, &height);
      kztab->circle = gdk_pixmap_new(widget->window,
                               width, height, -1);
      kztab->mask = gdk_pixmap_new(widget->window,
                             width, height, 1);
      gc = gdk_gc_new(kztab->mask);
      gdk_draw_rectangle(kztab->mask,
                     gc,
                     TRUE,
                     0, 0,
                     width, height);
      gdk_gc_set_function(gc, GDK_INVERT);
      gdk_draw_arc(kztab->mask,
                 gc,
                 TRUE,
                 0, 0,
                 width, height,
                 90 * 64, 360 * 64);
      g_object_unref(gc);

      gc = gdk_gc_new(kztab->circle);
      colormap = gdk_gc_get_colormap(gc);
      gdk_rgb_find_color(colormap, &red);
      gdk_gc_set_foreground(gc, &red);    
      gdk_draw_rectangle(kztab->circle,
                     widget->style->white_gc, 
                     TRUE,
                     0, 0,
                     width, height);
      gdk_draw_arc(kztab->circle,
                 gc, 
                 TRUE,
                 0, 0,
                 width, height,
                 90 * 64, 360 * 64);
      g_object_unref(colormap);
      g_object_unref(gc);
}

            
static void
cb_close_button_clicked (GtkWidget *button, KzTabLabel *kztab)
{
      g_return_if_fail(KZ_IS_TAB_LABEL(kztab));
      kz_window_close_tab(kztab->kz, GTK_WIDGET(kztab->kzembed));
}

static void
cb_profile_changed (KzProfile *profile,
                const gchar *section,
                const gchar *key,
                const gchar *old_value,
                KzTabLabel *kztab)
{
      g_return_if_fail(KZ_IS_TAB_LABEL(kztab));

      kz_tab_label_sync_to_profile (kztab);
}

/* callbacks for embed */

static void
cb_title_changed (KzEmbed *embed, KzTabLabel *kztab)
{
      gchar *title;

      g_return_if_fail(KZ_IS_TAB_LABEL(kztab));

      title = kz_embed_ensure_title(kztab->kzembed);
      kz_tab_label_set_text(kztab, title);
      g_free(title);
}

static void
cb_net_start (KzEmbed *embed, KzTabLabel *kztab)
{
      g_return_if_fail(KZ_IS_TAB_LABEL(kztab));

      kz_tab_label_set_state(kztab, KZ_TAB_LABEL_STATE_LOADING);

      if (kztab->favicon_pixbuf)
      {
            gtk_image_set_from_pixbuf(GTK_IMAGE(kztab->favicon), NULL);
            g_object_unref(kztab->favicon_pixbuf);
            kztab->favicon_pixbuf = NULL;
      }
      /* show favicon widget for progress maru. */
      gtk_widget_show(kztab->favicon);
}

static void
cb_net_stop (KzEmbed *embed, KzTabLabel *kztab)
{
      GtkNotebook *note;
      gboolean show_favicon;
      gboolean save_session = FALSE;

      g_return_if_fail(KZ_IS_TAB_LABEL(kztab));

      kz_embed_get_history(KZ_EMBED(embed), 
                       kztab->history);

      /* save session */
      KZ_CONF_GET("Session", "save", save_session, BOOL);
      if (save_session && !kztab->kz->is_closing_all)
            kz_bookmark_file_save(KZ_BOOKMARK_FILE(kz_bookmarks->current_session));

      note = GTK_NOTEBOOK(kztab->kz->notebook);
      if(gtk_notebook_page_num(note, GTK_WIDGET(embed)) ==
         gtk_notebook_get_current_page(note))
      {
            kz_tab_label_set_state(kztab, KZ_TAB_LABEL_STATE_NORMAL);
      }
      else
      {
            KzBookmark *bookmark = NULL;
            guint cur, last_modified, last_visited = 0;
            GList *children;
      
            cur = kz_bookmark_get_current(kztab->history);
            children = kz_bookmark_get_children(kztab->history);
            bookmark = KZ_BOOKMARK(g_list_nth_data(children, cur));
            g_list_free(children);

            if (bookmark)
                  last_visited = kz_bookmark_get_last_visited(bookmark);
            last_modified = kz_embed_get_last_modified(embed);

            if (last_modified != 0 && last_visited > last_modified)
                  kz_tab_label_set_state(kztab, KZ_TAB_LABEL_STATE_NORMAL);
            else
                  kz_tab_label_set_state(kztab, KZ_TAB_LABEL_STATE_LOADED);
      }

      KZ_CONF_GET("Tab", "show_favicon", show_favicon, BOOL);

      if (show_favicon)
      {
            const gchar *uri;
            uri = kz_embed_get_location(KZ_EMBED(kztab->kzembed));
            kztab->favicon_pixbuf = kz_favicon_get_pixbuf(kztab->kz->kzfav, uri,
                                                GTK_ICON_SIZE_MENU);
            gtk_image_set_from_pixbuf(GTK_IMAGE(kztab->favicon),
                                kztab->favicon_pixbuf);
      }

      kz_tab_label_set_show_favicon(kztab, show_favicon);
}



static void
cb_destroy (GtkObject *object, KzTabLabel *kztab)
{
      g_return_if_fail(KZ_IS_TAB_LABEL(kztab));
      g_object_unref(kztab->kzembed);
      kztab->kzembed = NULL;
}


static void
cb_progress (KzEmbed *embed, KzTabLabel *kztab)
{
      gdouble progress;
      GtkWidget *widget;             
      GdkGC *gc;

      g_return_if_fail(KZ_IS_TAB_LABEL(kztab));

      widget = GTK_WIDGET(kztab);
      progress = kz_embed_get_progress(KZ_EMBED(embed));

      if(GTK_WIDGET_REALIZED(widget))
      {
            GdkBitmap *mask;
            gint width, height;
            gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &width, &height);

            mask = gdk_pixmap_new(widget->window,
                              width, height, 1);
            gc = gdk_gc_new(mask);
            gdk_draw_rectangle(mask,
                           gc,
                           TRUE,
                           0, 0,
                           width, height);
            gdk_gc_set_function(gc, GDK_INVERT);
            gdk_draw_rectangle(mask,
                           gc,
                           TRUE,
                           0, 0,
                           width, height);
            gdk_gc_set_function(gc, GDK_COPY);
            gdk_draw_arc(mask,
                       gc,
                       TRUE,
                       0, 0,
                       width, height,
                       90 * 64, 360 * 64 * progress);
            gdk_gc_set_function(gc, GDK_AND);
            gdk_draw_drawable(mask,
                          gc,
                          kztab->mask,
                          0, 0,
                          0, 0,
                          -1, -1);
            gtk_image_set_from_pixmap(GTK_IMAGE(kztab->favicon), 
                                kztab->circle,
                                mask);
            g_object_unref(mask);
            g_object_unref(gc);
      }
}


gboolean
kz_tab_label_get_lock (KzTabLabel *kztab)
{
      g_return_val_if_fail(KZ_IS_TAB_LABEL(kztab), FALSE);
      return kztab->priv->lock;
}


void
kz_tab_label_set_lock (KzTabLabel *kztab, gboolean lock)
{
      gboolean save = FALSE;

      g_return_if_fail(KZ_IS_TAB_LABEL(kztab));
      kztab->priv->lock = lock;
      kz_embed_set_lock(kztab->kzembed, lock);
      kz_actions_set_sensitive(kztab->kz, kztab->kzembed);
      
      kz_bookmark_set_lock(kztab->history, lock);
      KZ_CONF_GET("Session", "save", save, BOOL);
      if (save)
            kz_bookmark_file_save(KZ_BOOKMARK_FILE(kz_bookmarks->current_session));
      kz_tab_label_sync_to_profile(kztab);
}

static gboolean
cb_auto_refresh(KzTabLabel* kztab)
{
      gint auto_refresh_interval_sec = DEFAULT_AUTO_REFRESH_INTERVAL_SEC;

      g_return_val_if_fail(KZ_IS_TAB_LABEL(kztab), TRUE);

      KZ_CONF_GET("Tab", "auto_refresh_interval_sec", auto_refresh_interval_sec, INT);

      kz_embed_reload(KZ_EMBED(kztab->kzembed),
                  KZ_EMBED_RELOAD_NORMAL);

      if (kztab->priv->auto_refresh_id != 0)
            g_source_remove(kztab->priv->auto_refresh_id);

      kztab->priv->auto_refresh_id
            = g_timeout_add(auto_refresh_interval_sec * 1000,
                        (GSourceFunc)cb_auto_refresh, kztab);
      return FALSE;
}

gboolean
kz_tab_label_get_auto_refresh (KzTabLabel *kztab)
{
      g_return_val_if_fail(KZ_IS_TAB_LABEL(kztab), FALSE);
      return kztab->priv->auto_refresh;

}
void
kz_tab_label_set_auto_refresh (KzTabLabel *kztab, gboolean auto_refresh)
{
      gboolean save = FALSE;

      g_return_if_fail(KZ_IS_TAB_LABEL(kztab));
      if(auto_refresh)
      {
            gint auto_refresh_interval_sec = DEFAULT_AUTO_REFRESH_INTERVAL_SEC;
            KZ_CONF_GET("Tab", "auto_refresh_interval_sec", auto_refresh_interval_sec, INT);

            if (kztab->priv->auto_refresh_id != 0)
                  g_source_remove(kztab->priv->auto_refresh_id);

            kztab->priv->auto_refresh_id 
                  = g_timeout_add(auto_refresh_interval_sec * 1000,
                              (GSourceFunc)cb_auto_refresh, kztab);
      }
      else
      {
            if (kztab->priv->auto_refresh_id != 0)
            {
                  g_source_remove(kztab->priv->auto_refresh_id);
                  kztab->priv->auto_refresh_id = 0;
            }
      }
      kztab->priv->auto_refresh = auto_refresh;
      kz_actions_set_sensitive(kztab->kz, kztab->kzembed);

      kz_bookmark_set_auto_refresh(kztab->history, auto_refresh);
      KZ_CONF_GET("Session", "save", save, BOOL);
      if (save)
            kz_bookmark_file_save(KZ_BOOKMARK_FILE(kz_bookmarks->current_session));
      kz_tab_label_sync_to_profile(kztab);
}

void
kz_tab_label_set_history (KzTabLabel *kztab, KzBookmark *history)
{     
      GList *children, *node;

      g_return_if_fail(KZ_IS_TAB_LABEL(kztab));
      
      kz_bookmark_remove_all(kztab->history);

      children = kz_bookmark_get_children(history);
      for (node =children; node; node = g_list_next(node))
      {
            KzBookmark *new;
            KzBookmark *child = KZ_BOOKMARK(node->data);

            new = kz_bookmark_new_with_attrs(kz_bookmark_get_title(child),
                                     kz_bookmark_get_link(child),
                                     NULL);
            kz_bookmark_set_last_visited(new, 
                                   kz_bookmark_get_last_visited(child));
            kz_bookmark_append(kztab->history, new);
            g_object_unref(new);
      }
      kz_bookmark_set_current(kztab->history,
                        kz_bookmark_get_current(history));
      
      g_list_free(children);

      kz_embed_set_history(kztab->kzembed, 
                       kztab->history);
}
static void
kz_tab_label_set_visited (KzTabLabel *kztab)
{
      KzBookmark *bookmark = NULL;
      const gchar *uri;
      GTimeVal now;
      guint cur;
      GList *children;
      
      g_get_current_time(&now);

      cur = kz_bookmark_get_current(kztab->history);
      children = kz_bookmark_get_children(kztab->history);
      bookmark = KZ_BOOKMARK(g_list_nth_data(children, cur));
      g_list_free(children);

      if (bookmark)
      {
            gboolean save_session = FALSE;
            kz_bookmark_set_last_visited(bookmark, now.tv_sec);
            /* save session */
            KZ_CONF_GET("Session", "save", save_session, BOOL);
            if (save_session && !kztab->kz->is_closing_all)
                  kz_bookmark_file_save(KZ_BOOKMARK_FILE(kz_bookmarks->current_session));
      }
      /* find the bookmark which has the same uri from the system bookmark */
      uri = kz_embed_get_location(kztab->kzembed);
      bookmark = kz_bookmark_find_bookmark_from_uri(kz_bookmarks->menu,
                                          uri);
      if (bookmark)
            kz_bookmark_set_last_visited(bookmark, now.tv_sec);
}


Generated by  Doxygen 1.6.0   Back to index