Finish refactoring the toolbar to use only actions

Finally the trash, which was the last item that
needed to be implemented as an action, is an
action, a KatzeArrayAction to be exact.

This simplifies more code and also makes Window
and RecentlyVisited generically implementable.

Incidentally this change also fixes a bug where
the browser tried to add a new tab when the last
one was closed, even while destroying itself.

Furthermore sokoke_image_menu_item_ellipsized
and sokoke_widget_popup were promoted to Katze.
We're still keeping the old functions for now.
This commit is contained in:
Christian Dywan 2008-10-10 22:31:37 +02:00
parent 16e47a6a1f
commit e1b828edf2
9 changed files with 732 additions and 233 deletions

View file

@ -16,4 +16,5 @@ libkatze_la_SOURCES = \
katze-utils.c katze-utils.h \
katze-item.c katze-item.h \
katze-list.c katze-list.h \
katze-array.c katze-array.h
katze-array.c katze-array.h \
katze-arrayaction.c katze-arrayaction.h

361
katze/katze-arrayaction.c Normal file
View file

@ -0,0 +1,361 @@
/*
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 "katze-arrayaction.h"
#include "katze-utils.h"
#include <gtk/gtk.h>
#include <glib/gi18n.h>
struct _KatzeArrayAction
{
GtkAction parent_instance;
KatzeArray* array;
};
struct _KatzeArrayActionClass
{
GtkActionClass parent_class;
};
G_DEFINE_TYPE (KatzeArrayAction, katze_array_action, GTK_TYPE_ACTION)
enum
{
PROP_0,
PROP_ARRAY
};
enum
{
POPULATE_POPUP,
ACTIVATE_ITEM,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL];
static void
katze_array_action_finalize (GObject* object);
static void
katze_array_action_set_property (GObject* object,
guint prop_id,
const GValue* value,
GParamSpec* pspec);
static void
katze_array_action_get_property (GObject* object,
guint prop_id,
GValue* value,
GParamSpec* pspec);
static void
katze_array_action_activate (GtkAction* object);
static GtkWidget*
katze_array_action_create_tool_item (GtkAction* action);
static GtkWidget*
katze_array_action_create_menu_item (GtkAction* action);
static void
katze_array_action_connect_proxy (GtkAction* action,
GtkWidget* proxy);
static void
katze_array_action_disconnect_proxy (GtkAction* action,
GtkWidget* proxy);
static void
katze_array_action_class_init (KatzeArrayActionClass* class)
{
GObjectClass* gobject_class;
GtkActionClass* action_class;
signals[POPULATE_POPUP] = g_signal_new ("populate-popup",
G_TYPE_FROM_CLASS (class),
(GSignalFlags) (G_SIGNAL_RUN_LAST),
0,
0,
NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1,
GTK_TYPE_MENU);
signals[ACTIVATE_ITEM] = g_signal_new ("activate-item",
G_TYPE_FROM_CLASS (class),
(GSignalFlags) (G_SIGNAL_RUN_LAST),
0,
0,
NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1,
KATZE_TYPE_ITEM);
gobject_class = G_OBJECT_CLASS (class);
gobject_class->finalize = katze_array_action_finalize;
gobject_class->set_property = katze_array_action_set_property;
gobject_class->get_property = katze_array_action_get_property;
action_class = GTK_ACTION_CLASS (class);
action_class->activate = katze_array_action_activate;
action_class->create_menu_item = katze_array_action_create_menu_item;
action_class->create_tool_item = katze_array_action_create_tool_item;
action_class->connect_proxy = katze_array_action_connect_proxy;
action_class->disconnect_proxy = katze_array_action_disconnect_proxy;
g_object_class_install_property (gobject_class,
PROP_ARRAY,
g_param_spec_object (
"array",
_("Array"),
_("The array the action represents"),
KATZE_TYPE_ARRAY,
G_PARAM_READWRITE));
}
static void
katze_array_action_init (KatzeArrayAction* array_action)
{
array_action->array = NULL;
}
static void
katze_array_action_finalize (GObject* object)
{
KatzeArrayAction* array_action = KATZE_ARRAY_ACTION (object);
if (array_action->array)
g_object_unref (array_action->array);
G_OBJECT_CLASS (katze_array_action_parent_class)->finalize (object);
}
static void
katze_array_action_set_property (GObject* object,
guint prop_id,
const GValue* value,
GParamSpec* pspec)
{
KatzeArrayAction* array_action = KATZE_ARRAY_ACTION (object);
switch (prop_id)
{
case PROP_ARRAY:
katze_array_action_set_array (array_action, g_value_get_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
katze_array_action_get_property (GObject* object,
guint prop_id,
GValue* value,
GParamSpec* pspec)
{
KatzeArrayAction* array_action = KATZE_ARRAY_ACTION (object);
switch (prop_id)
{
case PROP_ARRAY:
g_value_set_object (value, array_action->array);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
katze_array_action_activate (GtkAction* action)
{
GSList* proxies;
proxies = gtk_action_get_proxies (action);
if (!proxies)
return;
do
if (GTK_IS_TOOL_ITEM (proxies->data))
{
}
while ((proxies = g_slist_next (proxies)));
if (GTK_ACTION_CLASS (katze_array_action_parent_class)->activate)
GTK_ACTION_CLASS (katze_array_action_parent_class)->activate (action);
}
static void
katze_array_action_menu_item_activate_cb (GtkWidget* proxy,
KatzeArrayAction* array_action)
{
KatzeItem* item = g_object_get_data (G_OBJECT (proxy), "KatzeItem");
g_signal_emit (array_action, signals[ACTIVATE_ITEM], 0, item);
}
static void
katze_array_action_proxy_clicked_cb (GtkWidget* proxy,
KatzeArrayAction* array_action)
{
GtkWidget* menu;
guint n, i;
GtkWidget* menuitem;
KatzeItem* item;
GdkPixbuf* pixbuf;
GtkWidget* icon;
if (GTK_IS_MENU_ITEM (proxy))
{
if (!(menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (proxy))))
{
menu = gtk_menu_new ();
gtk_menu_item_set_submenu (GTK_MENU_ITEM (proxy), menu);
}
gtk_container_foreach (GTK_CONTAINER (menu), (GtkCallback)(gtk_widget_destroy), NULL);
}
else
menu = gtk_menu_new ();
n = katze_array_get_length (array_action->array);
if (n > 0)
for (i = 0; i < n; i++)
{
item = katze_array_get_nth_item (array_action->array, i);
/* FIXME: The menu item should reflect changes to the item */
menuitem = katze_image_menu_item_new_ellipsized (
katze_item_get_name (item));
pixbuf = gtk_widget_render_icon (menuitem, GTK_STOCK_FILE,
GTK_ICON_SIZE_MENU, NULL);
icon = gtk_image_new_from_pixbuf (pixbuf);
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), icon);
g_object_unref (pixbuf);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
g_object_set_data (G_OBJECT (menuitem), "KatzeItem", item);
g_signal_connect (menuitem, "activate",
G_CALLBACK (katze_array_action_menu_item_activate_cb), array_action);
gtk_widget_show (menuitem);
}
else
{
menuitem = gtk_image_menu_item_new_with_label (_("Empty"));
gtk_widget_set_sensitive (menuitem, FALSE);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
gtk_widget_show (menuitem);
}
g_signal_emit (array_action, signals[POPULATE_POPUP], 0, menu);
if (!GTK_IS_MENU_ITEM (proxy))
katze_widget_popup (GTK_WIDGET (proxy), GTK_MENU (menu),
NULL, KATZE_MENU_POSITION_LEFT);
}
static GtkWidget*
katze_array_action_create_menu_item (GtkAction* action)
{
GtkWidget* menuitem;
menuitem = gtk_menu_item_new ();
return menuitem;
}
static GtkWidget*
katze_array_action_create_tool_item (GtkAction* action)
{
GtkWidget* toolitem;
toolitem = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
return toolitem;
}
static void
katze_array_action_connect_proxy (GtkAction* action,
GtkWidget* proxy)
{
GTK_ACTION_CLASS (katze_array_action_parent_class)->connect_proxy (
action, proxy);
if (GTK_IS_TOOL_ITEM (proxy))
{
g_signal_connect (proxy, "clicked",
G_CALLBACK (katze_array_action_proxy_clicked_cb), action);
}
else if (GTK_IS_MENU_ITEM (proxy))
{
/* FIXME: 'select' doesn't cover all ways of selection */
g_signal_connect (proxy, "select",
G_CALLBACK (katze_array_action_proxy_clicked_cb), action);
}
}
static void
katze_array_action_disconnect_proxy (GtkAction* action,
GtkWidget* proxy)
{
g_signal_handlers_disconnect_by_func (proxy,
G_CALLBACK (katze_array_action_proxy_clicked_cb), action);
GTK_ACTION_CLASS (katze_array_action_parent_class)->disconnect_proxy
(action, proxy);
}
KatzeArray*
katze_array_action_get_array (KatzeArrayAction* array_action)
{
g_return_val_if_fail (KATZE_IS_ARRAY_ACTION (array_action), NULL);
return array_action->array;
}
void
katze_array_action_set_array (KatzeArrayAction* array_action,
KatzeArray* array)
{
GSList* proxies;
g_return_if_fail (KATZE_IS_ARRAY_ACTION (array_action));
g_return_if_fail (!array || katze_array_is_a (array, KATZE_TYPE_ITEM));
/* FIXME: Disconnect old array */
if (array)
g_object_ref (array);
katze_object_assign (array_action->array, array);
/* FIXME: Add and remove items dynamically */
/*g_object_connect (array,
"signal-after::add-item",
katze_array_action_engines_add_item_cb, array_action,
"signal-after::remove-item",
katze_array_action_engines_remove_item_cb, array_action,
NULL);*/
g_object_notify (G_OBJECT (array_action), "array");
proxies = gtk_action_get_proxies (GTK_ACTION (array_action));
if (!proxies)
return;
do
if (GTK_IS_TOOL_ITEM (proxies->data))
{
}
while ((proxies = g_slist_next (proxies)));
}

