Logo Search packages:      
Sourcecode: galeon version File versions

galeon-window.c

/*
 *  Copyright (C) 2000, 2001, 2002 Marco Pesenti Gritti
 *
 *  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.
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include "galeon-marshal.h"
#include "galeon-window.h"
#include "galeon-sidebar.h"
#include "galeon-dnd.h"
#include "gul-state.h"
#include "gul-notebook.h"
#include "gul-gui.h"
#include "gul-general.h"
#include "gul-prefs-utils.h"
#include "statusbar.h"
#include "ppview-toolbar.h"
#include "window-commands.h"
#include "find-dialog.h"
#include "history-dialog.h"
#include "galeon-shell.h"
#include "bookmarks-gtk-menu.h"
#include "bookmarks-gtk-toolbar-set.h"
#include "eel-gconf-extensions.h"
#include "prefs-strings.h"
#include "galeon-embed-utils.h"
#include "galeon-embed-prefs.h"
#include "bookmarks-editor-dockable.h"
#include "galeon-recent-history-menu.h"
#include "galeon-embed-prefs.h"
#include "galeon-css-menu.h"
#include "galeon-window-menu.h"
#include "galeon-tab-menu.h"
#include "galeon-encoding-menu.h"
#include "hig-alert.h"
#include "galeon-debug.h"
#include "galeon-sidebars.h"

#include <stdlib.h>
#include <string.h>
#include <glib/gi18n.h>
#include "egg-dock.h"
#include "egg-dock-item.h"
#include <libgnomevfs/gnome-vfs-uri.h>
#include <X11/X.h>
#include <X11/Xlib.h>
#include <gdk/gdkx.h>
#include <gdk/gdkkeysyms.h>
#include <gtk/gtkmenuitem.h>
#include <gtk/gtkpaned.h>
#include <gtk/gtkstock.h>
#include <gtk/gtkentry.h>
#include <gtk/gtkeditable.h>
#include <gtk/gtkdialog.h>
#include <gtk/gtkimage.h>
#include <gtk/gtkhpaned.h>
#include <gtk/gtklabel.h>
#include <gtk/gtkuimanager.h>
#include <gtk/gtktoolbar.h>
#include <gtk/gtkmenushell.h>

#include <gtk/gtkmessagedialog.h>
#include <libgnomeui/gnome-stock-icons.h>

#include "pixbuf-cache.h"
#include "egg-editable-toolbar.h"

#include "galeon-action-location.h"
#include "galeon-action-navigation.h"
#include "galeon-action-home.h"
#include "galeon-action-new.h"
#include "galeon-action-refresh.h"
#include "galeon-action-stop.h"
#include "galeon-action-go.h"
#include "galeon-action-zoom.h"
#include "galeon-action-spinner.h"
#include "galeon-action-favicon.h"

/* keys and defaults for state */
#define STATE_SIDEBAR_SIZE         "Main Window/sidebar_size"

#define STATE_SIDEBAR_SIZE_DEFAULT 175

#define STATE_MAIN_WIDTH_DEFAULT   700
#define STATE_MAIN_HEIGHT_DEFAULT  500

#define GCONF_DETACH_TOOLBAR "/desktop/gnome/interface/toolbar_detachable"
#define GCONF_DETACH_MENUBAR "/desktop/gnome/interface/menubar_detachable"

enum GaleonWindowSignalsEnum
{
      ACTIVE_EMBED_CHANGED,
      LAST_SIGNAL
};
static gint GaleonWindowSignals[LAST_SIGNAL];

/* These are the values of in gconf for these items */
#define VIEW_IMAGES_ALWAYS    0
#define VIEW_IMAGES_CURRENT   1
#define VIEW_IMAGES_NEVER     2
#define ACCEPT_COOKIES_ALWAYS 0
#define ACCEPT_COOKIES_CURRENT      1
#define ACCEPT_COOKIES_NEVER  2

#define GALEON_WINDOW_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), \
                               GALEON_TYPE_WINDOW, GaleonWindowPrivate))


struct GaleonWindowPrivate
{
      GList *notifiers;
      PPViewToolbar *ppview_toolbar;
      GbGtkMenu *bookmarks_menu;
      GbGtkToolbarSet *bookmarks_toolbar;
      GaleonCssMenu *css_menu;
      GaleonWindowMenu *window_menu;
      GaleonTabMenu *tab_menu;
      GaleonEncodingMenu *encoding_menu;
      GaleonRecentHistoryMenu *rh_menu;
      GtkNotebook *notebook;
      GtkWidget *hpaned;
      GaleonTab *active_tab;
      GtkWidget *sidebar;
      GaleonPopup *embed_popup;
      GaleonDialog *find_dialog;
      GaleonDialog *history_dialog;
      GaleonDialog *history_sidebar;
      GbEditorDockable *bookmarks_sidebar;
      EmbedChromeMask chrome_mask;
      gboolean ignore_layout_toggles;
      gboolean has_default_size;
      gboolean closing;
      GaleonWindowRecentHistory *recent_history;

      GtkWidget *main_area;
      GtkWidget *menubar;
      GtkWidget *statusbar;
      EggEditableToolbar *egg_toolbar;
      GtkActionGroup *action_group;

      GaleonActionLocation *location_action;
      GaleonActionSpinner *spinner_action;
};

#define ACTION_ITEM(name) gtk_action_group_get_action(window->priv->action_group, name)
#define TOGGLE_ITEM(name) GTK_TOGGLE_ACTION(ACTION_ITEM(name))
#define RADIO_ITEM(name) GTK_RADIO_ACTION(ACTION_ITEM(name))

#define FILE_OFFLINE_ACTION         "FileOfflineAction"

#define VIEW_STOP_ACTION            "ViewStopAction"
#define VIEW_TOOLBAR_ACTION         "ViewToolbarAction"
#define VIEW_BMTOOLBARS_ACTION            "ViewBmToolbarsAction"
#define VIEW_STATUSBAR_ACTION       "ViewStatusbarAction"
#define VIEW_SIDEBAR_ACTION         "ViewSidebarAction"
#define VIEW_FULLSCREEN_ACTION            "Fullscreen" /* for compatability with 1.3.12 toolbar */

#define VIEW_IMAGES_BLOCKSITE_ACTION      "ViewImagesBlockSiteAction"
#define VIEW_IMAGES_ALLOWSITE_ACTION      "ViewImagesAllowSiteAction"
#define WEB_COOKIES_BLOCKSITE_ACTION      "WebCookiesBlockSiteAction"
#define WEB_COOKIES_ALLOWSITE_ACTION      "WebCookiesAllowSiteAction"
#define WEB_POPUPS_ALLOWSITE_ACTION "WebPopupsAllowSiteAction"

#define WEB_POPUPS_ALWAYS_ACTION    "WebPopupsAlwaysAction"
#define WEB_ALLOW_JAVA_ACTION       "WebAllowJavaAction"
#define WEB_ALLOW_JS_ACTION         "WebAllowJSAction"
#define WEB_JAVA_CONSOLE_ACTION         "WebJavaConsoleAction"

#define VIEW_SOURCE_ACTION              "FilePageSourceAction"
#define FILE_PRINT_ACTION               "FilePrintAction"

#define BOOKMARK_MENU_PATH          "/menubar/Bookmarks"
#define TAB_POPUP_PATH              "/GaleonTabPopup"

static void
set_offline_action_state(GtkToggleAction *action, gboolean offline)
{
      gtk_toggle_action_set_active (action, offline);
      galeon_embed_shell_set_offline_mode (embed_shell, offline);
}

static void
gtk_cmd_file_offline(GtkToggleAction *action, GaleonWindow *window)
{
      gboolean offline = gtk_toggle_action_get_active (action);

      eel_gconf_set_boolean (CONF_GENERAL_OFFLINE, offline);
      set_offline_action_state (action, offline);
}

static void
gtk_cmd_gconf_toggle_monitor(GConfClient *client,
                             guint cnxn_id,
                             GConfEntry *entry,
                       gpointer user_data)
{
      GtkToggleAction *action = user_data;
      set_offline_action_state (action, eel_gconf_get_boolean (entry->key));
}

static void
gtk_cmd_view_toolbar(GtkAction *action, GaleonWindow *window)
{
      EmbedChromeMask mask;

      if (window->priv->ignore_layout_toggles) return;
      
        mask = galeon_window_get_chrome(window);
        mask ^= EMBED_CHROME_TOOLBARON;
        galeon_window_set_chrome(window, mask);
}

static void
gtk_cmd_view_bmtoolbars(GtkAction *action, GaleonWindow *window)
{
      EmbedChromeMask mask;
      
      if (window->priv->ignore_layout_toggles) return;

        mask = galeon_window_get_chrome(window);
        mask ^= EMBED_CHROME_PERSONALTOOLBARON;
        galeon_window_set_chrome(window, mask);
}

static void
gtk_cmd_view_sidebar(GtkAction *action, GaleonWindow *window)
{
      EmbedChromeMask mask;

      if (window->priv->ignore_layout_toggles) return;
      
        mask = galeon_window_get_chrome(window);
        mask ^= EMBED_CHROME_SIDEBARON;
        galeon_window_set_chrome(window, mask);
}

static void
gtk_cmd_view_statusbar(GtkAction *action, GaleonWindow *window)
{
      EmbedChromeMask mask;

      if (window->priv->ignore_layout_toggles) return;
      
        mask = galeon_window_get_chrome(window);
        mask ^= EMBED_CHROME_STATUSBARON;
        galeon_window_set_chrome(window, mask);
}

static void
gtk_cmd_view_fullscreen(GtkAction *action, GaleonWindow *window)
{     
      if (window->priv->ignore_layout_toggles) return;

      galeon_window_toggle_fullscreen(window);
}

static void
gtk_cmd_allow_java(GtkToggleAction *action, GaleonWindow *window)
{
      eel_gconf_set_boolean(CONF_FILTERING_JAVA_ENABLED,
                        gtk_toggle_action_get_active(action));
}

static void
gtk_cmd_allow_js(GtkToggleAction *action, GaleonWindow *window)
{
      eel_gconf_set_boolean(CONF_FILTERING_JAVASCRIPT_ENABLED,
                        gtk_toggle_action_get_active(action));
}

/* Prototype needed as implemented later */
static void update_permission_control(GaleonWindow *window, GaleonTab *tab);

static void
gtk_cmd_allow_popups(GtkToggleAction *action, GaleonWindow *window)
{
      eel_gconf_set_boolean(CONF_FILTERING_ALLOW_POPUPS,
                        gtk_toggle_action_get_active(action));
      update_permission_control(window, NULL);
}

static GtkActionEntry entries[] = {
      { "FileMenuAction", NULL, N_("_File"), NULL, NULL, NULL, },
      { "EditMenuAction", NULL, N_("_Edit"), NULL, NULL, NULL, },
      { "ViewMenuAction", NULL, N_("_View"), NULL, NULL, NULL, },
      { "ViewImagesMenuAction", NULL, N_("I_mages"), NULL, NULL, NULL },
      { "ViewEncodingMenuAction", NULL, N_("_Encoding"), NULL, NULL, NULL },
      { "ViewStylesMenuAction", NULL, N_("St_yles"), NULL, NULL, NULL  },
      { "WebMenuAction", NULL, N_("_Web"), NULL, NULL, NULL },
      { "WebCookiesMenuAction", NULL, N_("C_ookies"), NULL, NULL, NULL },
      { "WebPopupsMenuAction", NULL, N_("_Popups"), NULL, NULL, NULL },
      { "GoMenuAction", NULL, N_("_Go"), NULL, NULL, NULL },
      { "BookmarksMenuAction", NULL, N_("_Bookmarks"), NULL, NULL, NULL },
      { "TabsMenuAction", NULL, N_("_Tabs"), NULL, NULL, NULL },
      { "TabsMoveMenuAction", NULL, N_("_Move Tab to Another Window"), NULL, NULL, NULL },
      { "HelpMenuAction", NULL, N_("_Help"), NULL, NULL, NULL },

      { "FileNewWindowAction", GTK_STOCK_NEW, N_("_New Window"), "<control>n",
        N_("Open another Galeon window"), G_CALLBACK(window_cmd_new_window) },
      { "FileNewTabAction", STOCK_NEW_TAB, N_("New _Tab"), "<control>t",
        N_("Open a new tab in this window"), G_CALLBACK(window_cmd_new_tab) },
      { "FileOpenAction", GTK_STOCK_OPEN, N_("_Open..."), "<control>o",
        N_("Open a file"), G_CALLBACK(window_cmd_file_open) },
      { "FileSaveAsAction", GTK_STOCK_SAVE_AS, N_("Save _As..."), "<control><shift>s",
        N_("Save the current page with a different name"), G_CALLBACK(window_cmd_file_save_as) },
      { FILE_PRINT_ACTION, GTK_STOCK_PRINT, N_("_Print..."), "<control>p",
        N_("Print the current page"), G_CALLBACK(window_cmd_file_print) },
      { "FileSendToAction", STOCK_SEND_MAIL, N_("_Send Link To..."), NULL,
        N_("Send the address of the current page by Email"), G_CALLBACK(window_cmd_file_send_to) },
      { "FilePageSourceAction", STOCK_VIEW_SOURCE, N_("_View Source"), "<control>u",
        N_("Show the source of the current page"), G_CALLBACK(window_cmd_view_page_source) },
      { "FilePageInfoAction", GTK_STOCK_PROPERTIES, N_("P_roperties"), NULL,
        N_("See page properties"), G_CALLBACK(window_cmd_view_page_info) },
      { "FileCloseTabAction", GTK_STOCK_CLOSE, N_("_Close"), "<control>w",
        N_("Close the current page"), G_CALLBACK(window_cmd_file_close_tab) },
      { "FileQuitAction", GTK_STOCK_QUIT, N_("_Quit"), "<control>q",
        N_("Close all windows and quit"), G_CALLBACK(window_cmd_file_quit) },

      { "EditCutAction", GTK_STOCK_CUT, N_("Cu_t"), "<control>x",
        N_("Cut the selection to the clipboard"), G_CALLBACK(window_cmd_edit_cut) },
      { "EditCopyAction", GTK_STOCK_COPY, N_("_Copy"), "<control>c",
        N_("Copy the selection to the clipboard"), G_CALLBACK(window_cmd_edit_copy) },
      { "EditPasteAction", GTK_STOCK_PASTE, N_("_Paste"), "<control>v",
        N_("Paste the selection from the clipboard"), G_CALLBACK(window_cmd_edit_paste) },
      { "EditSelectAllAction", STOCK_SELECT_ALL, N_("Select _All"), "<control>a",
        N_("Select the entire page"), G_CALLBACK(window_cmd_edit_select_all) },
      { "EditFindAction", GTK_STOCK_FIND, N_("_Find..."), "<control>f",
        N_("Search for a string in the current page"), G_CALLBACK(window_cmd_edit_find) },
      { "EditFindNextAction", NULL, N_("Find Ne_xt"), "<control>g",
        N_("Find next occurrence of the same string"), G_CALLBACK(window_cmd_edit_find_next) },
      { "EditFindPrevAction", NULL, N_("Find Pre_vious"), "<control><shift>g",
        N_("Find previous occurrence of the same string"), G_CALLBACK(window_cmd_edit_find_prev) },
      { "EditPDMAction", NULL, N_("P_ersonal Data"), NULL,
        N_("Edit your personal data"), G_CALLBACK(window_cmd_tools_pdm) },
      { "EditToolbarAction", NULL, N_("T_oolbar"), NULL,
        N_("Edit the main toolbar"), G_CALLBACK(window_cmd_settings_toolbar_editor) },
      { "EditPrefsAction", GTK_STOCK_PREFERENCES, N_("P_references"), NULL,
        N_("Edit Galeon preferences"), G_CALLBACK(window_cmd_edit_prefs) },

      { "ViewZoomInAction", GTK_STOCK_ZOOM_IN, N_("Zoom In"), "<control>plus",
        N_("Show the contents in more detail"), G_CALLBACK(window_cmd_view_zoom_in) },
      { "ViewZoomOutAction", GTK_STOCK_ZOOM_OUT, N_("Zoom Out"), "<control>minus",
        N_("Show the contents in less detail"), G_CALLBACK(window_cmd_view_zoom_out) },
      { "ViewZoomNormalAction", GTK_STOCK_ZOOM_100, N_("Normal Size"), "<control>0",
        N_("Show the contents at the normal size"), G_CALLBACK(window_cmd_view_zoom_normal) },
      { "ViewStopAction", GTK_STOCK_STOP, N_("_Stop"), "Escape",
        N_("Stop current data transfer"), G_CALLBACK(window_cmd_go_stop) },
      { "ViewReloadAction", GTK_STOCK_REFRESH, N_("_Reload"), "<control>r",
        N_("Display the latest content of the current page"), G_CALLBACK(window_cmd_go_reload) },

      { "ViewImagesBlockSiteAction", NULL, N_("_Block Images From This Site"), NULL,
        N_("Allow Images from this site to load"), G_CALLBACK(window_cmd_set_permission) },
      { "ViewImagesAllowSiteAction", NULL, N_("_Allow Images From This Site"), NULL,
        N_("Block Images from this site from loading"), G_CALLBACK(window_cmd_set_permission) },

      { WEB_JAVA_CONSOLE_ACTION, NULL, N_("Java _Console"), NULL,
        N_("Show Java console window"), G_CALLBACK(window_cmd_show_java_console) },
      { "WebJSConsoleAction", NULL, N_("J_avaScript Console"), NULL,
        N_("Show JavaScript console window"), G_CALLBACK(window_cmd_show_js_console) },

      { "WebCookiesBlockSiteAction", NULL, N_("_Block Cookies From This Site"), NULL,
        N_("Block Cookies from this site from being accepted"), G_CALLBACK(window_cmd_set_permission) },
      { "WebCookiesAllowSiteAction", NULL, N_("_Allow Cookies From This Site"), NULL,
        N_("Allow Cookies from this site to accepted"), G_CALLBACK(window_cmd_set_permission) },

      { "WebPopupsAllowSiteAction", NULL, N_("_Allow Popups From This Site"), NULL,
        N_("Allow Popups from this site to be accepted"), G_CALLBACK(window_cmd_set_permission) },

      { "GoMyportalAction", NULL, N_("_My Portal"), NULL,
        N_("Go to the My Portal"), G_CALLBACK(window_cmd_go_myportal) },
      { "GoLocationAction", NULL, N_("_Location..."), "<control>l",
        N_("Specify a location to visit"), G_CALLBACK(window_cmd_go_location) },
      { "GoHistoryAction", GALEON_STOCK_HISTORY, N_("_History"), "<control>h",
        N_("Show browser history window"), G_CALLBACK(window_cmd_tools_history) },

      { "BookmarksAddInteractiveAction", STOCK_ADD_BOOKMARK, N_("_Add Bookmark..."), "<control>d",
        N_("Add a bookmark for the current location"), G_CALLBACK(window_cmd_bookmarks_add_interactive) },
      { "BookmarksAddTabFolderAction", GTK_STOCK_ADD, N_("_Add Tabs As Folder..."), NULL,
        N_("Add the current window's tabs as a folder"), G_CALLBACK(window_cmd_bookmarks_add_tab_folder) },
      { "BookmarksEditAction", STOCK_EDIT_BOOKMARK, N_("_Edit Bookmarks"), "<control>b",
        N_("Open a bookmarks editor"), G_CALLBACK(window_cmd_bookmarks_edit) },


      { "TabsPrevAction", NULL, N_("_Previous Tab"), "<control>Page_Up",
        N_("View previous tab"), G_CALLBACK(window_cmd_tabs_previous) },
      { "TabsNextAction", NULL, N_("_Next Tab"), "<control>Page_Down",
        N_("View next tab"), G_CALLBACK(window_cmd_tabs_next) },
      { "TabsMoveLeftAction", NULL, N_("Move Tab _Left"), "<control><shift>Page_Up",
        N_("Move this tab left"), G_CALLBACK(window_cmd_tabs_move_left) },
      { "TabsMoveRightAction", NULL, N_("Move Tab _Right"), "<control><shift>Page_Down",
        N_("Move this tab right"), G_CALLBACK(window_cmd_tabs_move_right) },
      { "TabsCloneAction", NULL, N_("_Clone Tab"), "<control><shift>u",
        N_("Create a copy of this tab"), G_CALLBACK(window_cmd_tabs_clone) },
      { "TabsDetachAction", NULL, N_("_Detach Tab"), "<control><shift>m",
        N_("Detach this tab into its own window"), G_CALLBACK(window_cmd_tabs_detach) },
      { "TabsCloseOtherTabsAction", NULL, N_("Close _Other Tabs in Window"), NULL,
        N_("Close the other tabs in this window"), G_CALLBACK(window_cmd_tabs_close_other_tabs) },

      { "HelpContentsAction", GTK_STOCK_HELP, N_("_Contents"), "F1",
        N_("Open the Galeon manual"), G_CALLBACK(window_cmd_help_manual) },
      { "HelpAboutPluginsAction", NULL, N_("About _Plugins"), NULL,
        N_("Show information about the currently installed plugins"), G_CALLBACK(window_cmd_help_plugins) },
      { "HelpAboutAction", GNOME_STOCK_ABOUT, N_("_About"), NULL,
        N_("About Galeon"), G_CALLBACK(window_cmd_help_about) },

      { "TabPopupCloseTabAction", GTK_STOCK_CLOSE, N_("_Close Tab"), NULL,
        N_("Close the current tab"), G_CALLBACK(window_cmd_file_close_tab) }
};
static guint n_entries = G_N_ELEMENTS(entries);

