Logo Search packages:      
Sourcecode: kazehakase version File versions

kz-location-entry-action.c

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

/*
 *  Copyright (C) 2003 Hiroyuki Ikezoe
 *  Copyright (C) 2003 - 2004 Takuro Ashie
 *  Copyright (C) 2004 Hidetaka Iwai
 *
 *  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-location-entry-action.h"

#include <stdlib.h>
#include <gdk/gdkkeysyms.h>
#include <sys/types.h>
#include <glib/gi18n.h>

#include "kazehakase.h"
#include "utils/utils.h"
#include "gobject-utils.h"
#include "kz-bookmark.h"
#include "kz-smart-bookmark.h"
#include "kz-actions.h"

#define KZ_LOCATION_ENTRY_ACTION_KEY "KzLocationEntryAction::Action"

enum {
      PROP_0,
      PROP_KZ_WINDOW,
      PROP_KZ_BOOKMARK
};

static void kz_location_entry_action_class_init       (KzLocationEntryActionClass *class);
static void kz_location_entry_action_init             (KzLocationEntryAction      *action);
static void kz_location_entry_action_dispose          (GObject *obj);
static void kz_location_entry_action_set_property     (GObject           *object,
                                           guint              prop_id,
                                           const GValue      *value,
                                           GParamSpec        *pspec);
static void kz_location_entry_action_get_property     (GObject           *object,
                                           guint              prop_id,
                                           GValue            *value,
                                           GParamSpec        *pspec);

static void kz_location_entry_action_activate         (GtkAction         *action);
static void kz_location_entry_action_connect_proxy    (GtkAction         *action,
                                           GtkWidget         *proxy);
static void kz_location_entry_action_disconnect_proxy (GtkAction         *action,
                                           GtkWidget         *proxy);

static void     kz_location_entry_action_history_changed (KzHistoryAction *action);
static void     kz_location_entry_action_sync_history    (KzLocationEntryAction *action);
static gboolean cb_entry_key_press                       (GtkWidget *widget,
                                            GdkEventKey *event,
                                            KzLocationEntryAction *action);
static void     cb_entry_populate_popup                (GtkEntry *entry,
                                            GtkMenu *menu,
                                            KzLocationEntryAction *action);

static void     cb_profile_entry_changed     (KzProfile       *profile,
                                     const gchar     *section,
                                     const gchar     *key,
                                     const gchar     *old_value,
                                     GtkEntry        *entry);
static KzHistoryActionClass *parent_class = NULL;


KZ_OBJECT_GET_TYPE(kz_location_entry_action,
               "KzLocationEntryAction",
               KzLocationEntryAction,
               kz_location_entry_action_class_init,
               kz_location_entry_action_init,
               KZ_TYPE_HISTORY_ACTION)


static void
kz_location_entry_action_class_init (KzLocationEntryActionClass *klass)
{
      GObjectClass *object_class;
      GtkActionClass *action_class;
      KzHistoryActionClass *history_class;

      parent_class  = g_type_class_peek_parent(klass);
      object_class  = G_OBJECT_CLASS(klass);
      action_class  = GTK_ACTION_CLASS(klass);
      history_class = KZ_HISTORY_ACTION_CLASS(klass);

      object_class->set_property     = kz_location_entry_action_set_property;
      object_class->get_property     = kz_location_entry_action_get_property;
      object_class->dispose          = kz_location_entry_action_dispose;

      action_class->activate         = kz_location_entry_action_activate;
      action_class->connect_proxy    = kz_location_entry_action_connect_proxy;
      action_class->disconnect_proxy = kz_location_entry_action_disconnect_proxy;

      history_class->history_changed = kz_location_entry_action_history_changed;

      g_object_class_install_property
            (object_class,
             PROP_KZ_WINDOW,
             g_param_spec_object ("kz-window",
                              _("KzWindow"),
                              _("The KzWindow to add a home button"),
                              KZ_TYPE_WINDOW,
                              G_PARAM_READWRITE |
                              G_PARAM_CONSTRUCT_ONLY));
      g_object_class_install_property
            (object_class,
             PROP_KZ_BOOKMARK,
             g_param_spec_object ("kz-bookmark",
                              _("KzBookmark"),
                              _("The Bookmark object"),
                              KZ_TYPE_BOOKMARK,
                              G_PARAM_READWRITE));
}


static void
kz_location_entry_action_init (KzLocationEntryAction *action)
{
      action->kz            = NULL;
      action->bookmark      = NULL;
      action->history       = NULL;
      action->activating    = FALSE;
      action->synchronizing = FALSE;
}


static void
kz_location_entry_action_dispose (GObject *obj)
{
      KzLocationEntryAction *action = KZ_LOCATION_ENTRY_ACTION(obj);

      if (action->kz)
      {
            kz_profile_set_save_each_time(kz_global_profile, FALSE);
            kz_location_entry_action_store_history(action);
            kz_profile_set_save_each_time(kz_global_profile, TRUE);
            g_object_unref(action->kz);
            action->kz = NULL;
      }

      if (action->history)
      {
            g_object_unref(action->history);
            action->history = NULL;
      }

      if (action->bookmark)
      {
            g_object_unref(action->bookmark);
            action->bookmark = NULL;
      }

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


static void
kz_location_entry_action_set_property (GObject         *object,
                               guint            prop_id,
                               const GValue    *value,
                               GParamSpec      *pspec)
{
      KzLocationEntryAction *action = KZ_LOCATION_ENTRY_ACTION(object);
  
      switch (prop_id)
      {
      case PROP_KZ_WINDOW:
            action->kz = g_object_ref(g_value_get_object(value));
            break;
      case PROP_KZ_BOOKMARK:
            if (action->bookmark)
                  g_object_unref(action->bookmark);
            action->bookmark = g_object_ref(g_value_get_object(value));
            break;
      default:
            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
            break;
      }
}


static void
kz_location_entry_action_get_property (GObject         *object,
                               guint            prop_id,
                               GValue          *value,
                               GParamSpec      *pspec)
{
      KzLocationEntryAction *action = KZ_LOCATION_ENTRY_ACTION(object);

      switch (prop_id)
      {
      case PROP_KZ_WINDOW:
            g_value_set_object(value, action->kz);
            break;
      case PROP_KZ_BOOKMARK:
            g_value_set_object(value, action->bookmark);
            break;
      default:
            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
            break;
      }
}


static void
kz_location_entry_action_activate (GtkAction *action)
{
      KzLocationEntryAction *entry_action;
      const gchar *uri;
      gchar *smart_uri;
      gboolean new_tab;
      GdkModifierType state = (GdkModifierType)0;
      gint x, y;
 
      g_return_if_fail(KZ_IS_LOCATION_ENTRY_ACTION(action));
      entry_action = KZ_LOCATION_ENTRY_ACTION(action);

      entry_action->activating = TRUE;
      if (GTK_ACTION_CLASS(parent_class)->activate)
            GTK_ACTION_CLASS(parent_class)->activate(action);
      entry_action->activating = FALSE;


      uri = kz_entry_action_get_text(KZ_ENTRY_ACTION(action));
      smart_uri = kz_smart_bookmark_get_smart_uri(KZ_SMART_BOOKMARK(entry_action->bookmark), uri);

      gdk_window_get_pointer(NULL, &x, &y, &state);
      
      KZ_CONF_GET("Global", "entry_open_in_new_tab", new_tab, BOOL);
      new_tab = (state & GDK_CONTROL_MASK) ? !new_tab: new_tab;

      if (new_tab)
            kz_window_open_new_tab(entry_action->kz, smart_uri);
      else  
            kz_window_load_url(entry_action->kz, smart_uri);
      g_free(smart_uri);
}


static void
kz_location_entry_action_connect_proxy (GtkAction *action, GtkWidget *proxy)
{
      GtkEntry *entry;

      GTK_ACTION_CLASS (parent_class)->connect_proxy (action, proxy);

      entry = kz_entry_action_get_entry_widget(KZ_ENTRY_ACTION(action), proxy);
      if (entry)
      {
            gboolean autocompletion = FALSE;
            KZ_CONF_GET("Global", "use_auto_completion", autocompletion, BOOL);
            if(autocompletion)
                  kz_history_set_completion (KZ_HISTORY_ACTION(action), entry);

            g_object_set_data(G_OBJECT(entry),
                          KZ_LOCATION_ENTRY_ACTION_KEY,
                          action);
            g_signal_connect(entry, "key-press-event",
                         G_CALLBACK(cb_entry_key_press), action);
            g_signal_connect(entry, "populate-popup",
                         G_CALLBACK(cb_entry_populate_popup), action);
            g_signal_connect(kz_global_profile, "changed::Entry",
                         G_CALLBACK(cb_profile_entry_changed), entry);
      }
}


static void
kz_location_entry_action_disconnect_proxy (GtkAction *action, GtkWidget *proxy)
{
      GtkEntry *entry;

      entry = kz_entry_action_get_entry_widget(KZ_ENTRY_ACTION(action), proxy);
      if (entry)
      {
            g_signal_handlers_disconnect_by_func
                  (entry,
                   G_CALLBACK(cb_entry_key_press),
                   action);
            g_signal_handlers_disconnect_by_func
                  (entry,
                   G_CALLBACK(cb_entry_populate_popup),
                   action);
            g_signal_handlers_disconnect_by_func
                  (kz_global_profile,
                   G_CALLBACK(cb_profile_entry_changed),
                   entry);
              g_object_set_data(G_OBJECT(entry),
                          KZ_LOCATION_ENTRY_ACTION_KEY,
                            NULL);
      }

      GTK_ACTION_CLASS (parent_class)->disconnect_proxy (action, proxy);
}


static void
kz_location_entry_action_history_changed (KzHistoryAction *action)
{
      g_return_if_fail(KZ_IS_LOCATION_ENTRY_ACTION(action));

      kz_location_entry_action_sync_history(KZ_LOCATION_ENTRY_ACTION(action));

      if (KZ_HISTORY_ACTION_CLASS(parent_class)->history_changed)
            KZ_HISTORY_ACTION_CLASS(parent_class)->history_changed(action);
}


KzLocationEntryAction *
kz_location_entry_action_new (KzWindow *kz)
{
      KzLocationEntryAction *action;

      action = g_object_new(KZ_TYPE_LOCATION_ENTRY_ACTION,
                        "name",        "LocationEntry",
                        "label",       _("Location Entry"),
                        "tooltip",     NULL,
                        "stock_id",    GTK_STOCK_NEW,
                        "kz-window",   kz,
                        NULL);
      kz_profile_set_save_each_time(kz_global_profile, FALSE);
      kz_location_entry_action_restore_history(action);
      kz_profile_set_save_each_time(kz_global_profile, TRUE);

      return action;
}


void
kz_location_entry_action_store_history (KzLocationEntryAction *action)
{
      GList *list, *node;
      gint i = 0;

      g_return_if_fail(KZ_IS_LOCATION_ENTRY_ACTION(action));

      list = kz_profile_enum_key(kz_global_profile, "LocationEntry", TRUE);
      for (node = list; node; node = g_list_next(node))
      {
            const gchar *key = node->data;

            if (key && *key && key_seems_sequential(key, "history"))
                  kz_profile_delete_key(kz_global_profile,
                                    "LocationEntry", key);
      }
      g_list_free(list);

      list = kz_history_action_get_history(KZ_HISTORY_ACTION(action));
      for (node = list; node; node = g_list_next(node))
      {
            const gchar *uri = node->data;
            gchar key[256];

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

            g_snprintf(key, G_N_ELEMENTS(key), "history%d", i);

            KZ_CONF_SET_STR("LocationEntry", key, uri);
            i++;
      }
      g_list_foreach(list, (GFunc) g_free, NULL);
      g_list_free(list);

}


void
kz_location_entry_action_restore_history (KzLocationEntryAction *action)
{
      GList *list, *node, *history = NULL;
      gint max_history = 32;
      gboolean success;
      gchar *text;

      g_return_if_fail(KZ_IS_LOCATION_ENTRY_ACTION(action));

      if (action->activating) return;

      text = g_strdup(kz_entry_action_get_text(KZ_ENTRY_ACTION(action)));

      list = kz_profile_enum_key(kz_global_profile, "LocationEntry", TRUE);
      for (node = list; node; node = g_list_next(node))
      {
            const gchar *key = node->data;
            gchar *value;

            if (!key_seems_sequential(key, "history")) continue;

            value = KZ_CONF_GET_STR("LocationEntry", key);
            if (value && *value)
                  history = g_list_append(history, value);
      }

      success = KZ_CONF_GET("LocationEntry", "max_history",
                        max_history, INT);
      if (success)
            kz_history_action_set_max_history
                  (KZ_HISTORY_ACTION(action), max_history);

      if (history)
      {
            kz_history_action_set_history(KZ_HISTORY_ACTION(action),
                                    history);
      }

      g_list_foreach(history, (GFunc) g_free, NULL);
      g_list_free(history);

      kz_entry_action_set_text(KZ_ENTRY_ACTION(action), text);
      g_free(text);
}


static void
kz_location_entry_action_sync_history (KzLocationEntryAction *action)
{
      GList *list, *node;

      g_return_if_fail(KZ_IS_LOCATION_ENTRY_ACTION(action));

      if (action->synchronizing) return;
      action->synchronizing = TRUE;

      kz_location_entry_action_store_history
            (KZ_LOCATION_ENTRY_ACTION(action));

      list = kz_window_get_window_list();
      for (node = list; node; node = g_list_next(node))
      {
            KzWindow *tmpkz = node->data;
            GtkAction *act;

            if (tmpkz == action->kz) continue;

            act = gtk_action_group_get_action(tmpkz->actions,
                                      "LocationEntry");
            if (KZ_LOCATION_ENTRY_ACTION(act)->synchronizing) continue;
            kz_location_entry_action_restore_history
                  (KZ_LOCATION_ENTRY_ACTION(act));
      }

      action->synchronizing = FALSE;
}


static gboolean
cb_entry_key_press (GtkWidget *widget, GdkEventKey *event,
                KzLocationEntryAction *action)
{
      gboolean new_tab;

      if ((event->keyval == GDK_Return || event->keyval == GDK_ISO_Enter)
          && (event->state & GDK_CONTROL_MASK))
      {
            const gchar *uri;
            gchar *smart_uri;

            KZ_CONF_GET("Global", "entry_open_in_new_tab", new_tab, BOOL);

            uri = kz_entry_action_get_text(KZ_ENTRY_ACTION(action));
            smart_uri = kz_smart_bookmark_get_smart_uri(
                        KZ_SMART_BOOKMARK(KZ_LOCATION_ENTRY_ACTION(action)->bookmark), uri);
            if (new_tab)
                  kz_window_load_url(action->kz, smart_uri);
            else 
                  kz_window_open_new_tab(action->kz, smart_uri);
            g_free(smart_uri);

            return TRUE;
      }

      return FALSE;
}


static void
cb_activate_edit_bookmark (GtkMenuItem *menuitem,
                     KzLocationEntryAction *action)
{
      GtkAction *edit_action;
      KzWindow *kz = action->kz;

      kz_actions_set_bookmark_for_action(kz, action->bookmark);
      edit_action = gtk_action_group_get_action(kz->actions,
                                      "EditBookmarks");
      if (edit_action)
            gtk_action_activate(edit_action);
      kz_actions_set_bookmark_for_action(kz, NULL);
}

static void 
cb_entry_populate_popup (GtkEntry *entry, GtkMenu *menu,
                   KzLocationEntryAction *action)
{
      GtkWidget *separator, *menuitem;

      separator = gtk_separator_menu_item_new();
      gtk_menu_shell_append(GTK_MENU_SHELL(menu), separator);
      gtk_widget_show(separator);

      menuitem = gtk_menu_item_new_with_mnemonic(_("_Edit Smart Bookmark"));
      g_signal_connect(menuitem, "activate",
                   G_CALLBACK(cb_activate_edit_bookmark), action);
      gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
      gtk_widget_show(menuitem);
}

void
kz_location_entry_action_set_bookmark (KzLocationEntryAction *action,
                               KzBookmark *bookmark)
{
      g_return_if_fail(KZ_IS_BOOKMARK(bookmark));
      g_object_set(G_OBJECT(action),
                 "kz-bookmark", bookmark, NULL);
}


static void
cb_profile_entry_changed (KzProfile *profile,
                    const gchar *section, const gchar *key,
                    const gchar *old_value,
                    GtkEntry    *entry)
{
      if (!GTK_IS_ENTRY(entry)) return;
      
      switch (key[0])
      {
      case 'u':
            if (strcmp(key, "use_auto_completion") == 0)
            {
                  GtkAction *action;
                      
                  action = g_object_get_data(G_OBJECT(entry),
                                       KZ_LOCATION_ENTRY_ACTION_KEY);
                  if (action && KZ_IS_HISTORY_ACTION(action))
                        {
                            gboolean autocompletion = FALSE;
                          KZ_CONF_GET("Global", "use_auto_completion", autocompletion, BOOL);
                                if(autocompletion)
                                       kz_history_set_completion (KZ_HISTORY_ACTION(action), entry);
                                else

                                     kz_history_unset_completion (KZ_HISTORY_ACTION(action), entry);
                        }
            }
      default:
            break;
      }
}


Generated by  Doxygen 1.6.0   Back to index