diff --git a/HACKING b/HACKING index 22c846aa..ae54476f 100644 --- a/HACKING +++ b/HACKING @@ -21,16 +21,16 @@ Source file example: return; #ifdef BAR_STRICT - if(bar == FOO_N) + if (bar == FOO_N) { - g_print("illegal value for 'bar'.\n"); + g_print ("illegal value for 'bar'.\n"); return; } #endif // this is an example gint n; - switch(bar) + switch (bar) { case FOO_FOO: n = bar + 1; @@ -43,9 +43,9 @@ Source file example: } guint i; - for(i = 0; i < n; i++) + for (i = 0; i < n; i++) { - g_print("%s\n", foo); + g_print ("%s\n", foo); } } @@ -74,12 +74,18 @@ Header file example: typedef struct { - FooEnum fooBar; + FooEnum foo_bar; } FooStruct; // -- Declarations void - foobar(FooEnum, const gchar*); + foo_bar (FooEnum bar, + const gchar* foo); + + const gchar* + foo_foo (FooStruct foo_struct, + guint number, + gboolean flag); #endif /* !__FOO_H__ */ diff --git a/katze/katze-throbber.c b/katze/katze-throbber.c index fcaae5e6..0565f345 100644 --- a/katze/katze-throbber.c +++ b/katze/katze-throbber.c @@ -222,11 +222,9 @@ katze_throbber_destroy (GtkObject *object) KatzeThrobberPrivate* priv = throbber->priv; katze_assign (priv->icon_name, NULL); - if (priv->pixbuf) - katze_object_assign (priv->pixbuf, NULL); + katze_object_assign (priv->pixbuf, NULL); katze_assign (priv->static_icon_name, NULL); - if (priv->static_pixbuf) - katze_object_assign (priv->static_pixbuf, NULL); + katze_object_assign (priv->static_pixbuf, NULL); katze_assign (priv->static_stock_id, NULL); GTK_OBJECT_CLASS (katze_throbber_parent_class)->destroy (object); diff --git a/katze/katze-throbber.h b/katze/katze-throbber.h index 17f570b8..6f1be411 100644 --- a/katze/katze-throbber.h +++ b/katze/katze-throbber.h @@ -38,7 +38,8 @@ typedef struct _KatzeThrobberClass KatzeThrobberClass; struct _KatzeThrobber { - GtkMisc parent_object; + GtkMisc parent_instance; + KatzeThrobberPrivate* priv; }; diff --git a/src/Makefile.am b/src/Makefile.am index 2b98976a..82951045 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -15,11 +15,14 @@ bin_PROGRAMS = \ midori_SOURCES = \ main.c main.h \ - browser.c browser.h \ + midori-browser.c midori-browser.h \ + midori-panel.c midori-panel.h \ + midori-trash.c midori-trash.h \ + midori-webview.c midori-webview.h \ + midori-websettings.c midori-websettings.h \ prefs.c prefs.h \ webSearch.c webSearch.h \ helpers.c helpers.h \ - webView.c webView.h \ sokoke.c sokoke.h \ conf.c conf.h \ search.c search.h \ diff --git a/src/browser.c b/src/browser.c deleted file mode 100644 index 88044e39..00000000 --- a/src/browser.c +++ /dev/null @@ -1,1775 +0,0 @@ -/* - Copyright (C) 2007-2008 Christian Dywan - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - See the file COPYING for the full license text. -*/ - -#include "browser.h" - -#include "helpers.h" -#include "prefs.h" -#include "sokoke.h" -#include "ui.h" -#include "webView.h" -#include "webSearch.h" -#include "../katze/katze.h" - -#include -#include - -// -- GTK+ signal handlers begin here - -void on_action_window_new_activate(GtkAction* action, CBrowser* browser) -{ - browser_new(NULL); -} - -void on_action_tab_new_activate(GtkAction* action, CBrowser* browser) -{ - browser_new(browser); - update_browser_actions(browser); -} - -void on_action_open_activate(GtkAction* action, CBrowser* browser) -{ - GtkWidget* dialog = gtk_file_chooser_dialog_new("Open file" - , GTK_WINDOW(browser->window) - , GTK_FILE_CHOOSER_ACTION_OPEN - , GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL - , GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT - , NULL); - gtk_window_set_icon_name(GTK_WINDOW(dialog), GTK_STOCK_OPEN); - if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) - { - gchar* sFilename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); - webView_open(get_nth_webView(-1, browser), sFilename); - g_free(sFilename); - } - gtk_widget_destroy(dialog); -} - -void on_action_tab_close_activate(GtkAction* action, CBrowser* browser) -{ - webView_close(get_nth_webView(-1, browser), browser); -} - -void on_action_window_close_activate(GtkAction* action, CBrowser* browser) -{ - gtk_widget_destroy(browser->window); -} - -void on_action_quit_activate(GtkAction* action, CBrowser* browser) -{ - gtk_main_quit(); -} - -void on_action_edit_activate(GtkAction* action, CBrowser* browser) -{ - update_edit_items(browser); -} - -void on_action_cut_activate(GtkAction* action, CBrowser* browser) -{ - GtkWidget* widget = gtk_window_get_focus(GTK_WINDOW(browser->window)); - if(G_LIKELY(widget)) - g_signal_emit_by_name(widget, "cut-clipboard"); -} - -void on_action_copy_activate(GtkAction* action, CBrowser* browser) -{ - GtkWidget* widget = gtk_window_get_focus(GTK_WINDOW(browser->window)); - if(G_LIKELY(widget)) - g_signal_emit_by_name(widget, "copy-clipboard"); -} - -void on_action_paste_activate(GtkAction* action, CBrowser* browser) -{ - GtkWidget* widget = gtk_window_get_focus(GTK_WINDOW(browser->window)); - if(G_LIKELY(widget)) - g_signal_emit_by_name(widget, "paste-clipboard"); -} - -void on_action_delete_activate(GtkAction* action, CBrowser* browser) -{ - GtkWidget* widget = gtk_window_get_focus(GTK_WINDOW(browser->window)); - if(G_LIKELY(widget)) - { - if(WEBKIT_IS_WEB_VIEW(widget)) - webkit_web_view_delete_selection(WEBKIT_WEB_VIEW(widget)); - else if(GTK_IS_EDITABLE(widget)) - gtk_editable_delete_selection(GTK_EDITABLE(widget)); - } -} - -void on_action_selectAll_activate(GtkAction* action, CBrowser* browser) -{ - GtkWidget* widget = gtk_window_get_focus(GTK_WINDOW(browser->window)); - if(G_LIKELY(widget)) - { - if(GTK_IS_ENTRY(widget)) - gtk_editable_select_region(GTK_EDITABLE(widget), 0, -1); - else - g_signal_emit_by_name(widget, "select-all"); - } -} - -void on_action_find_activate(GtkAction* action, CBrowser* browser) -{ - if(GTK_WIDGET_VISIBLE(browser->findbox)) - { - GtkWidget* webView = get_nth_webView(-1, browser); - webkit_web_view_unmark_text_matches(WEBKIT_WEB_VIEW(webView)); - gtk_toggle_tool_button_set_active( - GTK_TOGGLE_TOOL_BUTTON(browser->findbox_highlight), FALSE); - gtk_widget_hide(browser->findbox); - } - else - { - GtkWidget* icon = gtk_image_new_from_stock(GTK_STOCK_FIND, GTK_ICON_SIZE_MENU); - sexy_icon_entry_set_icon(SEXY_ICON_ENTRY(browser->findbox_text) - , SEXY_ICON_ENTRY_PRIMARY, GTK_IMAGE(icon)); - gtk_entry_set_text(GTK_ENTRY(browser->findbox_text), ""); - gtk_widget_show(browser->findbox); - gtk_widget_grab_focus(GTK_WIDGET(browser->findbox_text)); - } -} - -static void findbox_find(gboolean forward, CBrowser* browser) -{ - const gchar* text = gtk_entry_get_text(GTK_ENTRY(browser->findbox_text)); - const gboolean caseSensitive = gtk_toggle_tool_button_get_active( - GTK_TOGGLE_TOOL_BUTTON(browser->findbox_case)); - GtkWidget* webView = get_nth_webView(-1, browser); - if(GTK_WIDGET_VISIBLE(browser->findbox)) - webkit_web_view_unmark_text_matches(WEBKIT_WEB_VIEW(webView)); - gboolean found = webkit_web_view_search_text(WEBKIT_WEB_VIEW(webView) - , text, caseSensitive, forward, TRUE); - if(GTK_WIDGET_VISIBLE(browser->findbox)) - { - GtkWidget* icon; - if(found) - icon = gtk_image_new_from_stock(GTK_STOCK_FIND, GTK_ICON_SIZE_MENU); - else - icon = gtk_image_new_from_stock(GTK_STOCK_STOP, GTK_ICON_SIZE_MENU); - sexy_icon_entry_set_icon(SEXY_ICON_ENTRY(browser->findbox_text) - , SEXY_ICON_ENTRY_PRIMARY, GTK_IMAGE(icon)); - webkit_web_view_mark_text_matches(WEBKIT_WEB_VIEW(webView), text, caseSensitive, 0); - const gboolean highlight = gtk_toggle_tool_button_get_active( - GTK_TOGGLE_TOOL_BUTTON(browser->findbox_highlight)); - webkit_web_view_set_highlight_text_matches(WEBKIT_WEB_VIEW(webView), highlight); - } -} - -void on_action_find_next_activate(GtkAction* action, CBrowser* browser) -{ - findbox_find(TRUE, browser); -} - -void on_action_find_previous_activate(GtkAction* action, CBrowser* browser) -{ - findbox_find(FALSE, browser); -} - -void on_findbox_highlight_toggled(GtkToggleToolButton* toolitem, CBrowser* browser) -{ - GtkWidget* webView = get_nth_webView(-1, browser); - const gboolean highlight = gtk_toggle_tool_button_get_active(toolitem); - webkit_web_view_set_highlight_text_matches(WEBKIT_WEB_VIEW(webView), highlight); -} - -void on_findbox_button_close_clicked(GtkWidget* widget, CBrowser* browser) -{ - gtk_widget_hide(browser->findbox); -} - -void on_action_preferences_activate(GtkAction* action, CBrowser* browser) -{ - // Show the preferences dialog. Create it if necessary. - static GtkWidget* dialog; - if(GTK_IS_DIALOG(dialog)) - gtk_window_present(GTK_WINDOW(dialog)); - else - { - dialog = prefs_preferences_dialog_new(browser); - gtk_widget_show(dialog); - } -} - -static void on_toolbar_navigation_notify_style(GObject* object, GParamSpec* arg1 - , CBrowser* browser) -{ - if(config->toolbarStyle == CONFIG_TOOLBAR_DEFAULT) - { - gtk_toolbar_set_style(GTK_TOOLBAR(browser->navibar) - , config_to_toolbarstyle(config->toolbarStyle)); - } -} - -void on_action_toolbar_navigation_activate(GtkToggleAction* action, CBrowser* browser) -{ - config->toolbarNavigation = gtk_toggle_action_get_active(action); - sokoke_widget_set_visible(browser->navibar, config->toolbarNavigation); -} - -void on_action_toolbar_bookmarks_activate(GtkToggleAction* action, CBrowser* browser) -{ - config->toolbarBookmarks = gtk_toggle_action_get_active(action); - sokoke_widget_set_visible(browser->bookmarkbar, config->toolbarBookmarks); -} - -void on_action_toolbar_downloads_activate(GtkToggleAction* action, CBrowser* browser) -{ - /*config->toolbarDownloads = gtk_toggle_action_get_active(action); - sokoke_widget_set_visible(browser->downloadbar, config->toolbarDownloads);*/ -} - -void on_action_toolbar_status_activate(GtkToggleAction* action, CBrowser* browser) -{ - config->toolbarStatus = gtk_toggle_action_get_active(action); - sokoke_widget_set_visible(browser->statusbar, config->toolbarStatus); -} - -void on_action_refresh_activate(GtkAction* action, CBrowser* browser) -{ - /*GdkModifierType state = (GdkModifierType)0; - gint x, y; gdk_window_get_pointer(NULL, &x, &y, &state); - gboolean fromCache = state & GDK_SHIFT_MASK;*/ - webkit_web_view_reload(WEBKIT_WEB_VIEW(get_nth_webView(-1, browser))); -} - -void on_action_refresh_stop_activate(GtkAction* action, CBrowser* browser) -{ - gchar* stockId; g_object_get(action, "stock-id", &stockId, NULL); - // Refresh or stop, depending on the stock id - if(!strcmp(stockId, GTK_STOCK_REFRESH)) - { - /*GdkModifierType state = (GdkModifierType)0; - gint x, y; gdk_window_get_pointer(NULL, &x, &y, &state); - gboolean fromCache = state & GDK_SHIFT_MASK;*/ - webkit_web_view_reload(WEBKIT_WEB_VIEW(get_nth_webView(-1, browser))); - } - else - webkit_web_view_stop_loading(WEBKIT_WEB_VIEW(get_nth_webView(-1, browser))); - g_free(stockId); -} - -void on_action_stop_activate(GtkAction* action, CBrowser* browser) -{ - webkit_web_view_stop_loading(WEBKIT_WEB_VIEW(get_nth_webView(-1, browser))); -} - -void on_action_zoom_in_activate(GtkAction* action, CBrowser* browser) -{ - /*GtkWidget* webView = get_nth_webView(-1, browser); - const gfloat zoom = webkit_web_view_get_text_multiplier(WEBKIT_WEB_VIEW(webView)); - webkit_web_view_set_text_multiplier(WEBKIT_WEB_VIEW(webView), zoom + 0.1);*/ -} - -void on_action_zoom_out_activate(GtkAction* action, CBrowser* browser) -{ - /*GtkWidget* webView = get_nth_webView(-1, browser); - const gfloat zoom = webView_get_text_size(WEBKIT_WEB_VIEW(webView)); - webkit_web_view_set_text_multiplier(WEBKIT_WEB_VIEW(webView), zoom - 0.1);*/ -} - -void on_action_zoom_normal_activate(GtkAction* action, CBrowser* browser) -{ - //webkit_web_view_set_text_multiplier(WEBKIT_WEB_VIEW(get_nth_webView(-1, browser)), 1); -} - -void on_action_source_view_activate(GtkAction* action, CBrowser* browser) -{ - /*GtkWidget* webView = get_nth_webView(-1, browser); - gchar* source = webkit_web_view_copy_source(WEBKIT_WEB_VIEW(webView)); - webkit_web_view_load_html_string(WEBKIT_WEB_VIEW(webView), source, ""); - g_free(source);*/ -} - -void on_action_fullscreen_activate(GtkAction* action, CBrowser* browser) -{ - GdkWindowState state = gdk_window_get_state(browser->window->window); - if(state & GDK_WINDOW_STATE_FULLSCREEN) - gtk_window_unfullscreen(GTK_WINDOW(browser->window)); - else - gtk_window_fullscreen(GTK_WINDOW(browser->window)); -} - -void on_action_back_activate(GtkAction* action, CBrowser* browser) -{ - webkit_web_view_go_back(WEBKIT_WEB_VIEW(get_nth_webView(-1, browser))); -} - -void on_action_forward_activate(GtkAction* action, CBrowser* browser) -{ - webkit_web_view_go_forward(WEBKIT_WEB_VIEW(get_nth_webView(-1, browser))); -} - -void on_action_home_activate(GtkAction* action, CBrowser* browser) -{ - webView_open(get_nth_webView(-1, browser), config->homepage); -} - -void on_action_location_activate(GtkAction* action, CBrowser* browser) -{ - if(GTK_WIDGET_VISIBLE(browser->navibar)) - gtk_widget_grab_focus(browser->location); - else - { - // TODO: We should offer all of the toolbar location's features here - GtkWidget* dialog; - dialog = gtk_dialog_new_with_buttons("Open location" - , GTK_WINDOW(browser->window) - , GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR - , GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL - , GTK_STOCK_JUMP_TO, GTK_RESPONSE_ACCEPT - , NULL); - gtk_window_set_icon_name(GTK_WINDOW(dialog), GTK_STOCK_JUMP_TO); - gtk_container_set_border_width(GTK_CONTAINER(dialog), 5); - gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), 5); - GtkWidget* hbox = gtk_hbox_new(FALSE, 8); - gtk_container_set_border_width(GTK_CONTAINER(hbox), 5); - GtkWidget* label = gtk_label_new_with_mnemonic("_Location:"); - gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); - GtkWidget* entry = gtk_entry_new(); - gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE); - gtk_box_pack_start(GTK_BOX(hbox), entry, FALSE, FALSE, 0); - gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox); - gtk_widget_show_all(hbox); - gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT); - if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) - { - gtk_entry_set_text(GTK_ENTRY(browser->location) - , gtk_entry_get_text(GTK_ENTRY(entry))); - GdkEventKey event; - event.keyval = GDK_Return; - on_location_key_down(browser->location, &event, browser); - } - gtk_widget_destroy(dialog); - } -} - -void on_action_webSearch_activate(GtkAction* action, CBrowser* browser) -{ - if(GTK_WIDGET_VISIBLE(browser->webSearch) - && GTK_WIDGET_VISIBLE(browser->navibar)) - gtk_widget_grab_focus(browser->webSearch); - else - { - // TODO: We should offer all of the toolbar search's features here - GtkWidget* dialog = gtk_dialog_new_with_buttons("Web search" - , GTK_WINDOW(browser->window) - , GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR - , GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL - , GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT - , NULL); - gtk_window_set_icon_name(GTK_WINDOW(dialog), GTK_STOCK_FIND); - gtk_container_set_border_width(GTK_CONTAINER(dialog), 5); - gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), 5); - GtkWidget* hbox = gtk_hbox_new(FALSE, 8); - gtk_container_set_border_width(GTK_CONTAINER(hbox), 5); - GtkWidget* label = gtk_label_new_with_mnemonic("_Location:"); - gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); - GtkWidget* entry = gtk_entry_new(); - gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE); - gtk_box_pack_start(GTK_BOX(hbox), entry, FALSE, FALSE, 0); - gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox); - gtk_widget_show_all(hbox); - gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT); - if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) - { - gtk_entry_set_text(GTK_ENTRY(browser->webSearch) - , gtk_entry_get_text(GTK_ENTRY(entry))); - on_webSearch_activate(browser->webSearch, browser); - } - gtk_widget_destroy(dialog); - } -} - -void on_menu_tabsClosed_activate(GtkWidget* widget, CBrowser* browser) -{ - GtkWidget* menu = gtk_menu_new(); - guint n = katze_xbel_folder_get_n_items(tabtrash); - GtkWidget* menuitem; - guint i; - for(i = 0; i < n; i++) - { - KatzeXbelItem* item = katze_xbel_folder_get_nth_item(tabtrash, i); - const gchar* title = katze_xbel_item_get_title(item); - const gchar* uri = katze_xbel_bookmark_get_href(item); - menuitem = gtk_image_menu_item_new_with_label(title ? title : uri); - // FIXME: Get the real icon - GtkWidget* icon = gtk_image_new_from_stock(GTK_STOCK_FILE, GTK_ICON_SIZE_MENU); - gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), icon); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); - g_object_set_data(G_OBJECT(menuitem), "KatzeXbelItem", item); - g_signal_connect(menuitem, "activate", G_CALLBACK(on_menu_tabsClosed_item_activate), browser); - gtk_widget_show(menuitem); - } - - menuitem = gtk_separator_menu_item_new(); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); - gtk_widget_show(menuitem); - GtkAction* action = gtk_action_group_get_action( - browser->actiongroup, "TabsClosedClear"); - menuitem = gtk_action_create_menu_item(action); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); - gtk_widget_show(menuitem); - sokoke_widget_popup(widget, GTK_MENU(menu), NULL); -} - -void on_menu_tabsClosed_item_activate(GtkWidget* menuitem, CBrowser* browser) -{ - // Create a new webView with an uri which has been closed before - KatzeXbelItem* item = g_object_get_data(G_OBJECT(menuitem), "KatzeXbelItem"); - const gchar* uri = katze_xbel_bookmark_get_href(item); - CBrowser* curBrowser = browser_new(browser); - webView_open(curBrowser->webView, uri); - katze_xbel_item_unref(item); - update_browser_actions(curBrowser); -} - -void on_action_tabsClosed_undo_activate(GtkAction* action, CBrowser* browser) -{ - // Open the most recent tabtrash item - KatzeXbelItem* item = katze_xbel_folder_get_nth_item(tabtrash, 0); - const gchar* uri = katze_xbel_bookmark_get_href(item); - CBrowser* curBrowser = browser_new(browser); - webView_open(curBrowser->webView, uri); - katze_xbel_item_unref(item); - update_browser_actions(curBrowser); -} - -void on_action_tabsClosed_clear_activate(GtkAction* action, CBrowser* browser) -{ - // Clear the closed tabs list - katze_xbel_item_unref(tabtrash); - tabtrash = katze_xbel_folder_new(); - update_browser_actions(browser); -} - -void on_action_link_tab_new_activate(GtkAction* action, CBrowser* browser) -{ - CBrowser* curBrowser = browser_new(browser); - webView_open(curBrowser->webView, browser->elementUri); -} - -void on_action_link_tab_current_activate(GtkAction* action, CBrowser* browser) -{ - webView_open(get_nth_webView(-1, browser), browser->elementUri); -} - -void on_action_link_window_new_activate(GtkAction* action, CBrowser* browser) -{ - CBrowser* curBrowser = browser_new(NULL); - webView_open(curBrowser->webView, browser->elementUri); -} - -void on_action_link_saveWith_activate(GtkAction* action, CBrowser* browser) -{ - spawn_protocol_command("download", browser->elementUri); -} - -void on_action_link_copy_activate(GtkAction* action, CBrowser* browser) -{ - GtkClipboard* clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD); - gtk_clipboard_set_text(clipboard, browser->elementUri, -1); -} - -static void browser_editBookmark_dialog_new(KatzeXbelItem* bookmark, CBrowser* browser) -{ - gboolean newBookmark = !bookmark; - GtkWidget* dialog = gtk_dialog_new_with_buttons( - newBookmark ? "New bookmark" : "Edit bookmark" - , GTK_WINDOW(browser->window) - , GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR - , GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL - , newBookmark ? GTK_STOCK_ADD : GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT - , NULL); - gtk_window_set_icon_name(GTK_WINDOW(dialog) - , newBookmark ? GTK_STOCK_ADD : GTK_STOCK_REMOVE); - gtk_container_set_border_width(GTK_CONTAINER(dialog), 5); - gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), 5); - GtkSizeGroup* sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); - - if(newBookmark) - bookmark = katze_xbel_bookmark_new(); - - GtkWidget* hbox = gtk_hbox_new(FALSE, 8); - gtk_container_set_border_width(GTK_CONTAINER(hbox), 5); - GtkWidget* label = gtk_label_new_with_mnemonic("_Title:"); - gtk_size_group_add_widget(sizegroup, label); - gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); - GtkWidget* entry_title = gtk_entry_new(); - gtk_entry_set_activates_default(GTK_ENTRY(entry_title), TRUE); - if(!newBookmark) - { - const gchar* title = katze_xbel_item_get_title(bookmark); - gtk_entry_set_text(GTK_ENTRY(entry_title), title ? title : ""); - } - gtk_box_pack_start(GTK_BOX(hbox), entry_title, TRUE, TRUE, 0); - gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox); - gtk_widget_show_all(hbox); - - hbox = gtk_hbox_new(FALSE, 8); - gtk_container_set_border_width(GTK_CONTAINER(hbox), 5); - label = gtk_label_new_with_mnemonic("_Description:"); - gtk_size_group_add_widget(sizegroup, label); - gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); - GtkWidget* entry_desc = gtk_entry_new(); - gtk_entry_set_activates_default(GTK_ENTRY(entry_desc), TRUE); - if(!newBookmark) - { - const gchar* desc = katze_xbel_item_get_desc(bookmark); - gtk_entry_set_text(GTK_ENTRY(entry_desc), desc ? desc : ""); - } - gtk_box_pack_start(GTK_BOX(hbox), entry_desc, TRUE, TRUE, 0); - gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox); - gtk_widget_show_all(hbox); - - GtkWidget* entry_uri = NULL; - if(katze_xbel_item_is_bookmark(bookmark)) - { - hbox = gtk_hbox_new(FALSE, 8); - gtk_container_set_border_width(GTK_CONTAINER(hbox), 5); - label = gtk_label_new_with_mnemonic("_Uri:"); - gtk_size_group_add_widget(sizegroup, label); - gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); - entry_uri = gtk_entry_new(); - gtk_entry_set_activates_default(GTK_ENTRY(entry_uri), TRUE); - if(!newBookmark) - gtk_entry_set_text(GTK_ENTRY(entry_uri), katze_xbel_bookmark_get_href(bookmark)); - gtk_box_pack_start(GTK_BOX(hbox), entry_uri, TRUE, TRUE, 0); - gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox); - gtk_widget_show_all(hbox); - } - - GtkWidget* combo_folder = NULL; - if(newBookmark) - { - hbox = gtk_hbox_new(FALSE, 8); - gtk_container_set_border_width(GTK_CONTAINER(hbox), 5); - label = gtk_label_new_with_mnemonic("_Folder:"); - gtk_size_group_add_widget(sizegroup, label); - gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); - combo_folder = gtk_combo_box_new_text(); - gtk_combo_box_append_text(GTK_COMBO_BOX(combo_folder), "Root"); - gtk_widget_set_sensitive(combo_folder, FALSE); - gtk_box_pack_start(GTK_BOX(hbox), combo_folder, TRUE, TRUE, 0); - gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox); - gtk_widget_show_all(hbox); - } - - gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT); - if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) - { - katze_xbel_item_set_title(bookmark, gtk_entry_get_text(GTK_ENTRY(entry_title))); - katze_xbel_item_set_desc(bookmark, gtk_entry_get_text(GTK_ENTRY(entry_desc))); - if(katze_xbel_item_is_bookmark(bookmark)) - katze_xbel_bookmark_set_href(bookmark, gtk_entry_get_text(GTK_ENTRY(entry_uri))); - - // FIXME: We want to choose a folder - if(newBookmark) - { - katze_xbel_folder_append_item(bookmarks, bookmark); - GtkTreeView* treeview = GTK_TREE_VIEW(browser->panel_bookmarks); - GtkTreeModel* treemodel = gtk_tree_view_get_model(treeview); - GtkTreeIter iter; - gtk_tree_store_insert_with_values(GTK_TREE_STORE(treemodel) - , &iter, NULL, G_MAXINT, 0, bookmark, -1); - katze_xbel_item_ref(bookmark); - } - - // FIXME: update toolbar - // FIXME: Update panels in other windows - } - gtk_widget_destroy(dialog); -} - -static void on_panel_bookmarks_row_activated(GtkTreeView* treeview - , GtkTreePath* path, GtkTreeViewColumn* column, CBrowser* browser) -{ - GtkTreeModel* model = gtk_tree_view_get_model(treeview); - GtkTreeIter iter; - if(gtk_tree_model_get_iter(model, &iter, path)) - { - KatzeXbelItem* item; - gtk_tree_model_get(model, &iter, 0, &item, -1); - if(katze_xbel_item_is_bookmark(item)) - webView_open(get_nth_webView(-1, browser), katze_xbel_bookmark_get_href(item)); - } -} - -static void on_panel_bookmarks_cursor_or_row_changed(GtkTreeView* treeview - , CBrowser* browser) -{ - GtkTreeSelection* selection = gtk_tree_view_get_selection(treeview); - if(selection) - { - GtkTreeModel* model; - GtkTreeIter iter; - if(gtk_tree_selection_get_selected(selection, &model, &iter)) - { - KatzeXbelItem* item; - gtk_tree_model_get(model, &iter, 0, &item, -1); - - gboolean isSeparator = katze_xbel_item_is_separator(item); - action_set_sensitive("BookmarkEdit", !isSeparator, browser); - action_set_sensitive("BookmarkDelete", TRUE, browser); - } - else - { - action_set_sensitive("BookmarkEdit", FALSE, browser); - action_set_sensitive("BookmarkDelete", FALSE, browser); - } - } -} - -static void panel_bookmarks_popup(GtkWidget* widget, GdkEventButton* event - , KatzeXbelItem* item, CBrowser* browser) -{ - gboolean isBookmark = katze_xbel_item_is_bookmark(item); - - action_set_sensitive("BookmarkOpen", isBookmark, browser); - action_set_sensitive("BookmarkOpenTab", isBookmark, browser); - action_set_sensitive("BookmarkOpenWindow", isBookmark, browser); - - sokoke_widget_popup(widget, GTK_MENU(browser->popup_bookmark), event); -} - -static gboolean on_panel_bookmarks_button_release(GtkWidget* widget - , GdkEventButton* event, CBrowser* browser) -{ - if(event->button != 2 && event->button != 3) - return FALSE; - - GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget)); - if(selection) - { - GtkTreeModel* model; - GtkTreeIter iter; - if(gtk_tree_selection_get_selected(selection, &model, &iter)) - { - KatzeXbelItem* item; - gtk_tree_model_get(model, &iter, 0, &item, -1); - if(event->button == 2 && katze_xbel_item_is_bookmark(item)) - { - CBrowser* newBrowser = browser_new(browser); - const gchar* uri = katze_xbel_bookmark_get_href(item); - webView_open(newBrowser->webView, uri); - } - else - panel_bookmarks_popup(widget, event, item, browser); - return TRUE; - } - } - return FALSE; -} - -void on_panel_bookmarks_popup(GtkWidget* widget, CBrowser* browser) -{ - GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget)); - if(selection) - { - GtkTreeModel* model; - GtkTreeIter iter; - if(gtk_tree_selection_get_selected(selection, &model, &iter)) - { - KatzeXbelItem* item; - gtk_tree_model_get(model, &iter, 0, &item, -1); - panel_bookmarks_popup(widget, NULL, item, browser); - } - } -} - -void on_action_bookmarkOpen_activate(GtkAction* action, CBrowser* browser) -{ - GtkTreeView* treeview = GTK_TREE_VIEW(browser->panel_bookmarks); - GtkTreeSelection* selection = gtk_tree_view_get_selection(treeview); - if(selection) - { - GtkTreeModel* model; - GtkTreeIter iter; - if(gtk_tree_selection_get_selected(selection, &model, &iter)) - { - KatzeXbelItem* item; - gtk_tree_model_get(model, &iter, 0, &item, -1); - if(katze_xbel_item_is_bookmark(item)) - webView_open(get_nth_webView(-1, browser) - , katze_xbel_bookmark_get_href(item)); - } - } -} - -void on_action_bookmarkOpenTab_activate(GtkAction* action, CBrowser* browser) -{ - GtkTreeView* treeview = GTK_TREE_VIEW(browser->panel_bookmarks); - GtkTreeSelection* selection = gtk_tree_view_get_selection(treeview); - if(selection) - { - GtkTreeModel* model; - GtkTreeIter iter; - if(gtk_tree_selection_get_selected(selection, &model, &iter)) - { - KatzeXbelItem* item; - gtk_tree_model_get(model, &iter, 0, &item, -1); - if(katze_xbel_item_is_bookmark(item)) - { - CBrowser* newBrowser = browser_new(browser); - const gchar* uri = katze_xbel_bookmark_get_href(item); - webView_open(newBrowser->webView, uri); - } - } - } -} - -void on_action_bookmarkOpenWindow_activate(GtkAction* action, CBrowser* browser) -{ - GtkTreeView* treeview = GTK_TREE_VIEW(browser->panel_bookmarks); - GtkTreeSelection* selection = gtk_tree_view_get_selection(treeview); - if(selection) - { - GtkTreeModel* model; - GtkTreeIter iter; - if(gtk_tree_selection_get_selected(selection, &model, &iter)) - { - KatzeXbelItem* item; - gtk_tree_model_get(model, &iter, 0, &item, -1); - if(katze_xbel_item_is_bookmark(item)) - { - CBrowser* newBrowser = browser_new(NULL); - const gchar* uri = katze_xbel_bookmark_get_href(item); - webView_open(newBrowser->webView, uri); - } - } - } -} - -void on_action_bookmarkEdit_activate(GtkAction* action, CBrowser* browser) -{ - GtkTreeView* treeview = GTK_TREE_VIEW(browser->panel_bookmarks); - GtkTreeSelection* selection = gtk_tree_view_get_selection(treeview); - if(selection) - { - GtkTreeModel* model; - GtkTreeIter iter; - if(gtk_tree_selection_get_selected(selection, &model, &iter)) - { - KatzeXbelItem* item; - gtk_tree_model_get(model, &iter, 0, &item, -1); - if(!katze_xbel_item_is_separator(item)) - browser_editBookmark_dialog_new(item, browser); - } - } -} - -void on_action_bookmarkDelete_activate(GtkAction* action, CBrowser* browser) -{ - GtkTreeView* treeview = GTK_TREE_VIEW(browser->panel_bookmarks); - GtkTreeSelection* selection = gtk_tree_view_get_selection(treeview); - if(selection) - { - GtkTreeModel* model; - GtkTreeIter iter; - if(gtk_tree_selection_get_selected(selection, &model, &iter)) - { - KatzeXbelItem* item; - gtk_tree_model_get(model, &iter, 0, &item, -1); - KatzeXbelItem* parent = katze_xbel_item_get_parent(item); - katze_xbel_folder_remove_item(parent, item); - katze_xbel_item_unref(item); - } - } -} - -static void tree_store_insert_folder(GtkTreeStore* treestore, GtkTreeIter* parent - , KatzeXbelItem* folder) -{ - guint n = katze_xbel_folder_get_n_items(folder); - guint i; - for(i = 0; i < n; i++) - { - KatzeXbelItem* item = katze_xbel_folder_get_nth_item(folder, i); - GtkTreeIter iter; - gtk_tree_store_insert_with_values(treestore, &iter, parent, n, 0, item, -1); - katze_xbel_item_ref(item); - if(katze_xbel_item_is_folder(item)) - tree_store_insert_folder(treestore, &iter, item); - } -} - -static void on_bookmarks_item_render_icon(GtkTreeViewColumn* column - , GtkCellRenderer* renderer, GtkTreeModel* model, GtkTreeIter* iter - , GtkWidget* treeview) -{ - KatzeXbelItem* item; - gtk_tree_model_get(model, iter, 0, &item, -1); - - if(G_UNLIKELY(!item)) - return; - if(G_UNLIKELY(!katze_xbel_item_get_parent(item))) - { - gtk_tree_store_remove(GTK_TREE_STORE(model), iter); - katze_xbel_item_unref(item); - return; - } - - // TODO: Would it be better to not do this on every redraw? - GdkPixbuf* pixbuf = NULL; - if(katze_xbel_item_is_bookmark(item)) - pixbuf = gtk_widget_render_icon(treeview, STOCK_BOOKMARK - , GTK_ICON_SIZE_MENU, NULL); - else if(katze_xbel_item_is_folder(item)) - pixbuf = gtk_widget_render_icon(treeview, GTK_STOCK_DIRECTORY - , GTK_ICON_SIZE_MENU, NULL); - g_object_set(renderer, "pixbuf", pixbuf, NULL); - if(pixbuf) - g_object_unref(pixbuf); -} - -static void on_bookmarks_item_render_text(GtkTreeViewColumn* column - , GtkCellRenderer* renderer, GtkTreeModel* model, GtkTreeIter* iter - , GtkWidget* treeview) -{ - KatzeXbelItem* item; - gtk_tree_model_get(model, iter, 0, &item, -1); - - if(G_UNLIKELY(!item)) - return; - if(G_UNLIKELY(!katze_xbel_item_get_parent(item))) - { - gtk_tree_store_remove(GTK_TREE_STORE(model), iter); - katze_xbel_item_unref(item); - return; - } - - if(katze_xbel_item_is_separator(item)) - g_object_set(renderer - , "markup", "Separator", NULL); - else - g_object_set(renderer - , "markup", NULL, "text", katze_xbel_item_get_title(item), NULL); -} - -static void create_bookmark_menu(KatzeXbelItem*, GtkWidget*, CBrowser*); - -static void on_bookmark_menu_folder_activate(GtkWidget* menuitem, CBrowser* browser) -{ - GtkWidget* menu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(menuitem)); - gtk_container_foreach(GTK_CONTAINER(menu), (GtkCallback)gtk_widget_destroy, NULL);//... - KatzeXbelItem* folder = (KatzeXbelItem*)g_object_get_data(G_OBJECT(menuitem), "KatzeXbelItem"); - create_bookmark_menu(folder, menu, browser); - // Remove all menuitems when the menu is hidden. - // FIXME: We really *want* the line below, but it won't work like that - //g_signal_connect_after(menu, "hide", G_CALLBACK(gtk_container_foreach), gtk_widget_destroy); - gtk_widget_show(menuitem); -} - -static void on_bookmark_toolbar_folder_activate(GtkToolItem* toolitem, CBrowser* browser) -{ - GtkWidget* menu = gtk_menu_new(); - KatzeXbelItem* folder = (KatzeXbelItem*)g_object_get_data(G_OBJECT(toolitem), "KatzeXbelItem"); - create_bookmark_menu(folder, menu, browser); - // Remove all menuitems when the menu is hidden. - // FIXME: We really *should* run the line below, but it won't work like that - //g_signal_connect(menu, "hide", G_CALLBACK(gtk_container_foreach), gtk_widget_destroy); - sokoke_widget_popup(GTK_WIDGET(toolitem), GTK_MENU(menu), NULL); -} - -void on_menu_bookmarks_item_activate(GtkWidget* widget, CBrowser* browser) -{ - KatzeXbelItem* item = (KatzeXbelItem*)g_object_get_data(G_OBJECT(widget), "KatzeXbelItem"); - webView_open(get_nth_webView(-1, browser), katze_xbel_bookmark_get_href(item)); -} - -static void create_bookmark_menu(KatzeXbelItem* folder, GtkWidget* menu, CBrowser* browser) -{ - guint n = katze_xbel_folder_get_n_items(folder); - guint i; - for(i = 0; i < n; i++) - { - KatzeXbelItem* item = katze_xbel_folder_get_nth_item(folder, i); - const gchar* title = katze_xbel_item_is_separator(item) ? "" : katze_xbel_item_get_title(item); - //const gchar* desc = katze_xbel_item_is_separator(item) ? "" : katze_xbel_item_get_desc(item); - GtkWidget* menuitem = NULL; - switch(katze_xbel_item_get_kind(item)) - { - case KATZE_XBEL_ITEM_KIND_FOLDER: - // FIXME: what about katze_xbel_folder_is_folded? - menuitem = gtk_image_menu_item_new_with_label(title); - gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem) - , gtk_image_new_from_stock(GTK_STOCK_DIRECTORY, GTK_ICON_SIZE_MENU)); - GtkWidget* _menu = gtk_menu_new(); - gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), _menu); - g_signal_connect(menuitem, "activate" - , G_CALLBACK(on_bookmark_menu_folder_activate), browser); - g_object_set_data(G_OBJECT(menuitem), "KatzeXbelItem", item); - break; - case KATZE_XBEL_ITEM_KIND_BOOKMARK: - menuitem = menu_item_new(title, STOCK_BOOKMARK - , G_CALLBACK(on_menu_bookmarks_item_activate), TRUE, browser); - g_object_set_data(G_OBJECT(menuitem), "KatzeXbelItem", item); - break; - case KATZE_XBEL_ITEM_KIND_SEPARATOR: - menuitem = gtk_separator_menu_item_new(); - break; - default: - g_warning("Unknown xbel item kind"); - } - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); - gtk_widget_show(menuitem); - } -} - -void on_action_bookmark_new_activate(GtkAction* action, CBrowser* browser) -{ - browser_editBookmark_dialog_new(NULL, browser); -} - -void on_action_manageSearchEngines_activate(GtkAction* action, CBrowser* browser) -{ - // Show the Manage search engines dialog. Create it if necessary. - static GtkWidget* dialog; - if(GTK_IS_DIALOG(dialog)) - gtk_window_present(GTK_WINDOW(dialog)); - else - { - dialog = webSearch_manageSearchEngines_dialog_new(browser); - gtk_widget_show(dialog); - } -} - -void on_action_tab_previous_activate(GtkAction* action, CBrowser* browser) -{ - gint page = gtk_notebook_get_current_page(GTK_NOTEBOOK(browser->webViews)); - gtk_notebook_set_current_page(GTK_NOTEBOOK(browser->webViews), page - 1); -} - -void on_action_tab_next_activate(GtkAction* action, CBrowser* browser) -{ - // Advance one tab or jump to the first one if we are at the last one - gint page = gtk_notebook_get_current_page(GTK_NOTEBOOK(browser->webViews)); - if(page == gtk_notebook_get_n_pages(GTK_NOTEBOOK(browser->webViews)) - 1) - page = -1; - gtk_notebook_set_current_page(GTK_NOTEBOOK(browser->webViews), page + 1); -} - -void on_window_menu_item_activate(GtkImageMenuItem* widget, CBrowser* browser) -{ - gint page = get_webView_index(browser->webView, browser); - gtk_notebook_set_current_page(GTK_NOTEBOOK(browser->webViews), page); -} - -void on_action_about_activate(GtkAction* action, CBrowser* browser) -{ - gtk_show_about_dialog(GTK_WINDOW(browser->window) - , "logo-icon-name", gtk_window_get_icon_name(GTK_WINDOW(browser->window)) - , "name", PACKAGE_NAME - , "version", PACKAGE_VERSION - , "comments", "A lightweight web browser." - , "copyright", "Copyright © 2007 Christian Dywan" - , "website", "http://software.twotoasts.de" - , "authors", credits_authors - , "documenters", credits_documenters - , "artists", credits_artists - , "license", license - , "wrap-license", TRUE - //, "translator-credits", _("translator-credits") - , NULL); -} - -gboolean on_location_key_down(GtkWidget* widget, GdkEventKey* event, CBrowser* browser) -{ - switch(event->keyval) - { - case GDK_Return: - { - const gchar* uri = gtk_entry_get_text(GTK_ENTRY(widget)); - if(uri) - { - gchar* newUri = magic_uri(uri, TRUE); - // TODO: Use newUrl intermediately when completion is better - /* TODO Completion should be generated from history, that is - the uri as well as the title. */ - entry_completion_append(GTK_ENTRY(widget), uri); - webView_open(get_nth_webView(-1, browser), newUri); - g_free(newUri); - } - return TRUE; - } - case GDK_Escape: - { - GtkWidget* webView = get_nth_webView(-1, browser); - WebKitWebFrame* frame = webkit_web_view_get_main_frame(WEBKIT_WEB_VIEW(webView)); - const gchar* uri = webkit_web_frame_get_uri(frame); - if(uri && *uri) - gtk_entry_set_text(GTK_ENTRY(widget), uri); - return TRUE; - } - } - return FALSE; -} - -void on_location_changed(GtkWidget* widget, CBrowser* browser) -{ - // Preserve changes to the uri - /*const gchar* newUri = gtk_entry_get_text(GTK_ENTRY(widget)); - katze_xbel_bookmark_set_href(browser->sessionItem, newUri);*/ - // FIXME: If we want this feature, this is the wrong approach -} - -void on_action_panels_activate(GtkToggleAction* action, CBrowser* browser) -{ - config->panelShow = gtk_toggle_action_get_active(action); - sokoke_widget_set_visible(browser->panels, config->panelShow); -} - -void on_action_panel_item_activate(GtkRadioAction* action - , GtkRadioAction* currentAction, CBrowser* browser) -{ - g_return_if_fail(GTK_IS_ACTION(action)); - // TODO: Activating again should hide the contents; how? - //gint iValue; gint iCurrentValue; - //g_object_get(G_OBJECT(action), "value", &iValue, NULL); - //g_object_get(G_OBJECT(currentAction), "value", &iCurrentValue, NULL); - //GtkWidget* parent = gtk_widget_get_parent(browser->panels_notebook); - //sokoke_widget_set_visible(parent, iCurrentValue == iValue); - /*gtk_paned_set_position(GTK_PANED(gtk_widget_get_parent(browser->panels)) - , iCurrentValue == iValue ? config->iPanelPos : 0);*/ - config->panelActive = gtk_radio_action_get_current_value(action); - gint page = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(currentAction), "iPage")); - gtk_notebook_set_current_page(GTK_NOTEBOOK(browser->panels_notebook), page); - // This is a special case where activation was not user requested. - if(!GPOINTER_TO_INT(g_object_get_data(G_OBJECT(action), "once-silent"))) - { - config->panelShow = TRUE; - gtk_widget_show(browser->panels); - } - else - g_object_set_data(G_OBJECT(action), "once-silent", NULL); -} - -void on_action_openInPanel_activate(GtkAction* action, CBrowser* browser) -{ - GtkWidget* webView = get_nth_webView(-1, browser); - WebKitWebFrame* frame = webkit_web_view_get_main_frame(WEBKIT_WEB_VIEW(webView)); - const gchar* uri = webkit_web_frame_get_uri(frame); - katze_assign(config->panelPageholder, g_strdup(uri)); - GtkAction* action_pageholder = - gtk_action_group_get_action(browser->actiongroup, "PanelPageholder"); - gint value; - g_object_get(G_OBJECT(action_pageholder), "value", &value, NULL); - sokoke_radio_action_set_current_value(GTK_RADIO_ACTION(action_pageholder), value); - gtk_widget_show(browser->panels); - webView_open(browser->panel_pageholder, config->panelPageholder); -} - - -static void on_panels_notify_position(GObject* object, GParamSpec* arg1 - , CBrowser* browser) -{ - config->winPanelPos = gtk_paned_get_position(GTK_PANED(object)); -} - -void on_panels_button_close_clicked(GtkWidget* widget, CBrowser* browser) -{ - config->panelShow = FALSE; - gtk_widget_hide(browser->panels); -} - -gboolean on_notebook_tab_mouse_up(GtkWidget* widget, GdkEventButton* event - , CBrowser* browser) -{ - if(event->button == 1 && event->type == GDK_2BUTTON_PRESS) - { - // Toggle the label visibility on double click - GtkWidget* child = gtk_bin_get_child(GTK_BIN(widget)); - GList* children = gtk_container_get_children(GTK_CONTAINER(child)); - child = (GtkWidget*)g_list_nth_data(children, 1); - gboolean visible = gtk_widget_get_child_visible(GTK_WIDGET(child)); - gtk_widget_set_child_visible(GTK_WIDGET(child), !visible); - gint a, b; sokoke_widget_get_text_size(browser->webView_name, "M", &a, &b); - gtk_widget_set_size_request(child, !visible - ? a * config->tabSize : 0, !visible ? -1 : 0); - g_list_free(children); - return TRUE; - } - else if(event->button == 2) - { - // Close the webView on middle click - webView_close(browser->webView, browser); - return TRUE; - } - - return FALSE; -} - -gboolean on_notebook_tab_close_clicked(GtkWidget* widget, CBrowser* browser) -{ - webView_close(browser->webView, browser); - return TRUE; -} - -void on_notebook_switch_page(GtkWidget* widget, GtkNotebookPage* page - , guint page_num, CBrowser* browser) -{ - GtkWidget* webView = get_nth_webView(page_num, browser); - browser = get_browser_from_webView(webView); - const gchar* uri = katze_xbel_bookmark_get_href(browser->sessionItem); - gtk_entry_set_text(GTK_ENTRY(browser->location), uri); - const gchar* title = katze_xbel_item_get_title(browser->sessionItem); - const gchar* effectiveTitle = title ? title : uri; - gchar* windowTitle = g_strconcat(effectiveTitle, " - ", PACKAGE_NAME, NULL); - gtk_window_set_title(GTK_WINDOW(browser->window), windowTitle); - g_free(windowTitle); - update_favicon(browser); - update_security(browser); - update_gui_state(browser); - update_statusbar(browser); - update_feeds(browser); - update_search_engines(browser); -} - -static void on_window_state_changed(GtkWidget* widget - , GdkEventWindowState* event, CBrowser* browser) -{ - if(event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) - { - if(event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN) - { - gtk_widget_hide(browser->menubar); - g_object_set(browser->fullscreen, "stock-id" - , GTK_STOCK_LEAVE_FULLSCREEN, NULL); - gtk_widget_show(browser->fullscreen); - } - else - { - gtk_widget_show(browser->menubar); - gtk_widget_hide(browser->fullscreen); - g_object_set(browser->fullscreen, "stock-id" - , GTK_STOCK_FULLSCREEN, NULL); - } - } -} - -static void on_window_size_allocate(GtkWidget* widget, GtkAllocation* allocation - , CBrowser* browser) -{ - if(GTK_WIDGET_REALIZED(widget)) - { - GdkWindowState state = gdk_window_get_state(widget->window); - if(!(state & (GDK_WINDOW_STATE_MAXIMIZED | GDK_WINDOW_STATE_FULLSCREEN))) - { - config->winWidth = allocation->width; - config->winHeight = allocation->height; - } - } -} - -gboolean on_window_destroy(GtkWidget* widget, GdkEvent* event, CBrowser* browser) -{ - gboolean proceed = TRUE; - // TODO: What if there are multiple windows? - // TODO: Smart dialog, à la 'Session?: Save, Discard, Cancel' - // TODO: Pref startup: session, ask, homepage, blank <-- ask - // TODO: Pref quit: session, ask, none <-- ask - - if(0 /*g_list_length(browser_list) > 1*/) - { - GtkDialog* dialog; - dialog = GTK_DIALOG(gtk_message_dialog_new(GTK_WINDOW(browser->window) - , GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_WARNING, GTK_BUTTONS_YES_NO - , "There is more than one tab open. Do you want to close anyway?")); - gtk_window_set_title(GTK_WINDOW(dialog), PACKAGE_NAME); - gtk_dialog_set_default_response(dialog, GTK_RESPONSE_YES); - proceed = gtk_dialog_run(dialog) == GTK_RESPONSE_YES; - gtk_widget_destroy(GTK_WIDGET(dialog)); - } - return !proceed; -} - -// -- Browser creation begins here - -CBrowser* browser_new(CBrowser* oldBrowser) -{ - CBrowser* browser = g_new0(CBrowser, 1); - browsers = g_list_prepend(browsers, browser); - browser->sessionItem = katze_xbel_bookmark_new(); - katze_xbel_item_set_title(browser->sessionItem, "about:blank"); - katze_xbel_folder_append_item(session, browser->sessionItem); - - GtkWidget* scrolled; - - if(!oldBrowser) - { - - GtkWidget* label; GtkWidget* hbox; - - // Setup the window metrics - browser->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - g_signal_connect(browser->window, "window-state-event" - , G_CALLBACK(on_window_state_changed), browser); - GdkScreen* screen = gtk_window_get_screen(GTK_WINDOW(browser->window)); - const gint defaultWidth = (gint)gdk_screen_get_width(screen) / 1.7; - const gint defaultHeight = (gint)gdk_screen_get_height(screen) / 1.7; - if(config->rememberWinSize) - { - if(!config->winWidth && !config->winHeight) - { - config->winWidth = defaultWidth; - config->winHeight = defaultWidth; - } - gtk_window_set_default_size(GTK_WINDOW(browser->window) - , config->winWidth, config->winHeight); - } - else - gtk_window_set_default_size(GTK_WINDOW(browser->window) - , defaultWidth, defaultHeight); - g_signal_connect(browser->window, "size-allocate" - , G_CALLBACK(on_window_size_allocate), browser); - // FIXME: Use custom program icon - gtk_window_set_icon_name(GTK_WINDOW(browser->window), "web-browser"); - gtk_window_set_title(GTK_WINDOW(browser->window), g_get_application_name()); - gtk_window_add_accel_group(GTK_WINDOW(browser->window), accel_group); - g_signal_connect(browser->window, "delete-event" - , G_CALLBACK(on_window_destroy), browser); - GtkWidget* vbox = gtk_vbox_new(FALSE, 0); - gtk_container_add(GTK_CONTAINER(browser->window), vbox); - gtk_widget_show(vbox); - - // Let us see some ui manager magic - browser->actiongroup = gtk_action_group_new("Browser"); - gtk_action_group_add_actions(browser->actiongroup, entries, entries_n, browser); - gtk_action_group_add_toggle_actions(browser->actiongroup - , toggle_entries, toggle_entries_n, browser); - gtk_action_group_add_radio_actions(browser->actiongroup - , refreshevery_entries, refreshevery_entries_n - , 300, NULL/*G_CALLBACK(activate_refreshevery_period_action)*/, browser); - gtk_action_group_add_radio_actions(browser->actiongroup - , panel_entries, panel_entries_n, -1 - , G_CALLBACK(on_action_panel_item_activate), browser); - GtkUIManager* ui_manager = gtk_ui_manager_new(); - gtk_ui_manager_insert_action_group(ui_manager, browser->actiongroup, 0); - gtk_window_add_accel_group(GTK_WINDOW(browser->window) - , gtk_ui_manager_get_accel_group(ui_manager)); - - GError* error = NULL; - if(!gtk_ui_manager_add_ui_from_string(ui_manager, ui_markup, -1, &error)) - { - // TODO: Should this be a message dialog? When does this happen? - g_message("User interface couldn't be created: %s", error->message); - g_error_free(error); - } - - GtkAction* action; - // Make all actions except toplevel menus which lack a callback insensitive - // This will vanish once all actions are implemented - guint i; - for(i = 0; i < entries_n; i++) - { - action = gtk_action_group_get_action(browser->actiongroup, entries[i].name); - gtk_action_set_sensitive(action, entries[i].callback || !entries[i].tooltip); - } - for(i = 0; i < toggle_entries_n; i++) - { - action = gtk_action_group_get_action(browser->actiongroup - , toggle_entries[i].name); - gtk_action_set_sensitive(action, toggle_entries[i].callback != NULL); - } - for(i = 0; i < refreshevery_entries_n; i++) - { - action = gtk_action_group_get_action(browser->actiongroup - , refreshevery_entries[i].name); - gtk_action_set_sensitive(action, FALSE); - } - - //action_set_active("ToolbarDownloads", config->bToolbarDownloads, browser); - - // Create the menubar - browser->menubar = gtk_ui_manager_get_widget(ui_manager, "/menubar"); - GtkWidget* menuitem = gtk_menu_item_new(); - gtk_widget_show(menuitem); - browser->throbber = katze_throbber_new(); - gtk_widget_show(browser->throbber); - gtk_container_add(GTK_CONTAINER(menuitem), browser->throbber); - gtk_widget_set_sensitive(menuitem, FALSE); - gtk_menu_item_set_right_justified(GTK_MENU_ITEM(menuitem), TRUE); - gtk_menu_shell_append(GTK_MENU_SHELL(browser->menubar), menuitem); - gtk_box_pack_start(GTK_BOX(vbox), browser->menubar, FALSE, FALSE, 0); - menuitem = gtk_ui_manager_get_widget(ui_manager, "/menubar/Go/TabsClosed"); - g_signal_connect(menuitem, "activate" - , G_CALLBACK(on_menu_tabsClosed_activate), browser); - browser->menu_bookmarks = gtk_menu_item_get_submenu( - GTK_MENU_ITEM(gtk_ui_manager_get_widget(ui_manager, "/menubar/Bookmarks"))); - menuitem = gtk_separator_menu_item_new(); - gtk_widget_show(menuitem); - gtk_menu_shell_append(GTK_MENU_SHELL(browser->menu_bookmarks), menuitem); - browser->popup_bookmark = gtk_ui_manager_get_widget(ui_manager, "/popup_bookmark"); - g_object_ref(browser->popup_bookmark); - browser->menu_window = gtk_menu_item_get_submenu( - GTK_MENU_ITEM(gtk_ui_manager_get_widget(ui_manager, "/menubar/Window"))); - menuitem = gtk_separator_menu_item_new(); - gtk_widget_show(menuitem); - gtk_menu_shell_append(GTK_MENU_SHELL(browser->menu_window), menuitem); - gtk_widget_show(browser->menubar); - action_set_sensitive("PrivateBrowsing", FALSE, browser); //... - action_set_sensitive("WorkOffline", FALSE, browser); //... - browser->popup_webView = gtk_ui_manager_get_widget(ui_manager, "/popup_webView"); - g_object_ref(browser->popup_webView); - browser->popup_element = gtk_ui_manager_get_widget(ui_manager, "/popup_element"); - g_object_ref(browser->popup_element); - browser->popup_editable = gtk_ui_manager_get_widget(ui_manager, "/popup_editable"); - g_object_ref(browser->popup_editable); - - // Create the navigation toolbar - browser->navibar = gtk_ui_manager_get_widget(ui_manager, "/toolbar_navigation"); - gtk_toolbar_set_style(GTK_TOOLBAR(browser->navibar) - , config_to_toolbarstyle(config->toolbarStyle)); - g_signal_connect(gtk_settings_get_default(), "notify::gtk-toolbar-style" - , G_CALLBACK(on_toolbar_navigation_notify_style), browser); - gtk_toolbar_set_icon_size(GTK_TOOLBAR(browser->navibar) - , config_to_toolbariconsize(config->toolbarSmall)); - gtk_toolbar_set_show_arrow(GTK_TOOLBAR(browser->navibar), TRUE); - gtk_box_pack_start(GTK_BOX(vbox), browser->navibar, FALSE, FALSE, 0); - browser->newTab = gtk_ui_manager_get_widget(ui_manager, "/toolbar_navigation/TabNew"); - action = gtk_action_group_get_action(browser->actiongroup, "Back"); - g_object_set(action, "is-important", TRUE, NULL); - - // Location entry - browser->location = sexy_icon_entry_new(); - entry_setup_completion(GTK_ENTRY(browser->location)); - sokoke_entry_set_can_undo(GTK_ENTRY(browser->location), TRUE); - browser->location_icon = gtk_image_new(); - sexy_icon_entry_set_icon(SEXY_ICON_ENTRY(browser->location) - , SEXY_ICON_ENTRY_PRIMARY, GTK_IMAGE(browser->location_icon)); - sexy_icon_entry_add_clear_button(SEXY_ICON_ENTRY(browser->location)); - g_signal_connect(browser->location, "key-press-event" - , G_CALLBACK(on_location_key_down), browser); - g_signal_connect(browser->location, "changed" - , G_CALLBACK(on_location_changed), browser); - GtkToolItem* toolitem = gtk_tool_item_new(); - gtk_tool_item_set_expand(GTK_TOOL_ITEM(toolitem), TRUE); - gtk_container_add(GTK_CONTAINER(toolitem), browser->location); - gtk_toolbar_insert(GTK_TOOLBAR(browser->navibar), toolitem, -1); - - // Search entry - browser->webSearch = sexy_icon_entry_new(); - sexy_icon_entry_set_icon_highlight(SEXY_ICON_ENTRY(browser->webSearch) - , SEXY_ICON_ENTRY_PRIMARY, TRUE); - // TODO: Make this actively resizable or enlarge to fit contents? - // FIXME: The interface is somewhat awkward and ought to be rethought - // TODO: Display "show in context menu" search engines as "completion actions" - entry_setup_completion(GTK_ENTRY(browser->webSearch)); - sokoke_entry_set_can_undo(GTK_ENTRY(browser->webSearch), TRUE); - update_searchEngine(config->searchEngine, browser); - g_signal_connect(browser->webSearch, "icon-released" - , G_CALLBACK(on_webSearch_icon_released), browser); - g_signal_connect(browser->webSearch, "key-press-event" - , G_CALLBACK(on_webSearch_key_down), browser); - g_signal_connect(browser->webSearch, "scroll-event" - , G_CALLBACK(on_webSearch_scroll), browser); - g_signal_connect(browser->webSearch, "activate" - , G_CALLBACK(on_webSearch_activate), browser); - toolitem = gtk_tool_item_new(); - gtk_container_add(GTK_CONTAINER(toolitem), browser->webSearch); - gtk_toolbar_insert(GTK_TOOLBAR(browser->navibar), toolitem, -1); - action = gtk_action_group_get_action(browser->actiongroup, "TabsClosed"); - browser->closedTabs = gtk_action_create_tool_item(action); - g_signal_connect(browser->closedTabs, "clicked" - , G_CALLBACK(on_menu_tabsClosed_activate), browser); - gtk_toolbar_insert(GTK_TOOLBAR(browser->navibar) - , GTK_TOOL_ITEM(browser->closedTabs), -1); - sokoke_container_show_children(GTK_CONTAINER(browser->navibar)); - action = gtk_action_group_get_action(browser->actiongroup, "Fullscreen"); - browser->fullscreen = gtk_action_create_tool_item(action); - gtk_widget_hide(browser->fullscreen); - g_signal_connect(browser->fullscreen, "clicked" - , G_CALLBACK(on_action_fullscreen_activate), browser); - gtk_toolbar_insert(GTK_TOOLBAR(browser->navibar) - , GTK_TOOL_ITEM(browser->fullscreen), -1); - action_set_active("ToolbarNavigation", config->toolbarNavigation, browser); - - // Bookmarkbar - browser->bookmarkbar = gtk_toolbar_new(); - gtk_toolbar_set_icon_size(GTK_TOOLBAR(browser->bookmarkbar), GTK_ICON_SIZE_MENU); - gtk_toolbar_set_style(GTK_TOOLBAR(browser->bookmarkbar), GTK_TOOLBAR_BOTH_HORIZ); - create_bookmark_menu(bookmarks, browser->menu_bookmarks, browser); - for(i = 0; i < katze_xbel_folder_get_n_items(bookmarks); i++) - { - KatzeXbelItem* item = katze_xbel_folder_get_nth_item(bookmarks, i); - const gchar* title = katze_xbel_item_is_separator(item) - ? "" : katze_xbel_item_get_title(item); - const gchar* desc = katze_xbel_item_is_separator(item) - ? "" : katze_xbel_item_get_desc(item); - switch(katze_xbel_item_get_kind(item)) - { - case KATZE_XBEL_ITEM_KIND_FOLDER: - toolitem = tool_button_new(title, GTK_STOCK_DIRECTORY, TRUE, TRUE - , G_CALLBACK(on_bookmark_toolbar_folder_activate), desc, browser); - g_object_set_data(G_OBJECT(toolitem), "KatzeXbelItem", item); - break; - case KATZE_XBEL_ITEM_KIND_BOOKMARK: - toolitem = tool_button_new(title, STOCK_BOOKMARK, TRUE, TRUE - , G_CALLBACK(on_menu_bookmarks_item_activate), desc, browser); - g_object_set_data(G_OBJECT(toolitem), "KatzeXbelItem", item); - break; - case KATZE_XBEL_ITEM_KIND_SEPARATOR: - toolitem = gtk_separator_tool_item_new(); - break; - default: - g_warning("Unknown item kind"); - } - gtk_toolbar_insert(GTK_TOOLBAR(browser->bookmarkbar), toolitem, -1); - } - sokoke_container_show_children(GTK_CONTAINER(browser->bookmarkbar)); - gtk_box_pack_start(GTK_BOX(vbox), browser->bookmarkbar, FALSE, FALSE, 0); - action_set_active("ToolbarBookmarks", config->toolbarBookmarks, browser); - - // Superuser warning - if((hbox = sokoke_superuser_warning_new())) - gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); - - // Create the panels - GtkWidget* hpaned = gtk_hpaned_new(); - gtk_paned_set_position(GTK_PANED(hpaned), config->winPanelPos); - g_signal_connect(hpaned, "notify::position" - , G_CALLBACK(on_panels_notify_position), browser); - gtk_box_pack_start(GTK_BOX(vbox), hpaned, TRUE, TRUE, 0); - gtk_widget_show(hpaned); - - browser->panels = gtk_hbox_new(FALSE, 0); - gtk_paned_pack1(GTK_PANED(hpaned), browser->panels, FALSE, FALSE); - sokoke_widget_set_visible(browser->panels, config->panelShow); - - // Create the panel toolbar - GtkWidget* panelbar = gtk_ui_manager_get_widget(ui_manager, "/toolbar_panels"); - gtk_toolbar_set_style(GTK_TOOLBAR(panelbar), GTK_TOOLBAR_BOTH); - gtk_toolbar_set_icon_size(GTK_TOOLBAR(panelbar), GTK_ICON_SIZE_BUTTON); - gtk_toolbar_set_orientation(GTK_TOOLBAR(panelbar), GTK_ORIENTATION_VERTICAL); - gtk_box_pack_start(GTK_BOX(browser->panels), panelbar, FALSE, FALSE, 0); - action_set_active("Panels", config->panelShow, browser); - - GtkWidget* cbox = gtk_vbox_new(FALSE, 0); - gtk_box_pack_start(GTK_BOX(browser->panels), cbox, TRUE, TRUE, 0); - gtk_widget_show(cbox); - - // Panels titlebar - GtkWidget* labelbar = gtk_toolbar_new(); - gtk_toolbar_set_icon_size(GTK_TOOLBAR(labelbar), GTK_ICON_SIZE_MENU); - gtk_toolbar_set_style(GTK_TOOLBAR(labelbar), GTK_TOOLBAR_ICONS); - toolitem = gtk_tool_item_new(); - gtk_tool_item_set_expand(toolitem, TRUE); - label = gtk_label_new_with_mnemonic("_Panels"); - gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); - gtk_container_add(GTK_CONTAINER(toolitem), label); - gtk_container_set_border_width(GTK_CONTAINER(toolitem), 6); - gtk_toolbar_insert(GTK_TOOLBAR(labelbar), toolitem, -1); - // TODO: Does 'goto top' actually indicate 'detach'? - toolitem = tool_button_new(NULL, GTK_STOCK_GOTO_TOP, FALSE, TRUE - , NULL/*G_CALLBACK(on_panels_button_float_clicked)*/, "Detach panel", browser); - gtk_toolbar_insert(GTK_TOOLBAR(labelbar), toolitem, -1); - toolitem = tool_button_new(NULL, GTK_STOCK_CLOSE, FALSE, TRUE - , G_CALLBACK(on_panels_button_close_clicked), "Close panel", browser); - gtk_toolbar_insert(GTK_TOOLBAR(labelbar), toolitem, -1); - gtk_box_pack_start(GTK_BOX(cbox), labelbar, FALSE, FALSE, 0); - gtk_widget_show_all(labelbar); - - // Notebook, containing all panels - browser->panels_notebook = gtk_notebook_new(); - gtk_notebook_set_show_border(GTK_NOTEBOOK(browser->panels_notebook), FALSE); - gtk_notebook_set_show_tabs(GTK_NOTEBOOK(browser->panels_notebook), FALSE); - gint page; - // Dummy: This is the "fallback" panel for now - page = gtk_notebook_append_page(GTK_NOTEBOOK(browser->panels_notebook) - , gtk_label_new("empty"), NULL); - // Bookmarks - GtkWidget* box = gtk_vbox_new(FALSE, 0); - GtkWidget* toolbar = gtk_ui_manager_get_widget(ui_manager, "/toolbar_bookmarks"); - gtk_toolbar_set_icon_size(GTK_TOOLBAR(toolbar), GTK_ICON_SIZE_MENU); - gtk_box_pack_start(GTK_BOX(box), toolbar, FALSE, FALSE, 0); - gtk_widget_show(toolbar); - GtkTreeViewColumn* column; - GtkCellRenderer* renderer_text; GtkCellRenderer* renderer_pixbuf; - GtkTreeStore* treestore = gtk_tree_store_new(1, KATZE_TYPE_XBEL_ITEM); - GtkWidget* treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(treestore)); - gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(treeview), FALSE); - column = gtk_tree_view_column_new(); - renderer_pixbuf = gtk_cell_renderer_pixbuf_new(); - gtk_tree_view_column_pack_start(column, renderer_pixbuf, FALSE); - gtk_tree_view_column_set_cell_data_func(column, renderer_pixbuf - , (GtkTreeCellDataFunc)on_bookmarks_item_render_icon, treeview, NULL); - renderer_text = gtk_cell_renderer_text_new(); - gtk_tree_view_column_pack_start(column, renderer_text, FALSE); - gtk_tree_view_column_set_cell_data_func(column, renderer_text - , (GtkTreeCellDataFunc)on_bookmarks_item_render_text, treeview, NULL); - gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); - GtkWidget* scrolled = gtk_scrolled_window_new(NULL, NULL); - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled) - , GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_container_add(GTK_CONTAINER(scrolled), treeview); - gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN); - tree_store_insert_folder(GTK_TREE_STORE(treestore), NULL, bookmarks); - g_object_unref(treestore); - g_signal_connect(treeview, "row-activated" - , G_CALLBACK(on_panel_bookmarks_row_activated), browser); - g_signal_connect(treeview, "cursor-changed" - , G_CALLBACK(on_panel_bookmarks_cursor_or_row_changed), browser); - g_signal_connect(treeview, "columns-changed" - , G_CALLBACK(on_panel_bookmarks_cursor_or_row_changed), browser); - on_panel_bookmarks_cursor_or_row_changed(GTK_TREE_VIEW(treeview), browser); - g_signal_connect(treeview, "button-release-event" - , G_CALLBACK(on_panel_bookmarks_button_release), browser); - g_signal_connect(treeview, "popup-menu" - , G_CALLBACK(on_panel_bookmarks_popup), browser); - browser->panel_bookmarks = treeview; - gtk_box_pack_start(GTK_BOX(box), scrolled, TRUE, TRUE, 0); - gtk_widget_show(box); - page = gtk_notebook_append_page(GTK_NOTEBOOK(browser->panels_notebook) - , box, NULL); - action = gtk_action_group_get_action(browser->actiongroup, "PanelBookmarks"); - g_object_set_data(G_OBJECT(action), "iPage", GINT_TO_POINTER(page)); - // Pageholder - browser->panel_pageholder = webView_new(&scrolled); - page = gtk_notebook_append_page(GTK_NOTEBOOK(browser->panels_notebook) - , scrolled, NULL); - //webView_load_from_uri(browser->panel_pageholder, config->panelPageholder); - action = gtk_action_group_get_action(browser->actiongroup, "PanelPageholder"); - g_object_set_data(G_OBJECT(action), "iPage", GINT_TO_POINTER(page)); - GtkWidget* frame = gtk_frame_new(NULL); - gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN); - gtk_container_add(GTK_CONTAINER(frame), browser->panels_notebook); - gtk_box_pack_start(GTK_BOX(cbox), frame, TRUE, TRUE, 0); - gtk_widget_show_all(gtk_widget_get_parent(browser->panels_notebook)); - action = gtk_action_group_get_action(browser->actiongroup, "PanelDownloads"); - g_object_set_data(G_OBJECT(action), "once-silent", GINT_TO_POINTER(1)); - sokoke_radio_action_set_current_value(GTK_RADIO_ACTION(action), config->panelActive); - sokoke_widget_set_visible(browser->panels, config->panelShow); - g_object_unref(ui_manager); - - // Notebook, containing all webViews - browser->webViews = gtk_notebook_new(); - gtk_notebook_set_scrollable(GTK_NOTEBOOK(browser->webViews), TRUE); - #if GTK_CHECK_VERSION(2, 10, 0) - //gtk_notebook_set_group_id(GTK_NOTEBOOK(browser->webViews), 0); - #endif - gtk_paned_pack2(GTK_PANED(hpaned), browser->webViews, FALSE, FALSE); - gtk_widget_show(browser->webViews); - - // Incremental findbar - browser->findbox = gtk_toolbar_new(); - gtk_toolbar_set_icon_size(GTK_TOOLBAR(browser->findbox), GTK_ICON_SIZE_MENU); - gtk_toolbar_set_style(GTK_TOOLBAR(browser->findbox), GTK_TOOLBAR_BOTH_HORIZ); - toolitem = gtk_tool_item_new(); - gtk_container_set_border_width(GTK_CONTAINER(toolitem), 6); - gtk_container_add(GTK_CONTAINER(toolitem) - , gtk_label_new_with_mnemonic("_Inline find:")); - gtk_toolbar_insert(GTK_TOOLBAR(browser->findbox), toolitem, -1); - browser->findbox_text = sexy_icon_entry_new(); - GtkWidget* icon = gtk_image_new_from_stock(GTK_STOCK_FIND, GTK_ICON_SIZE_MENU); - sexy_icon_entry_set_icon(SEXY_ICON_ENTRY(browser->findbox_text) - , SEXY_ICON_ENTRY_PRIMARY, GTK_IMAGE(icon)); - sexy_icon_entry_add_clear_button(SEXY_ICON_ENTRY(browser->findbox_text)); - sokoke_entry_set_can_undo(GTK_ENTRY(browser->findbox_text), TRUE); - g_signal_connect(browser->findbox_text, "activate" - , G_CALLBACK(on_action_find_next_activate), browser); - toolitem = gtk_tool_item_new(); - gtk_container_add(GTK_CONTAINER(toolitem), browser->findbox_text); - gtk_tool_item_set_expand(GTK_TOOL_ITEM(toolitem), TRUE); - gtk_toolbar_insert(GTK_TOOLBAR(browser->findbox), toolitem, -1); - toolitem = tool_button_new(NULL, GTK_STOCK_GO_BACK, TRUE, TRUE - , G_CALLBACK(on_action_find_previous_activate), NULL, browser); - gtk_toolbar_insert(GTK_TOOLBAR(browser->findbox), toolitem, -1); - toolitem = tool_button_new(NULL, GTK_STOCK_GO_FORWARD, TRUE, TRUE - , G_CALLBACK(on_action_find_next_activate), NULL, browser); - gtk_toolbar_insert(GTK_TOOLBAR(browser->findbox), toolitem, -1); - browser->findbox_case = gtk_toggle_tool_button_new_from_stock(GTK_STOCK_SPELL_CHECK); - gtk_tool_button_set_label(GTK_TOOL_BUTTON(browser->findbox_case), "Match Case"); - gtk_tool_item_set_is_important(GTK_TOOL_ITEM(browser->findbox_case), TRUE); - gtk_toolbar_insert(GTK_TOOLBAR(browser->findbox), browser->findbox_case, -1); - browser->findbox_highlight = gtk_toggle_tool_button_new_from_stock(GTK_STOCK_SELECT_ALL); - g_signal_connect(browser->findbox_highlight, "toggled" - , G_CALLBACK(on_findbox_highlight_toggled), browser); - gtk_tool_button_set_label(GTK_TOOL_BUTTON(browser->findbox_highlight), "Highlight Matches"); - gtk_tool_item_set_is_important(GTK_TOOL_ITEM(browser->findbox_highlight), TRUE); - gtk_toolbar_insert(GTK_TOOLBAR(browser->findbox), browser->findbox_highlight, -1); - toolitem = gtk_separator_tool_item_new(); - gtk_separator_tool_item_set_draw(GTK_SEPARATOR_TOOL_ITEM(toolitem), FALSE); - gtk_tool_item_set_expand(GTK_TOOL_ITEM(toolitem), TRUE); - gtk_toolbar_insert(GTK_TOOLBAR(browser->findbox), toolitem, -1); - toolitem = tool_button_new(NULL, GTK_STOCK_CLOSE, FALSE, TRUE - , G_CALLBACK(on_findbox_button_close_clicked), "Close Findbar", browser); - gtk_toolbar_insert(GTK_TOOLBAR(browser->findbox), toolitem, -1); - sokoke_container_show_children(GTK_CONTAINER(browser->findbox)); - gtk_box_pack_start(GTK_BOX(vbox), browser->findbox, FALSE, FALSE, 0); - - // Statusbar - // TODO: fix children overlapping statusbar border - browser->statusbar = gtk_statusbar_new(); - gtk_box_pack_start(GTK_BOX(vbox), browser->statusbar, FALSE, FALSE, 0); - browser->progress = gtk_progress_bar_new(); - // Setting the progressbar's height to 1 makes it fit in the statusbar - gtk_widget_set_size_request(browser->progress, -1, 1); - gtk_box_pack_start(GTK_BOX(browser->statusbar), browser->progress - , FALSE, FALSE, 3); - browser->icon_security = gtk_image_new(); - gtk_box_pack_start(GTK_BOX(browser->statusbar) - , browser->icon_security, FALSE, FALSE, 0); - gtk_widget_show(browser->icon_security); - browser->icon_newsfeed = gtk_image_new_from_icon_name(STOCK_NEWSFEED - , GTK_ICON_SIZE_MENU); - gtk_box_pack_start(GTK_BOX(browser->statusbar) - , browser->icon_newsfeed, FALSE, FALSE, 0); - action_set_active("ToolbarStatus", config->toolbarStatus, browser); - - } - else - { - - browser->window = oldBrowser->window; - browser->actiongroup = oldBrowser->actiongroup; - browser->menubar = oldBrowser->menubar; - browser->menu_bookmarks = oldBrowser->menu_bookmarks; - browser->popup_bookmark = oldBrowser->popup_bookmark; - browser->menu_window = oldBrowser->menu_window; - browser->popup_webView = oldBrowser->popup_webView; - browser->popup_element = oldBrowser->popup_element; - browser->popup_editable = oldBrowser->popup_editable; - browser->throbber = oldBrowser->throbber; - browser->navibar = oldBrowser->navibar; - browser->newTab = oldBrowser->newTab; - browser->location_icon = oldBrowser->location_icon; - browser->location = oldBrowser->location; - browser->webSearch = oldBrowser->webSearch; - browser->closedTabs = oldBrowser->closedTabs; - browser->fullscreen = oldBrowser->fullscreen; - browser->bookmarkbar = oldBrowser->bookmarkbar; - browser->panels = oldBrowser->panels; - browser->panels_notebook = oldBrowser->panels_notebook; - browser->panel_pageholder = oldBrowser->panel_pageholder; - browser->webViews = oldBrowser->webViews; - browser->findbox = oldBrowser->findbox; - browser->findbox_case = oldBrowser->findbox_case; - browser->findbox_highlight = oldBrowser->findbox_highlight; - browser->statusbar = oldBrowser->statusbar; - browser->progress = oldBrowser->progress; - browser->icon_security = oldBrowser->icon_security; - browser->icon_newsfeed = oldBrowser->icon_newsfeed; - - } - - // Define some default values - browser->hasMenubar = TRUE; - browser->hasToolbar = TRUE; - browser->hasLocation = TRUE; - browser->hasStatusbar = TRUE; - browser->elementUri = NULL; - browser->loadedPercent = -1; // initially "not loading" - - // Add a window menu item - // TODO: Menu items should be ordered like the notebook tabs - // TODO: Watch tab reordering in >= gtk 2.10 - browser->webView_menu = menu_item_new("about:blank", GTK_STOCK_FILE - , G_CALLBACK(on_window_menu_item_activate), TRUE, browser); - gtk_widget_show(browser->webView_menu); - gtk_menu_shell_append(GTK_MENU_SHELL(browser->menu_window), browser->webView_menu); - - // Create a new tab label - GtkWidget* eventbox = gtk_event_box_new(); - gtk_event_box_set_visible_window(GTK_EVENT_BOX(eventbox), FALSE); - g_signal_connect(eventbox, "button-release-event" - , G_CALLBACK(on_notebook_tab_mouse_up), browser); - GtkWidget* hbox = gtk_hbox_new(FALSE, 1); - gtk_container_add(GTK_CONTAINER(eventbox), GTK_WIDGET(hbox)); - browser->webView_icon = katze_throbber_new(); - katze_throbber_set_static_stock_id(KATZE_THROBBER(browser->webView_icon) - , GTK_STOCK_FILE); - gtk_box_pack_start(GTK_BOX(hbox), browser->webView_icon, FALSE, FALSE, 0); - browser->webView_name = gtk_label_new(katze_xbel_item_get_title(browser->sessionItem)); - gtk_misc_set_alignment(GTK_MISC(browser->webView_name), 0.0, 0.5); - // TODO: make the tab initially look "unvisited" until it's focused - // TODO: gtk's tab scrolling is weird? - gint w, h; - sokoke_widget_get_text_size(browser->webView_name, "M", &w, &h); - gtk_widget_set_size_request(GTK_WIDGET(browser->webView_name) - , w * config->tabSize, -1); - gtk_label_set_ellipsize(GTK_LABEL(browser->webView_name), PANGO_ELLIPSIZE_END); - gtk_box_pack_start(GTK_BOX(hbox), browser->webView_name, FALSE, FALSE, 0); - browser->webView_close = gtk_button_new(); - gtk_button_set_relief(GTK_BUTTON(browser->webView_close), GTK_RELIEF_NONE); - gtk_button_set_focus_on_click(GTK_BUTTON(browser->webView_close), FALSE); - GtkRcStyle* rcstyle = gtk_rc_style_new(); - rcstyle->xthickness = rcstyle->ythickness = 0; - gtk_widget_modify_style(browser->webView_close, rcstyle); - GtkWidget* image = gtk_image_new_from_stock(GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU); - gtk_button_set_image(GTK_BUTTON(browser->webView_close), image); - gtk_box_pack_start(GTK_BOX(hbox), browser->webView_close, FALSE, FALSE, 0); - GtkSettings* gtksettings = gtk_settings_get_default(); - gint height; - gtk_icon_size_lookup_for_settings(gtksettings, GTK_ICON_SIZE_BUTTON, 0, &height); - gtk_widget_set_size_request(browser->webView_close, -1, height); - gtk_widget_show_all(GTK_WIDGET(eventbox)); - sokoke_widget_set_visible(browser->webView_close, config->tabClose); - g_signal_connect(browser->webView_close, "clicked" - , G_CALLBACK(on_notebook_tab_close_clicked), browser); - - // Create a webView inside a scrolled window - browser->webView = webView_new(&scrolled); - gtk_widget_show(GTK_WIDGET(scrolled)); - gtk_widget_show(GTK_WIDGET(browser->webView)); - gint page = gtk_notebook_get_current_page(GTK_NOTEBOOK(browser->webViews)); - page = gtk_notebook_insert_page(GTK_NOTEBOOK(browser->webViews) - , scrolled, GTK_WIDGET(eventbox), page + 1); - g_signal_connect_after(browser->webViews, "switch-page" - , G_CALLBACK(on_notebook_switch_page), browser); - #if GTK_CHECK_VERSION(2, 10, 0) - gtk_notebook_set_tab_reorderable(GTK_NOTEBOOK(browser->webViews), scrolled, TRUE); - gtk_notebook_set_tab_detachable(GTK_NOTEBOOK(browser->webViews), scrolled, TRUE); - #endif - - // Connect signals - #define DOC_CONNECT(__sig, __func) g_signal_connect \ - (browser->webView, __sig, G_CALLBACK(__func), browser); - #define DOC_CONNECTA(__sig, __func) g_signal_connect_after \ - (browser->webView, __sig, G_CALLBACK(__func), browser); - DOC_CONNECT ("navigation-requested" , on_webView_navigation_requested) - DOC_CONNECT ("title-changed" , on_webView_title_changed) - DOC_CONNECT ("icon-loaded" , on_webView_icon_changed) - DOC_CONNECT ("load-started" , on_webView_load_started) - DOC_CONNECT ("load-committed" , on_webView_load_committed) - DOC_CONNECT ("load-progress-changed" , on_webView_load_changed) - DOC_CONNECT ("load-finished" , on_webView_load_finished) - DOC_CONNECT ("status-bar-text-changed" , on_webView_status_message) - DOC_CONNECT ("hovering-over-link" , on_webView_link_hover) - DOC_CONNECT ("console-message" , on_webView_console_message) - - DOC_CONNECT ("button-press-event" , on_webView_button_press) - DOC_CONNECTA ("button-press-event" , on_webView_button_press_after) - DOC_CONNECT ("popup-menu" , on_webView_popup); - DOC_CONNECT ("scroll-event" , on_webView_scroll); - DOC_CONNECT ("leave-notify-event" , on_webView_leave) - DOC_CONNECT ("destroy" , on_webView_destroy) - #undef DOC_CONNECT - #undef DOC_CONNECTA - - webkit_web_view_set_settings(WEBKIT_WEB_VIEW(browser->webView), webSettings); - - // Eventually pack and display everything - sokoke_widget_set_visible(browser->navibar, config->toolbarNavigation); - sokoke_widget_set_visible(browser->newTab, config->toolbarNewTab); - sokoke_widget_set_visible(browser->webSearch, config->toolbarWebSearch); - sokoke_widget_set_visible(browser->closedTabs, config->toolbarClosedTabs); - sokoke_widget_set_visible(browser->bookmarkbar, config->toolbarBookmarks); - sokoke_widget_set_visible(browser->statusbar, config->toolbarStatus); - if(!config->openTabsInTheBackground) - gtk_notebook_set_current_page(GTK_NOTEBOOK(browser->webViews), page); - - update_browser_actions(browser); - gtk_widget_show(browser->window); - gtk_widget_grab_focus(GTK_WIDGET(browser->location)); - - return browser; -} diff --git a/src/browser.h b/src/browser.h deleted file mode 100644 index a3c4f3df..00000000 --- a/src/browser.h +++ /dev/null @@ -1,600 +0,0 @@ -/* - Copyright (C) 2007 Christian Dywan - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - See the file COPYING for the full license text. -*/ - -#ifndef __BROWSER_H__ -#define __BROWSER_H__ 1 - -#include "global.h" - -#include - -// -- Types - -typedef struct _CBrowser -{ - // shared widgets - GtkWidget* window; - GtkActionGroup* actiongroup; - // menus - GtkWidget* menubar; - GtkWidget* menu_bookmarks; - GtkWidget* popup_bookmark; - GtkWidget* menu_window; - GtkWidget* popup_webView; - GtkWidget* popup_element; - GtkWidget* popup_editable; - GtkWidget* throbber; - // navibar - GtkWidget* navibar; - GtkWidget* newTab; - GtkWidget* location_icon; - GtkWidget* location; - GtkWidget* webSearch; - GtkWidget* closedTabs; - GtkWidget* fullscreen; - GtkWidget* bookmarkbar; - // panels - GtkWidget* panels; - GtkWidget* panels_notebook; - GtkWidget* panel_bookmarks; - GtkWidget* panel_pageholder; - GtkWidget* webViews; - // findbox - GtkWidget* findbox; - GtkWidget* findbox_text; - GtkToolItem* findbox_case; - GtkToolItem* findbox_highlight; - GtkWidget* statusbar; - GtkWidget* progress; - GtkWidget* icon_security; - GtkWidget* icon_newsfeed; - - // view specific widgets - GtkWidget* webView_menu; - GtkWidget* webView_icon; - GtkWidget* webView_name; - GtkWidget* webView_close; - GtkWidget* webView; - - // view specific values - gboolean hasMenubar; - gboolean hasToolbar; - gboolean hasLocation; - gboolean hasStatusbar; - gchar* elementUri; // the element the mouse is hovering on - gint loadedPercent; // -1 means "not loading" - //UNDEFINED favicon; - guint security; - gchar* statusMessage; // message from a webView - KatzeXbelItem* sessionItem; -} CBrowser; - -enum -{ - SEARCH_COL_ICON, - SEARCH_COL_TEXT, - SEARCH_COL_N -}; - -// -- Declarations - -void -on_action_window_new_activate(GtkAction*, CBrowser*); - -void -on_action_tab_new_activate(GtkAction*, CBrowser*); - -void -on_action_open_activate(GtkAction*, CBrowser*); - -void -on_action_tab_close_activate(GtkAction*, CBrowser*); - -void -on_action_window_close_activate(GtkAction*, CBrowser*); - -void -on_action_quit_activate(GtkAction*, CBrowser*); - -void -on_action_edit_activate(GtkAction*, CBrowser*); - -void -on_action_cut_activate(GtkAction*, CBrowser*); - -void -on_action_copy_activate(GtkAction*, CBrowser*); - -void -on_action_paste_activate(GtkAction*, CBrowser*); - -void -on_action_delete_activate(GtkAction*, CBrowser*); - -void -on_action_selectAll_activate(GtkAction*, CBrowser*); - -void -on_action_find_activate(GtkAction*, CBrowser*); - -void -on_action_find_next_activate(GtkAction*, CBrowser*); - -void -on_action_find_previous_activate(GtkAction*, CBrowser*); - -void -on_action_preferences_activate(GtkAction*, CBrowser*); - -void -on_action_toolbar_navigation_activate(GtkToggleAction*, CBrowser*); - -void -on_action_toolbar_bookmarks_activate(GtkToggleAction*, CBrowser*); - -void -on_action_panels_activate(GtkToggleAction*, CBrowser*); - -void -on_action_toolbar_status_activate(GtkToggleAction*, CBrowser*); - -void -on_action_refresh_stop_activate(GtkAction*, CBrowser*); - -void -on_action_zoom_in_activate(GtkAction*, CBrowser*); - -void -on_action_zoom_out_activate(GtkAction*, CBrowser*); - -void -on_action_zoom_normal_activate(GtkAction*, CBrowser*); - -void -on_action_source_view_activate(GtkAction*, CBrowser*); - -void -on_action_fullscreen_activate(GtkAction*, CBrowser*); - -void -on_action_back_activate(GtkAction*, CBrowser*); - -void -on_action_forward_activate(GtkAction*, CBrowser*); - -void -on_action_home_activate(GtkAction*, CBrowser*); - -void -on_action_location_activate(GtkAction*, CBrowser*); - -void -on_action_webSearch_activate(GtkAction*, CBrowser*); - -void -on_action_openInPanel_activate(GtkAction*, CBrowser*); - -void -on_menu_tabsClosed_activate(GtkWidget*, CBrowser*); - -void -on_menu_tabsClosed_item_activate(GtkWidget*, CBrowser*); - -void -on_action_tabsClosed_clear_activate(GtkAction*, CBrowser*); - -void -on_action_tabsClosed_undo_activate(GtkAction*, CBrowser*); - -void -on_action_link_tab_new_activate(GtkAction*, CBrowser*); - -void -on_action_link_tab_current_activate(GtkAction*, CBrowser*); - -void -on_action_link_window_new_activate(GtkAction*, CBrowser*); - -void -on_action_link_saveWith_activate(GtkAction*, CBrowser*); - -void -on_action_link_copy_activate(GtkAction*, CBrowser*); - -void -on_action_bookmarkOpen_activate(GtkAction*, CBrowser*); - -void -on_action_bookmarkOpenTab_activate(GtkAction*, CBrowser*); - -void -on_action_bookmarkOpenWindow_activate(GtkAction*, CBrowser*); - -void -on_action_bookmarkEdit_activate(GtkAction*, CBrowser*); - -void -on_action_bookmarkDelete_activate(GtkAction*, CBrowser*); - -void -on_menu_bookmarks_item_activate(GtkWidget*, CBrowser*); - -void -on_action_bookmark_new_activate(GtkAction*, CBrowser*); - -void -on_action_manageSearchEngines_activate(GtkAction*, CBrowser*); - -void -on_action_tab_previous_activate(GtkAction*, CBrowser*); - -void -on_action_tab_next_activate(GtkAction*, CBrowser*); - -void -on_action_about_activate(GtkAction*, CBrowser*); - -gboolean -on_location_key_down(GtkWidget*, GdkEventKey*, CBrowser*); - -CBrowser* -browser_new(CBrowser*); - -// -- Action definitions - -// TODO: Fill in a good description for each 'hm?' -static const GtkActionEntry entries[] = { - { "File", NULL, "_File" }, - { "WindowNew", STOCK_WINDOW_NEW - , NULL, "n" - , "Open a new window", G_CALLBACK(on_action_window_new_activate) }, - { "TabNew", STOCK_TAB_NEW - , NULL, "t" - , "Open a new tab", G_CALLBACK(on_action_tab_new_activate) }, - { "Open", GTK_STOCK_OPEN - , NULL, "o" - , "Open a file", G_CALLBACK(on_action_open_activate) }, - { "SaveAs", GTK_STOCK_SAVE_AS - , NULL, "s" - , "Save to a file", NULL/*G_CALLBACK(on_action_saveas_activate)*/ }, - { "TabClose", STOCK_TAB_CLOSE - , NULL, "w" - , "Close the current tab", G_CALLBACK(on_action_tab_close_activate) }, - { "WindowClose", STOCK_WINDOW_CLOSE - , NULL, "w" - , "Close this window", G_CALLBACK(on_action_window_close_activate) }, - { "PageSetup", GTK_STOCK_PROPERTIES - , "Pa_ge Setup", "" - , "hm?", NULL/*G_CALLBACK(on_action_page_setup_activate)*/ }, - { "PrintPreview", GTK_STOCK_PRINT_PREVIEW - , NULL, "" - , "hm?", NULL/*G_CALLBACK(on_action_print_preview_activate)*/ }, - { "Print", GTK_STOCK_PRINT - , NULL, "p" - , "hm?", NULL/*G_CALLBACK(on_action_print_activate)*/ }, - { "Quit", GTK_STOCK_QUIT - , NULL, "q" - , "Quit the application", G_CALLBACK(on_action_quit_activate) }, - - { "Edit", NULL, "_Edit", NULL, NULL, G_CALLBACK(on_action_edit_activate) }, - { "Undo", GTK_STOCK_UNDO - , NULL, "z" - , "Undo the last modification", NULL/*G_CALLBACK(on_action_undo_activate)*/ }, - { "Redo", GTK_STOCK_REDO - , NULL, "z" - , "Redo the last modification", NULL/*G_CALLBACK(on_action_redo_activate)*/ }, - { "Cut", GTK_STOCK_CUT - , NULL, "x" - , "Cut the selected text", G_CALLBACK(on_action_cut_activate) }, - { "Copy", GTK_STOCK_COPY - , NULL, "c" - , "Copy the selected text", G_CALLBACK(on_action_copy_activate) }, - { "Copy_", GTK_STOCK_COPY - , NULL, "c" - , "Copy the selected text", G_CALLBACK(on_action_copy_activate) }, - { "Paste", GTK_STOCK_PASTE - , NULL, "v" - , "Paste text from the clipboard", G_CALLBACK(on_action_paste_activate) }, - { "Delete", GTK_STOCK_DELETE - , NULL, NULL - , "Delete the selected text", G_CALLBACK(on_action_delete_activate) }, - { "SelectAll", GTK_STOCK_SELECT_ALL - , NULL, "a" - , "Selected all text", G_CALLBACK(on_action_selectAll_activate) }, - { "FormFill", STOCK_FORM_FILL - , NULL, "" - , "hm?", NULL/*G_CALLBACK(on_action_formfill_activate)*/ }, - { "Find", GTK_STOCK_FIND - , NULL, "f" - , "hm?", G_CALLBACK(on_action_find_activate) }, - { "FindNext", GTK_STOCK_GO_FORWARD - , "Find _Next", "g" - , "hm?", G_CALLBACK(on_action_find_next_activate) }, - { "FindPrevious", GTK_STOCK_GO_BACK - , "Find _Previous", "g" - , "hm?", G_CALLBACK(on_action_find_previous_activate) }, - { "FindQuick", GTK_STOCK_FIND - , "_Quick Find", "period" - , "hm?", NULL/*G_CALLBACK(on_action_find_quick_activate)*/ }, - { "ManageSearchEngines", GTK_STOCK_PROPERTIES - , "_Manage Search Engines", "s" - , "hm?", G_CALLBACK(on_action_manageSearchEngines_activate) }, - { "Preferences", GTK_STOCK_PREFERENCES - , NULL, "p" - , "hm?", G_CALLBACK(on_action_preferences_activate) }, - - { "View", NULL, "_View" }, - { "Toolbars", NULL, "_Toolbars" }, - { "Refresh", GTK_STOCK_REFRESH - , NULL, "r" - , "Refresh the current page", G_CALLBACK(on_action_refresh_stop_activate) }, - // TODO: Is appointment-new a good choice? - // TODO: What if it isn't available? - { "RefreshEvery", "appointment-new" - , "Refresh _Every...", "" - , "Refresh the current page", G_CALLBACK(on_action_refresh_stop_activate) }, - { "Stop", GTK_STOCK_STOP - , NULL, "Escape" - , "Stop loading of the current page", G_CALLBACK(on_action_refresh_stop_activate) }, - { "RefreshStop", GTK_STOCK_REFRESH - , NULL, "" - , NULL, G_CALLBACK(on_action_refresh_stop_activate) }, - { "ZoomIn", GTK_STOCK_ZOOM_IN - , NULL, "plus" - , "hm?", G_CALLBACK(on_action_zoom_in_activate) }, - { "ZoomOut", GTK_STOCK_ZOOM_OUT - , NULL, "minus" - , "hm?", G_CALLBACK(on_action_zoom_out_activate) }, - { "ZoomNormal", GTK_STOCK_ZOOM_100 - , NULL, "0" - , "hm?", G_CALLBACK(on_action_zoom_normal_activate) }, - { "BackgroundImage", STOCK_IMAGE - , "_Background Image", "" - , "hm?", NULL/*G_CALLBACK(on_action_background_image_activate)*/ }, - { "SourceView", STOCK_SOURCE_VIEW - , NULL, "" - , "hm?", /*G_CALLBACK(on_action_source_view_activate)*/ }, - { "SelectionSourceView", STOCK_SOURCE_VIEW - , "View Selection Source", "" - , "hm?", NULL/*G_CALLBACK(on_action_selection_source_view_activate)*/ }, - { "Properties", GTK_STOCK_PROPERTIES - , NULL, "" - , "hm?", NULL/*G_CALLBACK(on_action_properties_activate)*/ }, - { "Fullscreen", GTK_STOCK_FULLSCREEN - , NULL, "F11" - , "Toggle fullscreen view", G_CALLBACK(on_action_fullscreen_activate) }, - - { "Go", NULL, "_Go" }, - { "Back", GTK_STOCK_GO_BACK - , NULL, "Left" - , "hm?", G_CALLBACK(on_action_back_activate) }, - { "Forward", GTK_STOCK_GO_FORWARD - , NULL, "Right" - , "hm?", G_CALLBACK(on_action_forward_activate) }, - { "Home", STOCK_HOMEPAGE - , NULL, "Home" - , "hm?", G_CALLBACK(on_action_home_activate) }, - { "Location", GTK_STOCK_JUMP_TO - , "Location...", "l" - , "hm?", G_CALLBACK(on_action_location_activate) }, - { "Websearch", GTK_STOCK_FIND - , "Websearch...", "f" - , "hm?", G_CALLBACK(on_action_webSearch_activate) }, - { "OpenInPageholder", GTK_STOCK_JUMP_TO - , "Open in Page_holder...", "" - , "hm?", G_CALLBACK(on_action_openInPanel_activate) }, - { "TabsClosed", STOCK_USER_TRASH - , "Closed Tabs", "" - , "hm?", NULL }, - { "TabsClosedClear", GTK_STOCK_CLEAR - , "Clear List of Closed Tabs", "" - , "hm?", G_CALLBACK(on_action_tabsClosed_clear_activate) }, - { "UndoTabClose", GTK_STOCK_UNDELETE - , "Undo Close Tab", "" - , "hm?", G_CALLBACK(on_action_tabsClosed_undo_activate) }, - { "LinkTabNew", STOCK_TAB_NEW - , "Open Link in New Tab", "" - , "hm?", G_CALLBACK(on_action_link_tab_new_activate) }, - { "LinkTabCurrent", NULL - , "Open Link in Current Tab", "" - , "hm?", G_CALLBACK(on_action_link_tab_current_activate) }, - { "LinkWindowNew", STOCK_WINDOW_NEW - , "Open Link in New Window", "" - , "hm?", G_CALLBACK(on_action_link_window_new_activate) }, - { "LinkBookmarkNew", STOCK_BOOKMARK_NEW - , NULL, "" - , "Bookmark this link", NULL/*G_CALLBACK(on_action_link_bookmark_activate)*/ }, - { "LinkSaveAs", GTK_STOCK_SAVE - , "Save Destination as...", "" - , "Save destination to a file", NULL/*G_CALLBACK(on_action_link_saveas_activate)*/ }, - { "LinkSaveWith", STOCK_DOWNLOADS - , "Download Destination", "" - , "Save destination with the chosen download manager", G_CALLBACK(on_action_link_saveWith_activate) }, - { "LinkCopy", GTK_STOCK_COPY - , "Copy Link Address", "" - , "Copy the link address to the clipboard", G_CALLBACK(on_action_link_copy_activate) }, - { "SelectionLinksNewTabs", NULL - , "Open Selected Links in Tabs", "" - , "hm?", NULL/*G_CALLBACK(on_action_properties_selection_activate)*/ }, - { "SelectionTextTabNew", STOCK_TAB_NEW - , "Open in New Tab", "" - , "hm?", NULL/*G_CALLBACK(on_action_properties_selection_activate)*/ }, - { "SelectionTextTabCurrent", NULL - , "Open in Current Tab", "" - , "hm?", NULL/*G_CALLBACK(on_action_properties_selection_activate)*/ }, - { "SelectionTextWindowNew", STOCK_WINDOW_NEW - , "Open in New Qindow", "" - , "hm?", NULL/*G_CALLBACK(on_action_properties_selection_activate)*/ }, - { "SelectionSearch", GTK_STOCK_FIND - , "Search for ", "" - , "hm?", NULL/*G_CALLBACK(on_action_properties_selection_activate)*/ }, - { "SelectionSearchWith", GTK_STOCK_FIND - , "Search for with...", "" - , "hm?", NULL/*G_CALLBACK(on_action_properties_selection_activate)*/ }, - { "ImageViewTabNew", STOCK_TAB_NEW - , "View Image in New Tab", "" - , "hm?", NULL/*G_CALLBACK(on_action_properties_selection_activate)*/ }, - { "ImageViewTabCurrent", NULL - , "View image in current tab", "" - , "hm?", NULL/*G_CALLBACK(on_action_properties_selection_activate)*/ }, - { "ImageSaveAs", GTK_STOCK_SAVE - , "Save Image as...", "" - , "Save image to a file", NULL/*G_CALLBACK(on_action_properties_selection_activate)*/ }, - { "ImageSaveWith", STOCK_DOWNLOADS - , "Download Image", "" - , "Save image with the chosen download manager", NULL/*G_CALLBACK(on_action_properties_selection_activate)*/ }, - { "ImageCopy", GTK_STOCK_COPY - , "Copy Image Address", "" - , "Copy the image address to the clipboard", NULL/*G_CALLBACK(on_action_properties_selection_activate)*/ }, - - { "Bookmarks", NULL, "_Bookmarks" }, - { "BookmarkNew", STOCK_BOOKMARK_NEW - , NULL, "d" - , "hm?", G_CALLBACK(on_action_bookmark_new_activate) }, - { "BookmarksManage", STOCK_BOOKMARKS - , "_Manage Bookmarks", "b" - , "hm?", NULL/*G_CALLBACK(on_action_bookmarks_manage_activate)*/ }, - { "BookmarkOpen", GTK_STOCK_OPEN - , NULL, "" - , "hm?", G_CALLBACK(on_action_bookmarkOpen_activate) }, - { "BookmarkOpenTab", STOCK_TAB_NEW - , "Open in New _Tab", "" - , "hm?", G_CALLBACK(on_action_bookmarkOpenTab_activate) }, - { "BookmarkOpenWindow", STOCK_WINDOW_NEW - , "Open in New _Window", "" - , "hm?", G_CALLBACK(on_action_bookmarkOpenWindow_activate) }, - { "BookmarkEdit", GTK_STOCK_EDIT - , NULL, "" - , "hm?", G_CALLBACK(on_action_bookmarkEdit_activate) }, - { "BookmarkDelete", GTK_STOCK_DELETE - , NULL, "" - , "hm?", G_CALLBACK(on_action_bookmarkDelete_activate) }, - - { "Tools", NULL, "_Tools" }, - - { "Window", NULL, "_Window" }, - { "SessionLoad", GTK_STOCK_REVERT_TO_SAVED - , "_Load Session", "" - , "hm?", NULL/*G_CALLBACK(on_action_session_load_activate)*/ }, - { "SessionSave", GTK_STOCK_SAVE_AS - , "_Save Session", "" - , "hm?", NULL/*G_CALLBACK(on_action_session_save_activate)*/ }, - { "TabPrevious", GTK_STOCK_GO_BACK - , "_Previous Tab", "Page_Up" - , "hm?", G_CALLBACK(on_action_tab_previous_activate) }, - { "TabNext", GTK_STOCK_GO_FORWARD - , "_Next Tab", "Page_Down" - , "hm?", G_CALLBACK(on_action_tab_next_activate) }, - { "TabOverview", NULL - , "Tab _Overview", "" - , "hm?", NULL/*G_CALLBACK(on_action_tab_overview_activate)*/ }, - - { "Help", NULL, "_Help" }, - { "HelpContents", GTK_STOCK_HELP - , "_Contents", "F1" - , "hm?", NULL/*G_CALLBACK(on_action_help_contents_activate)*/ }, - { "About", GTK_STOCK_ABOUT - , NULL, "" - , "hm?", G_CALLBACK(on_action_about_activate) }, - }; - static const guint entries_n = G_N_ELEMENTS(entries); - -static const GtkToggleActionEntry toggle_entries[] = { - { "PrivateBrowsing", NULL - , "P_rivate Browsing", "" - , "hm?", NULL/*G_CALLBACK(on_action_private_browsing_activate)*/ - , FALSE }, - { "WorkOffline", GTK_STOCK_DISCONNECT - , "_Work Offline", "" - , "hm?", NULL/*G_CALLBACK(on_action_work_offline_activate)*/ - , FALSE }, - - { "ToolbarNavigation", NULL - , "_Navigationbar", "" - , "hm?", G_CALLBACK(on_action_toolbar_navigation_activate) - , FALSE }, - { "Panels", NULL - , "_Panels", "F9" - , "hm?", G_CALLBACK(on_action_panels_activate) - , FALSE }, - { "ToolbarBookmarks", NULL - , "_Bookmarkbar", "" - , "hm?", G_CALLBACK(on_action_toolbar_bookmarks_activate) - , FALSE }, - { "ToolbarDownloads", NULL - , "_Downloadbar", "" - , "hm?", NULL/*G_CALLBACK(on_action_toolbar_downloads_activate)*/ - , FALSE }, - { "ToolbarStatus", NULL - , "_Statusbar", "" - , "hm?", G_CALLBACK(on_action_toolbar_status_activate) - , FALSE }, - { "RefreshEveryEnable", NULL - , "_Enabled", "" - , "hm?", NULL/*G_CALLBACK(on_action_reloadevery_enable_activate)*/ - , FALSE }, - { "ReloadEveryActive", NULL - , "_Active", "" - , "hm?", NULL/*G_CALLBACK(on_action_reloadevery_active_activate)*/ - , FALSE }, - }; - static const guint toggle_entries_n = G_N_ELEMENTS(toggle_entries); - -static const GtkRadioActionEntry refreshevery_entries[] = { - { "RefreshEvery30", NULL - , "30 seconds", "" - , "Refresh Every _30 Seconds", 30 }, - { "RefreshEvery60", NULL - , "60 seconds", "" - , "Refresh Every _60 Seconds", 60 }, - { "RefreshEvery300", NULL - , "5 minutes", "" - , "Refresh Every _5 Minutes", 300 }, - { "RefreshEvery900", NULL - , "15 minutes", "" - , "Refresh Every _15 Minutes", 900 }, - { "RefreshEvery1800", NULL - , "30 minutes", "" - , "Refresh Every 3_0 Minutes", 1800 }, - { "RefreshEveryCustom", NULL - , "Custom...", "" - , "Refresh by a _Custom Period", 0 }, - }; - static const guint refreshevery_entries_n = G_N_ELEMENTS(refreshevery_entries); - -static const GtkRadioActionEntry panel_entries[] = { - { "PanelDownloads", STOCK_DOWNLOADS - , NULL, "" - , "hm?", 0 }, - { "PanelBookmarks", STOCK_BOOKMARKS - , "_Bookmarks", "" - , "hm?", 1 }, - { "PanelConsole", STOCK_CONSOLE - , NULL, "" - , "hm?", 2 }, - { "PanelExtensions", STOCK_EXTENSIONS - , NULL, "" - , "hm?", 3 }, - { "PanelHistory", STOCK_HISTORY - , "_History", "" - , "hm?", 4 }, - // TODO: We want a better icon here, but which one? - { "PanelTabs", STOCK_TAB_NEW - , "_Tabs", "" - , "hm?", 5 }, - // TODO: We probably want another icon here - { "PanelPageholder", GTK_STOCK_CONVERT - , "_Pageholder", "" - , "hm?", 6 }, - }; - static const guint panel_entries_n = G_N_ELEMENTS(panel_entries); - -#endif /* !__BROWSER_H__ */ diff --git a/src/global.h b/src/global.h index 868ebd68..e27125c9 100644 --- a/src/global.h +++ b/src/global.h @@ -13,21 +13,19 @@ #define __GLOBAL_H__ 1 #include "conf.h" + +#include "midori-websettings.h" #include "../katze/katze.h" #include #include -// -- globals +// FIXME: Remove these globals -CConfig* config; GList* searchEngines; // Items of type 'SearchEngine' -GList* browsers; // Items of type 'CBrowser' -WebKitWebSettings* webSettings; -GtkAccelGroup* accel_group; KatzeXbelItem* bookmarks; -KatzeXbelItem* session; -KatzeXbelItem* tabtrash; +CConfig* config; +MidoriWebSettings* webSettings; // Custom stock items @@ -37,13 +35,7 @@ KatzeXbelItem* tabtrash; in order to reduce the amount of warnings :D */ #define STOCK_BOOKMARK GTK_STOCK_FILE // "stock_bookmark" // "bookmark-web" -#define STOCK_BOOKMARKS "bookmark-view" -#define STOCK_DOWNLOADS "package" // "download" -#define STOCK_CONSOLE "terminal" // "console" // MISSING -#define STOCK_EXTENSIONS "extension" // MISSING #define STOCK_FORM_FILL "insert-text" // "form-fill" // MISSING -#define STOCK_HISTORY "document-open-recent" -#define STOCK_HISTORY_ "history-view" #define STOCK_LOCATION "location-entry" #define STOCK_NEWSFEED "gtk-index" // "newsfeed" // MISSING #define STOCK_PLUGINS "plugin" // MISSING diff --git a/src/helpers.c b/src/helpers.c index 04b66837..489b8d7e 100644 --- a/src/helpers.c +++ b/src/helpers.c @@ -11,78 +11,24 @@ #include "helpers.h" +#include "global.h" #include "search.h" #include "sokoke.h" -#include "../katze/katze.h" + +#include "midori-webview.h" +#include #include #include -GtkIconTheme* get_icon_theme(GtkWidget* widget) -{ - return gtk_icon_theme_get_for_screen(gtk_widget_get_screen(widget)); -} - -GtkWidget* menu_item_new(const gchar* text, const gchar* icon - , GCallback signal, gboolean sensitive, gpointer userdata) -{ - GtkWidget* menuitem; - if(text) - menuitem = gtk_image_menu_item_new_with_mnemonic(text); - else - menuitem = gtk_image_menu_item_new_from_stock(icon, NULL); - if(icon) - { - GtkWidget* image = gtk_image_new_from_stock(icon, GTK_ICON_SIZE_MENU); - if(gtk_image_get_storage_type(GTK_IMAGE(image)) == GTK_IMAGE_EMPTY) - image = gtk_image_new_from_icon_name(icon, GTK_ICON_SIZE_MENU); - if(gtk_image_get_storage_type(GTK_IMAGE(image)) != GTK_IMAGE_EMPTY) - gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), image); - else - g_print("Note: The icon %s is not available.", icon); - } - if(signal) - g_signal_connect(menuitem, "activate", signal, userdata); - gtk_widget_set_sensitive(GTK_WIDGET(menuitem), sensitive && signal); - return menuitem; -} - -GtkToolItem* tool_button_new(const gchar* text, const gchar* icon - , gboolean important, gboolean sensitive, GCallback signal - , const gchar* tooltip, gpointer userdata) -{ - GtkToolItem* toolbutton = gtk_tool_button_new(NULL, NULL); - GtkStockItem stockItem; - if(gtk_stock_lookup(icon, &stockItem)) - toolbutton = gtk_tool_button_new_from_stock(icon); - else - { - GtkIconTheme* iconTheme = get_icon_theme(GTK_WIDGET(toolbutton)); - if(gtk_icon_theme_has_icon(iconTheme, icon)) - gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(toolbutton), icon); - else - gtk_tool_button_set_stock_id(GTK_TOOL_BUTTON(toolbutton), GTK_STOCK_MISSING_IMAGE); - } - if(text) - gtk_tool_button_set_label(GTK_TOOL_BUTTON(toolbutton), text); - if(important) - gtk_tool_item_set_is_important(toolbutton, TRUE); - if(signal) - g_signal_connect(toolbutton, "clicked", signal, userdata); - gtk_widget_set_sensitive(GTK_WIDGET(toolbutton), sensitive && signal); - if(tooltip) - sokoke_tool_item_set_tooltip_text(toolbutton, tooltip); - return toolbutton; -} - GtkWidget* check_menu_item_new(const gchar* text - , GCallback signal, gboolean sensitive, gboolean active, CBrowser* browser) + , GCallback signal, gboolean sensitive, gboolean active, gpointer userdata) { GtkWidget* menuitem = gtk_check_menu_item_new_with_mnemonic(text); gtk_widget_set_sensitive(menuitem, sensitive && signal); gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem), active); if(signal) - g_signal_connect(menuitem, "activate", signal, browser); + g_signal_connect(menuitem, "activate", signal, userdata); return menuitem; } @@ -91,10 +37,10 @@ GtkWidget* radio_button_new(GtkRadioButton* radio_button, const gchar* label) return gtk_radio_button_new_with_mnemonic_from_widget(radio_button, label); } -void show_error(const gchar* text, const gchar* text2, CBrowser* browser) +void show_error(const gchar* text, const gchar* text2, MidoriBrowser* browser) { GtkWidget* dialog = gtk_message_dialog_new( - browser ? GTK_WINDOW(browser->window) : NULL + browser ? GTK_WINDOW(browser) : NULL , 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, text); if(text2) gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), text2); @@ -191,223 +137,6 @@ void entry_completion_append(GtkEntry* entry, const gchar* text) gtk_list_store_set(GTK_LIST_STORE(completion_store), &iter, 0, text, -1); } -GtkWidget* get_nth_webView(gint n, CBrowser* browser) -{ - if(n < 0) - n = gtk_notebook_get_current_page(GTK_NOTEBOOK(browser->webViews)); - GtkWidget* scrolled = gtk_notebook_get_nth_page(GTK_NOTEBOOK(browser->webViews), n); - return gtk_bin_get_child(GTK_BIN(scrolled)); -} - -gint get_webView_index(GtkWidget* webView, CBrowser* browser) -{ - GtkWidget* scrolled = gtk_widget_get_parent(webView); - return gtk_notebook_page_num(GTK_NOTEBOOK(browser->webViews), scrolled); -} - -CBrowser* get_browser_from_webView(GtkWidget* webView) -{ - // FIXME: g_list_first - CBrowser* browser = NULL; GList* item = g_list_first(browsers); - do - { - browser = (CBrowser*)item->data; - if(browser->webView == webView) - return browser; - } - while((item = g_list_next(item))); - return NULL; -} - -void update_favicon(CBrowser* browser) -{ - if(browser->loadedPercent == -1) - { - if(0) //browser->favicon // Has favicon? - { - // TODO: use custom icon - // gtk_image_set_from_file(GTK_IMAGE(browser->icon_page), "image"); - } - else if(0) // Known mime-type? - { - // TODO: Retrieve mime type and load icon; don't forget ftp listings - } - else - katze_throbber_set_static_stock_id(KATZE_THROBBER(browser->webView_icon) - , GTK_STOCK_FILE); - } - katze_throbber_set_animated(KATZE_THROBBER(browser->webView_icon) - , browser->loadedPercent != -1); -} - -void update_security(CBrowser* browser) -{ - const gchar* uri = katze_xbel_bookmark_get_href(browser->sessionItem); - // TODO: This check is bogus, until webkit tells us how secure a page is - if(g_str_has_prefix(uri, "https://")) - { - // TODO: highlighted entry indicates security, find an alternative - gtk_widget_modify_base(browser->location, GTK_STATE_NORMAL - , &browser->location->style->base[GTK_STATE_SELECTED]); - gtk_widget_modify_text(browser->location, GTK_STATE_NORMAL - , &browser->location->style->text[GTK_STATE_SELECTED]); - gtk_image_set_from_stock(GTK_IMAGE(browser->icon_security) - , GTK_STOCK_DIALOG_AUTHENTICATION, GTK_ICON_SIZE_MENU); - } - else - { - gtk_widget_modify_base(browser->location, GTK_STATE_NORMAL, NULL); - gtk_widget_modify_text(browser->location, GTK_STATE_NORMAL, NULL); - gtk_image_set_from_stock(GTK_IMAGE(browser->icon_security) - , GTK_STOCK_INFO, GTK_ICON_SIZE_MENU); - } -} - -void update_visibility(CBrowser* browser, gboolean visibility) -{ - // A tabbed window shouldn't be manipulatable - if(gtk_notebook_get_n_pages(GTK_NOTEBOOK(browser->webViews)) > 1) - return; - - // SHOULD SCRIPTS BE ABLE TO HIDE WINDOWS AT ALL? - if(0 && !visibility) - { - gtk_widget_hide(browser->window); - return; - } - else if(!visibility) - g_print("Window was not hidden.\n"); - - sokoke_widget_set_visible(browser->menubar, browser->hasMenubar); - sokoke_widget_set_visible(browser->navibar, browser->hasToolbar); - sokoke_widget_set_visible(browser->location, browser->hasLocation); - sokoke_widget_set_visible(browser->webSearch, browser->hasLocation); - sokoke_widget_set_visible(browser->statusbar, browser->hasStatusbar); -} - -void action_set_active(const gchar* name, gboolean active, CBrowser* browser) -{ - // This shortcut toggles activity state by an action name - GtkAction* action = gtk_action_group_get_action(browser->actiongroup, name); - gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), active); -} - -void action_set_sensitive(const gchar* name, gboolean sensitive, CBrowser* browser) -{ - // This shortcut toggles sensitivity by an action name - GtkAction* action = gtk_action_group_get_action(browser->actiongroup, name); - gtk_action_set_sensitive(action, sensitive); -} - -void action_set_visible(const gchar* name, gboolean visible, CBrowser* browser) -{ - // This shortcut toggles visibility by an action name - GtkAction* action = gtk_action_group_get_action(browser->actiongroup, name); - gtk_action_set_visible(action, visible); -} - -void update_statusbar(CBrowser* browser) -{ - gtk_statusbar_pop(GTK_STATUSBAR(browser->statusbar), 1); - gtk_statusbar_push(GTK_STATUSBAR(browser->statusbar), 1 - , browser->statusMessage ? browser->statusMessage : ""); - if(browser->loadedPercent > -1) - { - if(browser->loadedPercent > -1) - gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(browser->progress) - , browser->loadedPercent ? browser->loadedPercent / 100.0 : 0); - else - gtk_progress_bar_pulse(GTK_PROGRESS_BAR(browser->progress)); - gchar* message = g_strdup_printf("%d%% loaded", browser->loadedPercent); - gtk_progress_bar_set_text(GTK_PROGRESS_BAR(browser->progress), message); - g_free(message); - } -} - -void update_edit_items(CBrowser* browser) -{ - GtkWidget* widget = gtk_window_get_focus(GTK_WINDOW(browser->window)); - gboolean canCut = FALSE; gboolean canCopy = FALSE; gboolean canPaste = FALSE; - if(widget && (WEBKIT_IS_WEB_VIEW(widget) || GTK_IS_EDITABLE(widget))) - { - gboolean hasSelection = WEBKIT_IS_WEB_VIEW(widget) - ? webkit_web_view_has_selection(WEBKIT_WEB_VIEW(widget)) - : gtk_editable_get_selection_bounds(GTK_EDITABLE(widget), NULL, NULL); - canCut = WEBKIT_IS_WEB_VIEW(widget) - ? webkit_web_view_can_cut_clipboard(WEBKIT_WEB_VIEW(widget)) - : hasSelection && gtk_editable_get_editable(GTK_EDITABLE(widget)); - canCopy = WEBKIT_IS_WEB_VIEW(widget) - ? webkit_web_view_can_copy_clipboard(WEBKIT_WEB_VIEW(widget)) - : hasSelection; - canPaste = WEBKIT_IS_WEB_VIEW(widget) - ? webkit_web_view_can_paste_clipboard(WEBKIT_WEB_VIEW(widget)) - : gtk_editable_get_editable(GTK_EDITABLE(widget)); - action_set_sensitive("SelectAll", TRUE, browser); - } - else - action_set_sensitive("SelectAll", FALSE, browser); - action_set_sensitive("Cut", canCut, browser); - action_set_sensitive("Copy", canCopy, browser); - action_set_sensitive("Paste", canPaste, browser); - action_set_sensitive("Delete", canCut, browser); -} - -void update_gui_state(CBrowser* browser) -{ - GtkWidget* webView = get_nth_webView(-1, browser); - action_set_sensitive("ZoomIn", FALSE, browser);//webkit_web_view_can_increase_text_size(WEBKIT_WEB_VIEW(webView), browser); - action_set_sensitive("ZoomOut", FALSE, browser);//webkit_web_view_can_decrease_text_size(WEBKIT_WEB_VIEW(webView)), browser); - action_set_sensitive("ZoomNormal", FALSE, browser);//webkit_web_view_get_text_size(WEBKIT_WEB_VIEW(webView)) != 1, browser); - action_set_sensitive("Back", webkit_web_view_can_go_back(WEBKIT_WEB_VIEW(webView)), browser); - action_set_sensitive("Forward", webkit_web_view_can_go_forward(WEBKIT_WEB_VIEW(webView)), browser); - action_set_sensitive("Refresh", browser->loadedPercent == -1, browser); - action_set_sensitive("Stop", browser->loadedPercent != -1, browser); - - GtkAction* action = gtk_action_group_get_action(browser->actiongroup, "RefreshStop"); - if(browser->loadedPercent == -1) - { - gtk_widget_set_sensitive(browser->throbber, FALSE); - g_object_set(action, "stock-id", GTK_STOCK_REFRESH, NULL); - g_object_set(action, "tooltip", "Refresh the current page", NULL); - gtk_widget_hide(browser->progress); - } - else - { - gtk_widget_set_sensitive(browser->throbber, TRUE); - g_object_set(action, "stock-id", GTK_STOCK_STOP, NULL); - g_object_set(action, "tooltip", "Stop loading the current page", NULL); - gtk_widget_show(browser->progress); - } - katze_throbber_set_animated(KATZE_THROBBER(browser->throbber) - , browser->loadedPercent != -1); - - gtk_image_set_from_stock(GTK_IMAGE(browser->location_icon), GTK_STOCK_FILE - , GTK_ICON_SIZE_MENU); -} - -void update_feeds(CBrowser* browser) -{ - // TODO: Look for available feeds, requires dom access -} - -void update_search_engines(CBrowser* browser) -{ - // TODO: Look for available search engines, requires dom access -} - -void update_browser_actions(CBrowser* browser) -{ - gboolean active = gtk_notebook_get_n_pages(GTK_NOTEBOOK(browser->webViews)) > 1; - gtk_notebook_set_show_tabs(GTK_NOTEBOOK(browser->webViews), active); - action_set_sensitive("TabClose", active, browser); - action_set_sensitive("TabPrevious", active, browser); - action_set_sensitive("TabNext", active, browser); - - gboolean tabtrashEmpty = katze_xbel_folder_is_empty(tabtrash); - action_set_sensitive("UndoTabClose", !tabtrashEmpty, browser); - action_set_sensitive("TabsClosed", !tabtrashEmpty, browser); -} - gchar* magic_uri(const gchar* uri, gboolean search) { // Add file:// if we have a local path diff --git a/src/helpers.h b/src/helpers.h index c1812166..0db7400f 100644 --- a/src/helpers.h +++ b/src/helpers.h @@ -12,28 +12,18 @@ #ifndef __HELPERS_H__ #define __HELPERS_H__ 1 -#include "browser.h" - #include -GtkIconTheme* -get_icon_theme(GtkWidget*); +#include "midori-browser.h" GtkWidget* -menu_item_new(const gchar*, const gchar*, GCallback, gboolean, gpointer); - -GtkToolItem* -tool_button_new(const gchar*, const gchar* - , gboolean, gboolean, GCallback, const gchar*, gpointer); - -GtkWidget* -check_menu_item_new(const gchar*, GCallback, gboolean, gboolean, CBrowser*); +check_menu_item_new(const gchar*, GCallback, gboolean, gboolean, gpointer); GtkWidget* radio_button_new(GtkRadioButton*, const gchar*); void -show_error(const gchar*, const gchar*, CBrowser*); +show_error(const gchar*, const gchar*, MidoriBrowser*); gboolean spawn_protocol_command(const gchar*, const gchar*); @@ -47,51 +37,6 @@ entry_setup_completion(GtkEntry*); void entry_completion_append(GtkEntry*, const gchar*); -GtkWidget* -get_nth_webView(gint, CBrowser*); - -gint -get_webView_index(GtkWidget*, CBrowser*); - -CBrowser* -get_browser_from_webView(GtkWidget*); - -void -update_favicon(CBrowser*); - -void -update_security(CBrowser*); - -void -update_visibility(CBrowser*, gboolean); - -void -action_set_active(const gchar*, gboolean, CBrowser*); - -void -action_set_sensitive(const gchar*, gboolean, CBrowser*); - -void -action_set_visible(const gchar*, gboolean, CBrowser*); - -void -update_statusbar(CBrowser*); - -void -update_edit_items(CBrowser*); - -void -update_gui_state(CBrowser*); - -void -update_feeds(CBrowser*); - -void -update_search_engines(CBrowser*); - -void -update_browser_actions(CBrowser*); - gchar* magic_uri(const gchar*, gboolean bSearch); diff --git a/src/main.c b/src/main.c old mode 100755 new mode 100644 index 55e23485..2fdf1854 --- a/src/main.c +++ b/src/main.c @@ -11,17 +11,18 @@ #include "main.h" -#include "browser.h" #include "global.h" #include "helpers.h" #include "sokoke.h" #include "search.h" -#include "webView.h" -#include "../katze/katze.h" + +#include "midori-websettings.h" +#include "midori-trash.h" +#include "midori-browser.h" +#include #include #include -#include #include "config.h" @@ -40,12 +41,7 @@ static void stock_items_init(void) { STOCK_BOOKMARK, "Bookmark", 0, 0, NULL }, { STOCK_BOOKMARK_NEW, "New Bookmark", 0, 0, NULL }, - { STOCK_BOOKMARKS, "_Bookmarks", 0, 0, NULL }, - { STOCK_DOWNLOADS, "_Downloads", 0, 0, NULL }, - { STOCK_CONSOLE, "_Console", 0, 0, NULL }, - { STOCK_EXTENSIONS, "_Extensions", 0, 0, NULL }, { STOCK_FORM_FILL, "_Form Fill", 0, 0, NULL }, - { STOCK_HISTORY, "History", 0, 0, NULL }, { STOCK_HOMEPAGE, "Homepage", 0, 0, NULL }, { STOCK_LOCATION, "Location Entry", 0, 0, NULL }, { STOCK_NEWSFEED, "Newsfeed", 0, 0, NULL }, @@ -81,7 +77,46 @@ static void stock_items_init(void) g_object_unref(factory); } -// -- main function +static gboolean +midori_browser_delete_event_cb (MidoriBrowser* browser, + GdkEvent* event, + GList* browsers) +{ + browsers = g_list_remove (browsers, browser); + if (g_list_nth (browsers, 0)) + return FALSE; + gtk_main_quit (); + return TRUE; +} + +static void +midori_browser_quit_cb (MidoriBrowser* browser, + GdkEvent* event, + GList* browsers) +{ + gtk_main_quit (); +} + +static void +midori_browser_new_window_cb (MidoriBrowser* browser, + const gchar* uri, + GList* browsers) +{ + MidoriBrowser* new_browser = g_object_new (MIDORI_TYPE_BROWSER, + // "settings", settings, + // "trash", trash, + NULL); + // gtk_window_add_accel_group (GTK_WINDOW (browser), accel_group); + g_object_connect (new_browser, + "signal::new-window", midori_browser_new_window_cb, browsers, + "signal::delete-event", midori_browser_delete_event_cb, browsers, + "signal::quit", midori_browser_quit_cb, browsers, + NULL); + browsers = g_list_prepend(browsers, new_browser); + gtk_widget_show (GTK_WIDGET (new_browser)); + + midori_browser_append_uri (new_browser, uri); +} int main(int argc, char** argv) { @@ -105,7 +140,7 @@ int main(int argc, char** argv) if(version) { - g_print(PACKAGE_STRING " - Copyright (c) 2007 Christian Dywan\n\n" + g_print(PACKAGE_STRING " - Copyright (c) 2007-2008 Christian Dywan\n\n" "GTK+2: " GTK_VER "\n" "WebKit: " WEBKIT_VER "\n" "Libsexy: " LIBSEXY_VER "\n" @@ -128,7 +163,7 @@ int main(int argc, char** argv) g_mkdir_with_parents(configPath, 0755); gchar* configFile = g_build_filename(configPath, "config", NULL); error = NULL; - config = config_new(); + /*CConfig* */config = config_new(); if(!config_from_file(config, configFile, &error)) { if(error->code != G_FILE_ERROR_NOENT) @@ -178,9 +213,9 @@ int main(int argc, char** argv) g_free(configFile); } configFile = g_build_filename(configPath, "tabtrash.xbel", NULL); - tabtrash = katze_xbel_folder_new(); + KatzeXbelItem* xbel_trash = katze_xbel_folder_new(); error = NULL; - if(!katze_xbel_folder_from_file(tabtrash, configFile, &error)) + if(!katze_xbel_folder_from_file(xbel_trash, configFile, &error)) { if(error->code != G_FILE_ERROR_NOENT) g_string_append_printf(errorMessages @@ -211,6 +246,7 @@ int main(int argc, char** argv) search_engines_free(searchEngines); katze_xbel_item_unref(bookmarks); katze_xbel_item_unref(_session); + katze_xbel_item_unref(xbel_trash); g_string_free(errorMessages, TRUE); return 0; } @@ -245,37 +281,68 @@ int main(int argc, char** argv) } g_free(configPath); - accel_group = gtk_accel_group_new(); stock_items_init(); - browsers = NULL; - webSettings = g_object_new(WEBKIT_TYPE_WEB_SETTINGS - , "default-font-family" , config->defaultFontFamily - , "default-font-size" , config->defaultFontSize - , "minimum-font-size" , config->minimumFontSize - , "default-encoding" , config->defaultEncoding - , "auto-load-images" , config->autoLoadImages - , "auto-shrink-images" , config->autoShrinkImages - , "print-backgrounds" , config->printBackgrounds - , "resizable-text-areas", config->resizableTextAreas - , "user-stylesheet-uri" , config->userStylesheet ? config->userStylesheetUri : NULL - , "enable-scripts" , config->enableScripts - , "enable-plugins" , config->enablePlugins - , NULL); + MidoriWebSettings* settings; + settings = g_object_new (MIDORI_TYPE_WEB_SETTINGS, + "default-font-family", config->defaultFontFamily, + "default-font-size", config->defaultFontSize, + "minimum-font-size", config->minimumFontSize, + "default-encoding", config->defaultEncoding, + "auto-load-images", config->autoLoadImages, + "auto-shrink-images", config->autoShrinkImages, + "print-backgrounds", config->printBackgrounds, + "resizable-text-areas", config->resizableTextAreas, + "user-stylesheet-uri", + config->userStylesheet ? + config->userStylesheetUri : NULL, + "enable-scripts", config->enableScripts, + "enable-plugins", config->enablePlugins, + "tab-label-size", config->tabSize, + "close-button", config->tabClose, + "middle-click-goto", config->middleClickGoto, + NULL); + webSettings = settings; - session = katze_xbel_folder_new(); - CBrowser* browser = NULL; - guint n = katze_xbel_folder_get_n_items(_session); + MidoriTrash* trash = g_object_new (MIDORI_TYPE_TRASH, + "limit", 10, + NULL); guint i; - for(i = 0; i < n; i++) + guint n = katze_xbel_folder_get_n_items (xbel_trash); + for (i = 0; i < n; i++) { - KatzeXbelItem* item = katze_xbel_folder_get_nth_item(_session, i); - browser = browser_new(browser); - webView_open(browser->webView, katze_xbel_bookmark_get_href(item)); + KatzeXbelItem* item = katze_xbel_folder_get_nth_item (xbel_trash, i); + midori_trash_prepend_xbel_item (trash, item); } - katze_xbel_item_unref(_session); - gtk_main(); + GtkAccelGroup* accel_group = gtk_accel_group_new(); + GList* browsers = NULL; + + MidoriBrowser* browser = g_object_new (MIDORI_TYPE_BROWSER, + "settings", settings, + "trash", trash, + NULL); + gtk_window_add_accel_group (GTK_WINDOW (browser), accel_group); + g_object_connect (browser, + "signal::new-window", midori_browser_new_window_cb, browsers, + "signal::delete-event", midori_browser_delete_event_cb, browsers, + "signal::quit", midori_browser_quit_cb, browsers, + NULL); + browsers = g_list_prepend(browsers, browser); + gtk_widget_show (GTK_WIDGET (browser)); + + KatzeXbelItem* session = katze_xbel_folder_new (); + n = katze_xbel_folder_get_n_items (_session); + for (i = 0; i < n; i++) + { + KatzeXbelItem* item = katze_xbel_folder_get_nth_item (_session, i); + midori_browser_append_xbel_item (browser, item); + } + katze_xbel_item_unref (_session); + + gtk_main (); + + g_object_unref (accel_group); // Save configuration files configPath = g_build_filename(g_get_user_config_dir(), PACKAGE_NAME, NULL); @@ -300,13 +367,13 @@ int main(int argc, char** argv) g_free(configFile); configFile = g_build_filename(configPath, "tabtrash.xbel", NULL); error = NULL; - if(!katze_xbel_folder_to_file(tabtrash, configFile, &error)) + if (!katze_xbel_folder_to_file (xbel_trash, configFile, &error)) { - g_warning("Tabtrash couldn't be saved. %s", error->message); - g_error_free(error); + g_warning ("Tabtrash couldn't be saved. %s", error->message); + g_error_free (error); } - katze_xbel_item_unref(tabtrash); - g_free(configFile); + katze_xbel_item_unref (xbel_trash); + g_free (configFile); if(config->startup == CONFIG_STARTUP_SESSION) { configFile = g_build_filename(configPath, "session.xbel", NULL); diff --git a/src/midori-browser.c b/src/midori-browser.c new file mode 100644 index 00000000..21e54763 --- /dev/null +++ b/src/midori-browser.c @@ -0,0 +1,2986 @@ +/* + Copyright (C) 2007-2008 Christian Dywan + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + See the file COPYING for the full license text. +*/ + +#include "config.h" + +#include "midori-browser.h" + +#include "global.h" +#include "conf.h" +#include "helpers.h" +#include "webSearch.h" +#include "prefs.h" + +#include "sokoke.h" +#include "midori-webview.h" +#include "midori-panel.h" +#include "midori-trash.h" + +#include +#include +#include +#include + +G_DEFINE_TYPE (MidoriBrowser, midori_browser, GTK_TYPE_WINDOW) + +struct _MidoriBrowserPrivate +{ + GtkActionGroup* action_group; + GtkWidget* menubar; + GtkWidget* menu_bookmarks; + GtkWidget* menu_tools; + GtkWidget* menu_window; + GtkWidget* popup_bookmark; + GtkWidget* throbber; + GtkWidget* navigationbar; + GtkWidget* button_tab_new; + GtkWidget* location_icon; + GtkWidget* location; + GtkWidget* search; + GtkWidget* button_trash; + GtkWidget* button_fullscreen; + GtkWidget* bookmarkbar; + + GtkWidget* panel; + GtkWidget* panel_bookmarks; + GtkWidget* panel_pageholder; + GtkWidget* notebook; + + GtkWidget* find; + GtkWidget* find_text; + GtkToolItem* find_case; + GtkToolItem* find_highlight; + + GtkWidget* statusbar; + GtkWidget* progressbar; + + gchar* uri; + gchar* title; + gchar* statusbar_text; + MidoriWebSettings* settings; + + KatzeXbelItem* proxy_xbel_folder; + MidoriTrash* trash; +}; + +#define MIDORI_BROWSER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + MIDORI_TYPE_BROWSER, MidoriBrowserPrivate)) + +enum +{ + PROP_0, + + PROP_SETTINGS, + PROP_STATUSBAR_TEXT, + PROP_TRASH +}; + +enum { + NEW_WINDOW, + STATUSBAR_TEXT_CHANGED, + ELEMENT_MOTION, + QUIT, + + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL]; + +static void +midori_browser_finalize (GObject* object); + +static void +midori_browser_set_property (GObject* object, + guint prop_id, + const GValue* value, + GParamSpec* pspec); + +static void +midori_browser_get_property (GObject* object, + guint prop_id, + GValue* value, + GParamSpec* pspec); + +static GtkAction* +_action_by_name (MidoriBrowser* browser, + const gchar* name) +{ + MidoriBrowserPrivate* priv = browser->priv; + + return gtk_action_group_get_action (priv->action_group, name); +} + +static void +_action_set_sensitive (MidoriBrowser* browser, + const gchar* name, + gboolean sensitive) +{ + gtk_action_set_sensitive (_action_by_name (browser, name), sensitive); +} + +static void +_action_set_active (MidoriBrowser* browser, + const gchar* name, + gboolean active) +{ + GtkAction* action = _action_by_name (browser, name); + gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), active); +} + +static void +_midori_browser_update_actions (MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + guint n = gtk_notebook_get_n_pages (GTK_NOTEBOOK (priv->notebook)); + gtk_notebook_set_show_tabs (GTK_NOTEBOOK (priv->notebook), n > 1); + _action_set_sensitive (browser, "TabClose", n > 1); + _action_set_sensitive (browser, "TabPrevious", n > 1); + _action_set_sensitive (browser, "TabNext", n > 1); + + if (priv->trash) + { + gboolean trash_empty = midori_trash_is_empty (priv->trash); + _action_set_sensitive (browser, "UndoTabClose", !trash_empty); + _action_set_sensitive (browser, "Trash", !trash_empty); + } +} + +static void +_midori_browser_update_interface (MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + GtkWidget* web_view = midori_browser_get_current_web_view (browser); + gboolean loading = midori_web_view_is_loading (MIDORI_WEB_VIEW (web_view)); + /*_action_set_sensitive (browser, "ZoomIn", + webkit_web_view_can_increase_text_size (WEBKIT_WEB_VIEW (web_view))); + _action_set_sensitive (browser, "ZoomOut", + webkit_web_view_can_decrease_text_size (WEBKIT_WEB_VIEW (web_view))); + _action_set_sensitive (browser, "ZoomNormal", + webkit_web_view_get_text_size (WEBKIT_WEB_VIEW (web_view)) != 1);*/ + _action_set_sensitive (browser, "Back", + webkit_web_view_can_go_back (WEBKIT_WEB_VIEW (web_view))); + _action_set_sensitive (browser, "Back", + webkit_web_view_can_go_forward (WEBKIT_WEB_VIEW (web_view))); + _action_set_sensitive (browser, "Reload", loading); + _action_set_sensitive (browser, "Stop", !loading); + + GtkAction* action = gtk_action_group_get_action (priv->action_group, + "ReloadStop"); + if (!loading) + { + gtk_widget_set_sensitive (priv->throbber, FALSE); + g_object_set (action, + "stock-id", GTK_STOCK_REFRESH, + "tooltip", "Reload the current page", NULL); + gtk_widget_hide (priv->progressbar); + } + else + { + gtk_widget_set_sensitive (priv->throbber, TRUE); + g_object_set (action, + "stock-id", GTK_STOCK_STOP, + "tooltip", "Stop loading the current page", NULL); + gtk_widget_show (priv->progressbar); + } + katze_throbber_set_animated (KATZE_THROBBER (priv->throbber), loading); + gtk_image_set_from_stock (GTK_IMAGE (priv->location_icon), + GTK_STOCK_FILE, GTK_ICON_SIZE_MENU); +} + +static GtkWidget* +_midori_browser_scrolled_for_child (MidoriBrowser* panel, + GtkWidget* child) +{ + GtkWidget* scrolled = gtk_widget_get_parent (child); + if (GTK_IS_VIEWPORT (scrolled)) + scrolled = gtk_widget_get_parent (scrolled); + return scrolled; +} + +static GtkWidget* +_midori_browser_child_for_scrolled (MidoriBrowser* panel, + GtkWidget* scrolled) +{ + GtkWidget* child = gtk_bin_get_child (GTK_BIN (scrolled)); + if (GTK_IS_VIEWPORT (child)) + child = gtk_bin_get_child (GTK_BIN (child)); + return child; +} + +static WebKitNavigationResponse +midori_web_view_navigation_requested_cb (GtkWidget* web_view, + WebKitWebFrame* web_frame, + WebKitNetworkRequest* request) +{ + WebKitNavigationResponse response = WEBKIT_NAVIGATION_RESPONSE_ACCEPT; + // FIXME: This isn't the place for uri scheme handling + const gchar* uri = webkit_network_request_get_uri (request); + gchar* protocol = strtok (g_strdup (uri), ":"); + if (spawn_protocol_command (protocol, uri)) + response = WEBKIT_NAVIGATION_RESPONSE_IGNORE; + g_free (protocol); + return response; +} + +static void +_midori_browser_set_statusbar_text (MidoriBrowser* browser, + const gchar* text) +{ + MidoriBrowserPrivate* priv = browser->priv; + + katze_assign (priv->statusbar_text, g_strdup (text)); + gtk_statusbar_pop (GTK_STATUSBAR (priv->statusbar), 1); + gtk_statusbar_push (GTK_STATUSBAR (priv->statusbar), 1, + priv->statusbar_text ? priv->statusbar_text : ""); +} + +static void +_midori_browser_update_progress (MidoriBrowser* browser, + gint progress) +{ + MidoriBrowserPrivate* priv = browser->priv; + + if (progress > -1) + { + gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (priv->progressbar), + progress ? progress / 100.0 : 0); + gchar* message = g_strdup_printf ("%d%% loaded", progress); + gtk_progress_bar_set_text (GTK_PROGRESS_BAR (priv->progressbar), + message); + g_free (message); + } + else + { + gtk_progress_bar_pulse (GTK_PROGRESS_BAR (priv->progressbar)); + gtk_progress_bar_set_text (GTK_PROGRESS_BAR (priv->progressbar), + NULL); + } +} + +static void +midori_web_view_load_started_cb (GtkWidget* web_view, + WebKitWebFrame* web_frame, + MidoriBrowser* browser) +{ + if (web_view == midori_browser_get_current_web_view (browser)) + { + _midori_browser_update_interface (browser); + _midori_browser_set_statusbar_text (browser, NULL); + } +} + +static void +midori_web_view_progress_started_cb (GtkWidget* web_view, + guint progress, + MidoriBrowser* browser) +{ + if (web_view == midori_browser_get_current_web_view (browser)) + _midori_browser_update_progress (browser, progress); +} + +static void +midori_web_view_progress_changed_cb (GtkWidget* web_view, + guint progress, + MidoriBrowser* browser) +{ + if (web_view == midori_browser_get_current_web_view (browser)) + _midori_browser_update_progress (browser, progress); +} + +static void +midori_web_view_progress_done_cb (GtkWidget* web_view, + guint progress, + MidoriBrowser* browser) +{ + if (web_view == midori_browser_get_current_web_view (browser)) + _midori_browser_update_progress (browser, progress); +} + +static void +midori_web_view_load_done_cb (GtkWidget* web_view, + WebKitWebFrame* web_frame, + MidoriBrowser* browser) +{ + if (web_view == midori_browser_get_current_web_view (browser)) + { + _midori_browser_update_interface (browser); + _midori_browser_set_statusbar_text (browser, NULL); + } +} + +static void +midori_web_view_title_changed_cb (GtkWidget* web_view, + WebKitWebFrame* web_frame, + const gchar* title, + MidoriBrowser* browser) +{ + if (web_view == midori_browser_get_current_web_view (browser)) + { + const gchar* title = midori_web_view_get_display_title ( + MIDORI_WEB_VIEW (web_view)); + gchar* window_title = g_strconcat (title, " - ", + g_get_application_name (), NULL); + gtk_window_set_title (GTK_WINDOW (browser), window_title); + g_free (window_title); + } +} + +static void +midori_web_view_statusbar_text_changed_cb (MidoriWebView* web_view, + const gchar* text, + MidoriBrowser* browser) +{ + _midori_browser_set_statusbar_text (browser, text); +} + +static void +midori_web_view_element_motion_cb (MidoriWebView* web_View, + const gchar* link_uri, + MidoriBrowser* browser) +{ + _midori_browser_set_statusbar_text (browser, link_uri); +} + +static void +midori_web_view_load_committed_cb (GtkWidget* web_view, + WebKitWebFrame* web_frame, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + if (web_view == midori_browser_get_current_web_view (browser)) + { + const gchar* uri = midori_web_view_get_display_uri (MIDORI_WEB_VIEW (web_view)); + gtk_entry_set_text (GTK_ENTRY (priv->location), uri); + _midori_browser_set_statusbar_text (browser, NULL); + } +} + +static gboolean +midori_web_view_console_message_cb (GtkWidget* web_view, + const gchar* message, + gint line, + const gchar* sourceId, + MidoriBrowser* browser) +{ + // FIXME: We want this to appear in a panel + return FALSE; +} + +static void +midori_web_view_populate_popup_cb (GtkWidget* web_view, + GtkWidget* menu, + MidoriBrowser* browser) +{ + const gchar* uri = midori_web_view_get_link_uri (MIDORI_WEB_VIEW (web_view)); + if (uri) + { + // TODO: bookmark link + } + + if (webkit_web_view_has_selection (WEBKIT_WEB_VIEW (web_view))) + { + // TODO: view selection source + } + + if (!uri && !webkit_web_view_has_selection (WEBKIT_WEB_VIEW (web_view))) + { + // TODO: menu items + // undo close tab + // sep + // BookmarkNew + // SaveAs + // SourceView + // Print + } +} + +static gboolean +midori_web_view_leave_notify_event_cb (GtkWidget* web_view, + GdkEventCrossing* event, + MidoriBrowser* browser) +{ + _midori_browser_set_statusbar_text (browser, NULL); + return TRUE; +} + +static void +midori_web_view_new_tab_cb (GtkWidget* web_view, + const gchar* uri, + MidoriBrowser* browser) +{ + midori_browser_append_uri (browser, uri); +} + +static void +midori_web_view_new_window_cb (GtkWidget* web_view, + const gchar* uri, + MidoriBrowser* browser) +{ + g_signal_emit (browser, signals[NEW_WINDOW], 0, uri); +} + +static void +midori_web_view_close_cb (GtkWidget* web_view, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + if (priv->proxy_xbel_folder) + { + KatzeXbelItem* xbel_item = midori_web_view_get_proxy_xbel_item ( + MIDORI_WEB_VIEW (web_view)); + const gchar* uri = katze_xbel_bookmark_get_href (xbel_item); + if (priv->trash && uri && *uri) + midori_trash_prepend_xbel_item (priv->trash, xbel_item); + katze_xbel_folder_remove_item (priv->proxy_xbel_folder, xbel_item); + katze_xbel_item_unref (xbel_item); + } + GtkWidget* scrolled = _midori_browser_scrolled_for_child (browser, web_view); + guint n = gtk_notebook_page_num (GTK_NOTEBOOK (priv->notebook), scrolled); + gtk_notebook_remove_page (GTK_NOTEBOOK (priv->notebook), n); + + _midori_browser_update_actions (browser); +} + +static gboolean +midori_web_view_destroy_cb (GtkWidget* widget, + MidoriBrowser* browser) +{ + _midori_browser_update_actions (browser); + return FALSE; +} + +static void +midori_browser_class_init (MidoriBrowserClass* class) +{ + + signals[QUIT] = g_signal_new( + "quit", + G_TYPE_FROM_CLASS(class), + (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), + 0, + 0, + NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + signals[NEW_WINDOW] = g_signal_new( + "new-window", + G_TYPE_FROM_CLASS(class), + (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), + G_STRUCT_OFFSET (MidoriBrowserClass, new_window), + 0, + NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, + G_TYPE_STRING); + + GObjectClass* gobject_class = G_OBJECT_CLASS (class); + gobject_class->finalize = midori_browser_finalize; + gobject_class->set_property = midori_browser_set_property; + gobject_class->get_property = midori_browser_get_property; + + GParamFlags flags = G_PARAM_READWRITE | G_PARAM_CONSTRUCT; + + /** + * MidoriBrowser::settings + * + * An associated settings instance that is shared among all web views. + * + * Setting this value is propagated to every present web view. Also + * every newly created web view will use this instance automatically. + */ + g_object_class_install_property (gobject_class, + PROP_SETTINGS, + g_param_spec_object ( + "settings", + "Settings", + "The associated settings", + MIDORI_TYPE_WEB_SETTINGS, + G_PARAM_READWRITE)); + + /** + * MidoriBrowser::statusbar-text + * + * The text that is displayed in the statusbar. + * + * This value reflects changes to the text visible in the statusbar, such + * as the uri of a hyperlink the mouse hovers over or the description of + * a menuitem. + * + * Setting this value changes the displayed text until the next change. + */ + g_object_class_install_property (gobject_class, + PROP_STATUSBAR_TEXT, + g_param_spec_string ( + "statusbar-text", + "Statusbar Text", + "The text that is displayed in the statusbar", + "", + flags)); + + /** + * MidoriBrowser::trash + * + * The trash, that collects all closed tabs and windows. + * + * This is actually a reference to a trash instance, so if a trash should + * be used it must be initially set. + * + * Note: In the future the trash might collect other types of items. + */ + g_object_class_install_property (gobject_class, + PROP_TRASH, + g_param_spec_object ( + "trash", + "Trash", + "The trash, collecting recently closed tabs and windows", + MIDORI_TYPE_TRASH, + G_PARAM_READWRITE)); + + g_type_class_add_private (class, sizeof (MidoriBrowserPrivate)); +} + +static void +_action_window_new_activate (GtkAction* action, + MidoriBrowser* browser) +{ + g_signal_emit (browser, signals[NEW_WINDOW], 0, "about:blank"); +} + +static void +_action_tab_new_activate (GtkAction* action, + MidoriBrowser* browser) +{ + midori_browser_append_uri (browser, "about:blank"); +} + +static void +_action_open_activate (GtkAction* action, + MidoriBrowser* browser) +{ + GtkWidget* dialog = gtk_file_chooser_dialog_new ( + "Open file", GTK_WINDOW (browser), + GTK_FILE_CHOOSER_ACTION_OPEN, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, + NULL); + gtk_window_set_icon_name (GTK_WINDOW (dialog), GTK_STOCK_OPEN); + if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) + { + gchar* uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (dialog)); + GtkWidget* web_view = midori_browser_get_current_web_view (browser); + g_object_set (web_view, "uri", uri, NULL); + g_free (uri); + } + gtk_widget_destroy (dialog); +} + +static void +_action_tab_close_activate (GtkAction* action, + MidoriBrowser* browser) +{ + GtkWidget* web_view = midori_browser_get_current_web_view (browser); + gtk_widget_destroy (web_view); +} + +static void +_action_window_close_activate (GtkAction* action, + MidoriBrowser* browser) +{ + gtk_widget_destroy (GTK_WIDGET (browser)); +} + +static void +_action_quit_activate (GtkAction* action, + MidoriBrowser* browser) +{ + gtk_main_quit (); +} + +static void +_action_edit_activate(GtkAction* action, + MidoriBrowser* browser) +{ + GtkWidget* widget = gtk_window_get_focus (GTK_WINDOW (browser)); + gboolean can_cut = FALSE, can_copy = FALSE, can_paste = FALSE; + gboolean has_selection; + + if (WEBKIT_IS_WEB_VIEW (widget)) + { + WebKitWebView* web_view = WEBKIT_WEB_VIEW (widget); + can_cut = webkit_web_view_can_cut_clipboard (web_view); + can_copy = webkit_web_view_can_copy_clipboard (web_view); + can_paste = webkit_web_view_can_paste_clipboard (web_view); + } + else if (GTK_IS_EDITABLE (widget)) + { + GtkEditable* editable = GTK_EDITABLE (widget); + has_selection = gtk_editable_get_selection_bounds (editable, NULL, NULL); + can_cut = has_selection && gtk_editable_get_editable (editable); + can_copy = has_selection; + can_paste = gtk_editable_get_editable (editable); + } + + _action_set_sensitive (browser, "Cut", can_cut); + _action_set_sensitive (browser, "Copy", can_copy); + _action_set_sensitive (browser, "Paste", can_paste); + _action_set_sensitive (browser, "Delete", can_cut); + _action_set_sensitive (browser, "SelectAll", FALSE); +} + +static void +_action_cut_activate(GtkAction* action, + MidoriBrowser* browser) +{ + GtkWidget* widget = gtk_window_get_focus (GTK_WINDOW (browser)); + if (G_LIKELY (widget)) + g_signal_emit_by_name (widget, "cut-clipboard"); +} + +static void +_action_copy_activate(GtkAction* action, + MidoriBrowser* browser) +{ + GtkWidget* widget = gtk_window_get_focus (GTK_WINDOW (browser)); + if (G_LIKELY (widget)) + g_signal_emit_by_name (widget, "copy-clipboard"); +} + +static void +_action_paste_activate(GtkAction* action, + MidoriBrowser* browser) +{ + GtkWidget* widget = gtk_window_get_focus (GTK_WINDOW (browser)); + if (G_LIKELY (widget)) + g_signal_emit_by_name (widget, "paste-clipboard"); +} + +static void +_action_delete_activate(GtkAction* action, + MidoriBrowser* browser) +{ + GtkWidget* widget = gtk_window_get_focus (GTK_WINDOW (browser)); + if (G_LIKELY (widget)) + { + if (WEBKIT_IS_WEB_VIEW (widget)) + webkit_web_view_delete_selection (WEBKIT_WEB_VIEW (widget)); + else if (GTK_IS_EDITABLE(widget)) + gtk_editable_delete_selection (GTK_EDITABLE (widget)); + } +} + +static void +_action_select_all_activate(GtkAction* action, + MidoriBrowser* browser) +{ + GtkWidget* widget = gtk_window_get_focus (GTK_WINDOW (browser)); + if (G_LIKELY (widget)) + { + if (GTK_IS_ENTRY (widget)) + gtk_editable_select_region (GTK_EDITABLE (widget), 0, -1); + else + g_signal_emit_by_name (widget, "select-all"); + } +} + +static void +_action_find_activate(GtkAction* action, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + if (GTK_WIDGET_VISIBLE (priv->find)) + { + GtkWidget* web_view = midori_browser_get_current_web_view (browser); + webkit_web_view_unmark_text_matches (WEBKIT_WEB_VIEW (web_view)); + gtk_toggle_tool_button_set_active ( + GTK_TOGGLE_TOOL_BUTTON (priv->find_highlight), FALSE); + gtk_widget_hide (priv->find); + } + else + { + GtkWidget* icon = gtk_image_new_from_stock (GTK_STOCK_FIND, + GTK_ICON_SIZE_MENU); + sexy_icon_entry_set_icon (SEXY_ICON_ENTRY (priv->find_text), + SEXY_ICON_ENTRY_PRIMARY, GTK_IMAGE (icon)); + gtk_entry_set_text (GTK_ENTRY (priv->find_text), ""); + gtk_widget_show (priv->find); + gtk_widget_grab_focus (GTK_WIDGET (priv->find_text)); + } +} + +static void +_midori_browser_find (MidoriBrowser* browser, + gboolean forward) +{ + MidoriBrowserPrivate* priv = browser->priv; + + const gchar* text = gtk_entry_get_text (GTK_ENTRY (priv->find_text)); + const gboolean case_sensitive = gtk_toggle_tool_button_get_active ( + GTK_TOGGLE_TOOL_BUTTON(priv->find_case)); + GtkWidget* web_view = midori_browser_get_current_web_view (browser); + if (GTK_WIDGET_VISIBLE (priv->find)) + webkit_web_view_unmark_text_matches (WEBKIT_WEB_VIEW (web_view)); + gboolean found = webkit_web_view_search_text (WEBKIT_WEB_VIEW (web_view), + text, case_sensitive, forward, TRUE); + if (GTK_WIDGET_VISIBLE (priv->find)) + { + GtkWidget* icon; + if (found) + icon = gtk_image_new_from_stock (GTK_STOCK_FIND, GTK_ICON_SIZE_MENU); + else + icon = gtk_image_new_from_stock (GTK_STOCK_STOP, GTK_ICON_SIZE_MENU); + sexy_icon_entry_set_icon (SEXY_ICON_ENTRY (priv->find_text), + SEXY_ICON_ENTRY_PRIMARY, GTK_IMAGE(icon)); + webkit_web_view_mark_text_matches (WEBKIT_WEB_VIEW (web_view), text, + case_sensitive, 0); + const gboolean highlight = gtk_toggle_tool_button_get_active ( + GTK_TOGGLE_TOOL_BUTTON (priv->find_highlight)); + webkit_web_view_set_highlight_text_matches (WEBKIT_WEB_VIEW (web_view), + highlight); + } +} + +static void +_action_find_next_activate (GtkAction* action, + MidoriBrowser* browser) +{ + _midori_browser_find (browser, TRUE); +} + +static void +_action_find_previous_activate (GtkAction* action, + MidoriBrowser* browser) +{ + _midori_browser_find (browser, FALSE); +} + +static void +_find_highlight_toggled (GtkToggleToolButton* toolitem, + MidoriBrowser* browser) +{ + GtkWidget* web_view = midori_browser_get_current_web_view (browser); + const gboolean highlight = gtk_toggle_tool_button_get_active (toolitem); + webkit_web_view_set_highlight_text_matches (WEBKIT_WEB_VIEW (web_view), + highlight); +} + +static void +midori_browser_find_button_close_clicked_cb (GtkWidget* widget, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + gtk_widget_hide (priv->find); +} + +static void +midori_browser_navigationbar_notify_style_cb (GObject* object, + GParamSpec* arg1, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + if (config->toolbarStyle == CONFIG_TOOLBAR_DEFAULT) + { + gtk_toolbar_set_style (GTK_TOOLBAR(priv->navigationbar), + config_to_toolbarstyle (config->toolbarStyle)); + } +} + +static void +midori_browser_menu_trash_item_activate_cb (GtkWidget* menuitem, + MidoriBrowser* browser) +{ + // Create a new web view with an uri which has been closed before + KatzeXbelItem* item = g_object_get_data (G_OBJECT (menuitem), + "KatzeXbelItem"); + const gchar* uri = katze_xbel_bookmark_get_href (item); + midori_browser_append_uri (browser, uri); + katze_xbel_item_unref (item); +} + +static void +midori_browser_menu_trash_activate_cb (GtkWidget* widget, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + GtkWidget* menu = gtk_menu_new (); + guint n = midori_trash_get_n_items (priv->trash); + GtkWidget* menuitem; + guint i; + for (i = 0; i < n; i++) + { + KatzeXbelItem* item = midori_trash_get_nth_xbel_item (priv->trash, i); + const gchar* title = katze_xbel_item_get_title (item); + const gchar* uri = katze_xbel_bookmark_get_href (item); + menuitem = gtk_image_menu_item_new_with_label (title ? title : uri); + // FIXME: Get the real icon + GtkWidget* icon = gtk_image_new_from_stock (GTK_STOCK_FILE, + GTK_ICON_SIZE_MENU); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), icon); + gtk_menu_shell_append(GTK_MENU_SHELL (menu), menuitem); + g_object_set_data (G_OBJECT (menuitem), "KatzeXbelItem", item); + g_signal_connect (menuitem, "activate", + G_CALLBACK (midori_browser_menu_trash_item_activate_cb), browser); + gtk_widget_show (menuitem); + } + + menuitem = gtk_separator_menu_item_new (); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); + gtk_widget_show (menuitem); + GtkAction* action = gtk_action_group_get_action (priv->action_group, + "TrashEmpty"); + menuitem = gtk_action_create_menu_item (action); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); + gtk_widget_show (menuitem); + sokoke_widget_popup (widget, GTK_MENU (menu), NULL); +} + +static void +_action_preferences_activate (GtkAction* action, + MidoriBrowser* browser) +{ + // Show the preferences dialog. Create it if necessary. + static GtkWidget* dialog = NULL; + if (GTK_IS_DIALOG (dialog)) + gtk_window_present (GTK_WINDOW (dialog)); + else + { + dialog = prefs_preferences_dialog_new (browser); + gtk_widget_show (dialog); + } +} + +static void +_action_navigationbar_activate (GtkToggleAction* action, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + config->toolbarNavigation = gtk_toggle_action_get_active (action); + sokoke_widget_set_visible (priv->navigationbar, config->toolbarNavigation); +} + +static void +_action_bookmarkbar_activate (GtkToggleAction* action, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + config->toolbarBookmarks = gtk_toggle_action_get_active (action); + sokoke_widget_set_visible (priv->bookmarkbar, config->toolbarBookmarks); +} + +static void +_action_statusbar_activate (GtkToggleAction* action, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + config->toolbarStatus = gtk_toggle_action_get_active (action); + sokoke_widget_set_visible (priv->statusbar, config->toolbarStatus); +} + +static void +_action_reload_stop_activate (GtkAction* action, + MidoriBrowser* browser) +{ + gchar* stock_id; + g_object_get (action, "stock-id", &stock_id, NULL); + GtkWidget* web_view = midori_browser_get_current_web_view (browser); + // Refresh or stop, depending on the stock id + if (!strcmp (stock_id, GTK_STOCK_REFRESH)) + { + /*GdkModifierType state = (GdkModifierType)0; + gint x, y; + gdk_window_get_pointer (NULL, &x, &y, &state); + gboolean from_cache = state & GDK_SHIFT_MASK;*/ + webkit_web_view_reload (WEBKIT_WEB_VIEW (web_view)); + } + else + webkit_web_view_stop_loading (WEBKIT_WEB_VIEW (web_view)); + g_free (stock_id); +} + +/*static void +_action_zoom_in_activate (GtkAction* action, + MidoriBrowser* browser) +{ + GtkWidget* web_view = midori_browser_get_current_web_view (browser); + const gfloat zoom = webkit_web_view_get_text_multiplier ( + WEBKIT_WEB_VIEW (web_view)); + webkit_web_view_set_text_multiplier (WEBKIT_WEB_VIEW (web_view), zoom + 0.1); +}*/ + +/*static void +_action_zoom_out_activate (GtkAction* action, + MidoriBrowser* browser) +{ + GtkWidget* web_view = midori_browser_get_current_web_view (browser); + const gfloat zoom = webkit_web_view_get_text_multiplier ( + WEBKIT_WEB_VIEW (web_view)); + webkit_web_view_set_text_multiplier (WEBKIT_WEB_VIEW (web_view), zoom - 0.1); +}*/ + +/*static void +_action_zoom_normal_activate (GtkAction* action, + MidoriBrowser* browser) +{ + GtkWidget* web_view = midori_browser_get_current_web_view (browser); + webkit_web_view_set_text_multiplier (WEBKIT_WEB_VIEW (web_View, 1)); +}*/ + +/*static void +_action_source_view_activate (GtkAction* action, + MidoriBrowser* browser) +{ + GtkWidget* web_view = midori_browser_get_current_web_view (browser); + gchar* source = webkit_web_view_copy_source (WEBKIT_WEB_VIEW (web_view)); + webkit_web_view_load_html_string (WEBKIT_WEB_VIEW (web_view), source, ""); + g_free (source); +}*/ + +static void +_action_fullscreen_activate (GtkAction* action, + MidoriBrowser* browser) +{ + GdkWindowState state = gdk_window_get_state (GTK_WIDGET (browser)->window); + if (state & GDK_WINDOW_STATE_FULLSCREEN) + gtk_window_unfullscreen (GTK_WINDOW (browser)); + else + gtk_window_fullscreen (GTK_WINDOW (browser)); +} + +static void +_action_back_activate (GtkAction* action, + MidoriBrowser* browser) +{ + GtkWidget* web_view = midori_browser_get_current_web_view (browser); + webkit_web_view_go_back (WEBKIT_WEB_VIEW (web_view)); +} + +static void +_action_forward_activate (GtkAction* action, + MidoriBrowser* browser) +{ + GtkWidget* web_view = midori_browser_get_current_web_view (browser); + webkit_web_view_go_forward (WEBKIT_WEB_VIEW (web_view)); +} + +static void +_action_home_activate (GtkAction* action, + MidoriBrowser* browser) +{ + GtkWidget* web_view = midori_browser_get_current_web_view (browser); + g_object_set (web_view, "uri", config->homepage, NULL); +} + +static gboolean +midori_browser_location_key_press_event_cb (GtkWidget* widget, + GdkEventKey* event, + MidoriBrowser* browser) +{ + switch (event->keyval) + { + case GDK_Return: + { + const gchar* uri = gtk_entry_get_text (GTK_ENTRY (widget)); + if (uri) + { + gchar* new_uri = magic_uri (uri, TRUE); + // TODO: Use new_uri intermediately when completion is better + /* TODO Completion should be generated from history, that is + the uri as well as the title. */ + entry_completion_append (GTK_ENTRY (widget), uri); + GtkWidget* web_view = midori_browser_get_current_web_view (browser); + g_object_set (web_view, "uri", new_uri, NULL); + g_free (new_uri); + } + return TRUE; + } + case GDK_Escape: + { + GtkWidget* web_view = midori_browser_get_current_web_view (browser); + const gchar* uri = midori_web_view_get_display_uri ( + MIDORI_WEB_VIEW (web_view)); + gtk_entry_set_text (GTK_ENTRY (widget), uri); + return TRUE; + } + } + return FALSE; +} + +static void +_action_location_activate (GtkAction* action, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + if (GTK_WIDGET_VISIBLE (priv->navigationbar)) + gtk_widget_grab_focus (priv->location); + else + { + // TODO: We should offer all of the location's features here + GtkWidget* dialog; + dialog = gtk_dialog_new_with_buttons ("Open location" + , GTK_WINDOW (browser) + , GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR + , GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL + , GTK_STOCK_JUMP_TO, GTK_RESPONSE_ACCEPT + , NULL); + gtk_window_set_icon_name (GTK_WINDOW (dialog), GTK_STOCK_JUMP_TO); + gtk_container_set_border_width (GTK_CONTAINER (dialog), 5); + gtk_container_set_border_width ( + GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), 5); + GtkWidget* hbox = gtk_hbox_new (FALSE, 8); + gtk_container_set_border_width (GTK_CONTAINER (hbox), 5); + GtkWidget* label = gtk_label_new_with_mnemonic ("_Location:"); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); + GtkWidget* entry = gtk_entry_new (); + gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE); + gtk_box_pack_start (GTK_BOX (hbox), entry, FALSE, FALSE, 0); + gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), hbox); + gtk_widget_show_all( hbox); + gtk_dialog_set_default_response (GTK_DIALOG (dialog), + GTK_RESPONSE_ACCEPT); + if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) + { + gtk_entry_set_text (GTK_ENTRY (priv->location) + , gtk_entry_get_text (GTK_ENTRY (entry))); + GdkEventKey event; + event.keyval = GDK_Return; + midori_browser_location_key_press_event_cb (priv->location, + &event, browser); + } + gtk_widget_destroy (dialog); + } +} + +static void +_action_search_activate (GtkAction* action, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + if (GTK_WIDGET_VISIBLE (priv->search) + && GTK_WIDGET_VISIBLE (priv->navigationbar)) + gtk_widget_grab_focus (priv->search); + else + { + // TODO: We should offer all of the search's features here + GtkWidget* dialog = gtk_dialog_new_with_buttons ("Web search" + , GTK_WINDOW (browser) + , GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR + , GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL + , GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT + , NULL); + gtk_window_set_icon_name (GTK_WINDOW (dialog), GTK_STOCK_FIND); + gtk_container_set_border_width(GTK_CONTAINER (dialog), 5); + gtk_container_set_border_width ( + GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), 5); + GtkWidget* hbox = gtk_hbox_new (FALSE, 8); + gtk_container_set_border_width (GTK_CONTAINER (hbox), 5); + GtkWidget* label = gtk_label_new_with_mnemonic ("_Location:"); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); + GtkWidget* entry = gtk_entry_new (); + gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE); + gtk_box_pack_start (GTK_BOX (hbox), entry, FALSE, FALSE, 0); + gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), hbox); + gtk_widget_show_all (hbox); + gtk_dialog_set_default_response (GTK_DIALOG (dialog), + GTK_RESPONSE_ACCEPT); + if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) + { + gtk_entry_set_text (GTK_ENTRY (priv->search) + , gtk_entry_get_text (GTK_ENTRY (entry))); + on_webSearch_activate (priv->search, browser); + } + gtk_widget_destroy (dialog); + } +} + +static void +midori_browser_edit_bookmark_dialog_new (MidoriBrowser* browser, + KatzeXbelItem* bookmark) +{ + MidoriBrowserPrivate* priv = browser->priv; + + gboolean new_bookmark = !bookmark; + GtkWidget* dialog = gtk_dialog_new_with_buttons ( + new_bookmark ? "New bookmark" : "Edit bookmark", + GTK_WINDOW (browser), + GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + new_bookmark ? GTK_STOCK_ADD : GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, + NULL); + gtk_window_set_icon_name (GTK_WINDOW (dialog), + new_bookmark ? GTK_STOCK_ADD : GTK_STOCK_REMOVE); + gtk_container_set_border_width (GTK_CONTAINER (dialog), 5); + gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), 5); + GtkSizeGroup* sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); + + if (new_bookmark) + bookmark = katze_xbel_bookmark_new (); + + GtkWidget* hbox = gtk_hbox_new (FALSE, 8); + gtk_container_set_border_width (GTK_CONTAINER (hbox), 5); + GtkWidget* label = gtk_label_new_with_mnemonic ("_Title:"); + gtk_size_group_add_widget (sizegroup, label); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); + GtkWidget* entry_title = gtk_entry_new (); + gtk_entry_set_activates_default (GTK_ENTRY (entry_title), TRUE); + if (!new_bookmark) + { + const gchar* title = katze_xbel_item_get_title (bookmark); + gtk_entry_set_text (GTK_ENTRY (entry_title), title ? title : ""); + } + gtk_box_pack_start (GTK_BOX (hbox), entry_title, TRUE, TRUE, 0); + gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), hbox); + gtk_widget_show_all (hbox); + + hbox = gtk_hbox_new (FALSE, 8); + gtk_container_set_border_width (GTK_CONTAINER (hbox), 5); + label = gtk_label_new_with_mnemonic ("_Description:"); + gtk_size_group_add_widget (sizegroup, label); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); + GtkWidget* entry_desc = gtk_entry_new (); + gtk_entry_set_activates_default (GTK_ENTRY (entry_desc), TRUE); + if (!new_bookmark) + { + const gchar* desc = katze_xbel_item_get_desc (bookmark); + gtk_entry_set_text (GTK_ENTRY (entry_desc), desc ? desc : ""); + } + gtk_box_pack_start (GTK_BOX (hbox), entry_desc, TRUE, TRUE, 0); + gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), hbox); + gtk_widget_show_all (hbox); + + GtkWidget* entry_uri = NULL; + if (katze_xbel_item_is_bookmark (bookmark)) + { + hbox = gtk_hbox_new (FALSE, 8); + gtk_container_set_border_width (GTK_CONTAINER (hbox), 5); + label = gtk_label_new_with_mnemonic ("_Uri:"); + gtk_size_group_add_widget (sizegroup, label); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); + entry_uri = gtk_entry_new (); + gtk_entry_set_activates_default (GTK_ENTRY (entry_uri), TRUE); + if (!new_bookmark) + gtk_entry_set_text (GTK_ENTRY (entry_uri), + katze_xbel_bookmark_get_href (bookmark)); + gtk_box_pack_start (GTK_BOX(hbox), entry_uri, TRUE, TRUE, 0); + gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), hbox); + gtk_widget_show_all (hbox); + } + + GtkWidget* combo_folder = NULL; + if (new_bookmark) + { + hbox = gtk_hbox_new (FALSE, 8); + gtk_container_set_border_width (GTK_CONTAINER (hbox), 5); + label = gtk_label_new_with_mnemonic ("_Folder:"); + gtk_size_group_add_widget (sizegroup, label); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); + combo_folder = gtk_combo_box_new_text (); + gtk_combo_box_append_text (GTK_COMBO_BOX (combo_folder), "Root"); + gtk_widget_set_sensitive (combo_folder, FALSE); + gtk_box_pack_start (GTK_BOX (hbox), combo_folder, TRUE, TRUE, 0); + gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), hbox); + gtk_widget_show_all (hbox); + } + + gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT); + if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) + { + katze_xbel_item_set_title (bookmark, + gtk_entry_get_text (GTK_ENTRY (entry_title))); + katze_xbel_item_set_desc (bookmark, + gtk_entry_get_text(GTK_ENTRY(entry_desc))); + if (katze_xbel_item_is_bookmark (bookmark)) + katze_xbel_bookmark_set_href (bookmark, + gtk_entry_get_text (GTK_ENTRY (entry_uri))); + + // FIXME: We want to choose a folder + if (new_bookmark) + { + katze_xbel_folder_append_item (bookmarks, bookmark); + GtkTreeView* treeview = GTK_TREE_VIEW (priv->panel_bookmarks); + GtkTreeModel* treemodel = gtk_tree_view_get_model (treeview); + GtkTreeIter iter; + gtk_tree_store_insert_with_values (GTK_TREE_STORE (treemodel), + &iter, NULL, G_MAXINT, 0, bookmark, -1); + katze_xbel_item_ref (bookmark); + } + + // FIXME: update navigationbar + // FIXME: Update panel in other windows + } + gtk_widget_destroy (dialog); +} + +static void +midori_panel_bookmarks_row_activated_cb (GtkTreeView* treeview, + GtkTreePath* path, + GtkTreeViewColumn* column, + MidoriBrowser* browser) +{ + GtkTreeModel* model = gtk_tree_view_get_model (treeview); + GtkTreeIter iter; + if (gtk_tree_model_get_iter (model, &iter, path)) + { + KatzeXbelItem* item; + gtk_tree_model_get (model, &iter, 0, &item, -1); + if (katze_xbel_item_is_bookmark (item)) + { + GtkWidget* web_view = midori_browser_get_current_web_view (browser); + const gchar* uri = katze_xbel_bookmark_get_href (item); + g_object_set (web_view, "uri", uri, NULL); + } + } +} + +static void +midori_panel_bookmarks_cursor_or_row_changed_cb (GtkTreeView* treeview, + MidoriBrowser* browser) +{ + GtkTreeSelection* selection = gtk_tree_view_get_selection (treeview); + if (selection) + { + GtkTreeModel* model; + GtkTreeIter iter; + if (gtk_tree_selection_get_selected (selection, &model, &iter)) + { + KatzeXbelItem* item; + gtk_tree_model_get (model, &iter, 0, &item, -1); + + gboolean is_separator = katze_xbel_item_is_separator (item); + _action_set_sensitive (browser, "BookmarkEdit", !is_separator); + _action_set_sensitive (browser, "BookmarkDelete", TRUE); + } + else + { + _action_set_sensitive (browser, "BookmarkEdit", FALSE); + _action_set_sensitive (browser, "BookmarkDelete", FALSE); + } + } +} + +static void +_midori_panel_bookmarks_popup (GtkWidget* widget, + GdkEventButton* event, + KatzeXbelItem* item, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + gboolean is_bookmark = katze_xbel_item_is_bookmark (item); + + _action_set_sensitive (browser, "BookmarkOpen", is_bookmark); + _action_set_sensitive (browser, "BookmarkOpenTab", is_bookmark); + _action_set_sensitive (browser, "BookmarkOpenWindow", is_bookmark); + + sokoke_widget_popup (widget, GTK_MENU (priv->popup_bookmark), event); +} + +static gboolean +midori_panel_bookmarks_button_release_event_cb (GtkWidget* widget, + GdkEventButton* event, + MidoriBrowser* browser) +{ + if (event->button != 2 && event->button != 3) + return FALSE; + + GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget)); + if (selection) + { + GtkTreeModel* model; + GtkTreeIter iter; + if (gtk_tree_selection_get_selected(selection, &model, &iter)) + { + KatzeXbelItem* item; + gtk_tree_model_get(model, &iter, 0, &item, -1); + if (event->button == 2 && katze_xbel_item_is_bookmark(item)) + { + const gchar* uri = katze_xbel_bookmark_get_href(item); + midori_browser_append_uri (browser, uri); + } + else + _midori_panel_bookmarks_popup(widget, event, item, browser); + return TRUE; + } + } + return FALSE; +} + +static void +midori_panel_bookmarks_popup_menu_cb (GtkWidget* widget, + MidoriBrowser* browser) +{ + GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget)); + if (selection) + { + GtkTreeModel* model; + GtkTreeIter iter; + if (gtk_tree_selection_get_selected(selection, &model, &iter)) + { + KatzeXbelItem* item; + gtk_tree_model_get(model, &iter, 0, &item, -1); + _midori_panel_bookmarks_popup(widget, NULL, item, browser); + } + } +} + +static void +_tree_store_insert_folder (GtkTreeStore* treestore, + GtkTreeIter* parent, + KatzeXbelItem* folder) +{ + guint n = katze_xbel_folder_get_n_items (folder); + guint i; + for (i = 0; i < n; i++) + { + KatzeXbelItem* item = katze_xbel_folder_get_nth_item (folder, i); + GtkTreeIter iter; + gtk_tree_store_insert_with_values (treestore, &iter, parent, n, + 0, item, -1); + katze_xbel_item_ref (item); + if (katze_xbel_item_is_folder (item)) + _tree_store_insert_folder (treestore, &iter, item); + } +} + +static void +midori_browser_bookmarks_item_render_icon_cb (GtkTreeViewColumn* column, + GtkCellRenderer* renderer, + GtkTreeModel* model, + GtkTreeIter* iter, + GtkWidget* treeview) +{ + KatzeXbelItem* item; + gtk_tree_model_get (model, iter, 0, &item, -1); + + if (G_UNLIKELY (!item)) + return; + if (G_UNLIKELY (!katze_xbel_item_get_parent (item))) + { + gtk_tree_store_remove (GTK_TREE_STORE (model), iter); + katze_xbel_item_unref (item); + return; + } + + // TODO: Would it be better to not do this on every redraw? + GdkPixbuf* pixbuf = NULL; + if (katze_xbel_item_is_bookmark (item)) + pixbuf = gtk_widget_render_icon (treeview, STOCK_BOOKMARK, + GTK_ICON_SIZE_MENU, NULL); + else if (katze_xbel_item_is_folder (item)) + pixbuf = gtk_widget_render_icon (treeview, GTK_STOCK_DIRECTORY, + GTK_ICON_SIZE_MENU, NULL); + g_object_set (renderer, "pixbuf", pixbuf, NULL); + if (pixbuf) + g_object_unref (pixbuf); +} + +static void +midori_browser_bookmarks_item_render_text_cb (GtkTreeViewColumn* column, + GtkCellRenderer* renderer, + GtkTreeModel* model, + GtkTreeIter* iter, + GtkWidget* treeview) +{ + KatzeXbelItem* item; + gtk_tree_model_get (model, iter, 0, &item, -1); + + if (G_UNLIKELY (!item)) + return; + if (G_UNLIKELY (!katze_xbel_item_get_parent (item))) + { + gtk_tree_store_remove (GTK_TREE_STORE (model), iter); + katze_xbel_item_unref (item); + return; + } + + if (katze_xbel_item_is_separator (item)) + g_object_set (renderer, "markup", "Separator", NULL); + else + g_object_set (renderer, "markup", NULL, + "text", katze_xbel_item_get_title(item), NULL); +} + +static void +_midori_browser_create_bookmark_menu (MidoriBrowser* browser, + KatzeXbelItem* folder, + GtkWidget* menu); + +static void +midori_browser_bookmark_menu_folder_activate_cb (GtkWidget* menuitem, + MidoriBrowser* browser) +{ + GtkWidget* menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (menuitem)); + gtk_container_foreach(GTK_CONTAINER (menu), (GtkCallback) gtk_widget_destroy, NULL);//... + KatzeXbelItem* folder = (KatzeXbelItem*)g_object_get_data(G_OBJECT (menuitem), "KatzeXbelItem"); + _midori_browser_create_bookmark_menu (browser, folder, menu); + // Remove all menuitems when the menu is hidden. + // FIXME: We really *want* the line below, but it won't work like that + //g_signal_connect_after (menu, "hide", G_CALLBACK (gtk_container_foreach), gtk_widget_destroy); + gtk_widget_show (menuitem); +} + +static void +midori_browser_bookmarkbar_folder_activate_cb (GtkToolItem* toolitem, + MidoriBrowser* browser) +{ + GtkWidget* menu = gtk_menu_new(); + KatzeXbelItem* folder = (KatzeXbelItem*)g_object_get_data ( + G_OBJECT (toolitem), "KatzeXbelItem"); + _midori_browser_create_bookmark_menu (browser, folder, menu); + // Remove all menuitems when the menu is hidden. + // FIXME: We really *should* run the line below, but it won't work like that + /*g_signal_connect (menu, "hide", G_CALLBACK (gtk_container_foreach), + gtk_widget_destroy);*/ + sokoke_widget_popup (GTK_WIDGET (toolitem), GTK_MENU (menu), NULL); +} + +static void +midori_browser_menu_bookmarks_item_activate_cb (GtkWidget* widget, + MidoriBrowser* browser) +{ + KatzeXbelItem* item = (KatzeXbelItem*)g_object_get_data(G_OBJECT(widget), "KatzeXbelItem"); + GtkWidget* web_view = midori_browser_get_current_web_view (browser); + g_object_set (web_view, "uri", katze_xbel_bookmark_get_href (item), NULL); +} + +static void +_midori_browser_create_bookmark_menu (MidoriBrowser* browser, + KatzeXbelItem* folder, + GtkWidget* menu) +{ + guint n = katze_xbel_folder_get_n_items (folder); + guint i; + for (i = 0; i < n; i++) + { + KatzeXbelItem* item = katze_xbel_folder_get_nth_item (folder, i); + const gchar* title = katze_xbel_item_is_separator (item) + ? "" : katze_xbel_item_get_title (item); + /* const gchar* desc = katze_xbel_item_is_separator (item) + ? "" : katze_xbel_item_get_desc (item); */ + GtkWidget* menuitem = NULL; + switch (katze_xbel_item_get_kind (item)) + { + case KATZE_XBEL_ITEM_KIND_FOLDER: + // FIXME: what about katze_xbel_folder_is_folded? + menuitem = gtk_image_menu_item_new_with_label (title); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), + gtk_image_new_from_stock (GTK_STOCK_DIRECTORY, + GTK_ICON_SIZE_MENU)); + GtkWidget* _menu = gtk_menu_new (); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), _menu); + g_signal_connect (menuitem, "activate", + G_CALLBACK (midori_browser_bookmark_menu_folder_activate_cb), + browser); + g_object_set_data (G_OBJECT (menuitem), "KatzeXbelItem", item); + break; + case KATZE_XBEL_ITEM_KIND_BOOKMARK: + menuitem = gtk_image_menu_item_new_with_label (title); + GtkWidget* image = gtk_image_new_from_stock (STOCK_BOOKMARK, + GTK_ICON_SIZE_MENU); + gtk_widget_show (image); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), + image); + g_signal_connect (menuitem, "activate", + G_CALLBACK (midori_browser_menu_bookmarks_item_activate_cb), + browser); + g_object_set_data (G_OBJECT (menuitem), "KatzeXbelItem", item); + break; + case KATZE_XBEL_ITEM_KIND_SEPARATOR: + menuitem = gtk_separator_menu_item_new (); + break; + default: + g_warning ("Unknown xbel item kind"); + } + gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); + gtk_widget_show (menuitem); + } +} + +static void +_action_bookmark_new_activate (GtkAction* action, + MidoriBrowser* browser) +{ + midori_browser_edit_bookmark_dialog_new (browser, NULL); +} + +static void +_action_manage_search_engines_activate (GtkAction* action, + MidoriBrowser* browser) +{ + // Show the Manage search engines dialog. Create it if necessary. + static GtkWidget* dialog; + if (GTK_IS_DIALOG (dialog)) + gtk_window_present (GTK_WINDOW (dialog)); + else + { + dialog = webSearch_manageSearchEngines_dialog_new (browser); + gtk_widget_show (dialog); + } +} + +static void +_action_tab_previous_activate (GtkAction* action, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + gint n = gtk_notebook_get_current_page (GTK_NOTEBOOK (priv->notebook)); + gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), n - 1); +} + +static void +_action_tab_next_activate (GtkAction* action, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + // Advance one tab or jump to the first one if we are at the last one + gint n = gtk_notebook_get_current_page (GTK_NOTEBOOK (priv->notebook)); + if (n == gtk_notebook_get_n_pages (GTK_NOTEBOOK (priv->notebook)) - 1) + n = -1; + gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), n + 1); +} + +static void +midori_browser_window_menu_item_activate_cb (GtkWidget* widget, + GtkWidget* web_view) +{ + MidoriBrowser* browser = MIDORI_BROWSER (gtk_widget_get_toplevel (web_view)); + if (!browser) + { + g_warning ("Orphaned web view"); + return; + } + + MidoriBrowserPrivate* priv = browser->priv; + + GtkWidget* scrolled = _midori_browser_scrolled_for_child (browser, web_view); + guint n = gtk_notebook_page_num (GTK_NOTEBOOK (priv->notebook), scrolled); + gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), n); +} + +static const gchar* credits_authors[] = { + "Christian Dywan ", NULL }; +static const gchar* credits_documenters/*[]*/ = /*{ + */NULL/* }*/; +static const gchar* credits_artists[] = { + "Nancy Runge ", NULL }; + +static const gchar* license = + "This library is free software; you can redistribute it and/or\n" + "modify it under the terms of the GNU Lesser General Public\n" + "License as published by the Free Software Foundation; either\n" + "version 2.1 of the License, or (at your option) any later version.\n"; + +static void +_action_about_activate (GtkAction* action, + MidoriBrowser* browser) +{ + gtk_show_about_dialog (GTK_WINDOW (browser), + "logo-icon-name", gtk_window_get_icon_name (GTK_WINDOW (browser)), + "name", PACKAGE_NAME, + "version", PACKAGE_VERSION, + "comments", "A lightweight web browser.", + "copyright", "Copyright © 2007-2008 Christian Dywan", + "website", "http://software.twotoasts.de", + "authors", credits_authors, + "documenters", credits_documenters, + "artists", credits_artists, + "license", license, + "wrap-license", TRUE, + // "translator-credits", _("translator-credits"), + NULL); +} + +static void +midori_browser_location_changed_cb (GtkWidget* widget, + MidoriBrowser* browser) +{ + // Preserve changes to the uri + /*const gchar* newUri = gtk_entry_get_text(GTK_ENTRY(widget)); + katze_xbel_bookmark_set_href(browser->sessionItem, newUri);*/ + // FIXME: If we want this feature, this is the wrong approach +} + +static void +_action_panel_activate (GtkToggleAction* action, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + config->panelShow = gtk_toggle_action_get_active (action); + sokoke_widget_set_visible (priv->panel, config->panelShow); +} + +static void +_action_open_in_panel_activate (GtkAction* action, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + GtkWidget* web_view = midori_browser_get_current_web_view (browser); + const gchar* uri = midori_web_view_get_display_uri (MIDORI_WEB_VIEW (web_view)); + katze_assign (config->panelPageholder, g_strdup (uri)); + gint n = midori_panel_page_num (MIDORI_PANEL (priv->panel), + priv->panel_pageholder); + midori_panel_set_current_page (MIDORI_PANEL (priv->panel), n); + gtk_widget_show (priv->panel); + g_object_set (priv->panel_pageholder, "uri", config->panelPageholder, NULL); +} + + +static void +midori_panel_notify_position_cb (GObject* object, + GParamSpec* arg1, + MidoriBrowser* browser) +{ + config->winPanelPos = gtk_paned_get_position (GTK_PANED (object)); +} + +static gboolean +midori_panel_close_cb (MidoriPanel* panel, + MidoriBrowser* browser) +{ + config->panelShow = FALSE; + return FALSE; +} + +static void +gtk_notebook_switch_page_cb (GtkWidget* widget, + GtkNotebookPage* page, + guint page_num, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + GtkWidget* web_view = midori_browser_get_current_web_view (browser); + const gchar* uri = midori_web_view_get_display_uri (MIDORI_WEB_VIEW (web_view)); + gtk_entry_set_text (GTK_ENTRY (priv->location), uri); + const gchar* title = midori_web_view_get_display_title ( + MIDORI_WEB_VIEW (web_view)); + gchar* window_title = g_strconcat (title, " - ", + g_get_application_name (), NULL); + gtk_window_set_title (GTK_WINDOW (browser), window_title); + g_free (window_title); + _midori_browser_set_statusbar_text (browser, NULL); + _midori_browser_update_interface (browser); +} + +static void +_action_bookmark_open_activate (GtkAction* action, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + GtkTreeView* treeview = GTK_TREE_VIEW (priv->panel_bookmarks); + GtkTreeSelection* selection = gtk_tree_view_get_selection (treeview); + if (selection) + { + GtkTreeModel* model; + GtkTreeIter iter; + if (gtk_tree_selection_get_selected (selection, &model, &iter)) + { + KatzeXbelItem* item; + gtk_tree_model_get (model, &iter, 0, &item, -1); + if (katze_xbel_item_is_bookmark (item)) + g_object_set(midori_browser_get_current_web_view (browser), + "uri", katze_xbel_bookmark_get_href(item), NULL); + } + } +} + +static void +_action_bookmark_open_tab_activate (GtkAction* action, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + GtkTreeView* treeview = GTK_TREE_VIEW (priv->panel_bookmarks); + GtkTreeSelection* selection = gtk_tree_view_get_selection (treeview); + if (selection) + { + GtkTreeModel* model; + GtkTreeIter iter; + if (gtk_tree_selection_get_selected (selection, &model, &iter)) + { + KatzeXbelItem* item; + gtk_tree_model_get (model, &iter, 0, &item, -1); + if (katze_xbel_item_is_bookmark (item)) + midori_browser_append_xbel_item (browser, item); + } + } +} + +static void +_action_bookmark_open_window_activate (GtkAction* action, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + GtkTreeView* treeview = GTK_TREE_VIEW (priv->panel_bookmarks); + GtkTreeSelection* selection = gtk_tree_view_get_selection (treeview); + if (selection) + { + GtkTreeModel* model; + GtkTreeIter iter; + if (gtk_tree_selection_get_selected (selection, &model, &iter)) + { + KatzeXbelItem* item; + gtk_tree_model_get (model, &iter, 0, &item, -1); + if (katze_xbel_item_is_bookmark (item)) + midori_browser_append_xbel_item (browser, item); + } + } +} + +static void +_action_bookmark_edit_activate (GtkAction* action, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + GtkTreeView* treeview = GTK_TREE_VIEW (priv->panel_bookmarks); + GtkTreeSelection* selection = gtk_tree_view_get_selection (treeview); + if (selection) + { + GtkTreeModel* model; + GtkTreeIter iter; + if (gtk_tree_selection_get_selected (selection, &model, &iter)) + { + KatzeXbelItem* item; + gtk_tree_model_get (model, &iter, 0, &item, -1); + if (!katze_xbel_item_is_separator (item)) + midori_browser_edit_bookmark_dialog_new (browser, item); + } + } +} + +static void +_action_trash_undo_activate (GtkAction* action, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + // Reopen the most recent trash item + KatzeXbelItem* item = midori_trash_get_nth_xbel_item (priv->trash, 0); + midori_browser_append_xbel_item (browser, item); + midori_trash_remove_nth_item (priv->trash, 0); + _midori_browser_update_actions (browser); +} + +static void +_action_trash_empty_activate (GtkAction* action, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + midori_trash_empty (priv->trash); + _midori_browser_update_actions (browser); +} + +static void +_action_bookmark_delete_activate (GtkAction* action, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + GtkTreeView* treeview = GTK_TREE_VIEW (priv->panel_bookmarks); + GtkTreeSelection* selection = gtk_tree_view_get_selection (treeview); + if (selection) + { + GtkTreeModel* model; + GtkTreeIter iter; + if (gtk_tree_selection_get_selected (selection, &model, &iter)) + { + KatzeXbelItem* item; + gtk_tree_model_get (model, &iter, 0, &item, -1); + KatzeXbelItem* parent = katze_xbel_item_get_parent (item); + katze_xbel_folder_remove_item (parent, item); + katze_xbel_item_unref (item); + } + } +} + +// FIXME: Fill in a good description for each 'hm?' +static const GtkActionEntry entries[] = { + { "File", NULL, "_File" }, + { "WindowNew", STOCK_WINDOW_NEW, + NULL, "n", + "Open a new window", G_CALLBACK (_action_window_new_activate) }, + { "TabNew", STOCK_TAB_NEW, + NULL, "t", + "Open a new tab", G_CALLBACK (_action_tab_new_activate) }, + { "Open", GTK_STOCK_OPEN, + NULL, "o", + "Open a file", G_CALLBACK (_action_open_activate) }, + { "SaveAs", GTK_STOCK_SAVE_AS, + NULL, "s", + "Save to a file", NULL/*G_CALLBACK (_action_saveas_activate)*/ }, + { "TabClose", STOCK_TAB_CLOSE, + NULL, "w", + "Close the current tab", G_CALLBACK (_action_tab_close_activate) }, + { "WindowClose", STOCK_WINDOW_CLOSE, + NULL, "w", + "Close this window", G_CALLBACK (_action_window_close_activate) }, + { "PageSetup", GTK_STOCK_PROPERTIES, + "Pa_ge Setup", "", + "hm?", NULL/*G_CALLBACK (_action_page_setup_activate)*/ }, + { "PrintPreview", GTK_STOCK_PRINT_PREVIEW, + NULL, "", + "hm?", NULL/*G_CALLBACK (_action_print_preview_activate)*/ }, + { "Print", GTK_STOCK_PRINT, + NULL, "p", + "hm?", NULL/*G_CALLBACK (_action_print_activate)*/ }, + { "Quit", GTK_STOCK_QUIT, + NULL, "q", + "Quit the application", G_CALLBACK (_action_quit_activate) }, + + { "Edit", NULL, "_Edit", NULL, NULL, G_CALLBACK (_action_edit_activate) }, + { "Undo", GTK_STOCK_UNDO, + NULL, "z", + "Undo the last modification", NULL/*G_CALLBACK (_action_undo_activate)*/ }, + { "Redo", GTK_STOCK_REDO, + NULL, "z", + "Redo the last modification", NULL/*G_CALLBACK (_action_redo_activate)*/ }, + { "Cut", GTK_STOCK_CUT, + NULL, "x", + "Cut the selected text", G_CALLBACK (_action_cut_activate) }, + { "Copy", GTK_STOCK_COPY, + NULL, "c", + "Copy the selected text", G_CALLBACK (_action_copy_activate) }, + { "Copy_", GTK_STOCK_COPY, + NULL, "c", + "Copy the selected text", G_CALLBACK (_action_copy_activate) }, + { "Paste", GTK_STOCK_PASTE, + NULL, "v", + "Paste text from the clipboard", G_CALLBACK (_action_paste_activate) }, + { "Delete", GTK_STOCK_DELETE, + NULL, NULL, + "Delete the selected text", G_CALLBACK (_action_delete_activate) }, + { "SelectAll", GTK_STOCK_SELECT_ALL, + NULL, "a", + "Selected all text", G_CALLBACK (_action_select_all_activate) }, + { "FormFill", STOCK_FORM_FILL, + NULL, "", + "hm?", NULL/*G_CALLBACK (_action_form_fill_activate)*/ }, + { "Find", GTK_STOCK_FIND, + NULL, "f", + "hm?", G_CALLBACK (_action_find_activate) }, + { "FindNext", GTK_STOCK_GO_FORWARD, + "Find _Next", "g", + "hm?", G_CALLBACK (_action_find_next_activate) }, + { "FindPrevious", GTK_STOCK_GO_BACK, + "Find _Previous", "g", + "hm?", G_CALLBACK (_action_find_previous_activate) }, + { "FindQuick", GTK_STOCK_FIND, + "_Quick Find", "period", + "hm?", NULL/*G_CALLBACK (_action_find_quick_activate)*/ }, + { "Preferences", GTK_STOCK_PREFERENCES, + NULL, "p", + "hm?", G_CALLBACK (_action_preferences_activate) }, + + { "View", NULL, "_View" }, + { "Toolbars", NULL, "_Toolbars" }, + { "Reload", GTK_STOCK_REFRESH, + NULL, "r", + "Reload the current page", G_CALLBACK (_action_reload_stop_activate) }, + { "Stop", GTK_STOCK_REFRESH, + NULL, "r", + "Stop loading the current page", G_CALLBACK (_action_reload_stop_activate) }, + { "ReloadStop", GTK_STOCK_STOP, + NULL, "r", + "Reload the current page", G_CALLBACK (_action_reload_stop_activate) }, + { "ZoomIn", GTK_STOCK_ZOOM_IN, + NULL, "plus", + "hm?", NULL/*G_CALLBACK (_action_zoom_in_activate)*/ }, + { "ZoomOut", GTK_STOCK_ZOOM_OUT, + NULL, "minus", + "hm?", NULL/*G_CALLBACK (_action_zoom_out_activate)*/ }, + { "ZoomNormal", GTK_STOCK_ZOOM_100, + NULL, "0", + "hm?", NULL/*G_CALLBACK (_action_zoom_normal_activate)*/ }, + { "SourceView", STOCK_SOURCE_VIEW, + NULL, "", + "hm?", /*G_CALLBACK (_action_source_view_activate)*/ }, + { "SelectionSourceView", STOCK_SOURCE_VIEW, + "View Selection Source", "", + "hm?", NULL/*G_CALLBACK (_action_selection_source_view_activate)*/ }, + { "Fullscreen", GTK_STOCK_FULLSCREEN, + NULL, "F11", + "Toggle fullscreen view", G_CALLBACK (_action_fullscreen_activate) }, + + { "Go", NULL, "_Go" }, + { "Back", GTK_STOCK_GO_BACK, + NULL, "Left", + "hm?", G_CALLBACK (_action_back_activate) }, + { "Forward", GTK_STOCK_GO_FORWARD, + NULL, "Right", + "hm?", G_CALLBACK (_action_forward_activate) }, + { "Home", STOCK_HOMEPAGE, + NULL, "Home", + "hm?", G_CALLBACK (_action_home_activate) }, + { "Location", GTK_STOCK_JUMP_TO, + "Location...", "l", + "hm?", G_CALLBACK (_action_location_activate) }, + { "Search", GTK_STOCK_FIND, + "Web Search...", "f", + "hm?", G_CALLBACK (_action_search_activate) }, + { "OpenInPageholder", GTK_STOCK_JUMP_TO, + "Open in Page_holder...", "", + "hm?", G_CALLBACK (_action_open_in_panel_activate) }, + { "Trash", STOCK_USER_TRASH, + "Closed Tabs and Windows", "", + "Reopen a previously closed tab or window", NULL }, + { "TrashEmpty", GTK_STOCK_CLEAR, + "Empty Trash", "", + "hm?", G_CALLBACK (_action_trash_empty_activate) }, + + { "Bookmarks", NULL, "_Bookmarks" }, + { "BookmarkNew", STOCK_BOOKMARK_NEW, + NULL, "d", + "hm?", G_CALLBACK (_action_bookmark_new_activate) }, + { "BookmarksManage", NULL, + "_Manage Bookmarks", "b", + "hm?", NULL/*G_CALLBACK (_action_bookmarks_manage_activate)*/ }, + { "BookmarkOpen", GTK_STOCK_OPEN, + NULL, "", + "hm?", G_CALLBACK (_action_bookmark_open_activate) }, + { "BookmarkOpenTab", STOCK_TAB_NEW, + "Open in New _Tab", "", + "hm?", G_CALLBACK (_action_bookmark_open_tab_activate) }, + { "BookmarkOpenWindow", STOCK_WINDOW_NEW, + "Open in New _Window", "", + "hm?", G_CALLBACK (_action_bookmark_open_window_activate) }, + { "BookmarkEdit", GTK_STOCK_EDIT, + NULL, "", + "hm?", G_CALLBACK (_action_bookmark_edit_activate) }, + { "BookmarkDelete", GTK_STOCK_DELETE, + NULL, "", + "hm?", G_CALLBACK (_action_bookmark_delete_activate) }, + + { "Tools", NULL, "_Tools" }, + { "ManageSearchEngines", GTK_STOCK_PROPERTIES, + "_Manage Search Engines", "s", + "Add, edit and remove search engines...", + G_CALLBACK (_action_manage_search_engines_activate) }, + + { "Window", NULL, "_Window" }, + { "TabPrevious", GTK_STOCK_GO_BACK, + "_Previous Tab", "Page_Up", + "hm?", G_CALLBACK (_action_tab_previous_activate) }, + { "TabNext", GTK_STOCK_GO_FORWARD, + "_Next Tab", "Page_Down", + "hm?", G_CALLBACK (_action_tab_next_activate) }, + { "TabOverview", NULL, + "Tab _Overview", "", + "hm?", NULL/*G_CALLBACK (_action_tab_overview_activate)*/ }, + + { "Help", NULL, "_Help" }, + { "HelpContents", GTK_STOCK_HELP, + "_Contents", "F1", + "hm?", NULL/*G_CALLBACK (_action_help_contents_activate)*/ }, + { "About", GTK_STOCK_ABOUT, + NULL, "", + "hm?", G_CALLBACK (_action_about_activate) }, + }; + static const guint entries_n = G_N_ELEMENTS(entries); + +static const GtkToggleActionEntry toggle_entries[] = { + { "PrivateBrowsing", NULL, + "P_rivate Browsing", "", + "hm?", NULL/*G_CALLBACK (_action_private_browsing_activate)*/, + FALSE }, + { "WorkOffline", GTK_STOCK_DISCONNECT, + "_Work Offline", "", + "hm?", NULL/*G_CALLBACK (_action_work_offline_activate)*/, + FALSE }, + + { "Navigationbar", NULL, + "_Navigationbar", "", + "hm?", G_CALLBACK (_action_navigationbar_activate), + FALSE }, + { "Panel", NULL, + "_Panel", "F9", + "hm?", G_CALLBACK (_action_panel_activate), + FALSE }, + { "Bookmarkbar", NULL, + "_Bookmarkbar", "", + "hm?", G_CALLBACK (_action_bookmarkbar_activate), + FALSE }, + { "Downloadbar", NULL, + "_Downloadbar", "", + "hm?", NULL/*G_CALLBACK (_action_downloadbar_activate)*/, + FALSE }, + { "Statusbar", NULL, + "_Statusbar", "", + "hm?", G_CALLBACK (_action_statusbar_activate), + FALSE }, + }; + static const guint toggle_entries_n = G_N_ELEMENTS(toggle_entries); + +static void +midori_browser_window_state_event_cb (MidoriBrowser* browser, + GdkEventWindowState* event) +{ + MidoriBrowserPrivate* priv = browser->priv; + + if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) + { + if (event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN) + { + gtk_widget_hide (priv->menubar); + g_object_set (priv->button_fullscreen, + "stock-id", GTK_STOCK_LEAVE_FULLSCREEN, NULL); + gtk_widget_show (priv->button_fullscreen); + } + else + { + gtk_widget_show (priv->menubar); + gtk_widget_hide (priv->button_fullscreen); + g_object_set (priv->button_fullscreen, + "stock-id", GTK_STOCK_FULLSCREEN, NULL); + } + } +} + +static void +midori_browser_size_allocate_cb (MidoriBrowser* browser, + GtkAllocation* allocation) +{ + GtkWidget* widget = GTK_WIDGET (browser); + + if (GTK_WIDGET_REALIZED (widget)) + { + GdkWindowState state = gdk_window_get_state (widget->window); + if (!(state & (GDK_WINDOW_STATE_MAXIMIZED | GDK_WINDOW_STATE_FULLSCREEN))) + { + config->winWidth = allocation->width; + config->winHeight = allocation->height; + } + } +} + +static const gchar* ui_markup = + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + // Closed tabs shall be prepended here + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + // Bookmarks shall be appended here + "" + "" + "" + // Panel items shall be appended here + "" + "" + "" + "" + "" + "" + // All open tabs shall be appended here + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + ""; + +static void +midori_browser_init (MidoriBrowser* browser) +{ + browser->priv = MIDORI_BROWSER_GET_PRIVATE (browser); + + MidoriBrowserPrivate* priv = browser->priv; + + // Setup the window metrics + g_signal_connect (browser, "window-state-event", + G_CALLBACK (midori_browser_window_state_event_cb), NULL); + GdkScreen* screen = gtk_window_get_screen (GTK_WINDOW (browser)); + const gint default_width = (gint)gdk_screen_get_width (screen) / 1.7; + const gint default_height = (gint)gdk_screen_get_height (screen) / 1.7; + if (config->rememberWinSize) + { + if (!config->winWidth && !config->winHeight) + { + config->winWidth = default_width; + config->winHeight = default_width; + } + gtk_window_set_default_size (GTK_WINDOW (browser), + config->winWidth, config->winHeight); + } + else + gtk_window_set_default_size (GTK_WINDOW(browser), + default_width, default_height); + g_signal_connect (browser, "size-allocate", + G_CALLBACK (midori_browser_size_allocate_cb), NULL); + // FIXME: Use custom program icon + gtk_window_set_icon_name (GTK_WINDOW (browser), "web-browser"); + gtk_window_set_title (GTK_WINDOW (browser), g_get_application_name ()); + GtkWidget* vbox = gtk_vbox_new (FALSE, 0); + gtk_container_add (GTK_CONTAINER (browser), vbox); + gtk_widget_show (vbox); + + // Let us see some ui manager magic + priv->action_group = gtk_action_group_new ("Browser"); + gtk_action_group_add_actions (priv->action_group, + entries, entries_n, browser); + gtk_action_group_add_toggle_actions (priv->action_group, + toggle_entries, toggle_entries_n, browser); + GtkUIManager* ui_manager = gtk_ui_manager_new (); + gtk_ui_manager_insert_action_group (ui_manager, priv->action_group, 0); + gtk_window_add_accel_group (GTK_WINDOW (browser), + gtk_ui_manager_get_accel_group (ui_manager)); + + GError* error = NULL; + if (!gtk_ui_manager_add_ui_from_string(ui_manager, ui_markup, -1, &error)) + { + // TODO: Should this be a message dialog? When does this happen? + g_message ("User interface couldn't be created: %s", error->message); + g_error_free (error); + } + + GtkAction* action; + // Make all actions except toplevel menus which lack a callback insensitive + // This will vanish once all actions are implemented + guint i; + for (i = 0; i < entries_n; i++) + { + action = gtk_action_group_get_action(priv->action_group, + entries[i].name); + gtk_action_set_sensitive (action, + entries[i].callback || !entries[i].tooltip); + } + for (i = 0; i < toggle_entries_n; i++) + { + action = gtk_action_group_get_action (priv->action_group, + toggle_entries[i].name); + gtk_action_set_sensitive (action, toggle_entries[i].callback != NULL); + } + + //_action_set_active(browser, "Downloadbar", config->toolbarDownloads); + + // Create the menubar + priv->menubar = gtk_ui_manager_get_widget (ui_manager, "/menubar"); + GtkWidget* menuitem = gtk_menu_item_new(); + gtk_widget_show (menuitem); + priv->throbber = katze_throbber_new(); + gtk_widget_show(priv->throbber); + gtk_container_add (GTK_CONTAINER (menuitem), priv->throbber); + gtk_widget_set_sensitive (menuitem, FALSE); + gtk_menu_item_set_right_justified (GTK_MENU_ITEM (menuitem), TRUE); + gtk_menu_shell_append (GTK_MENU_SHELL (priv->menubar), menuitem); + gtk_box_pack_start (GTK_BOX (vbox), priv->menubar, FALSE, FALSE, 0); + menuitem = gtk_ui_manager_get_widget (ui_manager, "/menubar/Go/Trash"); + g_signal_connect (menuitem, "activate", + G_CALLBACK (midori_browser_menu_trash_activate_cb), + browser); + priv->menu_bookmarks = gtk_menu_item_get_submenu (GTK_MENU_ITEM ( + gtk_ui_manager_get_widget (ui_manager, "/menubar/Bookmarks"))); + menuitem = gtk_separator_menu_item_new (); + gtk_widget_show (menuitem); + gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu_bookmarks), menuitem); + priv->popup_bookmark = gtk_ui_manager_get_widget ( + ui_manager, "/popup_bookmark"); + g_object_ref (priv->popup_bookmark); + priv->menu_tools = gtk_menu_item_get_submenu (GTK_MENU_ITEM ( + gtk_ui_manager_get_widget (ui_manager, "/menubar/Tools"))); + menuitem = gtk_separator_menu_item_new(); + gtk_widget_show (menuitem); + gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu_tools), menuitem); + priv->menu_window = gtk_menu_item_get_submenu (GTK_MENU_ITEM ( + gtk_ui_manager_get_widget (ui_manager, "/menubar/Window"))); + menuitem = gtk_separator_menu_item_new(); + gtk_widget_show (menuitem); + gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu_window), menuitem); + gtk_widget_show (priv->menubar); + _action_set_sensitive (browser, "PrivateBrowsing", FALSE); + _action_set_sensitive (browser, "WorkOffline", FALSE); + + // Create the navigationbar + priv->navigationbar = gtk_ui_manager_get_widget ( + ui_manager, "/toolbar_navigation"); + gtk_toolbar_set_style (GTK_TOOLBAR (priv->navigationbar), + config_to_toolbarstyle (config->toolbarStyle)); + GtkSettings* gtk_settings = gtk_widget_get_settings (priv->navigationbar); + g_signal_connect (gtk_settings, "notify::gtk-toolbar-style", + G_CALLBACK (midori_browser_navigationbar_notify_style_cb), + browser); + gtk_toolbar_set_icon_size (GTK_TOOLBAR (priv->navigationbar), + config_to_toolbariconsize (config->toolbarSmall)); + gtk_toolbar_set_show_arrow (GTK_TOOLBAR (priv->navigationbar), TRUE); + gtk_box_pack_start (GTK_BOX (vbox), priv->navigationbar, FALSE, FALSE, 0); + priv->button_tab_new = gtk_ui_manager_get_widget ( + ui_manager, "/toolbar_navigation/TabNew"); + g_object_set (_action_by_name (browser, "Back"), "is-important", TRUE, NULL); + + // Location + priv->location = sexy_icon_entry_new(); + entry_setup_completion (GTK_ENTRY (priv->location)); + priv->location_icon = gtk_image_new (); + sexy_icon_entry_set_icon (SEXY_ICON_ENTRY (priv->location) + , SEXY_ICON_ENTRY_PRIMARY, GTK_IMAGE (priv->location_icon)); + sexy_icon_entry_add_clear_button (SEXY_ICON_ENTRY (priv->location)); + g_signal_connect (priv->location, "key-press-event", + G_CALLBACK (midori_browser_location_key_press_event_cb), + browser); + g_signal_connect (priv->location, "changed", + G_CALLBACK (midori_browser_location_changed_cb), browser); + GtkToolItem* toolitem = gtk_tool_item_new (); + gtk_tool_item_set_expand (GTK_TOOL_ITEM (toolitem), TRUE); + gtk_container_add (GTK_CONTAINER(toolitem), priv->location); + gtk_toolbar_insert (GTK_TOOLBAR (priv->navigationbar), toolitem, -1); + + // Search + priv->search = sexy_icon_entry_new (); + sexy_icon_entry_set_icon_highlight (SEXY_ICON_ENTRY (priv->search), + SEXY_ICON_ENTRY_PRIMARY, TRUE); + // TODO: Make this actively resizable or enlarge to fit contents? + // FIXME: The interface is somewhat awkward and ought to be rethought + // TODO: Display "show in context menu" search engines as "completion actions" + entry_setup_completion (GTK_ENTRY (priv->search)); + update_searchEngine (config->searchEngine, priv->search); + g_object_connect (priv->search, + "signal::icon-released", + on_webSearch_icon_released, browser, + "signal::key-press-event", + on_webSearch_key_down, browser, + "signal::scroll-event", + on_webSearch_scroll, browser, + "signal::activate", + on_webSearch_activate, browser, + NULL); + toolitem = gtk_tool_item_new (); + gtk_container_add (GTK_CONTAINER (toolitem), priv->search); + gtk_toolbar_insert (GTK_TOOLBAR (priv->navigationbar), toolitem, -1); + action = gtk_action_group_get_action (priv->action_group, "Trash"); + priv->button_trash = gtk_action_create_tool_item (action); + g_signal_connect (priv->button_trash, "clicked", + G_CALLBACK (midori_browser_menu_trash_activate_cb), browser); + gtk_toolbar_insert (GTK_TOOLBAR (priv->navigationbar), + GTK_TOOL_ITEM (priv->button_trash), -1); + sokoke_container_show_children (GTK_CONTAINER (priv->navigationbar)); + action = gtk_action_group_get_action (priv->action_group, "Fullscreen"); + priv->button_fullscreen = gtk_action_create_tool_item (action); + gtk_widget_hide (priv->button_fullscreen); + g_signal_connect (priv->button_fullscreen, "clicked", + G_CALLBACK (_action_fullscreen_activate), browser); + gtk_toolbar_insert (GTK_TOOLBAR (priv->navigationbar), + GTK_TOOL_ITEM (priv->button_fullscreen), -1); + _action_set_active (browser, "Navigationbar", config->toolbarNavigation); + + // Bookmarkbar + priv->bookmarkbar = gtk_toolbar_new (); + gtk_toolbar_set_icon_size (GTK_TOOLBAR (priv->bookmarkbar), + GTK_ICON_SIZE_MENU); + gtk_toolbar_set_style (GTK_TOOLBAR(priv->bookmarkbar), + GTK_TOOLBAR_BOTH_HORIZ); + _midori_browser_create_bookmark_menu (browser, bookmarks, + priv->menu_bookmarks); + for (i = 0; i < katze_xbel_folder_get_n_items (bookmarks); i++) + { + KatzeXbelItem* item = katze_xbel_folder_get_nth_item (bookmarks, i); + const gchar* title = katze_xbel_item_is_separator (item) + ? "" : katze_xbel_item_get_title (item); + const gchar* desc = katze_xbel_item_is_separator (item) + ? "" : katze_xbel_item_get_desc (item); + switch (katze_xbel_item_get_kind (item)) + { + case KATZE_XBEL_ITEM_KIND_FOLDER: + toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_DIRECTORY); + gtk_tool_button_set_label (GTK_TOOL_BUTTON (toolitem), title); + gtk_tool_item_set_is_important(toolitem, TRUE); + g_signal_connect (toolitem, "clicked", + G_CALLBACK (midori_browser_bookmarkbar_folder_activate_cb), + browser); + sokoke_tool_item_set_tooltip_text(toolitem, desc); + g_object_set_data (G_OBJECT (toolitem), "KatzeXbelItem", item); + break; + case KATZE_XBEL_ITEM_KIND_BOOKMARK: + toolitem = gtk_tool_button_new_from_stock (STOCK_BOOKMARK); + gtk_tool_button_set_label (GTK_TOOL_BUTTON (toolitem), title); + gtk_tool_item_set_is_important(toolitem, TRUE); + g_signal_connect (toolitem, "clicked", + G_CALLBACK (midori_browser_menu_bookmarks_item_activate_cb), + browser); + sokoke_tool_item_set_tooltip_text(toolitem, desc); + g_object_set_data (G_OBJECT (toolitem), "KatzeXbelItem", item); + break; + case KATZE_XBEL_ITEM_KIND_SEPARATOR: + toolitem = gtk_separator_tool_item_new (); + break; + default: + g_warning ("Unknown item kind"); + } + gtk_toolbar_insert (GTK_TOOLBAR (priv->bookmarkbar), toolitem, -1); + } + sokoke_container_show_children (GTK_CONTAINER (priv->bookmarkbar)); + gtk_box_pack_start (GTK_BOX (vbox), priv->bookmarkbar, FALSE, FALSE, 0); + _action_set_active (browser, "Bookmarkbar", config->toolbarBookmarks); + + // Superuser warning + GtkWidget* hbox; + if ((hbox = sokoke_superuser_warning_new ())) + gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); + + // Create the panel + GtkWidget* hpaned = gtk_hpaned_new (); + gtk_paned_set_position (GTK_PANED (hpaned), config->winPanelPos); + g_signal_connect (hpaned, "notify::position", + G_CALLBACK (midori_panel_notify_position_cb), + browser); + gtk_box_pack_start (GTK_BOX (vbox), hpaned, TRUE, TRUE, 0); + gtk_widget_show (hpaned); + priv->panel = g_object_new (MIDORI_TYPE_PANEL, + "shadow-type", GTK_SHADOW_IN, + "menu", priv->menu_tools, + NULL); + g_signal_connect (priv->panel, "close", + G_CALLBACK (midori_panel_close_cb), browser); + gtk_paned_pack1 (GTK_PANED (hpaned), priv->panel, FALSE, FALSE); + sokoke_widget_set_visible (priv->panel, config->panelShow); + _action_set_active (browser, "Panel", config->panelShow); + + // Bookmarks + GtkWidget* box = gtk_vbox_new (FALSE, 0); + GtkWidget* toolbar = gtk_ui_manager_get_widget (ui_manager, "/toolbar_bookmarks"); + gtk_toolbar_set_icon_size (GTK_TOOLBAR (toolbar), GTK_ICON_SIZE_MENU); + gtk_box_pack_start (GTK_BOX (box), toolbar, FALSE, FALSE, 0); + GtkTreeViewColumn* column; + GtkCellRenderer* renderer_text; + GtkCellRenderer* renderer_pixbuf; + GtkTreeStore* treestore = gtk_tree_store_new (1, KATZE_TYPE_XBEL_ITEM); + GtkWidget* treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (treestore)); + gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE); + column = gtk_tree_view_column_new (); + renderer_pixbuf = gtk_cell_renderer_pixbuf_new (); + gtk_tree_view_column_pack_start (column, renderer_pixbuf, FALSE); + gtk_tree_view_column_set_cell_data_func (column, renderer_pixbuf, + (GtkTreeCellDataFunc)midori_browser_bookmarks_item_render_icon_cb, + treeview, NULL); + renderer_text = gtk_cell_renderer_text_new (); + gtk_tree_view_column_pack_start (column, renderer_text, FALSE); + gtk_tree_view_column_set_cell_data_func (column, renderer_text, + (GtkTreeCellDataFunc)midori_browser_bookmarks_item_render_text_cb, + treeview, NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column); + _tree_store_insert_folder (GTK_TREE_STORE (treestore), NULL, bookmarks); + g_object_unref (treestore); + g_object_connect (treeview, + "signal::row-activated", + midori_panel_bookmarks_row_activated_cb, browser, + "signal::cursor-changed", + midori_panel_bookmarks_cursor_or_row_changed_cb, browser, + "signal::columns-changed", + midori_panel_bookmarks_cursor_or_row_changed_cb, browser, + "signal::button-release-event", + midori_panel_bookmarks_button_release_event_cb, browser, + "signal::popup-menu", + midori_panel_bookmarks_popup_menu_cb, browser, + NULL); + midori_panel_bookmarks_cursor_or_row_changed_cb (GTK_TREE_VIEW (treeview), + browser); + gtk_box_pack_start (GTK_BOX (box), treeview, FALSE, FALSE, 0); + priv->panel_bookmarks = treeview; + gtk_widget_show_all (box); + midori_panel_append_page (MIDORI_PANEL (priv->panel), + box, "vcard", "Bookmarks"); + action = _action_by_name (browser, "PanelBookmarks"); + + // Downloads + priv->panel_pageholder = g_object_new (MIDORI_TYPE_WEB_VIEW, + "uri", "about:blank", + NULL); + gtk_widget_show (priv->panel_pageholder); + midori_panel_append_page (MIDORI_PANEL (priv->panel), + priv->panel_pageholder, + "package", "Downloads"); + + // Console + priv->panel_pageholder = g_object_new (MIDORI_TYPE_WEB_VIEW, + "uri", "about:blank", + NULL); + gtk_widget_show (priv->panel_pageholder); + midori_panel_append_page (MIDORI_PANEL (priv->panel), + priv->panel_pageholder, + "terminal", "Console"); + + // History + priv->panel_pageholder = g_object_new (MIDORI_TYPE_WEB_VIEW, + "uri", "about:blank", + NULL); + gtk_widget_show (priv->panel_pageholder); + midori_panel_append_page (MIDORI_PANEL (priv->panel), + priv->panel_pageholder, + "document-open-recent", "History"); + + // Pageholder + priv->panel_pageholder = g_object_new (MIDORI_TYPE_WEB_VIEW, + "uri", config->panelPageholder, + NULL); + gtk_widget_show (priv->panel_pageholder); + midori_panel_append_page (MIDORI_PANEL (priv->panel), + priv->panel_pageholder, + GTK_STOCK_CONVERT, "Pageholder"); + + midori_panel_set_current_page (MIDORI_PANEL (priv->panel), + config->panelActive); + sokoke_widget_set_visible (priv->panel, config->panelShow); + + // Notebook, containing all web_views + priv->notebook = gtk_notebook_new (); + gtk_notebook_set_scrollable (GTK_NOTEBOOK (priv->notebook), TRUE); + gtk_paned_pack2 (GTK_PANED (hpaned), priv->notebook, FALSE, FALSE); + g_signal_connect_after (priv->notebook, "switch-page", + G_CALLBACK (gtk_notebook_switch_page_cb), + browser); + gtk_widget_show (priv->notebook); + + // Incremental findbar + priv->find = gtk_toolbar_new (); + gtk_toolbar_set_icon_size (GTK_TOOLBAR (priv->find), GTK_ICON_SIZE_MENU); + gtk_toolbar_set_style (GTK_TOOLBAR (priv->find), GTK_TOOLBAR_BOTH_HORIZ); + toolitem = gtk_tool_item_new (); + gtk_container_set_border_width (GTK_CONTAINER (toolitem), 6); + gtk_container_add (GTK_CONTAINER (toolitem), + gtk_label_new_with_mnemonic ("_Inline find:")); + gtk_toolbar_insert (GTK_TOOLBAR (priv->find), toolitem, -1); + priv->find_text = sexy_icon_entry_new (); + GtkWidget* icon = gtk_image_new_from_stock (GTK_STOCK_FIND, + GTK_ICON_SIZE_MENU); + sexy_icon_entry_set_icon (SEXY_ICON_ENTRY(priv->find_text), + SEXY_ICON_ENTRY_PRIMARY, GTK_IMAGE(icon)); + sexy_icon_entry_add_clear_button (SEXY_ICON_ENTRY(priv->find_text)); + g_signal_connect (priv->find_text, "activate", + G_CALLBACK (_action_find_next_activate), browser); + toolitem = gtk_tool_item_new (); + gtk_container_add (GTK_CONTAINER (toolitem), priv->find_text); + gtk_tool_item_set_expand (GTK_TOOL_ITEM (toolitem), TRUE); + gtk_toolbar_insert (GTK_TOOLBAR(priv->find), toolitem, -1); + toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_GO_BACK); + gtk_tool_item_set_is_important (toolitem, TRUE); + g_signal_connect (toolitem, "clicked", + G_CALLBACK (_action_find_previous_activate), browser); + gtk_toolbar_insert (GTK_TOOLBAR (priv->find), toolitem, -1); + toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_GO_FORWARD); + gtk_tool_item_set_is_important (toolitem, TRUE); + g_signal_connect (toolitem, "clicked", + G_CALLBACK (_action_find_next_activate), browser); + gtk_toolbar_insert (GTK_TOOLBAR (priv->find), toolitem, -1); + priv->find_case = gtk_toggle_tool_button_new_from_stock ( + GTK_STOCK_SPELL_CHECK); + gtk_tool_button_set_label (GTK_TOOL_BUTTON (priv->find_case), "Match Case"); + gtk_tool_item_set_is_important (GTK_TOOL_ITEM (priv->find_case), TRUE); + gtk_toolbar_insert (GTK_TOOLBAR (priv->find), priv->find_case, -1); + priv->find_highlight = gtk_toggle_tool_button_new_from_stock ( + GTK_STOCK_SELECT_ALL); + g_signal_connect (priv->find_highlight, "toggled", + G_CALLBACK (_find_highlight_toggled), browser); + gtk_tool_button_set_label (GTK_TOOL_BUTTON (priv->find_highlight), + "Highlight Matches"); + gtk_tool_item_set_is_important (GTK_TOOL_ITEM (priv->find_highlight), TRUE); + gtk_toolbar_insert (GTK_TOOLBAR (priv->find), priv->find_highlight, -1); + toolitem = gtk_separator_tool_item_new (); + gtk_separator_tool_item_set_draw ( + GTK_SEPARATOR_TOOL_ITEM (toolitem), FALSE); + gtk_tool_item_set_expand (GTK_TOOL_ITEM (toolitem), TRUE); + gtk_toolbar_insert (GTK_TOOLBAR (priv->find), toolitem, -1); + toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_CLOSE); + gtk_tool_button_set_label (GTK_TOOL_BUTTON (toolitem), "Close Findbar"); + g_signal_connect (toolitem, "clicked", + G_CALLBACK (midori_browser_find_button_close_clicked_cb), browser); + gtk_toolbar_insert (GTK_TOOLBAR (priv->find), toolitem, -1); + sokoke_container_show_children (GTK_CONTAINER (priv->find)); + gtk_box_pack_start (GTK_BOX (vbox), priv->find, FALSE, FALSE, 0); + + // Statusbar + // TODO: fix children overlapping statusbar border + priv->statusbar = gtk_statusbar_new (); + gtk_box_pack_start (GTK_BOX (vbox), priv->statusbar, FALSE, FALSE, 0); + priv->progressbar = gtk_progress_bar_new (); + // Setting the progressbar's height to 1 makes it fit in the statusbar + gtk_widget_set_size_request (priv->progressbar, -1, 1); + gtk_box_pack_start (GTK_BOX (priv->statusbar), priv->progressbar, + FALSE, FALSE, 3); + _action_set_active (browser, "Statusbar", config->toolbarStatus); + + g_object_unref (ui_manager); + + sokoke_widget_set_visible (priv->button_tab_new, config->toolbarNewTab); + sokoke_widget_set_visible (priv->search, config->toolbarWebSearch); + sokoke_widget_set_visible (priv->button_trash, config->toolbarClosedTabs); +} + +static void +midori_browser_finalize (GObject* object) +{ + MidoriBrowser* browser = MIDORI_BROWSER (object); + MidoriBrowserPrivate* priv = browser->priv; + + g_free (priv->uri); + g_free (priv->title); + g_free (priv->statusbar_text); + + if (priv->proxy_xbel_folder) + katze_xbel_item_unref (priv->proxy_xbel_folder); + + if (priv->settings) + g_object_unref (priv->settings); + if (priv->trash) + g_object_unref (priv->trash); + + G_OBJECT_CLASS (midori_browser_parent_class)->finalize (object); +} + +static void +midori_browser_set_property (GObject* object, + guint prop_id, + const GValue* value, + GParamSpec* pspec) +{ + MidoriBrowser* browser = MIDORI_BROWSER (object); + MidoriBrowserPrivate* priv = browser->priv; + + switch (prop_id) + { + case PROP_STATUSBAR_TEXT: + _midori_browser_set_statusbar_text (browser, g_value_get_string (value)); + break; + case PROP_SETTINGS: + katze_object_assign (priv->settings, g_value_get_object (value)); + g_object_ref (priv->settings); + // FIXME: Assign settings to each web view + break; + case PROP_TRASH: + ; // FIXME: Disconnect handlers + katze_object_assign (priv->trash, g_value_get_object (value)); + g_object_ref (priv->trash); + // FIXME: Connect to updates + _midori_browser_update_actions (browser); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +midori_browser_get_property (GObject* object, + guint prop_id, + GValue* value, + GParamSpec* pspec) +{ + MidoriBrowser* browser = MIDORI_BROWSER (object); + MidoriBrowserPrivate* priv = browser->priv; + + switch (prop_id) + { + case PROP_STATUSBAR_TEXT: + g_value_set_string (value, priv->statusbar_text); + break; + case PROP_SETTINGS: + g_value_set_object (value, priv->settings); + break; + case PROP_TRASH: + g_value_set_object (value, priv->trash); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/** + * midori_browser_new: + * + * Creates a new browser widget. + * + * A browser is a window with toolbars and one or multiple web views. + * + * Return value: a new #MidoriBrowser + **/ +GtkWidget* +midori_browser_new (void) +{ + MidoriBrowser* browser = g_object_new (MIDORI_TYPE_BROWSER, + NULL); + + return GTK_WIDGET (browser); +} + +/** + * midori_browser_append_tab: + * @browser: a #MidoriBrowser + * @widget: a tab + * + * Appends an arbitrary widget in the form of a new tab and creates an + * according item in the Window menu. + * + * Return value: the index of the new tab, or -1 in case of an error + **/ +gint +midori_browser_append_tab (MidoriBrowser* browser, + GtkWidget* widget) +{ + g_return_val_if_fail (GTK_IS_WIDGET (widget), -1); + + MidoriBrowserPrivate* priv = browser->priv; + + GtkWidget* scrolled = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + GTK_WIDGET_SET_FLAGS (scrolled, GTK_CAN_FOCUS); + GtkWidget* child; + GObjectClass* gobject_class = G_OBJECT_GET_CLASS (widget); + if (GTK_WIDGET_CLASS (gobject_class)->set_scroll_adjustments_signal) + child = widget; + else + { + child = gtk_viewport_new (NULL, NULL); + gtk_widget_show (child); + gtk_container_add (GTK_CONTAINER (child), widget); + } + gtk_container_add (GTK_CONTAINER (scrolled), child); + gtk_widget_show (scrolled); + + GtkWidget* label = NULL; + GtkWidget* menuitem = NULL; + + if (MIDORI_IS_WEB_VIEW (widget)) + { + label = midori_web_view_get_proxy_tab_label (MIDORI_WEB_VIEW (widget)); + + menuitem = midori_web_view_get_proxy_menu_item (MIDORI_WEB_VIEW (widget)); + + if (priv->proxy_xbel_folder) + { + KatzeXbelItem* xbel_item = midori_web_view_get_proxy_xbel_item ( + MIDORI_WEB_VIEW (widget)); + katze_xbel_item_ref (xbel_item); + katze_xbel_folder_append_item (priv->proxy_xbel_folder, xbel_item); + } + + g_object_connect (widget, + "signal::navigation-requested", + midori_web_view_navigation_requested_cb, browser, + "signal::load-started", + midori_web_view_load_started_cb, browser, + "signal::load-committed", + midori_web_view_load_committed_cb, browser, + "signal::progress-started", + midori_web_view_progress_started_cb, browser, + "signal::progress-changed", + midori_web_view_progress_changed_cb, browser, + "signal::progress-done", + midori_web_view_progress_done_cb, browser, + "signal::load-done", + midori_web_view_load_done_cb, browser, + "signal::title-changed", + midori_web_view_title_changed_cb, browser, + "signal::status-bar-text-changed", + midori_web_view_statusbar_text_changed_cb, browser, + "signal::element-motion", + midori_web_view_element_motion_cb, browser, + "signal::console-message", + midori_web_view_console_message_cb, browser, + "signal::close", + midori_web_view_close_cb, browser, + "signal::new-tab", + midori_web_view_new_tab_cb, browser, + "signal::new-window", + midori_web_view_new_window_cb, browser, + "signal::populate-popup", + midori_web_view_populate_popup_cb, browser, + "signal::leave-notify-event", + midori_web_view_leave_notify_event_cb, browser, + "signal::destroy", + midori_web_view_destroy_cb, browser, + NULL); + } + + if (menuitem) + { + gtk_widget_show (menuitem); + g_signal_connect (menuitem, "activate", + G_CALLBACK (midori_browser_window_menu_item_activate_cb), browser); + gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu_window), menuitem); + } + + guint n = gtk_notebook_get_current_page (GTK_NOTEBOOK (priv->notebook)); + gtk_notebook_insert_page (GTK_NOTEBOOK (priv->notebook), scrolled, + label, n + 1); + #if GTK_CHECK_VERSION(2, 10, 0) + gtk_notebook_set_tab_reorderable (GTK_NOTEBOOK (priv->notebook), + scrolled, TRUE); + gtk_notebook_set_tab_detachable (GTK_NOTEBOOK (priv->notebook), + scrolled, TRUE); + #endif + _midori_browser_update_actions (browser); + + n = gtk_notebook_page_num (GTK_NOTEBOOK (priv->notebook), scrolled); + if (!config->openTabsInTheBackground) + gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), n); + return n; +} + +/** + * midori_browser_remove_tab: + * @browser: a #MidoriBrowser + * @widget: a tab + * + * Removes an existing tab from the browser, including an associated menu item. + **/ +void +midori_browser_remove_tab (MidoriBrowser* browser, + GtkWidget* widget) +{ + MidoriBrowserPrivate* priv = browser->priv; + + GtkWidget* scrolled = _midori_browser_scrolled_for_child (browser, widget); + gtk_container_remove (GTK_CONTAINER (priv->notebook), scrolled); + + // FIXME: Remove the menuitem if this is a web view +} + +/** + * midori_browser_append_xbel_item: + * @browser: a #MidoriBrowser + * @xbel_item: a bookmark + * + * Appends a #KatzeXbelItem in the form of a new tab. + * + * Return value: the index of the new tab, or -1 in case of an error + **/ +gint +midori_browser_append_xbel_item (MidoriBrowser* browser, + KatzeXbelItem* xbel_item) +{ + MidoriBrowserPrivate* priv = browser->priv; + + g_return_val_if_fail (katze_xbel_item_is_bookmark (xbel_item), -1); + + const gchar* uri = katze_xbel_bookmark_get_href (xbel_item); + const gchar* title = katze_xbel_item_get_title (xbel_item); + GtkWidget* web_view = g_object_new (MIDORI_TYPE_WEB_VIEW, + "uri", uri, + "title", title, + "settings", priv->settings, + NULL); + gtk_widget_show (web_view); + + return midori_browser_append_tab (browser, web_view); +} + +/** + * midori_browser_append_uri: + * + * Appends an uri in the form of a new tab. + * + * Return value: the index of the new tab, or -1 + **/ +gint +midori_browser_append_uri (MidoriBrowser* browser, + const gchar* uri) +{ + MidoriBrowserPrivate* priv = browser->priv; + + GtkWidget* web_view = g_object_new (MIDORI_TYPE_WEB_VIEW, + "uri", uri, + "settings", priv->settings, + NULL); + gtk_widget_show (web_view); + + return midori_browser_append_tab (browser, web_view); +} + +/** + * midori_browser_get_current_page: + * @browser: a #MidoriBrowser + * + * Determines the currently selected page. + * + * If there is no page present at all, %NULL is returned. + * + * Return value: the selected page, or %NULL + **/ +GtkWidget* +midori_browser_get_current_page (MidoriBrowser* browser) +{ + g_return_val_if_fail (MIDORI_IS_BROWSER (browser), NULL); + + MidoriBrowserPrivate* priv = browser->priv; + + gint n = gtk_notebook_get_current_page (GTK_NOTEBOOK (priv->notebook)); + GtkWidget* widget = _midori_browser_child_for_scrolled (browser, + gtk_notebook_get_nth_page (GTK_NOTEBOOK (priv->notebook), n)); + return widget; +} + +/** + * midori_browser_get_current_web_view: + * @browser: a #MidoriBrowser + * + * Determines the currently selected web view. + * + * If there is no web view selected or if there is no tab present + * at all, %NULL is returned. + * + * See also midori_browser_get_current_page + * + * Return value: the selected web view, or %NULL + **/ +GtkWidget* +midori_browser_get_current_web_view (MidoriBrowser* browser) +{ + g_return_val_if_fail (MIDORI_IS_BROWSER (browser), NULL); + + GtkWidget* web_view = midori_browser_get_current_page (browser); + return MIDORI_IS_WEB_VIEW (web_view) ? web_view : NULL; +} + +/** + * midori_browser_get_proxy_xbel_folder: + * @browser: a #MidoriBrowser + * + * Retrieves a proxy xbel folder representing the respective proxy xbel items + * of the present web views that can be used for session management. + * + * The folder is created on the first call and will be updated to reflect + * changes to all items automatically. + * + * Note that this implicitly creates proxy xbel items of all web views. + * + * Return value: the proxy #KatzeXbelItem + **/ +KatzeXbelItem* +midori_browser_get_proxy_xbel_folder (MidoriBrowser* browser) +{ + g_return_val_if_fail (MIDORI_IS_BROWSER (browser), NULL); + + MidoriBrowserPrivate* priv = browser->priv; + + if (!priv->proxy_xbel_folder) + { + priv->proxy_xbel_folder = katze_xbel_folder_new (); + // FIXME: Fill in xbel items of all present web views + } + return priv->proxy_xbel_folder; +} diff --git a/src/midori-browser.h b/src/midori-browser.h new file mode 100644 index 00000000..1853563c --- /dev/null +++ b/src/midori-browser.h @@ -0,0 +1,90 @@ +/* + Copyright (C) 2008 Christian Dywan + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + See the file COPYING for the full license text. +*/ + +#ifndef __MIDORI_BROWSER_H__ +#define __MIDORI_BROWSER_H__ + +#include + +#include + +G_BEGIN_DECLS + +#define MIDORI_TYPE_BROWSER \ + (midori_browser_get_type ()) +#define MIDORI_BROWSER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), MIDORI_TYPE_BROWSER, MidoriBrowser)) +#define MIDORI_BROWSER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), MIDORI_TYPE_BROWSER, MidoriBrowserClass)) +#define MIDORI_IS_BROWSER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MIDORI_TYPE_BROWSER)) +#define MIDORI_IS_BROWSER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), MIDORI_TYPE_BROWSER)) +#define MIDORI_BROWSER_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), MIDORI_TYPE_BROWSER, MidoriBrowserClass)) + +typedef struct _MidoriBrowser MidoriBrowser; +typedef struct _MidoriBrowserPrivate MidoriBrowserPrivate; +typedef struct _MidoriBrowserClass MidoriBrowserClass; + +struct _MidoriBrowser +{ + GtkWindow parent_instance; + + MidoriBrowserPrivate* priv; +}; + +struct _MidoriBrowserClass +{ + GtkWindowClass parent_class; + + /* Signals */ + void + (*quit) (MidoriBrowser* browser); + void + (*new_window) (MidoriBrowser* browser, + const gchar* uri); +}; + +GType +midori_browser_get_type (void); + +GtkWidget* +midori_browser_new (void); + +gint +midori_browser_append_tab (MidoriBrowser* browser, + GtkWidget* widget); + +void +midori_browser_remove_tab (MidoriBrowser* browser, + GtkWidget* widget); + +gint +midori_browser_append_xbel_item (MidoriBrowser* browser, + KatzeXbelItem* xbel_item); + +gint +midori_browser_append_uri (MidoriBrowser* browser, + const gchar* uri); + +GtkWidget* +midori_browser_get_current_page (MidoriBrowser* browser); + +GtkWidget* +midori_browser_get_current_web_view (MidoriBrowser* browser); + +KatzeXbelItem* +midori_browser_get_proxy_xbel_folder (MidoriBrowser* browser); + +G_END_DECLS + +#endif /* __MIDORI_BROWSER_H__ */ diff --git a/src/midori-panel.c b/src/midori-panel.c new file mode 100644 index 00000000..4ff42779 --- /dev/null +++ b/src/midori-panel.c @@ -0,0 +1,515 @@ +/* + Copyright (C) 2007-2008 Christian Dywan + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + See the file COPYING for the full license text. +*/ + +#include "midori-panel.h" + +#include "sokoke.h" + +G_DEFINE_TYPE (MidoriPanel, midori_panel, GTK_TYPE_HBOX) + +struct _MidoriPanelPrivate +{ + GtkWidget* toolbar; + GtkWidget* toolbar_label; + GtkWidget* frame; + GtkWidget* notebook; + GSList* group; + GtkMenu* menu; +}; + +#define MIDORI_PANEL_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + MIDORI_TYPE_PANEL, MidoriPanelPrivate)) + +enum +{ + PROP_0, + + PROP_SHADOW_TYPE, + PROP_MENU, + PROP_PAGE +}; + +enum { + CLOSE, + SWITCH_PAGE, + + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL]; + +static void +midori_panel_finalize (GObject* object); + +static void +midori_panel_set_property (GObject* object, + guint prop_id, + const GValue* value, + GParamSpec* pspec); + +static void +midori_panel_get_property (GObject* object, + guint prop_id, + GValue* value, + GParamSpec* pspec); + +static gboolean +midori_panel_close_cb (MidoriPanel* panel) +{ + gtk_widget_hide (GTK_WIDGET (panel)); + return FALSE; +} + +static void +midori_cclosure_marshal_BOOLEAN__VOID (GClosure* closure, GValue* return_value, guint n_param_values, const GValue *param_values, gpointer invocation_hint, gpointer marshal_data) +{ + typedef gboolean(*GMarshalFunc_BOOLEAN__VOID) (gpointer data1, + gpointer data2); + register GMarshalFunc_BOOLEAN__VOID callback; + register GCClosure* cc = (GCClosure*) closure; + register gpointer data1, data2; + gboolean v_return; + + g_return_if_fail(return_value != NULL); + g_return_if_fail(n_param_values == 1); + + if (G_CCLOSURE_SWAP_DATA (closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer(param_values + 0); + } + else + { + data1 = g_value_peek_pointer(param_values + 0); + data2 = closure->data; + } + callback = (GMarshalFunc_BOOLEAN__VOID) (marshal_data ? marshal_data : cc->callback); + v_return = callback(data1, data2); + g_value_set_boolean (return_value, v_return); +} + +static void +midori_panel_class_init (MidoriPanelClass* class) +{ + + signals[CLOSE] = g_signal_new ( + "close", + G_TYPE_FROM_CLASS (class), + (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), + G_STRUCT_OFFSET (MidoriPanelClass, close), + g_signal_accumulator_true_handled, + NULL, + midori_cclosure_marshal_BOOLEAN__VOID, + G_TYPE_BOOLEAN, 0); + + signals[SWITCH_PAGE] = g_signal_new ( + "switch-page", + G_TYPE_FROM_CLASS (class), + (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), + G_STRUCT_OFFSET (MidoriPanelClass, switch_page), + 0, + NULL, + g_cclosure_marshal_VOID__INT, + G_TYPE_NONE, 1, + G_TYPE_INT); + + class->close = midori_panel_close_cb; + + GObjectClass* gobject_class = G_OBJECT_CLASS (class); + gobject_class->finalize = midori_panel_finalize; + gobject_class->set_property = midori_panel_set_property; + gobject_class->get_property = midori_panel_get_property; + + GParamFlags flags = G_PARAM_READWRITE | G_PARAM_CONSTRUCT; + + g_object_class_install_property (gobject_class, + PROP_SHADOW_TYPE, + g_param_spec_enum ( + "shadow-type", + "Shadow Type", + "Appearance of the shadow around each panel", + GTK_TYPE_SHADOW_TYPE, + GTK_SHADOW_NONE, + flags)); + + g_object_class_install_property (gobject_class, + PROP_MENU, + g_param_spec_object ( + "menu", + "Menu", + "Menu to hold panel items", + GTK_TYPE_MENU, + G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, + PROP_PAGE, + g_param_spec_int ( + "page", + "Page", + "The index of the current page", + -1, G_MAXINT, -1, + flags)); + + g_type_class_add_private (class, sizeof (MidoriPanelPrivate)); +} + +static void +midori_panel_button_close_clicked_cb (MidoriPanel* panel) +{ + g_signal_emit (panel, signals[CLOSE], 0); +} + +static void +midori_panel_init (MidoriPanel* panel) +{ + panel->priv = MIDORI_PANEL_GET_PRIVATE (panel); + + MidoriPanelPrivate* priv = panel->priv; + + // Create the sidebar + priv->toolbar = gtk_toolbar_new (); + gtk_toolbar_set_style (GTK_TOOLBAR (priv->toolbar), GTK_TOOLBAR_BOTH); + gtk_toolbar_set_icon_size (GTK_TOOLBAR (priv->toolbar), + GTK_ICON_SIZE_BUTTON); + gtk_toolbar_set_orientation (GTK_TOOLBAR (priv->toolbar), + GTK_ORIENTATION_VERTICAL); + gtk_box_pack_start (GTK_BOX (panel), priv->toolbar, FALSE, FALSE, 0); + gtk_widget_show_all (priv->toolbar); + GtkWidget* vbox = gtk_vbox_new (FALSE, 0); + gtk_box_pack_start (GTK_BOX (panel), vbox, TRUE, TRUE, 0); + + // Create the titlebar + GtkWidget* labelbar = gtk_toolbar_new (); + gtk_toolbar_set_icon_size (GTK_TOOLBAR (labelbar), GTK_ICON_SIZE_MENU); + gtk_toolbar_set_style (GTK_TOOLBAR (labelbar), GTK_TOOLBAR_ICONS); + GtkToolItem* toolitem = gtk_tool_item_new (); + gtk_tool_item_set_expand (toolitem, TRUE); + priv->toolbar_label = gtk_label_new (NULL); + gtk_misc_set_alignment (GTK_MISC (priv->toolbar_label), 0, 0.5); + gtk_container_add (GTK_CONTAINER (toolitem), priv->toolbar_label); + gtk_container_set_border_width (GTK_CONTAINER (toolitem), 6); + gtk_toolbar_insert (GTK_TOOLBAR (labelbar), toolitem, -1); + toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_CLOSE); + gtk_tool_button_set_label (GTK_TOOL_BUTTON (toolitem), "Close panel"); + sokoke_tool_item_set_tooltip_text (GTK_TOOL_ITEM (toolitem), "Close panel"); + g_signal_connect (toolitem, "clicked", + G_CALLBACK (midori_panel_button_close_clicked_cb), panel); + gtk_toolbar_insert (GTK_TOOLBAR (labelbar), toolitem, -1); + gtk_box_pack_start (GTK_BOX (vbox), labelbar, FALSE, FALSE, 0); + gtk_widget_show_all (vbox); + + // Create the notebook + priv->notebook = gtk_notebook_new (); + gtk_notebook_set_show_border (GTK_NOTEBOOK (priv->notebook), FALSE); + gtk_notebook_set_show_tabs (GTK_NOTEBOOK (priv->notebook), FALSE); + priv->frame = gtk_frame_new (NULL); + gtk_container_add (GTK_CONTAINER (priv->frame), priv->notebook); + gtk_box_pack_start (GTK_BOX (vbox), priv->frame, TRUE, TRUE, 0); + gtk_widget_show_all (priv->frame); +} + +static void +midori_panel_finalize (GObject* object) +{ + MidoriPanel* panel = MIDORI_PANEL (object); + MidoriPanelPrivate* priv = panel->priv; + + if (priv->menu) + { + // FIXME: Remove all menu items + } + + G_OBJECT_CLASS (midori_panel_parent_class)->finalize (object); +} + +static void +midori_panel_set_property (GObject* object, + guint prop_id, + const GValue* value, + GParamSpec* pspec) +{ + MidoriPanel* panel = MIDORI_PANEL (object); + MidoriPanelPrivate* priv = panel->priv; + + switch (prop_id) + { + case PROP_SHADOW_TYPE: + gtk_frame_set_shadow_type (GTK_FRAME (priv->frame), + g_value_get_enum (value)); + break; + case PROP_MENU: + katze_object_assign (priv->menu, g_value_get_object (value)); + // FIXME: Move existing items to the new menu + break; + case PROP_PAGE: + gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), + g_value_get_int (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +midori_panel_get_property (GObject* object, + guint prop_id, + GValue* value, + GParamSpec* pspec) +{ + MidoriPanel* panel = MIDORI_PANEL (object); + MidoriPanelPrivate* priv = panel->priv; + + switch (prop_id) + { + case PROP_SHADOW_TYPE: + g_value_set_enum (value, + gtk_frame_get_shadow_type (GTK_FRAME (priv->frame))); + break; + case PROP_MENU: + g_value_set_object (value, priv->menu); + break; + case PROP_PAGE: + g_value_set_int (value, + gtk_notebook_get_current_page (GTK_NOTEBOOK (priv->notebook))); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/** + * midori_panel_new: + * + * Creates a new empty panel. + * + * Return value: a new #MidoriPanel + **/ +GtkWidget* +midori_panel_new (void) +{ + MidoriPanel* panel = g_object_new (MIDORI_TYPE_PANEL, + NULL); + + return GTK_WIDGET (panel); +} + +static void +midori_panel_menu_item_activate_cb (GtkWidget* widget, + MidoriPanel* panel) +{ + GtkWidget* child = g_object_get_data (G_OBJECT (widget), "page"); + guint n = midori_panel_page_num (panel, child); + midori_panel_set_current_page (panel, n); + g_signal_emit (panel, signals[SWITCH_PAGE], 0, n); +} + +/** + * midori_panel_append_page: + * @panel: a #MidoriPanel + * @child: the child widget + * @icon: a stock ID or icon name, or %NULL + * @label: a string to use as the label, or %NULL + * + * Appends a new page to the panel. + * + * If @icon is an icon name, the according image is used as an + * icon for this page. + * + * If @label is given, it is used as the label of this page. + * + * In the case of an error, -1 is returned. + * + * Return value: the index of the new page, or -1 + **/ +gint +midori_panel_append_page (MidoriPanel* panel, + GtkWidget* child, + const gchar* icon, + const gchar* label) +{ + g_return_val_if_fail (MIDORI_IS_PANEL (panel), -1); + g_return_val_if_fail (GTK_IS_WIDGET (child), -1); + + MidoriPanelPrivate* priv = panel->priv; + + GtkWidget* scrolled = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + GTK_WIDGET_SET_FLAGS (scrolled, GTK_CAN_FOCUS); + gtk_widget_show (scrolled); + GtkWidget* widget; + GObjectClass* gobject_class = G_OBJECT_GET_CLASS (child); + if (GTK_WIDGET_CLASS (gobject_class)->set_scroll_adjustments_signal) + widget = child; + else + { + widget = gtk_viewport_new (NULL, NULL); + gtk_widget_show (widget); + gtk_container_add (GTK_CONTAINER (widget), child); + } + gtk_container_add (GTK_CONTAINER (scrolled), widget); + gtk_container_add (GTK_CONTAINER (priv->notebook), scrolled); + + guint n = midori_panel_page_num (panel, child); + + const gchar* text = label ? label : "Untitled"; + + GtkWidget* image; + GtkToolItem* toolitem = gtk_radio_tool_button_new (priv->group); + priv->group = gtk_radio_tool_button_get_group (GTK_RADIO_TOOL_BUTTON ( + toolitem)); + gtk_tool_button_set_label (GTK_TOOL_BUTTON (toolitem), text); + if (icon) + { + image = gtk_image_new_from_icon_name (icon, GTK_ICON_SIZE_BUTTON); + gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (toolitem), image); + } + g_object_set_data (G_OBJECT (toolitem), "page", child); + g_signal_connect (toolitem, "clicked", + G_CALLBACK (midori_panel_menu_item_activate_cb), panel); + gtk_widget_show_all (GTK_WIDGET (toolitem)); + gtk_toolbar_insert (GTK_TOOLBAR (priv->toolbar), toolitem, -1); + + if (priv->menu) + { + GtkWidget* menuitem = gtk_image_menu_item_new_with_label (text); + if (icon) + { + image = gtk_image_new_from_icon_name (icon, GTK_ICON_SIZE_MENU); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), + image); + } + gtk_widget_show_all (menuitem); + g_object_set_data (G_OBJECT (menuitem), "page", child); + g_signal_connect (menuitem, "activate", + G_CALLBACK (midori_panel_menu_item_activate_cb), + panel); + gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu), menuitem); + } + + return n; +} + +/** + * midori_panel_get_current_page: + * @panel: a #MidoriPanel + * + * Retrieves the index of the currently selected page. + * + * If @panel has no children, -1 is returned. + * + * Return value: the index of the current page, or -1 + **/ +gint +midori_panel_get_current_page (MidoriPanel* panel) +{ + g_return_val_if_fail (MIDORI_IS_PANEL (panel), -1); + + MidoriPanelPrivate* priv = panel->priv; + + return gtk_notebook_get_current_page (GTK_NOTEBOOK (priv->notebook)); +} + +/** + * midori_panel_get_nth_page: + * @panel: a #MidoriPanel + * + * Retrieves the child widget of the nth page. + * + * If @panel has no children, -1 is returned. + * + * Return value: the child widget of the new page, or -1 + **/ +GtkWidget* +midori_panel_get_nth_page (MidoriPanel* panel, + guint page_num) +{ + g_return_val_if_fail (MIDORI_IS_PANEL (panel), NULL); + + MidoriPanelPrivate* priv = panel->priv; + + return gtk_notebook_get_nth_page (GTK_NOTEBOOK (priv->notebook), page_num); +} + +/** + * midori_panel_get_n_pages: + * @panel: a #MidoriPanel + * + * Retrieves the number of pages contained in the panel. + * + * Return value: the number of pages + **/ +guint +midori_panel_get_n_pages (MidoriPanel* panel) +{ + g_return_val_if_fail (MIDORI_IS_PANEL (panel), 0); + + MidoriPanelPrivate* priv = panel->priv; + + return gtk_notebook_get_n_pages (GTK_NOTEBOOK (priv->notebook)); +} + +static GtkWidget* +_midori_panel_scrolled_for_child (MidoriPanel* panel, + GtkWidget* child) +{ + GtkWidget* scrolled = gtk_widget_get_parent (GTK_WIDGET (child)); + if (GTK_IS_VIEWPORT (scrolled)) + scrolled = gtk_widget_get_parent (scrolled); + return scrolled; +} + +/** + * midori_panel_page_num: + * @panel: a #MidoriPanel + * + * Retrieves the index of the page associated to @widget. + * + * If @panel has no children, -1 is returned. + * + * Return value: the index of page associated to @widget, or -1 + **/ +gint +midori_panel_page_num (MidoriPanel* panel, + GtkWidget* child) +{ + g_return_val_if_fail (MIDORI_IS_PANEL (panel), -1); + + MidoriPanelPrivate* priv = panel->priv; + + GtkWidget* scrolled = _midori_panel_scrolled_for_child (panel, child); + return gtk_notebook_page_num (GTK_NOTEBOOK (priv->notebook), scrolled); +} + +/** + * midori_panel_set_current_page: + * @panel: a #MidoriPanel + * @n: index of the page to switch to, or -1 to mean the last page + * + * Switches to the page with the given index. + * + * The child must be visible, otherwise the underlying GtkNotebook will + * silently ignore the attempt to switch the page. + **/ +void +midori_panel_set_current_page (MidoriPanel* panel, + gint n) +{ + g_return_if_fail (MIDORI_IS_PANEL (panel)); + + MidoriPanelPrivate* priv = panel->priv; + + gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), n); +} diff --git a/src/midori-panel.h b/src/midori-panel.h new file mode 100644 index 00000000..c4772039 --- /dev/null +++ b/src/midori-panel.h @@ -0,0 +1,90 @@ +/* + Copyright (C) 2008 Christian Dywan + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + See the file COPYING for the full license text. +*/ + +#ifndef __MIDORI_PANEL_H__ +#define __MIDORI_PANEL_H__ + +#include + +#include + +G_BEGIN_DECLS + +#define MIDORI_TYPE_PANEL \ + (midori_panel_get_type ()) +#define MIDORI_PANEL(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), MIDORI_TYPE_PANEL, MidoriPanel)) +#define MIDORI_PANEL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), MIDORI_TYPE_PANEL, MidoriPanelClass)) +#define MIDORI_IS_PANEL(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MIDORI_TYPE_PANEL)) +#define MIDORI_IS_PANEL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), MIDORI_TYPE_PANEL)) +#define MIDORI_PANEL_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), MIDORI_TYPE_PANEL, MidoriPanelClass)) + +typedef struct _MidoriPanel MidoriPanel; +typedef struct _MidoriPanelPrivate MidoriPanelPrivate; +typedef struct _MidoriPanelClass MidoriPanelClass; + +struct _MidoriPanel +{ + GtkFrame parent_instance; + + MidoriPanelPrivate* priv; +}; + +struct _MidoriPanelClass +{ + GtkFrameClass parent_class; + + /* Signals */ + gboolean + (*close) (MidoriPanel* panel); + + void + (*switch_page) (MidoriPanel* panel, + gint page); +}; + +GType +midori_panel_get_type (void); + +GtkWidget* +midori_panel_new (void); + +gint +midori_panel_append_page (MidoriPanel* panel, + GtkWidget* child, + const gchar* icon, + const gchar* label); + +gint +midori_panel_get_current_page (MidoriPanel* panel); + +GtkWidget* +midori_panel_get_nth_page (MidoriPanel* panel, + guint page_num); + +guint +midori_panel_get_n_pages (MidoriPanel* panel); + +gint +midori_panel_page_num (MidoriPanel* panel, + GtkWidget* child); + +void +midori_panel_set_current_page (MidoriPanel* panel, + gint n); + +G_END_DECLS + +#endif /* __MIDORI_PANEL_H__ */ diff --git a/src/midori-trash.c b/src/midori-trash.c new file mode 100644 index 00000000..d3f8f6a6 --- /dev/null +++ b/src/midori-trash.c @@ -0,0 +1,327 @@ +/* + Copyright (C) 2008 Christian Dywan + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + See the file COPYING for the full license text. +*/ + +#include "midori-trash.h" + +#include "sokoke.h" + +G_DEFINE_TYPE (MidoriTrash, midori_trash, G_TYPE_OBJECT) + +struct _MidoriTrashPrivate +{ + guint limit; + KatzeXbelItem* xbel_folder; +}; + +#define MIDORI_TRASH_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + MIDORI_TYPE_TRASH, MidoriTrashPrivate)) + +enum +{ + PROP_0, + + PROP_LIMIT +}; + +enum { + INSERTED, + REMOVED, + + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL]; + +static void +midori_trash_finalize (GObject* object); + +static void +midori_trash_set_property (GObject* object, + guint prop_id, + const GValue* value, + GParamSpec* pspec); + +static void +midori_trash_get_property (GObject* object, + guint prop_id, + GValue* value, + GParamSpec* pspec); + +static void +midori_trash_class_init (MidoriTrashClass* class) +{ + signals[INSERTED] = g_signal_new( + "inserted", + G_TYPE_FROM_CLASS(class), + (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), + G_STRUCT_OFFSET (MidoriTrashClass, inserted), + 0, + NULL, + g_cclosure_marshal_VOID__UINT, + G_TYPE_NONE, 1, + G_TYPE_UINT); + + signals[REMOVED] = g_signal_new( + "removed", + G_TYPE_FROM_CLASS(class), + (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), + G_STRUCT_OFFSET (MidoriTrashClass, removed), + 0, + NULL, + g_cclosure_marshal_VOID__UINT, + G_TYPE_NONE, 1, + G_TYPE_UINT); + + GObjectClass* gobject_class = G_OBJECT_CLASS (class); + gobject_class->finalize = midori_trash_finalize; + gobject_class->set_property = midori_trash_set_property; + gobject_class->get_property = midori_trash_get_property; + + GParamFlags flags = G_PARAM_READWRITE | G_PARAM_CONSTRUCT; + + g_object_class_install_property (gobject_class, + PROP_LIMIT, + g_param_spec_uint ( + "limit", + "Limit", + "The maximum number of items", + 0, G_MAXUINT, 10, + flags)); + + g_type_class_add_private (class, sizeof (MidoriTrashPrivate)); +} + + + +static void +midori_trash_init (MidoriTrash* trash) +{ + trash->priv = MIDORI_TRASH_GET_PRIVATE (trash); + + MidoriTrashPrivate* priv = trash->priv; + + priv->xbel_folder = katze_xbel_folder_new (); +} + +static void +midori_trash_finalize (GObject* object) +{ + MidoriTrash* trash = MIDORI_TRASH (object); + MidoriTrashPrivate* priv = trash->priv; + + katze_xbel_item_unref (priv->xbel_folder); + + G_OBJECT_CLASS (midori_trash_parent_class)->finalize (object); +} + +static void +midori_trash_set_property (GObject* object, + guint prop_id, + const GValue* value, + GParamSpec* pspec) +{ + MidoriTrash* trash = MIDORI_TRASH (object); + MidoriTrashPrivate* priv = trash->priv; + + switch (prop_id) + { + case PROP_LIMIT: + priv->limit = g_value_get_uint (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +midori_trash_get_property (GObject* object, + guint prop_id, + GValue* value, + GParamSpec* pspec) +{ + MidoriTrash* trash = MIDORI_TRASH (object); + MidoriTrashPrivate* priv = trash->priv; + + switch (prop_id) + { + case PROP_LIMIT: + g_value_set_uint (value, priv->limit); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/** + * midori_trash_new: + * @limit: the maximum number of items + * + * Creates a new #MidoriTrash that can contain a specified number of items, + * meaning that each additional item will replace the oldest existing item. + * + * The value 0 for @limit actually means that there is no limit. + * + * You will typically want to assign this to a #MidoriBrowser. + * + * Return value: a new #MidoriTrash + **/ +MidoriTrash* +midori_trash_new (guint limit) +{ + MidoriTrash* trash = g_object_new (MIDORI_TYPE_TRASH, + "limit", limit, + NULL); + + return trash; +} + +/** + * midori_trash_is_empty: + * @trash: a #MidoriTrash + * + * Determines whether the @trash contains no items. + * + * Return value: %TRUE if there are no items, %FALSE otherwise + **/ +gboolean +midori_trash_is_empty (MidoriTrash* trash) +{ + g_return_val_if_fail (MIDORI_IS_TRASH (trash), FALSE); + + MidoriTrashPrivate* priv = trash->priv; + + return katze_xbel_folder_is_empty (priv->xbel_folder); +} + +/** + * midori_trash_get_n_items: + * @trash: a #MidoriTrash + * + * Determines the number of items in @trash. + * + * Return value: the current number of items + **/ +guint +midori_trash_get_n_items (MidoriTrash* trash) +{ + g_return_val_if_fail (MIDORI_IS_TRASH (trash), 0); + + MidoriTrashPrivate* priv = trash->priv; + + return katze_xbel_folder_get_n_items (priv->xbel_folder); +} + +/** + * midori_trash_get_nth_xbel_item: + * @trash: a #MidoriTrash + * @n: the index of an item + * + * Retrieve an item contained in @trash by its index. + * + * Note that you mustn't unref this item. + * + * Return value: the index at the given index or %NULL + **/ +KatzeXbelItem* +midori_trash_get_nth_xbel_item (MidoriTrash* trash, + guint n) +{ + g_return_val_if_fail (MIDORI_IS_TRASH (trash), 0); + + MidoriTrashPrivate* priv = trash->priv; + + return katze_xbel_folder_get_nth_item (priv->xbel_folder, n); +} + +/** + * midori_trash_prepend_xbel_item: + * @trash: a #MidoriTrash + * @xbel_item: a #KatzeXbelItem + * + * Prepends a #KatzeXbelItem to @trash. + * + * The item is copied. If there is a limit set, the oldest item is + * removed automatically. + * + * Return value: %TRUE if there are no items, %FALSE otherwise + **/ +void +midori_trash_prepend_xbel_item (MidoriTrash* trash, + KatzeXbelItem* xbel_item) +{ + g_return_if_fail (MIDORI_IS_TRASH (trash)); + + MidoriTrashPrivate* priv = trash->priv; + + KatzeXbelItem* copy = katze_xbel_item_copy (xbel_item); + katze_xbel_folder_prepend_item (priv->xbel_folder, copy); + g_signal_emit (trash, signals[INSERTED], 0, 0); + guint n = katze_xbel_folder_get_n_items (priv->xbel_folder); + if (n > 10) + { + KatzeXbelItem* item = katze_xbel_folder_get_nth_item (priv->xbel_folder, + n - 1); + g_signal_emit (trash, signals[REMOVED], 0, n - 1); + katze_xbel_item_unref (item); + } +} + +/** + * midori_trash_remove_nth_item: + * @trash: a #MidoriTrash + * @n: the index of an item + * + * Removes the item at the specified position from @trash. + * + * Nothing happens if the function fails. + **/ +void +midori_trash_remove_nth_item (MidoriTrash* trash, + guint n) +{ + g_return_if_fail (MIDORI_IS_TRASH (trash)); + + MidoriTrashPrivate* priv = trash->priv; + + KatzeXbelItem* item = katze_xbel_folder_get_nth_item (priv->xbel_folder, n); + if (!n) + return; + katze_xbel_folder_remove_item (priv->xbel_folder, item); + g_signal_emit (trash, signals[REMOVED], 0, n); + katze_xbel_item_unref (item); +} + +/** + * midori_trash_empty: + * @trash: a #MidoriTrash + * + * Deletes all items currently contained in @trash. + **/ +void +midori_trash_empty (MidoriTrash* trash) +{ + g_return_if_fail (MIDORI_IS_TRASH (trash)); + + MidoriTrashPrivate* priv = trash->priv; + + guint n = katze_xbel_folder_get_n_items (priv->xbel_folder); + guint i; + for (i = 0; i < n; i++) + { + KatzeXbelItem* item = katze_xbel_folder_get_nth_item (priv->xbel_folder, + i); + g_signal_emit (trash, signals[REMOVED], 0, i); + katze_xbel_item_unref (item); + } +} diff --git a/src/midori-trash.h b/src/midori-trash.h new file mode 100644 index 00000000..bc711792 --- /dev/null +++ b/src/midori-trash.h @@ -0,0 +1,85 @@ +/* + Copyright (C) 2008 Christian Dywan + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + See the file COPYING for the full license text. +*/ + +#ifndef __MIDORI_TRASH_H__ +#define __MIDORI_TRASH_H__ + +#include + +G_BEGIN_DECLS + +#define MIDORI_TYPE_TRASH \ + (midori_trash_get_type ()) +#define MIDORI_TRASH(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), MIDORI_TYPE_TRASH, MidoriTrash)) +#define MIDORI_TRASH_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), MIDORI_TYPE_TRASH, MidoriTrashClass)) +#define MIDORI_IS_TRASH(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MIDORI_TYPE_TRASH)) +#define MIDORI_IS_TRASH_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), MIDORI_TYPE_TRASH)) +#define MIDORI_TRASH_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), MIDORI_TYPE_TRASH, MidoriTrashClass)) + +typedef struct _MidoriTrash MidoriTrash; +typedef struct _MidoriTrashPrivate MidoriTrashPrivate; +typedef struct _MidoriTrashClass MidoriTrashClass; + +struct _MidoriTrash +{ + GObject parent_instance; + + MidoriTrashPrivate* priv; +}; + +struct _MidoriTrashClass +{ + GObjectClass parent_class; + + /* Signals */ + void + (*inserted) (MidoriTrash* trash, + guint n); + void + (*removed) (MidoriTrash* trash, + guint n); +}; + +GType +midori_trash_get_type (void); + +MidoriTrash* +midori_trash_new (guint limit); + +gboolean +midori_trash_is_empty (MidoriTrash* trash); + +guint +midori_trash_get_n_items (MidoriTrash* trash); + +KatzeXbelItem* +midori_trash_get_nth_xbel_item (MidoriTrash* trash, + guint n); + +void +midori_trash_prepend_xbel_item (MidoriTrash* trash, + KatzeXbelItem* xbel_item); + +void +midori_trash_remove_nth_item (MidoriTrash* trash, + guint n); + +void +midori_trash_empty (MidoriTrash* trash); + +G_END_DECLS + +#endif /* __MIDORI_TRASH_H__ */ diff --git a/src/midori-websettings.c b/src/midori-websettings.c new file mode 100644 index 00000000..0fd34ebd --- /dev/null +++ b/src/midori-websettings.c @@ -0,0 +1,200 @@ +/* + Copyright (C) 2008 Christian Dywan + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + See the file COPYING for the full license text. +*/ + +#include "midori-webview.h" + +#include "sokoke.h" + +G_DEFINE_TYPE (MidoriWebSettings, midori_web_settings, WEBKIT_TYPE_WEB_SETTINGS) + +struct _MidoriWebSettingsPrivate +{ + gint tab_label_size; + gboolean close_button; + gboolean middle_click_goto; +}; + +#define MIDORI_WEB_SETTINGS_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + MIDORI_TYPE_WEB_SETTINGS, MidoriWebSettingsPrivate)) + +enum +{ + PROP_0, + + PROP_TAB_LABEL_SIZE, + PROP_CLOSE_BUTTON, + PROP_MIDDLE_CLICK_GOTO +}; + +static void +midori_web_settings_finalize (GObject* object); + +static void +midori_web_settings_set_property (GObject* object, + guint prop_id, + const GValue* value, + GParamSpec* pspec); + +static void +midori_web_settings_get_property (GObject* object, + guint prop_id, + GValue* value, + GParamSpec* pspec); + +static void +midori_web_settings_class_init (MidoriWebSettingsClass* class) +{ + GObjectClass* gobject_class = G_OBJECT_CLASS (class); + gobject_class->finalize = midori_web_settings_finalize; + gobject_class->set_property = midori_web_settings_set_property; + gobject_class->get_property = midori_web_settings_get_property; + + GParamFlags flags = G_PARAM_READWRITE | G_PARAM_CONSTRUCT; + + g_object_class_install_property (gobject_class, + PROP_TAB_LABEL_SIZE, + g_param_spec_int ( + "tab-label-size", + "Tab Label Size", + "The desired tab label size", + 0, G_MAXINT, 10, + flags)); + + g_object_class_install_property (gobject_class, + PROP_CLOSE_BUTTON, + g_param_spec_boolean ( + "close-button", + "Close Button", + "Whether the associated tab has a close button", + FALSE, + flags)); + + g_object_class_install_property (gobject_class, + PROP_MIDDLE_CLICK_GOTO, + g_param_spec_boolean ( + "middle-click-goto", + "Middle Click Goto", + "Load an uri from the selection via middle click", + FALSE, + flags)); + + g_type_class_add_private (class, sizeof (MidoriWebSettingsPrivate)); +} + + + +static void +midori_web_settings_init (MidoriWebSettings* web_settings) +{ + web_settings->priv = MIDORI_WEB_SETTINGS_GET_PRIVATE (web_settings); +} + +static void +midori_web_settings_finalize (GObject* object) +{ + G_OBJECT_CLASS (midori_web_settings_parent_class)->finalize (object); +} + +static void +midori_web_settings_set_property (GObject* object, + guint prop_id, + const GValue* value, + GParamSpec* pspec) +{ + MidoriWebSettings* web_settings = MIDORI_WEB_SETTINGS (object); + MidoriWebSettingsPrivate* priv = web_settings->priv; + + switch (prop_id) + { + case PROP_TAB_LABEL_SIZE: + priv->tab_label_size = g_value_get_int (value); + break; + case PROP_CLOSE_BUTTON: + priv->close_button = g_value_get_boolean (value); + break; + case PROP_MIDDLE_CLICK_GOTO: + priv->middle_click_goto = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +midori_web_settings_get_property (GObject* object, + guint prop_id, + GValue* value, + GParamSpec* pspec) +{ + MidoriWebSettings* web_settings = MIDORI_WEB_SETTINGS (object); + MidoriWebSettingsPrivate* priv = web_settings->priv; + + switch (prop_id) + { + case PROP_TAB_LABEL_SIZE: + g_value_set_int (value, priv->tab_label_size); + break; + case PROP_CLOSE_BUTTON: + g_value_set_boolean (value, priv->close_button); + break; + case PROP_MIDDLE_CLICK_GOTO: + g_value_set_boolean (value, priv->middle_click_goto); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/** + * midori_web_settings_new: + * + * Creates a new #MidoriWebSettings instance with default values. + * + * You will typically want to assign this to a #MidoriWebView or #MidoriBrowser. + * + * Return value: a new #MidoriWebSettings + **/ +MidoriWebSettings* +midori_web_settings_new (void) +{ + MidoriWebSettings* web_settings = g_object_new (MIDORI_TYPE_WEB_SETTINGS, + NULL); + + return web_settings; +} + +/** + * midori_web_settings_copy: + * + * Copies an existing #MidoriWebSettings instance. + * + * Return value: a new #MidoriWebSettings + **/ +MidoriWebSettings* +midori_web_settings_copy (MidoriWebSettings* web_settings) +{ + g_return_val_if_fail (MIDORI_IS_WEB_SETTINGS (web_settings), NULL); + + MidoriWebSettingsPrivate* priv = web_settings->priv; + + MidoriWebSettings* copy; + copy = MIDORI_WEB_SETTINGS (webkit_web_settings_copy (WEBKIT_WEB_SETTINGS (web_settings))); + g_object_set (copy, + "tab-label-size", priv->tab_label_size, + "close-button", priv->close_button, + "middle-click-goto", priv->middle_click_goto, + NULL); + + return copy; +} diff --git a/src/midori-websettings.h b/src/midori-websettings.h new file mode 100644 index 00000000..8ea40206 --- /dev/null +++ b/src/midori-websettings.h @@ -0,0 +1,89 @@ +/* + Copyright (C) 2008 Christian Dywan + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + See the file COPYING for the full license text. +*/ + +#ifndef __MIDORI_WEB_SETTINGS_H__ +#define __MIDORI_WEB_SETTINGS_H__ + +#include + +#include + +G_BEGIN_DECLS + +#define MIDORI_TYPE_WEB_SETTINGS \ + (midori_web_settings_get_type ()) +#define MIDORI_WEB_SETTINGS(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), MIDORI_TYPE_WEB_SETTINGS, MidoriWebSettings)) +#define MIDORI_WEB_SETTINGS_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), MIDORI_TYPE_WEB_SETTINGS, MidoriWebSettingsClass)) +#define MIDORI_IS_WEB_SETTINGS(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MIDORI_TYPE_WEB_SETTINGS)) +#define MIDORI_IS_WEB_SETTINGS_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), MIDORI_TYPE_WEB_SETTINGS)) +#define MIDORI_WEB_SETTINGS_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), MIDORI_TYPE_WEB_SETTINGS, MidoriWebSettingsClass)) + +typedef struct _MidoriWebSettings MidoriWebSettings; +typedef struct _MidoriWebSettingsPrivate MidoriWebSettingsPrivate; +typedef struct _MidoriWebSettingsClass MidoriWebSettingsClass; + +struct _MidoriWebSettings +{ + WebKitWebSettings parent_instance; + + MidoriWebSettingsPrivate* priv; +}; + +struct _MidoriWebSettingsClass +{ + WebKitWebSettingsClass parent_class; + + /* Signals */ + void + (*progress_started) (MidoriWebSettings* web_settings, + guint progress); + void + (*progress_changed) (MidoriWebSettings* web_settings, + guint progress); + void + (*progress_done) (MidoriWebSettings* web_settings, + guint progress); + void + (*load_done) (MidoriWebSettings* web_settings, + WebKitWebFrame* frame); + void + (*statusbar_text_changed) (MidoriWebSettings* web_settings, + const gchar* text); + void + (*element_motion) (MidoriWebSettings* web_settings, + const gchar* link_uri); + void + (*close) (MidoriWebSettings* web_settings); + void + (*new_tab) (MidoriWebSettings* web_settings, + const gchar* uri); + void + (*new_window) (MidoriWebSettings* web_settings, + const gchar* uri); +}; + +GType +midori_web_settings_get_type (void); + +MidoriWebSettings* +midori_web_settings_new (void); + +MidoriWebSettings* +midori_web_settings_copy (MidoriWebSettings* web_settings); + +G_END_DECLS + +#endif /* __MIDORI_WEB_SETTINGS_H__ */ diff --git a/src/midori-webview.c b/src/midori-webview.c new file mode 100644 index 00000000..60f33492 --- /dev/null +++ b/src/midori-webview.c @@ -0,0 +1,1039 @@ +/* + Copyright (C) 2007-2008 Christian Dywan + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + See the file COPYING for the full license text. +*/ + +#include "midori-webview.h" + +#include "sokoke.h" + +#include +#include + +G_DEFINE_TYPE (MidoriWebView, midori_web_view, WEBKIT_TYPE_WEB_VIEW) + +struct _MidoriWebViewPrivate +{ + GtkWidget* tab_icon; + GtkWidget* tab_label; + GtkWidget* tab_close; + GdkPixbuf* icon; + gchar* uri; + gchar* title; + gboolean is_loading; + gint progress; + gchar* statusbar_text; + gchar* link_uri; + + gint tab_label_size; + gboolean close_button; + gboolean middle_click_goto; + MidoriWebSettings* settings; + + GtkWidget* proxy_menu_item; + GtkWidget* proxy_tab_label; + KatzeXbelItem* proxy_xbel_item; +}; + +#define MIDORI_WEB_VIEW_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + MIDORI_TYPE_WEB_VIEW, MidoriWebViewPrivate)) + +enum +{ + PROP_0, + + PROP_ICON, + PROP_URI, + PROP_TITLE, + PROP_STATUSBAR_TEXT, + PROP_SETTINGS +}; + +enum { + LOAD_STARTED, + PROGRESS_STARTED, + PROGRESS_CHANGED, + PROGRESS_DONE, + LOAD_DONE, + ELEMENT_MOTION, + CLOSE, + NEW_TAB, + NEW_WINDOW, + + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL]; + +static void +midori_web_view_finalize (GObject* object); + +static void +midori_web_view_set_property (GObject* object, + guint prop_id, + const GValue* value, + GParamSpec* pspec); + +static void +midori_web_view_get_property (GObject* object, + guint prop_id, + GValue* value, + GParamSpec* pspec); + +/*static WebKitWebView* +midori_web_view_create_web_view (WebKitWebView* web_view) +{ + MidoriWebView* new_web_view = NULL; + g_signal_emit (web_view, signals[NEW_WINDOW], 0, &new_web_view); + if (new_web_view) + return WEBKIT_WEB_VIEW (new_web_view); + return WEBKIT_WEB_VIEW (midori_web_view_new ()); +}*/ + +static void +midori_web_view_class_init (MidoriWebViewClass* class) +{ + signals[PROGRESS_STARTED] = g_signal_new ( + "progress-started", + G_TYPE_FROM_CLASS(class), + (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), + G_STRUCT_OFFSET (MidoriWebViewClass, progress_started), + 0, + NULL, + g_cclosure_marshal_VOID__INT, + G_TYPE_NONE, 1, + G_TYPE_INT); + + signals[PROGRESS_CHANGED] = g_signal_new ( + "progress-changed", + G_TYPE_FROM_CLASS(class), + (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), + G_STRUCT_OFFSET (MidoriWebViewClass, progress_changed), + 0, + NULL, + g_cclosure_marshal_VOID__INT, + G_TYPE_NONE, 1, + G_TYPE_INT); + + signals[PROGRESS_DONE] = g_signal_new ( + "progress-done", + G_TYPE_FROM_CLASS(class), + (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), + G_STRUCT_OFFSET (MidoriWebViewClass, progress_done), + 0, + NULL, + g_cclosure_marshal_VOID__INT, + G_TYPE_NONE, 1, + G_TYPE_INT); + + signals[LOAD_DONE] = g_signal_new ( + "load-done", + G_TYPE_FROM_CLASS(class), + (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), + G_STRUCT_OFFSET (MidoriWebViewClass, load_done), + 0, + NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + WEBKIT_TYPE_WEB_FRAME); + + signals[ELEMENT_MOTION] = g_signal_new( + "element-motion", + G_TYPE_FROM_CLASS(class), + (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), + G_STRUCT_OFFSET (MidoriWebViewClass, element_motion), + 0, + NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, + G_TYPE_STRING); + + signals[CLOSE] = g_signal_new( + "close", + G_TYPE_FROM_CLASS(class), + (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), + G_STRUCT_OFFSET (MidoriWebViewClass, close), + 0, + NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + signals[NEW_TAB] = g_signal_new( + "new-tab", + G_TYPE_FROM_CLASS(class), + (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), + G_STRUCT_OFFSET (MidoriWebViewClass, new_tab), + 0, + NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + signals[NEW_WINDOW] = g_signal_new( + "new-window", + G_TYPE_FROM_CLASS(class), + (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), + G_STRUCT_OFFSET (MidoriWebViewClass, new_window), + 0, + NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, + G_TYPE_STRING); + + /*WEBKIT_WEB_VIEW_CLASS (class)->create_web_view = g_signal_new ("create-web-view", + G_TYPE_FROM_CLASS(class), + (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), + G_STRUCT_OFFSET(MidoriWebViewClass, create_web_view), + 0, + NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + MIDORI_TYPE_WEB_VIEW);*/ + + GObjectClass* gobject_class = G_OBJECT_CLASS (class); + gobject_class->finalize = midori_web_view_finalize; + gobject_class->set_property = midori_web_view_set_property; + gobject_class->get_property = midori_web_view_get_property; + + GParamFlags flags = G_PARAM_READWRITE | G_PARAM_CONSTRUCT; + + g_object_class_install_property (gobject_class, + PROP_ICON, + g_param_spec_object ( + "icon", + "Icon", + "The icon of the loaded page", + GDK_TYPE_PIXBUF, + G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, + PROP_URI, + g_param_spec_string ( + "uri", + "Uri", + "The current uri of the loaded page", + "about:blank", + flags)); + + g_object_class_install_property (gobject_class, + PROP_TITLE, + g_param_spec_string ( + "title", + "Title", + "The current title of the loaded page", + NULL, + flags)); + + g_object_class_install_property (gobject_class, + PROP_STATUSBAR_TEXT, + g_param_spec_string ( + "statusbar-text", + "Statusbar Text", + "The text that is displayed in the statusbar", + "", + flags)); + + g_object_class_install_property (gobject_class, + PROP_SETTINGS, + g_param_spec_object ( + "settings", + "Settings", + "The associated settings", + MIDORI_TYPE_WEB_SETTINGS, + G_PARAM_READWRITE)); + + g_type_class_add_private (class, sizeof (MidoriWebViewPrivate)); +} + +/*static void +webkit_web_view_load_started (MidoriWebView* web_view, + WebKitWebFrame* web_frame) +{ + MidoriWebViewPrivate* priv = web_view->priv; + + priv->is_loading = TRUE; + priv->progress = -1; + katze_throbber_set_animated(KATZE_THROBBER(priv->tab_icon), TRUE); +}*/ + +static void +_midori_web_view_set_uri (MidoriWebView* web_view, + const gchar* uri) +{ + MidoriWebViewPrivate* priv = web_view->priv; + + katze_assign (priv->uri, g_strdup (uri)); + if (priv->proxy_xbel_item) + { + const gchar* uri = midori_web_view_get_display_uri (web_view); + katze_xbel_bookmark_set_href (priv->proxy_xbel_item, uri); + } + g_object_set (web_view, "title", NULL, NULL); +} + +static void +webkit_web_view_load_committed (MidoriWebView* web_view, + WebKitWebFrame* web_frame) +{ + MidoriWebViewPrivate* priv = web_view->priv; + + priv->progress = 0; + const gchar* uri = webkit_web_frame_get_uri (web_frame); + _midori_web_view_set_uri (web_view, uri); +} + +static void +webkit_web_view_load_started (MidoriWebView* web_view, + WebKitWebFrame* web_frame) +{ + MidoriWebViewPrivate* priv = web_view->priv; + + // FIXME: This is a hack, until signals are fixed upstream + priv->is_loading = TRUE; + if (priv->tab_icon) + katze_throbber_set_animated (KATZE_THROBBER (priv->tab_icon), TRUE); + + priv->progress = 0; + g_signal_emit (web_view, signals[PROGRESS_STARTED], 0, priv->progress); +} + +static void +webkit_web_view_progress_changed (MidoriWebView* web_view, gint progress) +{ + MidoriWebViewPrivate* priv = web_view->priv; + + priv->progress = progress; + g_signal_emit (web_view, signals[PROGRESS_CHANGED], 0, priv->progress); +} + +static void +webkit_web_view_load_finished (MidoriWebView* web_view) +{ + MidoriWebViewPrivate* priv = web_view->priv; + + priv->progress = 100; + g_signal_emit (web_view, signals[PROGRESS_DONE], 0, priv->progress); +} + +static void +webkit_web_frame_load_done (WebKitWebFrame* web_frame, gboolean success, + MidoriWebView* web_view) +{ + MidoriWebViewPrivate* priv = web_view->priv; + + priv->is_loading = FALSE; + priv->progress = -1; + if (priv->tab_icon) + katze_throbber_set_animated (KATZE_THROBBER (priv->tab_icon), FALSE); + g_signal_emit (web_view, signals[LOAD_DONE], 0, web_frame); +} + +static void +webkit_web_view_title_changed (MidoriWebView* web_view, + WebKitWebFrame* web_frame, const gchar* title) +{ + g_object_set (web_view, "title", title, NULL); +} + +static void +webkit_web_view_statusbar_text_changed (MidoriWebView* web_view, + const gchar* text) +{ + g_object_set (web_view, "statusbar-text", text, NULL); +} + +static void +webkit_web_view_hovering_over_link (MidoriWebView* web_view, + const gchar* tooltip, + const gchar* link_uri) +{ + MidoriWebViewPrivate* priv = web_view->priv; + + katze_assign (priv->link_uri, g_strdup (link_uri)); + g_signal_emit (web_view, signals[ELEMENT_MOTION], 0, link_uri); +} + +static gboolean +gtk_widget_button_press_event (MidoriWebView* web_view, + GdkEventButton* event) +{ + MidoriWebViewPrivate* priv = web_view->priv; + + GdkModifierType state = (GdkModifierType)0; + gint x, y; + gdk_window_get_pointer (NULL, &x, &y, &state); + switch (event->button) + { + case 1: + if (!priv->link_uri) + return FALSE; + if (state & GDK_SHIFT_MASK) + { + // Open link in new window + g_signal_emit (web_view, signals[NEW_WINDOW], 0, priv->link_uri); + return TRUE; + } + else if(state & GDK_MOD1_MASK) + { + // Open link in new tab + g_signal_emit (web_view, signals[NEW_TAB], 0, priv->link_uri); + return TRUE; + } + break; + case 2: + if (state & GDK_CONTROL_MASK) + { + // FIXME: Reset font multiplier or zoom level + return TRUE; + } + else + { + if (!priv->link_uri) + return FALSE; + // Open link in new tab + g_signal_emit (web_view, signals[NEW_TAB], 0, priv->link_uri); + return TRUE; + } + break; + case 3: + return FALSE; + } + return FALSE; +} + +static gboolean +gtk_widget_button_press_event_after (MidoriWebView* web_view, + GdkEventButton* event) +{ + MidoriWebViewPrivate* priv = web_view->priv; + + if (event->button == 2 && priv->middle_click_goto) + { + GtkClipboard* clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY); + gchar* uri = gtk_clipboard_wait_for_text (clipboard); + if (uri && strchr (uri, '.') && !strchr (uri, ' ')) + { + g_object_set (web_view, "uri", uri, NULL); + g_free (uri); + return TRUE; + } + } + return FALSE; +} + +static gboolean +gtk_widget_scroll_event (MidoriWebView* web_view, + GdkEventScroll* event) +{ + GdkModifierType state = (GdkModifierType)0; + gint x, y; + gdk_window_get_pointer (NULL, &x, &y, &state); + if (state & GDK_CONTROL_MASK) + { + // FIXME: Increase or decrease the font multiplier or zoom level + if (event->direction == GDK_SCROLL_DOWN) + ; + else if(event->direction == GDK_SCROLL_UP) + ; + return TRUE; + } + else + return FALSE; +} + +static void +midori_web_view_menu_new_tab_activate (GtkWidget* action, + MidoriBrowser* browser) +{ + // FIXME: Open a new tab and load the uri +} + +static void +webkit_web_view_populate_popup_cb (GtkWidget* web_view, + GtkWidget* menu) +{ + const gchar* uri = midori_web_view_get_link_uri (MIDORI_WEB_VIEW (web_view)); + if (uri) + { + // new tab + } + + if (webkit_web_view_has_selection (WEBKIT_WEB_VIEW (web_view))) + { + // selected uri in tab + } +} + +static void +_midori_web_view_update_tab_label_size (MidoriWebView* web_view) +{ + MidoriWebViewPrivate* priv = web_view->priv; + + if (priv->tab_label) + { + if (priv->tab_label_size > -1) + { + gint width, height; + sokoke_widget_get_text_size (priv->tab_label, "M", + &width, &height); + gtk_widget_set_size_request (priv->tab_label, + width * priv->tab_label_size, -1); + gtk_label_set_ellipsize (GTK_LABEL (priv->tab_label), + PANGO_ELLIPSIZE_END); + } + else + { + gtk_widget_set_size_request (priv->tab_label, -1, -1); + gtk_label_set_ellipsize (GTK_LABEL (priv->tab_label), + PANGO_ELLIPSIZE_NONE); + } + } +} + +static void +_midori_web_view_update_settings (MidoriWebView* web_view) +{ + MidoriWebViewPrivate* priv = web_view->priv; + + g_object_get (G_OBJECT (priv->settings), + "tab-label-size", &priv->tab_label_size, + "close-button", &priv->close_button, + "middle-click-goto", &priv->middle_click_goto, + NULL); +} + +static void +midori_web_view_settings_notify (MidoriWebSettings* web_settings, + GParamSpec* pspec, + MidoriWebView* web_view) +{ + MidoriWebViewPrivate* priv = web_view->priv; + + const gchar* name = g_intern_string (pspec->name); + GValue value = {0, }; + g_value_init (&value, pspec->value_type); + g_object_get_property (G_OBJECT (priv->settings), name, &value); + + if (name == g_intern_string ("tab-label-size")) + { + priv->tab_label_size = g_value_get_int (&value); + _midori_web_view_update_tab_label_size (web_view); + } + else if (name == g_intern_string ("close-button")) + { + priv->close_button = g_value_get_boolean (&value); + if (priv->tab_close) + sokoke_widget_set_visible (priv->tab_close, priv->close_button); + } + else if (name == g_intern_string ("middle-click-goto")) + priv->middle_click_goto = g_value_get_boolean (&value); + else if (!g_object_class_find_property (G_OBJECT_GET_CLASS (web_settings), + name)) + g_warning("Unexpected setting '%s'", name); + g_value_unset(&value); +} + +static void +midori_web_view_init (MidoriWebView* web_view) +{ + web_view->priv = MIDORI_WEB_VIEW_GET_PRIVATE (web_view); + + MidoriWebViewPrivate* priv = web_view->priv; + priv->is_loading = FALSE; + priv->progress = -1; + + priv->settings = midori_web_settings_new (); + _midori_web_view_update_settings (web_view); + g_signal_connect (priv->settings, "notify", + G_CALLBACK(midori_web_view_settings_notify), web_view); + + WebKitWebFrame* web_frame; + web_frame = webkit_web_view_get_main_frame (WEBKIT_WEB_VIEW (web_view)); + + g_object_connect (web_view, + //"signal::load-started", + //webkit_web_view_load_started, NULL, + "signal::load-committed", + webkit_web_view_load_committed, NULL, + "signal::load-started", + webkit_web_view_load_started, NULL, + "signal::load-progress-changed", + webkit_web_view_progress_changed, NULL, + "signal::load-finished", + webkit_web_view_load_finished, NULL, + //"signal::load-done", + //webkit_web_view_load_done, NULL, + "signal::title-changed", + webkit_web_view_title_changed, NULL, + "signal::status-bar-text-changed", + webkit_web_view_statusbar_text_changed, NULL, + "signal::hovering-over-link", + webkit_web_view_hovering_over_link, NULL, + "signal::button-press-event", + gtk_widget_button_press_event, NULL, + "signal_after::button-press-event", + gtk_widget_button_press_event_after, NULL, + "signal::scroll-event", + gtk_widget_scroll_event, NULL, + "signal::populate-popup", + webkit_web_view_populate_popup_cb, browser, + NULL); + g_object_connect (web_frame, + "signal::load-done", + webkit_web_frame_load_done, web_view, + NULL); +} + +static void +midori_web_view_finalize (GObject* object) +{ + MidoriWebView* web_view = MIDORI_WEB_VIEW (object); + MidoriWebViewPrivate* priv = web_view->priv; + + if (priv->icon) + g_object_unref (priv->icon); + g_free (priv->uri); + g_free (priv->title); + g_free (priv->statusbar_text); + g_free (priv->link_uri); + + if (priv->proxy_menu_item) + gtk_widget_destroy (priv->proxy_menu_item); + if (priv->proxy_xbel_item) + katze_xbel_item_unref (priv->proxy_xbel_item); + + if (priv->settings) + g_object_unref (priv->settings); + + G_OBJECT_CLASS (midori_web_view_parent_class)->finalize (object); +} + +static void +midori_web_view_set_property (GObject* object, + guint prop_id, + const GValue* value, + GParamSpec* pspec) +{ + MidoriWebView* web_view = MIDORI_WEB_VIEW (object); + MidoriWebViewPrivate* priv = web_view->priv; + + switch (prop_id) + { + case PROP_ICON: + katze_object_assign (priv->icon, g_value_get_object (value)); + g_object_ref (priv->icon); + if (priv->tab_icon) + katze_throbber_set_static_pixbuf (KATZE_THROBBER (priv->tab_icon), + priv->icon); + break; + case PROP_URI: + // FIXME: Autocomplete the uri + webkit_web_view_open (WEBKIT_WEB_VIEW (web_view), + g_value_get_string (value)); + break; + case PROP_TITLE: + katze_assign (priv->title, g_value_dup_string (value)); + const gchar* title = midori_web_view_get_display_title (web_view); + if (priv->tab_label) + { + gtk_label_set_text (GTK_LABEL (priv->tab_label), title); + sokoke_widget_set_tooltip_text (priv->tab_label, title); + } + if (priv->proxy_menu_item) + gtk_label_set_text (GTK_LABEL (gtk_bin_get_child (GTK_BIN ( + priv->proxy_menu_item))), title); + if (priv->proxy_xbel_item) + katze_xbel_item_set_title (priv->proxy_xbel_item, title); + break; + case PROP_STATUSBAR_TEXT: + katze_assign (priv->statusbar_text, g_value_dup_string (value)); + break; + case PROP_SETTINGS: + g_signal_handlers_disconnect_by_func (priv->settings, + midori_web_view_settings_notify, + web_view); + katze_object_assign (priv->settings, g_value_get_object (value)); + g_object_ref (priv->settings); + _midori_web_view_update_settings (web_view); + g_signal_connect (priv->settings, "notify", + G_CALLBACK (midori_web_view_settings_notify), web_view); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +midori_web_view_get_property (GObject* object, + guint prop_id, + GValue* value, + GParamSpec* pspec) +{ + MidoriWebView* web_view = MIDORI_WEB_VIEW (object); + MidoriWebViewPrivate* priv = web_view->priv; + + switch (prop_id) + { + case PROP_ICON: + g_value_set_object (value, priv->icon); + break; + case PROP_URI: + g_value_set_string (value, priv->uri); + break; + case PROP_TITLE: + g_value_set_string (value, priv->title); + break; + case PROP_STATUSBAR_TEXT: + g_value_set_string (value, priv->statusbar_text); + break; + case PROP_SETTINGS: + g_value_set_object (value, priv->settings); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/** + * midori_web_view_new: + * + * Creates a new web view widget. + * + * Return value: a new #MidoriWebView + **/ +GtkWidget* +midori_web_view_new (void) +{ + MidoriWebView* web_view = g_object_new (MIDORI_TYPE_WEB_VIEW, + NULL); + + return GTK_WIDGET (web_view); +} + +/** + * midori_web_view_get_proxy_menu_item: + * @web_view: a #MidoriWebView + * + * Retrieves a proxy menu item that is typically added to a Window menu + * and which on activation switches to the right window/ tab. + * + * The item is created on the first call and will be updated to reflect + * changes to the icon and title automatically. + * + * Note: The item is only valid as the web view is embedded in a #GtkNotebook. + * + * Return value: the proxy #GtkMenuItem or %NULL + **/ +GtkWidget* +midori_web_view_get_proxy_menu_item (MidoriWebView* web_view) +{ + g_return_val_if_fail (MIDORI_IS_WEB_VIEW (web_view), FALSE); + + MidoriWebViewPrivate* priv = web_view->priv; + + if (!priv->proxy_menu_item) + { + const gchar* title = midori_web_view_get_display_title (web_view); + GtkWidget* menu_item = gtk_image_menu_item_new_with_label (title); + GtkWidget* icon = gtk_image_new_from_stock (GTK_STOCK_FILE, + GTK_ICON_SIZE_MENU); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item), icon); + + priv->proxy_menu_item = menu_item; + } + return priv->proxy_menu_item; +} + +/** + * midori_web_view_get_proxy_tab_icon: + * @web_view: a #MidoriWebView + * + * Retrieves a proxy tab icon that is typically used in a tab label. + * + * The icon is created on the first call and will be updated to reflect + * loading progress and changes of the actual icon. + * + * Note: If a proxy tab label has been created before, this represents + * the existing icon used in the label. + * + * Return value: the proxy #GtkImage + **/ +GtkWidget* +midori_web_view_get_proxy_tab_icon (MidoriWebView* web_view) +{ + g_return_val_if_fail (MIDORI_IS_WEB_VIEW (web_view), NULL); + + MidoriWebViewPrivate* priv = web_view->priv; + + if (!priv->tab_icon) + { + priv->tab_icon = katze_throbber_new (); + katze_throbber_set_pixbuf (KATZE_THROBBER(priv->tab_icon), priv->icon); + } + return priv->tab_icon; +} + +static gboolean +midori_web_view_tab_label_button_release_event (GtkWidget* tab_label, + GdkEventButton* event, + MidoriWebView* web_view) +{ + MidoriWebViewPrivate* priv = web_view->priv; + + if (event->button == 1 && event->type == GDK_2BUTTON_PRESS) + { + // Toggle the label visibility on double click + GtkWidget* child = gtk_bin_get_child (GTK_BIN (tab_label)); + GList* children = gtk_container_get_children (GTK_CONTAINER (child)); + child = (GtkWidget*)g_list_nth_data (children, 1); + gboolean visible = gtk_widget_get_child_visible (GTK_WIDGET (child)); + gtk_widget_set_child_visible (GTK_WIDGET (child), !visible); + gint width, height; + sokoke_widget_get_text_size(tab_label, "M", &width, &height); + gtk_widget_set_size_request (child, !visible + ? width * priv->tab_label_size : 0, !visible ? -1 : 0); + g_list_free (children); + return TRUE; + } + else if (event->button == 2) + { + // Close the web view on middle click + g_signal_emit (web_view, signals[CLOSE], 0); + return TRUE; + } + + return FALSE; +} + +static void +midori_web_view_tab_close_style_set (GtkWidget* tab_close, + GtkStyle* previous_style, + MidoriWebView* web_view) +{ + GtkSettings* gtk_settings = gtk_widget_get_settings (tab_close); + gint width, height; + gtk_icon_size_lookup_for_settings (gtk_settings, GTK_ICON_SIZE_BUTTON, + &width, &height); + gtk_widget_set_size_request (tab_close, width + 2, height + 2); +} + +static void +midori_web_view_tab_close_clicked (GtkWidget* tab_close, + MidoriWebView* web_view) +{ + g_signal_emit (web_view, signals[CLOSE], 0); +} + +/** + * midori_web_view_get_proxy_tab_label: + * @web_view: a #MidoriWebView + * + * Retrieves a proxy tab label that is typically used as the label of + * a #GtkNotebook page. + * + * The label is created on the first call and will be updated to reflect + * changes to the icon and title automatically. + * + * The icon embedded in the label will reflect the loading status of the + * web view. + * + * Note: This fails if a proxy tab icon has been created already. + * + * Return value: the proxy #GtkEventBox + **/ +GtkWidget* +midori_web_view_get_proxy_tab_label (MidoriWebView* web_view) +{ + g_return_val_if_fail (MIDORI_IS_WEB_VIEW (web_view), NULL); + + MidoriWebViewPrivate* priv = web_view->priv; + + GtkWidget* proxy_tab_icon = priv->tab_icon; + g_return_val_if_fail (!proxy_tab_icon, NULL); + + if (!priv->proxy_tab_label) + { + priv->tab_icon = katze_throbber_new (); + katze_throbber_set_pixbuf (KATZE_THROBBER(priv->tab_icon), priv->icon); + + GtkWidget* event_box = gtk_event_box_new (); + gtk_event_box_set_visible_window(GTK_EVENT_BOX (event_box), FALSE); + GtkWidget* hbox = gtk_hbox_new (FALSE, 1); + gtk_container_add (GTK_CONTAINER (event_box), GTK_WIDGET (hbox)); + gtk_box_pack_start (GTK_BOX (hbox), priv->tab_icon, FALSE, FALSE, 0); + const gchar* title = midori_web_view_get_display_title (web_view); + priv->tab_label = gtk_label_new (title); + gtk_misc_set_alignment (GTK_MISC (priv->tab_label), 0.0, 0.5); + // TODO: make the tab initially look "unvisited" until it's focused + gtk_box_pack_start (GTK_BOX (hbox), priv->tab_label, FALSE, FALSE, 0); + priv->proxy_tab_label = event_box; + _midori_web_view_update_tab_label_size (web_view); + + GtkWidget* close_button = gtk_button_new (); + gtk_button_set_relief (GTK_BUTTON (close_button), GTK_RELIEF_NONE); + gtk_button_set_focus_on_click (GTK_BUTTON (close_button), FALSE); + GtkRcStyle* rcstyle = gtk_rc_style_new (); + rcstyle->xthickness = rcstyle->ythickness = 0; + gtk_widget_modify_style(close_button, rcstyle); + GtkWidget* image = gtk_image_new_from_stock (GTK_STOCK_CLOSE, + GTK_ICON_SIZE_MENU); + gtk_button_set_image (GTK_BUTTON(close_button), image); + gtk_box_pack_start (GTK_BOX (hbox), close_button, FALSE, FALSE, 0); + gtk_widget_show_all (GTK_WIDGET (event_box)); + if (!priv->close_button) + gtk_widget_hide (close_button); + priv->tab_close = close_button; + + g_signal_connect(priv->proxy_tab_label, "button-release-event", + G_CALLBACK(midori_web_view_tab_label_button_release_event), + web_view); + g_signal_connect(priv->tab_close, "style-set", + G_CALLBACK(midori_web_view_tab_close_style_set), + web_view); + g_signal_connect(priv->tab_close, "clicked", + G_CALLBACK(midori_web_view_tab_close_clicked), + web_view); + } + return priv->proxy_tab_label; +} + +/** + * midori_web_view_get_proxy_xbel_item: + * @web_view: a #MidoriWebView + * + * Retrieves a proxy xbel item that can be used for bookmark storage as + * well as session management. + * + * The item is created on the first call and will be updated to reflect + * changes to the title and href automatically. + * + * Note: Currently the item is always a bookmark, but this might change + * in the future. + * + * Return value: the proxy #KatzeXbelItem + **/ +KatzeXbelItem* +midori_web_view_get_proxy_xbel_item (MidoriWebView* web_view) +{ + g_return_val_if_fail (MIDORI_IS_WEB_VIEW (web_view), NULL); + + MidoriWebViewPrivate* priv = web_view->priv; + + if (!priv->proxy_xbel_item) + { + priv->proxy_xbel_item = katze_xbel_bookmark_new (); + const gchar* uri = midori_web_view_get_display_uri (web_view); + katze_xbel_bookmark_set_href (priv->proxy_xbel_item, uri); + const gchar* title = midori_web_view_get_display_title (web_view); + katze_xbel_item_set_title (priv->proxy_xbel_item, title); + } + return priv->proxy_xbel_item; +} + +/** + * midori_web_view_is_loading: + * @web_view: a #MidoriWebView + * + * Determines whether currently a page is being loaded or not. + * + * Return value: %TRUE if a page is being loaded, %FALSE otherwise + **/ +gint +midori_web_view_is_loading (MidoriWebView* web_view) +{ + g_return_val_if_fail (MIDORI_IS_WEB_VIEW (web_view), -1); + + MidoriWebViewPrivate* priv = web_view->priv; + return priv->is_loading; +} + +/** + * midori_web_view_get_progress: + * @web_view: a #MidoriWebView + * + * Retrieves the current loading progress in percent or -1 if no data + * has been loaded so far. + * + * The value is undefined if no loading is in progress. + * + * Return value: the current loading progress or -1 + **/ +gint +midori_web_view_get_progress (MidoriWebView* web_view) +{ + g_return_val_if_fail (MIDORI_IS_WEB_VIEW (web_view), -1); + + MidoriWebViewPrivate* priv = web_view->priv; + return priv->progress; +} + +/** + * midori_web_view_get_uri: + * @web_view: a #MidoriWebView + * + * Retrieves a string that is suitable for displaying, particularly an + * empty uri is represented as "about:blank". + * + * You can assume that the string is not %NULL. + * + * Return value: an uri string + **/ +const gchar* +midori_web_view_get_display_uri (MidoriWebView* web_view) +{ + g_return_val_if_fail (MIDORI_IS_WEB_VIEW (web_view), "about:blank"); + + MidoriWebViewPrivate* priv = web_view->priv; + return priv->uri ? priv->uri : "about:blank"; +} + +/** + * midori_web_view_get_display_title: + * @web_view: a #MidoriWebView + * + * Retrieves a string that is suitable for displaying as a title. Most of the + * time this will be the title or the current uri. + * + * You can assume that the string is not %NULL. + * + * Return value: a title string + **/ +const gchar* +midori_web_view_get_display_title (MidoriWebView* web_view) +{ + g_return_val_if_fail (MIDORI_IS_WEB_VIEW (web_view), "about:blank"); + + MidoriWebViewPrivate* priv = web_view->priv; + + if (priv->title) + return priv->title; + if (priv->uri) + return priv->uri; + return "about:blank"; +} + +/** + * midori_web_view_get_link_uri: + * @web_view: a #MidoriWebView + * + * Retrieves the uri of the currently focused link, particularly while the + * mouse hovers a link or a context menu is being opened. + * + * Return value: an uri string, or %NULL if there is no link focussed + **/ +const gchar* +midori_web_view_get_link_uri (MidoriWebView* web_view) +{ + g_return_val_if_fail (MIDORI_IS_WEB_VIEW (web_view), NULL); + + MidoriWebViewPrivate* priv = web_view->priv; + return priv->link_uri; +} diff --git a/src/midori-webview.h b/src/midori-webview.h new file mode 100644 index 00000000..5b506218 --- /dev/null +++ b/src/midori-webview.h @@ -0,0 +1,118 @@ +/* + Copyright (C) 2008 Christian Dywan + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + See the file COPYING for the full license text. +*/ + +#ifndef __MIDORI_WEB_VIEW_H__ +#define __MIDORI_WEB_VIEW_H__ + +#include + +#include +#include "midori-websettings.h" + +G_BEGIN_DECLS + +#define MIDORI_TYPE_WEB_VIEW \ + (midori_web_view_get_type ()) +#define MIDORI_WEB_VIEW(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), MIDORI_TYPE_WEB_VIEW, MidoriWebView)) +#define MIDORI_WEB_VIEW_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), MIDORI_TYPE_WEB_VIEW, MidoriWebViewClass)) +#define MIDORI_IS_WEB_VIEW(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MIDORI_TYPE_WEB_VIEW)) +#define MIDORI_IS_WEB_VIEW_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), MIDORI_TYPE_WEB_VIEW)) +#define MIDORI_WEB_VIEW_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), MIDORI_TYPE_WEB_VIEW, MidoriWebViewClass)) + +typedef struct _MidoriWebView MidoriWebView; +typedef struct _MidoriWebViewPrivate MidoriWebViewPrivate; +typedef struct _MidoriWebViewClass MidoriWebViewClass; + +struct _MidoriWebView +{ + WebKitWebView parent_instance; + + MidoriWebViewPrivate* priv; +}; + +struct _MidoriWebViewClass +{ + WebKitWebViewClass parent_class; + + /* Signals */ + void + (*progress_started) (MidoriWebView* web_view, + guint progress); + void + (*progress_changed) (MidoriWebView* web_view, + guint progress); + void + (*progress_done) (MidoriWebView* web_view, + guint progress); + void + (*load_done) (MidoriWebView* web_view, + WebKitWebFrame* frame); + void + (*statusbar_text_changed) (MidoriWebView* web_view, + const gchar* text); + void + (*element_motion) (MidoriWebView* web_view, + const gchar* link_uri); + void + (*close) (MidoriWebView* web_view); + void + (*new_tab) (MidoriWebView* web_view, + const gchar* uri); + void + (*new_window) (MidoriWebView* web_view, + const gchar* uri); + void + (*create_web_view) (MidoriWebView* web_view, + MidoriWebView* new_web_view); +}; + +GType +midori_web_view_get_type (void); + +GtkWidget* +midori_web_view_new (void); + +void +midori_web_view_set_settings (MidoriWebView* web_view, + MidoriWebSettings* web_settings); + +GtkWidget* +midori_web_view_get_proxy_menu_item (MidoriWebView* web_view); + +GtkWidget* +midori_web_view_get_proxy_tab_label (MidoriWebView* web_view); + +KatzeXbelItem* +midori_web_view_get_proxy_xbel_item (MidoriWebView* web_view); + +gboolean +midori_web_view_is_loading (MidoriWebView* web_view); + +gint +midori_web_view_get_progress (MidoriWebView* web_view); + +const gchar* +midori_web_view_get_display_uri (MidoriWebView* web_view); + +const gchar* +midori_web_view_get_display_title (MidoriWebView* web_view); + +const gchar* +midori_web_view_get_link_uri (MidoriWebView* web_view); + +G_END_DECLS + +#endif /* __MIDORI_WEB_VIEW_H__ */ diff --git a/src/prefs.c b/src/prefs.c index d5bcc6d7..e4cd0836 100644 --- a/src/prefs.c +++ b/src/prefs.c @@ -152,62 +152,45 @@ static void on_prefs_userStylesheetUri_file_set(GtkWidget* widget, CPrefs* prefs static void on_prefs_toolbarstyle_changed(GtkWidget* widget, CPrefs* prefs) { config->toolbarStyle = gtk_combo_box_get_active(GTK_COMBO_BOX(widget)); - gtk_toolbar_set_style(GTK_TOOLBAR(prefs->browser->navibar) - , config_to_toolbarstyle(config->toolbarStyle)); + /*gtk_toolbar_set_style(GTK_TOOLBAR(prefs->browser->navibar) + , config_to_toolbarstyle(config->toolbarStyle));*/ } static void on_prefs_toolbarSmall_toggled(GtkWidget* widget, CPrefs* prefs) { config->toolbarSmall = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); - gtk_toolbar_set_icon_size(GTK_TOOLBAR(prefs->browser->navibar) - , config_to_toolbariconsize(config->toolbarSmall)); + /*gtk_toolbar_set_icon_size(GTK_TOOLBAR(prefs->browser->navibar) + , config_to_toolbariconsize(config->toolbarSmall));*/ } static void on_prefs_tabClose_toggled(GtkWidget* widget, CPrefs* prefs) { config->tabClose = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); - GList* items = browsers; - do - { - CBrowser* browser = (CBrowser*)items->data; - sokoke_widget_set_visible(browser->webView_close, config->tabClose); - } - while((items = g_list_next(items))); - g_list_free(items); + g_object_set(webSettings, "close-button", config->tabClose, NULL); } static void on_prefs_tabSize_changed(GtkWidget* widget, CPrefs* prefs) { config->tabSize = gtk_spin_button_get_value(GTK_SPIN_BUTTON(widget)); - gint w, h; - sokoke_widget_get_text_size(prefs->browser->webView_name, "M", &w, &h); - GList* items = browsers; - do - { - CBrowser* browser = (CBrowser*)items->data; - gtk_widget_set_size_request(GTK_WIDGET(browser->webView_name) - , w * config->tabSize, -1); - } - while((items = g_list_next(items))); - g_list_free(items); + g_object_set(webSettings, "tab-label-size", config->tabSize, NULL); } static void on_prefs_toolbarWebSearch_toggled(GtkWidget* widget, CPrefs* prefs) { config->toolbarWebSearch = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); - sokoke_widget_set_visible(prefs->browser->webSearch, config->toolbarWebSearch); + //sokoke_widget_set_visible(prefs->browser->webSearch, config->toolbarWebSearch); } static void on_prefs_toolbarNewTab_toggled(GtkWidget* widget, CPrefs* prefs) { config->toolbarNewTab = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); - sokoke_widget_set_visible(prefs->browser->newTab, config->toolbarNewTab); + //sokoke_widget_set_visible(prefs->browser->newTab, config->toolbarNewTab); } static void on_prefs_toolbarClosedTabs_toggled(GtkWidget* widget, CPrefs* prefs) { config->toolbarClosedTabs = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); - sokoke_widget_set_visible(prefs->browser->closedTabs, config->toolbarClosedTabs); + //sokoke_widget_set_visible(prefs->browser->closedTabs, config->toolbarClosedTabs); } static gboolean on_prefs_locationsearch_focus_out(GtkWidget* widget @@ -233,7 +216,10 @@ static void on_prefs_protocols_render_icon(GtkTreeViewColumn* column gchar* path; if((path = g_find_program_in_path(binary))) { - GtkIconTheme* icon_theme = get_icon_theme(prefs->treeview); + GdkScreen* screen = gtk_widget_get_screen(prefs->treeview); + if(!screen) + screen = gdk_screen_get_default(); + GtkIconTheme* icon_theme = gtk_icon_theme_get_for_screen(screen); if(g_path_is_absolute(binary)) { g_free(path); path = g_path_get_basename(binary); @@ -308,16 +294,14 @@ static void on_prefs_protocols_combobox_changed(GtkWidget* widget, CPrefs* prefs gtk_widget_set_sensitive(prefs->add, command == NULL); } -GtkWidget* prefs_preferences_dialog_new(CBrowser* browser) +GtkWidget* prefs_preferences_dialog_new(MidoriBrowser* browser) { gchar* dialogTitle = g_strdup_printf("%s Preferences", g_get_application_name()); GtkWidget* dialog = gtk_dialog_new_with_buttons(dialogTitle - , GTK_WINDOW(browser->window) + , GTK_WINDOW(browser) , GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR - , GTK_STOCK_HELP - , GTK_RESPONSE_HELP - , GTK_STOCK_CLOSE - , GTK_RESPONSE_CLOSE + , GTK_STOCK_HELP, GTK_RESPONSE_HELP + , GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE , NULL); gtk_window_set_icon_name(GTK_WINDOW(dialog), GTK_STOCK_PREFERENCES); // TODO: Implement some kind of help function @@ -326,7 +310,6 @@ GtkWidget* prefs_preferences_dialog_new(CBrowser* browser) CPrefs* prefs = g_new0(CPrefs, 1); prefs->browser = browser; - //prefs->window = dialog; g_signal_connect(dialog, "response", G_CALLBACK(g_free), prefs); // TODO: Do we want tooltips for explainations or can we omit that? @@ -334,7 +317,7 @@ GtkWidget* prefs_preferences_dialog_new(CBrowser* browser) // TODO: Take multiple windows into account when applying changes GtkWidget* xfce_heading; if((xfce_heading = sokoke_xfce_header_new( - gtk_window_get_icon_name(GTK_WINDOW(browser->window)), dialogTitle))) + gtk_window_get_icon_name(GTK_WINDOW(browser)), dialogTitle))) gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox) , xfce_heading, FALSE, FALSE, 0); g_free(dialogTitle); diff --git a/src/prefs.h b/src/prefs.h index 7576095e..e56d2087 100644 --- a/src/prefs.h +++ b/src/prefs.h @@ -12,7 +12,7 @@ #ifndef __PREFS_H__ #define __PREFS_H__ 1 -#include "browser.h" +#include "midori-browser.h" #include @@ -20,8 +20,7 @@ typedef struct { - CBrowser* browser; - //GtkWidget* window; + MidoriBrowser* browser; GtkWidget* userStylesheetUri; GtkWidget* treeview; GtkWidget* combobox; @@ -38,6 +37,6 @@ enum // -- Declarations GtkWidget* -prefs_preferences_dialog_new(CBrowser*); +prefs_preferences_dialog_new(MidoriBrowser*); #endif /* !__PREFS_H__ */ diff --git a/src/search.c b/src/search.c index a40a10d3..26afcb5e 100644 --- a/src/search.c +++ b/src/search.c @@ -12,7 +12,7 @@ #include "search.h" #include "sokoke.h" -#include "../katze/katze.h" +#include #include #include diff --git a/src/sokoke.c b/src/sokoke.c index ea0c6f49..8bcca67f 100644 --- a/src/sokoke.c +++ b/src/sokoke.c @@ -34,18 +34,6 @@ void sokoke_combo_box_add_strings(GtkComboBox* combobox va_end(args); } -void sokoke_radio_action_set_current_value(GtkRadioAction* action - , gint currentValue) -{ - // Activates the group member with the given value - #if GTK_CHECK_VERSION(2, 10, 0) - gtk_radio_action_set_current_value(action, currentValue); - #else - // TODO: Implement this for older gtk - UNIMPLEMENTED - #endif -} - void sokoke_widget_set_visible(GtkWidget* widget, gboolean visible) { // Show or hide the widget @@ -304,86 +292,3 @@ void sokoke_menu_item_set_accel(GtkMenuItem* menuitem, const gchar* path g_free(accel); } } - -gboolean sokoke_entry_can_undo(GtkEntry* entry) -{ - // TODO: Can we undo the last input? - return FALSE; -} - -gboolean sokoke_entry_can_redo(GtkEntry* entry) -{ - // TODO: Can we redo the last input? - return FALSE; -} - -void sokoke_entry_undo(GtkEntry* entry) -{ - // TODO: Implement undo - UNIMPLEMENTED -} - -void sokoke_entry_redo(GtkEntry* entry) -{ - // TODO: Implement redo - UNIMPLEMENTED -} - -static gboolean sokoke_on_undo_entry_key_down(GtkEntry* widget, GdkEventKey* event - , gpointer userdata) -{ - switch(event->keyval) - { - case GDK_Undo: - sokoke_entry_undo(widget); - return FALSE; - case GDK_Redo: - sokoke_entry_redo(widget); - return FALSE; - default: - return FALSE; - } -} - -static void sokoke_on_undo_entry_populate_popup(GtkEntry* entry, GtkMenu* menu - , gpointer userdata) -{ - // Enhance the entry's menu with undo and redo items. - GtkWidget* menuitem = gtk_separator_menu_item_new(); - gtk_menu_shell_prepend(GTK_MENU_SHELL(menu), menuitem); - gtk_widget_show(menuitem); - menuitem = gtk_image_menu_item_new_from_stock(GTK_STOCK_REDO, NULL); - g_signal_connect(menuitem, "activate", G_CALLBACK(sokoke_entry_redo), userdata); - gtk_widget_set_sensitive(menuitem, sokoke_entry_can_redo(entry)); - gtk_menu_shell_prepend(GTK_MENU_SHELL(menu), menuitem); - gtk_widget_show(menuitem); - menuitem = gtk_image_menu_item_new_from_stock(GTK_STOCK_UNDO, NULL); - g_signal_connect(menuitem, "activate", G_CALLBACK(sokoke_entry_undo), userdata); - gtk_widget_set_sensitive(menuitem, sokoke_entry_can_undo(entry)); - gtk_menu_shell_prepend(GTK_MENU_SHELL(menu), menuitem); - gtk_widget_show(menuitem); -} - -gboolean sokoke_entry_get_can_undo(GtkEntry* entry) -{ - // TODO: Is this entry undo enabled? - return FALSE; -} - -void sokoke_entry_set_can_undo(GtkEntry* entry, gboolean canUndo) -{ - if(canUndo) - { - g_signal_connect(entry, "key-press-event" - , G_CALLBACK(sokoke_on_undo_entry_key_down), NULL); - g_signal_connect(entry, "populate-popup" - , G_CALLBACK(sokoke_on_undo_entry_populate_popup), NULL); - } - else - { - g_signal_handlers_disconnect_by_func(entry - , G_CALLBACK(sokoke_on_undo_entry_key_down), NULL); - g_signal_handlers_disconnect_by_func(entry - , G_CALLBACK(sokoke_on_undo_entry_populate_popup), NULL); - } -} diff --git a/src/sokoke.h b/src/sokoke.h index 995e2481..74e751be 100644 --- a/src/sokoke.h +++ b/src/sokoke.h @@ -20,9 +20,6 @@ void sokoke_combo_box_add_strings(GtkComboBox*, const gchar*, ...); -void -sokoke_radio_action_set_current_value(GtkRadioAction*, gint); - void sokoke_widget_set_visible(GtkWidget*, gboolean); @@ -70,22 +67,4 @@ sokoke_widget_get_text_size(GtkWidget*, const gchar*, gint*, gint*); void sokoke_menu_item_set_accel(GtkMenuItem*, const gchar*, const gchar*, GdkModifierType); -gboolean -sokoke_entry_can_undo(GtkEntry*); - -gboolean -sokoke_entry_can_redo(GtkEntry*); - -void -sokoke_entry_undo(GtkEntry*); - -void -sokoke_entry_redo(GtkEntry*); - -gboolean -sokoke_entry_get_can_undo(GtkEntry*); - -void -sokoke_entry_set_can_undo(GtkEntry*, gboolean); - #endif /* !__SOKOKE_H__ */ diff --git a/src/ui.h b/src/ui.h index 787fdd41..bc5d6a8b 100644 --- a/src/ui.h +++ b/src/ui.h @@ -12,246 +12,4 @@ #ifndef __UI_H__ #define __UI_H__ 1 -// -- Credits - -static const gchar* credits_authors[] = { "Christian Dywan ", NULL }; -static const gchar* credits_documenters/*[]*/ = /*{ */NULL/* }*/; -static const gchar* credits_artists[] = { "Nancy Runge ", NULL }; - -// -- Licenses - -static const gchar* license = - "This library is free software; you can redistribute it and/or\n" - "modify it under the terms of the GNU Lesser General Public\n" - "License as published by the Free Software Foundation; either\n" - "version 2.1 of the License, or (at your option) any later version.\n"; - -// -- User interface description - -static const gchar* ui_markup = - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - // Closed tabs shall be prepended here - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - // Bookmarks shall be appended here - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - // TODO: Insert widgets and custom tools here - "" - "" - "" - "" - "" - "" - "" - "" - "" - // All open tabs shall be appended here - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - ""; - #endif /* !__UI_H__ */ diff --git a/src/webSearch.c b/src/webSearch.c index 8390571c..a7a4d6ae 100644 --- a/src/webSearch.c +++ b/src/webSearch.c @@ -19,12 +19,12 @@ #include #include -void update_searchEngine(guint index, CBrowser* browser) +void update_searchEngine(guint index, GtkWidget* search) { guint n = g_list_length(searchEngines); // Display a default icon in case we have no engines if(!n) - sexy_icon_entry_set_icon(SEXY_ICON_ENTRY(browser->webSearch), SEXY_ICON_ENTRY_PRIMARY + sexy_icon_entry_set_icon(SEXY_ICON_ENTRY(search), SEXY_ICON_ENTRY_PRIMARY , GTK_IMAGE(gtk_image_new_from_stock(GTK_STOCK_FIND, GTK_ICON_SIZE_MENU))); // Change the icon and default text according to the chosen engine else @@ -34,24 +34,24 @@ void update_searchEngine(guint index, CBrowser* browser) index = 0; SearchEngine* engine = (SearchEngine*)g_list_nth_data(searchEngines, index); GdkPixbuf* pixbuf = load_web_icon(search_engine_get_icon(engine) - , GTK_ICON_SIZE_MENU, browser->navibar); - sexy_icon_entry_set_icon(SEXY_ICON_ENTRY(browser->webSearch) + , GTK_ICON_SIZE_MENU, search); + sexy_icon_entry_set_icon(SEXY_ICON_ENTRY(search) , SEXY_ICON_ENTRY_PRIMARY, GTK_IMAGE(gtk_image_new_from_pixbuf(pixbuf))); g_object_unref(pixbuf); - sokoke_entry_set_default_text(GTK_ENTRY(browser->webSearch) + sokoke_entry_set_default_text(GTK_ENTRY(search) , search_engine_get_short_name(engine)); config->searchEngine = index; } } -void on_webSearch_engine_activate(GtkWidget* widget, CBrowser* browser) +void on_webSearch_engine_activate(GtkWidget* widget, MidoriBrowser* browser) { guint index = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(widget), "engine")); - update_searchEngine(index, browser); + update_searchEngine(index, widget); } void on_webSearch_icon_released(GtkWidget* widget, SexyIconEntryPosition* pos - , gint button, CBrowser* browser) + , gint button, MidoriBrowser* browser) { GtkWidget* menu = gtk_menu_new(); guint n = g_list_length(searchEngines); @@ -84,14 +84,14 @@ void on_webSearch_icon_released(GtkWidget* widget, SexyIconEntryPosition* pos gtk_widget_show(menuitem); } - menuitem = gtk_separator_menu_item_new(); + /*menuitem = gtk_separator_menu_item_new(); gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); gtk_widget_show(menuitem); GtkAction* action = gtk_action_group_get_action( browser->actiongroup, "ManageSearchEngines"); menuitem = gtk_action_create_menu_item(action); gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); - gtk_widget_show(menuitem); + gtk_widget_show(menuitem);*/ sokoke_widget_popup(widget, GTK_MENU(menu), NULL); } @@ -299,16 +299,16 @@ static void on_webSearch_remove(GtkWidget* widget, CWebSearch* webSearch) gtk_list_store_remove(GTK_LIST_STORE(liststore), &iter); search_engine_free(searchEngine); searchEngines = g_list_remove(searchEngines, searchEngine); - update_searchEngine(config->searchEngine, webSearch->browser); + //update_searchEngine(config->searchEngine, webSearch->browser); webSearch_toggle_edit_buttons(g_list_nth(searchEngines, 0) != NULL, webSearch); // FIXME: we want to allow undo of some kind } -GtkWidget* webSearch_manageSearchEngines_dialog_new(CBrowser* browser) +GtkWidget* webSearch_manageSearchEngines_dialog_new(MidoriBrowser* browser) { const gchar* dialogTitle = "Manage search engines"; GtkWidget* dialog = gtk_dialog_new_with_buttons(dialogTitle - , GTK_WINDOW(browser->window) + , GTK_WINDOW(browser) , GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR , GTK_STOCK_HELP , GTK_RESPONSE_HELP @@ -394,7 +394,7 @@ GtkWidget* webSearch_manageSearchEngines_dialog_new(CBrowser* browser) return dialog; } -gboolean on_webSearch_key_down(GtkWidget* widget, GdkEventKey* event, CBrowser* browser) +gboolean on_webSearch_key_down(GtkWidget* widget, GdkEventKey* event, MidoriBrowser* browser) { GdkModifierType state = (GdkModifierType)0; gint x, y; gdk_window_get_pointer(NULL, &x, &y, &state); @@ -403,25 +403,25 @@ gboolean on_webSearch_key_down(GtkWidget* widget, GdkEventKey* event, CBrowser* switch(event->keyval) { case GDK_Up: - update_searchEngine(config->searchEngine - 1, browser); + //update_searchEngine(config->searchEngine - 1, browser); return TRUE; case GDK_Down: - update_searchEngine(config->searchEngine + 1, browser); + //update_searchEngine(config->searchEngine + 1, browser); return TRUE; } return FALSE; } -gboolean on_webSearch_scroll(GtkWidget* webView, GdkEventScroll* event, CBrowser* browser) +gboolean on_webSearch_scroll(GtkWidget* webView, GdkEventScroll* event, MidoriBrowser* browser) { if(event->direction == GDK_SCROLL_DOWN) - update_searchEngine(config->searchEngine + 1, browser); + ;//update_searchEngine(config->searchEngine + 1, browser); else if(event->direction == GDK_SCROLL_UP) - update_searchEngine(config->searchEngine - 1, browser); + ;//update_searchEngine(config->searchEngine - 1, browser); return TRUE; } -void on_webSearch_activate(GtkWidget* widget, CBrowser* browser) +void on_webSearch_activate(GtkWidget* widget, MidoriBrowser* browser) { const gchar* keywords = gtk_entry_get_text(GTK_ENTRY(widget)); gchar* url; @@ -436,6 +436,7 @@ void on_webSearch_activate(GtkWidget* widget, CBrowser* browser) else search = g_strconcat(url, " ", keywords, NULL); entry_completion_append(GTK_ENTRY(widget), keywords); - webkit_web_view_open(WEBKIT_WEB_VIEW(get_nth_webView(-1, browser)), search); + GtkWidget* webView = midori_browser_get_current_web_view(browser); + webkit_web_view_open(WEBKIT_WEB_VIEW(webView), search); g_free(search); } diff --git a/src/webSearch.h b/src/webSearch.h index 3cefc395..cefa89be 100644 --- a/src/webSearch.h +++ b/src/webSearch.h @@ -12,7 +12,7 @@ #ifndef __WEBSEARCH_H__ #define __WEBSEARCH_H__ 1 -#include "browser.h" +#include "midori-browser.h" #include #include @@ -22,7 +22,7 @@ typedef struct { - CBrowser* browser; + MidoriBrowser* browser; GtkWidget* window; GtkWidget* treeview; GtkWidget* edit; @@ -38,24 +38,24 @@ enum // -- Declarations void -update_searchEngine(guint, CBrowser*); +update_searchEngine(guint, GtkWidget*); void -on_webSearch_icon_released(GtkWidget*, SexyIconEntryPosition*, gint, CBrowser*); +on_webSearch_icon_released(GtkWidget*, SexyIconEntryPosition*, gint, MidoriBrowser*); void -on_webSearch_engine_activate(GtkWidget*, CBrowser*); +on_webSearch_engine_activate(GtkWidget*, MidoriBrowser*); void -on_webSearch_activate(GtkWidget*, CBrowser*); +on_webSearch_activate(GtkWidget*, MidoriBrowser*); GtkWidget* -webSearch_manageSearchEngines_dialog_new(CBrowser*); +webSearch_manageSearchEngines_dialog_new(MidoriBrowser*); gboolean -on_webSearch_key_down(GtkWidget*, GdkEventKey*, CBrowser*); +on_webSearch_key_down(GtkWidget*, GdkEventKey*, MidoriBrowser*); gboolean -on_webSearch_scroll(GtkWidget*, GdkEventScroll*, CBrowser*); +on_webSearch_scroll(GtkWidget*, GdkEventScroll*, MidoriBrowser*); #endif /* !__WEBSEARCH_H__ */ diff --git a/src/webView.c b/src/webView.c deleted file mode 100644 index be91e220..00000000 --- a/src/webView.c +++ /dev/null @@ -1,376 +0,0 @@ -/* - Copyright (C) 2007-2008 Christian Dywan - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - See the file COPYING for the full license text. -*/ - -#include "webView.h" - -#include "helpers.h" -#include "sokoke.h" -#include "../katze/katze.h" - -#include - -WebKitNavigationResponse on_webView_navigation_requested(GtkWidget* webView - , WebKitWebFrame* frame, WebKitNetworkRequest* networkRequest) -{ - WebKitNavigationResponse response = WEBKIT_NAVIGATION_RESPONSE_ACCEPT; - // TODO: Ask webkit wether it knows the protocol for "unknown protcol" - // TODO: This isn't the place for uri scheme handling - const gchar* uri = webkit_network_request_get_uri(networkRequest); - gchar* protocol = strtok(g_strdup(uri), ":"); - if(spawn_protocol_command(protocol, uri)) - response = WEBKIT_NAVIGATION_RESPONSE_IGNORE; - g_free(protocol); - return response; -} - -void on_webView_title_changed(GtkWidget* webView, WebKitWebFrame* frame - , const gchar* title, CBrowser* browser) -{ - const gchar* newTitle; - if(title) - newTitle = title; - else - newTitle = webkit_web_frame_get_uri(frame); - katze_xbel_item_set_title(browser->sessionItem, newTitle); - gtk_label_set_text(GTK_LABEL(browser->webView_name), newTitle); - sokoke_widget_set_tooltip_text(gtk_widget_get_parent( - gtk_widget_get_parent(browser->webView_name)), newTitle); - gtk_label_set_text(GTK_LABEL(gtk_bin_get_child(GTK_BIN( - browser->webView_menu))), newTitle); - if(webView == get_nth_webView(-1, browser)) - { - gchar* windowTitle = g_strconcat(newTitle, " - ", PACKAGE_NAME, NULL); - gtk_window_set_title(GTK_WINDOW(browser->window), windowTitle); - g_free(windowTitle); - } -} - -void on_webView_icon_changed(GtkWidget* webView, WebKitWebFrame* widget - , CBrowser* browser) -{ - // TODO: Implement icon updates; currently this isn't ever called anyway - const gchar* icon = NULL; - UNIMPLEMENTED - if(icon) - { - gtk_label_set_text(GTK_LABEL(browser->webView_name), "icon"); - gtk_label_set_text(GTK_LABEL(gtk_bin_get_child(GTK_BIN( - browser->webView_menu))), "icon"); - if(webView == get_nth_webView(-1, browser)) - { - gchar* windowTitle = g_strconcat("icon", " - ", PACKAGE_NAME, NULL); - gtk_window_set_title(GTK_WINDOW(browser->window), windowTitle); - g_free(windowTitle); - } - } -} - -void on_webView_load_started(GtkWidget* webView, WebKitWebFrame* widget - , CBrowser* browser) -{ - browser->loadedPercent = 0; - update_favicon(browser); - if(webView == get_nth_webView(-1, browser)) - { - update_gui_state(browser); - update_statusbar(browser); - } -} - -void on_webView_load_committed(GtkWidget* webView, WebKitWebFrame* frame - , CBrowser* browser) -{ - const gchar* uri = webkit_web_frame_get_uri(frame); - gchar* newUri = g_strdup(uri ? uri : ""); - katze_xbel_bookmark_set_href(browser->sessionItem, newUri); - if(webView == get_nth_webView(-1, browser)) - { - gtk_entry_set_text(GTK_ENTRY(browser->location), newUri); - gtk_label_set_text(GTK_LABEL(browser->webView_name), newUri); - katze_assign(browser->statusMessage, NULL); - } -} - -void on_webView_load_changed(GtkWidget* webView, gint progress, CBrowser* browser) -{ - browser->loadedPercent = progress; - if(webView == get_nth_webView(-1, browser)) - update_statusbar(browser); -} - -void on_webView_load_finished(GtkWidget* webView, WebKitWebFrame* widget - , CBrowser* browser) -{ - browser->loadedPercent = -1; - update_favicon(browser); - if(webView == get_nth_webView(-1, browser)) - update_gui_state(browser); -} - -void on_webView_status_message(GtkWidget* webView, const gchar* text, CBrowser* browser) -{ - katze_assign(browser->statusMessage, g_strdup(text)); - update_statusbar(browser); -} - -void on_webView_selection_changed(GtkWidget* webView, CBrowser* browser) -{ - UNIMPLEMENTED -} - -gboolean on_webView_console_message(GtkWidget* webView - , const gchar* message, gint line, const gchar* sourceId, CBrowser* browser) -{ - return FALSE; -} - -void on_webView_link_hover(GtkWidget* webView, const gchar* tooltip - , const gchar* uri, CBrowser* browser) -{ - katze_assign(browser->statusMessage, g_strdup(uri)); - update_statusbar(browser); - katze_assign(browser->elementUri, g_strdup(uri)); -} - -/* -GtkWidget* on_webView_window_open(GtkWidget* webView, const gchar* sUri - , CBrowser* browser) -{ - // A window is created - // TODO: Respect config->iNewPages - // TODO: Find out if this comes from a script or a click - // TODO: Block scripted popups, return NULL and show status icon - CBrowser* newBrowser = browser_new(config->openPopupsInTabs ? browser : NULL); - return newBrowser->webView; -} -*/ - -void webView_popup(GtkWidget* webView, GdkEventButton* event, CBrowser* browser) -{ - gboolean isLink = browser->elementUri != NULL; // Did we right-click a link? - gboolean haveLinks = FALSE; // TODO: Are several links selected? - gboolean isImage = FALSE; // TODO: Did we right-click an image? - gboolean isEditable = webkit_web_view_can_paste_clipboard(WEBKIT_WEB_VIEW(webView)); - gboolean hasSelection = webkit_web_view_has_selection(WEBKIT_WEB_VIEW(webView)); - - update_edit_items(browser); - - // Download manager available? - const gchar* downloadManager = g_datalist_get_data(&config->protocols_commands, "download"); - gboolean canDownload = downloadManager && *downloadManager; - - action_set_visible("LinkTabNew", isLink, browser); - action_set_visible("LinkTabCurrent", isLink, browser); - action_set_visible("LinkWindowNew", isLink, browser); - - action_set_visible("LinkSaveAs", isLink, browser); - action_set_visible("LinkSaveWith", isLink && canDownload, browser); - action_set_visible("LinkCopy", isLink, browser); - action_set_visible("LinkBookmarkNew", isLink, browser); - - action_set_visible("SelectionLinksNewTabs", haveLinks && hasSelection, browser); - action_set_visible("SelectionTextTabNew", haveLinks && hasSelection, browser); - action_set_visible("SelectionTextTabCurrent", haveLinks && hasSelection, browser); - action_set_visible("SelectionTextWindowNew", haveLinks && hasSelection, browser); - - action_set_visible("ImageViewTabNew", isImage, browser); - action_set_visible("ImageViewTabCurrent", isImage, browser); - action_set_visible("ImageSaveAs", isImage, browser); - action_set_visible("ImageSaveWith", isImage && canDownload, browser); - action_set_visible("ImageCopy", isImage, browser); - - action_set_visible("Copy_", hasSelection || isEditable, browser); - action_set_visible("SelectionSearch", hasSelection, browser); - action_set_visible("SelectionSearchWith", hasSelection, browser); - action_set_visible("SelectionSourceView", hasSelection, browser); - - action_set_visible("SourceView", !hasSelection, browser); - - if(isEditable) - sokoke_widget_popup(webView, GTK_MENU(browser->popup_editable), event); - else if(isLink || isImage || hasSelection) - sokoke_widget_popup(webView, GTK_MENU(browser->popup_element), event); - else - sokoke_widget_popup(webView, GTK_MENU(browser->popup_webView), event); -} - -gboolean on_webView_button_press(GtkWidget* webView, GdkEventButton* event - , CBrowser* browser) -{ - GdkModifierType state = (GdkModifierType)0; - gint x, y; - gdk_window_get_pointer(NULL, &x, &y, &state); - switch(event->button) - { - case 1: - if(!browser->elementUri) - return FALSE; - if(state & GDK_SHIFT_MASK) - { - // Open link in new window - CBrowser* curBrowser = browser_new(NULL); - webkit_web_view_open(WEBKIT_WEB_VIEW(curBrowser->webView), browser->elementUri); - return TRUE; - } - else if(state & GDK_MOD1_MASK) - { - // Open link in new tab - CBrowser* curBrowser = browser_new(browser); - webkit_web_view_open(WEBKIT_WEB_VIEW(curBrowser->webView), browser->elementUri); - return TRUE; - } - break; - case 2: - if(state & GDK_CONTROL_MASK) - { - //webkit_web_view_set_text_size(WEBKIT_WEB_VIEW(webView), 1); - return TRUE; - } - else - { - if(!browser->elementUri) - return FALSE; - // Open link in new tab - CBrowser* curBrowser = browser_new(browser); - webkit_web_view_open(WEBKIT_WEB_VIEW(curBrowser->webView), browser->elementUri); - return TRUE; - } - break; - case 3: - webView_popup(webView, event, browser); - return TRUE; - } - return FALSE; -} - -gboolean on_webView_button_press_after(GtkWidget* webView, GdkEventButton* event - , CBrowser* browser) -{ - if(event->button == 2 && config->middleClickGoto) - { - GtkClipboard* clipboard = gtk_clipboard_get(GDK_SELECTION_PRIMARY); - gchar* text = gtk_clipboard_wait_for_text(clipboard); - gchar* uri = NULL; - if(text && strchr(text, '.') && !strchr(text, ' ')) - uri = magic_uri(text, FALSE); - g_free(text); - if(uri) - { - webkit_web_view_open(WEBKIT_WEB_VIEW(browser->webView), uri); - g_free(uri); - return TRUE; - } - } - return FALSE; -} - -void on_webView_popup(GtkWidget* webView, CBrowser* browser) -{ - webView_popup(webView, NULL, browser); -} - -gboolean on_webView_scroll(GtkWidget* webView, GdkEventScroll* event - , CBrowser* browser) -{ - GdkModifierType state = (GdkModifierType)0; - gint x, y; - gdk_window_get_pointer(NULL, &x, &y, &state); - if(state & GDK_CONTROL_MASK) - { - /*const gfloat size = webkit_web_view_get_text_size(WEBKIT_WEB_VIEW(webView)); - if(event->direction == GDK_SCROLL_DOWN) - webkit_web_view_set_text_size(WEBKIT_WEB_VIEW(webView), size + 0.1); - else if(event->direction == GDK_SCROLL_UP) - webView_set_text_size(WEBKIT_WEB_VIEW(webView), size - 0.1);*/ - return TRUE; - } - else - return FALSE; -} - -gboolean on_webView_leave(GtkWidget* webView, GdkEventCrossing* event, CBrowser* browser) -{ - katze_assign(browser->statusMessage, NULL); - update_statusbar(browser); - return TRUE; -} - -void on_webView_destroy(GtkWidget* widget, CBrowser* browser) -{ - // Update browser list, free memory and possibly quit - GList* tmp = g_list_find(browsers, browser); - browsers = g_list_delete_link(browsers, tmp); - g_free(browser->elementUri); - g_free(browser->statusMessage); - // FIXME: Multiple windows are not taken into account - if(!g_list_nth(browsers, 0)) - { - g_object_unref(browser->actiongroup); - g_object_unref(browser->popup_bookmark); - g_object_unref(browser->popup_webView); - g_object_unref(browser->popup_element); - g_object_unref(browser->popup_editable); - guint i; - guint n = katze_xbel_folder_get_n_items(bookmarks); - for(i = 0; i < n; i++) - katze_xbel_item_unref(katze_xbel_folder_get_nth_item(bookmarks, i)); - gtk_main_quit(); - } -} - -// webView actions begin here - -GtkWidget* webView_new(GtkWidget** scrolled) -{ - *scrolled = gtk_scrolled_window_new(NULL, NULL); - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(*scrolled) - , GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - GTK_WIDGET_SET_FLAGS(*scrolled, GTK_CAN_FOCUS); - GtkWidget* webView = webkit_web_view_new(); - gtk_container_add(GTK_CONTAINER(*scrolled), webView); - return webView; -} - -void webView_open(GtkWidget* webView, const gchar* uri) -{ - webkit_web_view_open(WEBKIT_WEB_VIEW(webView), uri); - // We need to check the browser first - // No browser means this is a panel - CBrowser* browser = get_browser_from_webView(webView); - if(browser) - { - katze_xbel_bookmark_set_href(browser->sessionItem, uri); - katze_xbel_item_set_title(browser->sessionItem, ""); - } -} - -void webView_close(GtkWidget* webView, CBrowser* browser) -{ - browser = get_browser_from_webView(webView); - const gchar* uri = katze_xbel_bookmark_get_href(browser->sessionItem); - katze_xbel_folder_remove_item(session, browser->sessionItem); - if(uri && *uri) - { - katze_xbel_folder_prepend_item(tabtrash, browser->sessionItem); - guint n = katze_xbel_folder_get_n_items(tabtrash); - if(n > 10) - { - KatzeXbelItem* item = katze_xbel_folder_get_nth_item(tabtrash, n - 1); - katze_xbel_item_unref(item); - } - } - else - katze_xbel_item_unref(browser->sessionItem); - gtk_widget_destroy(browser->webView_menu); - gtk_notebook_remove_page(GTK_NOTEBOOK(browser->webViews) - , get_webView_index(webView, browser)); - update_browser_actions(browser); -} diff --git a/src/webView.h b/src/webView.h deleted file mode 100644 index 552b571b..00000000 --- a/src/webView.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - Copyright (C) 2007 Christian Dywan - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - See the file COPYING for the full license text. -*/ - -#ifndef __webView_H__ -#define __webView_H__ 1 - -#include -#include "browser.h" -#include "debug.h" - -#include - -WebKitNavigationResponse -on_webView_navigation_requested(GtkWidget* webView, WebKitWebFrame* frame - , WebKitNetworkRequest* networkRequest); - -void -on_webView_title_changed(GtkWidget*, WebKitWebFrame*, const gchar*, CBrowser*); - -void -on_webView_icon_changed(GtkWidget*, WebKitWebFrame*, CBrowser*); - -void -on_webView_load_started(GtkWidget* , WebKitWebFrame*, CBrowser*); - -void -on_webView_load_committed(GtkWidget* , WebKitWebFrame*, CBrowser*); - -void -on_webView_load_changed(GtkWidget*, gint progress, CBrowser*); - -void -on_webView_load_finished(GtkWidget*, WebKitWebFrame*, CBrowser*); - -void -on_webView_status_message(GtkWidget*, const gchar*, CBrowser*); - -void -on_webView_selection_changed(GtkWidget*, CBrowser*); - -gboolean -on_webView_console_message(GtkWidget*, const gchar*, gint, const gchar*, CBrowser*); - -void -on_webView_link_hover(GtkWidget*, const gchar*, const gchar*, CBrowser*); - -/* -GtkWidget* -on_webView_window_open(GtkWidget*, const gchar*, CBrowser*); -*/ - -gboolean -on_webView_button_press(GtkWidget*, GdkEventButton*, CBrowser*); - -gboolean -on_webView_button_press_after(GtkWidget*, GdkEventButton*, CBrowser*); - -void -on_webView_popup(GtkWidget*, CBrowser*); - -gboolean -on_webView_scroll(GtkWidget*, GdkEventScroll*, CBrowser*); - -gboolean -on_webView_leave(GtkWidget*, GdkEventCrossing*, CBrowser*); - -void -on_webView_destroy(GtkWidget*, CBrowser*); - -GtkWidget* -webView_new(GtkWidget**); - -void -webView_open(GtkWidget*, const gchar*); - -void -webView_close(GtkWidget*, CBrowser*); - -#endif /* !__webView_H__ */