static GtkToggleActionEntry toggle_entries[] = {
      { "FileOfflineAction", NULL, N_("_Work Offline"), NULL,
        N_("Work in offline mode"), 
        G_CALLBACK(gtk_cmd_file_offline), FALSE },

      { "ViewToolbarAction", NULL, N_("_Toolbar"), NULL, 
        N_("Change the visibility of the main toolbar"), 
        G_CALLBACK(gtk_cmd_view_toolbar), FALSE },

      { "ViewBmToolbarsAction", NULL, N_("_Bookmark Toolbars"), NULL, 
        N_("Change the visibility of the bookmarks toolbars"), 
        G_CALLBACK(gtk_cmd_view_bmtoolbars), FALSE },

      { "ViewStatusbarAction", NULL, N_("St_atusbar"), NULL, 
        N_("Change the visibility of the statusbar"), 
        G_CALLBACK(gtk_cmd_view_statusbar), FALSE },

      { "ViewSidebarAction", NULL, N_("_Side Pane"), "F9", 
        N_("Change the visibility of the side pane"),
        G_CALLBACK(gtk_cmd_view_sidebar), FALSE },

      { VIEW_FULLSCREEN_ACTION, STOCK_FULLSCREEN, N_("_Fullscreen"), "F11", 
        N_("Toggle fullscreen mode"), 
        G_CALLBACK(gtk_cmd_view_fullscreen), FALSE },

      { "WebAllowJavaAction", NULL, N_("Allow _Java"), NULL,
        N_("Toggle allowing of java applets to run"),
        G_CALLBACK(gtk_cmd_allow_java), FALSE },

      { "WebAllowJSAction", NULL, N_("Allow Java_Script"), NULL,
        N_("Toggle allowing of javascript code to run"), 
        G_CALLBACK(gtk_cmd_allow_js), FALSE },

      { "WebPopupsAlwaysAction", NULL, N_("Allow Popups"), NULL,
        N_("Always allow popup windows"), 
        G_CALLBACK(gtk_cmd_allow_popups), FALSE }
};

static guint n_toggle_entries = G_N_ELEMENTS(toggle_entries);

/* Keep this in order, see radio_group_set_from_value */
static GtkRadioActionEntry image_radio_entries[] = {
      { "ViewImagesAlwaysAction", NULL, N_("_Always"), NULL,
        N_("View all images"), VIEW_IMAGES_ALWAYS },
      { "ViewImagesCurrentAction", NULL, N_("_From Current Server Only"), NULL,
        N_("View images originating from current server only"), VIEW_IMAGES_CURRENT },
      { "ViewImagesNeverAction", NULL, N_("_Never"),  NULL,
        N_("Don't view any images"), VIEW_IMAGES_NEVER }
};

static guint n_image_radio_entries = G_N_ELEMENTS (image_radio_entries);

/* Keep this in order, see radio_group_set_from_value */
static GtkRadioActionEntry cookie_radio_entries[] = {
      { "WebCookiesAlwaysAction", NULL, N_("A_lways Allow"), NULL,
        N_("Always accept cookies"), ACCEPT_COOKIES_ALWAYS },
      { "WebCookiesCurrentAction", NULL, N_("Allow _From Current Server Only"), NULL,
        N_("Only allow cookies from a page's own server"), ACCEPT_COOKIES_CURRENT },
      { "WebCookiesNeverAction", NULL, N_("_Never Allow"),  NULL,
        N_("Never accept cookies"), ACCEPT_COOKIES_NEVER }
};

static guint n_cookie_radio_entries = G_N_ELEMENTS (cookie_radio_entries);

static void
galeon_window_class_init (GaleonWindowClass *klass);
static void
galeon_window_gb_location_source_init (GbLocationSourceIface *iface);
static void
galeon_window_init (GaleonWindow *gs);
static void
galeon_window_finalize (GObject *object);
static void
galeon_window_dispose (GObject *object);
static void
galeon_window_show (GtkWidget *widget);
static gboolean
galeon_window_notebook_button_press_cb(GtkNotebook *notebook,
                               GdkEventButton *event,
                               GaleonWindow *window);
static gboolean
galeon_window_notebook_popup_menu_cb(GtkNotebook *notebook,
                             GaleonWindow *window);
static void
galeon_window_notebook_switch_page_cb (GtkNotebook *notebook,
                               GtkNotebookPage *page,
                               guint page_num,
                               GaleonWindow *window);
static void
galeon_window_bookmark_activated_cb (GObject *sender,
                             GbBookmarkEventActivated *ev,
                             GaleonWindow *w);

static void             
galeon_window_tab_detached_cb    (GulNotebook *notebook, gint page,
                          gint x, gint y, GaleonWindow *window);
static void
galeon_window_tabs_reordered_cb (GulNotebook *notebook, GaleonWindow *window);

static void             
galeon_window_tab_drag_data_received_cb (GtkWidget* widget, GdkDragContext *context,
                               gint x, gint y, GtkSelectionData *selection_data,
                               guint info, guint time, GtkWidget *child);

static void             
galeon_window_tab_added_cb  (GulNotebook *notebook, GtkWidget* child, 
                       GaleonWindow *window);

static void             
galeon_window_tab_removed_cb  (GulNotebook *notebook, GtkWidget* child, 
                         GaleonWindow *window);

static gboolean
galeon_window_tab_delete_cb  (GulNotebook *notebook, GtkWidget* child, 
                        GaleonWindow *window);

void /* yes, this is not static */
galeon_window_bookmark_activate (GaleonWindow *w, GbBookmarkEventActivated *ev);

static char *
galeon_window_gb_location_source_get_location (GbLocationSource *src);
static char *
galeon_window_gb_location_source_get_title (GbLocationSource *src);

static void
galeon_window_fullscreen (GaleonWindow *window);
static void
galeon_window_unfullscreen (GaleonWindow *window);

static gboolean 
galeon_window_key_press_event(GtkWidget *widget,
                        GdkEventKey *event);

static gboolean 
galeon_window_delete_event(GtkWidget *widget,
                     GdkEventAny *event);

static void
gtk_key_theme_changed_cb (GtkSettings  *settings,
                          GParamSpec   *pspec,
                          gpointer dummy);

/* static class variables */
static GdkColor _galeon_window_loading_tab_color;
static GdkColor _galeon_window_new_tab_color;
static GdkPixbufAnimation * _galeon_window_loading_animation;
static gboolean key_theme_is_emacs = FALSE;

static GObjectClass *parent_class = NULL;


G_DEFINE_TYPE_WITH_CODE (GaleonWindow, galeon_window, GTK_TYPE_WINDOW,
                   G_IMPLEMENT_INTERFACE (GB_TYPE_LOCATION_SOURCE,
                                    galeon_window_gb_location_source_init));

static void
galeon_window_class_init (GaleonWindowClass *klass)
{
        GObjectClass *object_class = G_OBJECT_CLASS (klass);
      GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
      char *tmp;
      GtkSettings *settings;
      
        parent_class = g_type_class_peek_parent (klass);

        object_class->finalize = galeon_window_finalize;
        object_class->dispose  = galeon_window_dispose;
      
      widget_class->show = galeon_window_show;
      widget_class->key_press_event = galeon_window_key_press_event;
      widget_class->delete_event = galeon_window_delete_event;

      /* initialize colors */
      tmp = eel_gconf_get_string (CONF_TABS_TABBED_LOADING_COLOR);
      gdk_color_parse (tmp, &_galeon_window_loading_tab_color);
      g_free (tmp);

      tmp = eel_gconf_get_string (CONF_TABS_TABBED_NEW_COLOR);
      gdk_color_parse (tmp, &_galeon_window_new_tab_color);
      g_free (tmp);

      tmp =  gul_general_user_file( "galeon-tab-loading.gif", FALSE );
      _galeon_window_loading_animation = 
            gdk_pixbuf_animation_new_from_file (tmp, NULL);
      g_free (tmp);

      /* initialize the listener for the key theme */
      settings = gtk_settings_get_default();
      g_signal_connect (settings,
                    "notify::gtk-key-theme-name",
                    G_CALLBACK (gtk_key_theme_changed_cb),
                    NULL);
      gtk_key_theme_changed_cb (settings, NULL, NULL);

      GaleonWindowSignals[ACTIVE_EMBED_CHANGED] = g_signal_new (
            "active-embed-changed", G_OBJECT_CLASS_TYPE (klass),  
            G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST | G_SIGNAL_RUN_CLEANUP,
                G_STRUCT_OFFSET (GaleonWindowClass, active_embed_changed), 
            NULL, NULL, 
            galeon_marshal_VOID__OBJECT_OBJECT,
            G_TYPE_NONE, 2, G_TYPE_OBJECT, G_TYPE_OBJECT);

      g_type_class_add_private (klass, sizeof (GaleonWindowPrivate));
}

static void
galeon_window_gb_location_source_init (GbLocationSourceIface *iface)
{
      iface->get_location = galeon_window_gb_location_source_get_location;
      iface->get_title = galeon_window_gb_location_source_get_title;
}


static void
gtk_key_theme_changed_cb (GtkSettings  *settings,
                          GParamSpec   *pspec,
                          gpointer dummy)
{
      gchar *key_theme_name;

      g_object_get (settings,
                  "gtk-key-theme-name", &key_theme_name,
                  NULL);
      if (key_theme_name && g_ascii_strcasecmp (key_theme_name, "Emacs") == 0)
      {
            key_theme_is_emacs = TRUE;
      }
      else
      {
            key_theme_is_emacs = FALSE;
      }
      g_free (key_theme_name);
}

/* The extra keybindings that aren't explictly associated with actions.
 * Come Gtk 2.4 there are better ways to do this ... (the <accelerator.../> tag
 * in the gtk_ui_manager xml file  */
struct keybinding {
      guint modifier;
      guint keyval;
      const gchar *action;
} extra_keybindings[] = {
      { GDK_CONTROL_MASK, GDK_KP_Add,      "ViewZoomInAction"  },
      { GDK_CONTROL_MASK, GDK_KP_Subtract, "ViewZoomOutAction" },
      { GDK_CONTROL_MASK, GDK_s,           "FileSaveAsAction"  }
};

static void
menubar_deactivate_cb (GtkWidget *menubar, gulong *handler_id)
{
      GaleonWindow *window;

      g_signal_handler_disconnect (menubar, *handler_id);
      gtk_menu_shell_deselect (GTK_MENU_SHELL(menubar));

      /* we could've switched back to normal mode in the meantime, let's not
       * hide the menubar in that case, it wouldn't be nice */
      window = GALEON_WINDOW(gtk_widget_get_toplevel (menubar));
      if (!(window->priv->chrome_mask & EMBED_CHROME_MENUBARON))
      {
            gtk_widget_hide (menubar->parent);
      }
}

/* very much copied from gtkmenubar.c(window_key_press_handler) */
static gboolean
is_menu_bar_accel (GtkWidget *widget, GdkEventKey *event)
{
      char *accel = NULL;
      gboolean retval = FALSE;

      g_object_get (gtk_widget_get_settings (widget),
                  "gtk-menu-bar-accel", &accel,
                  NULL);

      if (accel)
      {
            guint keyval = 0;
            GdkModifierType mods = 0;

            gtk_accelerator_parse (accel, &keyval, &mods);

            if (keyval == 0)
                  g_warning ("Failed to parse menu bar accelerator '%s'\n", accel);

            retval = (event->keyval == keyval && 
                    (event->state & gtk_accelerator_get_default_mod_mask()) == 
                    (mods & gtk_accelerator_get_default_mod_mask()));

            g_free (accel);
      }

      return retval;
}

