midori/midori/midori-locationaction.c
2008-09-03 02:39:25 +02:00

606 lines
19 KiB
C

/*
Copyright (C) 2008 Christian Dywan <christian@twotoasts.de>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
See the file COPYING for the full license text.
*/
#include "midori-locationaction.h"
#include "gtkiconentry.h"
#include <katze/katze.h>
#include <glib/gi18n.h>
#include <gdk/gdkkeysyms.h>
#include <gtk/gtk.h>
struct _MidoriLocationAction
{
GtkAction parent_instance;
gchar* uri;
gdouble progress;
};
struct _MidoriLocationActionClass
{
GtkActionClass parent_class;
};
G_DEFINE_TYPE (MidoriLocationAction, midori_location_action, GTK_TYPE_ACTION)
enum
{
PROP_0,
PROP_PROGRESS,
PROP_SECONDARY_ICON
};
enum
{
ACTIVE_CHANGED,
FOCUS_OUT,
SECONDARY_ICON_RELEASED,
RESET_URI,
SUBMIT_URI,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL];
static void
midori_location_action_finalize (GObject* object);
static void
midori_location_action_set_property (GObject* object,
guint prop_id,
const GValue* value,
GParamSpec* pspec);
static void
midori_location_action_activate (GtkAction* object);
static GtkWidget*
midori_location_action_create_tool_item (GtkAction* action);
static void
midori_location_action_connect_proxy (GtkAction* action,
GtkWidget* proxy);
static void
midori_location_action_disconnect_proxy (GtkAction* action,
GtkWidget* proxy);
static void
midori_cclosure_marshal_VOID__STRING_BOOLEAN (GClosure* closure,
GValue* return_value,
guint n_param_values,
const GValue* param_values,
gpointer invocation_hint,
gpointer marshal_data)
{
typedef void(*GMarshalFunc_VOID__STRING_BOOLEAN) (gpointer data1,
const gchar* arg_1,
gboolean arg_2,
gpointer data2);
register GMarshalFunc_VOID__STRING_BOOLEAN callback;
register GCClosure* cc = (GCClosure*) closure;
register gpointer data1, data2;
g_return_if_fail (n_param_values == 3);
if (G_CCLOSURE_SWAP_DATA (closure))
{
data1 = closure->data;
data2 = g_value_peek_pointer (param_values + 0);
}
else
{
data1 = g_value_peek_pointer (param_values + 0);
data2 = closure->data;
}
callback = (GMarshalFunc_VOID__STRING_BOOLEAN) (marshal_data
? marshal_data : cc->callback);
callback (data1,
g_value_get_string (param_values + 1),
g_value_get_boolean (param_values + 2),
data2);
}
static void
midori_location_action_class_init (MidoriLocationActionClass* class)
{
GObjectClass* gobject_class;
GtkActionClass* action_class;
signals[ACTIVE_CHANGED] = g_signal_new ("active-changed",
G_TYPE_FROM_CLASS (class),
(GSignalFlags) (G_SIGNAL_RUN_LAST),
0,
0,
NULL,
g_cclosure_marshal_VOID__INT,
G_TYPE_NONE, 1,
G_TYPE_INT);
signals[FOCUS_OUT] = g_signal_new ("focus-out",
G_TYPE_FROM_CLASS (class),
(GSignalFlags) (G_SIGNAL_RUN_LAST),
0,
0,
NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
signals[SECONDARY_ICON_RELEASED] = g_signal_new ("secondary-icon-released",
G_TYPE_FROM_CLASS (class),
(GSignalFlags) (G_SIGNAL_RUN_LAST),
0,
0,
NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1,
GTK_TYPE_WIDGET);
signals[RESET_URI] = g_signal_new ("reset-uri",
G_TYPE_FROM_CLASS (class),
(GSignalFlags) (G_SIGNAL_RUN_LAST),
0,
0,
NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
signals[SUBMIT_URI] = g_signal_new ("submit-uri",
G_TYPE_FROM_CLASS (class),
(GSignalFlags) (G_SIGNAL_RUN_LAST),
0,
0,
NULL,
midori_cclosure_marshal_VOID__STRING_BOOLEAN,
G_TYPE_NONE, 2,
G_TYPE_STRING,
G_TYPE_BOOLEAN);
gobject_class = G_OBJECT_CLASS (class);
gobject_class->finalize = midori_location_action_finalize;
gobject_class->set_property = midori_location_action_set_property;
action_class = GTK_ACTION_CLASS (class);
action_class->activate = midori_location_action_activate;
action_class->create_tool_item = midori_location_action_create_tool_item;
action_class->connect_proxy = midori_location_action_connect_proxy;
action_class->disconnect_proxy = midori_location_action_disconnect_proxy;
g_object_class_install_property (gobject_class,
PROP_PROGRESS,
g_param_spec_double (
"progress",
_("Progress"),
_("The current progress of the action"),
0.0, 1.0, 0.0,
G_PARAM_WRITABLE));
g_object_class_install_property (gobject_class,
PROP_SECONDARY_ICON,
g_param_spec_string (
"secondary-icon",
_("Secondary"),
_("The stock ID of the secondary icon"),
NULL,
G_PARAM_WRITABLE));
}
static void
midori_location_action_init (MidoriLocationAction* location_action)
{
location_action->uri = NULL;
location_action->progress = 0.0;
}
static void
midori_location_action_finalize (GObject* object)
{
MidoriLocationAction* location_action = MIDORI_LOCATION_ACTION (object);
g_free (location_action->uri);
G_OBJECT_CLASS (midori_location_action_parent_class)->finalize (object);
}
static void
midori_location_action_set_property (GObject* object,
guint prop_id,
const GValue* value,
GParamSpec* pspec)
{
MidoriLocationAction* location_action = MIDORI_LOCATION_ACTION (object);
switch (prop_id)
{
case PROP_PROGRESS:
{
midori_location_action_set_progress (location_action,
g_value_get_double (value));
break;
}
case PROP_SECONDARY_ICON:
{
midori_location_action_set_secondary_icon (location_action,
g_value_get_string (value));
break;
}
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
midori_location_action_activate (GtkAction* action)
{
GSList* proxies;
GtkWidget* alignment;
GtkWidget* entry;
proxies = gtk_action_get_proxies (action);
if (!proxies)
return;
do
if (GTK_IS_TOOL_ITEM (proxies->data))
{
alignment = gtk_bin_get_child (GTK_BIN (proxies->data));
entry = gtk_bin_get_child (GTK_BIN (alignment));
/* Obviously only one widget can end up with the focus.
Yet we can't predict which one that is, can we? */
gtk_widget_grab_focus (entry);
}
while ((proxies = g_slist_next (proxies)));
if (GTK_ACTION_CLASS (midori_location_action_parent_class)->activate)
GTK_ACTION_CLASS (midori_location_action_parent_class)->activate (action);
}
static GtkWidget*
midori_location_action_create_tool_item (GtkAction* action)
{
GtkWidget* toolitem;
GtkWidget* entry;
GtkWidget* alignment;
toolitem = GTK_WIDGET (gtk_tool_item_new ());
gtk_tool_item_set_expand (GTK_TOOL_ITEM (toolitem), TRUE);
entry = midori_location_entry_new ();
midori_location_entry_set_progress (MIDORI_LOCATION_ENTRY (entry),
MIDORI_LOCATION_ACTION (action)->progress);
gtk_icon_entry_set_icon_highlight (GTK_ICON_ENTRY (
gtk_bin_get_child (GTK_BIN (entry))),
GTK_ICON_ENTRY_SECONDARY, TRUE);
alignment = gtk_alignment_new (0, 0.5, 1, 0.1);
gtk_container_add (GTK_CONTAINER (alignment), entry);
gtk_widget_show (entry);
gtk_container_add (GTK_CONTAINER (toolitem), alignment);
gtk_widget_show (alignment);
return GTK_WIDGET (toolitem);
}
static void
midori_location_action_active_changed_cb (GtkWidget* widget,
gint active,
GtkAction* action)
{
MidoriLocationAction* location_action;
const gchar* text;
location_action = MIDORI_LOCATION_ACTION (action);
text = midori_location_entry_get_text (MIDORI_LOCATION_ENTRY (widget));
katze_assign (location_action->uri, g_strdup (text));
g_signal_emit (action, signals[ACTIVE_CHANGED], 0, active);
}
static gboolean
midori_location_action_key_press_event_cb (GtkWidget* widget,
GdkEventKey* event,
GtkAction* action)
{
const gchar* uri;
switch (event->keyval)
{
case GDK_ISO_Enter:
case GDK_KP_Enter:
case GDK_Return:
{
if ((uri = gtk_entry_get_text (GTK_ENTRY (widget))))
{
g_signal_emit (action, signals[SUBMIT_URI], 0, uri,
(event->state & GDK_MOD1_MASK) ? TRUE : FALSE);
return TRUE;
}
}
case GDK_Escape:
{
g_signal_emit (action, signals[RESET_URI], 0);
return TRUE;
}
}
return FALSE;
}
static gboolean
midori_location_action_focus_out_event_cb (GtkWidget* widget,
GdkEventKey* event,
GtkAction* action)
{
g_signal_emit (action, signals[FOCUS_OUT], 0);
return FALSE;
}
static void
midori_location_action_icon_released_cb (GtkWidget* widget,
GtkIconEntryPosition icon_pos,
gint button,
GtkAction* action)
{
if (icon_pos == GTK_ICON_ENTRY_SECONDARY)
g_signal_emit (action, signals[SECONDARY_ICON_RELEASED], 0, widget);
}
static void
midori_location_action_connect_proxy (GtkAction* action,
GtkWidget* proxy)
{
GtkWidget* alignment;
GtkWidget* entry;
GTK_ACTION_CLASS (midori_location_action_parent_class)->connect_proxy (
action, proxy);
if (GTK_IS_TOOL_ITEM (proxy))
{
alignment = gtk_bin_get_child (GTK_BIN (proxy));
entry = gtk_bin_get_child (GTK_BIN (alignment));
g_signal_connect (entry, "active-changed",
G_CALLBACK (midori_location_action_active_changed_cb), action);
g_object_connect (gtk_bin_get_child (GTK_BIN (entry)),
"signal::key-press-event",
midori_location_action_key_press_event_cb, action,
"signal::focus-out-event",
midori_location_action_focus_out_event_cb, action,
"signal::icon-released",
midori_location_action_icon_released_cb, action,
NULL);
}
}
static void
midori_location_action_disconnect_proxy (GtkAction* action,
GtkWidget* proxy)
{
g_signal_handlers_disconnect_by_func (proxy,
G_CALLBACK (gtk_action_activate), action);
GTK_ACTION_CLASS (midori_location_action_parent_class)->disconnect_proxy
(action, proxy);
}
const gchar*
midori_location_action_get_uri (MidoriLocationAction* location_action)
{
g_return_val_if_fail (MIDORI_IS_LOCATION_ACTION (location_action), NULL);
return location_action->uri;
}
void
midori_location_action_set_uri (MidoriLocationAction* location_action,
const gchar* uri)
{
GSList* proxies;
GtkWidget* alignment;
GtkWidget* entry;
g_return_if_fail (MIDORI_IS_LOCATION_ACTION (location_action));
g_return_if_fail (uri != NULL);
katze_assign (location_action->uri, g_strdup (uri));
proxies = gtk_action_get_proxies (GTK_ACTION (location_action));
if (!proxies)
return;
do
if (GTK_IS_TOOL_ITEM (proxies->data))
{
alignment = gtk_bin_get_child (GTK_BIN (proxies->data));
entry = gtk_bin_get_child (GTK_BIN (alignment));
midori_location_entry_set_text (MIDORI_LOCATION_ENTRY (entry), uri);
}
while ((proxies = g_slist_next (proxies)));
}
void
midori_location_action_add_uri (MidoriLocationAction* location_action,
const gchar* uri)
{
GSList* proxies;
GtkWidget* alignment;
GtkWidget* entry;
MidoriLocationEntryItem item;
g_return_if_fail (MIDORI_IS_LOCATION_ACTION (location_action));
g_return_if_fail (uri != NULL);
katze_assign (location_action->uri, g_strdup (uri));
proxies = gtk_action_get_proxies (GTK_ACTION (location_action));
if (!proxies)
return;
do
if (GTK_IS_TOOL_ITEM (proxies->data))
{
alignment = gtk_bin_get_child (GTK_BIN (proxies->data));
entry = gtk_bin_get_child (GTK_BIN (alignment));
item.favicon = NULL;
item.uri = uri;
item.title = NULL;
midori_location_entry_add_item (
MIDORI_LOCATION_ENTRY (entry), &item);
}
while ((proxies = g_slist_next (proxies)));
}
void
midori_location_action_set_icon_for_uri (MidoriLocationAction* location_action,
GdkPixbuf* icon,
const gchar* uri)
{
GSList* proxies;
GtkWidget* alignment;
GtkWidget* entry;
GtkWidget* child;
MidoriLocationEntryItem item;
g_return_if_fail (MIDORI_IS_LOCATION_ACTION (location_action));
g_return_if_fail (!icon || GDK_IS_PIXBUF (icon));
g_return_if_fail (uri != NULL);
proxies = gtk_action_get_proxies (GTK_ACTION (location_action));
if (!proxies)
return;
do
if (GTK_IS_TOOL_ITEM (proxies->data))
{
alignment = gtk_bin_get_child (GTK_BIN (proxies->data));
entry = gtk_bin_get_child (GTK_BIN (alignment));
child = gtk_bin_get_child (GTK_BIN (entry));
item.favicon = icon;
item.uri = uri;
item.title = NULL;
midori_location_entry_add_item (
MIDORI_LOCATION_ENTRY (entry), &item);
if (location_action->uri == uri)
gtk_icon_entry_set_icon_from_pixbuf (GTK_ICON_ENTRY (child),
GTK_ICON_ENTRY_PRIMARY, icon);
}
while ((proxies = g_slist_next (proxies)));
}
void
midori_location_action_set_title_for_uri (MidoriLocationAction* location_action,
const gchar* title,
const gchar* uri)
{
GSList* proxies;
GtkWidget* alignment;
GtkWidget* entry;
MidoriLocationEntryItem item;
g_return_if_fail (MIDORI_IS_LOCATION_ACTION (location_action));
g_return_if_fail (title != NULL);
g_return_if_fail (uri != NULL);
proxies = gtk_action_get_proxies (GTK_ACTION (location_action));
if (!proxies)
return;
do
if (GTK_IS_TOOL_ITEM (proxies->data))
{
alignment = gtk_bin_get_child (GTK_BIN (proxies->data));
entry = gtk_bin_get_child (GTK_BIN (alignment));
item.favicon = NULL;
item.uri = uri;
item.title = item.uri;
midori_location_entry_add_item (
MIDORI_LOCATION_ENTRY (entry), &item);
}
while ((proxies = g_slist_next (proxies)));
}
gdouble
midori_location_action_get_progress (MidoriLocationAction* location_action)
{
g_return_val_if_fail (MIDORI_IS_LOCATION_ACTION (location_action), 0.0);
return location_action->progress;
}
void
midori_location_action_set_progress (MidoriLocationAction* location_action,
gdouble progress)
{
GSList* proxies;
GtkWidget* alignment;
GtkWidget* entry;
g_return_if_fail (MIDORI_IS_LOCATION_ACTION (location_action));
location_action->progress = CLAMP (progress, 0.0, 1.0);
proxies = gtk_action_get_proxies (GTK_ACTION (location_action));
if (!proxies)
return;
do
if (GTK_IS_TOOL_ITEM (proxies->data))
{
alignment = gtk_bin_get_child (GTK_BIN (proxies->data));
entry = gtk_bin_get_child (GTK_BIN (alignment));
midori_location_entry_set_progress (MIDORI_LOCATION_ENTRY (entry),
location_action->progress);
}
while ((proxies = g_slist_next (proxies)));
}
void
midori_location_action_set_secondary_icon (MidoriLocationAction* location_action,
const gchar* stock_id)
{
GSList* proxies;
GtkWidget* alignment;
GtkWidget* entry;
GtkWidget* child;
GtkStockItem stock_item;
g_return_if_fail (MIDORI_IS_LOCATION_ACTION (location_action));
g_return_if_fail (!stock_id || gtk_stock_lookup (stock_id, &stock_item));
proxies = gtk_action_get_proxies (GTK_ACTION (location_action));
if (!proxies)
return;
do
if (GTK_IS_TOOL_ITEM (proxies->data))
{
alignment = gtk_bin_get_child (GTK_BIN (proxies->data));
entry = gtk_bin_get_child (GTK_BIN (alignment));
child = gtk_bin_get_child (GTK_BIN (entry));
if (stock_id)
gtk_icon_entry_set_icon_from_stock (GTK_ICON_ENTRY (child),
GTK_ICON_ENTRY_SECONDARY, stock_id);
else
gtk_icon_entry_set_icon_from_pixbuf (GTK_ICON_ENTRY (child),
GTK_ICON_ENTRY_SECONDARY, NULL);
}
while ((proxies = g_slist_next (proxies)));
}