47
katze/katze-arrayaction.h Normal file
View file

@ -0,0 +1,47 @@
/*
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.
*/
#ifndef __KATZE_ARRAY_ACTION_H__
#define __KATZE_ARRAY_ACTION_H__
#include "katze-array.h"
G_BEGIN_DECLS
#define KATZE_TYPE_ARRAY_ACTION \
(katze_array_action_get_type ())
#define KATZE_ARRAY_ACTION(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), KATZE_TYPE_ARRAY_ACTION, KatzeArrayAction))
#define KATZE_ARRAY_ACTION_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST ((klass), KATZE_TYPE_ARRAY_ACTION, KatzeArrayActionClass))
#define KATZE_IS_ARRAY_ACTION(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), KATZE_TYPE_ARRAY_ACTION))
#define KATZE_IS_ARRAY_ACTION_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE ((klass), KATZE_TYPE_ARRAY_ACTION))
#define KATZE_ARRAY_ACTION_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS ((obj), KATZE_TYPE_ARRAY_ACTION, KatzeArrayActionClass))
typedef struct _KatzeArrayAction KatzeArrayAction;
typedef struct _KatzeArrayActionClass KatzeArrayActionClass;
GType
katze_array_action_get_type (void);
KatzeArray*
katze_array_action_get_array (KatzeArrayAction* array_action);
void
katze_array_action_set_array (KatzeArrayAction* array_action,
KatzeArray* array);
G_END_DECLS
#endif /* __KATZE_ARRAY_ACTION_H__ */