static gboolean 
galeon_window_key_press_event (GtkWidget *window,
                         GdkEventKey *event)
{
      GaleonWindowPrivate *priv = GALEON_WINDOW(window)->priv;

      /* In an attempt to get the mozembed playing nice with things like emacs keybindings
       * we are passing important events to the focused child widget before letting the window's
       * base handler see them. This is *completely against* stated gtk2 policy but the 
       * 'correct' behaviour is exceptionally useless. We need to keep an eye out for 
       * unexpected consequences of this decision. IME's should be a high concern, but 
       * considering that the IME folks complained about the upside-down event propagation
       * rules, we might be doing them a favour.
       */

      gboolean shortcircuit = FALSE;
      gboolean force_chain  = FALSE;
      gboolean handled = FALSE;
      guint modifier = event->state & gtk_accelerator_get_default_mod_mask ();
      guint i;

      if (event->keyval == GDK_Escape)
      {
            /* Always pass Escape to both the widget, and the parent */
            shortcircuit = TRUE;
            force_chain = TRUE;
      }
      else if (key_theme_is_emacs && 
             (modifier == GDK_CONTROL_MASK) && event->length > 0 &&
             /* But don't pass Ctrl+Enter twice */
             event->keyval != GDK_Return)
      {
            /* Pass CTRL+letter characters to the widget */
            shortcircuit = TRUE;
      }

      if (shortcircuit)
      {
            GtkWidget *widget = gtk_window_get_focus (GTK_WINDOW (window));

            if (GTK_IS_WIDGET (widget))
            {
                  handled = gtk_widget_event (widget, (GdkEvent*)event);
            }

            if (handled && !force_chain)
            {
                  return handled;
            }
      }

      /* Handle accelerators that we want bound, but aren't associated with
       * an action */
      for (i = 0; i < G_N_ELEMENTS (extra_keybindings); i++)
      {
            if (modifier == extra_keybindings[i].modifier &&
                event->keyval == extra_keybindings[i].keyval)
            {
                  GtkAction * action = gtk_action_group_get_action 
                        (priv->action_group, 
                         extra_keybindings[i].action);
                  gtk_action_activate (action);
                  return TRUE;
            }
      }

      if (is_menu_bar_accel (window, event) &&
          priv->menubar && priv->menubar->parent &&
          !GTK_WIDGET_VISIBLE(priv->menubar->parent))
      {
            /* When F10 is pressed gtk+ automatically opens the menu if the
             * menubar is visible, but when the menubar is not visible
             * (think fullscreen or popup windows) we show it manually and
             * hide again when the user activates or otherwise dismisses
             * the menu.
             */

            gulong *handler_id = g_new(gulong, 1);

            *handler_id = g_signal_connect_data (priv->menubar, "deactivate",
                                         G_CALLBACK(menubar_deactivate_cb),
                                         handler_id, (GClosureNotify)g_free, 0);
            gtk_widget_show (GTK_WIDGET(priv->menubar->parent));

            /* now that the menubar is visible again, re-emit the key press
             * and let the menubar do its job */
            gtk_widget_event (window, (GdkEvent*)event);

            return TRUE;
      }

      return GTK_WIDGET_CLASS(parent_class)->key_press_event(window, event);
}

static gboolean
galeon_window_delete_event (GtkWidget *widget, GdkEventAny *event)
{
      GaleonWindow *window = GALEON_WINDOW (widget);

      if (!galeon_window_can_close (window))
      {
            return TRUE;
      }

      return gul_gui_widget_hide_now (widget);
}

static gboolean
galeon_window_state_event_cb (GtkWidget *widget,
                        GdkEventWindowState *event,
                        gpointer data)
{
      if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN)
      {
            GaleonWindow *window = GALEON_WINDOW (widget);
            if (event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN)
            {
                  galeon_window_fullscreen (window);
            }
            else
            {
                  galeon_window_unfullscreen (window);
            }
      }
      return FALSE;
}


static gboolean
confirm_close_with_modified_forms (GaleonWindow *window, GaleonTab *tab)
{
      GtkWidget *dialog;
      int response;

      /* Jump to the modified tab with modified forms */
      gtk_window_present (GTK_WINDOW (window));
      galeon_window_jump_to_tab (window, tab);

      dialog = hig_alert_new (GTK_WINDOW (window),
                        GTK_DIALOG_MODAL,
                        HIG_ALERT_CONFIRMATION,
                        _("Discard changes?"),
                        _("This page contains changes that have not been submitted."),
                        GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                        _("_Discard Changes"), GTK_RESPONSE_OK,
                        NULL);

      response = gtk_dialog_run (GTK_DIALOG (dialog));

      gtk_widget_destroy (dialog);

      return response == GTK_RESPONSE_OK;
}


gboolean
galeon_window_can_close (GaleonWindow *window)
{
      GList *tabs, *l;
      gboolean allow_close = TRUE;

      tabs = galeon_window_get_tabs (window);
      for (l = tabs; l != NULL; l = l->next)
      {
            GaleonTab *tab = (GaleonTab *) l->data;
            GaleonEmbed *embed;

            g_return_val_if_fail (GALEON_IS_TAB (tab), FALSE);

            embed = galeon_tab_get_embed (tab);
            g_return_val_if_fail (GALEON_IS_EMBED (embed), FALSE);

            if (galeon_embed_has_modified_forms (embed) && 
                confirm_close_with_modified_forms (window, tab) == FALSE)
            {
                  allow_close = FALSE;
                  break;
            }
      }
      g_list_free (tabs);

      return allow_close;
}

static gboolean
focus_in_event_cb(GaleonWindow *window, GdkEventFocus *event)
{
      galeon_shell_set_active_window(galeon_shell, window); 
      return FALSE;
}

static void
setup_gtk_window (GaleonWindow *window)
{
      g_signal_connect (G_OBJECT(window), "window_state_event",
                    G_CALLBACK (galeon_window_state_event_cb), NULL);
      
      g_signal_connect (G_OBJECT(window),
                    "focus-in-event",
                    G_CALLBACK (focus_in_event_cb), NULL);
}

static void
tabbed_position_gconf_changed_cb(GConfClient *client,
                             guint cnxn_id,
                             GConfEntry *entry,
                             GtkNotebook *notebook)
{
      GtkPositionType position = eel_gconf_get_integer (CONF_TABS_TABBED_EDGE);    
      gtk_notebook_set_tab_pos (notebook, position);
}


static void
tabbed_always_show_gconf_changed_cb(GConfClient *client,
                            guint cnxn_id,
                            GConfEntry *entry,
                            GtkNotebook *notebook)
{
      GtkPositionType policy = eel_gconf_get_boolean (CONF_TABS_TABBED_ALWAYS_SHOW)
            ? GTK_POLICY_ALWAYS
            : GTK_POLICY_AUTOMATIC;
      gul_notebook_set_policy (GUL_NOTEBOOK (notebook), policy);
}

static GtkNotebook *
setup_notebook (GaleonWindow *window)
{
      GtkNotebook *notebook;
      GtkPolicyType policy;
      GtkPositionType position = eel_gconf_get_integer (CONF_TABS_TABBED_EDGE);

      policy = eel_gconf_get_boolean (CONF_TABS_TABBED_ALWAYS_SHOW)
             ? GTK_POLICY_ALWAYS
             : GTK_POLICY_AUTOMATIC;
      
      notebook = GTK_NOTEBOOK (gul_notebook_new ());
      gtk_notebook_set_scrollable (notebook, TRUE);
      gtk_notebook_set_show_border (notebook, FALSE);
      gtk_notebook_set_tab_pos (notebook, position);
      gul_notebook_set_policy (GUL_NOTEBOOK (notebook), policy);
      gtk_notebook_popup_disable (notebook);

      g_signal_connect_after(G_OBJECT(notebook), "button-press-event",
                         G_CALLBACK(
                        galeon_window_notebook_button_press_cb),
                        window);

      g_signal_connect(G_OBJECT(notebook), "popup-menu",
                   G_CALLBACK(
                        galeon_window_notebook_popup_menu_cb),
                        window);

      g_signal_connect_after (G_OBJECT (notebook), "switch_page",
                        G_CALLBACK (
                        galeon_window_notebook_switch_page_cb),
                        window);

      g_signal_connect (G_OBJECT (notebook), "tab_detached", 
                    G_CALLBACK (galeon_window_tab_detached_cb), 
                    window);
      g_signal_connect (G_OBJECT (notebook), "tabs_reordered", 
                    G_CALLBACK (galeon_window_tabs_reordered_cb), 
                    window);

      g_signal_connect (G_OBJECT (notebook), "tab_added", 
                    G_CALLBACK (galeon_window_tab_added_cb), 
                    window);

      g_signal_connect (G_OBJECT (notebook), "tab_removed", 
                    G_CALLBACK (galeon_window_tab_removed_cb), 
                    window);

      g_signal_connect (G_OBJECT (notebook), "tab_delete", 
                    G_CALLBACK (galeon_window_tab_delete_cb), 
                    window);
 
      galeon_dnd_url_list_drag_dest_set_with_flags (GTK_WIDGET(notebook),
                                          GTK_DEST_DEFAULT_MOTION |
                                          GTK_DEST_DEFAULT_DROP);
 
      g_signal_connect (G_OBJECT(notebook), "drag_data_received",
                    G_CALLBACK(galeon_window_tab_drag_data_received_cb),
                    NULL);
 
      galeon_notification_add(CONF_TABS_TABBED_EDGE,
                        (GConfClientNotifyFunc)tabbed_position_gconf_changed_cb,
                        notebook, &window->priv->notifiers);

      galeon_notification_add(CONF_TABS_TABBED_ALWAYS_SHOW,
                        (GConfClientNotifyFunc)tabbed_always_show_gconf_changed_cb,
                        notebook, &window->priv->notifiers);
    
      gtk_widget_show (GTK_WIDGET (notebook));

      return notebook;
}

static void
setup_bookmarks_menu (GaleonWindow *window, GbBookmarkSet *bs)
{
      GaleonWindowPrivate *p = window->priv;
      GtkWidget *menu_item;
      GtkWidget *menu_shell;
      
      menu_item = gtk_ui_manager_get_widget (window->merge,
                                     BOOKMARK_MENU_PATH);
      menu_shell = gtk_menu_item_get_submenu (GTK_MENU_ITEM (menu_item));
      
      p->bookmarks_menu = gb_gtk_menu_new (bs->root, GTK_MENU_SHELL(menu_shell));
      gb_gtk_menu_set_location_source (p->bookmarks_menu, GB_LOCATION_SOURCE (window));
      
      g_signal_connect (p->bookmarks_menu, "bookmark-activated", 
                    G_CALLBACK (galeon_window_bookmark_activated_cb), window);
      gb_gtk_menu_set_statusbar (p->bookmarks_menu, GTK_STATUSBAR (p->statusbar));
}

static void
galeon_window_add_bookmark_toolbar (GbGtkToolbarSet *gts, GbFolder *f, GtkWidget *tb, gpointer data)
{
      GaleonWindow *window = data;
      static guint ihatebonoboui = 0;

      char *name = g_strdup_printf("BookmarksToolbar%d", ihatebonoboui++);
      GtkWidget *item = egg_dock_item_new(name, "Bookmarks Toolbar",
                                  EGG_DOCK_ITEM_BEH_NORMAL);
      g_free(name);

      eel_gconf_get_boolean(GCONF_DETACH_TOOLBAR) ?
            egg_dock_item_unlock(EGG_DOCK_ITEM(item)) :
            egg_dock_item_lock(EGG_DOCK_ITEM(item));

      egg_dock_add_item (EGG_DOCK(window->egg_dock),
                        EGG_DOCK_ITEM(item),
                        EGG_DOCK_BOTTOM);
      gtk_container_add(GTK_CONTAINER(item), tb);
      gtk_widget_show(item);

      g_signal_connect_swapped (tb, "hide", 
                          G_CALLBACK (gtk_widget_hide), item);
      g_signal_connect_swapped (tb, "show", 
                          G_CALLBACK (gtk_widget_show), item);
}

static void
galeon_window_remove_bookmark_toolbar (GbGtkToolbarSet *gts, GbFolder *f, GtkWidget *tb, gpointer data)
{
      /* TODO: this is a hack just to keep going while we still use BonoboDock */
      if (tb->parent)
      {
            if (tb->parent->parent)
            {
                  gtk_container_remove (GTK_CONTAINER (tb->parent->parent), tb->parent);
            }
      }
}

static GbGtkToolbarSet *
setup_bookmarks_toolbar (GaleonWindow *window, GbBookmarkSet *bs)
{
      GbGtkToolbarSet *toolbar;
      
      toolbar = gb_gtk_toolbar_set_new (bs, galeon_window_add_bookmark_toolbar, 
                                galeon_window_remove_bookmark_toolbar, window);
      gb_gtk_toolbar_set_set_location_source (toolbar, GB_LOCATION_SOURCE (window));
      gb_gtk_toolbar_set_set_statusbar (toolbar, GTK_STATUSBAR (window->priv->statusbar));
      
      g_signal_connect (toolbar, "bookmark-activated", 
                    G_CALLBACK (galeon_window_bookmark_activated_cb), window);

      return toolbar;
}

static void
update_layout_toggles(GaleonWindow *window)
{
      EmbedChromeMask mask = window->priv->chrome_mask;

      window->priv->ignore_layout_toggles = TRUE;

      gtk_toggle_action_set_active(TOGGLE_ITEM(VIEW_TOOLBAR_ACTION),
                             mask & EMBED_CHROME_TOOLBARON);
      gtk_toggle_action_set_active(TOGGLE_ITEM(VIEW_BMTOOLBARS_ACTION),
                             mask & EMBED_CHROME_PERSONALTOOLBARON);
      gtk_toggle_action_set_active(TOGGLE_ITEM(VIEW_STATUSBAR_ACTION),
                             mask & EMBED_CHROME_STATUSBARON);
      gtk_toggle_action_set_active(TOGGLE_ITEM(VIEW_SIDEBAR_ACTION),
                             mask & EMBED_CHROME_SIDEBARON);
      gtk_toggle_action_set_active(TOGGLE_ITEM(VIEW_FULLSCREEN_ACTION),
                             mask & EMBED_CHROME_OPENASFULLSCREEN);

      window->priv->ignore_layout_toggles = FALSE;
}

static void
allow_setting_gconf_changed_cb(GConfClient *client,
                         guint cnxn_id,
                         GConfEntry *entry,
                         GaleonWindow *window)
{
      gboolean java_enabled;

      gtk_toggle_action_set_active (TOGGLE_ITEM(WEB_POPUPS_ALWAYS_ACTION),
                              eel_gconf_get_boolean(CONF_FILTERING_ALLOW_POPUPS));
      update_permission_control(window, NULL);

      gtk_toggle_action_set_active(TOGGLE_ITEM(WEB_ALLOW_JS_ACTION),
                             eel_gconf_get_boolean(CONF_FILTERING_JAVASCRIPT_ENABLED));

      java_enabled = eel_gconf_get_boolean(CONF_FILTERING_JAVA_ENABLED);

      gtk_toggle_action_set_active(TOGGLE_ITEM(WEB_ALLOW_JAVA_ACTION), java_enabled);

      g_object_set (ACTION_ITEM(WEB_JAVA_CONSOLE_ACTION),
                  "sensitive", java_enabled, NULL);
}

