#ifdef HAVE_CONFIG_H #include #endif #include #include #include "web2.h" #ifdef HAVE_LIBOWL #include #endif static void quit_cb (GtkWidget *window, Web2Data *data) { g_object_unref (data->header); gtk_main_quit (); } static void back_clicked_cb (GtkButton *button, Web2Data *data) { if (!data->current_page) return; webkit_web_view_go_back (data->current_page); } static void forward_clicked_cb (GtkButton *button, Web2Data *data) { if (!data->current_page) return; webkit_web_view_go_forward (data->current_page); } static void go_toggled_cb (GtkToggleToolButton *button, Web2Data *data) { if (gtk_toggle_tool_button_get_active (button)) { gtk_widget_hide (data->progress_box); gtk_widget_show (data->nav_box); gtk_widget_show (data->header); gtk_widget_grab_focus (data->url_entry); gtk_window_set_default (GTK_WINDOW (data->main_window), data->nav_go_button); } else { if (g_object_get_data (G_OBJECT (data->current_page), "progress")) { gtk_widget_hide (data->nav_box); gtk_widget_show (data->progress_box); gtk_widget_show (data->header); } else { gtk_widget_hide (data->header); } } } static void update_buttons (Web2Data *data) { if (!data->current_page) return; g_object_set (G_OBJECT (data->back_button), "sensitive", webkit_web_view_can_go_back (data->current_page), NULL); g_object_set (G_OBJECT (data->forward_button), "sensitive", webkit_web_view_can_go_forward (data->current_page), NULL); } static void load_started_cb (WebKitWebView *view, WebKitWebFrame *frame, Web2Data *data) { g_object_set_data (G_OBJECT (frame), "loading", GINT_TO_POINTER (1)); if (view == data->current_page) { gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON ( data->go_button), FALSE); gtk_widget_hide (data->nav_box); gtk_widget_show (data->progress_box); gtk_widget_show (data->header); } } static void load_progress_changed_cb (WebKitWebView *view, gint progress, Web2Data *data) { g_object_set_data (G_OBJECT (view), "progress", GINT_TO_POINTER (progress)); if (view == data->current_page) { gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR ( data->progress_bar), (gdouble)progress/100.0); } } static void load_finished_cb (WebKitWebView *view, WebKitWebFrame *frame, Web2Data *data) { g_object_set_data (G_OBJECT (frame), "loading", NULL); g_object_set_data (G_OBJECT (view), "progress", NULL); if (view == data->current_page) { gtk_widget_hide (data->header); gtk_widget_show (data->nav_box); gtk_widget_hide (data->progress_box); } } static void title_changed_cb (WebKitWebFrame *frame, const gchar *title, Web2Data *data) { GtkWidget *label; if (!title) title = "Blank page"; label = g_object_get_data (G_OBJECT (frame), "label"); gtk_label_set_text (GTK_LABEL (label), title); if (webkit_web_frame_get_web_view (frame) == data->current_page) { const gchar * location = webkit_web_frame_get_uri (frame); if (!location) location = ""; gtk_entry_set_text (GTK_ENTRY (data->url_entry), location); gtk_progress_bar_set_text (GTK_PROGRESS_BAR ( data->progress_bar), location); gtk_window_set_title (GTK_WINDOW (data->main_window), title); update_buttons (data); } } static gboolean set_page (Web2Data *data) { gtk_notebook_set_current_page (GTK_NOTEBOOK (data->pages_notebook), gtk_notebook_get_n_pages ( GTK_NOTEBOOK (data->pages_notebook)) - 2); return FALSE; } static void close_clicked_cb (GtkButton *button, Web2Data *data) { gint page = gtk_notebook_page_num (GTK_NOTEBOOK (data->pages_notebook), g_object_get_data (G_OBJECT (button), "child")); if (gtk_notebook_get_n_pages (GTK_NOTEBOOK ( data->pages_notebook)) <= 2) { quit_cb (data->main_window, data); return; } if (gtk_notebook_get_current_page (GTK_NOTEBOOK ( data->pages_notebook)) == page) gtk_notebook_set_current_page (GTK_NOTEBOOK ( data->pages_notebook), page - 1); if (page != -1) gtk_notebook_remove_page ( GTK_NOTEBOOK (data->pages_notebook), page); } static void create_page (Web2Data *data, const gchar *url) { GtkRcStyle *rcstyle; WebKitWebFrame *frame; GtkWidget *page, *scroll, *label, *button, *image, *hbox, *vpaned; label = gtk_label_new ("Empty page"); button = gtk_button_new (); image = gtk_image_new_from_stock (GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU); gtk_button_set_focus_on_click (GTK_BUTTON (button), FALSE); gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE); /* Reduce button padding */ rcstyle = gtk_rc_style_new (); rcstyle->xthickness = 0; rcstyle->ythickness = 0; gtk_widget_modify_style (button, rcstyle); g_object_unref (rcstyle); /* This can make the tabs smaller but is a bit hacky... */ /*gtk_icon_size_lookup_for_settings (gtk_settings_get_default (), GTK_ICON_SIZE_MENU, &width, &height); gtk_widget_set_size_request (button, width + 2, height + 2);*/ gtk_container_add (GTK_CONTAINER (button), image); hbox = gtk_hbox_new (FALSE, 6); gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0); gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0); gtk_widget_show_all (hbox); page = webkit_web_view_new (); frame = webkit_web_view_get_main_frame (WEBKIT_WEB_VIEW (page)); g_object_set_data (G_OBJECT (frame), "label", label); g_signal_connect (frame, "title_changed", G_CALLBACK (title_changed_cb), data); g_signal_connect (page, "load_started", G_CALLBACK (load_started_cb), data); g_signal_connect (page, "load_progress_changed", G_CALLBACK (load_progress_changed_cb), data); g_signal_connect (page, "load_finished", G_CALLBACK (load_finished_cb), data); if (url) webkit_web_view_open (WEBKIT_WEB_VIEW (page), url); scroll = gtk_scrolled_window_new (NULL, NULL); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_container_add (GTK_CONTAINER (scroll), page); vpaned = gtk_vpaned_new (); gtk_paned_pack2 (GTK_PANED (vpaned), scroll, TRUE, FALSE); gtk_widget_show_all (vpaned); g_object_set_data (G_OBJECT (button), "child", vpaned); g_signal_connect (button, "clicked", G_CALLBACK (close_clicked_cb), data); gtk_notebook_insert_page (GTK_NOTEBOOK (data->pages_notebook), vpaned, hbox, gtk_notebook_get_n_pages ( GTK_NOTEBOOK (data->pages_notebook)) - 1); g_idle_add ((GSourceFunc)set_page, data); } static void switch_page_cb (GtkNotebook *book, GtkNotebookPage *page, guint page_num, Web2Data *data) { GtkWidget *container, *vpaned; WebKitWebFrame *frame; if (page_num == gtk_notebook_get_n_pages (book) - 1) { create_page (data, "http://www.google.co.uk/"); return; } if ((container = gtk_widget_get_parent (data->header))) { gtk_container_remove (GTK_CONTAINER (container), data->header); } vpaned = gtk_notebook_get_nth_page (book, page_num); gtk_paned_pack1 (GTK_PANED (vpaned), data->header, FALSE, FALSE); data->current_page = WEBKIT_WEB_VIEW (gtk_bin_get_child (GTK_BIN ( gtk_paned_get_child2 (GTK_PANED (vpaned))))); frame = webkit_web_view_get_main_frame (data->current_page); title_changed_cb (frame, webkit_web_frame_get_title (frame), data); if (g_object_get_data (G_OBJECT (frame), "loading")) { load_progress_changed_cb (data->current_page, GPOINTER_TO_INT (g_object_get_data ( G_OBJECT (data->current_page), "progress")), data); gtk_widget_hide (data->nav_box); gtk_widget_show (data->progress_box); gtk_widget_show (data->header); } else { gtk_widget_hide (data->header); gtk_widget_hide (data->progress_box); gtk_widget_show (data->nav_box); } gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON ( data->go_button), FALSE); update_buttons (data); } static void create_notebook (Web2Data *data) { GtkWidget *ebox, *label, *hbox, *image; data->pages_notebook = gtk_notebook_new (); gtk_notebook_set_scrollable (GTK_NOTEBOOK (data->pages_notebook), TRUE); gtk_widget_show (data->pages_notebook); label = gtk_label_new ("New page"); image = gtk_image_new_from_stock (GTK_STOCK_NEW, GTK_ICON_SIZE_MENU); hbox = gtk_hbox_new (FALSE, 6); gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0); gtk_box_pack_end (GTK_BOX (hbox), label, TRUE, TRUE, 0); gtk_widget_show_all (hbox); ebox = gtk_event_box_new (); gtk_widget_show (ebox); gtk_notebook_append_page (GTK_NOTEBOOK (data->pages_notebook), ebox, hbox); create_page (data, "http://www.google.co.uk/"); g_signal_connect (data->pages_notebook, "switch-page", G_CALLBACK (switch_page_cb), data); } static void navbox_go_clicked_cb (GtkButton *button, Web2Data *data) { const gchar *url; if (!data->current_page) { g_warning ("No current page selected?!"); return; } url = gtk_entry_get_text (GTK_ENTRY (data->url_entry)); if (url) webkit_web_view_open (data->current_page, url); } static void stop_clicked_cb (GtkButton *button, Web2Data *data) { if (!data->current_page) return; webkit_web_view_stop_loading (data->current_page); } static void create_header (Web2Data *data) { GtkWidget *hbox, *label, *button, *placeholder; data->header = gtk_hbox_new (FALSE, 0); label = gtk_label_new ("Address:"); data->url_entry = gtk_entry_new (); gtk_entry_set_activates_default (GTK_ENTRY (data->url_entry), TRUE); data->nav_go_button = gtk_button_new (); g_object_set (data->nav_go_button, "can-default", TRUE, NULL); g_signal_connect (data->nav_go_button, "clicked", G_CALLBACK (navbox_go_clicked_cb), data); gtk_container_add (GTK_CONTAINER (data->nav_go_button), gtk_image_new_from_stock ( GTK_STOCK_JUMP_TO, GTK_ICON_SIZE_BUTTON)); hbox = gtk_hbox_new (FALSE, 6); gtk_container_set_border_width (GTK_CONTAINER (hbox), 6); gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0); gtk_box_pack_start (GTK_BOX (hbox), data->url_entry, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (hbox), data->nav_go_button, FALSE, TRUE, 0); placeholder = gtk_label_new ("Bookmarks treeview goes here"); data->nav_box = gtk_vbox_new (FALSE, 6); gtk_box_pack_start (GTK_BOX (data->nav_box), hbox, FALSE, TRUE, 0); gtk_box_pack_start (GTK_BOX (data->nav_box), placeholder, TRUE, TRUE, 32); gtk_widget_show_all (hbox); gtk_widget_show_all (placeholder); gtk_box_pack_start (GTK_BOX (data->header), data->nav_box, TRUE, TRUE, 0); data->progress_bar = gtk_progress_bar_new (); button = gtk_button_new (); g_signal_connect (button, "clicked", G_CALLBACK (stop_clicked_cb), data); gtk_container_add (GTK_CONTAINER (button), gtk_image_new_from_stock ( GTK_STOCK_STOP, GTK_ICON_SIZE_BUTTON)); data->progress_box = gtk_hbox_new (FALSE, 6); gtk_box_pack_start (GTK_BOX (data->progress_box), data->progress_bar, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (data->progress_box), button, FALSE, TRUE, 0); gtk_widget_show (data->progress_bar); gtk_widget_show_all (button); gtk_box_pack_start (GTK_BOX (data->header), data->progress_box, TRUE, TRUE, 0); g_object_ref_sink (data->header); } static GtkWidget * create_toolbar (Web2Data *data) { GtkWidget *toolbar; data->go_button = gtk_toggle_tool_button_new (); gtk_tool_button_set_label (GTK_TOOL_BUTTON (data->go_button), "Go"); gtk_tool_button_set_label (GTK_TOOL_BUTTON (data->go_button), "Go"); gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (data->go_button), gtk_image_new_from_stock ( GTK_STOCK_OPEN, GTK_ICON_SIZE_LARGE_TOOLBAR)); g_object_set (data->go_button, "can-default", TRUE, NULL); gtk_tool_item_set_is_important (data->go_button, TRUE); g_signal_connect (data->go_button, "toggled", G_CALLBACK (go_toggled_cb), data); data->back_button = gtk_tool_button_new_from_stock (GTK_STOCK_GO_BACK); g_signal_connect (data->back_button, "clicked", G_CALLBACK (back_clicked_cb), data); data->forward_button = gtk_tool_button_new_from_stock ( GTK_STOCK_GO_FORWARD); g_signal_connect (data->forward_button, "clicked", G_CALLBACK (forward_clicked_cb), data); data->bookmark_button = gtk_tool_button_new (gtk_image_new_from_stock ( GTK_STOCK_ADD, GTK_ICON_SIZE_LARGE_TOOLBAR), "Bookmark"); gtk_tool_item_set_is_important (data->bookmark_button, TRUE); gtk_widget_set_sensitive (GTK_WIDGET (data->bookmark_button), FALSE); data->find_button = gtk_tool_button_new_from_stock (GTK_STOCK_FIND); gtk_tool_item_set_is_important (data->find_button, TRUE); gtk_widget_set_sensitive (GTK_WIDGET (data->find_button), FALSE); /*data->edit_button = gtk_toggle_tool_button_new_from_stock ( GTK_STOCK_EDIT); gtk_widget_set_sensitive (GTK_WIDGET (data->edit_button), FALSE);*/ data->zoomout_button = gtk_tool_button_new_from_stock ( GTK_STOCK_ZOOM_OUT); gtk_widget_set_sensitive (GTK_WIDGET (data->zoomout_button), FALSE); data->zoomin_button = gtk_tool_button_new_from_stock (GTK_STOCK_ZOOM_IN); gtk_widget_set_sensitive (GTK_WIDGET (data->zoomin_button), FALSE); toolbar = gtk_toolbar_new (); gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_BOTH_HORIZ); gtk_toolbar_insert (GTK_TOOLBAR (toolbar), data->go_button, -1); gtk_toolbar_insert (GTK_TOOLBAR (toolbar), data->back_button, -1); gtk_toolbar_insert (GTK_TOOLBAR (toolbar), data->forward_button, -1); gtk_toolbar_insert (GTK_TOOLBAR (toolbar), data->bookmark_button, -1); gtk_toolbar_insert (GTK_TOOLBAR (toolbar), data->find_button, -1); /*gtk_toolbar_insert (GTK_TOOLBAR (toolbar), data->edit_button, -1);*/ gtk_toolbar_insert (GTK_TOOLBAR (toolbar), data->zoomout_button, -1); gtk_toolbar_insert (GTK_TOOLBAR (toolbar), data->zoomin_button, -1); gtk_widget_show_all (toolbar); return toolbar; } static GtkWidget * create_menubar (Web2Data *data) { static const GtkActionEntry actions[] = { /* Action name, stock ID, label, accel, tooltip, callback */ { "PageMenu", NULL, "_Page" }, { "NewPage", GTK_STOCK_NEW, NULL, NULL, NULL, NULL }, { "BookmarkPage", NULL, "_Bookmark Page", NULL, NULL, NULL }, { "BackPage", GTK_STOCK_GO_BACK, NULL, NULL, NULL, NULL }, { "ForwardPage", GTK_STOCK_GO_FORWARD, NULL, NULL, NULL, NULL }, { "ClosePage", GTK_STOCK_CLOSE, NULL, NULL, NULL, NULL }, { "Quit", GTK_STOCK_QUIT, NULL, NULL, NULL, NULL }, { "EditMenu", NULL, "_Edit" }, { "Copy", GTK_STOCK_COPY, NULL, NULL, NULL, NULL }, { "Find", GTK_STOCK_FIND, NULL, NULL, NULL, NULL }, { "Preferences", GTK_STOCK_PREFERENCES, NULL, NULL, NULL, NULL }, { "ViewMenu", NULL, "_View" }, { "ZoomOut", GTK_STOCK_ZOOM_OUT, NULL, NULL, NULL, NULL }, { "ZoomIn", GTK_STOCK_ZOOM_IN, NULL, NULL, NULL, NULL }, { "ZoomReset", GTK_STOCK_ZOOM_100, NULL, NULL, NULL, NULL }, { "HelpMenu", NULL, "_Help" }, { "About", GTK_STOCK_ABOUT, NULL, NULL, NULL, NULL }, }; GtkActionGroup *action_group; GtkUIManager *ui_manager; GtkWidget *menu; GError *error = NULL; action_group = gtk_action_group_new ("Actions"); gtk_action_group_add_actions (action_group, actions, G_N_ELEMENTS (actions), NULL); ui_manager = gtk_ui_manager_new (); gtk_ui_manager_insert_action_group (ui_manager, action_group, 0); gtk_ui_manager_add_ui_from_file (ui_manager, PKGDATADIR G_DIR_SEPARATOR_S "web2-ui.xml", &error); if (error) { g_warning ("Error loading UI: %s", error->message); g_error_free (error); return NULL; } gtk_ui_manager_ensure_update (ui_manager); #ifdef HAVE_LIBOWL menu = gtk_ui_manager_get_widget (ui_manager, "/OwlMenuBar/PageMenu"); #else menu = gtk_ui_manager_get_widget (ui_manager, "/MenuBar"); #endif gtk_widget_show_all (menu); /*g_object_unref (ui_manager);*/ return menu; } int main (int argc, char **argv) { GtkWidget *toolbar, *vbox, *menu; Web2Data data; gtk_init (&argc, &argv); data.main_window = gtk_window_new (GTK_WINDOW_TOPLEVEL); toolbar = create_toolbar (&data); create_header (&data); create_notebook (&data); menu = create_menubar (&data); vbox = gtk_vbox_new (FALSE, 0); if (menu) { #ifdef HAVE_LIBOWL owl_set_window_menu_item (GTK_WINDOW (data.main_window), GTK_MENU_ITEM (menu)); #else gtk_box_pack_start (GTK_BOX (vbox), menu, FALSE, TRUE, 0); #endif } gtk_box_pack_start (GTK_BOX (vbox), data.pages_notebook, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (vbox), toolbar, FALSE, TRUE, 0); gtk_widget_show (vbox); gtk_container_add (GTK_CONTAINER (data.main_window), vbox); g_signal_connect (data.main_window, "destroy", G_CALLBACK (quit_cb), &data); gtk_window_set_default_size (GTK_WINDOW (data.main_window), 480, 640); gtk_widget_show (data.main_window); gtk_main (); return 0; }