View file

@ -328,3 +328,126 @@ katze_property_label (gpointer object,
return widget;
}
typedef struct
{
GtkWidget* widget;
KatzeMenuPos position;
} KatzePopupInfo;
static void
katze_widget_popup_position_menu (GtkMenu* menu,
gint* x,
gint* y,
gboolean* push_in,
gpointer user_data)
{
gint wx, wy;
gint menu_width;
GtkRequisition menu_req;
GtkRequisition widget_req;
KatzePopupInfo* info = user_data;
GtkWidget* widget = info->widget;
gint widget_height;
/* Retrieve size and position of both widget and menu */
if (GTK_WIDGET_NO_WINDOW (widget))
{
gdk_window_get_position (widget->window, &wx, &wy);
wx += widget->allocation.x;
wy += widget->allocation.y;
}
else
gdk_window_get_origin (widget->window, &wx, &wy);
gtk_widget_size_request (GTK_WIDGET (menu), &menu_req);
gtk_widget_size_request (widget, &widget_req);
menu_width = menu_req.width;
widget_height = widget_req.height; /* Better than allocation.height */
/* Calculate menu position */
if (info->position == KATZE_MENU_POSITION_CURSOR)
; /* Do nothing? */
else if (info->position == KATZE_MENU_POSITION_RIGHT)
{
*x = wx + widget->allocation.width - menu_width;
*y = wy + widget_height;
} else if (info->position == KATZE_MENU_POSITION_LEFT)
{
*x = wx;
*y = wy + widget_height;
}
*push_in = TRUE;
}
/**
* katze_widget_popup:
* @widget: a widget
* @menu: the menu to popup
* @event: a button event, or %NULL
* @pos: the preferred positioning
*
* Pops up the given menu relative to @widget. Use this
* instead of writing custom positioning functions.
*
* Return value: a new label widget
**/
void
katze_widget_popup (GtkWidget* widget,
GtkMenu* menu,
GdkEventButton* event,
KatzeMenuPos pos)
{
int button, event_time;
if (event)
{
button = event->button;
event_time = event->time;
}
else
{
button = 0;
event_time = gtk_get_current_event_time ();
}
if (!gtk_menu_get_attach_widget (menu))
gtk_menu_attach_to_widget (menu, widget, NULL);
if (widget)
{
KatzePopupInfo info = { widget, pos };
gtk_menu_popup (menu, NULL, NULL,
katze_widget_popup_position_menu, &info,
button, event_time);
}
else
gtk_menu_popup (menu, NULL, NULL, NULL, NULL, button, event_time);
}
/**
* katze_image_menu_item_new_ellipsized:
* @label: a label or %NULL
*
* Creates an image menu item where the label is
* reasonably ellipsized for you.
*
* Return value: a new label widget
**/
GtkWidget*
katze_image_menu_item_new_ellipsized (const gchar* label)
{
GtkWidget* menuitem;
GtkWidget* label_widget;
menuitem = gtk_image_menu_item_new ();
label_widget = gtk_label_new (label);
/* FIXME: Should text direction be respected here? */
gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.0);
gtk_label_set_max_width_chars (GTK_LABEL (label_widget), 50);
gtk_label_set_ellipsize (GTK_LABEL (label_widget), PANGO_ELLIPSIZE_MIDDLE);
gtk_widget_show (label_widget);
gtk_container_add (GTK_CONTAINER (menuitem), label_widget);
return menuitem;
}