static void
radio_group_set_from_value (GaleonWindow *window, GtkRadioActionEntry *entries,
                      int n_entries, GConfValue *value)
{
      GtkAction *action;
      int val = gconf_value_get_int(value);
      g_return_if_fail (val < n_entries);
      g_return_if_fail (entries[val].value == val);

      action = gtk_action_group_get_action(window->priv->action_group, entries[val].name);

      if (! gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
      {
            gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
      }
}

static void
web_cookies_policy_changed (GtkRadioAction *action, GtkRadioAction *current, 
                      GaleonWindow *window)
{
      /* The current value is the gconf value */
      gint val = gtk_radio_action_get_current_value (action);
      eel_gconf_set_integer (CONF_PERSISTENT_COOKIES_BEHAVIOR, val);
}

static void
accept_cookies_gconf_changed_cb(GConfClient *client,
                        guint cnxn_id,
                        GConfEntry *entry,
                        GaleonWindow *window)
{
      radio_group_set_from_value (window, cookie_radio_entries,
                            n_cookie_radio_entries, entry->value);
}

static void
setup_web_menu (GaleonWindow *window)
{
      GConfValue *gcvalue;
      gcvalue = eel_gconf_get_value(CONF_PERSISTENT_COOKIES_BEHAVIOR);
      radio_group_set_from_value (window, cookie_radio_entries,
                            n_cookie_radio_entries, gcvalue);
      gconf_value_free (gcvalue);

      galeon_notification_add(CONF_PERSISTENT_COOKIES_BEHAVIOR, 
                        (GConfClientNotifyFunc)accept_cookies_gconf_changed_cb, 
                        window, &window->priv->notifiers);

      gtk_toggle_action_set_active(TOGGLE_ITEM(WEB_POPUPS_ALWAYS_ACTION),
                             eel_gconf_get_boolean(CONF_FILTERING_ALLOW_POPUPS));
      gtk_toggle_action_set_active(TOGGLE_ITEM(WEB_ALLOW_JS_ACTION),
                             eel_gconf_get_boolean(CONF_FILTERING_JAVASCRIPT_ENABLED));
      gtk_toggle_action_set_active(TOGGLE_ITEM(WEB_ALLOW_JAVA_ACTION),
                             eel_gconf_get_boolean(CONF_FILTERING_JAVA_ENABLED));

      galeon_notification_add(CONF_FILTERING_ALLOW_POPUPS,
                        (GConfClientNotifyFunc)allow_setting_gconf_changed_cb,
                        window, &window->priv->notifiers);
      galeon_notification_add(CONF_FILTERING_JAVASCRIPT_ENABLED,
                        (GConfClientNotifyFunc)allow_setting_gconf_changed_cb,
                        window, &window->priv->notifiers);
      galeon_notification_add(CONF_FILTERING_JAVA_ENABLED,
                        (GConfClientNotifyFunc)allow_setting_gconf_changed_cb,
                        window, &window->priv->notifiers);
}

static void
view_images_policy_changed (GtkRadioAction *action, GtkRadioAction *current, 
                      GaleonWindow *window)
{
      /* The current value is the gconf value */
      gint val = gtk_radio_action_get_current_value (action);
      eel_gconf_set_integer (CONF_FILTERING_IMAGE_LOADING_TYPE, val);
}

static void
view_images_gconf_changed_cb(GConfClient *client,
                         guint cnxn_id,
                       GConfEntry *entry,
                       GaleonWindow *window)
{
      radio_group_set_from_value (window, image_radio_entries,
                            n_image_radio_entries, entry->value);
}

static void
setup_images_menu(GaleonWindow *window)
{
      GConfValue *gcvalue;
      gcvalue = eel_gconf_get_value(CONF_FILTERING_IMAGE_LOADING_TYPE);
      radio_group_set_from_value (window, image_radio_entries,
                            n_image_radio_entries, gcvalue);
      gconf_value_free (gcvalue);

      galeon_notification_add(CONF_FILTERING_IMAGE_LOADING_TYPE, 
                        (GConfClientNotifyFunc)view_images_gconf_changed_cb, 
                        window, &window->priv->notifiers);
}

static void
sidebar_close_requested_cb (GaleonSidebar *sidebar, 
                      GaleonWindow *window)
{
      GtkToggleAction *action = TOGGLE_ITEM(VIEW_SIDEBAR_ACTION);

      gtk_toggle_action_set_active(action, FALSE);
}

static void
sidebar_page_changed_cb (GaleonSidebar *sidebar, 
                   const char *page_id, 
                   GaleonWindow *window)
{
      GaleonEmbed *embed;

      embed = galeon_window_get_active_embed (window);

      if (strcmp (page_id, "history") == 0)
      {
            window->priv->history_sidebar = 
                  history_dialog_new (embed, TRUE);
      
            galeon_sidebar_set_content 
                  (sidebar, 
                   G_OBJECT(window->priv->history_sidebar));
      }
      else if (strcmp (page_id, "bookmarks") == 0)
      {
            GtkWidget *w;
            if (!window->priv->bookmarks_sidebar)
            {
                  GbEditorDockable *e;
                  GbBookmarkSet *set;
                  
                  set = galeon_shell_get_bookmark_set (galeon_shell);
                  if (!set) return;
            
                  e = gb_editor_dockable_new_for_set (set);
                  
                  gb_editor_set_location_source (GB_EDITOR (e), GB_LOCATION_SOURCE (window));

                  g_signal_connect (e, "bookmark-activated", 
                                G_CALLBACK (galeon_window_bookmark_activated_cb), window);
                  window->priv->bookmarks_sidebar = e;
            }
            w = gb_editor_get_main_widget (GB_EDITOR (window->priv->bookmarks_sidebar));
            gtk_widget_show (w);
            galeon_sidebar_set_content (sidebar, G_OBJECT (w));
      }
}

static GtkWidget *
setup_sidebar (GaleonWindow *window)
{
      GtkWidget *hpaned;
      GtkWidget *sidebar;
      GaleonSidebars *sidebars;

      hpaned = gtk_hpaned_new ();
      gtk_widget_show (hpaned);

      sidebar = galeon_sidebar_new ();

      g_signal_connect (G_OBJECT(sidebar),
                    "close_requested",
                    G_CALLBACK (sidebar_close_requested_cb),
                    window);
      
      galeon_sidebar_add_page (GALEON_SIDEBAR(sidebar), 
                         _("Bookmarks"), "bookmarks", FALSE);
      galeon_sidebar_add_page (GALEON_SIDEBAR(sidebar), 
                         _("History"), "history", FALSE);

      g_signal_connect (sidebar, "page_changed",
                    G_CALLBACK (sidebar_page_changed_cb),
                    window);

      gtk_paned_add1 (GTK_PANED(hpaned), 
                  sidebar);
      gtk_paned_add2 (GTK_PANED(hpaned),
                  GTK_WIDGET(window->priv->notebook));

      gul_state_monitor_paned (hpaned, STATE_SIDEBAR_SIZE,
                           STATE_SIDEBAR_SIZE_DEFAULT);

      sidebars = galeon_shell_get_sidebars (galeon_shell);
      galeon_sidebars_init_window_sidebar (sidebars, GALEON_SIDEBAR (sidebar));

      window->priv->sidebar = sidebar;
      
      return hpaned;
}

static void
statusbar_request_cb (Statusbar *statusbar, StatusbarRequest request, GaleonWindow *window)
{
      switch (request)
      {
      case STATUSBAR_SHOW_SECURITY_INFO:
            galeon_window_show_page_info (window, PAGE_INFO_SECURITY);
            break;
      }
}


static void
ppview_toolbar_print_cb (PPViewToolbar *toolbar, GaleonWindow *window)
{
      gtk_action_activate (ACTION_ITEM (FILE_PRINT_ACTION));
}

static void
menu_item_select_cb (GtkMenuItem *proxy,
                 GaleonWindow *window)
{
      GtkAction *action;
      char *message;

      action = g_object_get_data (G_OBJECT (proxy),  "gtk-action");
      g_return_if_fail (action != NULL);
      
      g_object_get (G_OBJECT (action), "tooltip", &message, NULL);
      if (message)
      {
            gtk_statusbar_push (GTK_STATUSBAR (window->priv->statusbar),
                            1, message);
            g_free (message);
      }
}

static void
menu_item_deselect_cb (GtkMenuItem *proxy,
                   GaleonWindow *window)
{
      gtk_statusbar_pop (GTK_STATUSBAR (window->priv->statusbar), 1);
}

static void
ui_manager_disconnect_proxy_cb (GtkUIManager *manager,
                        GtkAction *action,
                        GtkWidget *proxy,
                        GaleonWindow *window)
{
      if (GTK_IS_MENU_ITEM (proxy))
      {
            g_signal_handlers_disconnect_by_func
                  (proxy, G_CALLBACK (menu_item_select_cb), window);
            g_signal_handlers_disconnect_by_func
                  (proxy, G_CALLBACK (menu_item_deselect_cb), window);
      }
}

static void
ui_manager_connect_proxy_cb (GtkUIManager *manager,
                      GtkAction *action,
                      GtkWidget *proxy,
                      GaleonWindow *window)
{
      if (GTK_IS_MENU_ITEM (proxy))
      {
            g_signal_connect (proxy, "select",
                          G_CALLBACK (menu_item_select_cb), window);
            g_signal_connect (proxy, "deselect",
                          G_CALLBACK (menu_item_deselect_cb), window);
      }
}

static void
ui_manager_widget_add (GtkUIManager *merge, GtkWidget *widget, GaleonWindow *window)
{
      if (GTK_IS_MENU_SHELL(widget))
      {
              GtkWidget *item;
            window->priv->menubar = widget;
            gtk_widget_show(widget);
            LOG( "Adding menu bar" );

            item = egg_dock_item_new("EggMenu",
                               "Menubar",
                               EGG_DOCK_ITEM_BEH_NORMAL);
            eel_gconf_get_boolean(GCONF_DETACH_MENUBAR) ?
                  egg_dock_item_unlock(EGG_DOCK_ITEM(item)) :
                  egg_dock_item_lock(EGG_DOCK_ITEM(item));

            egg_dock_add_item(EGG_DOCK(window->egg_dock),
                          EGG_DOCK_ITEM(item),
                          EGG_DOCK_TOP);
            gtk_container_add(GTK_CONTAINER(item), widget);
            gtk_widget_show(item);
      }
      else if (GTK_IS_TOOLBAR(widget))
      {
              GtkWidget *item;
            gtk_widget_show (widget);
            LOG( "Adding toolbar" );
            item = egg_dock_item_new("PPVToolbar",
                               "Print Preview Toolbar",
                               EGG_DOCK_ITEM_BEH_NORMAL);
            eel_gconf_get_boolean(GCONF_DETACH_TOOLBAR) ?
                  egg_dock_item_unlock(EGG_DOCK_ITEM(item)) :
                  egg_dock_item_lock(EGG_DOCK_ITEM(item));

            egg_dock_add_item(EGG_DOCK(window->egg_dock),
                          EGG_DOCK_ITEM(item),
                          EGG_DOCK_TOP);
            gtk_container_add(GTK_CONTAINER(item), widget);
            /* Don't show dock_item. Controlled by ppvtoolbar object */
      }
      else
      {
            g_warning ("unexpected widget in egg_widget_add");
      }
}

static void
toolbar_style_gconf_changed_cb(GConfClient *client,
                         guint cnxn_id,
                         GConfEntry *entry,
                         GaleonWindow *window)
{
      gint i;
      EggToolbarsModel *model;
      GtkToolbar *ppvtb;
      EggTbModelFlags flags;
      GtkToolbarStyle style = GTK_TOOLBAR_BOTH_HORIZ;

      gchar *override_style = eel_gconf_get_string(CONF_TOOLBAR_STYLE);

      if (!override_style ||
          g_ascii_strcasecmp(override_style, "system") == 0)
      {
            flags = 0;
      }
      else if (g_ascii_strcasecmp(override_style, "icons_only") == 0)
      {
            flags = EGG_TB_MODEL_ICONS_ONLY;
            style = GTK_TOOLBAR_ICONS;
      }
      else if (g_ascii_strcasecmp(override_style, "text_only") == 0)
      {
            flags = EGG_TB_MODEL_TEXT_ONLY;
            style = GTK_TOOLBAR_TEXT;
      }
      else if (g_ascii_strcasecmp(override_style, "text_below") == 0)
      {
            flags = EGG_TB_MODEL_ICONS_TEXT;
            style = GTK_TOOLBAR_BOTH;
      }
      else if (g_ascii_strcasecmp(override_style, "text_beside") == 0)
      {
            flags = EGG_TB_MODEL_ICONS_TEXT_HORIZ;
            style = GTK_TOOLBAR_BOTH_HORIZ;
      }
      else
      {
            g_warning("Unrecognised value for toolbar_override_style");
            flags = 0;
      }
      g_free (override_style);

      model =     galeon_shell_get_toolbars_model(galeon_shell);

      for (i=0 ; i<egg_toolbars_model_n_toolbars(model) ; i++)
      {
            egg_toolbars_model_set_flags(model, i, flags);
      }

      ppvtb = GTK_TOOLBAR(gtk_ui_manager_get_widget(window->merge,
                                          "/pptoolbar"));
      g_return_if_fail (GTK_IS_TOOLBAR (ppvtb));
      if (flags != 0)
      {
            gtk_toolbar_set_style(ppvtb, style);
      }
      else
      {
            gtk_toolbar_unset_style(ppvtb);
      }
}


void
galeon_window_update_edit_actions_sensitivity (GaleonWindow *window, gboolean hide)
{
      GtkWidget *widget = gtk_window_get_focus (GTK_WINDOW (window));
      GtkActionGroup *action_group;
      GtkAction *action;
      gboolean can_copy, can_cut, can_paste;

      /* Don't update the sensitivity if the tearoffs are enabled
       * we can't keep them in sync when the menu is torn off */
      if (gtk_ui_manager_get_add_tearoffs (window->merge))
      {
            return;
      }


      if (GTK_IS_EDITABLE (widget))
      {
            gboolean has_selection;

            has_selection = gtk_editable_get_selection_bounds
                  (GTK_EDITABLE (widget), NULL, NULL);

            can_copy = has_selection;
            can_cut = has_selection;
            can_paste = TRUE;
      }
      else
      {
            GaleonEmbed *embed;

            embed = galeon_window_get_active_embed (window);
            g_return_if_fail (embed != NULL);

            can_copy = galeon_embed_selection_can_copy (embed);
            can_cut  = galeon_embed_selection_can_cut (embed);
            can_paste = galeon_embed_can_paste (embed);
      }

      action_group = window->priv->action_group;

      action = gtk_action_group_get_action (action_group, "EditCopyAction");
      g_object_set (action, "sensitive", can_copy, "visible", !hide || can_copy, NULL);
      action = gtk_action_group_get_action (action_group, "EditCutAction");
      g_object_set (action, "sensitive", can_cut, "visible", !hide || can_cut, NULL);
      action = gtk_action_group_get_action (action_group, "EditPasteAction");
      g_object_set (action, "sensitive", can_paste, "visible", !hide || can_paste, NULL);
}

void
galeon_window_enable_edit_actions_sensitivity (GaleonWindow *window)
{
      GtkActionGroup *action_group;
      GtkAction *action;

      action_group = window->priv->action_group;
      action = gtk_action_group_get_action (action_group, "EditCopyAction");
      g_object_set (action, "sensitive", TRUE, "visible", TRUE, NULL);
      action = gtk_action_group_get_action (action_group, "EditCutAction");
      g_object_set (action, "sensitive", TRUE, "visible", TRUE, NULL);
      action = gtk_action_group_get_action (action_group, "EditPasteAction");
      g_object_set (action, "sensitive", TRUE, "visible", TRUE, NULL);
}

static gboolean
edit_menu_show_cb (GtkWidget *menu,
                 GaleonWindow *window)
{
      galeon_window_update_edit_actions_sensitivity (window, FALSE);
      return FALSE;
}

static void
edit_menu_hide_cb (GtkWidget *menu,
               GaleonWindow *window)
{
      galeon_window_enable_edit_actions_sensitivity (window);
}

static void
setup_edit_menu (GaleonWindow *window)
{
      GtkWidget *edit_menu_item, *edit_menu;

      edit_menu_item = gtk_ui_manager_get_widget
            (GTK_UI_MANAGER (window->merge), "/menubar/Edit");
      edit_menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (edit_menu_item));

      g_signal_connect (edit_menu, "show",
                    G_CALLBACK (edit_menu_show_cb), window);
      g_signal_connect (edit_menu, "hide",
                    G_CALLBACK (edit_menu_hide_cb), window);
}

static void
permission_changed_cb (GaleonEmbedShell *ges, GaleonWindow *window)
{
      update_permission_control (window, NULL);
}

