From e62374600bfae078ae7ac5a350416f852705b139 Mon Sep 17 00:00:00 2001 From: Shaun McCance Date: Thu, 11 Mar 2010 12:16:21 -0600 Subject: [yelp-window] Basic new YelpWindow for YelpApplication --- src/Makefile.am | 1 + src/yelp-application.c | 89 +- src/yelp-application.h | 2 +- src/yelp-window.c | 2838 +----------------------------------------------- src/yelp-window.h | 38 +- 5 files changed, 113 insertions(+), 2855 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 251e2cb6..a1e26ea3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -2,6 +2,7 @@ bin_PROGRAMS = yelp yelp_SOURCES = \ yelp-application.c yelp-application.h \ + yelp-window.c yelp-window.h \ yelp.c # yelp-base.c yelp-base.h \ diff --git a/src/yelp-application.c b/src/yelp-application.c index 46ccd720..d12f7300 100644 --- a/src/yelp-application.c +++ b/src/yelp-application.c @@ -28,9 +28,11 @@ #include #include +#include "yelp-view.h" + #include "yelp-application.h" #include "yelp-dbus.h" -#include "yelp-view.h" +#include "yelp-window.h" typedef struct _YelpApplicationLoad YelpApplicationLoad; struct _YelpApplicationLoad { @@ -43,9 +45,12 @@ static void yelp_application_class_init (YelpApplicationClass *k static void yelp_application_dispose (GObject *object); static void yelp_application_finalize (GObject *object); -static GtkWidget * application_new_window (YelpApplication *app); static void application_uri_resolved (YelpUri *uri, YelpApplicationLoad *data); +static gboolean application_window_deleted (YelpWindow *window, + GdkEvent *event, + YelpApplication *app); +static gboolean application_maybe_quit (YelpApplication *app); G_DEFINE_TYPE (YelpApplication, yelp_application, G_TYPE_OBJECT); #define GET_PRIV(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), YELP_TYPE_APPLICATION, YelpApplicationPrivate)) @@ -89,9 +94,10 @@ yelp_application_dispose (GObject *object) { YelpApplicationPrivate *priv = GET_PRIV (object); - g_object_unref (priv->connection); - - g_hash_table_destroy (priv->windows_by_document); + if (priv->connection) { + g_object_unref (priv->connection); + priv->connection = NULL; + } G_OBJECT_CLASS (yelp_application_parent_class)->dispose (object); } @@ -99,6 +105,10 @@ yelp_application_dispose (GObject *object) static void yelp_application_finalize (GObject *object) { + YelpApplicationPrivate *priv = GET_PRIV (object); + + g_hash_table_destroy (priv->windows_by_document); + G_OBJECT_CLASS (yelp_application_parent_class)->finalize (object); } @@ -214,37 +224,11 @@ yelp_application_load_uri (YelpApplication *app, return TRUE; } -static GtkWidget * -application_new_window (YelpApplication *app) -{ - GtkWidget *window, *scroll, *view; - YelpApplicationPrivate *priv = GET_PRIV (app); - - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_window_set_type_hint (GTK_WINDOW (window), GDK_WINDOW_TYPE_HINT_UTILITY); - gtk_window_set_default_size (GTK_WINDOW (window), 520, 580); - priv->windows = g_slist_prepend (priv->windows, window); - - 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 (window), scroll); - - view = yelp_view_new (); - gtk_container_add (GTK_CONTAINER (scroll), view); - - g_object_set_data (G_OBJECT (window), "view", view); - - return window; -} - static void application_uri_resolved (YelpUri *uri, YelpApplicationLoad *data) { - GtkWidget *window; - YelpView *view; + YelpWindow *window; gchar *doc_uri; YelpApplicationPrivate *priv = GET_PRIV (data->app); @@ -253,18 +237,51 @@ application_uri_resolved (YelpUri *uri, window = g_hash_table_lookup (priv->windows_by_document, doc_uri); if (window == NULL) { - window = application_new_window (data->app); + window = yelp_window_new (data->app); + priv->windows = g_slist_prepend (priv->windows, window); g_hash_table_insert (priv->windows_by_document, doc_uri, window); + g_object_set_data (G_OBJECT (window), "doc_uri", doc_uri); + g_signal_connect (window, "delete-event", + G_CALLBACK (application_window_deleted), data->app); } else { g_free (doc_uri); } - view = g_object_get_data (G_OBJECT (window), "view"); - yelp_view_load_uri (YELP_VIEW (view), uri); + yelp_window_load_uri (window, uri); - gtk_widget_show_all (window); + gtk_widget_show_all (GTK_WIDGET (window)); gtk_window_present_with_time (GTK_WINDOW (window), data->timestamp); g_free (data); } + +static gboolean +application_window_deleted (YelpWindow *window, + GdkEvent *event, + YelpApplication *app) +{ + gchar *doc_uri; /* owned by windows_by_document */ + YelpApplicationPrivate *priv = GET_PRIV (app); + + priv->windows = g_slist_remove (priv->windows, window); + doc_uri = g_object_get_data (G_OBJECT (window), "doc_uri"); + if (doc_uri) + g_hash_table_remove (priv->windows_by_document, doc_uri); + + if (priv->windows == NULL) + g_timeout_add_seconds (5, (GSourceFunc) application_maybe_quit, app); + + return FALSE; +} + +static gboolean +application_maybe_quit (YelpApplication *app) +{ + YelpApplicationPrivate *priv = GET_PRIV (app); + + if (priv->windows == NULL) + gtk_main_quit (); + + return FALSE; +} diff --git a/src/yelp-application.h b/src/yelp-application.h index 6e5d141b..f4514b1a 100644 --- a/src/yelp-application.h +++ b/src/yelp-application.h @@ -23,7 +23,7 @@ #ifndef __YELP_APPLICATION_H__ #define __YELP_APPLICATION_H__ -#include +#include #define YELP_TYPE_APPLICATION (yelp_application_get_type ()) #define YELP_APPLICATION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), YELP_TYPE_APPLICATION, YelpApplication)) diff --git a/src/yelp-window.c b/src/yelp-window.c index 85439861..995c0db9 100644 --- a/src/yelp-window.c +++ b/src/yelp-window.c @@ -1,7 +1,6 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* - * Copyright (C) 2001-2002 Mikael Hallendal - * Copyright (C) 2003,2004 Shaun McCance + * Copyright (C) 2010 Shaun McCance * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -18,7 +17,6 @@ * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * - * Author: Mikael Hallendal * Author: Shaun McCance */ @@ -26,2835 +24,89 @@ #include #endif -#include -#include -#include -#include #include -#include -#include "yelp-bookmarks.h" -#include "yelp-utils.h" -#include "yelp-html.h" -#include "yelp-settings.h" -#include "yelp-toc.h" -#include "yelp-docbook.h" -#include "yelp-db-print.h" -#include "yelp-mallard.h" -#include "yelp-window.h" -#include "yelp-debug.h" - - -#include "yelp-man.h" -#include "yelp-info.h" -#include "yelp-search.h" -#include "gtkentryaction.h" - -#define YELP_CONFIG_PATH "/.gnome2/yelp" -#define YELP_CONFIG_GEOMETRY_GROUP "Geometry" -#define YELP_CONFIG_WIDTH "width" -#define YELP_CONFIG_HEIGHT "height" -#define YELP_CONFIG_WIDTH_DEFAULT 600 -#define YELP_CONFIG_HEIGHT_DEFAULT 420 - -#define BUFFER_SIZE 16384 - -typedef struct { - YelpDocument *doc; - YelpRrnType type; - - gchar *uri; - gchar *req_uri; - gchar *frag_id; - gchar *base_uri; - GtkWidget *menu_entry; - YelpWindow *window; - gint callback; - - gchar *page_title; - gchar *frag_title; -} YelpHistoryEntry; - -static void window_init (YelpWindow *window); -static void window_class_init (YelpWindowClass *klass); - -static void window_error (YelpWindow *window, - gchar *title, - gchar *message, - gboolean pop); -static void window_populate (YelpWindow *window); -static void window_populate_find (YelpWindow *window, - GtkWidget *find_bar); -static void window_set_sections (YelpWindow *window, - GtkTreeModel *sections); -static void window_set_section_cursor (YelpWindow *window, - GtkTreeModel *model); - -static gboolean window_do_load_html (YelpWindow *window, - gchar *uri, - gchar *frag_id, - YelpRrnType type, - gboolean need_history); -static void window_set_loading (YelpWindow *window); -static void window_setup_window (YelpWindow *window, - YelpRrnType type, - gchar *loading_uri, - gchar *frag, - gchar *req_uri, - gchar *base_uri, - gboolean add_history); - -/** Window Callbacks **/ -static gboolean window_configure_cb (GtkWidget *widget, - GdkEventConfigure *event, - gpointer data); - -/** Gecko Callbacks **/ -static void html_uri_selected_cb (YelpHtml *html, - gchar *uri, - gboolean handled, - gpointer user_data); -static gboolean html_frame_selected_cb (YelpHtml *html, - gchar *uri, - gboolean handled, - gpointer user_data); -static void html_title_changed_cb (YelpHtml *html, - gpointer webframe, - gchar *title, - gpointer user_data); -static gboolean window_key_event_cb (GtkWidget *widget, - GdkEventKey *event, - YelpWindow *window); -/** GtkTreeView Callbacks **/ -static void tree_selection_changed_cb (GtkTreeSelection *selection, - YelpWindow *window); -static void tree_drag_data_get_cb (GtkWidget *widget, - GdkDragContext *context, - GtkSelectionData *selection, - guint info, - guint32 time, - YelpWindow *window); -static void tree_row_expand_cb (GtkTreeView *view, - GtkTreePath *path, - GtkTreeViewColumn *column, - YelpWindow *window); - -/** UIManager Callbacks **/ -static void window_add_widget (GtkUIManager *ui_manager, - GtkWidget *widget, - GtkWidget *vbox); -static void window_new_window_cb (GtkAction *action, YelpWindow *window); -static void window_about_document_cb (GtkAction *action, YelpWindow *window); -static void window_print_document_cb (GtkAction *action, YelpWindow *window); -static void window_print_page_cb (GtkAction *action, YelpWindow *window); -static void window_open_location_cb (GtkAction *action, YelpWindow *window); -static void window_close_window_cb (GtkAction *action, YelpWindow *window); -static void window_copy_cb (GtkAction *action, YelpWindow *window); -static void window_select_all_cb (GtkAction *action, YelpWindow *window); -static void window_find_cb (GtkAction *action, YelpWindow *window); -static void window_preferences_cb (GtkAction *action, YelpWindow *window); -static void window_reload_cb (GtkAction *action, YelpWindow *window); -static void window_enable_cursor_cb (GtkAction *action, YelpWindow *window); -static void window_go_back_cb (GtkAction *action, YelpWindow *window); -static void window_go_forward_cb (GtkAction *action, YelpWindow *window); -static void window_go_home_cb (GtkAction *action, YelpWindow *window); -static void window_go_previous_cb (GtkAction *action, YelpWindow *window); -static void window_go_next_cb (GtkAction *action, YelpWindow *window); -static void window_go_toc_cb (GtkAction *action, YelpWindow *window); -static void window_add_bookmark_cb (GtkAction *action, YelpWindow *window); -static void window_help_contents_cb (GtkAction *action, YelpWindow *window); -static void window_about_cb (GtkAction *action, YelpWindow *window); -static void window_copy_link_cb (GtkAction *action, YelpWindow *window); -static void window_open_link_cb (GtkAction *action, YelpWindow *window); -static void window_open_link_new_cb (GtkAction *action, YelpWindow *window); -static void window_copy_mail_cb (GtkAction *action, YelpWindow *window); - -/** History Functions **/ -static void history_push_back (YelpWindow *window); -static void history_push_forward (YelpWindow *window); -static void history_clear_forward (YelpWindow *window); -static void history_step_back (YelpWindow *window); -static YelpHistoryEntry * history_pop_back (YelpWindow *window); -static YelpHistoryEntry * history_pop_forward (YelpWindow *window); -static void history_entry_free (YelpHistoryEntry *entry); -static void history_back_to (GtkMenuItem *menuitem, - YelpHistoryEntry *entry); -static void history_forward_to (GtkMenuItem *menuitem, - YelpHistoryEntry *entry); -static void history_load_entry (YelpWindow *window, - YelpHistoryEntry *entry); - -static void location_response_cb (GtkDialog *dialog, - gint id, - YelpWindow *window); - -static gboolean window_find_action (YelpWindow *window); -static void window_find_entry_changed_cb (GtkEditable *editable, - gpointer data); -static void window_find_entry_activate_cb (GtkEditable *editable, - gpointer data); -static gboolean window_find_entry_key_pressed_cb (GtkWidget *widget, - GdkEventKey *key, - gpointer data); -static void window_find_save_settings (YelpWindow *window); -static void window_find_buttons_set_sensitive (YelpWindow *window, - gboolean prev, - gboolean next); -static void window_find_clicked_cb (GtkWidget *button, - YelpWindow *window); -static gboolean window_find_hide_cb (GtkWidget *widget, - GdkEventFocus *event, - YelpWindow *window); -static void window_find_next_cb (GtkAction *action, - YelpWindow *window); -static void window_find_previous_cb (GtkAction *action, - YelpWindow *window); -static gboolean tree_model_iter_following (GtkTreeModel *model, - GtkTreeIter *iter); -static void window_write_html (YelpWindow *window, - YelpHtml *html, - YelpPage *page); - -enum { - NEW_WINDOW_REQUESTED, - LAST_SIGNAL -}; -static gint signals[LAST_SIGNAL] = { 0 }; -static GObjectClass *parent_class = NULL; - -#define YELP_WINDOW_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), YELP_TYPE_WINDOW, YelpWindowPriv)) - -struct _YelpWindowPriv { - /* Main Widgets */ - GtkWidget *main_box; - GtkWidget *pane; - GtkWidget *side_sects; - GtkWidget *html_pane; - GtkWidget *find_bar; - GtkWidget *find_entry; - YelpHtml *html_view; - GtkWidget *side_sw; - GtkWidget *search_action; - GtkWidget *html_sw; - - - /* Find in Page */ - GtkToolItem *find_prev; - GtkToolItem *find_next; - gchar *find_string; - GtkAction *find_next_menu; - GtkAction *find_prev_menu; - GtkToolItem *find_sep; - GtkToolItem *find_not_found; - - /* Open Location */ - GtkWidget *location_dialog; - GtkWidget *location_entry; - - /* Popup menu*/ - GtkWidget *popup; - gint merge_id; - GtkWidget *maillink; - - /* Location Information */ - gchar *uri; - YelpRrnType current_type; - gchar *req_uri; - gchar *base_uri; - gint current_request; - YelpDocument *current_document; - gchar *current_frag; - GSList *history_back; - GSList *history_forward; - GtkWidget *back_menu; - GtkWidget *forward_menu; - GtkTreeModel *current_sidebar; - - /* Callbacks and Idles */ - gulong start_handler; - gulong page_handler; - gulong error_handler; - gulong cancel_handler; - gulong finish_handler; - - gint toc_pause; - - GtkActionGroup *action_group; - GtkUIManager *ui_manager; - - /* Don't free these */ - gchar *prev_id; - gchar *next_id; - gchar *toc_id; -}; +#include "yelp-uri.h" +#include "yelp-view.h" -#define TARGET_TYPE_URI_LIST "text/uri-list" -enum { - TARGET_URI_LIST -}; - -static const GtkActionEntry entries[] = { - { "FileMenu", NULL, N_("_File") }, - { "EditMenu", NULL, N_("_Edit") }, - { "GoMenu", NULL, N_("_Go") }, - { "BookmarksMenu", NULL, N_("_Bookmarks") }, - { "HelpMenu", NULL, N_("_Help") }, - - { "NewWindow", GTK_STOCK_NEW, - N_("_New Window"), - "N", - NULL, - G_CALLBACK (window_new_window_cb) }, - { "PrintDocument", NULL, - N_("Print This Document ..."), - NULL, - NULL, - G_CALLBACK (window_print_document_cb) }, - { "PrintPage", NULL, - N_("Print This Page ..."), - NULL, - NULL, - G_CALLBACK (window_print_page_cb) }, - { "AboutDocument", NULL, - N_("About This Document"), - NULL, - NULL, - G_CALLBACK (window_about_document_cb) }, - { "OpenLocation", NULL, - N_("Open _Location"), - "L", - NULL, - G_CALLBACK (window_open_location_cb) }, - { "CloseWindow", GTK_STOCK_CLOSE, - N_("_Close Window"), - "W", - NULL, - G_CALLBACK (window_close_window_cb) }, - - { "Copy", GTK_STOCK_COPY, - N_("_Copy"), - "C", - NULL, - G_CALLBACK (window_copy_cb) }, - - { "SelectAll", NULL, - N_("_Select All"), - "A", - NULL, - G_CALLBACK (window_select_all_cb) }, - { "Find", GTK_STOCK_FIND, - N_("_Find..."), - "F", - NULL, - G_CALLBACK (window_find_cb) }, - { "FindPrev", NULL, - N_("Find Pre_vious"), - "G", - N_("Find previous occurrence of the word or phrase"), - G_CALLBACK (window_find_previous_cb) }, - { "FindNext", NULL, - N_("Find Ne_xt"), - "G", - N_("Find next occurrence of the word or phrase"), - G_CALLBACK (window_find_next_cb) }, - { "Preferences", GTK_STOCK_PREFERENCES, - N_("_Preferences"), - NULL, NULL, - G_CALLBACK (window_preferences_cb) }, - - { "Reload", NULL, - N_("_Reload"), - "R", - NULL, - G_CALLBACK (window_reload_cb) }, - - { "TextCursor", NULL, - "TextCursor", - "F7", - NULL, - G_CALLBACK (window_enable_cursor_cb) }, +#include "yelp-application.h" +#include "yelp-window.h" - { "GoBack", GTK_STOCK_GO_BACK, - N_("_Back"), - "Left", - N_("Show previous page in history"), - G_CALLBACK (window_go_back_cb) }, - { "GoForward", GTK_STOCK_GO_FORWARD, - N_("_Forward"), - "Right", - N_("Show next page in history"), - G_CALLBACK (window_go_forward_cb) }, - { "GoHome", GTK_STOCK_HOME, - N_("_Help Topics"), - "Home", - N_("Go to the listing of help topics"), - G_CALLBACK (window_go_home_cb) }, - { "GoPrevious", NULL, - N_("_Previous Section"), - "Up", - NULL, - G_CALLBACK (window_go_previous_cb) }, - { "GoNext", NULL, - N_("_Next Section"), - "Down", - NULL, - G_CALLBACK (window_go_next_cb) }, - { "GoContents", NULL, - N_("_Contents"), - NULL, - NULL, - G_CALLBACK (window_go_toc_cb) }, +static void yelp_window_init (YelpWindow *window); +static void yelp_window_class_init (YelpWindowClass *klass); +static void yelp_window_dispose (GObject *object); +static void yelp_window_finalize (GObject *object); - { "AddBookmark", NULL, - N_("_Add Bookmark"), - "D", - NULL, - G_CALLBACK (window_add_bookmark_cb) }, - { "EditBookmarks", NULL, - N_("_Edit Bookmarks..."), - "B", - NULL, - G_CALLBACK (yelp_bookmarks_edit) }, +G_DEFINE_TYPE (YelpWindow, yelp_window, GTK_TYPE_WINDOW); +#define GET_PRIV(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), YELP_TYPE_WINDOW, YelpWindowPrivate)) - { "OpenLink", NULL, - N_("_Open Link"), - NULL, - NULL, - G_CALLBACK (window_open_link_cb) }, - { "OpenLinkNewWindow", NULL, - N_("Open Link in _New Window"), - NULL, - NULL, - G_CALLBACK (window_open_link_new_cb) }, - { "CopyLocation", NULL, - N_("_Copy Link Address"), - NULL, - NULL, - G_CALLBACK (window_copy_link_cb) }, - { "Contents", GTK_STOCK_HELP, - N_("_Contents"), - "F1", - N_("Help On this application"), - G_CALLBACK (window_help_contents_cb) }, - { "About", GTK_STOCK_ABOUT, - N_("_About"), - NULL, - NULL, - G_CALLBACK (window_about_cb) }, - { "CopyMail", NULL, - N_("Copy _Email Address"), - NULL, - NULL, - G_CALLBACK (window_copy_mail_cb) } +typedef struct _YelpWindowPrivate YelpWindowPrivate; +struct _YelpWindowPrivate { + YelpView *view; /* no ref */ }; -GType -yelp_window_get_type (void) -{ - static GType window_type = 0; - - if (!window_type) { - static const GTypeInfo window_info = { - sizeof (YelpWindowClass), - NULL, - NULL, - (GClassInitFunc) window_class_init, - NULL, - NULL, - sizeof (YelpWindow), - 0, - (GInstanceInitFunc) window_init, - }; - - window_type = g_type_register_static (GTK_TYPE_WINDOW, - "YelpWindow", - &window_info, 0); - } - - return window_type; -} - -static void -window_init (YelpWindow *window) -{ - gint width, height; - - window->priv = YELP_WINDOW_GET_PRIVATE (window); - - GKeyFile *keyfile = g_key_file_new(); - GError *config_error = NULL; - gchar* config_path = g_strconcat( g_get_home_dir(), YELP_CONFIG_PATH, NULL); - - if( !g_key_file_load_from_file (keyfile, config_path, - G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS, - &config_error)) { - g_warning ("Failed to load config file: %s\n", config_error->message); - g_error_free (config_error); - - width = YELP_CONFIG_WIDTH_DEFAULT; - height = YELP_CONFIG_HEIGHT_DEFAULT; - } else { - width = g_key_file_get_integer (keyfile, YELP_CONFIG_GEOMETRY_GROUP, - YELP_CONFIG_WIDTH, NULL); - height = g_key_file_get_integer (keyfile, YELP_CONFIG_GEOMETRY_GROUP, - YELP_CONFIG_HEIGHT, NULL); - - if (width == 0) - width = YELP_CONFIG_WIDTH_DEFAULT; - if (height == 0) - height = YELP_CONFIG_HEIGHT_DEFAULT; - } - - g_free (config_path); - g_key_file_free (keyfile); - - gtk_window_set_default_size (GTK_WINDOW (window), width, height); - g_signal_connect (window, - "configure-event", - G_CALLBACK (window_configure_cb), - NULL); - - gtk_window_set_title (GTK_WINDOW (window), _("Help Browser")); - - window_populate (window); -} - -static void -window_dispose (GObject *object) -{ - parent_class->dispose (object); -} - static void -window_finalize (GObject *object) +yelp_window_init (YelpWindow *window) { - YelpWindow *window = YELP_WINDOW (object); - YelpWindowPriv *priv = window->priv; - - g_object_unref (priv->action_group); - g_object_unref (priv->ui_manager); + GtkWidget *scroll, *view; + YelpWindowPrivate *priv = GET_PRIV (window); - g_free (priv->find_string); - - g_free (priv->current_frag); - - g_free (priv->uri); - g_free (priv->base_uri); - g_free (priv->req_uri); + gtk_window_set_type_hint (GTK_WINDOW (window), GDK_WINDOW_TYPE_HINT_UTILITY); + gtk_window_set_default_size (GTK_WINDOW (window), 520, 580); + + 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 (window), scroll); - /* FIXME there are many more things to free */ + view = yelp_view_new (); + gtk_container_add (GTK_CONTAINER (scroll), view); - parent_class->finalize (object); + priv->view = (YelpView *) view; } static void -window_class_init (YelpWindowClass *klass) +yelp_window_class_init (YelpWindowClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - parent_class = (GObjectClass *) g_type_class_peek_parent (klass); - - object_class->dispose = window_dispose; - object_class->finalize = window_finalize; - - signals[NEW_WINDOW_REQUESTED] = - g_signal_new ("new_window_requested", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (YelpWindowClass, - new_window_requested), - NULL, NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, G_TYPE_STRING); - - g_type_class_add_private (klass, sizeof (YelpWindowPriv)); -} - -const gchar * -yelp_window_get_uri (YelpWindow *window) -{ - - return ((const gchar *) window->priv->uri); -} - -/** History Functions *********************************************************/ - -static void -history_push_back (YelpWindow *window) -{ - YelpWindowPriv *priv; - YelpHistoryEntry *entry; - GtkAction *action; - gchar *title; - - g_return_if_fail (YELP_IS_WINDOW (window)); - - priv = window->priv; - - entry = g_new0 (YelpHistoryEntry, 1); - - entry->frag_id = g_strdup (priv->current_frag); - entry->uri = g_strdup (priv->uri); - entry->req_uri = g_strdup(priv->req_uri); - entry->doc = priv->current_document; - entry->type = priv->current_type; - entry->base_uri = g_strdup (priv->base_uri); - - /* page_title, frag_title */ - - priv->history_back = g_slist_prepend (priv->history_back, entry); - - action = gtk_action_group_get_action (priv->action_group, "GoBack"); - if (action) - g_object_set (G_OBJECT (action), "sensitive", TRUE, NULL); - title = (gchar *) gtk_window_get_title (GTK_WINDOW (window)); - - if (g_str_equal (title, _("Loading..."))) - entry->page_title = g_strdup (_("Unknown Page")); - else - entry->page_title = g_strdup (title); - - entry->window = window; - - entry->menu_entry = gtk_menu_item_new_with_label (entry->page_title); - g_object_ref (entry->menu_entry); - - entry->callback = g_signal_connect (G_OBJECT (entry->menu_entry), - "activate", - G_CALLBACK (history_back_to), - entry); - - - gtk_menu_shell_prepend (GTK_MENU_SHELL (window->priv->back_menu), - entry->menu_entry); - gtk_widget_show (entry->menu_entry); -} - -static void -history_push_forward (YelpWindow *window) -{ - YelpWindowPriv *priv; - YelpHistoryEntry *entry; - GtkAction *action; - gchar *title; - - g_return_if_fail (YELP_IS_WINDOW (window)); - - priv = window->priv; - - entry = g_new0 (YelpHistoryEntry, 1); - - entry->frag_id = g_strdup (priv->current_frag); - entry->uri = g_strdup (priv->uri); - entry->req_uri = g_strdup(priv->req_uri); - entry->doc = priv->current_document; - entry->type = priv->current_type; - entry->base_uri = g_strdup (priv->base_uri); - - /* page_title, frag_title */ - - priv->history_forward = g_slist_prepend (priv->history_forward, entry); - - action = gtk_action_group_get_action (priv->action_group, "GoForward"); - if (action) - g_object_set (G_OBJECT (action), "sensitive", TRUE, NULL); - - title = (gchar *) gtk_window_get_title (GTK_WINDOW (window)); - - if (g_str_equal (title, _("Loading..."))) - entry->page_title = g_strdup (_("Unknown Page")); - else - entry->page_title = g_strdup (title); - - entry->window = window; - entry->menu_entry = gtk_menu_item_new_with_label (entry->page_title); - g_object_ref (entry->menu_entry); - - entry->callback = g_signal_connect (G_OBJECT (entry->menu_entry), - "activate", - G_CALLBACK (history_forward_to), - entry); - - - gtk_menu_shell_prepend (GTK_MENU_SHELL (window->priv->forward_menu), - entry->menu_entry); - gtk_widget_show (entry->menu_entry); -} - -static void -history_clear_forward (YelpWindow *window) -{ - YelpWindowPriv *priv; - GtkAction *action; - - g_return_if_fail (YELP_IS_WINDOW (window)); - - priv = window->priv; - - if (priv->history_forward) { - g_slist_foreach (priv->history_forward, - (GFunc) history_entry_free, - NULL); - g_slist_free (priv->history_forward); - priv->history_forward = NULL; - } - action = gtk_action_group_get_action (priv->action_group, "GoForward"); - if (action) - g_object_set (G_OBJECT (action), "sensitive", FALSE, NULL); -} - -static void -history_step_back (YelpWindow *window) -{ - YelpWindowPriv *priv; - YelpHistoryEntry *entry; - - /** FIXME: would be nice to re-select the correct entry on the left **/ - - g_return_if_fail (YELP_IS_WINDOW (window)); - - priv = window->priv; - entry = history_pop_back (window); - - g_free (priv->current_frag); - priv->current_frag = NULL; - - if (entry) { - priv->current_frag = g_strdup (entry->frag_id); - history_entry_free (entry); - } else { - yelp_window_load (window, "x-yelp-toc:"); - } -} - -static YelpHistoryEntry * -history_pop_back (YelpWindow *window) -{ - YelpWindowPriv *priv; - YelpHistoryEntry *entry; - GtkAction *action; - - g_return_val_if_fail (YELP_IS_WINDOW (window), NULL); - if (!window->priv->history_back) - return NULL; - - priv = window->priv; - - entry = (YelpHistoryEntry *) priv->history_back->data; - priv->history_back = g_slist_delete_link (priv->history_back, - priv->history_back); - - action = gtk_action_group_get_action (priv->action_group, "GoBack"); - if (action) - g_object_set (G_OBJECT (action), "sensitive", - priv->history_back ? TRUE : FALSE, - NULL); - return entry; -} - -static YelpHistoryEntry * -history_pop_forward (YelpWindow *window) -{ - YelpWindowPriv *priv; - YelpHistoryEntry *entry; - GtkAction *action; - - g_return_val_if_fail (YELP_IS_WINDOW (window), NULL); - if (!window->priv->history_forward) - return NULL; + object_class->dispose = yelp_window_dispose; + object_class->finalize = yelp_window_finalize; - priv = window->priv; - - entry = (YelpHistoryEntry *) priv->history_forward->data; - priv->history_forward = g_slist_delete_link (priv->history_forward, - priv->history_forward); - - action = gtk_action_group_get_action (priv->action_group, "GoForward"); - if (action) - g_object_set (G_OBJECT (action), "sensitive", - priv->history_forward ? TRUE : FALSE, - NULL); - return entry; + g_type_class_add_private (klass, sizeof (YelpWindowPrivate)); } static void -history_entry_free (YelpHistoryEntry *entry) +yelp_window_dispose (GObject *object) { - g_return_if_fail (entry != NULL); - - g_free (entry->frag_id); - g_free (entry->page_title); - g_free (entry->frag_title); - g_free (entry->base_uri); - g_free (entry->uri); - g_free (entry->req_uri); - - if (entry->menu_entry) { - gtk_widget_destroy (entry->menu_entry); - } - - g_free (entry); + G_OBJECT_CLASS (yelp_window_parent_class)->dispose (object); } static void -history_back_to (GtkMenuItem *menuitem, YelpHistoryEntry *entry) +yelp_window_finalize (GObject *object) { - YelpWindow *window; - YelpWindowPriv *priv; - YelpHistoryEntry *latest; - - window = entry->window; - - priv = window->priv; - - latest = history_pop_back (window); - history_push_forward (window); - - while (!g_str_equal (latest->page_title, entry->page_title)) { - priv->history_forward = g_slist_prepend (priv->history_forward, latest); - gtk_container_remove (GTK_CONTAINER (priv->back_menu), - latest->menu_entry); - - g_signal_handler_disconnect (latest->menu_entry, latest->callback); - latest->callback = g_signal_connect (G_OBJECT (latest->menu_entry), - "activate", - G_CALLBACK (history_forward_to), - latest); - - - gtk_menu_shell_prepend (GTK_MENU_SHELL (window->priv->forward_menu), - latest->menu_entry); - gtk_widget_show (latest->menu_entry); - - - latest = history_pop_back (window); - } - if (latest->menu_entry) { - gtk_widget_destroy (latest->menu_entry); - latest->menu_entry = NULL; - } - - history_load_entry (window, entry); - history_entry_free (entry); + G_OBJECT_CLASS (yelp_window_parent_class)->finalize (object); } -static void -history_forward_to (GtkMenuItem *menuitem, YelpHistoryEntry *entry) -{ - YelpWindow *window; - YelpWindowPriv *priv; - YelpHistoryEntry *latest; - - window = entry->window; - - priv = window->priv; - - latest = history_pop_forward (window); - history_push_back (window); - - while (!g_str_equal (latest->page_title, entry->page_title)) { - priv->history_back = g_slist_prepend (priv->history_back, latest); - gtk_container_remove (GTK_CONTAINER (priv->forward_menu), - latest->menu_entry); - - g_signal_handler_disconnect (latest->menu_entry, latest->callback); - latest->callback = g_signal_connect (G_OBJECT (latest->menu_entry), - "activate", - G_CALLBACK (history_back_to), - latest); - - gtk_menu_shell_prepend (GTK_MENU_SHELL (window->priv->back_menu), - latest->menu_entry); - gtk_widget_show (latest->menu_entry); - - - latest = history_pop_forward (window); - } - if (latest->menu_entry) { - gtk_widget_destroy (latest->menu_entry); - latest->menu_entry = NULL; - } - - history_load_entry (window, entry); - history_entry_free (entry); - - -} /******************************************************************************/ - -GtkWidget * -yelp_window_new (GNode *doc_tree, GList *index) -{ - return GTK_WIDGET (g_object_new (YELP_TYPE_WINDOW, NULL)); -} - -static void -page_request_cb (YelpDocument *document, - YelpDocumentSignal signal, - gint req_id, - gpointer *func_data, - YelpWindow *window) -{ - YelpError *error; - - switch (signal) { - case YELP_DOCUMENT_SIGNAL_PAGE: - window_set_sections (window, yelp_document_get_sections (document)); - - window_write_html (window, NULL, (YelpPage *) func_data); - - window->priv->current_request = -1; - yelp_page_free ((YelpPage *) func_data); - gdk_window_set_cursor (GTK_WIDGET (window)->window, NULL); - - break; - case YELP_DOCUMENT_SIGNAL_TITLE: - /* We don't need to actually handle title signals as gecko - * is wise enough to not annoy me by not handling it - */ - g_free (func_data); - break; - case YELP_DOCUMENT_SIGNAL_ERROR: - error = (YelpError *) func_data; - window_error (window, (gchar *) yelp_error_get_title (error), - (gchar *) yelp_error_get_message (error), FALSE); - yelp_error_free (error); - gdk_window_set_cursor (GTK_WIDGET (window)->window, NULL); - break; - default: - g_assert_not_reached(); - } -} - -static void -window_setup_window (YelpWindow *window, YelpRrnType type, - gchar *loading_uri, gchar *frag, gchar *req_uri, - gchar *base_uri, gboolean add_history) +YelpWindow * +yelp_window_new (YelpApplication *app) { - /* Before asking the YelpDocument to find - * a page, this should be called to set up various - * things (such as fixing history, setting - * menu items to sensitive etc.) - * These are all read from the YelpWindow struct - * so they must be set BEFORE calling this. - */ - YelpWindowPriv *priv; - GtkAction *action; - - g_return_if_fail (YELP_IS_WINDOW (window)); - - priv = window->priv; - - if (priv->current_request != -1) { - yelp_document_cancel_page (priv->current_document, priv->current_request); - priv->current_request = -1; - } else if (add_history) { - gchar *tmp = window->priv->base_uri; - window->priv->base_uri = base_uri; - history_push_back(window); - window->priv->base_uri = tmp; - } - - - window_set_loading (window); - - priv->current_type = type; - g_free (priv->uri); - priv->uri = g_strdup (loading_uri); - g_free (priv->current_frag); - priv->current_frag = g_strdup (frag); - g_free (priv->req_uri); - priv->req_uri = g_strdup (req_uri); - - switch (priv->current_type) { - case YELP_RRN_TYPE_DOC: - action = gtk_action_group_get_action (window->priv->action_group, - "PrintDocument"); - g_object_set (G_OBJECT (action), "sensitive", TRUE, NULL); - - action = gtk_action_group_get_action (window->priv->action_group, - "AboutDocument"); - g_object_set (G_OBJECT (action), "sensitive", TRUE, NULL); - break; - default: - action = gtk_action_group_get_action (window->priv->action_group, - "PrintDocument"); - g_object_set (G_OBJECT (action), "sensitive", FALSE, NULL); + YelpWindow *window; - action = gtk_action_group_get_action (window->priv->action_group, - "AboutDocument"); - g_object_set (G_OBJECT (action), "sensitive", FALSE, NULL); - break; + window = (YelpWindow *) g_object_new (YELP_TYPE_WINDOW, NULL); - } + return window; } - void -yelp_window_load (YelpWindow *window, const gchar *uri) -{ - YelpWindowPriv *priv; - gchar *frag_id = NULL; - gchar *real_uri = NULL; - gchar *trace_uri = NULL; - YelpRrnType type = YELP_RRN_TYPE_ERROR; - YelpDocument *doc = NULL; - gchar *current_base = NULL; - - g_return_if_fail (YELP_IS_WINDOW (window)); - - priv = window->priv; - - current_base = g_strdup (priv->base_uri); - - /* If someone asks for info:dir, they WILL get redirected to - * our index. Tough. - */ - if (g_str_has_prefix (uri, "info:") && g_str_has_suffix (uri, "dir")) { - trace_uri = g_strdup ("x-yelp-toc:#Info"); - } else { - trace_uri = g_strdup (uri); - } - - /* The way this route was taken, we need to clear the - * forward history now - */ - history_clear_forward (window); - - type = yelp_uri_resolve (trace_uri, &real_uri, &frag_id); - - if (type == YELP_RRN_TYPE_ERROR) { - gchar *message = g_strdup_printf (_("The requested URI \"%s\" is invalid"), trace_uri); - window_error (window, _("Unable to load page"), message, FALSE); - - goto Exit; - } - - if (priv->uri && g_str_equal (real_uri, priv->uri)) { - doc = priv->current_document; - } else { - gchar *old_base_uri = priv->base_uri; - priv->base_uri = NULL; - - switch (type) { - case YELP_RRN_TYPE_TOC: - doc = yelp_toc_get (); - priv->base_uri = g_strdup ("file:///fakefile"); - break; - case YELP_RRN_TYPE_MAL: - priv->base_uri = g_filename_to_uri (real_uri, NULL, NULL); - doc = yelp_mallard_new (real_uri); - break; - case YELP_RRN_TYPE_MAN: - priv->base_uri = g_filename_to_uri (real_uri, NULL, NULL); - doc = yelp_man_new (real_uri); - break; - case YELP_RRN_TYPE_INFO: - priv->base_uri = g_filename_to_uri (real_uri, NULL, NULL); - if (!frag_id) { - frag_id = g_strdup ("Top"); - } else { - g_strdelimit (frag_id, " ", '_'); - } - doc = yelp_info_new (real_uri); - break; - case YELP_RRN_TYPE_DOC: - priv->base_uri = g_strdup(real_uri); - doc = yelp_docbook_new (real_uri); - break; - case YELP_RRN_TYPE_SEARCH: - doc = yelp_search_new (&real_uri[14]); /* to remove x-yelp-search:*/ - priv->base_uri = g_strdup ("file:///fakefile"); - - break; - case YELP_RRN_TYPE_HTML: - case YELP_RRN_TYPE_XHTML: - case YELP_RRN_TYPE_TEXT: - { - gchar *call_uri; - priv->base_uri = g_strdup ("file:///fakefile"); - call_uri = g_filename_to_uri (real_uri, NULL, NULL); - window_do_load_html (window, call_uri, frag_id, type, TRUE); - g_free (call_uri); - } - break; - case YELP_RRN_TYPE_EXTERNAL: - { - GError *error = NULL; - - priv->base_uri = old_base_uri; - - /* disallow external links when running in the GDM greeter session */ - if (g_getenv ("RUNNING_UNDER_GDM") != NULL) { - gchar *message = g_strdup_printf (_("The requested URI \"%s\" is invalid"), trace_uri); - - window_error (window, _("Unable to load page"), message, FALSE); - g_free (message); - - goto Exit; - } - - if (!gtk_show_uri (NULL, trace_uri, gtk_get_current_event_time (), &error)) { - gchar *message = g_strdup_printf (_("The requested URI \"%s\" is invalid"), trace_uri); - window_error (window, _("Unable to load page"), message, FALSE); - /* todo: Freeing error here causes an immediate - * seg fault. Why? Who knows. For now, we'll - * leak it - */ - /* g_free (error); */ - error = NULL; - if (!priv->current_document) { - /* recurse to load the index if we're not - * already somewhere - */ - yelp_window_load (window, "x-yelp-toc:"); - } - goto Exit; - } - } - break; - - default: - priv->base_uri = old_base_uri; - break; - } - if (old_base_uri != priv->base_uri) - g_free (old_base_uri); - } - - if (doc) { - gchar *faux_frag_id, *slash; - gboolean need_hist = FALSE; - if (!frag_id) - frag_id = g_strdup ("x-yelp-index"); - - if (priv->current_document || (priv->current_type == YELP_RRN_TYPE_HTML || - priv->current_type == YELP_RRN_TYPE_XHTML || - priv->current_type == YELP_RRN_TYPE_TEXT)) - need_hist = TRUE; - - /* FIXME: Super hacky. We want the part before the slash for mallard IDs, - because right now we're outputting "#page_id/section_id". - */ - faux_frag_id = g_strdup (frag_id); - slash = strchr (faux_frag_id, '/'); - if (slash) - *slash = '\0'; - if (strlen (faux_frag_id) == 0) { - gchar *new_frag_id, *newslash; - if (slash) - slash = g_strdup (slash + 1); - g_free (faux_frag_id); - faux_frag_id = g_strdup (priv->current_frag); - newslash = strchr (faux_frag_id, '/'); - if (newslash) - *newslash = '\0'; - new_frag_id = g_strconcat (faux_frag_id, "/", slash, NULL); - g_free (frag_id); - g_free (slash); - frag_id = new_frag_id; - } - window_setup_window (window, type, real_uri, frag_id, - (gchar *) uri, current_base, need_hist); - priv->current_request = yelp_document_get_page (doc, - faux_frag_id, - (YelpDocumentFunc) page_request_cb, - (void *) window); - g_free (faux_frag_id); - priv->current_document = doc; - } - - Exit: - g_free (frag_id); - g_free(real_uri); - g_free(trace_uri); - g_free(current_base); -} - -GtkUIManager * -yelp_window_get_ui_manager (YelpWindow *window) -{ - g_return_val_if_fail (YELP_IS_WINDOW (window), NULL); - - return window->priv->ui_manager; -} - -/******************************************************************************/ - -static void -window_error (YelpWindow *window, gchar *title, gchar *message, gboolean pop) -{ - YelpWindowPriv *priv; - GtkWidget *dialog; - GtkAction *action; - - priv = window->priv; - - if (pop) - history_step_back (window); - - action = gtk_action_group_get_action (priv->action_group, "GoPrevious"); - if (action) - g_object_set (G_OBJECT (action), "sensitive", FALSE, NULL); - action = gtk_action_group_get_action (priv->action_group, "GoNext"); - if (action) - g_object_set (G_OBJECT (action), "sensitive", FALSE, NULL); - action = gtk_action_group_get_action (priv->action_group, "GoContents"); - if (action) - g_object_set (G_OBJECT (action), "sensitive", FALSE, NULL); - - dialog = gtk_message_dialog_new - (GTK_WINDOW (window), - GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_OK, - "%s", title); - gtk_message_dialog_format_secondary_markup - (GTK_MESSAGE_DIALOG (dialog), "%s", message); - gtk_dialog_run (GTK_DIALOG (dialog)); - - gtk_widget_destroy (dialog); -} - -static char * -encode_search_uri (const char *search_terms) -{ - return g_strdup_printf ("x-yelp-search:%s", search_terms); -} - -static void -search_activated (GtkAction *action, - YelpWindow *window) -{ - const char *search_terms; - char *uri; - - search_terms = gtk_entry_action_get_text (GTK_ENTRY_ACTION (action)); - - /* Do some basic checking here - if someones looking for a man - * or info page, save doing the search and just bring them directly to - * the relevant page - * Trigger it using "man:", "man " or "info:" - */ - if (g_str_has_prefix (search_terms, "man:") || - g_str_has_prefix (search_terms, "info:")) { - uri = g_strdup (search_terms); - } else if (g_str_has_prefix (search_terms, "man ") && - !strstr (&(search_terms[4])," ")) { - uri = g_strdup (search_terms); - uri[3]=':'; - } else if (g_str_has_prefix (search_terms, "info ")) { - gint count = 0; - gchar *spaces; - - spaces = strchr (search_terms, ' '); - while (spaces) { - count++; - spaces = strchr (spaces+1, ' '); - } - if (count == 1) { - uri = g_strdup (search_terms); - uri[4] = ':'; - } else { - uri = encode_search_uri (search_terms); - } - } else { - uri = encode_search_uri (search_terms); - } - yelp_window_load (window, uri); - - g_free (uri); -} - - -static void -window_populate (YelpWindow *window) +yelp_window_load_uri (YelpWindow *window, + YelpUri *uri) { - YelpWindowPriv *priv; - GtkAccelGroup *accel_group; - GError *error = NULL; - GtkAction *action; - GtkTreeSelection *selection; - GtkWidget *toolbar; - GtkWidget *toolitem; - GtkWidget *b_proxy; - GtkWidget *f_proxy; - - - priv = window->priv; - - priv->current_request = -1; - - priv->main_box = gtk_vbox_new (FALSE, 0); - - gtk_container_add (GTK_CONTAINER (window), priv->main_box); - - priv->action_group = gtk_action_group_new ("MenuActions"); - gtk_action_group_set_translation_domain (priv->action_group, - GETTEXT_PACKAGE); - gtk_action_group_add_actions (priv->action_group, - entries, G_N_ELEMENTS (entries), - window); - - b_proxy = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL)); - - priv->back_menu = gtk_menu_new (); - - priv->forward_menu = gtk_menu_new (); - - f_proxy = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL)); - - gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (b_proxy), - priv->back_menu); - - action = gtk_action_group_get_action(priv->action_group, "GoBack"); -#if GTK_CHECK_VERSION (2, 16, 0) - gtk_activatable_set_related_action (GTK_ACTIVATABLE (b_proxy), action); -#else - gtk_action_connect_proxy (action, b_proxy); -#endif - - action = gtk_action_group_get_action (priv->action_group, "GoForward"); -#if GTK_CHECK_VERSION (2, 16, 0) - gtk_activatable_set_related_action (GTK_ACTIVATABLE (f_proxy), action); -#else - gtk_action_connect_proxy (action, f_proxy); -#endif - - gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (f_proxy), - priv->forward_menu); - - priv->search_action = (GtkWidget * )gtk_entry_action_new ("Search", - _("_Search:"), - _("Search for other documentation"), - NULL); - g_signal_connect (G_OBJECT (priv->search_action), "activate", - G_CALLBACK (search_activated), window); - gtk_action_group_add_action (priv->action_group, - (GtkAction *) priv->search_action); - - priv->ui_manager = gtk_ui_manager_new (); - gtk_ui_manager_insert_action_group (priv->ui_manager, priv->action_group, 0); - - accel_group = gtk_ui_manager_get_accel_group (priv->ui_manager); - gtk_window_add_accel_group (GTK_WINDOW (window), accel_group); - - - g_signal_connect (G_OBJECT (priv->ui_manager), "add-widget", - G_CALLBACK (window_add_widget), priv->main_box); - - if (!gtk_ui_manager_add_ui_from_file (priv->ui_manager, - DATADIR "/yelp/ui/yelp-ui.xml", - &error)) { - window_error (window, _("Cannot create window"), error->message, FALSE); - } - - if (!gtk_ui_manager_add_ui_from_file (priv->ui_manager, - DATADIR "/yelp/ui/yelp-search-ui.xml", - &error)) { - window_error (window, _("Cannot create search component"), error->message, FALSE); - } - - yelp_bookmarks_register (window); - - action = gtk_action_group_get_action (priv->action_group, "GoBack"); - if (action) - g_object_set (G_OBJECT (action), "sensitive", FALSE, NULL); - action = gtk_action_group_get_action (priv->action_group, "GoForward"); - if (action) - g_object_set (G_OBJECT (action), "sensitive", FALSE, NULL); - - gtk_ui_manager_ensure_update (priv->ui_manager); - - toolbar = gtk_ui_manager_get_widget(priv->ui_manager, "ui/tools"); - - gtk_toolbar_insert (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM (f_proxy), 0); - gtk_toolbar_insert (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM (b_proxy), 0); - - /*To keep the seperator but get rid of the extra widget*/ - toolitem = gtk_ui_manager_get_widget(priv->ui_manager, "ui/tools/GoFor"); - - gtk_container_remove (GTK_CONTAINER (toolbar), toolitem); - - priv->popup = gtk_ui_manager_get_widget(priv->ui_manager, "ui/main_popup"); - priv->maillink = gtk_ui_manager_get_widget(priv->ui_manager, "ui/mail_popup"); - priv->merge_id = gtk_ui_manager_new_merge_id (priv->ui_manager); - - priv->find_next_menu = gtk_action_group_get_action (priv->action_group, - "FindNext"); - priv->find_prev_menu = gtk_action_group_get_action (priv->action_group, - "FindPrev"); - - priv->pane = gtk_hpaned_new (); - /* We should probably remember the last position and set to that. */ - gtk_paned_set_position (GTK_PANED (priv->pane), 180); - - priv->side_sw = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->side_sw), - GTK_POLICY_AUTOMATIC, - GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->side_sw), - GTK_SHADOW_IN); - - priv->side_sects = gtk_tree_view_new (); - g_object_set (priv->side_sects, - "headers-visible", FALSE, - NULL); - gtk_tree_view_insert_column_with_attributes - (GTK_TREE_VIEW (priv->side_sects), -1, - NULL, gtk_cell_renderer_text_new (), - "text", YELP_DOCUMENT_COLUMN_TITLE, - NULL); - - /* DISABLE FOR NOW - gtk_tree_view_enable_model_drag_source (GTK_TREE_VIEW (priv->side_sects), - GDK_BUTTON1_MASK, - row_targets, - G_N_ELEMENTS (row_targets), - GDK_ACTION_LINK); - */ - - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->side_sects)); - - g_signal_connect (selection, "changed", - G_CALLBACK (tree_selection_changed_cb), - window); - g_signal_connect (priv->side_sects, "row-activated", - G_CALLBACK (tree_row_expand_cb), - window); - g_signal_connect (priv->side_sects, "drag_data_get", - G_CALLBACK (tree_drag_data_get_cb), - window); - - gtk_container_add (GTK_CONTAINER (priv->side_sw), priv->side_sects); - gtk_paned_add1 (GTK_PANED (priv->pane), priv->side_sw); - - priv->html_pane = gtk_vbox_new (FALSE, 0); - /* Webkit don't like showing scrollbars, so we have to add our - own */ - priv->html_sw = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->html_sw), - GTK_POLICY_AUTOMATIC, - GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->html_sw), - GTK_SHADOW_IN); - - priv->find_bar = gtk_toolbar_new (); - gtk_toolbar_set_style (GTK_TOOLBAR (priv->find_bar), GTK_TOOLBAR_BOTH_HORIZ); - gtk_toolbar_set_icon_size (GTK_TOOLBAR (priv->find_bar), GTK_ICON_SIZE_MENU); - window_populate_find (window, priv->find_bar); - gtk_box_pack_end (GTK_BOX (priv->html_pane), - priv->find_bar, - FALSE, FALSE, 0); - - priv->html_view = yelp_html_new (); - g_signal_connect (priv->html_view, - "uri_selected", - G_CALLBACK (html_uri_selected_cb), - window); - g_signal_connect (priv->html_view, - "frame_selected", - G_CALLBACK (html_frame_selected_cb), - window); - g_signal_connect (priv->html_view, - "title_changed", - G_CALLBACK (html_title_changed_cb), - window); - /* Connect to look for /'s */ - g_signal_connect (window, - "key-press-event", - G_CALLBACK (window_key_event_cb), - window); - gtk_container_add (GTK_CONTAINER (priv->html_sw), - GTK_WIDGET (priv->html_view)); - gtk_box_pack_end (GTK_BOX (priv->html_pane), - GTK_WIDGET (priv->html_sw), - TRUE, TRUE, 0); - gtk_widget_show (priv->html_sw); - gtk_paned_add2 (GTK_PANED (priv->pane), - priv->html_pane); - - gtk_box_pack_start (GTK_BOX (priv->main_box), - priv->pane, - TRUE, TRUE, 0); - - gtk_widget_show (GTK_WIDGET (priv->html_view)); - gtk_widget_show (priv->html_pane); - gtk_widget_show (priv->pane); - gtk_widget_show (priv->main_box); - gtk_container_set_focus_child (GTK_CONTAINER (window), - GTK_WIDGET (priv->html_view)); -} - -static gboolean -window_key_event_cb (GtkWidget *widget, GdkEventKey *event, - YelpWindow *window) -{ - if ((window->priv->search_action && - gtk_entry_action_has_focus ((GtkEntryAction *) window->priv->search_action)) || - GTK_WIDGET_HAS_FOCUS (window->priv->find_entry)) - return FALSE; - - if (event->keyval == GDK_slash) { - window_find_cb (NULL, window); - return TRUE; - } - - return FALSE; -} - -static gboolean -window_find_hide_cb (GtkWidget *widget, GdkEventFocus *event, - YelpWindow *window) -{ - YelpWindowPriv *priv; - - g_return_val_if_fail (YELP_IS_WINDOW (window), FALSE); - - priv = window->priv; - - gtk_widget_hide ((GtkWidget *) priv->find_bar); - return FALSE; -} - - -static void -window_populate_find (YelpWindow *window, - GtkWidget *find_bar) -{ - GtkWidget *box; - GtkWidget *label; - GtkToolItem *item; - GtkWidget *arrow; - YelpWindowPriv *priv = window->priv; - - g_return_if_fail (GTK_IS_TOOLBAR (find_bar)); - - box = gtk_hbox_new (FALSE, 0); - label = gtk_label_new_with_mnemonic (_("Fin_d:")); - gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 6); - - priv->find_entry = gtk_entry_new (); - g_signal_connect (G_OBJECT (priv->find_entry), "changed", - G_CALLBACK (window_find_entry_changed_cb), window); - g_signal_connect (G_OBJECT (priv->find_entry), "activate", - G_CALLBACK (window_find_entry_activate_cb), window); - g_signal_connect (G_OBJECT (priv->find_entry), "key-press-event", - G_CALLBACK (window_find_entry_key_pressed_cb), window); - g_signal_connect (G_OBJECT (priv->find_entry), "focus-out-event", - G_CALLBACK (window_find_hide_cb), window); - gtk_box_pack_start (GTK_BOX (box), priv->find_entry, TRUE, TRUE, 0); - - item = gtk_tool_item_new (); - gtk_container_add (GTK_CONTAINER (item), box); - gtk_toolbar_insert (GTK_TOOLBAR (find_bar), item, -1); - - gtk_label_set_mnemonic_widget (GTK_LABEL (label), priv->find_entry); - - box = gtk_hbox_new (FALSE, 0); - arrow = gtk_arrow_new (GTK_ARROW_LEFT, GTK_SHADOW_NONE); - label = gtk_label_new_with_mnemonic (_("Find _Previous")); - gtk_box_pack_start (GTK_BOX (box), arrow, FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (box), label, TRUE, TRUE, 0); - priv->find_prev = gtk_tool_button_new (box, NULL); - g_signal_connect (priv->find_prev, - "clicked", - G_CALLBACK (window_find_clicked_cb), - window); - gtk_toolbar_insert (GTK_TOOLBAR (find_bar), priv->find_prev, -1); - - box = gtk_hbox_new (FALSE, 0); - arrow = gtk_arrow_new (GTK_ARROW_RIGHT, GTK_SHADOW_NONE); - label = gtk_label_new_with_mnemonic (_("Find _Next")); - gtk_box_pack_start (GTK_BOX (box), arrow, FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (box), label, TRUE, TRUE, 0); - priv->find_next = gtk_tool_button_new (box, NULL); - g_signal_connect (priv->find_next, - "clicked", - G_CALLBACK (window_find_clicked_cb), - window); - gtk_toolbar_insert (GTK_TOOLBAR (find_bar), priv->find_next, -1); - - priv->find_sep = gtk_separator_tool_item_new (); - gtk_toolbar_insert (GTK_TOOLBAR (find_bar), priv->find_sep, -1); - - label = gtk_label_new (_("Phrase not found")); - priv->find_not_found = gtk_tool_item_new (); - - gtk_tool_item_set_expand (priv->find_not_found, TRUE); - gtk_container_add (GTK_CONTAINER (priv->find_not_found), label); - gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); - gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_END); - gtk_toolbar_insert (GTK_TOOLBAR (find_bar), priv->find_not_found, -1); - - item = gtk_separator_tool_item_new (); - gtk_tool_item_set_expand (item, TRUE); - gtk_separator_tool_item_set_draw (GTK_SEPARATOR_TOOL_ITEM (item), FALSE); - gtk_toolbar_insert (GTK_TOOLBAR (find_bar), item, -1); - - item = gtk_tool_button_new_from_stock (GTK_STOCK_CLOSE); - gtk_tool_item_set_is_important (item, FALSE); - g_signal_connect_swapped (item, - "clicked", - G_CALLBACK (gtk_widget_hide), - priv->find_bar); - gtk_toolbar_insert (GTK_TOOLBAR (find_bar), item, -1); -} - -static void -window_set_sections (YelpWindow *window, - GtkTreeModel *sections) -{ - YelpWindowPriv *priv; - - g_return_if_fail (YELP_IS_WINDOW (window)); - priv = window->priv; - - gtk_tree_view_set_model (GTK_TREE_VIEW (priv->side_sects), sections); - - if (sections) { - gtk_widget_show_all (priv->side_sw); - window_set_section_cursor (window, sections); - } else - gtk_widget_hide (priv->side_sw); - -} - -static void -window_set_section_cursor (YelpWindow * window, GtkTreeModel *model) -{ - gboolean valid; - gchar *id = NULL; - GtkTreeIter iter; - YelpWindowPriv *priv = window->priv; - GtkTreeSelection *selection = - gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->side_sects)); - g_signal_handlers_block_by_func (selection, - tree_selection_changed_cb, - window); - gtk_tree_selection_unselect_all (selection); - - valid = gtk_tree_model_get_iter_first (model, &iter); - while (valid) { - gtk_tree_model_get (model, &iter, - YELP_DOCUMENT_COLUMN_ID, &id, - -1); - if (g_str_equal (id, priv->current_frag)) { - GtkTreePath *path = NULL; - GtkTreeIter parent; - if (gtk_tree_model_iter_parent (model, &parent, &iter)) { - path = gtk_tree_model_get_path (model, &parent); - gtk_tree_view_expand_to_path (GTK_TREE_VIEW (priv->side_sects), - path); - gtk_tree_path_free(path); - } - path = gtk_tree_model_get_path (model, &iter); - gtk_tree_selection_select_path (selection, path); - - gtk_tree_path_free (path); - g_free (id); - break; - } - - g_free (id); - - valid = tree_model_iter_following (model, &iter); - } - g_signal_handlers_unblock_by_func (selection, - tree_selection_changed_cb, - window); -} - -static gboolean -window_do_load_html (YelpWindow *window, - gchar *uri, - gchar *frag_id, - YelpRrnType type, - gboolean need_history) -{ - YelpWindowPriv *priv; - GFile *file; - GFileInputStream *stream; - gsize n; - gchar buffer[BUFFER_SIZE]; - GtkAction *action; - gchar *real_uri = NULL; - - gboolean handled = TRUE; - - g_return_val_if_fail (YELP_IS_WINDOW (window), FALSE); - - priv = window->priv; - - window_set_sections (window, NULL); - - action = gtk_action_group_get_action (priv->action_group, "GoPrevious"); - if (action) - g_object_set (G_OBJECT (action), "sensitive", FALSE, NULL); - action = gtk_action_group_get_action (priv->action_group, "GoNext"); - if (action) - g_object_set (G_OBJECT (action), "sensitive", FALSE, NULL); - action = gtk_action_group_get_action (priv->action_group, "GoContents"); - if (action) - g_object_set (G_OBJECT (action), "sensitive", FALSE, NULL); - - window_setup_window (window, type, uri, frag_id, uri, priv->base_uri, need_history); - - if (uri[0] == '/') - file = g_file_new_for_path (uri); - else - file = g_file_new_for_uri (uri); - stream = g_file_read (file, NULL, NULL); - - if (stream == NULL) { - gchar *message; - - message = g_strdup_printf (_("The file ‘%s’ could not be read. This file might " - "be missing, or you might not have permissions to " - "read it."), uri); - window_error (window, _("Could Not Read File"), message, TRUE); - g_free (message); - handled = FALSE; - goto done; - } - - if (frag_id) { - real_uri = g_strconcat (uri, "#", frag_id, NULL); - } else { - real_uri = g_strdup (uri); - } - yelp_html_set_base_uri (priv->html_view, real_uri); - - switch (type) { - case YELP_RRN_TYPE_HTML: - yelp_html_open_stream (priv->html_view, "text/html"); - break; - case YELP_RRN_TYPE_XHTML: - yelp_html_open_stream (priv->html_view, "application/xhtml+xml"); - break; - case YELP_RRN_TYPE_TEXT: - yelp_html_open_stream (priv->html_view, "text/plain"); - break; - default: - g_assert_not_reached (); - } - - while ((g_input_stream_read_all - ((GInputStream *)stream, buffer, BUFFER_SIZE, &n, NULL, NULL)) && n) { - gchar *tmp; - - if (n == 0) - break; - - tmp = g_utf8_strup (buffer, n); - if (strstr (tmp, "html_view, TRUE); - } - g_free (tmp); - - yelp_html_write (priv->html_view, buffer, n); - } - yelp_html_close (priv->html_view); - - done: - if (file) - g_object_unref (file); - if (stream) - g_object_unref (stream); - - g_free (real_uri); - gdk_window_set_cursor (GTK_WIDGET (window)->window, NULL); - - return handled; -} - -static void -window_set_loading (YelpWindow *window) -{ - YelpWindowPriv *priv; - GtkAction *action; - GdkCursor *cursor; - gchar *loading = _("Loading..."); - - g_return_if_fail (YELP_IS_WINDOW (window)); - - priv = window->priv; - - cursor = gdk_cursor_new (GDK_WATCH); - gdk_window_set_cursor (GTK_WIDGET (window)->window, cursor); - gdk_cursor_unref (cursor); - - action = gtk_action_group_get_action (priv->action_group, "GoPrevious"); - if (action) - g_object_set (G_OBJECT (action), "sensitive", FALSE, NULL); - action = gtk_action_group_get_action (priv->action_group, "GoNext"); - if (action) - g_object_set (G_OBJECT (action), "sensitive", FALSE, NULL); - action = gtk_action_group_get_action (priv->action_group, "GoContents"); - if (action) - g_object_set (G_OBJECT (action), "sensitive", FALSE, NULL); - - gtk_window_set_title (GTK_WINDOW (window), - (const gchar *) loading); - -} - -/** Window Callbacks **********************************************************/ - -static gboolean -window_configure_cb (GtkWidget *widget, - GdkEventConfigure *event, - gpointer data) -{ - gint width, height; - GKeyFile *keyfile; - GError *config_error = NULL; - gchar *sdata, *config_path; - gsize config_size; - - gtk_window_get_size (GTK_WINDOW (widget), &width, &height); - - keyfile = g_key_file_new(); - - config_path = g_strconcat (g_get_home_dir(), YELP_CONFIG_PATH, NULL); - - g_key_file_set_integer (keyfile, YELP_CONFIG_GEOMETRY_GROUP, - YELP_CONFIG_WIDTH, width); - g_key_file_set_integer (keyfile, YELP_CONFIG_GEOMETRY_GROUP, - YELP_CONFIG_HEIGHT, height); - - sdata = g_key_file_to_data (keyfile, &config_size, NULL); - - if ( !g_file_set_contents (config_path, sdata, - config_size, &config_error) ) { - g_warning ("Failed to save config file: %s\n", config_error->message); - g_error_free (config_error); - } - - g_free (sdata); - g_free (config_path); - g_key_file_free (keyfile); - - return FALSE; -} - -/** Gecko Callbacks ***********************************************************/ - -static void -html_uri_selected_cb (YelpHtml *html, - gchar *uri, - gboolean handled, - gpointer user_data) -{ - YelpWindow *window = YELP_WINDOW (user_data); - - debug_print (DB_FUNCTION, "entering\n"); - debug_print (DB_ARG, " uri = \"%s\"\n", uri); - - if (!handled) { - yelp_window_load (window, uri); - } -} - -static gboolean -html_frame_selected_cb (YelpHtml *html, gchar *uri, gboolean handled, - gpointer user_data) -{ - YelpWindow *window = YELP_WINDOW (user_data); - gboolean handle; - - switch (window->priv->current_type) { - case YELP_RRN_TYPE_XHTML: - case YELP_RRN_TYPE_HTML: - case YELP_RRN_TYPE_TEXT: - handle = TRUE; - break; - default: - handle = FALSE; - break; - } - if (handle) { - return FALSE; - } else { - yelp_window_load (window, uri); - } - return TRUE; -} - - -static void html_title_changed_cb (YelpHtml *html, - gpointer webframe, - gchar *title, - gpointer user_data) -{ - - gtk_window_set_title (GTK_WINDOW (user_data), title); -} - - -/** GtkTreeView Callbacks *****************************************************/ - -static void -tree_selection_changed_cb (GtkTreeSelection *selection, - YelpWindow *window) -{ - YelpWindowPriv *priv; - GtkTreeModel *model; - GtkTreeIter iter; - gchar *id, *uri; - - g_return_if_fail (YELP_IS_WINDOW (window)); - - priv = window->priv; - - if (gtk_tree_selection_get_selected (selection, NULL, &iter)) { - model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->side_sects)); - gtk_tree_model_get (model, &iter, - YELP_DOCUMENT_COLUMN_ID, &id, - -1); - uri = g_strdup_printf ("%s?%s", priv->base_uri, id); - yelp_window_load (window, uri); - g_free (uri); - } -} - -static void -tree_drag_data_get_cb (GtkWidget *widget, - GdkDragContext *context, - GtkSelectionData *selection, - guint info, - guint32 time, - YelpWindow *window) -{ - /* TODO: This is disabled by default anyway */ -#if 0 - YelpWindowPriv *priv; - GtkTreeSelection *tree_selection; - GtkTreeModel *model; - GtkTreeIter iter; - gchar *id, *uri = NULL; - - g_return_if_fail (YELP_IS_WINDOW (window)); - - debug_print (DB_FUNCTION, "entering\n"); - - priv = window->priv; - - tree_selection = - gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->side_sects)); - - if (gtk_tree_selection_get_selected (tree_selection, NULL, &iter)) { - model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->side_sects)); - gtk_tree_model_get (model, &iter, - YELP_DOCUMENT_COLUMN_ID, &id, - -1); - uri = yelp_doc_info_get_uri (priv->current_doc, id, - YELP_URI_TYPE_NO_FILE); - if (!uri) - uri = yelp_doc_info_get_uri (priv->current_doc, id, - YELP_URI_TYPE_FILE); - } - - switch (info) { - case TARGET_URI_LIST: - gtk_selection_data_set (selection, - selection->target, - 8, (const guchar *) uri, strlen (uri)); - break; - default: - g_assert_not_reached (); - } - - g_free (uri); -#endif -} - -void -tree_row_expand_cb (GtkTreeView *view, GtkTreePath *path, - GtkTreeViewColumn *column, YelpWindow *window) -{ - if (gtk_tree_view_row_expanded (view, path)) { - gtk_tree_view_collapse_row (view, path); - } else { - gtk_tree_view_expand_to_path (view, path); - } - -} - - -/** UIManager Callbacks *******************************************************/ - -static void -window_add_widget (GtkUIManager *ui_manager, - GtkWidget *widget, - GtkWidget *vbox) -{ - gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, FALSE, 0); -} - -static void -window_new_window_cb (GtkAction *action, YelpWindow *window) -{ - g_return_if_fail (YELP_IS_WINDOW (window)); - - g_signal_emit (window, signals[NEW_WINDOW_REQUESTED], 0, NULL); -} - - -typedef struct { - YelpWindow *window; - GtkWindow *gtk_win; - GtkVBox *vbox; - YelpHtml *html; -} PrintStruct; - -static void -window_print_signal (YelpDocument *document, - YelpDocumentSignal signal, - gint req_id, - gpointer *func_data, - PrintStruct *print) -{ - YelpError *error; - - switch (signal) { - case YELP_DOCUMENT_SIGNAL_PAGE: - window_write_html (print->window, print->html, (YelpPage *) func_data); - yelp_page_free ((YelpPage *) func_data); - yelp_html_print (print->html); - break; - case YELP_DOCUMENT_SIGNAL_TITLE: - g_free (func_data); - break; - case YELP_DOCUMENT_SIGNAL_ERROR: - error = (YelpError *) func_data; - window_error (print->window, (gchar *) yelp_error_get_title (error), - (gchar *) yelp_error_get_message (error), FALSE); - yelp_error_free (error); - break; - default: - g_assert_not_reached(); - } - -} - - -static void -window_print_document_cb (GtkAction *action, YelpWindow *window) -{ - YelpWindowPriv *priv; - GtkWidget *gtk_win; - YelpHtml *html; - GtkWidget *vbox = gtk_vbox_new (FALSE, FALSE); - PrintStruct *print; - YelpDocument *doc = NULL; - - priv = window->priv; - - switch (priv->current_type) { - case YELP_RRN_TYPE_DOC: - doc = yelp_dbprint_new (priv->uri); - break; - default: - g_assert_not_reached (); - return; - } - - - gtk_win = gtk_window_new (GTK_WINDOW_TOPLEVEL); - html = yelp_html_new (); - - gtk_container_add (GTK_CONTAINER (gtk_win), GTK_WIDGET (vbox)); - gtk_box_pack_end (GTK_BOX (vbox), GTK_WIDGET (html), TRUE, TRUE, 0); - gtk_widget_show (gtk_win); - gtk_widget_show (vbox); - gtk_widget_show (GTK_WIDGET (html)); - gtk_widget_hide (gtk_win); - - print = g_new0 (PrintStruct, 1); - - print->window = window; - print->gtk_win = (GtkWindow *) gtk_win; - print->vbox = (GtkVBox *) vbox; - print->html = html; - - yelp_document_get_page (doc, - "x-yelp-index", - (YelpDocumentFunc) window_print_signal, - (void *) print); -} - -static void -window_print_page_cb (GtkAction *action, YelpWindow *window) -{ - YelpWindowPriv *priv; - GtkWidget *gtk_win; - YelpHtml *html; - GtkWidget *vbox = gtk_vbox_new (FALSE, FALSE); - PrintStruct *print; - - priv = window->priv; - - gtk_win = gtk_window_new (GTK_WINDOW_TOPLEVEL); - html = yelp_html_new (); - - gtk_container_add (GTK_CONTAINER (gtk_win), GTK_WIDGET (vbox)); - gtk_box_pack_end (GTK_BOX (vbox), GTK_WIDGET (html), TRUE, TRUE, 0); - gtk_widget_show (gtk_win); - gtk_widget_show (vbox); - gtk_widget_show (GTK_WIDGET (html)); - gtk_widget_hide (gtk_win); - - print = g_new0 (PrintStruct, 1); - - print->window = window; - print->gtk_win = (GtkWindow *) gtk_win; - print->vbox = (GtkVBox *) vbox; - print->html = html; - - - if (priv->current_document) { - /* Need to go through the paging system */ - yelp_document_get_page (priv->current_document, - priv->current_frag, - (YelpDocumentFunc) window_print_signal, - (void *) print); - - } else { - /* HTML file */ - - GFile *file; - GFileInputStream *stream; - gsize n; - gchar buffer[BUFFER_SIZE]; - - file = g_file_new_for_uri (priv->uri); - stream = g_file_read (file, NULL, NULL); - - if (stream == NULL) { - /*GError *error = NULL; - g_set_error (&error, YELP_ERROR, YELP_ERROR_IO, - _("The file ‘%s’ could not be read. This file might " - "be missing, or you might not have permissions to " - "read it."), - uri); - window_error (window, error, TRUE);*/ - /* TODO: Proper errors */ - - if (file) - g_object_unref (file); - if (stream) - g_object_unref (stream); - return; - } - /* Assuming the file exists. If it doesn't how did we get this far? - * There are more sinister forces at work... - */ - - switch (priv->current_type) { - case YELP_RRN_TYPE_HTML: - yelp_html_open_stream (html, "text/html"); - break; - case YELP_RRN_TYPE_XHTML: - yelp_html_open_stream (html, "application/xhtml+xml"); - break; - case YELP_RRN_TYPE_TEXT: - yelp_html_open_stream (html, "text/plain"); - break; - default: - g_assert_not_reached (); - } - - while ((g_input_stream_read_all - ((GInputStream *)stream, buffer, BUFFER_SIZE, &n, NULL, NULL))) { - yelp_html_write (html, buffer, n); - } - - yelp_html_print (html); - - if (file) - g_object_unref (file); - if (stream) - g_object_unref (stream); - - yelp_html_close (html); - - } -} - -static void -window_about_document_cb (GtkAction *action, YelpWindow *window) -{ - YelpWindowPriv *priv; - gchar *uri; - - g_return_if_fail (YELP_IS_WINDOW (window)); - - priv = window->priv; - - uri = g_strdup_printf("%s#__yelp_info", priv->uri); - - yelp_window_load (window, uri); - g_free (uri); -} - -static void -window_open_location_cb (GtkAction *action, YelpWindow *window) -{ - YelpWindowPriv *priv; - GtkBuilder *builder; - GError *error = NULL; - GtkWidget *dialog; - GtkWidget *entry; - gchar *uri = NULL; - - g_return_if_fail (YELP_IS_WINDOW (window)); - - priv = window->priv; - - builder = gtk_builder_new (); - if (!gtk_builder_add_from_file (builder, - DATADIR "/yelp/ui/yelp-open-location.ui", - &error)) { - g_warning ("Could not load builder file: %s", error->message); - g_error_free(error); - return; - } - - dialog = GTK_WIDGET (gtk_builder_get_object (builder, "location_dialog")); - entry = GTK_WIDGET (gtk_builder_get_object (builder, "location_entry")); - - priv->location_dialog = dialog; - priv->location_entry = entry; - - uri = priv->req_uri; - if (uri) { - gtk_entry_set_text (GTK_ENTRY (entry), uri); - gtk_editable_select_region (GTK_EDITABLE (entry), 0, -1); - } - - gtk_window_set_transient_for (GTK_WINDOW (dialog), - GTK_WINDOW (window)); - g_signal_connect (G_OBJECT (dialog), - "response", - G_CALLBACK (location_response_cb), - window); - - gtk_window_present (GTK_WINDOW (dialog)); -} - -static void -window_close_window_cb (GtkAction *action, YelpWindow *window) -{ - gtk_widget_destroy (GTK_WIDGET (window)); -} - -static void -window_copy_cb (GtkAction *action, YelpWindow *window) -{ - GtkWidget *widget; - - g_return_if_fail (YELP_IS_WINDOW (window)); - - widget = gtk_window_get_focus (GTK_WINDOW (window)); - - if (GTK_IS_EDITABLE (widget)) { - gtk_editable_copy_clipboard (GTK_EDITABLE (widget)); - } else { - yelp_html_copy_selection (window->priv->html_view); - } -} - -static void -window_select_all_cb (GtkAction *action, YelpWindow *window) -{ - GtkWidget *widget; - - g_return_if_fail (YELP_IS_WINDOW (window)); - - widget = gtk_window_get_focus (GTK_WINDOW (window)); - - if (GTK_IS_EDITABLE (widget)) { - gtk_editable_select_region (GTK_EDITABLE (widget), 0, -1); - } else { - yelp_html_select_all (window->priv->html_view); - } -} - -static void -window_find_cb (GtkAction *action, YelpWindow *window) -{ - YelpWindowPriv *priv; - - g_return_if_fail (YELP_IS_WINDOW (window)); - - priv = window->priv; - - debug_print (DB_FUNCTION, "entering\n"); - - gtk_widget_show_all (priv->find_bar); - gtk_widget_hide (GTK_WIDGET (priv->find_not_found)); - gtk_widget_hide (GTK_WIDGET (priv->find_sep)); - gtk_widget_grab_focus (priv->find_entry); - window_find_entry_changed_cb (GTK_EDITABLE (priv->find_entry), window); -} - -static void -window_preferences_cb (GtkAction *action, YelpWindow *window) -{ - g_return_if_fail (YELP_IS_WINDOW (window)); - - yelp_settings_open_preferences (); -} - -static void -window_reload_cb (GtkAction *action, YelpWindow *window) -{ - if (window->priv->current_document) { - if (window->priv->current_request > -1) { - yelp_document_cancel_page (window->priv->current_document, window->priv->current_request); - } - g_free (window->priv->uri); - window->priv->uri = NULL; - g_object_unref (window->priv->current_document); - window->priv->current_document = NULL; - yelp_window_load (window, window->priv->req_uri); - } -} - -static void -window_enable_cursor_cb (GtkAction *action, YelpWindow *window) -{ - yelp_settings_toggle_caret (); -} - -static void -history_load_entry (YelpWindow *window, YelpHistoryEntry *entry) -{ - gchar *slash, *frag_id; - g_return_if_fail (YELP_IS_WINDOW (window)); - - if (entry->type == YELP_RRN_TYPE_HTML || entry->type == YELP_RRN_TYPE_XHTML || entry->type == YELP_RRN_TYPE_TEXT) { - window_do_load_html (window, entry->uri, entry->frag_id, entry->type, FALSE); - } else { - g_assert (entry->doc != NULL); - window_setup_window (window, entry->type, entry->uri, entry->frag_id, entry->req_uri, - window->priv->base_uri, FALSE); - if (window->priv->base_uri) - g_free (window->priv->base_uri); - window->priv->base_uri = g_strdup (entry->base_uri); - window->priv->current_document = entry->doc; - - /* FIXME: Super hacky. We want the part before the slash for mallard IDs, - because right now we're outputting "#page_id/section_id". We ought to - be scrolling to the section as well. - */ - slash = strchr (entry->frag_id, '/'); - if (slash) - frag_id = g_strndup (entry->frag_id, slash - entry->frag_id); - else - frag_id = g_strdup (entry->frag_id); - window->priv->current_request = yelp_document_get_page (entry->doc, - frag_id, - (YelpDocumentFunc) page_request_cb, - (void *) window); - g_free (frag_id); - } - -} - - -static void -window_go_back_cb (GtkAction *action, YelpWindow *window) -{ - YelpWindowPriv *priv; - YelpHistoryEntry *entry; - - g_return_if_fail (YELP_IS_WINDOW (window)); - g_return_if_fail (window->priv->history_back != NULL); - - priv = window->priv; - - history_push_forward (window); - - entry = history_pop_back (window); - - history_load_entry (window, entry); - - history_entry_free (entry); -} - -static void -window_go_forward_cb (GtkAction *action, YelpWindow *window) -{ - YelpWindowPriv *priv; - YelpHistoryEntry *entry; - - g_return_if_fail (YELP_IS_WINDOW (window)); - g_return_if_fail (window->priv->history_forward != NULL); - - priv = window->priv; - - history_push_back (window); - - entry = history_pop_forward (window); - - history_load_entry (window, entry); - - history_entry_free (entry); -} - -static void -window_go_home_cb (GtkAction *action, YelpWindow *window) -{ - debug_print (DB_FUNCTION, "entering\n"); - g_return_if_fail (YELP_IS_WINDOW (window)); - yelp_window_load (window, "x-yelp-toc:"); -} - -static void -window_go_previous_cb (GtkAction *action, YelpWindow *window) -{ - printf ("Prev: %s\n", window->priv->prev_id); -#if 0 - YelpWindowPriv *priv; - gchar *base, *uri; - - debug_print (DB_FUNCTION, "entering\n"); - g_return_if_fail (YELP_IS_WINDOW (window)); - g_return_if_fail (window->priv->current_doc); - priv = window->priv; - - base = yelp_doc_info_get_uri (priv->current_doc, NULL, YELP_URI_TYPE_ANY); - uri = yelp_uri_get_relative (base, priv->prev_id); - - yelp_window_load (window, uri); - - g_free (uri); - g_free (base); -#endif -} - -static void -window_go_next_cb (GtkAction *action, YelpWindow *window) -{ - printf ("Next: %s\n", window->priv->next_id); -#if 0 - YelpWindowPriv *priv; - gchar *base, *uri; - - debug_print (DB_FUNCTION, "entering\n"); - g_return_if_fail (YELP_IS_WINDOW (window)); - g_return_if_fail (window->priv->current_doc); - priv = window->priv; - - base = yelp_doc_info_get_uri (priv->current_doc, NULL, YELP_URI_TYPE_ANY); - uri = yelp_uri_get_relative (base, priv->next_id); - - yelp_window_load (window, uri); - - g_free (uri); - g_free (base); -#endif -} - -static void -window_go_toc_cb (GtkAction *action, YelpWindow *window) -{ - printf ("index toc: %s\n", window->priv->toc_id); -#if 0 - YelpWindowPriv *priv; - gchar *base, *uri; - - debug_print (DB_FUNCTION, "entering\n"); - g_return_if_fail (YELP_IS_WINDOW (window)); - g_return_if_fail (window->priv->current_doc); - priv = window->priv; - - base = yelp_doc_info_get_uri (priv->current_doc, NULL, YELP_URI_TYPE_ANY); - uri = yelp_uri_get_relative (base, priv->toc_id); - - yelp_window_load (window, uri); - - g_free (uri); - g_free (base); -#endif -} - -static void -window_add_bookmark_cb (GtkAction *action, YelpWindow *window) -{ - YelpWindowPriv *priv = window->priv; - - debug_print (DB_FUNCTION, "entering\n"); - - if (!priv->req_uri) - return; - - yelp_bookmarks_add (priv->req_uri, window); - -} - -static void window_copy_link_cb (GtkAction *action, YelpWindow *window) -{ - gtk_clipboard_set_text (gtk_clipboard_get (gdk_atom_intern ("CLIPBOARD", - TRUE)), - window->priv->uri, - -1); -} - -static void -window_open_link_cb (GtkAction *action, YelpWindow *window) -{ - yelp_window_load (window, window->priv->uri); -} - -static void -window_open_link_new_cb (GtkAction *action, YelpWindow *window) -{ - g_signal_emit (window, signals[NEW_WINDOW_REQUESTED], 0, - window->priv->uri); -} - -/* TODO: This doesn't work... */ -static void -window_copy_mail_cb (GtkAction *action, YelpWindow *window) -{ - /*Do things the simple way. - * Split the string and remove any query bit then - * remove the first 7 chars as they should be mailto: - */ - gchar **split_string = g_strsplit (window->priv->uri, "?", 2); - - gchar *mail_address = &split_string[0][7]; - - gtk_clipboard_set_text (gtk_clipboard_get (gdk_atom_intern ("CLIPBOARD", - TRUE)), - mail_address, - -1); - g_free (window->priv->uri); - g_strfreev(split_string); -} - -static void -window_help_contents_cb (GtkAction *action, YelpWindow *window) -{ - /* Since we are already running, and are calling ourselves, - * we can make this function easy by just creating a new window - * and avoiding calling gnome_help_display_desktop - */ - g_signal_emit (window, signals[NEW_WINDOW_REQUESTED], 0, - "ghelp:user-guide#yelp"); -} - -static void -window_about_cb (GtkAction *action, YelpWindow *window) -{ - const gchar *copyright = - "Copyright © 2001-2003 Mikael Hallendal\n" - "Copyright © 2003-2009 Shaun McCance\n" - "Copyright © 2005-2006 Don Scorgie\n" - "Copyright © 2005-2006 Brent Smith"; - const gchar *authors[] = { - "Mikael Hallendal ", - "Alexander Larsson ", - "Shaun McCance ", - "Don Scorgie ", - "Brent Smith ", - NULL - }; - /* Note to translators: put here your name (and address) so it - * will show up in the "about" box */ - const gchar *translator_credits = _("translator-credits"); - - gtk_show_about_dialog (GTK_WINDOW (window), - "name", _("Yelp"), - "version", VERSION, - "comments", _("A documentation browser and " - "viewer for the Gnome Desktop."), - "copyright", copyright, - "authors", authors, - "translator-credits", translator_credits, - "logo-icon-name", "help-browser", - NULL); -} - -/******************************************************************************/ - -static void -location_response_cb (GtkDialog *dialog, gint id, YelpWindow *window) -{ - g_return_if_fail (YELP_IS_WINDOW (window)); - - debug_print (DB_FUNCTION, "entering\n"); - debug_print (DB_ARG, " id = %i\n", id); - - if (id == GTK_RESPONSE_OK) { - const gchar *uri = - gtk_entry_get_text (GTK_ENTRY (window->priv->location_entry)); - - yelp_window_load (window, uri); - } - - window->priv->location_dialog = NULL; - window->priv->location_entry = NULL; - gtk_widget_destroy (GTK_WIDGET (dialog)); -} - -static void -window_find_save_settings (YelpWindow *window) -{ - YelpWindowPriv *priv; - const gchar *tmp; - - g_return_if_fail (YELP_IS_WINDOW (window)); - - priv = window->priv; - - tmp = gtk_entry_get_text (GTK_ENTRY (priv->find_entry)); - - g_free (priv->find_string); - - priv->find_string = g_utf8_casefold (tmp, -1); -} - -static gboolean -window_find_action (YelpWindow *window) -{ - YelpWindowPriv *priv = window->priv; - - window_find_save_settings (window); - - yelp_html_set_find_props (priv->html_view, priv->find_string, FALSE, FALSE); - - return yelp_html_find (priv->html_view, priv->find_string); -} - -static gboolean -window_find_again (YelpWindow *window, gboolean forward) -{ - YelpWindowPriv *priv = window->priv; - - return yelp_html_find_again (priv->html_view, forward); -} - -static void -window_find_previous_cb (GtkAction *action, YelpWindow *window) -{ - YelpWindowPriv * priv; - - priv = window->priv; - if (!window_find_again (window, FALSE)) { - window_find_buttons_set_sensitive (window, FALSE, TRUE); - } else { - window_find_buttons_set_sensitive (window, TRUE, TRUE); - } -} - -static void -window_find_next_cb (GtkAction *action, YelpWindow *window) -{ - YelpWindowPriv * priv; - - priv = window->priv; - if (!window_find_again (window, TRUE)) { - window_find_buttons_set_sensitive (window, TRUE, FALSE); - } else { - window_find_buttons_set_sensitive (window, TRUE, TRUE); - } -} - -static void -window_find_clicked_cb (GtkWidget *widget, - YelpWindow *window) -{ - YelpWindowPriv * priv; - - g_return_if_fail (GTK_IS_TOOL_ITEM (widget)); - - priv = window->priv; - - if (GTK_TOOL_ITEM (widget) == priv->find_next) { - if (!window_find_again (window, TRUE)) { - window_find_buttons_set_sensitive (window, TRUE, FALSE); - } else { - window_find_buttons_set_sensitive (window, TRUE, TRUE); - } - } - else if (GTK_TOOL_ITEM (widget) == priv->find_prev) { - if (!window_find_again (window, FALSE)) { - window_find_buttons_set_sensitive (window, FALSE, TRUE); - } else { - window_find_buttons_set_sensitive (window, TRUE, TRUE); - } - } - else - g_assert_not_reached (); -} - -static void -window_find_entry_changed_cb (GtkEditable *editable, - gpointer data) -{ - YelpWindow *window; - YelpWindowPriv *priv; - gchar *text; - gboolean found; - - g_return_if_fail (YELP_IS_WINDOW(data)); - - window = YELP_WINDOW (data); - priv = window->priv; - - text = gtk_editable_get_chars (editable, 0, -1); - - found = window_find_action (window); - - if (text == NULL || text[0] == '\0') - window_find_buttons_set_sensitive (window, FALSE, FALSE); - else - if (found) { - gtk_widget_hide (GTK_WIDGET (priv->find_sep)); - gtk_widget_hide (GTK_WIDGET (priv->find_not_found)); - window_find_buttons_set_sensitive (window, FALSE, TRUE); - } else { - gtk_widget_show_all (GTK_WIDGET (priv->find_sep)); - gtk_widget_show_all (GTK_WIDGET (priv->find_not_found)); - window_find_buttons_set_sensitive (window, TRUE, TRUE); - } - - g_free (text); -} - -static void -window_find_entry_activate_cb (GtkEditable *editable, - gpointer data) -{ - YelpWindow *window; - YelpWindowPriv *priv; - - g_return_if_fail (YELP_IS_WINDOW (data)); - - window = YELP_WINDOW (data); - priv = window->priv; - - /* search forward and update the buttons */ - if (!window_find_again (window, TRUE)) { - window_find_buttons_set_sensitive (window, TRUE, FALSE); - } else { - window_find_buttons_set_sensitive (window, TRUE, TRUE); - } -} - -static gboolean -window_find_entry_key_pressed_cb (GtkWidget *widget, - GdkEventKey *key, - gpointer data) -{ - YelpWindow *window; - YelpWindowPriv *priv; - - debug_print (DB_FUNCTION, "entering\n"); - - if (key->keyval == GDK_Escape) { - g_return_val_if_fail (YELP_IS_WINDOW (data), FALSE); - - window = YELP_WINDOW (data); - priv = window->priv; - - gtk_widget_hide_all (priv->find_bar); - - return TRUE; - } - - return FALSE; -} - -static void -window_find_buttons_set_sensitive (YelpWindow *window, - gboolean prev, gboolean next) -{ - YelpWindowPriv *priv; - - priv = window->priv; - - gtk_widget_set_sensitive (GTK_WIDGET (priv->find_next), next); - gtk_widget_set_sensitive (GTK_WIDGET (priv->find_prev), prev); - g_object_set (G_OBJECT (priv->find_next_menu), "sensitive", next, - NULL); - g_object_set (G_OBJECT (priv->find_prev_menu), "sensitive", prev, - NULL); -} - -static gboolean -tree_model_iter_following (GtkTreeModel *model, - GtkTreeIter *iter) -{ - gboolean valid; - GtkTreeIter *old_iter = gtk_tree_iter_copy (iter); - - if (gtk_tree_model_iter_has_child (model, iter)) { - gboolean ret_val; - ret_val = gtk_tree_model_iter_children (model, iter, old_iter); - gtk_tree_iter_free (old_iter); - return ret_val; - } - else do { - valid = gtk_tree_model_iter_next (model, iter); - - if (valid) { - gtk_tree_iter_free (old_iter); - return TRUE; - } - - valid = gtk_tree_model_iter_parent (model, iter, old_iter); - - if (!valid) { - gtk_tree_iter_free (old_iter); - return FALSE; - } - - *old_iter = *iter; - - } while (TRUE); - - g_assert_not_reached (); - return FALSE; -} - -static void -window_write_html (YelpWindow *window, YelpHtml *html, YelpPage *page) -{ - gchar *uri = NULL; - gsize read; - gchar contents[BUFFER_SIZE]; - - if (!html) - html = window->priv->html_view; - - /* Use a silly fake URI to stop gecko doing silly things */ - if (data->window->priv->current_frag) { - /* FIXME: more of this terrible slash hack */ - gchar *slash, *jump_id; - slash = strchr (data->window->priv->current_frag, '/'); - if (slash) - jump_id = slash + 1; - else - jump_id = data->window->priv->current_frag; - uri = g_strdup_printf ("%s#%s", data->window->priv->base_uri, jump_id); - } - else - uri = g_strdup (window->priv->base_uri); - - yelp_html_set_base_uri (html, uri); - g_free (uri); - yelp_html_open_stream (html, "application/xhtml+xml"); + YelpWindowPrivate *priv = GET_PRIV (window); - do { - yelp_page_read (page, contents, BUFFER_SIZE, &read, NULL); - yelp_html_write (html, contents, read); - } while (read == BUFFER_SIZE); - yelp_html_close (html); + yelp_view_load_uri (priv->view, uri); } diff --git a/src/yelp-window.h b/src/yelp-window.h index dc4929d6..47d3bd96 100644 --- a/src/yelp-window.h +++ b/src/yelp-window.h @@ -1,6 +1,6 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* - * Copyright (C) 2001-2002 Mikael Hallendal + * Copyright (C) 2010 Shaun McCance * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -17,7 +17,7 @@ * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * - * Author: Mikael Hallendal + * Author: Shaun McCance */ #ifndef __YELP_WINDOW_H__ @@ -25,42 +25,30 @@ #include -#include "yelp-base.h" -#include "yelp-utils.h" +#include "yelp-uri.h" -#define YELP_TYPE_WINDOW (yelp_window_get_type ()) -#define YELP_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), YELP_TYPE_WINDOW, YelpWindow)) -#define YELP_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), YELP_TYPE_WINDOW, YelpWindowClass)) -#define YELP_IS_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), YELP_TYPE_WINDOW)) -#define YELP_IS_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), YELP_TYPE_WINDOW)) +#define YELP_TYPE_WINDOW (yelp_window_get_type ()) +#define YELP_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), YELP_TYPE_WINDOW, YelpWindow)) +#define YELP_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), YELP_TYPE_WINDOW, YelpWindowClass)) +#define YELP_IS_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), YELP_TYPE_WINDOW)) +#define YELP_IS_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), YELP_TYPE_WINDOW)) typedef struct _YelpWindow YelpWindow; typedef struct _YelpWindowClass YelpWindowClass; -typedef struct _YelpWindowPriv YelpWindowPriv; struct _YelpWindow { GtkWindow parent; - - YelpWindowPriv *priv; }; struct _YelpWindowClass { GtkWindowClass parent_class; - - /* Signals */ - void (*new_window_requested) (YelpWindow *window); - void (*new_window_requested_uri) (YelpWindow *window, - const gchar *uri); }; -GType yelp_window_get_type (void); -GtkWidget * yelp_window_new (GNode *doc_tree, - GList *index); -void yelp_window_load (YelpWindow *window, - const gchar *uri); -const gchar * yelp_window_get_uri (YelpWindow *window); -GtkUIManager * yelp_window_get_ui_manager (YelpWindow *window); +GType yelp_window_get_type (void); +YelpWindow * yelp_window_new (YelpApplication *app); +void yelp_window_load_uri (YelpWindow *window, + YelpUri *uri); #endif /* __YELP_WINDOW_H__ */ -- cgit v1.2.1