View file

@ -63,6 +63,21 @@ GtkWidget*
katze_property_label (gpointer object,
const gchar* property);
typedef enum {
KATZE_MENU_POSITION_CURSOR = 0,
KATZE_MENU_POSITION_LEFT,
KATZE_MENU_POSITION_RIGHT
} KatzeMenuPos;
void
katze_widget_popup (GtkWidget* widget,
GtkMenu* menu,
GdkEventButton* event,
KatzeMenuPos pos);
GtkWidget*
katze_image_menu_item_new_ellipsized (const gchar* label);
G_END_DECLS
#endif /* __KATZE_UTILS_H__ */

View file

@ -17,5 +17,6 @@
#include "katze-item.h"
#include "katze-list.h"
#include "katze-array.h"
#include "katze-arrayaction.h"
#endif /* __KATZE_H__ */

View file

@ -44,9 +44,7 @@ struct _MidoriBrowser
GtkActionGroup* action_group;
GtkWidget* menubar;
GtkWidget* menu_bookmarks;
GtkWidget* menu_tools;
GtkWidget* menu_window;
GtkWidget* popup_bookmark;
GtkWidget* popup_history;
GtkWidget* throbber;
@ -72,12 +70,11 @@ struct _MidoriBrowser
GtkWidget* statusbar;
GtkWidget* progressbar;
gchar* statusbar_text;
MidoriWebSettings* settings;
KatzeArray* bookmarks;
MidoriWebSettings* settings;
KatzeArray* proxy_array;
KatzeArray* bookmarks;
KatzeArray* trash;
KatzeArray* search_engines;
KatzeArray* history;
@ -733,32 +730,19 @@ midori_browser_tab_destroy_cb (GtkWidget* widget,
g_signal_emit (browser, signals[REMOVE_TAB], 0, widget);
/* We don't ever want to be in a situation with no tabs,
so just create an empty one if the last one is closed. */
if (!midori_browser_get_current_tab (browser))
so just create an empty one if the last one is closed.
The only exception is when we are closing the window,
which is indicated by the proxy array having been unset. */
if (browser->proxy_array && !midori_browser_get_current_tab (browser))
midori_browser_add_uri (browser, "");
return FALSE;
}
static void
midori_browser_window_menu_item_activate_cb (GtkWidget* menuitem,
GtkWidget* widget)
{
MidoriBrowser* browser;
g_return_if_fail (GTK_IS_WIDGET (widget));
browser = MIDORI_BROWSER (gtk_widget_get_toplevel (widget));
g_return_if_fail (browser);
midori_browser_set_current_tab (browser, widget);
}
static void
_midori_browser_add_tab (MidoriBrowser* browser,
GtkWidget* view)
{
GtkWidget* tab_label;
GtkWidget* menuitem;
KatzeItem* item;
guint n;
@ -770,14 +754,10 @@ _midori_browser_add_tab (MidoriBrowser* browser,
GTK_SHADOW_ETCHED_IN);
tab_label = midori_view_get_proxy_tab_label (MIDORI_VIEW (view));
menuitem = midori_view_get_proxy_menu_item (MIDORI_VIEW (view));
if (browser->proxy_array)
{
item = midori_view_get_proxy_item (MIDORI_VIEW (view));
g_object_ref (item);
katze_array_add_item (browser->proxy_array, item);
}
g_object_connect (view,
"signal::notify::icon",
@ -828,14 +808,7 @@ _midori_browser_add_tab (MidoriBrowser* browser,
view, TRUE);
#endif
gtk_widget_show (menuitem);
g_signal_connect (menuitem, "activate",
G_CALLBACK (midori_browser_window_menu_item_activate_cb), view);
gtk_menu_shell_append (GTK_MENU_SHELL (browser->menu_window), menuitem);
/* We want the tab to be removed if the widget is destroyed */
g_signal_connect_swapped (view, "destroy",
G_CALLBACK (gtk_widget_destroy), menuitem);
g_signal_connect (view, "destroy",
G_CALLBACK (midori_browser_tab_destroy_cb), browser);
@ -1427,63 +1400,105 @@ midori_browser_navigationbar_notify_style_cb (GObject* object,
}
static void
midori_browser_menu_trash_item_activate_cb (GtkWidget* menuitem,
_action_trash_populate_popup (GtkAction* action,
GtkMenu* menu,
MidoriBrowser* browser)
{
KatzeItem* item;
gint n;
GtkWidget* menuitem;
/* Create a new web view with an uri which has been closed before */
item = g_object_get_data (G_OBJECT (menuitem), "KatzeItem");
n = midori_browser_add_item (browser, item);
menuitem = gtk_separator_menu_item_new ();
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
gtk_widget_show (menuitem);
menuitem = sokoke_action_create_popup_menu_item (
_action_by_name (browser, "TrashEmpty"));
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
gtk_widget_show (menuitem);
}
static void
_action_trash_activate_item (GtkAction* action,
KatzeItem* item,
MidoriBrowser* browser)
{
gint n = midori_browser_add_item (browser, item);
midori_browser_set_current_page (browser, n);
katze_array_remove_item (browser->trash, item);
_midori_browser_update_actions (browser);
}
static void
midori_browser_menu_trash_activate_cb (GtkWidget* widget,
_action_history_populate_popup (GtkAction* action,
GtkMenu* menu,
MidoriBrowser* browser)
{
GtkWidget* menu;
guint i, n;
KatzeItem* item;
const gchar* title;
const gchar* uri;
GtkWidget* menuitem;
GtkWidget* icon;
GtkAction* action;
/* Nothing to do */
}
menu = gtk_menu_new ();
n = katze_array_get_length (browser->trash);
static void
_action_history_activate_item (GtkAction* action,
KatzeItem* item,
MidoriBrowser* browser)
{
_midori_browser_open_uri (browser, katze_item_get_uri (item));
}
static void
_action_bookmarks_populate_popup (GtkAction* action,
GtkMenu* menu,
MidoriBrowser* browser)
{
GtkWidget* menuitem = gtk_separator_menu_item_new ();
gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), menuitem);
gtk_widget_show (menuitem);
menuitem = sokoke_action_create_popup_menu_item (
_action_by_name (browser, "BookmarkAdd"));
gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), menuitem);
gtk_widget_show (menuitem);
}
static void
_action_bookmarks_activate_item (GtkAction* action,
KatzeItem* item,
MidoriBrowser* browser)
{
gint n = midori_browser_add_item (browser, item);
midori_browser_set_current_page (browser, n);
_midori_browser_update_actions (browser);
}
static void
_action_window_populate_popup (GtkAction* action,
GtkMenu* menu,
MidoriBrowser* browser)
{
GtkWidget* menuitem = gtk_separator_menu_item_new ();
gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), menuitem);
gtk_widget_show (menuitem);
menuitem = sokoke_action_create_popup_menu_item (
_action_by_name (browser, "TabPrevious"));
gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), menuitem);
gtk_widget_show (menuitem);
menuitem = sokoke_action_create_popup_menu_item (
_action_by_name (browser, "TabNext"));
gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), menuitem);
gtk_widget_show (menuitem);
}
static void
_action_window_activate_item (GtkAction* action,
KatzeItem* item,
MidoriBrowser* browser)
{
guint i, n;
GtkWidget* view;
n = katze_array_get_length (browser->proxy_array);
for (i = 0; i < n; i++)
{
item = katze_array_get_nth_item (browser->trash, i);
title = katze_item_get_name (item);
uri = katze_item_get_uri (item);
menuitem = sokoke_image_menu_item_new_ellipsized (title ? title : uri);
/* FIXME: Get the real icon */
icon = gtk_image_new_from_stock (GTK_STOCK_FILE, GTK_ICON_SIZE_MENU);
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), icon);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
g_object_set_data (G_OBJECT (menuitem), "KatzeItem", item);
g_signal_connect (menuitem, "activate",
G_CALLBACK (midori_browser_menu_trash_item_activate_cb), browser);
gtk_widget_show (menuitem);
view = gtk_notebook_get_nth_page (GTK_NOTEBOOK (browser->notebook), i);
if (midori_view_get_proxy_item (MIDORI_VIEW (view)) == item)
gtk_notebook_set_current_page (GTK_NOTEBOOK (browser->notebook), i);
}
menuitem = gtk_separator_menu_item_new ();
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
gtk_widget_show (menuitem);
action = gtk_action_group_get_action (browser->action_group, "TrashEmpty");
menuitem = gtk_action_create_menu_item (action);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
gtk_widget_show (menuitem);
if (GTK_IS_MENU_ITEM (widget))
gtk_menu_item_set_submenu (GTK_MENU_ITEM (widget), menu);
else
sokoke_widget_popup (widget, GTK_MENU (menu), NULL,
SOKOKE_MENU_POSITION_RIGHT);
}
static void
@ -2877,10 +2892,6 @@ static const GtkActionEntry entries[] = {
{ "OpenInPageholder", GTK_STOCK_JUMP_TO,
N_("Open in Page_holder..."), "",
N_("Open the current page in the pageholder"), G_CALLBACK (_action_open_in_panel_activate) },
{ "Trash", STOCK_USER_TRASH,
NULL, "",
/* N_("Reopen a previously closed tab or window"), G_CALLBACK (_action_trash_activate) }, */
N_("Reopen a previously closed tab or window"), NULL },
{ "TrashEmpty", GTK_STOCK_CLEAR,
N_("Empty Trash"), "",
N_("Delete the contents of the trash"), G_CALLBACK (_action_trash_empty_activate) },
@ -2888,7 +2899,6 @@ static const GtkActionEntry entries[] = {
N_("Undo Close Tab"), "<Ctrl><Shift>t",
N_("Open the last closed tab"), G_CALLBACK (_action_undo_tab_close_activate) },
{ "Bookmarks", NULL, N_("_Bookmarks") },
{ "BookmarkAdd", STOCK_BOOKMARK_ADD,
NULL, "<Ctrl>d",
N_("Add a new bookmark"), G_CALLBACK (_action_bookmark_add_activate) },
@ -2925,7 +2935,6 @@ static const GtkActionEntry entries[] = {
N_("Add, edit and remove search engines..."),
G_CALLBACK (_action_manage_search_engines_activate) },
{ "Window", NULL, N_("_Window") },
{ "TabPrevious", GTK_STOCK_GO_BACK,
N_("_Previous Tab"), "<Ctrl>Page_Up",
N_("Switch to the previous tab"), G_CALLBACK (_action_tab_previous_activate) },
@ -3086,28 +3095,15 @@ static const gchar* ui_markup =
"<menuitem action='Location'/>"
"<menuitem action='Search'/>"
"<menuitem action='OpenInPageholder'/>"
"<menu action='Trash'>"
/* Closed tabs shall be prepended here */
"<separator/>"
"<menuitem action='TrashEmpty'/>"
"</menu>"
"<menuitem action='UndoTabClose'/>"
"</menu>"
"<menu action='Bookmarks'>"
"<menuitem action='BookmarkAdd'/>"
"<separator/>"
/* Bookmarks shall be appended here */
"<menuitem action='Trash'/>"
/* "<menuitem action='RecentlyVisited'/>" */
"</menu>"
"<menuitem action='Bookmarks'/>"
"<menu action='Tools'>"
"<menuitem action='ManageSearchEngines'/>"
/* Panel items shall be appended here */
"</menu>"
"<menu action='Window'>"
"<menuitem action='TabPrevious'/>"
"<menuitem action='TabNext'/>"
"<separator/>"
/* All open tabs shall be appended here */
"</menu>"
"<menuitem action='Window'/>"
"<menu action='Help'>"
"<menuitem action='HelpContents'/>"
"<menuitem action='HelpFAQ'/>"
@ -3124,7 +3120,7 @@ static const gchar* ui_markup =
"<toolitem action='Homepage'/>"
"<toolitem action='Location'/>"
"<toolitem action='Search'/>"
"<placeholder name='Trash'/>"
"<toolitem action='Trash'/>"
"</toolbar>"
"<toolbar name='toolbar_bookmarks'>"
"<toolitem action='BookmarkAdd'/>"
@ -3186,6 +3182,7 @@ midori_browser_init (MidoriBrowser* browser)
GtkRcStyle* rcstyle;
browser->settings = midori_web_settings_new ();
browser->proxy_array = katze_array_new (KATZE_TYPE_ARRAY);
browser->bookmarks = NULL;
browser->trash = NULL;
browser->search_engines = NULL;
@ -3292,6 +3289,70 @@ midori_browser_init (MidoriBrowser* browser)
action, "<Ctrl>K");
g_object_unref (action);
action = g_object_new (KATZE_TYPE_ARRAY_ACTION,
"name", "Trash",
"stock-id", STOCK_USER_TRASH,
"tooltip", _("Reopen a previously closed tab or window"),
NULL);
g_object_connect (action,
"signal::populate-popup",
_action_trash_populate_popup, browser,
"signal::activate-item",
_action_trash_activate_item, browser,
NULL);
gtk_action_group_add_action_with_accel (browser->action_group,
action, "");
g_object_unref (action);
action = g_object_new (KATZE_TYPE_ARRAY_ACTION,
"name", "RecentlyVisited",
"label", _("_Recently visited pages"),
"stock-id", STOCK_HISTORY,
"tooltip", _("Revisit pages that you opened before"),
NULL);
g_object_connect (action,
"signal::populate-popup",
_action_history_populate_popup, browser,
"signal::activate-item",
_action_history_activate_item, browser,
NULL);
gtk_action_group_add_action_with_accel (browser->action_group,
action, "");
g_object_unref (action);
action = g_object_new (KATZE_TYPE_ARRAY_ACTION,
"name", "Bookmarks",
"label", _("_Bookmarks"),
"stock-id", STOCK_BOOKMARKS,
"tooltip", _("Reopen a previously closed tab or window"),
NULL);
g_object_connect (action,
"signal::populate-popup",
_action_bookmarks_populate_popup, browser,
"signal::activate-item",
_action_bookmarks_activate_item, browser,
NULL);
gtk_action_group_add_action_with_accel (browser->action_group,
action, "");
g_object_unref (action);
action = g_object_new (KATZE_TYPE_ARRAY_ACTION,
"name", "Window",
"label", _("Window"),
"stock-id", GTK_STOCK_INDEX,
"tooltip", _("Show a list of all open tabs"),
"array", browser->proxy_array,
NULL);
g_object_connect (action,
"signal::populate-popup",
_action_window_populate_popup, browser,
"signal::activate-item",
_action_window_activate_item, browser,
NULL);
gtk_action_group_add_action_with_accel (browser->action_group,
action, "");
g_object_unref (action);
/* Create the menubar */
browser->menubar = gtk_ui_manager_get_widget (ui_manager, "/menubar");
GtkWidget* menuitem = gtk_menu_item_new ();
@ -3303,31 +3364,15 @@ midori_browser_init (MidoriBrowser* browser)
gtk_menu_item_set_right_justified (GTK_MENU_ITEM (menuitem), TRUE);
gtk_menu_shell_append (GTK_MENU_SHELL (browser->menubar), menuitem);
gtk_box_pack_start (GTK_BOX (vbox), browser->menubar, FALSE, FALSE, 0);
menuitem = gtk_ui_manager_get_widget (ui_manager, "/menubar/Go/Trash");
g_signal_connect (menuitem, "activate",
G_CALLBACK (midori_browser_menu_trash_activate_cb),
browser);
browser->menu_bookmarks = gtk_menu_item_get_submenu (GTK_MENU_ITEM (
gtk_ui_manager_get_widget (ui_manager, "/menubar/Bookmarks")));
menuitem = gtk_separator_menu_item_new ();
gtk_widget_show (menuitem);
gtk_menu_shell_append (GTK_MENU_SHELL (browser->menu_bookmarks), menuitem);
browser->popup_bookmark = gtk_ui_manager_get_widget (
ui_manager, "/popup_bookmark");
g_object_ref (browser->popup_bookmark);
browser->popup_history = gtk_ui_manager_get_widget (
ui_manager, "/popup_history");
g_object_ref (browser->popup_history);
browser->popup_bookmark = g_object_ref (gtk_ui_manager_get_widget (
ui_manager, "/popup_bookmark"));
browser->popup_history = g_object_ref (gtk_ui_manager_get_widget (
ui_manager, "/popup_history"));
browser->menu_tools = gtk_menu_item_get_submenu (GTK_MENU_ITEM (
gtk_ui_manager_get_widget (ui_manager, "/menubar/Tools")));
menuitem = gtk_separator_menu_item_new ();
gtk_widget_show (menuitem);
gtk_menu_shell_append (GTK_MENU_SHELL (browser->menu_tools), menuitem);
browser->menu_window = gtk_menu_item_get_submenu (GTK_MENU_ITEM (
gtk_ui_manager_get_widget (ui_manager, "/menubar/Window")));
menuitem = gtk_separator_menu_item_new ();
gtk_widget_show (menuitem);
gtk_menu_shell_append (GTK_MENU_SHELL (browser->menu_window), menuitem);
gtk_widget_show (browser->menubar);
_action_set_sensitive (browser, "PrivateBrowsing", FALSE);
@ -3348,13 +3393,9 @@ midori_browser_init (MidoriBrowser* browser)
ui_manager, "/toolbar_navigation/Homepage");
browser->search = gtk_ui_manager_get_widget (
ui_manager, "/toolbar_navigation/Search");
browser->button_trash = gtk_ui_manager_get_widget (
ui_manager, "/toolbar_navigation/Trash");
action = gtk_action_group_get_action (browser->action_group, "Trash");
browser->button_trash = gtk_action_create_tool_item (action);
g_signal_connect (browser->button_trash, "clicked",
G_CALLBACK (midori_browser_menu_trash_activate_cb), browser);
gtk_toolbar_insert (GTK_TOOLBAR (browser->navigationbar),
GTK_TOOL_ITEM (browser->button_trash), -1);
sokoke_container_show_children (GTK_CONTAINER (browser->navigationbar));
gtk_widget_hide (browser->navigationbar);
action = gtk_action_group_get_action (browser->action_group, "Fullscreen");
@ -3637,7 +3678,6 @@ midori_browser_dispose (GObject* object)
MidoriBrowser* browser = MIDORI_BROWSER (object);
/* We are done, the session mustn't change anymore */
if (browser->proxy_array)
katze_object_assign (browser->proxy_array, NULL);
G_OBJECT_CLASS (midori_browser_parent_class)->dispose (object);
@ -3827,8 +3867,6 @@ midori_browser_load_bookmarks (MidoriBrowser* browser)
if (!browser->bookmarks)
return;
_midori_browser_create_bookmark_menu (browser, browser->bookmarks,
browser->menu_bookmarks);
n = katze_array_get_length (browser->bookmarks);
for (i = 0; i < n; i++)
{
@ -4022,6 +4060,8 @@ midori_browser_set_property (GObject* object,
; /* FIXME: Disconnect handlers */
katze_object_assign (browser->bookmarks, g_value_get_object (value));
g_object_ref (browser->bookmarks);
g_object_set (_action_by_name (browser, "Bookmarks"), "array",
browser->bookmarks, NULL);
midori_browser_load_bookmarks (browser);
/* FIXME: Connect to updates */
break;
@ -4029,6 +4069,8 @@ midori_browser_set_property (GObject* object,
; /* FIXME: Disconnect handlers */
katze_object_assign (browser->trash, g_value_get_object (value));
g_object_ref (browser->trash);
g_object_set (_action_by_name (browser, "Trash"), "array",
browser->trash, NULL);
/* FIXME: Connect to updates */
_midori_browser_update_actions (browser);
break;
@ -4052,7 +4094,10 @@ midori_browser_set_property (GObject* object,
case PROP_HISTORY:
; /* FIXME: Disconnect handlers */
katze_object_assign (browser->history, g_value_get_object (value));
g_object_ref (browser->history);
midori_browser_load_history (browser);
g_object_set (_action_by_name (browser, "RecentlyVisited"), "array",
browser->history, NULL);
/* FIXME: Connect to updates */
break;
default:
@ -4358,10 +4403,7 @@ midori_browser_get_current_tab (MidoriBrowser* browser)
* Retrieves a proxy array representing the respective proxy items
* of the present views that can be used for session management.
*
* The folder is created on the first call and will be updated to reflect
* changes to all items automatically.
*
* Note that this implicitly creates proxy items of all views.
* The array is updated automatically.
*
* Note: Calling this function doesn't add a reference and the browser
* may release its reference at some point.
@ -4373,11 +4415,6 @@ midori_browser_get_proxy_array (MidoriBrowser* browser)
{
g_return_val_if_fail (MIDORI_IS_BROWSER (browser), NULL);
if (!browser->proxy_array)
{
browser->proxy_array = katze_array_new (KATZE_TYPE_ITEM);
/* FIXME: Fill in items of all present views */
}
return browser->proxy_array;
}

View file

@ -217,88 +217,13 @@ sokoke_container_show_children (GtkContainer* container)
gtk_container_foreach (container, (GtkCallback)(gtk_widget_show_all), NULL);
}
typedef struct
{
GtkWidget* widget;
SokokeMenuPos position;
} SokokePopupInfo;
static void
sokoke_widget_popup_position_menu (GtkMenu* menu,
gint* x,
gint* y,
gboolean* push_in,
gpointer user_data)
{
gint wx, wy;
gint menu_width;
GtkRequisition menu_req;
GtkRequisition widget_req;
SokokePopupInfo* info = user_data;
GtkWidget* widget = info->widget;
/* Retrieve size and position of both widget and menu */
if (GTK_WIDGET_NO_WINDOW (widget))
{
gdk_window_get_position (widget->window, &wx, &wy);
wx += widget->allocation.x;
wy += widget->allocation.y;
}
else
gdk_window_get_origin (widget->window, &wx, &wy);
gtk_widget_size_request (GTK_WIDGET (menu), &menu_req);
gtk_widget_size_request (widget, &widget_req);
menu_width = menu_req.width;
gint widget_height = widget_req.height; /* Better than allocation.height */
/* Calculate menu position */
if (info->position == SOKOKE_MENU_POSITION_CURSOR)
; /* Do nothing? */
else if (info->position == SOKOKE_MENU_POSITION_RIGHT)
{
*x = wx + widget->allocation.width - menu_width;
*y = wy + widget_height;
} else if (info->position == SOKOKE_MENU_POSITION_LEFT)
{
*x = wx;
*y = wy + widget_height;
}
*push_in = TRUE;
}
void
sokoke_widget_popup (GtkWidget* widget,
GtkMenu* menu,
GdkEventButton* event,
SokokeMenuPos pos)
{
int button, event_time;
if (event)
{
button = event->button;
event_time = event->time;
}
else
{
button = 0;
event_time = gtk_get_current_event_time ();
}
if (!gtk_menu_get_attach_widget (menu))
gtk_menu_attach_to_widget (menu, widget, NULL);
if (widget)
{
SokokePopupInfo info = { widget, pos };
gtk_menu_popup (menu, NULL, NULL,
sokoke_widget_popup_position_menu, &info,
button, event_time);
}
else
gtk_menu_popup (menu, NULL, NULL, NULL, NULL, button, event_time);
katze_widget_popup (widget, menu, event, (KatzeMenuPos)pos);
}
typedef enum
@ -704,19 +629,7 @@ sokoke_action_create_popup_menu_item (GtkAction* action)
GtkWidget*
sokoke_image_menu_item_new_ellipsized (const gchar* label)
{
GtkWidget* menuitem;
GtkWidget* label_widget;
menuitem = gtk_image_menu_item_new ();
label_widget = gtk_label_new (label);
/* FIXME: Should text direction be respected here? */
gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.0);
gtk_label_set_max_width_chars (GTK_LABEL (label_widget), 50);
gtk_label_set_ellipsize (GTK_LABEL (label_widget), PANGO_ELLIPSIZE_MIDDLE);
gtk_widget_show (label_widget);
gtk_container_add (GTK_CONTAINER (menuitem), label_widget);
return menuitem;
return katze_image_menu_item_new_ellipsized (label);
}
/**

View file

@ -19,3 +19,4 @@ katze/katze-utils.c
katze/katze-item.c
katze/katze-list.c
katze/katze-array.c
katze/katze-arrayaction.c