diff options
-rw-r--r-- | Makefile.sources | 2 | ||||
-rw-r--r-- | desktop/browser.c | 15 | ||||
-rw-r--r-- | desktop/browser.h | 2 | ||||
-rw-r--r-- | desktop/frames.c | 4 | ||||
-rw-r--r-- | desktop/gui.h | 2 | ||||
-rw-r--r-- | desktop/history_core.c | 2 | ||||
-rw-r--r-- | gtk/gtk_bitmap.c | 13 | ||||
-rw-r--r-- | gtk/gtk_gui.c | 2 | ||||
-rw-r--r-- | gtk/gtk_history.c | 605 | ||||
-rw-r--r-- | gtk/gtk_history.h | 19 | ||||
-rw-r--r-- | gtk/gtk_scaffolding.c | 100 | ||||
-rw-r--r-- | gtk/gtk_scaffolding.h | 6 | ||||
-rw-r--r-- | gtk/gtk_selection.c | 2 | ||||
-rw-r--r-- | gtk/gtk_tabs.c | 154 | ||||
-rw-r--r-- | gtk/gtk_tabs.h | 26 | ||||
-rw-r--r-- | gtk/gtk_window.c | 44 | ||||
-rw-r--r-- | gtk/gtk_window.h | 1 | ||||
-rw-r--r-- | gtk/res/downloads.glade | 1 | ||||
-rw-r--r-- | gtk/res/history.glade | 304 | ||||
-rw-r--r-- | gtk/res/netsurf.glade | 413 | ||||
-rw-r--r-- | riscos/dialog.c | 2 | ||||
-rw-r--r-- | riscos/gui.c | 13 | ||||
-rw-r--r-- | riscos/menus.c | 2 | ||||
-rw-r--r-- | riscos/plugin.c | 3 | ||||
-rw-r--r-- | riscos/treeview.c | 2 | ||||
-rw-r--r-- | riscos/uri.c | 2 | ||||
-rw-r--r-- | riscos/url_protocol.c | 2 | ||||
-rw-r--r-- | riscos/window.c | 9 |
28 files changed, 1348 insertions, 404 deletions
diff --git a/Makefile.sources b/Makefile.sources index f499c9e89..ecc0d6b87 100644 --- a/Makefile.sources +++ b/Makefile.sources @@ -63,7 +63,7 @@ S_GTK := font_pango.c gtk_bitmap.c gtk_gui.c gtk_schedule.c \ gtk_thumbnail.c gtk_plotters.c gtk_treeview.c gtk_scaffolding.c \ gtk_completion.c gtk_login.c gtk_throbber.c gtk_selection.c \ gtk_history.c gtk_window.c gtk_filetype.c gtk_download.c \ - gtk_print.c \ + gtk_print.c gtk_tabs.c \ $(addprefix dialogs/,gtk_options.c gtk_about.c) S_GTK := $(addprefix gtk/,$(S_GTK)) diff --git a/desktop/browser.c b/desktop/browser.c index 899457b74..ce9e79ce1 100644 --- a/desktop/browser.c +++ b/desktop/browser.c @@ -140,7 +140,7 @@ static void browser_window_scroll_box(struct browser_window *bw, struct browser_window *browser_window_create(const char *url, struct browser_window *clone, - const char *referer, bool history_add) + const char *referer, bool history_add, bool new_tab) { struct browser_window *bw; @@ -156,12 +156,12 @@ struct browser_window *browser_window_create(const char *url, /* window characteristics */ bw->browser_window_type = BROWSER_WINDOW_NORMAL; - bw->scrolling = SCROLLING_YES; + bw->scrolling = SCROLLING_AUTO; bw->border = true; bw->no_resize = true; /* gui window */ - if ((bw->window = gui_create_browser_window(bw, clone)) == NULL) { + if ((bw->window = gui_create_browser_window(bw, clone, new_tab)) == NULL) { browser_window_destroy(bw); return NULL; } @@ -1096,7 +1096,7 @@ struct browser_window *browser_window_find_target(struct browser_window *bw, con /* handle reserved keywords */ if ((new_window) || ((target == TARGET_BLANK) || (!strcasecmp(target, "_blank")))) { - bw_target = browser_window_create(NULL, bw, NULL, false); + bw_target = browser_window_create(NULL, bw, NULL, false, false); if (!bw_target) return bw; return bw_target; @@ -1127,7 +1127,7 @@ struct browser_window *browser_window_find_target(struct browser_window *bw, con /* we require a new window using the target name */ if (!option_target_blank) return bw; - bw_target = browser_window_create(NULL, bw, NULL, false); + bw_target = browser_window_create(NULL, bw, NULL, false, false); if (!bw_target) return bw; @@ -1539,7 +1539,10 @@ void browser_window_mouse_action_html(struct browser_window *bw, /* force download of link */ browser_window_go_post(bw, url, 0, 0, false, c->url, true, true, 0); - + } else if (mouse & BROWSER_MOUSE_CLICK_1 && + mouse & BROWSER_MOUSE_MOD_2) { + /* open link in new tab */ + browser_window_create(url, bw, c->url, true, true); } else if (mouse & BROWSER_MOUSE_CLICK_2 && mouse & BROWSER_MOUSE_MOD_1) { free(browser_window_href_content.url); diff --git a/desktop/browser.h b/desktop/browser.h index 45a930c6a..a3a10b9f3 100644 --- a/desktop/browser.h +++ b/desktop/browser.h @@ -214,7 +214,7 @@ extern bool browser_reformat_pending; struct browser_window * browser_window_create(const char *url, struct browser_window *clone, const char *referer, - bool history_add); + bool history_add, bool new_tab); void browser_window_initialise_common(struct browser_window *bw, struct browser_window *clone); void browser_window_go(struct browser_window *bw, const char *url, diff --git a/desktop/frames.c b/desktop/frames.c index 0244a0045..a59980d98 100644 --- a/desktop/frames.c +++ b/desktop/frames.c @@ -93,7 +93,7 @@ void browser_window_create_iframes(struct browser_window *bw, window->parent = bw; /* gui window */ - window->window = gui_create_browser_window(window, bw); + window->window = gui_create_browser_window(window, bw, false); } /* calculate dimensions */ @@ -201,7 +201,7 @@ void browser_window_create_frameset(struct browser_window *bw, window->parent = bw; /* gui window */ - window->window = gui_create_browser_window(window, bw); + window->window = gui_create_browser_window(window, bw, false); if (window->name) LOG(("Created frame '%s'", window->name)); diff --git a/desktop/gui.h b/desktop/gui.h index c6b1b49cb..de6eae3c5 100644 --- a/desktop/gui.h +++ b/desktop/gui.h @@ -66,7 +66,7 @@ void gui_poll(bool active); void gui_quit(void); struct gui_window *gui_create_browser_window(struct browser_window *bw, - struct browser_window *clone); + struct browser_window *clone, bool new_tab); void gui_window_destroy(struct gui_window *g); void gui_window_set_title(struct gui_window *g, const char *title); void gui_window_redraw(struct gui_window *g, int x0, int y0, int x1, int y1); diff --git a/desktop/history_core.c b/desktop/history_core.c index 9fa085d8d..bcc6fc190 100644 --- a/desktop/history_core.c +++ b/desktop/history_core.c @@ -454,7 +454,7 @@ void history_go(struct browser_window *bw, struct history *history, if (new_window) { current = history->current; history->current = entry; - browser_window_create(url, bw, 0, false); + browser_window_create(url, bw, 0, false, false); history->current = current; } else { history->current = entry; diff --git a/gtk/gtk_bitmap.c b/gtk/gtk_bitmap.c index dd62aad26..e08741260 100644 --- a/gtk/gtk_bitmap.c +++ b/gtk/gtk_bitmap.c @@ -58,12 +58,8 @@ void *bitmap_create(int width, int height, unsigned int state) { struct bitmap *bmp = malloc(sizeof(struct bitmap)); -// if ((state & BITMAP_OPAQUE) != 0) -// bmp->primary = gdk_pixbuf_new(GDK_COLORSPACE_RGB, false, -// 8, width, height); -// else - bmp->primary = gdk_pixbuf_new(GDK_COLORSPACE_RGB, true, - 8, width, height); + bmp->primary = gdk_pixbuf_new(GDK_COLORSPACE_RGB, true, + 8, width, height); /* fill the pixbuf in with 100% transparent black, as the memory * won't have been cleared. @@ -289,7 +285,10 @@ gtk_bitmap_generate_pretile(GdkPixbuf *primary, int repeat_x, int repeat_y) GdkPixbuf * gtk_bitmap_get_primary(struct bitmap *bitmap) { - return bitmap->primary; + if (bitmap != NULL) + return bitmap->primary; + else + return NULL; } /** diff --git a/gtk/gtk_gui.c b/gtk/gtk_gui.c index 5c346f1d3..abf3b0b5f 100644 --- a/gtk/gtk_gui.c +++ b/gtk/gtk_gui.c @@ -333,7 +333,7 @@ void gui_init2(int argc, char** argv) addr = option_homepage_url; if (argc > 1) addr = argv[1]; - bw = browser_window_create(addr, 0, 0, true); + bw = browser_window_create(addr, 0, 0, true, false); } diff --git a/gtk/gtk_history.c b/gtk/gtk_history.c index 349643e56..add76c1a1 100644 --- a/gtk/gtk_history.c +++ b/gtk/gtk_history.c @@ -19,135 +19,603 @@ #include <gtk/gtk.h> #include <glade/glade.h> #include "utils/log.h" +#include "utils/utils.h" +#include "utils/url.h" +#include "utils/messages.h" #include "content/urldb.h" #include "gtk/gtk_history.h" #include "gtk/gtk_gui.h" #include "gtk/gtk_window.h" +#include "gtk/gtk_bitmap.h" + +#define GLADE_NAME "history.glade" enum { - COL_TITLE = 0, - COL_ADDRESS, - COL_LASTVISIT, - COL_TOTALVISITS, - COL_THUMBNAIL, - COL_NCOLS + SITE_TITLE = 0, + SITE_DOMAIN, + SITE_ADDRESS, + SITE_LASTVISIT, + SITE_TOTALVISITS, + SITE_THUMBNAIL, + SITE_NCOLS +}; + +enum +{ + DOM_DOMAIN, + DOM_LASTVISIT, + DOM_TOTALVISITS, + DOM_HAS_SITES, + DOM_NCOLS }; GtkWindow *wndHistory; -static GtkTreeView *treeview; -static GtkTreeStore *history_tree; -static GtkTreeSelection *selection; +static GladeXML *gladeFile; + +static const gchar* dateToday; +static const gchar* dateYesterday; +static const gchar* dateAt; +static const gchar* domainAll; + +static struct history_model *history; + +static void nsgtk_history_init_model(); +static void nsgtk_history_init_filters(); +static void nsgtk_history_init_sort(); +static void nsgtk_history_init_treeviews(); +static void nsgtk_history_init_list(); static bool nsgtk_history_add_internal(const char *, const struct url_data *); -static void nsgtk_history_selection_changed(GtkTreeSelection *, gpointer); + +static void nsgtk_history_show_domain(GtkTreeSelection *treesel, + GString *domain_filter); + +static void nsgtk_history_show_all(); + +static gboolean nsgtk_history_filter_search(GtkTreeModel *model, + GtkTreeIter *iter, GtkWidget *search_entry); +static gboolean nsgtk_history_filter_sites(GtkTreeModel *model, + GtkTreeIter *iter, GString *domain_filter); + +static gchar *nsgtk_history_parent_get(gchar *domain); +static void nsgtk_history_parent_update(gchar *path, const struct url_data *data); + +static void nsgtk_history_domain_sort_changed(GtkComboBox *combo); +static gint nsgtk_history_domain_sort_compare(GtkTreeModel *model, GtkTreeIter *a, + GtkTreeIter *b, gint sort_column); +static void nsgtk_history_domain_set_visible (GtkTreeModel *model, + GtkTreePath *path, GtkTreeIter *iter, gboolean has_sites); + +static void nsgtk_history_search(); +static void nsgtk_history_search_clear (GtkEntry *entry); + +static gchar *nsgtk_history_date_parse(time_t visit_time); +static void nsgtk_history_row_activated(GtkTreeView *, GtkTreePath *, + GtkTreeViewColumn *); +static void nsgtk_history_update_info(GtkTreeSelection *treesel, + gboolean domain); +static void nsgtk_history_scroll_top (GtkScrolledWindow *scrolled_window); void nsgtk_history_init(void) { - GtkCellRenderer *renderer; + GtkTreeIter iter; - wndHistory = GTK_WINDOW(glade_xml_get_widget(gladeWindows, - "wndHistory")); - treeview = GTK_TREE_VIEW(glade_xml_get_widget(gladeWindows, - "treeHistory")); - history_tree = gtk_tree_store_new(COL_NCOLS, - G_TYPE_STRING, /* title */ - G_TYPE_STRING, /* address */ - G_TYPE_STRING, /* last visit */ - G_TYPE_INT, /* nr. visits */ - GDK_TYPE_PIXBUF); /* thumbnail */ - - selection = gtk_tree_view_get_selection(treeview); - gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE); - g_signal_connect(G_OBJECT(selection), "changed", - G_CALLBACK(nsgtk_history_selection_changed), NULL); + dateToday = messages_get("DateToday"); + dateYesterday = messages_get("DateYesterday"); + dateAt = messages_get("DateAt"); + domainAll = messages_get("DomainAll"); + + gchar *glade_location = g_strconcat(res_dir_location, GLADE_NAME, NULL); + gladeFile = glade_xml_new(glade_location, NULL, NULL); + g_free(glade_location); - renderer = gtk_cell_renderer_text_new(); - gtk_tree_view_insert_column_with_attributes(treeview, -1, "Title", - renderer, - "text", - COL_TITLE, - NULL); + glade_xml_signal_autoconnect(gladeFile); + wndHistory = GTK_WINDOW(glade_xml_get_widget(gladeFile, + "wndHistory")); + + nsgtk_history_init_model(); + nsgtk_history_init_list(); + nsgtk_history_init_filters(); + nsgtk_history_init_sort(); + nsgtk_history_init_treeviews(); - gtk_tree_view_set_model(treeview, GTK_TREE_MODEL(history_tree)); + nsgtk_history_show_all(); +} - nsgtk_history_update(); +void nsgtk_history_init_model() +{ + history = malloc(sizeof(struct history_model)); + + history->history_list = gtk_list_store_new(SITE_NCOLS, + G_TYPE_STRING, /* title */ + G_TYPE_STRING, /* domain */ + G_TYPE_STRING, /* address */ + G_TYPE_INT, /* last visit */ + G_TYPE_INT, /* num visits */ + G_TYPE_POINTER); /* thumbnail */ + history->history_filter = gtk_tree_model_filter_new( + GTK_TREE_MODEL(history->history_list), NULL); + + history->site_filter = gtk_tree_model_filter_new( + history->history_filter,NULL); + history->site_sort = gtk_tree_model_sort_new_with_model(history->site_filter); + history->site_treeview = GTK_TREE_VIEW(glade_xml_get_widget(gladeFile, + "treeHistory")); + history->site_selection = + gtk_tree_view_get_selection(history->site_treeview); + + history->domain_list = gtk_list_store_new(DOM_NCOLS, + G_TYPE_STRING, /* domain */ + G_TYPE_INT, /* last visit */ + G_TYPE_INT, /* num visits */ + G_TYPE_BOOLEAN); /* has sites */ + history->domain_filter = gtk_tree_model_filter_new( + GTK_TREE_MODEL(history->domain_list), NULL); + history->domain_hash = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, g_free); + history->domain_sort = gtk_tree_model_sort_new_with_model( + history->domain_filter); + history->domain_treeview = GTK_TREE_VIEW(glade_xml_get_widget( + gladeFile,"treeDomain")); + history->domain_selection = + gtk_tree_view_get_selection(history->domain_treeview); } -void nsgtk_history_update(void) +void nsgtk_history_init_list() { - gtk_tree_store_clear(history_tree); + GtkTreeIter iter; + + gtk_list_store_clear(history->history_list); + gtk_list_store_clear(history->domain_list); + + gtk_list_store_append(history->domain_list, &iter); + gtk_list_store_set(history->domain_list, &iter, + DOM_DOMAIN, domainAll, + DOM_LASTVISIT, -2, + DOM_TOTALVISITS, -2, + DOM_HAS_SITES, TRUE, + -1); + urldb_iterate_entries(nsgtk_history_add_internal); } +void nsgtk_history_init_filters() +{ + GtkWidget *search_entry, *clear_button; + GString *filter_string = g_string_new(NULL); + + search_entry = glade_xml_get_widget(gladeFile,"entrySearch"); + clear_button = glade_xml_get_widget(gladeFile,"buttonClearSearch"); + + g_signal_connect(G_OBJECT(search_entry), "changed", + G_CALLBACK(nsgtk_history_search), NULL); + g_signal_connect_swapped(G_OBJECT(clear_button), "clicked", + G_CALLBACK(nsgtk_history_search_clear), + GTK_ENTRY(search_entry)); + + gtk_tree_model_filter_set_visible_func( + GTK_TREE_MODEL_FILTER(history->history_filter), + (GtkTreeModelFilterVisibleFunc) + nsgtk_history_filter_search, search_entry, NULL); + gtk_tree_model_filter_set_visible_func( + GTK_TREE_MODEL_FILTER(history->site_filter), + (GtkTreeModelFilterVisibleFunc) + nsgtk_history_filter_sites, filter_string, NULL); + gtk_tree_model_filter_set_visible_column( + GTK_TREE_MODEL_FILTER(history->domain_filter), + DOM_HAS_SITES); + + g_signal_connect(G_OBJECT(history->site_selection), "changed", + G_CALLBACK(nsgtk_history_update_info), FALSE); + g_signal_connect(G_OBJECT(history->domain_selection), "changed", + G_CALLBACK(nsgtk_history_show_domain), filter_string); +} + +void nsgtk_history_init_sort() +{ + GtkWidget *domain_window = glade_xml_get_widget(gladeFile, + "windowDomain"); + GtkComboBox *sort_combo_box = + GTK_COMBO_BOX(glade_xml_get_widget( + gladeFile, "comboSort")); + gtk_combo_box_set_active(sort_combo_box, 0); + + g_signal_connect(G_OBJECT(sort_combo_box), "changed", + G_CALLBACK(nsgtk_history_domain_sort_changed), NULL); + g_signal_connect_swapped(G_OBJECT(sort_combo_box), "changed", + G_CALLBACK(nsgtk_history_scroll_top), domain_window); + + gtk_tree_sortable_set_sort_func( + GTK_TREE_SORTABLE(history->domain_sort), + DOM_LASTVISIT, (GtkTreeIterCompareFunc) + nsgtk_history_domain_sort_compare, + GUINT_TO_POINTER(DOM_LASTVISIT), NULL); + gtk_tree_sortable_set_sort_func( + GTK_TREE_SORTABLE(history->domain_sort), + DOM_TOTALVISITS, (GtkTreeIterCompareFunc) + nsgtk_history_domain_sort_compare, + GUINT_TO_POINTER(DOM_TOTALVISITS), NULL); + gtk_tree_sortable_set_sort_func( + GTK_TREE_SORTABLE(history->site_sort), + SITE_LASTVISIT, (GtkTreeIterCompareFunc) + nsgtk_history_domain_sort_compare, + GUINT_TO_POINTER(SITE_LASTVISIT), NULL); + gtk_tree_sortable_set_sort_func( + GTK_TREE_SORTABLE(history->site_sort), + SITE_TOTALVISITS, (GtkTreeIterCompareFunc) + nsgtk_history_domain_sort_compare, + GUINT_TO_POINTER(SITE_TOTALVISITS), NULL); +} + +void nsgtk_history_init_treeviews() +{ + GtkCellRenderer *renderer; + + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_insert_column_with_attributes(history->site_treeview, -1, + messages_get("Title"), renderer, + "text", SITE_TITLE, + NULL); + + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_insert_column_with_attributes(history->domain_treeview, + -1, messages_get("Domain"), renderer, + "markup", DOM_DOMAIN, + NULL); + + gtk_tree_view_set_model(history->site_treeview, history->site_sort); + gtk_tree_view_set_model(history->domain_treeview, history->domain_sort); + + g_signal_connect(history->site_treeview, "row-activated", + G_CALLBACK(nsgtk_history_row_activated), NULL); +} + bool nsgtk_history_add_internal(const char *url, const struct url_data *data) { GtkTreeIter iter; + gchar *domain, *path; + if (url_host(url, &domain) != URL_FUNC_OK) + strcpy(domain, messages_get("gtkUnknownHost")); if (data->visits > 0) { - gtk_tree_store_append(history_tree, &iter, NULL); - gtk_tree_store_set(history_tree, &iter, - COL_TITLE, data->title, - COL_ADDRESS, url, - COL_LASTVISIT, "Unknown", - COL_TOTALVISITS, data->visits, + path = nsgtk_history_parent_get(domain); + nsgtk_history_parent_update(path, data); + + gtk_list_store_append(history->history_list, &iter); + gtk_list_store_set(history->history_list, &iter, + SITE_TITLE, data->title ? data->title : + url, + SITE_DOMAIN, domain, + SITE_ADDRESS, url, + SITE_LASTVISIT, data->last_visit, + SITE_TOTALVISITS, data->visits, + SITE_THUMBNAIL, + gtk_bitmap_get_primary( + urldb_get_thumbnail(url)), -1); } - return true; } -void nsgtk_history_selection_changed(GtkTreeSelection *treesel, gpointer g) +gchar *nsgtk_history_parent_get(gchar *domain) { GtkTreeIter iter; - GtkTreeModel *model = GTK_TREE_MODEL(history_tree); - if (gtk_tree_selection_get_selected(treesel, &model, &iter)) - { - gchar *b; - gint i; - char buf[20]; + gchar *path; + + /* Adds an extra entry in the list to act as the root domain + * (which will keep track of things like visits to all sites + * in the domain), This does not work as a tree because the + * children cannot be displayed if the root is hidden + * (which would conflict with the site view) */ + path = g_hash_table_lookup(history->domain_hash, domain); + + if (path == NULL){ + gtk_list_store_append(history->domain_list, &iter); + gtk_list_store_set(history->domain_list, &iter, + DOM_DOMAIN, domain, + DOM_LASTVISIT, messages_get("gtkUnknownHost"), + DOM_TOTALVISITS, 0, + -1); + + path = gtk_tree_model_get_string_from_iter( + GTK_TREE_MODEL(history->domain_list), &iter); + g_hash_table_insert(history->domain_hash, domain, + path); + } - gtk_tree_model_get(model, &iter, COL_ADDRESS, &b, -1); - gtk_label_set_text(GTK_LABEL(glade_xml_get_widget(gladeWindows, - "labelHistoryAddress")), b); + return path; +} - gtk_tree_model_get(model, &iter, COL_LASTVISIT, &b, -1); - gtk_label_set_text(GTK_LABEL(glade_xml_get_widget(gladeWindows, - "labelHistoryLastVisit")), b); +void nsgtk_history_parent_update(gchar *path, const struct url_data *data) +{ + GtkTreeIter iter; + gint num_visits, last_visit; + + gtk_tree_model_get_iter_from_string( + GTK_TREE_MODEL(history->domain_list), &iter, path); + gtk_tree_model_get(GTK_TREE_MODEL(history->domain_list), &iter, + DOM_TOTALVISITS, &num_visits, + DOM_LASTVISIT, &last_visit, + -1); + + gtk_list_store_set(history->domain_list, &iter, + DOM_TOTALVISITS, num_visits + data->visits, + DOM_LASTVISIT, max(last_visit,data->last_visit), + -1); - gtk_tree_model_get(model, &iter, COL_TOTALVISITS, - &i, -1); - snprintf(buf, 20, "%d", i); - gtk_label_set_text(GTK_LABEL(glade_xml_get_widget(gladeWindows, - "labelHistoryVisits")), buf); + /* Handle "All" */ + gtk_tree_model_get_iter_from_string( + GTK_TREE_MODEL(history->domain_list), &iter, "0"); + gtk_tree_model_get(GTK_TREE_MODEL(history->domain_list), &iter, + DOM_TOTALVISITS, &num_visits, + DOM_LASTVISIT, &last_visit, + -1); + + gtk_list_store_set(history->domain_list, &iter, + DOM_TOTALVISITS, num_visits + data->visits, + DOM_LASTVISIT, max(last_visit,data->last_visit), + -1); +} +void nsgtk_history_show_domain(GtkTreeSelection *treesel, + GString *domain_filter) +{ + GtkTreeIter iter; + GtkTreeModel *model; + gint columns[] = { DOM_DOMAIN, DOM_LASTVISIT, DOM_TOTALVISITS }; + + if (gtk_tree_selection_get_selected(treesel, &model, &iter)) { + gtk_tree_model_get(model, &iter, DOM_DOMAIN, + &domain_filter->str, -1); + gtk_tree_model_filter_refilter( + GTK_TREE_MODEL_FILTER(history->site_filter)); + } + + nsgtk_history_update_info(treesel, TRUE); +} +void nsgtk_history_show_all() +{ + GtkTreePath *path = gtk_tree_path_new_from_string("0"); + + gtk_tree_selection_select_path(history->domain_selection, path); + + gtk_tree_path_free(path); +} +gboolean nsgtk_history_filter_search(GtkTreeModel *model, GtkTreeIter *iter, + GtkWidget *search_entry) +{ + gchar *title, *address, *domain, *path; + gint result; + GtkTreeIter new_iter; + const gchar *search = gtk_entry_get_text(GTK_ENTRY(search_entry)); + + gtk_tree_model_get(model, iter, SITE_TITLE, &title, + SITE_ADDRESS, &address, + SITE_DOMAIN, &domain, + -1); + + if (title) + result = (strstr(title, search) || strstr(address, search)); + else + result = FALSE; + + if (result) { + path = g_hash_table_lookup(history->domain_hash, domain); + gtk_tree_model_get_iter_from_string( + GTK_TREE_MODEL(history->domain_list),&new_iter, + path); + + nsgtk_history_domain_set_visible( + GTK_TREE_MODEL(history->domain_list), NULL, + &new_iter, result); } + + g_free(title); + g_free(address); + g_free(domain); + + return result; +} + +gboolean nsgtk_history_filter_sites(GtkTreeModel *model, GtkTreeIter *iter, + GString *domain_filter) +{ + gchar *domain; + gboolean domain_match; + + gtk_tree_model_get(model, iter, SITE_DOMAIN, &domain, -1); + + if (domain && domain_filter->str) + domain_match = g_str_equal(domain, domain_filter->str) || + g_str_equal(domain_filter->str, + domainAll); else - { + domain_match = FALSE; + + g_free(domain); + return domain_match; +} - } +void nsgtk_history_domain_sort_changed(GtkComboBox *combo) +{ + gint domain_options[] = { DOM_DOMAIN, DOM_LASTVISIT, DOM_TOTALVISITS }; + gint site_options[] = { SITE_TITLE, SITE_LASTVISIT, SITE_TOTALVISITS }; + gint sort = gtk_combo_box_get_active(combo); + + gtk_tree_sortable_set_sort_column_id( + GTK_TREE_SORTABLE(history->domain_sort), + domain_options[sort], GTK_SORT_ASCENDING); + gtk_tree_sortable_set_sort_column_id( + GTK_TREE_SORTABLE(history->site_sort), + site_options[sort], GTK_SORT_ASCENDING); +} + +gint nsgtk_history_domain_sort_compare(GtkTreeModel *model, GtkTreeIter *a, + GtkTreeIter *b, gint sort_column) +{ + gint comparable_a; + gint comparable_b; + + gtk_tree_model_get(model, a, sort_column, &comparable_a, -1); + gtk_tree_model_get(model, b, sort_column, &comparable_b, -1); + + /* Make sure "All" stays at the top */ + if (comparable_a < 0 || comparable_b < 0) + return comparable_a - comparable_b; + else + return comparable_b - comparable_a; } +void nsgtk_history_domain_set_visible (GtkTreeModel *model, GtkTreePath *path, + GtkTreeIter *iter, gboolean has_sites) +{ + gchar *string = gtk_tree_model_get_string_from_iter(model, iter); + + if (!g_str_equal(string, "0")) /* "All" */ + gtk_list_store_set(GTK_LIST_STORE(model), iter, + DOM_HAS_SITES, has_sites, -1); + + g_free(string); +} + +void nsgtk_history_search() +{ + gtk_tree_model_foreach(GTK_TREE_MODEL(history->domain_list), + (GtkTreeModelForeachFunc) + nsgtk_history_domain_set_visible, FALSE); + + nsgtk_history_show_all(); + gtk_tree_model_filter_refilter( + GTK_TREE_MODEL_FILTER(history->history_filter)); +} + +void nsgtk_history_search_clear (GtkEntry *entry) +{ + gtk_entry_set_text(entry, ""); +} + +gchar *nsgtk_history_date_parse(time_t visit_time) +{ + gchar *date_string = malloc(30); + gchar *format = malloc(30); + time_t current_time = time(NULL); + gint current_day = localtime(¤t_time)->tm_yday; + struct tm *visit_date = localtime(&visit_time); + + if (visit_date->tm_yday == current_day) + g_snprintf(format, 30, "%s %s %%I:%%M %%p", + dateToday, dateAt); + else if (current_day - visit_date->tm_yday == 1) + g_snprintf(format, 30, "%s %s %%I:%%M %%p", + dateYesterday, dateAt); + else if (current_day - visit_date->tm_yday < 7) + g_snprintf(format, 30, "%%A %s %%I:%%M %%p", + dateAt); + else + format = "%B %d, %Y"; + + strftime(date_string, 30, format, visit_date); + + return date_string; +} + + void nsgtk_history_row_activated(GtkTreeView *tv, GtkTreePath *path, - GtkTreeViewColumn *column, gpointer g) + GtkTreeViewColumn *column) { GtkTreeModel *model; - GtkTreeIter iter; + GtkTreeIter iter; model = gtk_tree_view_get_model(tv); if (gtk_tree_model_get_iter(model, &iter, path)) { - gchar *b; + gchar *address; + + gtk_tree_model_get(model, &iter, SITE_ADDRESS, &address, -1); + + browser_window_create(address, NULL, NULL, true, false); + } +} - gtk_tree_model_get(model, &iter, COL_ADDRESS, &b, -1); +void nsgtk_history_update_info(GtkTreeSelection *treesel, gboolean domain) +{ + GtkTreeIter iter; + GtkTreeModel *model; + gboolean has_selection; + + has_selection = gtk_tree_selection_get_selected(treesel, &model, &iter); + + if (has_selection && domain) { + gchar *b; + gint i; + char buf[20]; + gboolean all = g_str_equal(gtk_tree_model_get_string_from_iter( + model, &iter), "0"); + + /* Address */ + gtk_tree_model_get(model, &iter, DOM_DOMAIN, &b, -1); + gtk_label_set_text(GTK_LABEL(glade_xml_get_widget(gladeFile, + "labelHistoryAddress")), + all ? "-" : b); + g_free(b); + /* Last Visit */ + gtk_tree_model_get(model, &iter, DOM_LASTVISIT, &i, -1); + gtk_label_set_text(GTK_LABEL(glade_xml_get_widget(gladeFile, + "labelHistoryLastVisit")), + nsgtk_history_date_parse(i)); + + /* Total Visits */ + gtk_tree_model_get(model, &iter, DOM_TOTALVISITS, &i, -1); + snprintf(buf, 20, "%d", i); + gtk_label_set_text(GTK_LABEL(glade_xml_get_widget(gladeFile, + "labelHistoryVisits")), + buf); + } else if (has_selection){ + GdkPixbuf *thumb; + gchar *b; + gint i; + char buf[20]; + /* Address */ + gtk_tree_model_get(model, &iter, SITE_ADDRESS, &b, -1); + gtk_label_set_text(GTK_LABEL(glade_xml_get_widget(gladeFile, + "labelHistoryAddress")), b); + g_free(b); + /* Last Visit */ + gtk_tree_model_get(model, &iter, SITE_LASTVISIT, &i, -1); + gtk_label_set_text(GTK_LABEL(glade_xml_get_widget(gladeFile, + "labelHistoryLastVisit")), + nsgtk_history_date_parse(i)); + + /* Total Visits */ + gtk_tree_model_get(model, &iter, SITE_TOTALVISITS, &i, -1); + snprintf(buf, 20, "%d", i); + gtk_label_set_text(GTK_LABEL(glade_xml_get_widget(gladeFile, + "labelHistoryVisits")), buf); - browser_window_create((const char *)b, NULL, NULL, true); + gtk_tree_model_get(model, &iter, SITE_THUMBNAIL, &thumb, -1); + gtk_image_set_from_pixbuf(GTK_IMAGE( + glade_xml_get_widget(gladeFile, + "imageThumbnail")), thumb); + g_object_set(G_OBJECT(glade_xml_get_widget( + gladeFile, "imageFrame")), + "visible", (bool)thumb, NULL); } } +void nsgtk_history_scroll_top (GtkScrolledWindow *scrolled_window) +{ + GtkAdjustment *adjustment = + gtk_scrolled_window_get_vadjustment(scrolled_window); + + gtk_adjustment_set_value(adjustment, 0); + + gtk_scrolled_window_set_vadjustment(scrolled_window, adjustment); +} + void global_history_add(const char *url) { const struct url_data *data; @@ -157,5 +625,4 @@ void global_history_add(const char *url) return; nsgtk_history_add_internal(url, data); - } diff --git a/gtk/gtk_history.h b/gtk/gtk_history.h index 13b76358f..e5662fe89 100644 --- a/gtk/gtk_history.h +++ b/gtk/gtk_history.h @@ -23,9 +23,22 @@ extern GtkWindow *wndHistory; + +struct history_model { + GtkListStore *history_list; + GtkTreeModel *history_filter; + GtkTreeModel *site_filter; + GtkTreeModel *site_sort; + GtkTreeView *site_treeview; + GtkTreeSelection *site_selection; + GtkListStore *domain_list; + GtkTreeModel *domain_filter; + GHashTable *domain_hash; + GtkTreeModel *domain_sort; + GtkTreeView *domain_treeview; + GtkTreeSelection *domain_selection; +}; + void nsgtk_history_init(void); -void nsgtk_history_update(void); -void nsgtk_history_row_activated(GtkTreeView *, GtkTreePath *, - GtkTreeViewColumn *, gpointer); #endif /* __NSGTK_HISTORY_H__ */ diff --git a/gtk/gtk_scaffolding.c b/gtk/gtk_scaffolding.c index c2f546ec0..ca2385fbb 100644 --- a/gtk/gtk_scaffolding.c +++ b/gtk/gtk_scaffolding.c @@ -44,6 +44,7 @@ #include "gtk/gtk_schedule.h" #include "gtk/gtk_download.h" #include "gtk/options.h" +#include "gtk/gtk_tabs.h" #include "render/box.h" #include "render/font.h" #include "render/form.h" @@ -64,10 +65,12 @@ struct gtk_history_window; struct gtk_scaffolding { GtkWindow *window; + GtkNotebook *notebook; GtkEntry *url_bar; GtkEntryCompletion *url_bar_completion; GtkLabel *status_bar; GtkMenu *edit_menu; + GtkMenuItem *tabs_menu; GtkToolbar *tool_bar; GtkToolButton *back_button; GtkToolButton *forward_button; @@ -144,6 +147,7 @@ void nsgtk_openfile_open(char *filename); /* prototypes for menu handlers */ /* file menu */ MENUPROTO(new_window); +MENUPROTO(new_tab); MENUPROTO(open_location); MENUPROTO(open_file); MENUPROTO(export_pdf); @@ -180,6 +184,10 @@ MENUPROTO(home); MENUPROTO(local_history); MENUPROTO(global_history); +/* tabs menu */ +MENUPROTO(next_tab); +MENUPROTO(prev_tab); + /* help menu */ MENUPROTO(about); @@ -189,6 +197,7 @@ MENUPROTO(about); static struct menu_events menu_events[] = { /* file menu */ MENUEVENT(new_window), + MENUEVENT(new_tab), MENUEVENT(open_location), MENUEVENT(open_file), #ifdef WITH_PDF_EXPORT @@ -227,6 +236,10 @@ static struct menu_events menu_events[] = { MENUEVENT(local_history), MENUEVENT(global_history), + /* tab menu */ + MENUEVENT(next_tab), + MENUEVENT(prev_tab), + /* help menu */ MENUEVENT(about), @@ -427,6 +440,13 @@ gboolean nsgtk_window_url_changed(GtkWidget *widget, GdkEventKey *event, } +void nsgtk_window_tabs_num_changed(GtkNotebook *notebook, GtkWidget *page, + guint page_num, struct gtk_scaffolding *g) +{ + gboolean visible = gtk_notebook_get_show_tabs(g->notebook); + g_object_set(g->tabs_menu, "visible", visible, NULL); +} + void nsgtk_openfile_open(char *filename) { struct browser_window *bw = nsgtk_get_browser_for_gui( @@ -451,7 +471,18 @@ MENUHANDLER(new_window) struct browser_window *bw = nsgtk_get_browser_for_gui(gw->top_level); const char *url = gtk_entry_get_text(GTK_ENTRY(gw->url_bar)); - browser_window_create(url, bw, NULL, false); + browser_window_create(url, bw, NULL, false, false); + + return TRUE; +} + +MENUHANDLER(new_tab) +{ + struct gtk_scaffolding *gw = (struct gtk_scaffolding *)g; + struct browser_window *bw = nsgtk_get_browser_for_gui(gw->top_level); + const char *url = gtk_entry_get_text(GTK_ENTRY(gw->url_bar)); + + browser_window_create(url, bw, NULL, false, true); return TRUE; } @@ -880,6 +911,20 @@ MENUHANDLER(global_history) return TRUE; } +MENUHANDLER(next_tab) +{ + struct gtk_scaffolding *gw = (struct gtk_scaffolding *)g; + + gtk_notebook_next_page(gw->notebook); +} + +MENUHANDLER(prev_tab) +{ + struct gtk_scaffolding *gw = (struct gtk_scaffolding *)g; + + gtk_notebook_prev_page(gw->notebook); +} + MENUHANDLER(about) { struct gtk_scaffolding *gw = (struct gtk_scaffolding *)g; @@ -947,17 +992,17 @@ static gboolean do_scroll_event(GtkWidget *widget, GdkEvent *ev, } void nsgtk_attach_toplevel_viewport(nsgtk_scaffolding *g, - GtkViewport *vp) + GtkWidget *sw) { GtkWidget *scrollbar; /* Insert the viewport into the right part of our table */ GtkTable *table = GTK_TABLE(GET_WIDGET("centreTable")); LOG(("Attaching viewport to scaffolding %p", g)); - gtk_table_attach_defaults(table, GTK_WIDGET(vp), 0, 1, 0, 1); +/* gtk_table_attach_defaults(table, GTK_WIDGET(vp), 0, 1, 0, 1); /* connect our scrollbars to the viewport */ - scrollbar = GET_WIDGET("coreScrollHorizontal"); +/* scrollbar = GET_WIDGET("coreScrollHorizontal"); gtk_viewport_set_hadjustment(vp, gtk_range_get_adjustment(GTK_RANGE(scrollbar))); g_object_set_data(G_OBJECT(vp), "hScroll", scrollbar); @@ -971,8 +1016,9 @@ void nsgtk_attach_toplevel_viewport(nsgtk_scaffolding *g, gdk_window_set_accept_focus (GTK_WIDGET(vp)->window, TRUE); /* And set the size-request to zero to cause it to get its act together */ - gtk_widget_set_size_request(GTK_WIDGET(vp), 0, 0); +// gtk_widget_set_size_request(GTK_WIDGET(vp), 0, 0); + gtk_table_attach_defaults(table, sw, 0, 1, 0, 1); } nsgtk_scaffolding *nsgtk_new_scaffolding(struct gui_window *toplevel) @@ -991,10 +1037,12 @@ nsgtk_scaffolding *nsgtk_new_scaffolding(struct gui_window *toplevel) g->xml = glade_xml_new(glade_file_location, "wndBrowser", NULL); glade_xml_signal_autoconnect(g->xml); g->window = GTK_WINDOW(GET_WIDGET("wndBrowser")); + g->notebook = GTK_NOTEBOOK(GET_WIDGET("notebook")); g->url_bar = GTK_ENTRY(GET_WIDGET("URLBar")); g->menu_bar = GTK_MENU_BAR(GET_WIDGET("menubar")); g->status_bar = GTK_LABEL(GET_WIDGET("statusBar")); g->edit_menu = GTK_MENU(GET_WIDGET("menumain_edit")); + g->tabs_menu = GTK_MENU_ITEM(GET_WIDGET("menuitem_tabs")); g->tool_bar = GTK_TOOLBAR(GET_WIDGET("toolbar")); g->back_button = GTK_TOOL_BUTTON(GET_WIDGET("toolBack")); g->forward_button = GTK_TOOL_BUTTON(GET_WIDGET("toolForward")); @@ -1020,6 +1068,8 @@ nsgtk_scaffolding *nsgtk_new_scaffolding(struct gui_window *toplevel) gtk_window_set_default_size(g->window, 600, 600); } + nsgtk_tab_init(g->notebook); + /* set the size of the hpane with status bar and h scrollbar */ gtk_paned_set_position(g->status_pane, option_toolbar_status_width); @@ -1095,6 +1145,13 @@ nsgtk_scaffolding *nsgtk_new_scaffolding(struct gui_window *toplevel) CONNECT(g->history_window->window, "delete_event", gtk_widget_hide_on_delete, NULL); + g_signal_connect_swapped(g->notebook, "switch-page", + G_CALLBACK(nsgtk_window_update_back_forward), g); + g_signal_connect_after(g->notebook, "page-added", + G_CALLBACK(nsgtk_window_tabs_num_changed), g); + g_signal_connect_after(g->notebook, "page-removed", + G_CALLBACK(nsgtk_window_tabs_num_changed), g); + /* connect signals to handlers. */ CONNECT(g->window, "delete-event", nsgtk_window_delete_event, NULL); CONNECT(g->window, "destroy", nsgtk_window_destroy_event, g); @@ -1175,18 +1232,21 @@ void gui_window_set_title(struct gui_window *_g, const char *title) static char suffix[] = " - NetSurf"; char nt[strlen(title) + strlen(suffix) + 1]; struct gtk_scaffolding *g = nsgtk_get_scaffold(_g); - if (g->top_level != _g) return; - if (title == NULL || title[0] == '\0') - { - gtk_window_set_title(g->window, "NetSurf"); + nsgtk_tab_set_title(_g, title); - } - else - { - strcpy(nt, title); - strcat(nt, suffix); - gtk_window_set_title(g->window, nt); + if (g->top_level == _g) { + if (title == NULL || title[0] == '\0') + { + gtk_window_set_title(g->window, "NetSurf"); + + } + else + { + strcpy(nt, title); + strcat(nt, suffix); + gtk_window_set_title(g->window, nt); + } } } @@ -1245,6 +1305,16 @@ GtkWindow* nsgtk_scaffolding_get_window (struct gui_window *g) return g->scaffold->window; } +GtkNotebook* nsgtk_scaffolding_get_notebook (struct gui_window *g) +{ + return g->scaffold->notebook; +} + +void nsgtk_scaffolding_set_top_level (struct gui_window *gw) +{ + gw->scaffold->top_level = gw; +} + void nsgtk_scaffolding_popup_menu(struct gtk_scaffolding *g, guint button) { nsgtk_scaffolding_update_edit_actions_sensitivity(g, g->popup_xml, TRUE); diff --git a/gtk/gtk_scaffolding.h b/gtk/gtk_scaffolding.h index 5f886b68a..0917b7476 100644 --- a/gtk/gtk_scaffolding.h +++ b/gtk/gtk_scaffolding.h @@ -31,7 +31,11 @@ gboolean nsgtk_scaffolding_is_busy(nsgtk_scaffolding *scaffold); GtkWindow* nsgtk_scaffolding_get_window (struct gui_window *g); -void nsgtk_attach_toplevel_viewport(nsgtk_scaffolding *g, GtkViewport *vp); +GtkNotebook* nsgtk_scaffolding_get_notebook (struct gui_window *g); + +void nsgtk_scaffolding_set_top_level (struct gui_window *gw); + +void nsgtk_attach_toplevel_viewport(nsgtk_scaffolding *g, GtkWidget *sw); void nsgtk_scaffolding_destroy(nsgtk_scaffolding *scaffold); diff --git a/gtk/gtk_selection.c b/gtk/gtk_selection.c index b6a1227cb..cf9e1decd 100644 --- a/gtk/gtk_selection.c +++ b/gtk/gtk_selection.c @@ -107,6 +107,8 @@ bool gui_commit_clipboard(void) { clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD); gtk_clipboard_set_text(clipboard, current_selection->str, -1); + gui_empty_clipboard(); + return true; } diff --git a/gtk/gtk_tabs.c b/gtk/gtk_tabs.c new file mode 100644 index 000000000..6595086ca --- /dev/null +++ b/gtk/gtk_tabs.c @@ -0,0 +1,154 @@ +/* + * Copyright 2008 Michael Lester <element3260@gmail.com> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <glade/glade.h> +#include "gtk/gtk_window.h" +#include "gtk/gtk_gui.h" +#include "desktop/browser.h" +#include "content/content.h" + +#define TAB_WIDTH_N_CHARS 15 +#define GET_WIDGET(x) glade_xml_get_widget(gladeWindows, (x)) + +static GtkWidget *nsgtk_tab_label_setup(struct gui_window *window); +static void nsgtk_tab_visibility_update(GtkNotebook *notebook, GtkWidget *child, + guint page); +static void nsgtk_tab_update_size(GtkWidget *hbox, GtkStyle *previous_style, + GtkWidget *close_button); + +static void nsgtk_tab_page_changed(GtkNotebook *notebook, GtkNotebookPage *page, + gint page_num); + +void nsgtk_tab_init(GtkWidget *tabs) +{ + g_signal_connect(tabs, "switch-page", + G_CALLBACK(nsgtk_tab_page_changed), NULL); + + g_signal_connect(tabs, "page-removed", + G_CALLBACK(nsgtk_tab_visibility_update), NULL); + g_signal_connect(tabs, "page-added", + G_CALLBACK(nsgtk_tab_visibility_update), NULL); +} + +void nsgtk_tab_add(struct gui_window *window) +{ + GtkWidget *scrollbar; + GtkNotebook *tabs = nsgtk_scaffolding_get_notebook(window); + + GtkWidget *tabBox = nsgtk_tab_label_setup(window); + gint page = gtk_notebook_append_page(tabs, + GTK_WIDGET(window->scrolledwindow), tabBox); + + gtk_widget_show_all(GTK_WIDGET(window->scrolledwindow)); + gtk_notebook_set_current_page(tabs, page); +} + +void nsgtk_tab_visibility_update(GtkNotebook *notebook, GtkWidget *child, + guint page) +{ + gint num_pages = gtk_notebook_get_n_pages(notebook); + gtk_notebook_set_show_tabs(notebook, num_pages - 1); +} + +void nsgtk_tab_set_title(struct gui_window *g, const char *title) +{ + GtkWidget *label; + gboolean is_top_level = (g->tab != NULL); + + if (is_top_level) { + label = g_object_get_data(G_OBJECT(g->tab), "label"); + gtk_label_set_text(GTK_LABEL(label), title); + + gtk_widget_set_tooltip_text(g->tab, title); + } +} + +GtkWidget *nsgtk_tab_label_setup(struct gui_window *window) +{ + GtkWidget *hbox, *label, *button, *close; + + hbox = gtk_hbox_new(FALSE, 2); + + label = gtk_label_new("Loading..."); + gtk_label_set_ellipsize(GTK_LABEL(label), PANGO_ELLIPSIZE_END); + gtk_label_set_single_line_mode(GTK_LABEL(label), TRUE); + gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); + gtk_misc_set_padding(GTK_MISC(label), 0, 0); + gtk_widget_show(label); + + button = gtk_button_new(); + close = gtk_image_new_from_stock("gtk-close", + GTK_ICON_SIZE_MENU); + gtk_container_add(GTK_CONTAINER(button), close); + gtk_button_set_focus_on_click(GTK_BUTTON(button), FALSE); + gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE); + gtk_widget_set_tooltip_text(button, "Close this tab."); + + + g_signal_connect_swapped(button, "clicked", + G_CALLBACK(nsgtk_window_destroy_browser), window); + g_signal_connect(hbox, "style-set", + G_CALLBACK(nsgtk_tab_update_size), button); + + gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0); + + g_object_set_data (G_OBJECT (hbox), "label", label); + g_object_set_data (G_OBJECT (hbox), "close-button", button); + + window->tab = hbox; + + gtk_widget_show_all(hbox); + return hbox; +} + +void nsgtk_tab_update_size(GtkWidget *hbox, GtkStyle *previous_style, + GtkWidget *close_button) +{ + PangoFontMetrics *metrics; + PangoContext *context; + GtkWidget *button; + int char_width, h, w; + + context = gtk_widget_get_pango_context (hbox); + metrics = pango_context_get_metrics (context, hbox->style->font_desc, + pango_context_get_language( + context)); + + char_width = pango_font_metrics_get_approximate_digit_width (metrics); + pango_font_metrics_unref (metrics); + + gtk_icon_size_lookup_for_settings (gtk_widget_get_settings (hbox), + GTK_ICON_SIZE_MENU, &w, &h); + + gtk_widget_set_size_request(hbox, + TAB_WIDTH_N_CHARS * PANGO_PIXELS(char_width) + 2 * w, + -1); + + gtk_widget_set_size_request(close_button, w + 4, h + 4); +} + +void nsgtk_tab_page_changed(GtkNotebook *notebook, GtkNotebookPage *page, + gint page_num) +{ + GtkWidget *window = gtk_notebook_get_nth_page(notebook, page_num); + struct gui_window *gw = g_object_get_data(G_OBJECT(window), + "gui_window"); + if (gw) + nsgtk_scaffolding_set_top_level(gw); +} diff --git a/gtk/gtk_tabs.h b/gtk/gtk_tabs.h new file mode 100644 index 000000000..bc7f590b6 --- /dev/null +++ b/gtk/gtk_tabs.h @@ -0,0 +1,26 @@ +/* + * Copyright 2008 Michael Lester <element3260@gmail.com> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _NETSURF_GTK_TABS_H_ +#define _NETSURF_GTK_TABS_H_ + +void nsgtk_tab_init(); +void nsgtk_tab_add(struct gui_window *window); +void nsgtk_tab_set_title(struct gui_window *g, const char *title); + +#endif diff --git a/gtk/gtk_window.c b/gtk/gtk_window.c index a63341ff5..3dbed584e 100644 --- a/gtk/gtk_window.c +++ b/gtk/gtk_window.c @@ -27,6 +27,7 @@ #include "gtk/gtk_scaffolding.h" #include "gtk/gtk_plotters.h" #include "gtk/gtk_schedule.h" +#include "gtk/gtk_tabs.h" #undef NDEBUG #include "utils/log.h" #include "utils/utils.h" @@ -79,7 +80,8 @@ float nsgtk_get_scale_for_gui(struct gui_window *g) /* Create a gui_window */ struct gui_window *gui_create_browser_window(struct browser_window *bw, - struct browser_window *clone) + struct browser_window *clone, + bool new_tab) { struct gui_window *g; /**< what we're creating to return */ GtkPolicyType scrollpolicy; @@ -114,13 +116,15 @@ struct gui_window *gui_create_browser_window(struct browser_window *bw, g->prev = NULL; window_list = g; - if (bw->parent != NULL) { + if (bw->parent != NULL) /* Find our parent's scaffolding */ g->scaffold = bw->parent->window->scaffold; - } else { + else if (new_tab) + g->scaffold = clone->window->scaffold; + else /* Now construct and attach a scaffold */ g->scaffold = nsgtk_new_scaffolding(g); - } + /* Construct our primary elements */ g->fixed = GTK_FIXED(gtk_fixed_new()); @@ -128,32 +132,28 @@ struct gui_window *gui_create_browser_window(struct browser_window *bw, gtk_fixed_put(g->fixed, GTK_WIDGET(g->drawing_area), 0, 0); gtk_container_set_border_width(GTK_CONTAINER(g->fixed), 0); - if (bw->parent != NULL ) { - g->scrolledwindow = GTK_SCROLLED_WINDOW(gtk_scrolled_window_new(NULL, NULL)); - gtk_scrolled_window_add_with_viewport(g->scrolledwindow, - GTK_WIDGET(g->fixed)); - gtk_scrolled_window_set_shadow_type(g->scrolledwindow, - GTK_SHADOW_NONE); - g->viewport = GTK_VIEWPORT(gtk_bin_get_child(GTK_BIN(g->scrolledwindow))); - /* Attach ourselves into our parent at the right point */ + g->scrolledwindow = GTK_SCROLLED_WINDOW(gtk_scrolled_window_new(NULL, NULL)); + g_object_set_data(G_OBJECT(g->scrolledwindow), "gui_window", g); + gtk_scrolled_window_add_with_viewport(g->scrolledwindow, + GTK_WIDGET(g->fixed)); + gtk_scrolled_window_set_shadow_type(g->scrolledwindow, + GTK_SHADOW_NONE); + g->viewport = GTK_VIEWPORT(gtk_bin_get_child(GTK_BIN(g->scrolledwindow))); + g->tab = NULL; + + if (bw->parent != NULL) + /* Attach ourselves into our parent at the right point */ nsgtk_gui_window_attach_child(bw->parent->window, g); - } else { - g->scrolledwindow = 0; - g->viewport = GTK_VIEWPORT(gtk_viewport_new(NULL, NULL)); /* Need to attach adjustments */ - gtk_container_add(GTK_CONTAINER(g->viewport), GTK_WIDGET(g->fixed)); - + else /* Attach our viewport into the scaffold */ - nsgtk_attach_toplevel_viewport(g->scaffold, g->viewport); - } + nsgtk_tab_add(g); gtk_container_set_border_width(GTK_CONTAINER(g->viewport), 0); gtk_viewport_set_shadow_type(g->viewport, GTK_SHADOW_NONE); if (g->scrolledwindow) gtk_widget_show(GTK_WIDGET(g->scrolledwindow)); /* And enable visibility from our viewport down */ - gtk_widget_show(GTK_WIDGET(g->viewport)); - gtk_widget_show(GTK_WIDGET(g->fixed)); - gtk_widget_show(GTK_WIDGET(g->drawing_area)); + gtk_widget_show_all(GTK_WIDGET(g->viewport)); switch(bw->scrolling) { case SCROLLING_NO: diff --git a/gtk/gtk_window.h b/gtk/gtk_window.h index 43f292404..0f99549a7 100644 --- a/gtk/gtk_window.h +++ b/gtk/gtk_window.h @@ -43,6 +43,7 @@ struct gui_window { * for frames which need it. Otherwise we just use * a viewport. */ + GtkWidget *tab; GtkScrolledWindow *scrolledwindow; GtkViewport *viewport; GtkFixed *fixed; diff --git a/gtk/res/downloads.glade b/gtk/res/downloads.glade index 7b99a1a8d..72adc29df 100644 --- a/gtk/res/downloads.glade +++ b/gtk/res/downloads.glade @@ -1,6 +1,5 @@ <?xml version="1.0"?> <glade-interface> - <requires-version lib="gtk+" version="2.12"/> <widget class="GtkWindow" id="wndDownloads"> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> <property name="title" translatable="yes">NetSurf Downloads</property> diff --git a/gtk/res/history.glade b/gtk/res/history.glade new file mode 100644 index 000000000..99dea4dda --- /dev/null +++ b/gtk/res/history.glade @@ -0,0 +1,304 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd"> +<!--Generated with glade3 3.4.5 on Thu Aug 7 20:51:09 2008 --> +<glade-interface> + <widget class="GtkWindow" id="wndHistory"> + <property name="title" translatable="yes">NetSurf Global History</property> + <property name="window_position">GTK_WIN_POS_CENTER</property> + <property name="default_width">600</property> + <property name="default_height">500</property> + <property name="type_hint">GDK_WINDOW_TYPE_HINT_UTILITY</property> + <signal name="delete_event" handler="gtk_widget_hide"/> + <child> + <widget class="GtkVBox" id="vbox1"> + <property name="visible">True</property> + <property name="border_width">2</property> + <property name="spacing">2</property> + <child> + <widget class="GtkHPaned" id="hpaned2"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="position">234</property> + <child> + <widget class="GtkVBox" id="vbox28"> + <property name="visible">True</property> + <property name="spacing">2</property> + <child> + <widget class="GtkHBox" id="hbox2"> + <property name="visible">True</property> + <property name="spacing">2</property> + <child> + <widget class="GtkLabel" id="label1"> + <property name="visible">True</property> + <property name="label" translatable="yes">Sort by</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="padding">1</property> + </packing> + </child> + <child> + <widget class="GtkComboBox" id="comboSort"> + <property name="visible">True</property> + <property name="items" translatable="yes">Name +Last Visited +Number of Visits</property> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkScrolledWindow" id="windowDomain"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="border_width">1</property> + <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="shadow_type">GTK_SHADOW_IN</property> + <child> + <widget class="GtkTreeView" id="treeDomain"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="rules_hint">True</property> + </widget> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="resize">False</property> + <property name="shrink">True</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="vbox2"> + <property name="visible">True</property> + <property name="spacing">2</property> + <child> + <widget class="GtkHBox" id="hbox1"> + <property name="visible">True</property> + <child> + <widget class="GtkLabel" id="label2"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>_Search:</b></property> + <property name="use_markup">True</property> + <property name="use_underline">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="padding">1</property> + </packing> + </child> + <child> + <widget class="GtkEntry" id="entrySearch"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="shadow_type">GTK_SHADOW_OUT</property> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkButton" id="buttonClearSearch"> + <property name="visible">True</property> + <property name="receives_default">True</property> + <property name="relief">GTK_RELIEF_NONE</property> + <property name="focus_on_click">False</property> + <property name="xalign">0</property> + <property name="yalign">0</property> + <property name="response_id">0</property> + <child> + <widget class="GtkImage" id="image1"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Clear the search entry</property> + <property name="stock">gtk-clear</property> + <property name="icon_size">1</property> + </widget> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">2</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkScrolledWindow" id="windowSites"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="border_width">1</property> + <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="shadow_type">GTK_SHADOW_IN</property> + <child> + <widget class="GtkTreeView" id="treeHistory"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="rules_hint">True</property> + <property name="show_expanders">False</property> + </widget> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="resize">False</property> + <property name="shrink">True</property> + </packing> + </child> + </widget> + </child> + <child> + <widget class="GtkHBox" id="hbox3"> + <property name="visible">True</property> + <property name="spacing">5</property> + <child> + <widget class="GtkTable" id="table1"> + <property name="visible">True</property> + <property name="border_width">1</property> + <property name="n_rows">3</property> + <property name="n_columns">2</property> + <property name="column_spacing">5</property> + <child> + <widget class="GtkLabel" id="labelHistoryAddress"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">http://netsurf.sf.net/</property> + <property name="ellipsize">PANGO_ELLIPSIZE_MIDDLE</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="labelHistoryLastVisit"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Fri Aug 09, 2006</property> + <property name="ellipsize">PANGO_ELLIPSIZE_END</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="labelHistoryVisits"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">2</property> + <property name="ellipsize">PANGO_ELLIPSIZE_END</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label119"> + <property name="visible">True</property> + <property name="xalign">1</property> + <property name="label" translatable="yes">Number of visits:</property> + </widget> + <packing> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label118"> + <property name="visible">True</property> + <property name="xalign">1</property> + <property name="label" translatable="yes">Last visited:</property> + </widget> + <packing> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label117"> + <property name="visible">True</property> + <property name="xalign">1</property> + <property name="label" translatable="yes">Address:</property> + </widget> + <packing> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + </widget> + </child> + <child> + <widget class="GtkFrame" id="imageFrame"> + <property name="label_xalign">1</property> + <property name="label_yalign">1</property> + <property name="shadow_type">GTK_SHADOW_IN</property> + <child> + <widget class="GtkImage" id="imageThumbnail"> + <property name="width_request">100</property> + <property name="height_request">86</property> + <property name="visible">True</property> + <property name="stock">gtk-file</property> + <property name="icon_size">6</property> + </widget> + </child> + <child> + <placeholder/> + <packing> + <property name="type">label_item</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="padding">1</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + </child> + </widget> +</glade-interface> diff --git a/gtk/res/netsurf.glade b/gtk/res/netsurf.glade index 48084e555..cae1cc0d0 100644 --- a/gtk/res/netsurf.glade +++ b/gtk/res/netsurf.glade @@ -1,6 +1,7 @@ -<?xml version="1.0"?> +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd"> +<!--Generated with glade3 3.4.5 on Mon Aug 11 01:54:25 2008 --> <glade-interface> - <requires-version lib="gtk+" version="2.12"/> <widget class="GtkWindow" id="wndBrowser"> <property name="title" translatable="yes">NetSurf</property> <property name="window_position">GTK_WIN_POS_CENTER</property> @@ -23,6 +24,7 @@ <property name="tooltip" translatable="yes">Opens a new browser window.</property> <property name="label" translatable="yes">_New Window</property> <property name="use_underline">True</property> + <accelerator key="n" modifiers="GDK_CONTROL_MASK" signal="activate"/> <child internal-child="image"> <widget class="GtkImage" id="image554"> <property name="visible">True</property> @@ -30,7 +32,22 @@ <property name="icon_size">1</property> </widget> </child> - <accelerator key="N" signal="activate" modifiers="GDK_CONTROL_MASK"/> + </widget> + </child> + <child> + <widget class="GtkImageMenuItem" id="new_tab"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Opens a new browser tab.</property> + <property name="label" translatable="yes">New _Tab</property> + <property name="use_underline">True</property> + <accelerator key="t" modifiers="GDK_CONTROL_MASK" signal="activate"/> + <child internal-child="image"> + <widget class="GtkImage" id="menu-item-image25"> + <property name="visible">True</property> + <property name="stock">gtk-new</property> + <property name="icon_size">1</property> + </widget> + </child> </widget> </child> <child> @@ -39,6 +56,7 @@ <property name="tooltip" translatable="yes">Open a file on your computer into this browser window.</property> <property name="label" translatable="yes">_Open File...</property> <property name="use_underline">True</property> + <accelerator key="o" modifiers="GDK_CONTROL_MASK" signal="activate"/> <child internal-child="image"> <widget class="GtkImage" id="image555"> <property name="visible">True</property> @@ -46,7 +64,6 @@ <property name="icon_size">1</property> </widget> </child> - <accelerator key="F" signal="activate" modifiers="GDK_CONTROL_MASK"/> </widget> </child> <child> @@ -55,6 +72,7 @@ <property name="tooltip" translatable="yes">Close this browser window.</property> <property name="label" translatable="yes">_Close Window</property> <property name="use_underline">True</property> + <accelerator key="w" modifiers="GDK_CONTROL_MASK" signal="activate"/> <child internal-child="image"> <widget class="GtkImage" id="image556"> <property name="visible">True</property> @@ -62,7 +80,6 @@ <property name="icon_size">1</property> </widget> </child> - <accelerator key="W" signal="activate" modifiers="GDK_SHIFT_MASK | GDK_CONTROL_MASK"/> </widget> </child> <child> @@ -84,7 +101,6 @@ <property name="icon_size">1</property> </widget> </child> - <accelerator key="S" signal="activate" modifiers="GDK_CONTROL_MASK"/> </widget> </child> <child> @@ -244,7 +260,7 @@ <property name="label">gtk-select-all</property> <property name="use_underline">True</property> <property name="use_stock">True</property> - <accelerator key="a" signal="activate" modifiers="GDK_CONTROL_MASK"/> + <accelerator key="a" modifiers="GDK_CONTROL_MASK" signal="activate"/> </widget> </child> <child> @@ -259,7 +275,7 @@ <property name="tooltip" translatable="yes">Find specific text in the current browser window.</property> <property name="label" translatable="yes">_Find...</property> <property name="use_underline">True</property> - <accelerator key="F" signal="activate" modifiers="GDK_CONTROL_MASK"/> + <accelerator key="F" modifiers="GDK_CONTROL_MASK" signal="activate"/> </widget> </child> <child> @@ -298,6 +314,7 @@ <property name="visible">True</property> <property name="label" translatable="yes">_Stop</property> <property name="use_underline">True</property> + <accelerator key="Escape" modifiers="" signal="activate"/> <child internal-child="image"> <widget class="GtkImage" id="image561"> <property name="visible">True</property> @@ -305,7 +322,6 @@ <property name="icon_size">1</property> </widget> </child> - <accelerator key="Escape" signal="activate"/> </widget> </child> <child> @@ -313,6 +329,7 @@ <property name="visible">True</property> <property name="label" translatable="yes">_Reload</property> <property name="use_underline">True</property> + <accelerator key="F5" modifiers="" signal="activate"/> <child internal-child="image"> <widget class="GtkImage" id="image562"> <property name="visible">True</property> @@ -320,7 +337,6 @@ <property name="icon_size">1</property> </widget> </child> - <accelerator key="F5" signal="activate"/> </widget> </child> <child> @@ -348,9 +364,6 @@ <property name="icon_size">1</property> </widget> </child> - <accelerator key="equal" signal="activate" modifiers="GDK_CONTROL_MASK"/> - <accelerator key="KP_Add" signal="activate" modifiers="GDK_CONTROL_MASK"/> - <accelerator key="plus" signal="activate" modifiers="GDK_CONTROL_MASK"/> </widget> </child> <child> @@ -365,8 +378,6 @@ <property name="icon_size">1</property> </widget> </child> - <accelerator key="KP_0" signal="activate" modifiers="GDK_CONTROL_MASK"/> - <accelerator key="0" signal="activate" modifiers="GDK_CONTROL_MASK"/> </widget> </child> <child> @@ -381,8 +392,6 @@ <property name="icon_size">1</property> </widget> </child> - <accelerator key="KP_Subtract" signal="activate" modifiers="GDK_CONTROL_MASK"/> - <accelerator key="minus" signal="activate" modifiers="GDK_CONTROL_MASK"/> </widget> </child> </widget> @@ -394,7 +403,6 @@ <property name="icon_size">1</property> </widget> </child> - <accelerator key="F11" signal="activate"/> </widget> </child> <child> @@ -402,6 +410,7 @@ <property name="visible">True</property> <property name="label" translatable="yes">_Fullscreen</property> <property name="use_underline">True</property> + <accelerator key="F11" modifiers="" signal="activate"/> <child internal-child="image"> <widget class="GtkImage" id="image567"> <property name="visible">True</property> @@ -409,7 +418,6 @@ <property name="icon_size">1</property> </widget> </child> - <accelerator key="F11" signal="activate" modifiers="GDK_CONTROL_MASK"/> </widget> </child> <child> @@ -494,6 +502,7 @@ <property name="tooltip" translatable="yes">Shows the downloads window</property> <property name="label" translatable="yes">_Downloads...</property> <property name="use_underline">True</property> + <accelerator key="d" modifiers="GDK_CONTROL_MASK" signal="activate"/> </widget> </child> <child> @@ -549,6 +558,7 @@ <property name="visible">True</property> <property name="label" translatable="yes">_Back</property> <property name="use_underline">True</property> + <accelerator key="Left" modifiers="GDK_MOD1_MASK" signal="activate"/> <child internal-child="image"> <widget class="GtkImage" id="image568"> <property name="visible">True</property> @@ -556,7 +566,6 @@ <property name="icon_size">1</property> </widget> </child> - <accelerator key="Left" signal="activate" modifiers="GDK_MOD1_MASK"/> </widget> </child> <child> @@ -564,6 +573,7 @@ <property name="visible">True</property> <property name="label" translatable="yes">_Forward</property> <property name="use_underline">True</property> + <accelerator key="Right" modifiers="GDK_MOD1_MASK" signal="activate"/> <child internal-child="image"> <widget class="GtkImage" id="image569"> <property name="visible">True</property> @@ -571,7 +581,6 @@ <property name="icon_size">1</property> </widget> </child> - <accelerator key="Right" signal="activate" modifiers="GDK_MOD1_MASK"/> </widget> </child> <child> @@ -579,6 +588,7 @@ <property name="visible">True</property> <property name="label" translatable="yes">_Home</property> <property name="use_underline">True</property> + <accelerator key="Down" modifiers="GDK_MOD1_MASK" signal="activate"/> <child internal-child="image"> <widget class="GtkImage" id="image570"> <property name="visible">True</property> @@ -586,7 +596,6 @@ <property name="icon_size">1</property> </widget> </child> - <accelerator key="Home" signal="activate" modifiers="GDK_MOD1_MASK"/> </widget> </child> <child> @@ -600,7 +609,7 @@ <property name="tooltip" translatable="yes">Show the history tree for this browser window.</property> <property name="label" translatable="yes">_Local history...</property> <property name="use_underline">True</property> - <accelerator key="F7" signal="activate"/> + <accelerator key="H" modifiers="GDK_CONTROL_MASK" signal="activate"/> </widget> </child> <child> @@ -609,7 +618,7 @@ <property name="tooltip" translatable="yes">Show the history tree for all windows.</property> <property name="label" translatable="yes">_Global history...</property> <property name="use_underline">True</property> - <accelerator key="F7" signal="activate" modifiers="GDK_CONTROL_MASK"/> + <accelerator key="h" modifiers="GDK_SHIFT_MASK | GDK_CONTROL_MASK" signal="activate"/> </widget> </child> <child> @@ -633,7 +642,7 @@ <property name="tooltip" translatable="yes">Open a window showing all your bookmarks.</property> <property name="label" translatable="yes">_Show Bookmarks...</property> <property name="use_underline">True</property> - <accelerator key="F6" signal="activate"/> + <accelerator key="F6" modifiers="" signal="activate"/> </widget> </child> <child> @@ -647,7 +656,36 @@ <property name="tooltip" translatable="yes">Open an address into this browser window.</property> <property name="label" translatable="yes">_Open location...</property> <property name="use_underline">True</property> - <accelerator key="L" signal="activate" modifiers="GDK_CONTROL_MASK"/> + <accelerator key="L" modifiers="GDK_CONTROL_MASK" signal="activate"/> + </widget> + </child> + </widget> + </child> + </widget> + </child> + <child> + <widget class="GtkMenuItem" id="menuitem_tabs"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Tabs</property> + <property name="use_underline">True</property> + <child> + <widget class="GtkMenu" id="menumain_tabs"> + <property name="visible">True</property> + <child> + <widget class="GtkMenuItem" id="next_tab"> + <property name="visible">True</property> + <property name="border_width">1</property> + <property name="label" translatable="yes">_Next Tab</property> + <property name="use_underline">True</property> + <accelerator key="Right" modifiers="GDK_CONTROL_MASK" signal="activate"/> + </widget> + </child> + <child> + <widget class="GtkMenuItem" id="prev_tab"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Previous Tab</property> + <property name="use_underline">True</property> + <accelerator key="Left" modifiers="GDK_CONTROL_MASK" signal="activate"/> </widget> </child> </widget> @@ -675,7 +713,6 @@ <property name="icon_size">1</property> </widget> </child> - <accelerator key="F1" signal="activate"/> </widget> </child> <child> @@ -811,20 +848,57 @@ <property name="n_rows">3</property> <property name="n_columns">2</property> <child> - <placeholder/> - </child> - <child> - <widget class="GtkStatusbar" id="statusbar1"> - <property name="height_request">1</property> + <widget class="GtkNotebook" id="notebook"> <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="show_tabs">False</property> + <property name="show_border">False</property> + <property name="scrollable">True</property> + <child> + <placeholder/> + </child> + <child> + <widget class="GtkLabel" id="label1"> + <property name="visible">True</property> + <property name="label" translatable="yes">page 1</property> + </widget> + <packing> + <property name="type">tab</property> + <property name="tab_fill">False</property> + </packing> + </child> + <child> + <placeholder/> + </child> + <child> + <widget class="GtkLabel" id="label2"> + <property name="visible">True</property> + <property name="label" translatable="yes">page 2</property> + </widget> + <packing> + <property name="type">tab</property> + <property name="position">1</property> + <property name="tab_fill">False</property> + </packing> + </child> + <child> + <placeholder/> + </child> + <child> + <widget class="GtkLabel" id="label3"> + <property name="visible">True</property> + <property name="label" translatable="yes">page 3</property> + </widget> + <packing> + <property name="type">tab</property> + <property name="position">2</property> + <property name="tab_fill">False</property> + </packing> + </child> </widget> <packing> - <property name="left_attach">1</property> <property name="right_attach">2</property> - <property name="top_attach">2</property> - <property name="bottom_attach">3</property> - <property name="x_options">GTK_FILL</property> - <property name="y_options">GTK_SHRINK | GTK_FILL</property> + <property name="bottom_attach">2</property> </packing> </child> <child> @@ -845,14 +919,7 @@ </packing> </child> <child> - <widget class="GtkHScrollbar" id="coreScrollHorizontal"> - <property name="visible">True</property> - <property name="adjustment">0 0 100 1 10 0</property> - </widget> - <packing> - <property name="resize">False</property> - <property name="shrink">True</property> - </packing> + <placeholder/> </child> </widget> <packing> @@ -862,25 +929,17 @@ </packing> </child> <child> - <widget class="GtkVScrollbar" id="coreScrollVertical"> + <widget class="GtkStatusbar" id="statusbar1"> + <property name="height_request">1</property> <property name="visible">True</property> - <property name="adjustment">0 0 100 1 10 0</property> </widget> <packing> <property name="left_attach">1</property> <property name="right_attach">2</property> - <property name="bottom_attach">2</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> <property name="x_options">GTK_FILL</property> - </packing> - </child> - <child> - <widget class="GtkHSeparator" id="hseparator3"> - <property name="visible">True</property> - </widget> - <packing> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="y_options">GTK_FILL</property> + <property name="y_options">GTK_SHRINK | GTK_FILL</property> </packing> </child> </widget> @@ -924,106 +983,106 @@ <property name="column_spacing">11</property> <property name="row_spacing">10</property> <child> - <widget class="GtkLabel" id="labelLoginHost"> + <widget class="GtkEntry" id="entryLoginUser"> <property name="visible">True</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">moo.yoo.com</property> + <property name="can_focus">True</property> + <property name="has_focus">True</property> + <property name="text" translatable="yes">sesame</property> </widget> <packing> <property name="left_attach">1</property> <property name="right_attach">2</property> - <property name="x_options">GTK_FILL</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="y_options"></property> </packing> </child> <child> - <widget class="GtkLabel" id="label57"> + <widget class="GtkEntry" id="entryLoginPass"> <property name="visible">True</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Password</property> + <property name="can_focus">True</property> + <property name="visibility">False</property> + <property name="activates_default">True</property> + <property name="text" translatable="yes">opensesame</property> </widget> <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> <property name="top_attach">3</property> <property name="bottom_attach">4</property> - <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> </packing> </child> <child> - <widget class="GtkLabel" id="label56"> + <widget class="GtkLabel" id="labelLoginRealm"> <property name="visible">True</property> <property name="xalign">0</property> - <property name="label" translatable="yes">Username</property> + <property name="label" translatable="yes">my sekr3t area</property> </widget> <packing> - <property name="top_attach">2</property> - <property name="bottom_attach">3</property> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> <property name="x_options">GTK_FILL</property> </packing> </child> <child> - <widget class="GtkLabel" id="label54"> + <widget class="GtkLabel" id="label55"> <property name="visible">True</property> <property name="xalign">0</property> - <property name="label" translatable="yes">Host</property> + <property name="label" translatable="yes">Realm</property> </widget> <packing> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> <property name="x_options">GTK_FILL</property> </packing> </child> <child> - <widget class="GtkLabel" id="label55"> + <widget class="GtkLabel" id="label54"> <property name="visible">True</property> <property name="xalign">0</property> - <property name="label" translatable="yes">Realm</property> + <property name="label" translatable="yes">Host</property> </widget> <packing> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> <property name="x_options">GTK_FILL</property> </packing> </child> <child> - <widget class="GtkLabel" id="labelLoginRealm"> + <widget class="GtkLabel" id="label56"> <property name="visible">True</property> <property name="xalign">0</property> - <property name="label" translatable="yes">my sekr3t area</property> + <property name="label" translatable="yes">Username</property> </widget> <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> <property name="x_options">GTK_FILL</property> </packing> </child> <child> - <widget class="GtkEntry" id="entryLoginPass"> + <widget class="GtkLabel" id="label57"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="visibility">False</property> - <property name="activates_default">True</property> - <property name="text" translatable="yes">opensesame</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Password</property> </widget> <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> <property name="top_attach">3</property> <property name="bottom_attach">4</property> - <property name="y_options"></property> + <property name="x_options">GTK_FILL</property> </packing> </child> <child> - <widget class="GtkEntry" id="entryLoginUser"> + <widget class="GtkLabel" id="labelLoginHost"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="has_focus">True</property> - <property name="text" translatable="yes">sesame</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">moo.yoo.com</property> </widget> <packing> <property name="left_attach">1</property> <property name="right_attach">2</property> - <property name="top_attach">2</property> - <property name="bottom_attach">3</property> - <property name="y_options"></property> + <property name="x_options">GTK_FILL</property> </packing> </child> </widget> @@ -1300,166 +1359,6 @@ </widget> </child> </widget> - <widget class="GtkWindow" id="wndHistory"> - <property name="width_request">400</property> - <property name="height_request">500</property> - <property name="title" translatable="yes">NetSurf Global History</property> - <property name="window_position">GTK_WIN_POS_CENTER</property> - <property name="type_hint">GDK_WINDOW_TYPE_HINT_UTILITY</property> - <signal name="delete_event" handler="gtk_widget_hide"/> - <child> - <widget class="GtkVBox" id="vbox28"> - <property name="visible">True</property> - <child> - <widget class="GtkScrolledWindow" id="scrolledwindow2"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> - <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> - <property name="shadow_type">GTK_SHADOW_IN</property> - <child> - <widget class="GtkTreeView" id="treeHistory"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="headers_visible">False</property> - <property name="rules_hint">True</property> - <signal name="row_activated" handler="nsgtk_history_row_activated"/> - </widget> - </child> - </widget> - </child> - <child> - <widget class="GtkExpander" id="expander1"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="expanded">True</property> - <child> - <widget class="GtkHBox" id="hbox25"> - <property name="visible">True</property> - <child> - <widget class="GtkImage" id="image400"> - <property name="visible">True</property> - <property name="yalign">0</property> - <property name="xpad">5</property> - <property name="ypad">5</property> - <property name="stock">gtk-missing-image</property> - </widget> - <packing> - <property name="expand">False</property> - </packing> - </child> - <child> - <widget class="GtkTable" id="table11"> - <property name="visible">True</property> - <property name="border_width">2</property> - <property name="n_rows">3</property> - <property name="n_columns">2</property> - <property name="column_spacing">4</property> - <child> - <widget class="GtkLabel" id="labelHistoryAddress"> - <property name="visible">True</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">http://netsurf.sf.net/</property> - <property name="ellipsize">PANGO_ELLIPSIZE_MIDDLE</property> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <widget class="GtkLabel" id="labelHistoryLastVisit"> - <property name="visible">True</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Fri Aug 09 00:00:00 2006</property> - <property name="ellipsize">PANGO_ELLIPSIZE_END</property> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <widget class="GtkLabel" id="labelHistoryVisits"> - <property name="visible">True</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">2</property> - <property name="ellipsize">PANGO_ELLIPSIZE_END</property> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">2</property> - <property name="bottom_attach">3</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <widget class="GtkLabel" id="label119"> - <property name="visible">True</property> - <property name="xalign">1</property> - <property name="label" translatable="yes">Number of visits</property> - </widget> - <packing> - <property name="top_attach">2</property> - <property name="bottom_attach">3</property> - <property name="x_options">GTK_FILL</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <widget class="GtkLabel" id="label118"> - <property name="visible">True</property> - <property name="xalign">1</property> - <property name="label" translatable="yes">Last visited</property> - </widget> - <packing> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">GTK_FILL</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <widget class="GtkLabel" id="label117"> - <property name="visible">True</property> - <property name="xalign">1</property> - <property name="label" translatable="yes">Address</property> - </widget> - <packing> - <property name="x_options">GTK_FILL</property> - <property name="y_options"></property> - </packing> - </child> - </widget> - <packing> - <property name="position">1</property> - </packing> - </child> - </widget> - </child> - <child> - <widget class="GtkLabel" id="label116"> - <property name="visible">True</property> - <property name="label" translatable="yes">Details</property> - </widget> - <packing> - <property name="type">label_item</property> - </packing> - </child> - </widget> - <packing> - <property name="expand">False</property> - <property name="position">1</property> - </packing> - </child> - </widget> - </child> - </widget> <widget class="GtkWindow" id="wndWarning"> <property name="title" translatable="yes">Warning from NetSurf</property> <property name="window_position">GTK_WIN_POS_CENTER</property> diff --git a/riscos/dialog.c b/riscos/dialog.c index 8fac4376d..808a566b6 100644 --- a/riscos/dialog.c +++ b/riscos/dialog.c @@ -714,7 +714,7 @@ bool ro_gui_dialog_openurl_apply(wimp_w w) { url = ro_gui_get_icon_string(w, ICON_OPENURL_URL); res = url_normalize(url, &url2); if (res == URL_FUNC_OK) { - browser_window_create(url2, 0, 0, true); + browser_window_create(url2, 0, 0, true, false); global_history_add_recent(url2); free(url2); return true; diff --git a/riscos/gui.c b/riscos/gui.c index 5ff558f5d..ea3755730 100644 --- a/riscos/gui.c +++ b/riscos/gui.c @@ -763,7 +763,7 @@ void gui_init2(int argc, char** argv) } if (open_window) - browser_window_create(url, NULL, 0, true); + browser_window_create(url, NULL, 0, true, false); free(url); } @@ -1209,12 +1209,13 @@ bool ro_gui_icon_bar_click(wimp_pointer *pointer) } else if (pointer->buttons == wimp_CLICK_SELECT) { if (option_homepage_url && option_homepage_url[0]) { - browser_window_create(option_homepage_url, NULL, 0, true); + browser_window_create(option_homepage_url, NULL, 0, + true, false); } else { snprintf(url, sizeof url, "file:///<NetSurf$Dir>/Docs/welcome/index_%s", option_language); - browser_window_create(url, NULL, 0, true); + browser_window_create(url, NULL, 0, true, false); } } else if (pointer->buttons == wimp_CLICK_ADJUST) { @@ -1560,7 +1561,7 @@ void ro_msg_dataload(wimp_message *message) ro_gui_tree_start_edit(hotlist_tree, &node->data, NULL); } } else { - browser_window_create(url, 0, 0, true); + browser_window_create(url, 0, 0, true, false); } /* send DataLoadAck */ @@ -1919,7 +1920,7 @@ void ro_msg_dataopen(wimp_message *message) return; /* create a new window with the file */ - browser_window_create(url, NULL, 0, true); + browser_window_create(url, NULL, 0, true, false); free(url); } @@ -2164,7 +2165,7 @@ void ro_gui_open_help_page(const char *page) if ((length = snprintf(url, sizeof url, "file:///<NetSurf$Dir>/Docs/%s_%s", page, option_language)) >= 0 && length < (int)sizeof(url)) - browser_window_create(url, NULL, 0, true); + browser_window_create(url, NULL, 0, true, false); } diff --git a/riscos/menus.c b/riscos/menus.c index 9c2dfffda..ed67f7966 100644 --- a/riscos/menus.c +++ b/riscos/menus.c @@ -1516,7 +1516,7 @@ bool ro_gui_menu_handle_action(wimp_w owner, menu_action action, case BROWSER_NEW_WINDOW: if (!c) return false; - browser_window_create(c->url, bw, 0, false); + browser_window_create(c->url, bw, 0, false, false); return true; case BROWSER_VIEW_SOURCE: if (!c) diff --git a/riscos/plugin.c b/riscos/plugin.c index dbeb02b14..1e4279f18 100644 --- a/riscos/plugin.c +++ b/riscos/plugin.c @@ -930,7 +930,8 @@ void plugin_url_access(wimp_message *message) else if (!option_block_popups && strcasecmp(window, "_blank") == 0) { /* don't do this if popups are blocked */ - browser_window_create(url, NULL, 0, true); + browser_window_create(url, NULL, 0, true, + false); } } else { /* POST request */ diff --git a/riscos/treeview.c b/riscos/treeview.c index 819c2f178..3989d0887 100644 --- a/riscos/treeview.c +++ b/riscos/treeview.c @@ -1580,7 +1580,7 @@ bool ro_gui_tree_launch_node(struct tree *tree, struct node *node) element = tree_find_element(node, TREE_ELEMENT_URL); if (element) { - browser_window_create(element->text, NULL, 0, true); + browser_window_create(element->text, NULL, 0, true, false); return true; } diff --git a/riscos/uri.c b/riscos/uri.c index 53167d305..b4250941d 100644 --- a/riscos/uri.c +++ b/riscos/uri.c @@ -60,7 +60,7 @@ void ro_uri_message_received(wimp_message *msg) xuri_request_uri(0, uri_requested, uri_length, uri_handle, NULL); - browser_window_create(uri_requested, NULL, 0, true); + browser_window_create(uri_requested, NULL, 0, true, false); free(uri_requested); } diff --git a/riscos/url_protocol.c b/riscos/url_protocol.c index 7831334b6..57409d25f 100644 --- a/riscos/url_protocol.c +++ b/riscos/url_protocol.c @@ -116,7 +116,7 @@ void ro_url_message_received(wimp_message *message) } /* create new browser window */ - browser_window_create(url, 0, 0, true); + browser_window_create(url, 0, 0, true, false); free(url); } diff --git a/riscos/window.c b/riscos/window.c index 34725155e..9f791c81d 100644 --- a/riscos/window.c +++ b/riscos/window.c @@ -169,7 +169,7 @@ struct update_box *pending_updates; */ struct gui_window *gui_create_browser_window(struct browser_window *bw, - struct browser_window *clone) + struct browser_window *clone, bool new_tab) { int screen_width, screen_height, win_width, win_height, scroll_width; static int window_count = 2; @@ -2114,7 +2114,7 @@ bool ro_gui_toolbar_click(wimp_pointer *pointer) case ICON_TOOLBAR_BACK: if (pointer->buttons == wimp_CLICK_ADJUST) { new_bw = browser_window_create(NULL, - g->bw, NULL, false); + g->bw, NULL, false, false); ro_gui_menu_handle_action(new_bw->window->window, BROWSER_NAVIGATE_BACK, true); } else { @@ -2126,7 +2126,7 @@ bool ro_gui_toolbar_click(wimp_pointer *pointer) case ICON_TOOLBAR_FORWARD: if (pointer->buttons == wimp_CLICK_ADJUST) { new_bw = browser_window_create(NULL, - g->bw, NULL, false); + g->bw, NULL, false, false); ro_gui_menu_handle_action(new_bw->window->window, BROWSER_NAVIGATE_FORWARD, true); } else { @@ -2197,7 +2197,8 @@ bool ro_gui_toolbar_click(wimp_pointer *pointer) if (pointer->buttons == wimp_CLICK_ADJUST) { if (g->bw && g->bw->current_content) { new_bw = browser_window_create(NULL, - g->bw, NULL, false); + g->bw, NULL, false, + false); /* do it without loading the content into the new window */ ro_gui_window_navigate_up(new_bw->window, g->bw->current_content->url); |