static void
galeon_window_init (GaleonWindow *window)
{
      GtkToggleAction *offline_action;
      GaleonWindowPrivate *p;
      GbBookmarkSet *bs;
      Session *session;
      gchar *ui_file;
      GtkAction *act;
      EggDockItem *dock_item;

      session = galeon_shell_get_session (galeon_shell);

        window->priv = GALEON_WINDOW_GET_PRIVATE (window);
      p = window->priv;
      p->embed_popup = NULL;
      p->active_tab = NULL;
      p->chrome_mask = 0;
      p->ignore_layout_toggles = FALSE;
      p->closing = FALSE;
      p->has_default_size = FALSE;
      p->recent_history = galeon_window_recent_history_new ();

      /* Setup the window */
      setup_gtk_window(window);

      /* Setup the egg components */
      p->main_area = gtk_vbox_new(FALSE, 0);
      gtk_widget_show(p->main_area);
      window->egg_dock = G_OBJECT(egg_dock_new());
      gtk_widget_show(GTK_WIDGET(window->egg_dock));
      gtk_box_pack_start(GTK_BOX(p->main_area),
                           GTK_WIDGET(window->egg_dock), FALSE, FALSE, 0);

      p->action_group = gtk_action_group_new ("MainActions");
      gtk_action_group_set_translation_domain (p->action_group, NULL);
      gtk_action_group_add_actions (p->action_group, entries,
                              n_entries, window);
      
      gtk_action_group_add_toggle_actions (p->action_group, toggle_entries,
                                   n_toggle_entries, window);

      gtk_action_group_add_radio_actions (p->action_group, image_radio_entries,
                                  n_image_radio_entries, 0,
                                  G_CALLBACK (view_images_policy_changed),
                                  window);

      gtk_action_group_add_radio_actions (p->action_group, cookie_radio_entries,
                                  n_cookie_radio_entries, 0,
                                  G_CALLBACK (web_cookies_policy_changed),
                                  window);

      /* connect offline action */
      offline_action = TOGGLE_ITEM(FILE_OFFLINE_ACTION);
      set_offline_action_state (offline_action,
                            eel_gconf_get_boolean (CONF_GENERAL_OFFLINE));
      galeon_notification_add(CONF_GENERAL_OFFLINE,
                        gtk_cmd_gconf_toggle_monitor, 
                        offline_action, &window->priv->notifiers);
      /* keep it around for statusbar */

      window->merge = gtk_ui_manager_new ();
      g_signal_connect(window->merge, "add_widget", 
                   G_CALLBACK(ui_manager_widget_add), window);
      g_signal_connect (window->merge, "connect_proxy",
                    G_CALLBACK (ui_manager_connect_proxy_cb), window);
      g_signal_connect (window->merge, "disconnect_proxy",
                    G_CALLBACK (ui_manager_disconnect_proxy_cb), window);
      gtk_ui_manager_set_add_tearoffs (window->merge,
                   eel_gconf_get_boolean ("/desktop/gnome/interface/menus_have_tearoff"));

      gtk_ui_manager_insert_action_group(window->merge, p->action_group, 0);

      /* Setup any other properties that we need */
      act = gtk_action_group_get_action (p->action_group, "ViewEncodingMenuAction");
      g_object_set (act, "hide_if_empty", FALSE, NULL);

      act = gtk_action_group_get_action (p->action_group, VIEW_FULLSCREEN_ACTION);
      g_object_set (act, "short_label", _("Fullscreen"), NULL);
      act = gtk_action_group_get_action (p->action_group, FILE_PRINT_ACTION);
      g_object_set (act, "short_label", _("Print"), NULL);
      act = gtk_action_group_get_action (p->action_group, "FileSaveAsAction");
      g_object_set (act, "short_label", _("Save As"), NULL);
      act = gtk_action_group_get_action (p->action_group, "EditFindAction");
      g_object_set (act, "short_label", _("Find"), NULL);

      /* Create all the special actions that we need */
      {
            act = g_object_new (GALEON_TYPE_ACTION_NAVIGATION,
                            "name", "GoBack",
                            "window", window,
                            "direction", GALEON_NAVIGATION_DIRECTION_BACK,
                            NULL);
            gtk_action_group_add_action_with_accel (p->action_group, act, "<alt>Left");
            g_object_unref (act);

            act = g_object_new (GALEON_TYPE_ACTION_NAVIGATION,
                            "name", "GoBackWithArrow",
                            "window", window,
                            "direction", GALEON_NAVIGATION_DIRECTION_BACK,
                            "show_arrow", TRUE,
                            /* "short_label", _("Back History"), */
                            NULL);
            gtk_action_group_add_action (p->action_group, act);
            g_object_unref (act);

            act = g_object_new (GALEON_TYPE_ACTION_NAVIGATION,
                            "name", "GoForward",
                            "window", window,
                            "direction", GALEON_NAVIGATION_DIRECTION_FORWARD,
                            NULL);
            gtk_action_group_add_action_with_accel (p->action_group, act, "<alt>Right");
            g_object_unref (act);

            act = g_object_new (GALEON_TYPE_ACTION_NAVIGATION,
                            "name", "GoForwardWithArrow",
                            "window", window,
                            "direction", GALEON_NAVIGATION_DIRECTION_FORWARD,
                            "show_arrow", TRUE,
                            /* "short_label", _("Forward History"), */
                            NULL);
            gtk_action_group_add_action (p->action_group, act);
            g_object_unref (act);

            act = g_object_new (GALEON_TYPE_ACTION_NAVIGATION,
                            "name", "GoUp",
                            "window", window,
                            "direction", GALEON_NAVIGATION_DIRECTION_UP,
                            NULL);
            gtk_action_group_add_action_with_accel (p->action_group, act, "<alt>Up");
            g_object_unref (act);

            act = g_object_new (GALEON_TYPE_ACTION_NAVIGATION,
                            "name", "GoUpWithArrow",
                            "window", window,
                            "direction", GALEON_NAVIGATION_DIRECTION_UP,
                            "show_arrow", TRUE,
                            /* "short_label", _("Up (with menu)"), */
                            NULL);
            gtk_action_group_add_action (p->action_group, act);
            g_object_unref (act);

            act = g_object_new (GALEON_TYPE_ACTION_LOCATION,
                            "name", "LocationEntry",
                            "window", window,
                            NULL);
            gtk_action_group_add_action (p->action_group, act);
            g_object_unref (act);
            p->location_action = GALEON_ACTION_LOCATION (act);

            act = g_object_new (GALEON_TYPE_ACTION_HOME,
                            "name", "GoHome",
                            "window", window,
                            NULL);
            gtk_action_group_add_action_with_accel (p->action_group, act, "<alt>Home");
            g_object_unref (act);

            act = g_object_new (GALEON_TYPE_ACTION_NEW,
                            "name", "New",
                            "window", window,
                            NULL);
            gtk_action_group_add_action (p->action_group, act);
            g_object_unref (act);

            act = g_object_new (GALEON_TYPE_ACTION_REFRESH,
                            "name", "Refresh",
                            "window", window,
                            NULL);
            gtk_action_group_add_action (p->action_group, act);
            g_object_unref (act);

            act = g_object_new (GALEON_TYPE_ACTION_STOP,
                            "name", "Stop",
                            "window", window,
                            NULL);
            gtk_action_group_add_action (p->action_group, act);
            g_object_unref (act);

            act = g_object_new (GALEON_TYPE_ACTION_GO,
                            "name", "GoTo",
                            "window", window,
                            NULL);
            gtk_action_group_add_action (p->action_group, act);
            g_object_unref (act);

            act = g_object_new (GALEON_TYPE_ACTION_ZOOM,
                            "name", "ZoomSpinner",
                            "window", window,
                            NULL);
            gtk_action_group_add_action (p->action_group, act);
            g_object_unref (act);

            act = g_object_new (GALEON_TYPE_ACTION_SPINNER,
                            "name", "LogoSpinner",
                            "window", window,
                            NULL);
            gtk_action_group_add_action (p->action_group, act);
            g_object_unref (act);
            p->spinner_action = GALEON_ACTION_SPINNER (act);

            act = g_object_new (GALEON_TYPE_ACTION_FAVICON,
                            "name", "Favicon",
                            "window", window,
                            NULL);
            gtk_action_group_add_action (p->action_group, act);
            g_object_unref (act);
      }

      /* add the editable toolbar */
      {
            GtkWidget *item = egg_dock_item_new("EggEditableToolbar",
                                        "Primary Toolbar",
                                        EGG_DOCK_ITEM_BEH_NORMAL);
            GtkWidget *et = egg_editable_toolbar_new_with_model (window->merge, 
                                            galeon_shell_get_toolbars_model (galeon_shell));
            gtk_widget_show (et);

            eel_gconf_get_boolean(GCONF_DETACH_TOOLBAR) ?
                  egg_dock_item_unlock(EGG_DOCK_ITEM(item)) :
                  egg_dock_item_lock(EGG_DOCK_ITEM(item));

            egg_dock_add_item(EGG_DOCK(window->egg_dock),
                          EGG_DOCK_ITEM(item),
                          EGG_DOCK_TOP);
            gtk_container_add(GTK_CONTAINER(item), et);
            gtk_widget_show(item);

            p->egg_toolbar = EGG_EDITABLE_TOOLBAR (et);
      }

      /* Setup the embed popups factory */
      p->embed_popup = galeon_popup_new (window);

      /* add the printpreview toolbar */
      p->ppview_toolbar = ppview_toolbar_new(window);
      g_signal_connect_object (p->ppview_toolbar, "print",
                         G_CALLBACK (ppview_toolbar_print_cb),
                         window, 0);

      ui_file = gul_general_user_file("galeon-egg-ui.xml", TRUE);
      gtk_ui_manager_add_ui_from_file (window->merge, ui_file, NULL);
      g_free (ui_file);

      gtk_ui_manager_ensure_update (window->merge);

      dock_item = egg_dock_get_item_by_name (EGG_DOCK(window->egg_dock),
                                     "PPVToolbar");

      ppview_toolbar_set_dock_item (p->ppview_toolbar, dock_item);

      gtk_window_add_accel_group (GTK_WINDOW(window), 
                            gtk_ui_manager_get_accel_group (window->merge));


      /* Apply galeon's local override style for the toolbar is appropriate
       * and attach gconf notifier to override toolbar style
       */
      toolbar_style_gconf_changed_cb(NULL, 0, NULL, window);

      galeon_notification_add(CONF_TOOLBAR_STYLE,
                        (GConfClientNotifyFunc)toolbar_style_gconf_changed_cb,
                        window, &window->priv->notifiers);

      /* Setup gtk menus */
      setup_images_menu(window);
      setup_web_menu(window);
      setup_edit_menu (window);

      p->css_menu = galeon_css_menu_new (window);
      p->encoding_menu = galeon_encoding_menu_new (window);
      p->window_menu = galeon_window_menu_new (window);
      p->rh_menu = galeon_recent_history_menu_new (window, p->recent_history);

      /* Setup statusbar */
      p->statusbar = statusbar_new(offline_action);
      g_signal_connect (G_OBJECT(p->statusbar), "request",
                    G_CALLBACK(statusbar_request_cb),
                    window);
      gtk_widget_show(p->statusbar);

      /* Setup bookmarks ui elements */
      bs = galeon_shell_get_bookmark_set (galeon_shell);
      setup_bookmarks_menu(window, bs);
      p->bookmarks_toolbar = setup_bookmarks_toolbar (window, bs);      

      /* Setup window contents */
      p->notebook = setup_notebook (window);
      p->tab_menu = galeon_tab_menu_new (window);

      p->hpaned = setup_sidebar (window);
      gtk_box_pack_end(GTK_BOX(p->main_area),
                   p->statusbar,
                   FALSE, FALSE, 0);
      gtk_box_pack_end(GTK_BOX(p->main_area),
                   GTK_WIDGET(p->hpaned),
                   TRUE, TRUE, 0);

      gtk_container_add(GTK_CONTAINER(window),
                    GTK_WIDGET(p->main_area));

      g_object_ref (galeon_shell);

      /* Attach to the embed_shell signal, so that we update permissions */
      g_signal_connect_object (G_OBJECT (embed_shell), "permission_changed",
                         G_CALLBACK (permission_changed_cb), window, 0);

      /*Once window is fully created, add it to the session list*/
      session_add_window (session, window);
}

static void  
save_window_chrome (GaleonWindow *window)
{
      EmbedChromeMask flags = window->priv->chrome_mask;
      
      if (flags & EMBED_CHROME_OPENASPOPUP)
      {
      }
      else if (flags & EMBED_CHROME_PPVIEWTOOLBARON)
      {
      }
      else if (flags & EMBED_CHROME_OPENASFULLSCREEN)
      {
            eel_gconf_set_boolean (CONF_WINDOWS_FS_SHOW_SIDEBAR,
                               flags & EMBED_CHROME_SIDEBARON);
            eel_gconf_set_boolean (CONF_WINDOWS_FS_SHOW_TOOLBARS,
                               flags & EMBED_CHROME_TOOLBARON);
            eel_gconf_set_boolean (CONF_WINDOWS_FS_SHOW_BOOKMARKS,
                               flags & EMBED_CHROME_PERSONALTOOLBARON);
            eel_gconf_set_boolean (CONF_WINDOWS_FS_SHOW_STATUSBAR,
                               flags & EMBED_CHROME_STATUSBARON);
      }
      else
      {
            eel_gconf_set_boolean (CONF_WINDOWS_SHOW_SIDEBAR,
                               flags & EMBED_CHROME_SIDEBARON);
            eel_gconf_set_boolean (CONF_WINDOWS_SHOW_TOOLBARS,
                               flags & EMBED_CHROME_TOOLBARON);
            eel_gconf_set_boolean (CONF_WINDOWS_SHOW_BOOKMARKS,
                               flags & EMBED_CHROME_PERSONALTOOLBARON);
            eel_gconf_set_boolean (CONF_WINDOWS_SHOW_STATUSBAR,
                               flags & EMBED_CHROME_STATUSBARON);
      }
}

static void
remove_from_session (GaleonWindow *window)
{
      Session *session;

      session = galeon_shell_get_session (galeon_shell);
      g_return_if_fail (session != NULL);
      
      session_remove_window (session, window);
}

static void
galeon_window_dispose (GObject *object)
{
      GaleonWindow *window = GALEON_WINDOW (object);
      GaleonWindowPrivate *p = window->priv;
      GaleonJSConsole *jsconsole;
      GSList *popups;

      if (window->priv->notebook)
      {
            remove_from_session (window);
      }

      /* Ensure that we don't reference these objects after the
       * dispose, they may have been destroyed */
      window->priv->notebook = NULL;
      window->priv->hpaned = NULL;
      window->priv->active_tab = NULL;
      window->priv->sidebar = NULL;

      if (p->css_menu)
      {
            g_object_unref (p->css_menu);
            p->css_menu = NULL;
      }

      popups = gtk_ui_manager_get_toplevels (window->merge, GTK_UI_MANAGER_POPUP);
        g_slist_foreach (popups, (GFunc) gtk_menu_shell_deactivate, NULL);
        g_slist_free (popups);

      /* Hide the jsconsole if it is transient for us */
      jsconsole = galeon_embed_shell_get_js_console (embed_shell);
      if (jsconsole && 
          gtk_window_get_transient_for (GTK_WINDOW (jsconsole)) == GTK_WINDOW (object))
      {
            gtk_widget_hide (GTK_WIDGET (jsconsole));
      }

      window->priv->closing = TRUE;

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

static void
galeon_window_finalize (GObject *object)
{
        GaleonWindow *window;
      GaleonWindowPrivate *p;

        g_return_if_fail (GALEON_IS_WINDOW (object));

      window = GALEON_WINDOW (object);
      p = window->priv;

        g_return_if_fail (p != NULL);

      galeon_notification_remove (&p->notifiers);

      if (p->embed_popup)
      {
            g_object_unref (G_OBJECT (p->embed_popup));
      }

      g_object_unref (G_OBJECT (window->priv->bookmarks_toolbar));
      g_object_unref (G_OBJECT (window->priv->ppview_toolbar));
      
      if (p->find_dialog)
      {
            g_object_unref (G_OBJECT (p->find_dialog));
      }

      if (p->history_dialog)
      {
            g_object_remove_weak_pointer 
                        (G_OBJECT(p->history_dialog),
                         (gpointer *)&p->history_dialog);
      }

      if (p->bookmarks_sidebar)
      {
            g_object_unref (p->bookmarks_sidebar);
      }
      
      g_object_unref (p->tab_menu);
      g_object_unref (p->window_menu);
      g_object_unref (p->recent_history);
      g_object_unref (p->rh_menu);
      g_object_unref (p->bookmarks_menu);
      g_object_unref (p->encoding_menu);

      g_object_unref(p->action_group);
      g_object_unref(window->merge);


        G_OBJECT_CLASS (parent_class)->finalize (object);

      LOG ("Galeon Window finalized %p", window);
      
      g_object_unref (galeon_shell);
}

GaleonWindow *
galeon_window_new (void)
{
      return GALEON_WINDOW (g_object_new (GALEON_TYPE_WINDOW, NULL));
}

EmbedChromeMask  
galeon_window_get_chrome (GaleonWindow *window)
{
      return window->priv->chrome_mask;
}

static void
translate_default_chrome (EmbedChromeMask *chrome_mask)
{     
      /* keep only not layout flags */
      *chrome_mask &= (EMBED_CHROME_WINDOWRAISED |
                   EMBED_CHROME_WINDOWLOWERED |
                   EMBED_CHROME_CENTERSCREEN |
                   EMBED_CHROME_OPENASDIALOG |
                   EMBED_CHROME_OPENASCHROME |
                   EMBED_CHROME_OPENASPOPUP |
                   EMBED_CHROME_OPENASFULLSCREEN);

      /* Load defaults */
      if (*chrome_mask & EMBED_CHROME_OPENASFULLSCREEN)
      {
            if (eel_gconf_get_boolean (CONF_WINDOWS_FS_SHOW_SIDEBAR))
            {
                  *chrome_mask |= EMBED_CHROME_SIDEBARON;
            }
            if (eel_gconf_get_boolean (CONF_WINDOWS_FS_SHOW_STATUSBAR))
            {
                  *chrome_mask |= EMBED_CHROME_STATUSBARON;
            }
            if (eel_gconf_get_boolean (CONF_WINDOWS_FS_SHOW_TOOLBARS))
            {
                  *chrome_mask |= EMBED_CHROME_TOOLBARON;
            }
            if (eel_gconf_get_boolean (CONF_WINDOWS_FS_SHOW_BOOKMARKS))
            {
                  *chrome_mask |= EMBED_CHROME_PERSONALTOOLBARON;
            }
      }
      else
      {
            if (eel_gconf_get_boolean (CONF_WINDOWS_SHOW_SIDEBAR))
            {
                  *chrome_mask |= EMBED_CHROME_SIDEBARON;
            }
            if (eel_gconf_get_boolean (CONF_WINDOWS_SHOW_STATUSBAR))
            {
                  *chrome_mask |= EMBED_CHROME_STATUSBARON;
            }
            if (eel_gconf_get_boolean (CONF_WINDOWS_SHOW_TOOLBARS))
            {
                  *chrome_mask |= EMBED_CHROME_TOOLBARON;
            }
            if (eel_gconf_get_boolean (CONF_WINDOWS_SHOW_BOOKMARKS))
            {
                  *chrome_mask |= EMBED_CHROME_PERSONALTOOLBARON;
            }
            
            *chrome_mask |= EMBED_CHROME_MENUBARON;
      }
}

/* Called after GaleonWindow has switched to fullscreen, setup toolbars etc. to
 * match.
 */
static void
galeon_window_fullscreen (GaleonWindow *window)
{
      EmbedChromeMask mask;

      mask = window->priv->chrome_mask;
      mask |= EMBED_CHROME_DEFAULT;
      mask |= EMBED_CHROME_OPENASFULLSCREEN;
      galeon_window_set_chrome (window, mask);
}

/* Called after GaleonWindow has switched back to normal size again, restore
 * normal toolbar etc. layouts.
 */
static void
galeon_window_unfullscreen (GaleonWindow *window)
{
      EmbedChromeMask mask;

      mask = window->priv->chrome_mask;
      mask |= EMBED_CHROME_DEFAULT;
      mask &= ~EMBED_CHROME_OPENASFULLSCREEN;
      galeon_window_set_chrome (window, mask);
}

static void
galeon_window_toolbar_set_visibility (GaleonWindow *window, gboolean visible)
{
      GaleonWindowPrivate *p = window->priv;
      EggToolbarsModel *model = galeon_shell_get_toolbars_model (galeon_shell);
      int n_toolbars = egg_toolbars_model_n_toolbars (model);
      int i;

      for (i = 0; i < n_toolbars; i++)
      {
            const char *t_name = egg_toolbars_model_toolbar_nth (EGG_TOOLBARS_MODEL (model), i);

            if (visible)
            {
                  egg_editable_toolbar_show (p->egg_toolbar, t_name);
            }
            else
            {
                  egg_editable_toolbar_hide (p->egg_toolbar, t_name);
                  
            }
      }
}

void  
galeon_window_set_chrome (GaleonWindow *window, 
                    EmbedChromeMask flags)
{
      gboolean toolbar, ppvtoolbar, statusbar;
      
      /* If we are already in Print Preview mode, and the flags still
       * say to stay in print preview mode, then just update the preview
       * toolbars idea of the old chrome (but only if it there are any flags
       * set)
       */
      if (window->priv->chrome_mask & EMBED_CHROME_PPVIEWTOOLBARON &&
          flags & EMBED_CHROME_PPVIEWTOOLBARON)
      {
            int new_flags = (flags & ~EMBED_CHROME_PPVIEWTOOLBARON);
            if (new_flags)
            {
                  ppview_toolbar_set_old_chrome (window->priv->ppview_toolbar,
                                           new_flags);
            }
            return;
      }

      if (flags & EMBED_CHROME_DEFAULT)
      {
            translate_default_chrome (&flags);
      }
            
      if ((flags & EMBED_CHROME_MENUBARON) != FALSE)
      {
            if (window->priv->menubar)
            {
                  gtk_widget_show(window->priv->menubar->parent);
            }
      }
      else
      {
            if (window->priv->menubar)
            {
                  gtk_widget_hide(window->priv->menubar->parent);
            }
      }

      if ((flags & EMBED_CHROME_SIDEBARON) != FALSE)
      {
            gtk_widget_show (window->priv->sidebar);
      }
      else
      {
            gtk_widget_hide (window->priv->sidebar);
      }
      
      toolbar = (flags & EMBED_CHROME_TOOLBARON) != FALSE;
      galeon_window_toolbar_set_visibility (window, toolbar);

      statusbar = (flags & EMBED_CHROME_STATUSBARON) != FALSE;
      statusbar_set_visibility (STATUSBAR(window->priv->statusbar),
                          statusbar);

      ppvtoolbar = (flags & EMBED_CHROME_PPVIEWTOOLBARON) != FALSE;
      ppview_toolbar_set_old_chrome (window->priv->ppview_toolbar,
                               window->priv->chrome_mask);
      ppview_toolbar_set_visibility (window->priv->ppview_toolbar, 
                               ppvtoolbar);
      
      gb_gtk_toolbar_set_set_visible (window->priv->bookmarks_toolbar,
                              flags & EMBED_CHROME_PERSONALTOOLBARON);
      
      window->priv->chrome_mask = flags;

      update_layout_toggles (window);

      save_window_chrome (window);
}

void
galeon_window_toggle_fullscreen (GaleonWindow *window)
{
      if (gdk_window_get_state (GTK_WIDGET (window)->window) & GDK_WINDOW_STATE_FULLSCREEN)
      {
            gtk_window_unfullscreen (GTK_WINDOW (window));
      }
      else
      {
            gtk_window_fullscreen (GTK_WINDOW (window));
      }
}

void 
galeon_window_add_tab (GaleonWindow *window, 
                   GaleonTab *tab,
                   gint position,
                   gboolean jump_to)
{
      g_return_if_fail (GALEON_IS_WINDOW (window));
      g_return_if_fail (GALEON_IS_TAB (tab));

      gul_notebook_insert_page (GUL_NOTEBOOK (window->priv->notebook), 
                          GTK_WIDGET (tab),
                          position,
                          jump_to);
}

void
galeon_window_next_tab (GaleonWindow *window)
{
      gtk_notebook_next_page (GTK_NOTEBOOK(window->priv->notebook));
}

void
galeon_window_prev_tab (GaleonWindow *window)
{
      gtk_notebook_prev_page (GTK_NOTEBOOK(window->priv->notebook));
}

void 
galeon_window_jump_to_tab (GaleonWindow *window, 
                     GaleonTab *tab)
{
      int page;
      
      page = gtk_notebook_page_num (window->priv->notebook, GTK_WIDGET (tab));
      gtk_notebook_set_current_page (window->priv->notebook, page);
}

static GaleonTab *
get_tab_from_page_num (GtkNotebook *notebook, gint page_num) 
{
      GtkWidget *widget;

      if (page_num < 0) return NULL;
      
      widget = gtk_notebook_get_nth_page (notebook, page_num);
      
      g_return_val_if_fail (GALEON_IS_TAB (widget), NULL);
      
      return GALEON_TAB (widget);
}

static GaleonTab *
real_get_active_tab (GaleonWindow *window, int page_num)
{
      if (page_num == -1)
      {
            page_num = gtk_notebook_get_current_page (window->priv->notebook);
      }

      return get_tab_from_page_num (window->priv->notebook, page_num);
}

gboolean
galeon_window_remove_tab (GaleonWindow *window, 
                      GaleonTab *tab)
{
      GaleonEmbed *embed;
      
      g_return_val_if_fail (GALEON_IS_WINDOW (window), FALSE);
      g_return_val_if_fail (GALEON_IS_TAB (tab), FALSE);

      embed = galeon_tab_get_embed (tab);
      
      if (galeon_embed_has_modified_forms (GALEON_EMBED (embed)) &&
          confirm_close_with_modified_forms (window, tab) == FALSE)
      {
            return FALSE;
      }

      gul_notebook_remove_page (GUL_NOTEBOOK (window->priv->notebook), 
                          GTK_WIDGET (tab));
      return TRUE;
}

void 
galeon_window_move_tab (GaleonWindow *window, 
                  GaleonTab *tab,
                  GaleonTab *new_sibling)
{
      int move_to;
      GtkNotebook *nb = window->priv->notebook;
      
      move_to = gtk_notebook_page_num (nb, GTK_WIDGET (new_sibling));

      if (tab && move_to != -1)
      {
            gul_notebook_move_page (GUL_NOTEBOOK (nb), NULL, GTK_WIDGET (tab), move_to);
      }
}

void 
galeon_window_load_url (GaleonWindow *window,
                  const char *url)
{
      GaleonEmbed *embed;
      GbBookmarkSet *set;
      gchar *real_url;

        g_return_if_fail (GALEON_IS_WINDOW(window));
      embed = galeon_window_get_active_embed (window);
        g_return_if_fail (embed != NULL);
        g_return_if_fail (url != NULL);
      
      set = galeon_shell_get_bookmark_set (galeon_shell);
      real_url = gb_bookmark_set_get_url_by_nick_and_args (set, url);

        galeon_embed_load_url (embed, real_url != NULL ? real_url : url);
      gtk_widget_grab_focus (GTK_WIDGET(embed));

      g_free (real_url);
}

void 
galeon_window_edit_location (GaleonWindow *window)
{
      galeon_action_location_edit (window->priv->location_action);
}

gchar *
galeon_window_get_location_entry_location (GaleonWindow *window)
{
      return galeon_action_location_get_location (window->priv->location_action);
}

void
galeon_window_set_location_entry_location (GaleonWindow *window, 
                                 const gchar *location)
{
      galeon_action_location_set_location (window->priv->location_action, location);
}

void
galeon_window_show (GtkWidget *widget)
{
      GaleonWindow *window = GALEON_WINDOW(widget);
      int w = -1, h = -1;
      
      if (!window->priv->chrome_mask)
      {
            galeon_window_set_chrome (window, EMBED_CHROME_DEFAULT);
      }

      if (!window->priv->has_default_size &&
          window->priv->chrome_mask & EMBED_CHROME_OPENASPOPUP)
      {
            GaleonTab *tab;

            tab = galeon_window_get_active_tab (window);
            if (tab) galeon_tab_get_size (tab, &w, &h);
      }
      
      if (w == -1 && h == -1) 
      {
            gul_state_monitor_window (widget, "Main Window",
                                  STATE_MAIN_WIDTH_DEFAULT,
                                STATE_MAIN_HEIGHT_DEFAULT);
            window->priv->has_default_size = TRUE;
      }
      
      GTK_WIDGET_CLASS (parent_class)->show (widget);
}

static void
sync_tab_message (GaleonTab *tab, GParamSpec *pspec, GaleonWindow *window)
{
      const char *message;

      g_return_if_fail (GALEON_IS_TAB (tab));
      g_return_if_fail (GALEON_IS_WINDOW (window));

      if (window->priv->closing) return;

      message = galeon_tab_get_status_message (tab);
      g_return_if_fail (message != NULL);
      
      statusbar_set_message (STATUSBAR(window->priv->statusbar), message);
}

static void
sync_tab_progress (GaleonTab *tab, GParamSpec *pspec, GaleonWindow *window)
{
      int load_percent;
      
      g_return_if_fail (GALEON_IS_TAB (tab));
      g_return_if_fail (GALEON_IS_WINDOW (window));

      if (window->priv->closing) return;

      load_percent = galeon_tab_get_load_percent (tab);

      statusbar_set_progress (STATUSBAR(window->priv->statusbar),
                          load_percent);
}

static void
sync_tab_security (GaleonTab *tab, GParamSpec *pspec, GaleonWindow *window)
{
      GaleonEmbed *embed;
      EmbedSecurityLevel level;
      char *description;
      char *state = NULL;
      const char *stock_id;
      gboolean secure;
      char *tooltip;

      g_return_if_fail (GALEON_IS_TAB (tab));
      g_return_if_fail (GALEON_IS_WINDOW (window));

      if (window->priv->closing) return;

      embed = galeon_tab_get_embed (tab);
      g_return_if_fail (GALEON_IS_EMBED (embed));

      if (!galeon_embed_get_security_level (embed, &level, &description))
      {
            level = STATE_IS_UNKNOWN;
            description = NULL;
      }

      stock_id = GALEON_STOCK_INSECURE;
      secure = FALSE;
      switch (level)
      {
      case STATE_IS_UNKNOWN:
            state = _("Unknown");
            break;
      case STATE_IS_INSECURE:
            state = _("Insecure");
            break;
      case STATE_IS_BROKEN:
            state = _("Broken");
            stock_id = STOCK_LOCK_BROKEN;
            break;
      case STATE_IS_SECURE_MED:
            /* This state isn't actually used by mozilla ... */
            stock_id = GALEON_STOCK_SECURE;
            state = _("Medium");
            secure = TRUE;
            break;
      case STATE_IS_SECURE_LOW:
            state = _("Low");
            /* Don't treat low as insecure, 90 bits should be
             * an absolute minumum these days */
            break;
      case STATE_IS_SECURE_HIGH:
            state = _("High");
            stock_id = GALEON_STOCK_SECURE;
            secure = TRUE;
            break;
      default:
            g_assert_not_reached ();
            break;
      }

      if (description != NULL)
      {
            tooltip = g_strdup_printf (_("Security level: %s\n%s"),
                                 state, description);
            g_free (description);
      }
      else
      {
            tooltip = g_strdup_printf (_("Security level: %s"), state);

      }

      statusbar_set_security_state (STATUSBAR (window->priv->statusbar),
                                stock_id, tooltip);
      g_free (tooltip);

      galeon_action_location_set_is_secure (window->priv->location_action, secure);
}

static void
sync_tab_popup_blocked (GaleonTab *tab, GParamSpec *pspec, GaleonWindow *window)
{
      const char *uri;

      g_return_if_fail (GALEON_IS_TAB (tab));
      g_return_if_fail (GALEON_IS_WINDOW (window));

      if (window->priv->closing) return;

      uri = galeon_tab_get_blocked_popup_uri(tab);

      statusbar_set_popup_block(STATUSBAR(window->priv->statusbar),
                          uri ? TRUE : FALSE, uri);
}

static void
sync_tab_title (GaleonTab *tab, GParamSpec *pspec, GaleonWindow *window)
{
      const char *title;

      g_return_if_fail (GALEON_IS_TAB (tab));
      g_return_if_fail (GALEON_IS_WINDOW (window));

      if (window->priv->closing) return;

      title = galeon_tab_get_title (tab);

      gul_notebook_set_page_title (GUL_NOTEBOOK (window->priv->notebook),
                             GTK_WIDGET (tab),
                             title);

      if (galeon_window_get_active_tab (window) == tab)
      {
            gtk_window_set_title (GTK_WINDOW(window), title);
      }
}

static void
sync_tab_load_status (GaleonTab *tab, GParamSpec *pspec, GaleonWindow *window)
{
      GdkColor *color;
      GtkWidget *icon = galeon_tab_get_icon(tab);
      TabLoadStatus status = galeon_tab_get_load_status (tab);
      gboolean have_ref = FALSE;

      if (window->priv->closing) return;

      switch (status)
      {
      case TAB_LOAD_STARTED:
            color = &_galeon_window_loading_tab_color;

            /* Don't display the loading animation if favicons in tabs are
             * disabled. If they are disabled, then the icon retreived above
             * will be empty, so won't get displayed */
            if (eel_gconf_get_integer (CONF_TABS_FAVICON))
            {
                  icon = gtk_image_new_from_animation (_galeon_window_loading_animation);
                  gtk_widget_show (icon);
                  g_object_ref (G_OBJECT (icon));
                  gtk_object_sink (GTK_OBJECT (icon));
                  have_ref = TRUE;
            }

            break;
      case TAB_LOAD_COMPLETED:
            /* If this is the active tab, update the load status, that
             * will notify the property again, and we will get called
             * back */
            if (galeon_window_get_active_tab (window) == tab)
            {
                  galeon_tab_set_load_status (tab, TAB_LOAD_NONE);
                  return;
            }

            color = &_galeon_window_new_tab_color;
            break;
      case TAB_LOAD_NONE:
            color = NULL;
            break;
      default:
            g_return_if_reached();
      }

      gul_notebook_set_page_icon( GUL_NOTEBOOK (window->priv->notebook),
                            GTK_WIDGET (tab),
                            icon );

      gul_notebook_set_page_color (GUL_NOTEBOOK (window->priv->notebook),
                               GTK_WIDGET (tab),
                             color);
      
      if (have_ref)
      {
            g_object_unref (G_OBJECT(icon));
      }

      /* And finally update the spinner */
      galeon_action_update (GALEON_ACTION (window->priv->spinner_action));
}

static void
sync_tab_location (GaleonTab *tab, GParamSpec *pspec, GaleonWindow *window)
{
      const char *location, *host = NULL;
      char *allow_images_str, *block_images_str,
           *allow_cookies_str, *block_cookies_str,
           *allow_popups_str;
      GnomeVFSURI *uri = NULL;
      gboolean can_view_source = FALSE;
      GaleonEmbed *embed;

      g_return_if_fail (GALEON_IS_TAB (tab));
      g_return_if_fail (GALEON_IS_WINDOW (window));

      if (window->priv->closing) return;

      location = galeon_tab_get_location (tab);

      /* don't display about:blank in the location entry, it's uninteresting
       * and prevents the user from pasting a new url after opening a new
       * window/tab */
      if (!location || !strcmp (location, "about:blank")) location = "";

      /* Update cookie and image allow/block menu items to refer to
       * the current host. Makes things clearer for the user
       */
      if (location)
            uri = gnome_vfs_uri_new(location);

      if (uri)
            host = gnome_vfs_uri_get_host_name(uri);


      if (!host)
            host = _("This Site");

      allow_cookies_str = g_strdup_printf(_("_Allow Cookies From %s"), host);
      block_cookies_str = g_strdup_printf(_("_Block Cookies From %s"), host);
      allow_images_str = g_strdup_printf(_("_Allow Images From %s"), host);
      block_images_str = g_strdup_printf(_("_Block Images From %s"), host);
      allow_popups_str = g_strdup_printf(_("_Allow Popups From %s"), host);

      if (uri)
            gnome_vfs_uri_unref(uri);

      g_object_set(G_OBJECT(ACTION_ITEM(WEB_COOKIES_ALLOWSITE_ACTION)),
                 "label", allow_cookies_str, NULL);
      g_object_set(G_OBJECT(ACTION_ITEM(WEB_COOKIES_BLOCKSITE_ACTION)),
                 "label", block_cookies_str, NULL);
      g_object_set(G_OBJECT(ACTION_ITEM(WEB_POPUPS_ALLOWSITE_ACTION)),
                 "label", allow_popups_str, NULL);
      g_object_set(G_OBJECT(ACTION_ITEM(VIEW_IMAGES_ALLOWSITE_ACTION)),
                 "label", allow_images_str, NULL);
      g_object_set(G_OBJECT(ACTION_ITEM(VIEW_IMAGES_BLOCKSITE_ACTION)),
                 "label", block_images_str, NULL);

      embed = galeon_tab_get_embed (tab);
      can_view_source = galeon_embed_can_view_source (embed);
      g_object_set(G_OBJECT(ACTION_ITEM(VIEW_SOURCE_ACTION)),
                 "sensitive", can_view_source, NULL);

      g_free(allow_cookies_str);
      g_free(block_cookies_str);
      g_free(allow_images_str);
      g_free(block_images_str);
      g_free(allow_popups_str);

      update_permission_control (window, tab);
}

static void
sync_tab_visibility (GaleonTab *t, GParamSpec *pspec, GaleonWindow *window)
{
      GList *tabs, *l;
      
      if (window->priv->closing) return;

      tabs = galeon_window_get_tabs (window);
      for (l = tabs; l != NULL; l = l->next)
      {
            GaleonTab *tab = GALEON_TAB(l->data);
            g_return_if_fail (GALEON_IS_TAB(tab));
            
            if (galeon_tab_get_visibility (tab))
            {
                  gtk_widget_show (GTK_WIDGET(window));
                  g_list_free (tabs);
                  return;
            }
      }
      g_list_free (tabs);

      if (GTK_WIDGET_VISIBLE (GTK_WIDGET (window)))
      {
            gtk_widget_hide (GTK_WIDGET (window));
      }
}

static void
update_permission_control (GaleonWindow *window, GaleonTab *tab)
{
      GaleonEmbedShell *embed_shell;
      PermissionActionType image_action, cookie_action, popup_action;

      g_return_if_fail (GALEON_IS_WINDOW (window));
      
      if (!tab)
      {
            tab = galeon_window_get_active_tab (window);
      }

      /* This can happen when setting up a window */
      if (tab == NULL) return;

      embed_shell = galeon_shell_get_embed_shell(galeon_shell);
      g_return_if_fail(embed_shell != NULL);

      image_action = galeon_embed_shell_test_permission(embed_shell,
                                            galeon_tab_get_location(tab),
                                            IMAGES_PERMISSION);
      g_object_set(G_OBJECT(ACTION_ITEM(VIEW_IMAGES_ALLOWSITE_ACTION)),
                 "sensitive", (image_action != ALLOW_ACTION), NULL);
      g_object_set(G_OBJECT(ACTION_ITEM(VIEW_IMAGES_BLOCKSITE_ACTION)),
                 "sensitive", (image_action != DENY_ACTION), NULL);

      cookie_action = galeon_embed_shell_test_permission(embed_shell,
                                             galeon_tab_get_location(tab),
                                             COOKIES_PERMISSION);

      g_object_set(G_OBJECT(ACTION_ITEM(WEB_COOKIES_ALLOWSITE_ACTION)),
                 "sensitive", (cookie_action != ALLOW_ACTION), NULL);
      g_object_set(G_OBJECT(ACTION_ITEM(WEB_COOKIES_BLOCKSITE_ACTION)),
                 "sensitive", (cookie_action != DENY_ACTION), NULL);

      /* If global allow popups, then the site specific menu item
       * is always insensitive */
      if (eel_gconf_get_boolean(CONF_FILTERING_ALLOW_POPUPS))
      {
            g_object_set(G_OBJECT(ACTION_ITEM(WEB_POPUPS_ALLOWSITE_ACTION)),
                       "sensitive", FALSE, NULL);
            galeon_tab_clear_blocked_popup_uri(tab);
            return;
      }
      
      popup_action = galeon_embed_shell_test_permission(embed_shell,
                                            galeon_tab_get_location(tab),
                                            POPUPS_PERMISSION);
      g_object_set(G_OBJECT(ACTION_ITEM(WEB_POPUPS_ALLOWSITE_ACTION)),
                 "sensitive", (popup_action != ALLOW_ACTION), NULL);

      if (popup_action == ALLOW_ACTION)
      {
            galeon_tab_clear_blocked_popup_uri(tab);
      }
}

GtkWidget *
galeon_window_get_statusbar(GaleonWindow *window)
{
      g_return_val_if_fail(GALEON_IS_WINDOW(window), NULL);
      g_return_val_if_fail(IS_STATUSBAR(window->priv->statusbar), NULL);

      return window->priv->statusbar;
}

GaleonSidebar *
galeon_window_get_sidebar (GaleonWindow *window)
{
      g_return_val_if_fail (GALEON_IS_WINDOW (window), NULL);

      if(!GALEON_IS_SIDEBAR(G_OBJECT(window->priv->sidebar)))
            setup_sidebar(window);

      return GALEON_SIDEBAR(window->priv->sidebar);
}     

GaleonTab *
galeon_window_get_active_tab (GaleonWindow *window)
{
      g_return_val_if_fail (GALEON_IS_WINDOW (window), NULL);

      return window->priv->active_tab;
}

GaleonEmbed *
galeon_window_get_active_embed (GaleonWindow *window)
{
      GaleonTab *tab;

      tab = galeon_window_get_active_tab (window);
      if (!tab) return NULL;

      g_return_val_if_fail (GALEON_IS_WINDOW (window), NULL);
      return galeon_tab_get_embed (tab);
}

GaleonPopup *
galeon_window_get_popup_factory(GaleonWindow *window)
{
      return window->priv->embed_popup;
}

GulNotebook *
galeon_window_get_notebook(GaleonWindow *window)
{
      g_return_val_if_fail(GALEON_IS_WINDOW(window), NULL);
      g_return_val_if_fail(window->priv, NULL);
      g_return_val_if_fail(window->priv->notebook, NULL);

      return GUL_NOTEBOOK(window->priv->notebook);
}

/**
 * galeon_window_get_tabs:
 * @window: a #GaleonWindow
 *
 * Returns the list of #GaleonTab:s in the window.
 *
 * Return value: a newly-allocated list of #GaleonTab:s
 */
GList *
galeon_window_get_tabs (GaleonWindow *window)
{
      g_return_val_if_fail (GALEON_IS_WINDOW (window), NULL);

      return gtk_container_get_children (GTK_CONTAINER (window->priv->notebook));
}

static void
save_old_embed_status (GaleonTab *tab, GaleonWindow *window)
{
      /* save old tab location status */
      gchar *l = galeon_action_location_get_location (window->priv->location_action);
      galeon_tab_set_location (tab, l);
      g_free (l);
}

static void
update_embed_dialogs (GaleonWindow *window,
                  GaleonTab *tab)
{
      GaleonEmbed *embed;
      GaleonDialog *find_dialog = window->priv->find_dialog;
      GaleonDialog *history_dialog = window->priv->history_dialog;
      GaleonDialog *history_sidebar = window->priv->history_sidebar;

      embed = galeon_tab_get_embed (tab);

      if (find_dialog)
      {
            galeon_embed_dialog_set_embed 
                  (GALEON_EMBED_DIALOG(find_dialog),
                   embed);
      }

      if (history_dialog)
      {
            galeon_embed_dialog_set_embed 
                  (GALEON_EMBED_DIALOG(history_dialog),
                   embed);
      }

      if (history_sidebar)
      {
            galeon_embed_dialog_set_embed 
                  (GALEON_EMBED_DIALOG(history_sidebar),
                   embed);
      }
}


static void
update_tabs_menu_sensitivity (GaleonWindow *window)
{
      gboolean prev_tab, next_tab, detach;
      int current, n_pages;

      n_pages = gtk_notebook_get_n_pages
            (GTK_NOTEBOOK (window->priv->notebook));
      current = gtk_notebook_get_current_page
            (GTK_NOTEBOOK (window->priv->notebook));

      prev_tab  = (current > 0);
      next_tab  = (current < (n_pages-1));
      detach    = n_pages > 1;

      g_object_set (ACTION_ITEM ("TabsPrevAction"), "sensitive", prev_tab, NULL);
      g_object_set (ACTION_ITEM ("TabsNextAction"), "sensitive", next_tab, NULL);
      g_object_set (ACTION_ITEM ("TabsMoveLeftAction"), "sensitive", prev_tab, NULL);
      g_object_set (ACTION_ITEM ("TabsMoveRightAction"), "sensitive", next_tab, NULL);
      g_object_set (ACTION_ITEM ("TabsDetachAction"), "sensitive", detach, NULL);
      g_object_set (ACTION_ITEM ("TabsCloseOtherTabsAction"), "sensitive", detach, NULL);
}

static gboolean
show_notebook_popup_menu (GtkNotebook *notebook,
                    GaleonWindow *window,
                    GdkEventButton *event)
{
      GtkWidget *menu, *tab, *tab_label;

      menu = gtk_ui_manager_get_widget (window->merge, TAB_POPUP_PATH);
      g_return_val_if_fail (menu != NULL, FALSE);

      if (event != NULL)
      {
            gtk_menu_popup (GTK_MENU (menu), NULL, NULL,
                        NULL, NULL,
                        event->button, event->time);
      }
      else
      {
            tab = GTK_WIDGET (galeon_window_get_active_tab (window));
            tab_label = gtk_notebook_get_tab_label (notebook, tab);

            gtk_menu_popup (GTK_MENU (menu), NULL, NULL,
                        gul_gui_menu_position_under_widget, tab_label,
                        0, gtk_get_current_event_time ());
      }

      return TRUE;
}

static gboolean
galeon_window_notebook_button_press_cb(GtkNotebook *notebook,
                               GdkEventButton *event,
                               GaleonWindow *window)
{
      if (event->type == GDK_BUTTON_PRESS && event->button == 3)
      {
            return show_notebook_popup_menu(notebook, window, event);
      }

      return FALSE;
}

static gboolean
galeon_window_notebook_popup_menu_cb(GtkNotebook *notebook,
                             GaleonWindow *window)
{
      GtkWidget *widget = gtk_window_get_focus(GTK_WINDOW(window));

      /* Only respond if the notebook is the actual focus */
      if (GUL_IS_NOTEBOOK(widget))
      {
            return show_notebook_popup_menu(notebook, window, NULL);
      }

      return FALSE;
}

static void
galeon_window_notebook_switch_page_cb (GtkNotebook *notebook,
                               GtkNotebookPage *page,
                               guint page_num,
                               GaleonWindow *window)
{
      GaleonTab *tab, *old_tab;
      GaleonEmbed *old_embed = NULL;
      GaleonEmbed *new_embed = NULL;

      g_return_if_fail (GALEON_IS_WINDOW (window));
      if (window->priv->closing) return;

      /* get the new tab */
      tab = real_get_active_tab (window, page_num);
      
      /* update old tab */
      old_tab = window->priv->active_tab;

      if (tab == old_tab) return;

      if (old_tab)
      {
            g_return_if_fail (GALEON_IS_TAB (old_tab));
            old_embed = galeon_tab_get_embed (old_tab);
            save_old_embed_status (old_tab, window);

            g_signal_handlers_disconnect_by_func (G_OBJECT (old_tab),
                                          G_CALLBACK (sync_tab_security),
                                          window);
            g_signal_handlers_disconnect_by_func (G_OBJECT (old_tab),
                                          G_CALLBACK (sync_tab_message),
                                          window);
            g_signal_handlers_disconnect_by_func (G_OBJECT (old_tab),
                                          G_CALLBACK (sync_tab_progress),
                                          window);
            g_signal_handlers_disconnect_by_func (G_OBJECT (old_tab),
                                          G_CALLBACK (sync_tab_popup_blocked),
                                          window);
            g_signal_handlers_disconnect_by_func (G_OBJECT (old_tab),
                                          G_CALLBACK (sync_tab_location),
                                          window);
      }

      /* update new tab */
      window->priv->active_tab = tab;
      new_embed = galeon_tab_get_embed (window->priv->active_tab);

      g_signal_emit (window, GaleonWindowSignals[ACTIVE_EMBED_CHANGED], 0, old_embed, new_embed);

      update_embed_dialogs (window, tab);
      update_tabs_menu_sensitivity (window);

      /* Sync the window state and the tab state */

      sync_tab_title (GALEON_TAB (tab), NULL, window);
      sync_tab_load_status (GALEON_TAB (tab), NULL, window);
      sync_tab_security (GALEON_TAB (tab), NULL, window);
      sync_tab_message (GALEON_TAB (tab), NULL, window);
      sync_tab_progress (GALEON_TAB (tab), NULL, window);
      sync_tab_popup_blocked (GALEON_TAB (tab), NULL, window);
      sync_tab_location (GALEON_TAB (tab), NULL, window);
      
      g_signal_connect_object (G_OBJECT (tab), "notify::security-level",
                         G_CALLBACK (sync_tab_security), window, 0);
      g_signal_connect_object (G_OBJECT (tab), "notify::message",
                         G_CALLBACK (sync_tab_message), window, 0);
      g_signal_connect_object (G_OBJECT (tab), "notify::progress",
                         G_CALLBACK (sync_tab_progress), window, 0);
      g_signal_connect_object (G_OBJECT (tab), "notify::popup-blocked",
                         G_CALLBACK (sync_tab_popup_blocked), window, 0);
      g_signal_connect_object (G_OBJECT (tab), "notify::location",
                         G_CALLBACK (sync_tab_location), window, 0);
}

/**
 * Prompt the user for a smart bookmark arguments, and return the
 * completed URL to load, or NULL if cancelled.
 */
static char *
handle_smartsite (GaleonWindow *w, GbSmartSite *s)
{
      GtkWidget *dialog, *vbox, *label, *entry;
      int response;
      char *args[2]; /* TODO: match this with get_num_fields() */
      char *url;
      
      dialog = gtk_dialog_new_with_buttons (_("Galeon"), GTK_WINDOW(w),
                                    GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR,
                                    GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                                    GTK_STOCK_OK, GTK_RESPONSE_OK,
                                    NULL);
      gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
      gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);

      vbox = gtk_vbox_new (FALSE, 8);
      gtk_container_set_border_width (GTK_CONTAINER (vbox), 8);

      label = gtk_label_new (_("Enter the arguments for this smart site:"));
      gtk_box_pack_start_defaults (GTK_BOX (vbox), label);

      entry = gtk_entry_new ();
      gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE);
      gtk_box_pack_start_defaults (GTK_BOX (vbox), entry);

      gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), vbox);
      gtk_widget_show_all (dialog);

      response = gtk_dialog_run (GTK_DIALOG (dialog));
      if (response != GTK_RESPONSE_OK) {
            gtk_widget_destroy (dialog);
            return NULL;
      }

      args[0] = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1);
      args[1] = NULL;
      gtk_widget_destroy (dialog);
      url = gb_smart_site_subst_args(s, args);
      g_free(args[0]);
      return url;
}

static gboolean
confirm_open_many_bookmarks (GaleonWindow *w, int count)
{
      int many_bookmarks_warning_threshold = eel_gconf_get_integer (CONF_BOOKMARKS_MANY_BOOKMARKS_WARNING_THRESHOLD);
      if (count > many_bookmarks_warning_threshold)
      {
            GtkWidget *spin;
            GtkWidget *box;
            GtkWidget *label;
            gint response;
            GtkWidget *dialog = hig_alert_new
                  (GTK_WINDOW (w),
                   GTK_DIALOG_MODAL,
                   HIG_ALERT_CONFIRMATION,
                   _("Open multiple bookmarks?"),
                   NULL,
                   GTK_STOCK_CANCEL,
                   GTK_RESPONSE_CANCEL,
                   _("_Open the bookmarks"),
                   1,
                   NULL);
            hig_alert_set_secondary_printf (HIG_ALERT (dialog),
                                    ngettext("You have requested to show %d bookmarked "
                                           "site in a different window or tab. Are you sure?",
                                           "You have requested to show %d bookmarked sites "
                                           "in different windows or tabs. Are you sure?", 
                                           count), count);
            
            gtk_dialog_set_default_response (GTK_DIALOG (dialog), 1);

            spin = gtk_spin_button_new_with_range (2, 10000, 1);
            gtk_widget_show (spin);
            gul_pu_connect_config_spin_button (spin, 
                                       CONF_BOOKMARKS_MANY_BOOKMARKS_WARNING_THRESHOLD);
            box = gtk_hbox_new (FALSE, 12);
            gtk_widget_show (box);
            label = gtk_label_new (_("Maximum number of bookmarks to open without showing this dialog again:"));
            gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
            gtk_widget_show (label);
            hig_alert_add_widget (HIG_ALERT (dialog), box);
            gtk_box_pack_start_defaults (GTK_BOX (box), label);
            gtk_box_pack_start_defaults (GTK_BOX (box), spin);

            response = gtk_dialog_run (GTK_DIALOG (dialog));
            gtk_widget_destroy (dialog);
            
            if (response != 1)
            {
                  return FALSE;
            }
            else
            {
                  return TRUE;
            }
      }
      else
      {
            return TRUE;
      }
}

/**
 * Handle the activation of a bookmark.
 */
void
galeon_window_bookmark_activate (GaleonWindow *w, GbBookmarkEventActivated *ev)
{
      GaleonTab *tab = galeon_window_get_active_tab (w);
      GbBookmark *b = ev->bookmark;
      gchar *smarted_url = NULL;
      GbBookmarkActivatedFlags f = ev->flags;
      GaleonNewTabFlags flags = 0;
      const gchar *final_url;

      g_return_if_fail (f ==  GB_BAF_DEFAULT 
                    || f == GB_BAF_NEW_TAB_OR_WINDOW
                    || f == GB_BAF_NEW_WINDOW
                    || f == GB_BAF_NEW_TAB
                    || f == GB_BAF_EDITOR);

      if (GB_IS_SEPARATOR (b))
      {
            /* don't need to activate separators */
            return;
      }

      if (GB_IS_SMART_SITE (b) 
          && GB_SMART_SITE (b)->smarturl != NULL 
          && (GB_SITE (b)->url == NULL 
            || GB_SITE (b)->url[0]=='\0')
          && (ev->url == NULL
            || ev->url[0] == '\0'))
      {
            smarted_url = handle_smartsite (w, GB_SMART_SITE (b));
            if (smarted_url == NULL)
            {
                  return;
            }
      }

      final_url = smarted_url ? smarted_url 
                        : ev->url ? ev->url 
                                : GB_IS_SITE (b) ? GB_SITE (b)->url
                                             : NULL;

      if (f == GB_BAF_DEFAULT)
      {
            if (GB_IS_SITE (b) && f == GB_BAF_DEFAULT)
            {
                  g_return_if_fail (final_url);
                  galeon_window_load_url (w, final_url);
                  gb_site_set_time_visited_now (GB_SITE (b));
                  g_free (smarted_url);
                  return;
            }
            else if (GB_IS_FOLDER (b))
            {
                  f = GB_BAF_NEW_TAB_OR_WINDOW;
            }
            else
            {
                  g_free (smarted_url);
                  g_warning ("Don't know what to do...");
                  return;
            }
      }

      if (f == GB_BAF_NEW_WINDOW)
      {
            flags = GALEON_NEW_TAB_IN_NEW_WINDOW;
      }
      else if (f == GB_BAF_NEW_TAB)
      {
            flags = GALEON_NEW_TAB_IN_EXISTING_WINDOW;
      }
      else if (f == GB_BAF_NEW_TAB_OR_WINDOW)
      {
            GdkModifierType mod;
            gdk_event_get_state (ev->event, &mod);
            flags = galeon_shell_modifier_flags (mod);
      }
      else if (f == GB_BAF_EDITOR)
      {
            /* ignore it */
            g_free (smarted_url);
            return;
      }
      else
      {
            g_assert_not_reached ();
      }

      if (GB_IS_SITE (b))
      {
            galeon_shell_new_tab (galeon_shell, w, tab, final_url, flags);
            gb_site_set_time_visited_now (GB_SITE (b));
      }
      else if (GB_IS_FOLDER (b))
      {
            GbBookmark *bi;
            int count = 0;
            gboolean replace;
            
            /* count the number of activated bookmarks */
            for (bi = GB_FOLDER (b)->child; bi; bi = bi->next)
            {
                  if (GB_IS_SITE (bi))
                  {
                        count++;
                  }
            }
            
            if (!confirm_open_many_bookmarks (w, count))
            {
                  g_free (smarted_url);
                  return;
            }

            replace = galeon_tab_is_empty (tab);
            
            if (flags & GALEON_NEW_TAB_IN_NEW_WINDOW)
            {
                        /* When opening in new windows replace about:blank only
                         * if it's the sole tab in the window
                         */
                        if (gtk_notebook_get_n_pages (GTK_NOTEBOOK (w->priv->notebook)) > 1)
                        {
                                replace = FALSE;
                        }

                  for (bi = GB_FOLDER (b)->child; bi; bi = bi->next)
                  {
                        if (!GB_IS_SITE (bi)) continue;

                                if (replace)
                                {
                                        galeon_window_load_url (w, GB_SITE (bi)->url);
                                        replace = FALSE;
                                }
                                else
                                {
                                        galeon_shell_new_tab (galeon_shell, w, tab, 
                                                              GB_SITE (bi)->url, flags);
                                }
                        gb_site_set_time_visited_now (GB_SITE (bi));
                  }
            }
            else
            {
                  GaleonTab *jump_to_tab;
                  gboolean jump_to;
                  
                  jump_to = flags & GALEON_NEW_TAB_JUMP;
                  if (flags & GALEON_NEW_TAB_DONT_JUMP_TO) jump_to = FALSE;
                  
                  /* Open all bookmarks in order in the background.  Jumping
                   * to them automatically is a major performance hit with
                   * >3 bookmarks in a folder.  Once all bookmarks are opened,
                   * we can efficiently jump to the first one if 'jump to
                   * new tabs automatically' is enabled.
                   */
                  flags |= GALEON_NEW_TAB_DONT_JUMP_TO;
                  
                  jump_to_tab = NULL;
                  for (bi = GB_FOLDER (b)->child; bi; bi = bi->next)
                  {
                        if (!GB_IS_SITE (bi)) continue;

                                if (replace)
                                {
                                        galeon_window_load_url (w, GB_SITE (bi)->url);
                                        replace = FALSE;
                                }
                                else
                                {
                                        tab = galeon_shell_new_tab (galeon_shell, w, tab,
                                                                    GB_SITE (bi)->url, 
                                                                    flags);
                                }
                        gb_site_set_time_visited_now (GB_SITE (bi));

                        if (jump_to_tab == NULL) jump_to_tab = tab;
                  }

                  if (jump_to && jump_to_tab != NULL)
                  {
                        galeon_window_jump_to_tab (w, jump_to_tab);
                  }
            }
      }
      else
      {
            g_warning ("don't know what to do...");
      }

      g_free (smarted_url);
}

static void
galeon_window_bookmark_activated_cb (GObject *sender,
                             GbBookmarkEventActivated *ev,
                             GaleonWindow *w)
{
      galeon_window_bookmark_activate (w, ev);
}

void
galeon_window_show_js_console (GaleonWindow *window)
{
      GaleonJSConsole *jsconsole;

      jsconsole = galeon_embed_shell_get_js_console (embed_shell);
      g_return_if_fail (jsconsole);

      gtk_window_set_transient_for (GTK_WINDOW(jsconsole),
                              GTK_WINDOW(window));
      gtk_window_present (GTK_WINDOW(jsconsole));
}

void
galeon_window_show_page_info (GaleonWindow *window, PageInfoDialogPage page)
{
      GaleonDialog *dialog = page_info_dialog_new(GTK_WIDGET(window));
      page_info_dialog_set_current_page (PAGE_INFO_DIALOG (dialog), page);
      galeon_dialog_show(dialog);
}

void
galeon_window_show_find (GaleonWindow *window)
{                        
      GaleonDialog *dialog;
      GaleonEmbed *embed;

      if (!window->priv->find_dialog)
      {
            embed = galeon_window_get_active_embed (window);
            g_return_if_fail (GTK_IS_WINDOW(window));

            dialog = find_dialog_new_with_parent (GTK_WIDGET(window),
                                          embed);
            window->priv->find_dialog = dialog;

            g_object_add_weak_pointer(G_OBJECT (dialog),
                                (gpointer *) &window->priv->find_dialog);
      }
      galeon_dialog_show (window->priv->find_dialog);
}

void
galeon_window_show_history (GaleonWindow *window)
{
      GaleonEmbed *embed;

      embed = galeon_window_get_active_embed (window);
      g_return_if_fail (embed != NULL);

      window->priv->history_dialog = history_dialog_new_with_parent 
                                    (GTK_WIDGET(window),
                                     embed,
                                     FALSE);
      g_object_add_weak_pointer 
                        (G_OBJECT(window->priv->history_dialog),
                         (gpointer)&window->priv->history_dialog);

      galeon_dialog_show (window->priv->history_dialog);
}

static char *
galeon_window_gb_location_source_get_location (GbLocationSource *src)
{
      GaleonWindow *window;
      GaleonTab *tab;
      const gchar *location;

      window = GALEON_WINDOW (src);
      g_return_val_if_fail (window, NULL);

      tab = galeon_window_get_active_tab (window);
      g_return_val_if_fail (tab, NULL);

      location = galeon_tab_get_location (tab);
      if (!location) location = "";

      return g_strdup (location);
}

static char *
galeon_window_gb_location_source_get_title (GbLocationSource *src)
{
      GaleonWindow *window;
      GaleonTab *tab;
      const gchar *title;

      window = GALEON_WINDOW (src);
      g_return_val_if_fail (window, NULL);

      tab = galeon_window_get_active_tab (window);
      g_return_val_if_fail (tab, NULL);

      title = galeon_tab_get_title (tab);
      if (!title) 
      {
            return galeon_window_gb_location_source_get_location (src);
      }

      return g_strdup (title);
}


static void
tab_site_visited_cb (GaleonTab *tab, const gchar *url, const gchar *title,
                 GaleonWindow *window)
{
      g_return_if_fail (GALEON_IS_WINDOW (window));

      /* ignore about:blank, it's not shown in any other history either */
      if (!url || !strcmp (url, "about:blank")) return;

      galeon_window_recent_history_visited (window->priv->recent_history, url, title);
}


/**
 * Set the Zoom on the current active tab
 */
void
galeon_window_set_zoom (GaleonWindow *window, 
                  gint zoom)
{
      GaleonEmbed *embed;

        g_return_if_fail (GALEON_IS_WINDOW (window));
        
      embed = galeon_window_get_active_embed (window);
        g_return_if_fail (embed != NULL);
      
        galeon_embed_zoom_set (embed, zoom);
}

/**
 * Get the toolbar
 */
EggEditableToolbar *
galeon_window_get_toolbar (GaleonWindow *window)
{
      return window->priv->egg_toolbar;
}

/**
 *  Clear the recent history menu
 */
void
galeon_window_clear_history (GaleonWindow *window)
{
      GList *tabs, *item;

      g_return_if_fail (GALEON_IS_WINDOW (window));

      galeon_window_recent_history_clear (window->priv->recent_history);

      tabs = galeon_window_get_tabs (window);
      for (item = tabs ; item ; item = item->next)
      {
            GaleonTab *tab = GALEON_TAB (item->data);
            GaleonEmbed *embed = galeon_tab_get_embed (tab);

            galeon_embed_shistory_clear (embed);
      }
      g_list_free (tabs);

      galeon_action_update (GALEON_ACTION (ACTION_ITEM("GoBack")));
      galeon_action_update (GALEON_ACTION (ACTION_ITEM("GoForward")));
      galeon_action_update (GALEON_ACTION (ACTION_ITEM("GoBackWithArrow")));
      galeon_action_update (GALEON_ACTION (ACTION_ITEM("GoForwardWithArrow")));
}

/**
 *  Little helper structure that we use while iterating through the
 *  dropped urls
 */
03583 typedef struct {
      gboolean first_url;
      GaleonTab * tab;
      GaleonWindow * window;
} UrlReceiveContext;


static void
each_url_receive_data_binder (const char * url, const char * title, 
                        gpointer data )
{
      UrlReceiveContext * context = (UrlReceiveContext*)data;

      if (context->first_url && context->tab)
      {
            GaleonEmbed *embed = galeon_tab_get_embed (context->tab);
            /**
             * The first url is special: if the drag was to an
             * existing tab, load it there
             */
            galeon_embed_load_url (embed, url);
      }
      else
      {
            context->tab =
                  galeon_shell_new_tab (galeon_shell, context->window,
                                    context->tab, url,
                                    GALEON_NEW_TAB_IN_EXISTING_WINDOW |
                                    GALEON_NEW_TAB_APPEND);
      }
      context->first_url = FALSE;
}


static void
galeon_window_tab_drag_data_received_cb(GtkWidget *widget,
                              GdkDragContext *dc,
                              gint x, gint y,
                              GtkSelectionData *selection_data,
                              guint info,
                              guint t,
                              GtkWidget * child)
{
      UrlReceiveContext context;
      GtkWidget * toplevel;
      context.first_url = TRUE;
      context.tab = GALEON_TAB (child);

      toplevel = gtk_widget_get_toplevel (widget);
      g_return_if_fail (GALEON_IS_WINDOW (toplevel));
      
      context.window = GALEON_WINDOW(toplevel);

      galeon_dnd_drag_data_receive (widget, dc, x, y, selection_data,
                   info, t, &context, each_url_receive_data_binder);
}

static gboolean
tab_modal_alert_cb (GaleonEmbed *embed,
                GaleonTab *tab)
{
      GaleonWindow *window;
      char *address;

      window = galeon_tab_get_window (tab);
      g_return_val_if_fail (GALEON_IS_WINDOW (window), FALSE);

      galeon_window_jump_to_tab (window, tab);

      /* make sure the location entry shows the real URL of the tab's page */
      address = galeon_embed_get_location (embed, TRUE, TRUE);
      galeon_window_set_location_entry_location (window, address);
      g_free (address);

      /* don't suppress alert */
      return FALSE;
}


static void       
galeon_window_tab_added_cb  (GulNotebook *notebook, GtkWidget *child, GaleonWindow *window)
{
      GaleonEmbed *embed;
      GtkWidget * label = gtk_notebook_get_tab_label (GTK_NOTEBOOK (notebook), child);

      galeon_dnd_url_list_drag_dest_set (label);

      g_signal_connect (G_OBJECT(label), "drag_data_received",
                    G_CALLBACK(galeon_window_tab_drag_data_received_cb),
                    child);

      update_tabs_menu_sensitivity (window);

      /* Sync the tab and window */
      sync_tab_title (GALEON_TAB (child), NULL, window);
      sync_tab_load_status (GALEON_TAB (child), NULL, window);

      /* And connect the callbacks */
      g_signal_connect_object (G_OBJECT (child), "notify::title",
                         G_CALLBACK (sync_tab_title), window, 0);
      g_signal_connect_object (G_OBJECT (child), "notify::load-status",
                         G_CALLBACK (sync_tab_load_status), window, 0);
      g_signal_connect_object (G_OBJECT (child), "notify::visibility",
                         G_CALLBACK (sync_tab_visibility), window, 0);
      g_signal_connect_object (G_OBJECT (child), "site_visited",
                         G_CALLBACK (tab_site_visited_cb), window, 0);

      embed = galeon_tab_get_embed (GALEON_TAB (child));
      g_signal_connect_object (G_OBJECT (embed), "ge-modal-alert",
                         G_CALLBACK (tab_modal_alert_cb), child, 0);
      g_signal_connect_object (G_OBJECT (embed), "ge-show-js-console",
                         G_CALLBACK (galeon_window_show_js_console), window,
                         G_CONNECT_SWAPPED);
}


static void       
galeon_window_tab_removed_cb (GulNotebook *notebook, GtkWidget *child, GaleonWindow *window)
{
      GaleonEmbed *embed;

      update_tabs_menu_sensitivity (window);

      g_signal_handlers_disconnect_by_func (G_OBJECT (child),
                                    G_CALLBACK (sync_tab_title),
                                    window);
      g_signal_handlers_disconnect_by_func (G_OBJECT (child),
                                    G_CALLBACK (sync_tab_load_status),
                                    window);
      g_signal_handlers_disconnect_by_func (G_OBJECT (child),
                                    G_CALLBACK (sync_tab_visibility),
                                    window);
      g_signal_handlers_disconnect_by_func (G_OBJECT (child),
                                    G_CALLBACK (tab_site_visited_cb),
                                    window);

      embed = galeon_tab_get_embed (GALEON_TAB (child));
      g_signal_handlers_disconnect_by_func (G_OBJECT (embed),
                                    G_CALLBACK (tab_modal_alert_cb),
                                    child);
      g_signal_handlers_disconnect_by_func (G_OBJECT (embed),
                                    G_CALLBACK (galeon_window_show_js_console),
                                    window);

      /* Update the spinner */
      galeon_action_update (GALEON_ACTION (window->priv->spinner_action));
}

static void
galeon_window_tabs_reordered_cb (GulNotebook *notebook, GaleonWindow *window)
{
      update_tabs_menu_sensitivity (window);
}

static gboolean
galeon_window_tab_delete_cb (GulNotebook *notebook, GtkWidget *child, GaleonWindow *window)
{
      GaleonEmbed *embed;

      g_return_val_if_fail (GALEON_IS_TAB (child), FALSE);
      embed = galeon_tab_get_embed (GALEON_TAB (child));

      if (galeon_embed_has_modified_forms (GALEON_EMBED (embed)))
      {
            return !confirm_close_with_modified_forms (window, GALEON_TAB (child));
      }

      return FALSE;
}


static void
galeon_window_tab_detached_cb (GulNotebook *notebook, gint page, 
                          gint x, gint y, GaleonWindow *window)
{
      GaleonWindow *new_win;
      GaleonTab *tab;

      tab = get_tab_from_page_num (GTK_NOTEBOOK (notebook), page);
      new_win = galeon_window_new ();

      galeon_window_reparent_tab (new_win, window, tab);

      gtk_widget_show (GTK_WIDGET (new_win));
}

void
galeon_window_reparent_tab (GaleonWindow *window, GaleonWindow *source,
                        GaleonTab *tab)
{
      gul_notebook_move_page (GUL_NOTEBOOK (source->priv->notebook),
                        GUL_NOTEBOOK (window->priv->notebook),
                        GTK_WIDGET (tab), -1);
}

Generated by  Doxygen 1.6.0   Back to index