From 6173bb0e6c3bf51cd463f7bc4f725429d9087b2b Mon Sep 17 00:00:00 2001 From: John Mark Bell Date: Tue, 5 Oct 2010 19:14:46 +0000 Subject: Merge treeview-redux to trunk svn path=/trunk/netsurf/; revision=10865 --- gtk/gtk_cookies.c | 213 +++++++++++++++ gtk/gtk_cookies.h | 33 +++ gtk/gtk_gui.c | 149 +++++++---- gtk/gtk_history.c | 703 ++++++++++++-------------------------------------- gtk/gtk_history.h | 18 +- gtk/gtk_hotlist.c | 277 ++++++++++++++++++++ gtk/gtk_hotlist.h | 33 +++ gtk/gtk_menu.c | 3 + gtk/gtk_menu.h | 1 + gtk/gtk_plotters.c | 14 +- gtk/gtk_scaffolding.c | 33 ++- gtk/gtk_scaffolding.h | 2 + gtk/gtk_theme.c | 2 + gtk/gtk_toolbar.c | 2 + gtk/gtk_toolbar.h | 1 + gtk/gtk_treeview.c | 545 +++++++++++++++++++++++++++++++++----- gtk/gtk_treeview.h | 50 ++++ gtk/gtk_window.c | 2 +- gtk/options.h | 3 + gtk/res/cookies.glade | 174 +++++++++++++ gtk/res/history.glade | 358 +++++++++---------------- gtk/res/hotlist.glade | 218 ++++++++++++++++ gtk/res/icons | 1 + gtk/res/ssl.glade | 19 +- 24 files changed, 1933 insertions(+), 921 deletions(-) create mode 100644 gtk/gtk_cookies.c create mode 100644 gtk/gtk_cookies.h create mode 100644 gtk/gtk_hotlist.c create mode 100644 gtk/gtk_hotlist.h create mode 100644 gtk/gtk_treeview.h create mode 100644 gtk/res/cookies.glade create mode 100644 gtk/res/hotlist.glade create mode 120000 gtk/res/icons (limited to 'gtk') diff --git a/gtk/gtk_cookies.c b/gtk/gtk_cookies.c new file mode 100644 index 000000000..1576290ad --- /dev/null +++ b/gtk/gtk_cookies.c @@ -0,0 +1,213 @@ +/* + * Copyright 2009 Paul Blokus + * + * 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 . + */ + +/** \file + * Cookies (implementation). + */ + + +#include "desktop/cookies.h" +#include "desktop/plotters.h" +#include "desktop/tree.h" +#include "gtk/gtk_gui.h" +#include "gtk/gtk_cookies.h" +#include "gtk/gtk_plotters.h" +#include "gtk/gtk_scaffolding.h" +#include "gtk/gtk_treeview.h" + +#define GLADE_NAME "cookies.glade" + +#define MENUPROTO(x) static gboolean nsgtk_on_##x##_activate( \ + GtkMenuItem *widget, gpointer g) +#define MENUEVENT(x) { #x, G_CALLBACK(nsgtk_on_##x##_activate) } +#define MENUHANDLER(x) gboolean nsgtk_on_##x##_activate(GtkMenuItem *widget, \ + gpointer g) + +struct menu_events { + const char *widget; + GCallback handler; +}; + +static void nsgtk_cookies_init_menu(void); + +/* edit menu */ +MENUPROTO(delete_selected); +MENUPROTO(delete_all); +MENUPROTO(select_all); +MENUPROTO(clear_selection); + +/* view menu*/ +MENUPROTO(expand_all); +MENUPROTO(expand_domains); +MENUPROTO(expand_cookies); +MENUPROTO(collapse_all); +MENUPROTO(collapse_domains); +MENUPROTO(collapse_cookies); + + +static struct menu_events menu_events[] = { + + /* edit menu */ + MENUEVENT(delete_selected), + MENUEVENT(delete_all), + MENUEVENT(select_all), + MENUEVENT(clear_selection), + + /* view menu*/ + MENUEVENT(expand_all), + MENUEVENT(expand_domains), + MENUEVENT(expand_cookies), + MENUEVENT(collapse_all), + MENUEVENT(collapse_domains), + MENUEVENT(collapse_cookies), + + {NULL, NULL} +}; + +static struct nsgtk_treeview *cookies_window; +static GladeXML *gladeFile; +GtkWindow *wndCookies; + +/** + * Creates the window for the cookies tree. + */ +void nsgtk_cookies_init(void) +{ + gchar *glade_location = g_strconcat(res_dir_location, GLADE_NAME, NULL); + gladeFile = glade_xml_new(glade_location, NULL, NULL); + g_free(glade_location); + GtkWindow *window; + GtkScrolledWindow *scrolled; + GtkDrawingArea *drawing_area; + + glade_xml_signal_autoconnect(gladeFile); + + wndCookies = GTK_WINDOW(glade_xml_get_widget(gladeFile, "wndCookies")); + window = wndCookies; + + scrolled = GTK_SCROLLED_WINDOW(glade_xml_get_widget(gladeFile, + "cookiesScrolled")); + + drawing_area = GTK_DRAWING_AREA(glade_xml_get_widget(gladeFile, + "cookiesDrawingArea")); + + cookies_window = nsgtk_treeview_create(cookies_get_tree_flags(), window, + scrolled, drawing_area); + + if (cookies_window == NULL) + return; + +#define CONNECT(obj, sig, callback, ptr) \ + g_signal_connect(G_OBJECT(obj), (sig), G_CALLBACK(callback), (ptr)) + + CONNECT(window, "delete_event", gtk_widget_hide_on_delete, NULL); + CONNECT(window, "hide", nsgtk_tree_window_hide, cookies_window); + + cookies_initialise(nsgtk_treeview_get_tree(cookies_window)); + + nsgtk_cookies_init_menu(); +} + +/** + * Connects menu events in the cookies window. + */ +void nsgtk_cookies_init_menu() +{ + struct menu_events *event = menu_events; + + while (event->widget != NULL) + { + GtkWidget *w = glade_xml_get_widget(gladeFile, event->widget); + g_signal_connect(G_OBJECT(w), "activate", event->handler, + cookies_window); + event++; + } +} + +/** + * Destroys the cookies window and performs any other necessary cleanup actions. + */ +void nsgtk_cookies_destroy(void) +{ + /* TODO: what about gladeFile? */ + cookies_cleanup(); + nsgtk_treeview_destroy(cookies_window); +} + + +/* edit menu */ +MENUHANDLER(delete_selected) +{ + cookies_delete_selected(); + return TRUE; +} + +MENUHANDLER(delete_all) +{ + cookies_delete_all(); + return TRUE; +} + +MENUHANDLER(select_all) +{ + cookies_select_all(); + return TRUE; +} + +MENUHANDLER(clear_selection) +{ + cookies_clear_selection(); + return TRUE; +} + +/* view menu*/ +MENUHANDLER(expand_all) +{ + cookies_expand_all(); + return TRUE; +} + +MENUHANDLER(expand_domains) +{ + cookies_expand_domains(); + return TRUE; +} + +MENUHANDLER(expand_cookies) +{ + cookies_expand_cookies(); + return TRUE; +} + +MENUHANDLER(collapse_all) +{ + cookies_collapse_all(); + return TRUE; +} + +MENUHANDLER(collapse_domains) +{ + cookies_collapse_domains(); + return TRUE; +} + +MENUHANDLER(collapse_cookies) +{ + cookies_collapse_cookies(); + return TRUE; +} diff --git a/gtk/gtk_cookies.h b/gtk/gtk_cookies.h new file mode 100644 index 000000000..7048e2da9 --- /dev/null +++ b/gtk/gtk_cookies.h @@ -0,0 +1,33 @@ +/* + * Copyright 2009 Paul Blokus + * + * 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 . + */ + +/** \file + * Cookies (interface). + */ + +#ifndef __NSGTK_COOKIES_H__ +#define __NSGTK_COOKIES_H__ + +#include + +extern GtkWindow *wndCookies; + +void nsgtk_cookies_init(void); +void nsgtk_cookies_destroy(void); + +#endif /* __NSGTK_COOKIES_H__ */ diff --git a/gtk/gtk_gui.c b/gtk/gtk_gui.c index 1ca8ce533..a41789a41 100644 --- a/gtk/gtk_gui.c +++ b/gtk/gtk_gui.c @@ -49,20 +49,25 @@ #include "desktop/browser.h" #include "desktop/cookies.h" #include "desktop/gui.h" +#include "desktop/history_global_core.h" #include "desktop/netsurf.h" #include "desktop/options.h" #include "desktop/save_pdf/pdf_plotters.h" #include "desktop/searchweb.h" +#include "desktop/sslcert.h" #include "desktop/textinput.h" -#include "gtk/gtk_gui.h" #include "gtk/dialogs/gtk_options.h" #include "gtk/gtk_completion.h" +#include "gtk/gtk_cookies.h" +#include "gtk/gtk_download.h" +#include "gtk/gtk_filetype.h" +#include "gtk/gtk_gui.h" +#include "gtk/gtk_history.h" +#include "gtk/gtk_hotlist.h" +#include "gtk/gtk_throbber.h" +#include "gtk/gtk_treeview.h" #include "gtk/gtk_window.h" #include "gtk/options.h" -#include "gtk/gtk_throbber.h" -#include "gtk/gtk_history.h" -#include "gtk/gtk_filetype.h" -#include "gtk/gtk_download.h" #include "gtk/gtk_schedule.h" #include "render/box.h" @@ -101,7 +106,9 @@ static struct browser_window *select_menu_bw; static struct form_control *select_menu_control; static void nsgtk_ssl_accept(GtkButton *w, gpointer data); -static void nsgtk_ssl_reject(GtkButton *w, gpointer data); +static void nsgtk_ssl_reject(GtkWidget *w, gpointer data); +static gboolean nsgtk_ssl_delete_event(GtkWidget *w, GdkEvent *event, + gpointer data); static void nsgtk_select_menu_clicked(GtkCheckMenuItem *checkmenuitem, gpointer user_data); #ifdef WITH_PDF_EXPORT @@ -377,6 +384,24 @@ static void check_options(char **respath) LOG(("Using '%s' as download directory", hdir)); option_downloads_directory = hdir; } + + if (!option_tree_icons_dir) { + sfindresourcedef(respath, buf, "icons/", "~/.netsurf/"); + LOG(("Using '%s' as Tree icons dir", buf)); + option_tree_icons_dir = strdup(buf); + } + if (!option_tree_icons_dir) + die("Failed initialising tree icons option"); + + + if (!option_hotlist_path) { + sfindresourcedef(respath, buf, "Hotlist", "~/.netsurf/"); + LOG(("Using '%s' as Hotlist file", buf)); + option_hotlist_path = strdup(buf); + } + if (!option_hotlist_path) + die("Failed initialising hotlist option"); + sfindresourcedef(respath, buf, "Print", "~/.netsurf/"); LOG(("Using '%s' as Print Settings file", buf)); @@ -483,6 +508,10 @@ static void gui_init(int argc, char** argv, char **respath) if (nsgtk_download_init() == false) die("Unable to initialise download window.\n"); + nsgtk_cookies_init(); + nsgtk_hotlist_init(); + sslcert_init(); + if (option_homepage_url != NULL && option_homepage_url[0] != '\0') addr = option_homepage_url; @@ -642,11 +671,16 @@ void gui_quit(void) nsgtk_download_destroy(); urldb_save_cookies(option_cookie_jar); urldb_save(option_url_file); + nsgtk_cookies_destroy(); + nsgtk_history_destroy(); + nsgtk_hotlist_destroy(); + sslcert_cleanup(); free(default_stylesheet_url); free(quirks_stylesheet_url); free(adblock_stylesheet_url); free(option_cookie_file); free(option_cookie_jar); + free(option_tree_icons_dir); free(print_options_file_location); free(search_engines_file_location); free(search_default_ico_location); @@ -744,73 +778,88 @@ void die(const char * const error) } -void hotlist_visited(hlcache_handle *content) -{ -} - void gui_cert_verify(const char *url, const struct ssl_cert_info *certs, unsigned long num, nserror (*cb)(bool proceed, void *pw), void *cbpw) -{ +{ + static struct nsgtk_treeview *ssl_window; + struct sslcert_session_data *data; GladeXML *x = glade_xml_new(glade_ssl_file_location, NULL, NULL); - GtkWindow *wnd = GTK_WINDOW(glade_xml_get_widget(x, "wndSSLProblem")); GtkButton *accept, *reject; - void **session = calloc(sizeof(void *), 5); + void **session = calloc(sizeof(void *), 3); + GtkWindow *window; + GtkScrolledWindow *scrolled; + GtkDrawingArea *drawing_area; - session[0] = strdup(url); - session[1] = cb; - session[2] = cbpw; - session[3] = x; - session[4] = wnd; + data = sslcert_create_session_data(num, url, cb, cbpw); + + window = GTK_WINDOW( + glade_xml_get_widget(x,"wndSSLProblem")); + scrolled = GTK_SCROLLED_WINDOW( + glade_xml_get_widget(x,"SSLScrolled")); + drawing_area = GTK_DRAWING_AREA( + glade_xml_get_widget(x,"SSLDrawingArea")); - accept = GTK_BUTTON(glade_xml_get_widget(x, "sslaccept")); - reject = GTK_BUTTON(glade_xml_get_widget(x, "sslreject")); - g_signal_connect(G_OBJECT(accept), "clicked", - G_CALLBACK(nsgtk_ssl_accept), (gpointer)session); - g_signal_connect(G_OBJECT(reject), "clicked", - G_CALLBACK(nsgtk_ssl_reject), (gpointer)session); + ssl_window = nsgtk_treeview_create(sslcert_get_tree_flags(), + window, scrolled, drawing_area); + + if (ssl_window == NULL) + return; + + sslcert_load_tree(nsgtk_treeview_get_tree(ssl_window), certs, data); + + accept = GTK_BUTTON(glade_xml_get_widget(x, "sslaccept")); + reject = GTK_BUTTON(glade_xml_get_widget(x, "sslreject")); - gtk_widget_show(GTK_WIDGET(wnd)); + session[0] = x; + session[1] = ssl_window; + session[2] = data; + +#define CONNECT(obj, sig, callback, ptr) \ + g_signal_connect(G_OBJECT(obj), (sig), G_CALLBACK(callback), (ptr)) + + CONNECT(accept, "clicked", nsgtk_ssl_accept, session); + CONNECT(reject, "clicked", nsgtk_ssl_reject, session); + CONNECT(window, "delete_event", G_CALLBACK(nsgtk_ssl_delete_event), + (gpointer)session); + + gtk_widget_show(GTK_WIDGET(window)); } - void nsgtk_ssl_accept(GtkButton *w, gpointer data) { void **session = data; - char *url = session[0]; - nserror (*cb)(bool proceed, void *pw) = session[1]; - void *cbpw = session[2]; - GladeXML *x = session[3]; - GtkWindow *wnd = session[4]; + GladeXML *x = session[0]; + struct nsgtk_treeview *wnd = session[1]; + struct sslcert_session_data *ssl_data = session[2]; - urldb_set_cert_permissions(url, true); - - cb(true, cbpw); - - gtk_widget_destroy(GTK_WIDGET(wnd)); + sslcert_accept(ssl_data); + + nsgtk_treeview_destroy(wnd); g_object_unref(G_OBJECT(x)); - free(url); free(session); } - -void nsgtk_ssl_reject(GtkButton *w, gpointer data) +void nsgtk_ssl_reject(GtkWidget *w, gpointer data) { void **session = data; - nserror (*cb)(bool proceed, void *pw) = session[1]; - void *cbpw = session[2]; - GladeXML *x = session[3]; - GtkWindow *wnd = session[4]; - - cb(false, cbpw); + GladeXML *x = session[0]; + struct nsgtk_treeview *wnd = session[1]; + struct sslcert_session_data *ssl_data = session[2]; - gtk_widget_destroy(GTK_WIDGET(wnd)); + sslcert_reject(ssl_data); + + nsgtk_treeview_destroy(wnd); g_object_unref(G_OBJECT(x)); - free(session[0]); free(session); } +gboolean nsgtk_ssl_delete_event(GtkWidget *w, GdkEvent *event, gpointer data) +{ + nsgtk_ssl_reject(w, data); + return FALSE; +} utf8_convert_ret utf8_to_local_encoding(const char *string, size_t len, char **result) @@ -883,12 +932,6 @@ char *url_to_path(const char *url) return respath; } - -bool cookies_update(const char *domain, const struct cookie_data *data) -{ - return true; -} - #ifdef WITH_PDF_EXPORT void PDF_Password(char **owner_pass, char **user_pass, char *path) diff --git a/gtk/gtk_history.c b/gtk/gtk_history.c index ed0c912f6..75b392fb3 100644 --- a/gtk/gtk_history.c +++ b/gtk/gtk_history.c @@ -1,5 +1,6 @@ /* * Copyright 2006 Rob Kendrick + * Copyright 2009 Paul Blokus * * This file is part of NetSurf, http://www.netsurf-browser.org/ * @@ -16,612 +17,248 @@ * along with this program. If not, see . */ -#include - -#include -#include +#include "desktop/history_global_core.h" +#include "desktop/plotters.h" +#include "desktop/tree.h" +#include "gtk/gtk_gui.h" +#include "gtk/gtk_history.h" +#include "gtk/gtk_plotters.h" +#include "gtk/gtk_scaffolding.h" +#include "gtk/gtk_treeview.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" -enum -{ - SITE_TITLE = 0, - SITE_DOMAIN, - SITE_ADDRESS, - SITE_LASTVISIT, - SITE_TOTALVISITS, - SITE_THUMBNAIL, - SITE_NCOLS +#define MENUPROTO(x) static gboolean nsgtk_on_##x##_activate( \ + GtkMenuItem *widget, gpointer g) +#define MENUEVENT(x) { #x, G_CALLBACK(nsgtk_on_##x##_activate) } +#define MENUHANDLER(x) gboolean nsgtk_on_##x##_activate(GtkMenuItem *widget, \ + gpointer g) + +struct menu_events { + const char *widget; + GCallback handler; }; -enum -{ - DOM_DOMAIN, - DOM_LASTVISIT, - DOM_TOTALVISITS, - DOM_HAS_SITES, - DOM_NCOLS +static void nsgtk_history_init_menu(void); + +/* file menu*/ +MENUPROTO(export); + +/* edit menu */ +MENUPROTO(delete_selected); +MENUPROTO(delete_all); +MENUPROTO(select_all); +MENUPROTO(clear_selection); + +/* view menu*/ +MENUPROTO(expand_all); +MENUPROTO(expand_directories); +MENUPROTO(expand_addresses); +MENUPROTO(collapse_all); +MENUPROTO(collapse_directories); +MENUPROTO(collapse_addresses); + +MENUPROTO(launch); + +static struct menu_events menu_events[] = { + + /* file menu*/ + MENUEVENT(export), + + /* edit menu */ + MENUEVENT(delete_selected), + MENUEVENT(delete_all), + MENUEVENT(select_all), + MENUEVENT(clear_selection), + + /* view menu*/ + MENUEVENT(expand_all), + MENUEVENT(expand_directories), + MENUEVENT(expand_addresses), + MENUEVENT(collapse_all), + MENUEVENT(collapse_directories), + MENUEVENT(collapse_addresses), + + MENUEVENT(launch), + {NULL, NULL} }; -GtkWindow *wndHistory; +static struct nsgtk_treeview *global_history_window; static GladeXML *gladeFile; +GtkWindow *wndHistory; -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(void); -static void nsgtk_history_init_filters(void); -static void nsgtk_history_init_sort(void); -static void nsgtk_history_init_treeviews(void); -static void nsgtk_history_init_list(void); - -static bool nsgtk_history_add_internal(const char *, const struct url_data *); - -static void nsgtk_history_show_domain(GtkTreeSelection *treesel, - GString *domain_filter); - -static void nsgtk_history_show_all(void); - -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(void); -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); +/** + * Creates the window for the global history tree. + */ bool nsgtk_history_init(void) { - dateToday = messages_get("DateToday"); - dateYesterday = messages_get("DateYesterday"); - dateAt = messages_get("DateAt"); - domainAll = messages_get("DomainAll"); - + GtkWindow *window; + GtkScrolledWindow *scrolled; + GtkDrawingArea *drawing_area; + gladeFile = glade_xml_new(glade_history_file_location, NULL, NULL); if (gladeFile == NULL) return false; 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(); - - nsgtk_history_show_all(); - - return true; -} - -void nsgtk_history_init_model(void) -{ - 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); + wndHistory = GTK_WINDOW(glade_xml_get_widget(gladeFile, "wndHistory")); - 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); + window = wndHistory; - 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); -} + scrolled = GTK_SCROLLED_WINDOW(glade_xml_get_widget(gladeFile, + "globalHistoryScrolled")); -void nsgtk_history_init_list(void) -{ - GtkTreeIter iter; + drawing_area = GTK_DRAWING_AREA(glade_xml_get_widget(gladeFile, + "globalHistoryDrawingArea")); + + global_history_window = nsgtk_treeview_create( + history_global_get_tree_flags(), window, scrolled, + drawing_area); - gtk_list_store_clear(history->history_list); - gtk_list_store_clear(history->domain_list); + if (global_history_window == NULL) + return false; - 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); +#define CONNECT(obj, sig, callback, ptr) \ + g_signal_connect(G_OBJECT(obj), (sig), G_CALLBACK(callback), (ptr)) - urldb_iterate_entries(nsgtk_history_add_internal); -} - -void nsgtk_history_init_filters(void) -{ - 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"); + CONNECT(window, "delete_event", gtk_widget_hide_on_delete, NULL); + CONNECT(window, "hide", nsgtk_tree_window_hide, global_history_window); - 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)); + history_global_initialise( + nsgtk_treeview_get_tree(global_history_window)); - 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); + nsgtk_history_init_menu(); + + return true; } -void nsgtk_history_init_sort(void) -{ - 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(void) -{ - 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) +/** + * Connects menu events in the global history window. + */ +void nsgtk_history_init_menu(void) { - GtkTreeIter iter; - gchar *domain, *path; - if (url_host(url, &domain) != URL_FUNC_OK) - strcpy(domain, messages_get("gtkUnknownHost")); + struct menu_events *event = menu_events; - if (data->visits > 0) + while (event->widget != NULL) { - 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); + GtkWidget *w = glade_xml_get_widget(gladeFile, event->widget); + g_signal_connect(G_OBJECT(w), "activate", event->handler, + global_history_window); + event++; } - return true; } -gchar *nsgtk_history_parent_get(gchar *domain) -{ - GtkTreeIter iter; - 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); - } - return path; +/** + * Destroys the global history window and performs any other necessary cleanup + * actions. + */ +void nsgtk_history_destroy(void) +{ + /* TODO: what about gladeFile? */ + history_global_cleanup(); + nsgtk_treeview_destroy(global_history_window); } -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); - - /* 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) +/* file menu*/ +MENUHANDLER(export) { - GtkTreeIter iter; - GtkTreeModel *model; - - 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)); + GtkWidget *save_dialog; + save_dialog = gtk_file_chooser_dialog_new("Save File", + wndHistory, + GTK_FILE_CHOOSER_ACTION_SAVE, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, + NULL); + + gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(save_dialog), + getenv("HOME") ? getenv("HOME") : "/"); + + gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(save_dialog), + "history.html"); + + if (gtk_dialog_run(GTK_DIALOG(save_dialog)) == GTK_RESPONSE_ACCEPT) { + gchar *filename = gtk_file_chooser_get_filename( + GTK_FILE_CHOOSER(save_dialog)); + + history_global_export(filename); + g_free(filename); } - nsgtk_history_update_info(treesel, TRUE); -} + gtk_widget_destroy(save_dialog); -static void nsgtk_history_show_all(void) -{ - GtkTreePath *path = gtk_tree_path_new_from_string("0"); - - gtk_tree_selection_select_path(history->domain_selection, path); - - gtk_tree_path_free(path); + return TRUE; } -gboolean nsgtk_history_filter_search(GtkTreeModel *model, GtkTreeIter *iter, - GtkWidget *search_entry) +/* edit menu */ +MENUHANDLER(delete_selected) { - 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; + history_global_delete_selected(); + return TRUE; } -gboolean nsgtk_history_filter_sites(GtkTreeModel *model, GtkTreeIter *iter, - GString *domain_filter) +MENUHANDLER(delete_all) { - 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; + history_global_delete_all(); + return TRUE; } -void nsgtk_history_domain_sort_changed(GtkComboBox *combo) +MENUHANDLER(select_all) { - 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); + history_global_select_all(); + return TRUE; } -gint nsgtk_history_domain_sort_compare(GtkTreeModel *model, GtkTreeIter *a, - GtkTreeIter *b, gint sort_column) +MENUHANDLER(clear_selection) { - 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; + history_global_clear_selection(); + return TRUE; } -void nsgtk_history_domain_set_visible (GtkTreeModel *model, GtkTreePath *path, - GtkTreeIter *iter, gboolean has_sites) +/* view menu*/ +MENUHANDLER(expand_all) { - 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); + history_global_expand_all(); + return TRUE; } -void nsgtk_history_search() +MENUHANDLER(expand_directories) { - 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)); + history_global_expand_directories(); + return TRUE; } -void nsgtk_history_search_clear (GtkEntry *entry) +MENUHANDLER(expand_addresses) { - gtk_entry_set_text(entry, ""); -} - -gchar *nsgtk_history_date_parse(time_t visit_time) -{ - char *date_string = malloc(30); - char format[30]; - time_t current_time = time(NULL); - int current_day = localtime(¤t_time)->tm_yday; - struct tm *visit_date = localtime(&visit_time); - - if (visit_date->tm_yday == current_day) - snprintf(format, 30, "%s %s %%I:%%M %%p", - dateToday, dateAt); - else if (current_day - visit_date->tm_yday == 1) - snprintf(format, 30, "%s %s %%I:%%M %%p", - dateYesterday, dateAt); - else if (current_day - visit_date->tm_yday < 7) - snprintf(format, 30, "%%A %s %%I:%%M %%p", - dateAt); - else - snprintf(format, 30, "%%B %%d, %%Y"); - - strftime(date_string, 30, format, visit_date); - - return date_string; + history_global_expand_addresses(); + return TRUE; } - - -void nsgtk_history_row_activated(GtkTreeView *tv, GtkTreePath *path, - GtkTreeViewColumn *column) -{ - GtkTreeModel *model; - GtkTreeIter iter; - - model = gtk_tree_view_get_model(tv); - if (gtk_tree_model_get_iter(model, &iter, path)) - { - gchar *address; - gtk_tree_model_get(model, &iter, SITE_ADDRESS, &address, -1); - - browser_window_create(address, NULL, NULL, true, false); - } +MENUHANDLER(collapse_all) +{ + history_global_collapse_all(); + return TRUE; } -void nsgtk_history_update_info(GtkTreeSelection *treesel, gboolean domain) +MENUHANDLER(collapse_directories) { - 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); - - 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); - } + history_global_collapse_directories(); + return TRUE; } -void nsgtk_history_scroll_top (GtkScrolledWindow *scrolled_window) +MENUHANDLER(collapse_addresses) { - GtkAdjustment *adjustment = - gtk_scrolled_window_get_vadjustment(scrolled_window); - - gtk_adjustment_set_value(adjustment, 0); - - gtk_scrolled_window_set_vadjustment(scrolled_window, adjustment); + history_global_collapse_addresses(); + return TRUE; } - -void global_history_add(const char *url) -{ - const struct url_data *data; - data = urldb_get_url_data(url); - if (!data) - return; - - nsgtk_history_add_internal(url, data); +MENUHANDLER(launch) +{ + history_global_launch_selected(); + return TRUE; } diff --git a/gtk/gtk_history.h b/gtk/gtk_history.h index 02cb7f920..93d57b2b7 100644 --- a/gtk/gtk_history.h +++ b/gtk/gtk_history.h @@ -1,5 +1,6 @@ /* * Copyright 2006 Rob Kendrick + * Copyright 2009 Paul Blokus * * This file is part of NetSurf, http://www.netsurf-browser.org/ * @@ -23,22 +24,7 @@ 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; -}; - bool nsgtk_history_init(void); +void nsgtk_history_destroy(void); #endif /* __NSGTK_HISTORY_H__ */ diff --git a/gtk/gtk_hotlist.c b/gtk/gtk_hotlist.c new file mode 100644 index 000000000..905050260 --- /dev/null +++ b/gtk/gtk_hotlist.c @@ -0,0 +1,277 @@ +/* + * Copyright 2009 Paul Blokus + * + * 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 . + */ + + +#include "desktop/hotlist.h" +#include "desktop/options.h" +#include "desktop/plotters.h" +#include "desktop/tree.h" +#include "gtk/gtk_gui.h" +#include "gtk/gtk_hotlist.h" +#include "gtk/options.h" +#include "gtk/gtk_plotters.h" +#include "gtk/gtk_scaffolding.h" +#include "gtk/gtk_treeview.h" +#include "utils/log.h" + +#define GLADE_NAME "hotlist.glade" + +#define MENUPROTO(x) static gboolean nsgtk_on_##x##_activate( \ + GtkMenuItem *widget, gpointer g) +#define MENUEVENT(x) { #x, G_CALLBACK(nsgtk_on_##x##_activate) } +#define MENUHANDLER(x) gboolean nsgtk_on_##x##_activate(GtkMenuItem *widget, \ + gpointer g) + +struct menu_events { + const char *widget; + GCallback handler; +}; + +static void nsgtk_hotlist_init_menu(void); + +/* file menu*/ +MENUPROTO(export); +MENUPROTO(new_folder); +MENUPROTO(new_entry); + +/* edit menu */ +MENUPROTO(edit_selected); +MENUPROTO(delete_selected); +MENUPROTO(select_all); +MENUPROTO(clear_selection); + +/* view menu*/ +MENUPROTO(expand_all); +MENUPROTO(expand_directories); +MENUPROTO(expand_addresses); +MENUPROTO(collapse_all); +MENUPROTO(collapse_directories); +MENUPROTO(collapse_addresses); + +MENUPROTO(launch); + +static struct menu_events menu_events[] = { + + /* file menu*/ + MENUEVENT(export), + MENUEVENT(new_folder), + MENUEVENT(new_entry), + + /* edit menu */ + MENUEVENT(edit_selected), + MENUEVENT(delete_selected), + MENUEVENT(select_all), + MENUEVENT(clear_selection), + + /* view menu*/ + MENUEVENT(expand_all), + MENUEVENT(expand_directories), + MENUEVENT(expand_addresses), + MENUEVENT(collapse_all), + MENUEVENT(collapse_directories), + MENUEVENT(collapse_addresses), + + MENUEVENT(launch), + {NULL, NULL} +}; + +static struct nsgtk_treeview *hotlist_window; +static GladeXML *gladeFile; +GtkWindow *wndHotlist; + + +/** + * Creates the window for the hotlist tree. + */ +void nsgtk_hotlist_init() +{ + gchar *glade_location = g_strconcat(res_dir_location, GLADE_NAME, NULL); + gladeFile = glade_xml_new(glade_location, NULL, NULL); + g_free(glade_location); + GtkWindow *window; + GtkScrolledWindow *scrolled; + GtkDrawingArea *drawing_area; + + glade_xml_signal_autoconnect(gladeFile); + + wndHotlist = GTK_WINDOW(glade_xml_get_widget(gladeFile, "wndHotlist")); + window = wndHotlist; + + scrolled = GTK_SCROLLED_WINDOW(glade_xml_get_widget(gladeFile, + "hotlistScrolled")); + + drawing_area = GTK_DRAWING_AREA(glade_xml_get_widget(gladeFile, + "hotlistDrawingArea")); + + + hotlist_window = nsgtk_treeview_create(hotlist_get_tree_flags(), window, + scrolled, drawing_area); + + if (hotlist_window == NULL) + return; + +#define CONNECT(obj, sig, callback, ptr) \ + g_signal_connect(G_OBJECT(obj), (sig), G_CALLBACK(callback), (ptr)) + + CONNECT(window, "delete_event", gtk_widget_hide_on_delete, NULL); + CONNECT(window, "hide", nsgtk_tree_window_hide, hotlist_window); + + hotlist_initialise(nsgtk_treeview_get_tree(hotlist_window), + option_hotlist_path); + + nsgtk_hotlist_init_menu(); +} + + +/** + * Connects menu events in the hotlist window. + */ +void nsgtk_hotlist_init_menu(void) +{ + struct menu_events *event = menu_events; + + while (event->widget != NULL) + { + GtkWidget *w = glade_xml_get_widget(gladeFile, event->widget); + g_signal_connect(G_OBJECT(w), "activate", event->handler, + hotlist_window); + event++; + } +} + + +/** + * Destroys the hotlist window and performs any other necessary cleanup actions. + */ +void nsgtk_hotlist_destroy(void) +{ + /* TODO: what about gladeFile? */ + hotlist_cleanup(option_hotlist_path); + nsgtk_treeview_destroy(hotlist_window); +} + + +/* file menu*/ +MENUHANDLER(export) +{ + GtkWidget *save_dialog; + save_dialog = gtk_file_chooser_dialog_new("Save File", + wndHotlist, + GTK_FILE_CHOOSER_ACTION_SAVE, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, + NULL); + + gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(save_dialog), + getenv("HOME") ? getenv("HOME") : "/"); + + gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(save_dialog), + "hotlist.html"); + + if (gtk_dialog_run(GTK_DIALOG(save_dialog)) == GTK_RESPONSE_ACCEPT) { + gchar *filename = gtk_file_chooser_get_filename( + GTK_FILE_CHOOSER(save_dialog)); + + hotlist_export(filename); + g_free(filename); + } + + gtk_widget_destroy(save_dialog); + + return TRUE; +} + +MENUHANDLER(new_folder) +{ + hotlist_add_folder(); + return TRUE; +} + +MENUHANDLER(new_entry) +{ + hotlist_add_entry(); + return TRUE; +} + +/* edit menu */ +MENUHANDLER(edit_selected) +{ + hotlist_edit_selected(); + return TRUE; +} + +MENUHANDLER(delete_selected) +{ + hotlist_delete_selected(); + return TRUE; +} + +MENUHANDLER(select_all) +{ + hotlist_select_all(); + return TRUE; +} + +MENUHANDLER(clear_selection) +{ + hotlist_clear_selection(); + return TRUE; +} + +/* view menu*/ +MENUHANDLER(expand_all) +{ + hotlist_expand_all(); + return TRUE; +} + +MENUHANDLER(expand_directories) +{ + hotlist_expand_directories(); + return TRUE; +} + +MENUHANDLER(expand_addresses) +{ + hotlist_expand_addresses(); + return TRUE; +} + +MENUHANDLER(collapse_all) +{ + hotlist_collapse_all(); + return TRUE; +} + +MENUHANDLER(collapse_directories) +{ + hotlist_collapse_directories(); + return TRUE; +} + +MENUHANDLER(collapse_addresses) +{ + hotlist_collapse_addresses(); + return TRUE; +} + +MENUHANDLER(launch) +{ + hotlist_launch_selected(); + return TRUE; +} diff --git a/gtk/gtk_hotlist.h b/gtk/gtk_hotlist.h new file mode 100644 index 000000000..22dc0a45f --- /dev/null +++ b/gtk/gtk_hotlist.h @@ -0,0 +1,33 @@ +/* + * Copyright 2009 Paul Blokus + * + * 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 . + */ + +/** \file + * GTK hotlist (interface). + */ + +#ifndef __NSGTK_HOTLIST_H__ +#define __NSGTK_HOTLIST_H__ + +#include + +extern GtkWindow *wndHotlist; + +void nsgtk_hotlist_init(void); +void nsgtk_hotlist_destroy(void); + +#endif /* __NSGTK_HOTLIST_H__ */ diff --git a/gtk/gtk_menu.c b/gtk/gtk_menu.c index af9d0b67c..6fb5fc313 100644 --- a/gtk/gtk_menu.c +++ b/gtk/gtk_menu.c @@ -397,6 +397,7 @@ static struct nsgtk_nav_menu *nsgtk_menu_nav_menu(GtkAccelGroup *group, free(ret); return NULL; } + IMAGE_ITEM(nav, back, gtkBack, ret, group); IMAGE_ITEM(nav, forward, gtkForward, ret, group); IMAGE_ITEM(nav, home, gtkHome, ret, group); @@ -407,6 +408,8 @@ static struct nsgtk_nav_menu *nsgtk_menu_nav_menu(GtkAccelGroup *group, IMAGE_ITEM(nav, addbookmarks, gtkAddBookMarks, ret, group); IMAGE_ITEM(nav, showbookmarks, gtkShowBookMarks, ret, group); ADD_SEP(nav, ret); + IMAGE_ITEM(nav, showcookies, gtkShowCookies, ret, group); + ADD_SEP(nav, ret); IMAGE_ITEM(nav, openlocation, gtkOpenLocation, ret, group); ATTACH_PARENT(parent, gtkNavigate, ret->nav, group); diff --git a/gtk/gtk_menu.h b/gtk/gtk_menu.h index 2ddacd891..434eafd1b 100644 --- a/gtk/gtk_menu.h +++ b/gtk/gtk_menu.h @@ -78,6 +78,7 @@ struct nsgtk_nav_menu { GtkImageMenuItem *globalhistory_menuitem; GtkImageMenuItem *addbookmarks_menuitem; GtkImageMenuItem *showbookmarks_menuitem; + GtkImageMenuItem *showcookies_menuitem; GtkImageMenuItem *openlocation_menuitem; }; diff --git a/gtk/gtk_plotters.c b/gtk/gtk_plotters.c index 9598e2022..1428710ec 100644 --- a/gtk/gtk_plotters.c +++ b/gtk/gtk_plotters.c @@ -89,9 +89,9 @@ void nsgtk_set_colour(colour c) g / 255.0, b / 255.0, 1.0); } -/** Plot a caret. +/** Plot a caret. * - * @note It is assumed that the plotters have been set up. + * @note It is assumed that the plotters have been set up. */ void nsgtk_plot_caret(int x, int y, int h) { @@ -234,8 +234,12 @@ static bool nsgtk_plot_line(int x0, int y0, int x1, int y1, const plot_style_t * else cairo_set_line_width(current_cr, style->stroke_width); - cairo_move_to(current_cr, x0 + 0.5, y0 + 0.5); - cairo_line_to(current_cr, x1 + 0.5, y1 + 0.5); + /* core expects horizontal and vertical lines to be on pixels, not + * between pixels */ + cairo_move_to(current_cr, (x0 == x1) ? x0 + 0.5 : x0, + (y0 == y1) ? y0 + 0.5 : y0); + cairo_line_to(current_cr, (x0 == x1) ? x1 + 0.5 : x1, + (y0 == y1) ? y1 + 0.5 : y1); cairo_stroke(current_cr); return true; @@ -304,7 +308,7 @@ static bool nsgtk_plot_polygon(const int *p, unsigned int n, const plot_style_t -static bool nsgtk_plot_text(int x, int y, const char *text, size_t length, +static bool nsgtk_plot_text(int x, int y, const char *text, size_t length, const plot_font_style_t *fstyle) { return nsfont_paint(x, y, text, length, fstyle); diff --git a/gtk/gtk_scaffolding.c b/gtk/gtk_scaffolding.c index b2c7c7dba..e970a60af 100644 --- a/gtk/gtk_scaffolding.c +++ b/gtk/gtk_scaffolding.c @@ -34,6 +34,7 @@ #include "css/utils.h" #include "desktop/browser.h" #include "desktop/history_core.h" +#include "desktop/hotlist.h" #include "desktop/gui.h" #include "desktop/netsurf.h" #include "desktop/options.h" @@ -49,6 +50,8 @@ #include "desktop/searchweb.h" #include "desktop/selection.h" #include "desktop/textinput.h" +#include "desktop/tree.h" +#include "gtk/gtk_cookies.h" #include "gtk/gtk_completion.h" #include "gtk/dialogs/gtk_options.h" #include "gtk/dialogs/gtk_about.h" @@ -57,6 +60,7 @@ #include "gtk/gtk_download.h" #include "gtk/gtk_gui.h" #include "gtk/gtk_history.h" +#include "gtk/gtk_hotlist.h" #include "gtk/gtk_menu.h" #include "gtk/gtk_plotters.h" #include "gtk/gtk_print.h" @@ -66,6 +70,7 @@ #include "gtk/gtk_theme.h" #include "gtk/gtk_throbber.h" #include "gtk/gtk_toolbar.h" +#include "gtk/gtk_treeview.h" #include "gtk/gtk_window.h" #include "gtk/options.h" #include "gtk/sexy_icon_entry.h" @@ -217,7 +222,7 @@ void nsgtk_window_close(struct gtk_scaffolding *g) if ((g->history_window) && (g->history_window->window)) { gtk_widget_destroy(GTK_WIDGET(g->history_window->window)); } - + if (--open_windows == 0) netsurf_quit = true; @@ -1263,17 +1268,34 @@ MULTIHANDLER(globalhistory) { gtk_widget_show(GTK_WIDGET(wndHistory)); gdk_window_raise(GTK_WIDGET(wndHistory)->window); - + return TRUE; } MULTIHANDLER(addbookmarks) { + struct browser_window *bw = gui_window_get_browser_window(g->top_level); + + if (bw == NULL || bw->current_content == NULL || + content_get_url(bw->current_content) == NULL) + return TRUE; + hotlist_add_page(content_get_url(bw->current_content)); return TRUE; } MULTIHANDLER(showbookmarks) { + gtk_widget_show(GTK_WIDGET(wndHotlist)); + gdk_window_raise(GTK_WIDGET(wndHotlist)->window); + + return TRUE; +} + +MULTIHANDLER(showcookies) +{ + gtk_widget_show(GTK_WIDGET(wndCookies)); + gdk_window_raise(GTK_WIDGET(wndCookies)->window); + return TRUE; } @@ -1394,6 +1416,7 @@ gboolean nsgtk_history_button_press_event(GtkWidget *widget, return TRUE; } + #define GET_WIDGET(x) glade_xml_get_widget(g->xml, (x)) nsgtk_scaffolding *nsgtk_new_scaffolding(struct gui_window *toplevel) @@ -1582,6 +1605,7 @@ nsgtk_scaffolding *nsgtk_new_scaffolding(struct gui_window *toplevel) gtk_scrolled_window_add_with_viewport(g->history_window->scrolled, GTK_WIDGET(g->history_window->drawing_area)); gtk_widget_show(GTK_WIDGET(g->history_window->drawing_area)); + /* set up URL bar completion */ g->url_bar_completion = gtk_entry_completion_new(); @@ -1613,7 +1637,7 @@ nsgtk_scaffolding *nsgtk_new_scaffolding(struct gui_window *toplevel) nsgtk_history_button_press_event, g->history_window); CONNECT(g->history_window->window, "delete_event", gtk_widget_hide_on_delete, NULL); - + g_signal_connect_after(g->notebook, "page-added", G_CALLBACK(nsgtk_window_tabs_num_changed), g); g_signal_connect_after(g->notebook, "page-removed", @@ -2408,6 +2432,7 @@ void nsgtk_scaffolding_toolbar_init(struct gtk_scaffolding *g) ITEM_MAIN(GLOBALHISTORY, nav, globalhistory); ITEM_MAIN(ADDBOOKMARKS, nav, addbookmarks); ITEM_MAIN(SHOWBOOKMARKS, nav, showbookmarks); + ITEM_MAIN(SHOWCOOKIES, nav, showcookies); ITEM_MAIN(OPENLOCATION, nav, openlocation); ITEM_MAIN(CONTENTS, help, contents); ITEM_MAIN(INFO, help, info); @@ -2437,8 +2462,6 @@ void nsgtk_scaffolding_toolbar_init(struct gtk_scaffolding *g) SENSITIVITY(CONTENTS); SENSITIVITY(DRAWFILE); SENSITIVITY(POSTSCRIPT); - SENSITIVITY(ADDBOOKMARKS); - SENSITIVITY(SHOWBOOKMARKS); SENSITIVITY(NEXTTAB); SENSITIVITY(PREVTAB); SENSITIVITY(CLOSETAB); diff --git a/gtk/gtk_scaffolding.h b/gtk/gtk_scaffolding.h index ddc9fb232..1db576ac1 100644 --- a/gtk/gtk_scaffolding.h +++ b/gtk/gtk_scaffolding.h @@ -73,6 +73,7 @@ typedef enum { GLOBALHISTORY_BUTTON, ADDBOOKMARKS_BUTTON, SHOWBOOKMARKS_BUTTON, + SHOWCOOKIES_BUTTON, OPENLOCATION_BUTTON, NEXTTAB_BUTTON, PREVTAB_BUTTON, @@ -209,6 +210,7 @@ MULTIPROTO(localhistory); MULTIPROTO(globalhistory); MULTIPROTO(addbookmarks); MULTIPROTO(showbookmarks); +MULTIPROTO(showcookies); MULTIPROTO(openlocation); /* tabs menu */ diff --git a/gtk/gtk_theme.c b/gtk/gtk_theme.c index 05421c3d3..98fc03410 100644 --- a/gtk/gtk_theme.c +++ b/gtk/gtk_theme.c @@ -447,6 +447,7 @@ struct nsgtk_theme *nsgtk_theme_load(GtkIconSize s) SET_BUTTON_IMAGE(cachetheme, GLOBALHISTORY, theme) SET_BUTTON_IMAGE(cachetheme, ADDBOOKMARKS, theme) SET_BUTTON_IMAGE(cachetheme, SHOWBOOKMARKS, theme) + SET_BUTTON_IMAGE(cachetheme, SHOWCOOKIES, theme) SET_BUTTON_IMAGE(cachetheme, OPENLOCATION, theme) SET_BUTTON_IMAGE(cachetheme, NEXTTAB, theme) SET_BUTTON_IMAGE(cachetheme, PREVTAB, theme) @@ -571,6 +572,7 @@ void nsgtk_theme_prepare(void) CACHE_IMAGE(GLOBALHISTORY, globalhistory, path); CACHE_IMAGE(ADDBOOKMARKS, addbookmarks, path); CACHE_IMAGE(SHOWBOOKMARKS, showbookmarks, path); + CACHE_IMAGE(SHOWCOOKIES, showcookies, path); CACHE_IMAGE(OPENLOCATION, openlocation, path); CACHE_IMAGE(NEXTTAB, nexttab, path); CACHE_IMAGE(PREVTAB, prevtab, path); diff --git a/gtk/gtk_toolbar.c b/gtk/gtk_toolbar.c index 92bb21f93..ab463a103 100644 --- a/gtk/gtk_toolbar.c +++ b/gtk/gtk_toolbar.c @@ -822,6 +822,7 @@ GtkWidget *nsgtk_toolbar_make_widget(nsgtk_scaffolding *g, MAKE_MENUBUTTON(GLOBALHISTORY, gtkGlobalHistory) MAKE_MENUBUTTON(ADDBOOKMARKS, gtkAddBookMarks) MAKE_MENUBUTTON(SHOWBOOKMARKS, gtkShowBookMarks) + MAKE_MENUBUTTON(SHOWCOOKIES, gtkShowCookies) MAKE_MENUBUTTON(OPENLOCATION, gtkOpenLocation) MAKE_MENUBUTTON(NEXTTAB, gtkNextTab) MAKE_MENUBUTTON(PREVTAB, gtkPrevTab) @@ -986,6 +987,7 @@ DATAHANDLER(localhistory, LOCALHISTORY, window) DATAHANDLER(globalhistory, GLOBALHISTORY, window) DATAHANDLER(addbookmarks, ADDBOOKMARKS, window) DATAHANDLER(showbookmarks, SHOWBOOKMARKS, window) +DATAHANDLER(showcookies, SHOWCOOKIES, window) DATAHANDLER(openlocation, OPENLOCATION, window) DATAHANDLER(nexttab, NEXTTAB, window) DATAHANDLER(prevtab, PREVTAB, window) diff --git a/gtk/gtk_toolbar.h b/gtk/gtk_toolbar.h index a470a4480..7d483578b 100644 --- a/gtk/gtk_toolbar.h +++ b/gtk/gtk_toolbar.h @@ -74,6 +74,7 @@ TOOLPROTO(localhistory); TOOLPROTO(globalhistory); TOOLPROTO(addbookmarks); TOOLPROTO(showbookmarks); +TOOLPROTO(showcookies); TOOLPROTO(openlocation); TOOLPROTO(nexttab); TOOLPROTO(prevtab); diff --git a/gtk/gtk_treeview.c b/gtk/gtk_treeview.c index 6e5643009..20562e3d5 100644 --- a/gtk/gtk_treeview.c +++ b/gtk/gtk_treeview.c @@ -1,5 +1,6 @@ /* * Copyright 2004 Richard Wilson + * Copyright 2009 Paul Blokus * * This file is part of NetSurf, http://www.netsurf-browser.org/ * @@ -20,108 +21,522 @@ * Generic tree handling (implementation). */ +#include +#include +#include +#include #include "desktop/tree.h" +#include "desktop/tree_url_node.h" +#include "desktop/plotters.h" +#include "gtk/gtk_gui.h" +#include "gtk/gtk_plotters.h" +#include "gtk/gtk_treeview.h" +#include "utils/log.h" +#include "utils/utils.h" +struct nsgtk_treeview { + GtkWindow *window; + GtkScrolledWindow *scrolled; + GtkDrawingArea *drawing_area; + int mouse_pressed_x; + int mouse_pressed_y; + browser_mouse_state mouse_state; + struct tree *tree; +}; -/** - * Sets the origin variables to the correct values for a specified tree - * - * \param tree the tree to set the origin for - */ -void tree_initialise_redraw(struct tree *tree) { -} +const char tree_directory_icon_name[] = "directory.png"; +const char tree_content_icon_name[] = "content.png"; +static void nsgtk_tree_redraw_request(int x, int y, int width, int height, + void *data); +static void nsgtk_tree_resized(struct tree *tree, int width, int height, void *data); +static void nsgtk_tree_scroll_visible(int y, int height, void *data); +static void nsgtk_tree_get_window_dimensions(int *width, int *height, void *data); -/** - * Informs the current window manager that an area requires updating. - * - * \param tree the tree that is requesting a redraw - * \param x the x co-ordinate of the redraw area - * \param y the y co-ordinate of the redraw area - * \param width the width of the redraw area - * \param height the height of the redraw area - */ -void tree_redraw_area(struct tree *tree, int x, int y, int width, int height) { -} +static const struct treeview_table nsgtk_tree_callbacks = { + .redraw_request = nsgtk_tree_redraw_request, + .resized = nsgtk_tree_resized, + .scroll_visible = nsgtk_tree_scroll_visible, + .get_window_dimensions = nsgtk_tree_get_window_dimensions +}; +struct nsgtk_treeview *nsgtk_treeview_create(unsigned int flags, + GtkWindow *window, GtkScrolledWindow *scrolled, + GtkDrawingArea *drawing_area) +{ + struct nsgtk_treeview *tv; + + tv = malloc(sizeof(struct nsgtk_treeview)); + if (tv == NULL) { + LOG(("malloc failed")); + warn_user("NoMemory", 0); + return NULL; + } + + tv->window = window; + tv->scrolled = scrolled; + tv->drawing_area = drawing_area; + tv->tree = tree_create(flags, &nsgtk_tree_callbacks, tv); + tv->mouse_state = 0; + + gtk_widget_modify_bg(GTK_WIDGET(drawing_area), GTK_STATE_NORMAL, + &((GdkColor) { 0, 0xffff, 0xffff, 0xffff } )); + +#define CONNECT(obj, sig, callback, ptr) \ + g_signal_connect(G_OBJECT(obj), (sig), G_CALLBACK(callback), (ptr)) + + CONNECT(drawing_area, "expose_event", + nsgtk_tree_window_expose_event, + tv->tree); + CONNECT(drawing_area, "button_press_event", + nsgtk_tree_window_button_press_event, + tv); + CONNECT(drawing_area, "button_release_event", + nsgtk_tree_window_button_release_event, + tv); + CONNECT(drawing_area, "motion_notify_event", + nsgtk_tree_window_motion_notify_event, + tv); + CONNECT(drawing_area, "key_press_event", + nsgtk_tree_window_keypress_event, + tv); + return tv; +} -/** - * Draws a line. - * - * \param x the x co-ordinate - * \param x the y co-ordinate - * \param x the width of the line - * \param x the height of the line - */ -void tree_draw_line(int x, int y, int width, int height) { +void nsgtk_treeview_destroy(struct nsgtk_treeview *tv) +{ + tree_delete(tv->tree); + gtk_widget_destroy(GTK_WIDGET(tv->window)); + free(tv); } +struct tree *nsgtk_treeview_get_tree(struct nsgtk_treeview *tv) +{ + return tv->tree; +} -/** - * Draws an element, including any expansion icons - * - * \param tree the tree to draw an element for - * \param element the element to draw - */ -void tree_draw_node_element(struct tree *tree, struct node_element *element) { +void nsgtk_tree_redraw_request(int x, int y, int width, int height, void *data) +{ + struct nsgtk_treeview *tw = data; + + gtk_widget_queue_draw_area(GTK_WIDGET(tw->drawing_area), + x, y, width, height); } /** - * Draws an elements expansion icon + * Updates the tree owner following a tree resize * - * \param tree the tree to draw the expansion for - * \param element the element to draw the expansion for + * \param tree the tree to update the owner of */ -void tree_draw_node_expansion(struct tree *tree, struct node *node) { +void nsgtk_tree_resized(struct tree *tree, int width, int height, void *data) +{ + struct nsgtk_treeview *tw = data; + + gtk_widget_set_size_request(GTK_WIDGET(tw->drawing_area), + width, height); + return; } - /** - * Recalculates the dimensions of a node element. + * Translates a content_type to the name of a respective icon * - * \param element the element to recalculate + * \param content_type content type + * \param buffer buffer for the icon name */ -void tree_recalculate_node_element(struct node_element *element) { +void tree_icon_name_from_content_type(char *buffer, content_type type) +{ + // TODO: design/acquire icons + switch (type) { + case CONTENT_HTML: + case CONTENT_TEXTPLAIN: + case CONTENT_CSS: +#if defined(WITH_MNG) || defined(WITH_PNG) + case CONTENT_PNG: +#endif +#ifdef WITH_MNG + case CONTENT_JNG: + case CONTENT_MNG: +#endif +#ifdef WITH_JPEG + case CONTENT_JPEG: +#endif +#ifdef WITH_GIF + case CONTENT_GIF: +#endif +#ifdef WITH_BMP + case CONTENT_BMP: + case CONTENT_ICO: +#endif +#ifdef WITH_SPRITE + case CONTENT_SPRITE: +#endif +#ifdef WITH_DRAW + case CONTENT_DRAW: +#endif +#ifdef WITH_ARTWORKS + case CONTENT_ARTWORKS: +#endif +#ifdef WITH_NS_SVG + case CONTENT_SVG: +#endif + default: + sprintf(buffer, tree_content_icon_name); + break; + } } /** - * Sets a node element as having a specific sprite. + * Scrolls the tree to make an element visible * - * \param node the node to update - * \param sprite the sprite to use - * \param selected the expanded sprite name to use + * \param y Y coordinate of the element + * \param height height of the element + * \param data user data assigned to the tree on tree creation */ -void tree_set_node_sprite(struct node *node, const char *sprite, - const char *expanded) { +void nsgtk_tree_scroll_visible(int y, int height, void *data) +{ + int y0, y1; + gdouble page; + struct nsgtk_treeview *tw = data; + GtkAdjustment *vadj = gtk_scrolled_window_get_vadjustment(tw->scrolled); + assert(vadj); + + g_object_get(vadj, "page-size", &page, NULL); + + y0 = (int)(gtk_adjustment_get_value(vadj)); + y1 = y0 + page; + + if ((y >= y0) && (y + height <= y1)) + return; + if (y + height > y1) + y0 = y0 + (y + height - y1); + if (y < y0) + y0 = y; + gtk_adjustment_set_value(vadj, y0); } + /** - * Sets a node element as having a folder sprite + * Retrieves the dimensions of the window with the tree * - * \param node the node to update + * \param data user data assigned to the tree on tree creation + * \param width will be updated to window width if not NULL + * \param height will be updated to window height if not NULL */ -void tree_set_node_sprite_folder(struct node *node) { +void nsgtk_tree_get_window_dimensions(int *width, int *height, void *data) +{ + struct nsgtk_treeview *tw = data; + GtkAdjustment *vadj; + GtkAdjustment *hadj; + gdouble page; + + if (width != NULL) { + hadj = gtk_scrolled_window_get_hadjustment(tw->scrolled); + g_object_get(hadj, "page-size", &page, NULL); + *width = page; + } + + if (height != NULL) { + vadj = gtk_scrolled_window_get_vadjustment(tw->scrolled); + g_object_get(vadj, "page-size", &page, NULL); + *height = page; + } +} +/* signal handler functions for a tree window */ +gboolean nsgtk_tree_window_expose_event(GtkWidget *widget, + GdkEventExpose *event, gpointer g) +{ + struct tree *tree = (struct tree *) g; + int x, y, width, height; + + x = event->area.x; + y = event->area.y; + width = event->area.width; + height = event->area.height; + + current_widget = widget; + current_drawable = widget->window; + current_gc = gdk_gc_new(current_drawable); +#ifdef CAIRO_VERSION + current_cr = gdk_cairo_create(current_drawable); +#endif + plot = nsgtk_plotters; + nsgtk_plot_set_scale(1.0);current_widget = widget; + current_drawable = widget->window; + current_gc = gdk_gc_new(current_drawable); +#ifdef CAIRO_VERSION + current_cr = gdk_cairo_create(current_drawable); +#endif + plot = nsgtk_plotters; + nsgtk_plot_set_scale(1.0); + + tree_set_redraw(tree, true); + tree_draw(tree, 0, 0, x, y, width, height); + + current_widget = NULL; + g_object_unref(current_gc); +#ifdef CAIRO_VERSION + cairo_destroy(current_cr); +#endif + + return FALSE; } -/** - * Updates the node details for a URL node. - * The internal node dimensions are not updated. - * - * \param node the node to update - */ -void tree_update_URL_node(struct node *node, const char *url, - const struct url_data *data) { +void nsgtk_tree_window_hide(GtkWidget *widget, gpointer g) +{ + struct nsgtk_treeview *tw = g; + struct tree *tree = tw->tree; + + if (tree != NULL) + tree_set_redraw(tree, false); } +gboolean nsgtk_tree_window_button_press_event(GtkWidget *widget, + GdkEventButton *event, gpointer g) +{ + struct nsgtk_treeview *tw = g; + struct tree *tree = tw->tree; + + gtk_widget_grab_focus(GTK_WIDGET(tw->drawing_area)); + + + tw->mouse_pressed_x = event->x; + tw->mouse_pressed_y = event->y; -/** - * Updates the tree owner following a tree resize - * - * \param tree the tree to update the owner of - */ -void tree_resized(struct tree *tree) { + if (event->type == GDK_2BUTTON_PRESS) + tw->mouse_state = BROWSER_MOUSE_DOUBLE_CLICK; + + switch (event->button) { + case 1: tw->mouse_state |= BROWSER_MOUSE_PRESS_1; break; + case 3: tw->mouse_state |= BROWSER_MOUSE_PRESS_2; break; + } + /* Handle the modifiers too */ + if (event->state & GDK_SHIFT_MASK) + tw->mouse_state |= BROWSER_MOUSE_MOD_1; + if (event->state & GDK_CONTROL_MASK) + tw->mouse_state |= BROWSER_MOUSE_MOD_2; + if (event->state & GDK_MOD1_MASK) + tw->mouse_state |= BROWSER_MOUSE_MOD_3; + + tree_mouse_action(tree, tw->mouse_state, event->x, event->y); + + return TRUE; } + +gboolean nsgtk_tree_window_button_release_event(GtkWidget *widget, + GdkEventButton *event, gpointer g) +{ + bool shift = event->state & GDK_SHIFT_MASK; + bool ctrl = event->state & GDK_CONTROL_MASK; + bool alt = event->state & GDK_MOD1_MASK; + struct nsgtk_treeview *tw = (struct nsgtk_treeview *) g; + struct tree *tree = tw->tree; + + /* We consider only button 1 clicks as double clicks. + * If the mouse state is PRESS then we are waiting for a release to emit + * a click event, otherwise just reset the state to nothing*/ + if (tw->mouse_state & BROWSER_MOUSE_DOUBLE_CLICK) { + + if (tw->mouse_state & BROWSER_MOUSE_PRESS_1) + tw->mouse_state ^= BROWSER_MOUSE_PRESS_1; + else if (tw->mouse_state & BROWSER_MOUSE_PRESS_2) + tw->mouse_state ^= (BROWSER_MOUSE_PRESS_2 | + BROWSER_MOUSE_DOUBLE_CLICK); + + } else if (tw->mouse_state & BROWSER_MOUSE_PRESS_1) + tw->mouse_state ^= + (BROWSER_MOUSE_PRESS_1 | BROWSER_MOUSE_CLICK_1); + else if (tw->mouse_state & BROWSER_MOUSE_PRESS_2) + tw->mouse_state ^= (BROWSER_MOUSE_PRESS_2 | + BROWSER_MOUSE_CLICK_2); + + /* Handle modifiers being removed */ + if (tw->mouse_state & BROWSER_MOUSE_MOD_1 && !shift) + tw->mouse_state ^= BROWSER_MOUSE_MOD_1; + if (tw->mouse_state & BROWSER_MOUSE_MOD_2 && !ctrl) + tw->mouse_state ^= BROWSER_MOUSE_MOD_2; + if (tw->mouse_state & BROWSER_MOUSE_MOD_3 && !alt) + tw->mouse_state ^= BROWSER_MOUSE_MOD_3; + + + if (tw->mouse_state & + (BROWSER_MOUSE_CLICK_1 | BROWSER_MOUSE_CLICK_2 + | BROWSER_MOUSE_DOUBLE_CLICK)) + tree_mouse_action(tree, tw->mouse_state, + event->x, event->y); + else + tree_drag_end(tree, tw->mouse_state, + tw->mouse_pressed_x, + tw->mouse_pressed_y, + event->x, event->y); + + + tw->mouse_state = 0; + + + return TRUE; +} + +gboolean nsgtk_tree_window_motion_notify_event(GtkWidget *widget, + GdkEventButton *event, gpointer g) +{ + bool shift = event->state & GDK_SHIFT_MASK; + bool ctrl = event->state & GDK_CONTROL_MASK; + bool alt = event->state & GDK_MOD1_MASK; + struct nsgtk_treeview *tw = (struct nsgtk_treeview *) g; + struct tree *tree = tw->tree; + + + /* Handle modifiers being removed */ + if (tw->mouse_state & BROWSER_MOUSE_MOD_1 && !shift) + tw->mouse_state ^= BROWSER_MOUSE_MOD_1; + if (tw->mouse_state & BROWSER_MOUSE_MOD_2 && !ctrl) + tw->mouse_state ^= BROWSER_MOUSE_MOD_2; + if (tw->mouse_state & BROWSER_MOUSE_MOD_3 && !alt) + tw->mouse_state ^= BROWSER_MOUSE_MOD_3; + + if (tw->mouse_state & BROWSER_MOUSE_PRESS_1) { + /* Start button 1 drag */ + tree_mouse_action(tree, BROWSER_MOUSE_DRAG_1, + tw->mouse_pressed_x, tw->mouse_pressed_y); + /* Replace PRESS with HOLDING and declare drag in progress */ + tw->mouse_state ^= (BROWSER_MOUSE_PRESS_1 | + BROWSER_MOUSE_HOLDING_1); + tw->mouse_state |= BROWSER_MOUSE_DRAG_ON; + return TRUE; + } + else if (tw->mouse_state & BROWSER_MOUSE_PRESS_2){ + /* Start button 2s drag */ + tree_mouse_action(tree, BROWSER_MOUSE_DRAG_2, + tw->mouse_pressed_x, tw->mouse_pressed_y); + /* Replace PRESS with HOLDING and declare drag in progress */ + tw->mouse_state ^= (BROWSER_MOUSE_PRESS_2 | + BROWSER_MOUSE_HOLDING_2); + tw->mouse_state |= BROWSER_MOUSE_DRAG_ON; + return TRUE; + } + + if (tw->mouse_state & (BROWSER_MOUSE_HOLDING_1 | + BROWSER_MOUSE_HOLDING_2)) + tree_mouse_action(tree, tw->mouse_state, event->x, + event->y); + + return TRUE; +} + + +gboolean nsgtk_tree_window_keypress_event(GtkWidget *widget, GdkEventKey *event, + gpointer g) +{ + struct nsgtk_treeview *tw = (struct nsgtk_treeview *) g; + struct tree *tree = tw->tree; + uint32_t nskey; + double value; + GtkAdjustment *vscroll; + GtkAdjustment *hscroll; + GtkAdjustment *scroll = NULL; + gdouble hpage, vpage; + bool edited; + + nskey = gtk_gui_gdkkey_to_nskey(event); + + + vscroll = gtk_scrolled_window_get_vadjustment(tw->scrolled); + hscroll = gtk_scrolled_window_get_hadjustment(tw->scrolled); + g_object_get(vscroll, "page-size", &vpage, NULL); + g_object_get(hscroll, "page-size", &hpage, NULL); + + + edited = tree_is_edited(tree); + + switch (event->keyval) { + case GDK_Home: + case GDK_KP_Home: + if (edited) + break; + scroll = vscroll; + value = scroll->lower; + break; + + case GDK_End: + case GDK_KP_End: + if (edited) + break; + scroll = vscroll; + value = scroll->upper - vpage; + if (value < scroll->lower) + value = scroll->lower; + break; + + case GDK_Left: + case GDK_KP_Left: + if (edited) + break; + scroll = hscroll; + value = gtk_adjustment_get_value(scroll) - + scroll->step_increment; + if (value < scroll->lower) + value = scroll->lower; + break; + + case GDK_Up: + case GDK_KP_Up: + scroll = vscroll; + value = gtk_adjustment_get_value(scroll) - + scroll->step_increment; + if (value < scroll->lower) + value = scroll->lower; + break; + + case GDK_Right: + case GDK_KP_Right: + if (edited) + break; + scroll = hscroll; + value = gtk_adjustment_get_value(scroll) + + scroll->step_increment; + if (value > scroll->upper - hpage) + value = scroll->upper - hpage; + break; + + case GDK_Down: + case GDK_KP_Down: + scroll = vscroll; + value = gtk_adjustment_get_value(scroll) + + scroll->step_increment; + if (value > scroll->upper - vpage) + value = scroll->upper - vpage; + break; + + case GDK_Page_Up: + case GDK_KP_Page_Up: + scroll = vscroll; + value = gtk_adjustment_get_value(scroll) - + scroll->page_increment; + if (value < scroll->lower) + value = scroll->lower; + break; + + case GDK_Page_Down: + case GDK_KP_Page_Down: + scroll = vscroll; + value = gtk_adjustment_get_value(scroll) + + scroll->page_increment; + if (value > scroll->upper - vpage) + value = scroll->upper - vpage; + break; + default: + tree_keypress(tree, nskey); + return TRUE; + } + + if (scroll != NULL) + gtk_adjustment_set_value(scroll, value); + + tree_keypress(tree, nskey); + + return TRUE; +} diff --git a/gtk/gtk_treeview.h b/gtk/gtk_treeview.h new file mode 100644 index 000000000..655f8223d --- /dev/null +++ b/gtk/gtk_treeview.h @@ -0,0 +1,50 @@ +/* + * Copyright 2004 Richard Wilson + * Copyright 2009 Paul Blokus + * + * 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 . + */ + +/** \file + * Generic tree handling. + */ + +#ifndef __NSGTK_TREEVIEW_H__ +#define __NSGTK_TREEVIEW_H__ + +#include "desktop/browser.h" + +struct nsgtk_treeview; + +struct nsgtk_treeview *nsgtk_treeview_create(unsigned int flags, + GtkWindow *window, GtkScrolledWindow *scrolled, + GtkDrawingArea *drawing_area); +void nsgtk_treeview_destroy(struct nsgtk_treeview *tv); + +struct tree *nsgtk_treeview_get_tree(struct nsgtk_treeview *tv); + +gboolean nsgtk_tree_window_expose_event(GtkWidget *, GdkEventExpose *, + gpointer g); +void nsgtk_tree_window_hide(GtkWidget *widget, gpointer g); +gboolean nsgtk_tree_window_button_press_event(GtkWidget *widget, + GdkEventButton *event, gpointer g); +gboolean nsgtk_tree_window_button_release_event(GtkWidget *widget, + GdkEventButton *event, gpointer g); +gboolean nsgtk_tree_window_motion_notify_event(GtkWidget *widget, + GdkEventButton *event, gpointer g); +gboolean nsgtk_tree_window_keypress_event(GtkWidget *widget, GdkEventKey *event, + gpointer g); + +#endif /*__NSGTK_TREEVIEW_H__*/ diff --git a/gtk/gtk_window.c b/gtk/gtk_window.c index 509976519..68e636b82 100644 --- a/gtk/gtk_window.c +++ b/gtk/gtk_window.c @@ -606,7 +606,7 @@ gboolean nsgtk_window_scroll_event(GtkWidget *widget, } gboolean nsgtk_window_keypress_event(GtkWidget *widget, GdkEventKey *event, - gpointer data) + gpointer data) { struct gui_window *g = data; uint32_t nskey = gtk_gui_gdkkey_to_nskey(event); diff --git a/gtk/options.h b/gtk/options.h index cb6f0bde2..ac14259d8 100644 --- a/gtk/options.h +++ b/gtk/options.h @@ -34,6 +34,7 @@ extern int option_history_age; extern bool option_hover_urls; extern bool option_focus_new; extern bool option_new_blank; +extern char *option_hotlist_path; extern bool option_source_tab; extern int option_current_theme; @@ -51,6 +52,7 @@ int option_history_age = 0; \ bool option_hover_urls = false; \ bool option_focus_new = false; \ bool option_new_blank = false; \ +char *option_hotlist_path = NULL; \ bool option_source_tab = false;\ int option_current_theme = 0; @@ -68,6 +70,7 @@ int option_current_theme = 0; { "hover_urls", OPTION_BOOL, &option_hover_urls}, \ { "focus_new", OPTION_BOOL, &option_focus_new}, \ { "new_blank", OPTION_BOOL, &option_new_blank}, \ +{ "hotlist_path", OPTION_STRING, &option_hotlist_path}, \ { "source_tab", OPTION_BOOL, &option_source_tab},\ { "current_theme", OPTION_INTEGER, &option_current_theme} diff --git a/gtk/res/cookies.glade b/gtk/res/cookies.glade new file mode 100644 index 000000000..2bb92f372 --- /dev/null +++ b/gtk/res/cookies.glade @@ -0,0 +1,174 @@ + + + + + + NetSurf Cookies + GTK_WIN_POS_CENTER + 600 + 500 + GDK_WINDOW_TYPE_HINT_UTILITY + + + True + 2 + 2 + + + True + + + True + _Edit + True + + + True + + + True + Deletes selected nodes + _Delete + True + + + + + + True + D_elete all + True + + + + + True + _Select all + True + + + + + + True + _Clear selection + True + + + + + + + + + + True + _View + True + + + True + + + True + _Expand + True + + + True + + + True + _All + True + + + + + True + _Domains + True + + + + + True + _Cookies + True + + + + + + + + + True + Collapse + True + + + True + + + True + _All + True + + + + + True + _Domains + True + + + + + True + _Cookies + True + + + + + + + + + + + + + False + + + + + True + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + + + True + GTK_RESIZE_QUEUE + + + True + True + True + GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_STRUCTURE_MASK + + + + + + + 1 + + + + + + diff --git a/gtk/res/history.glade b/gtk/res/history.glade index e44edecd5..5c6e06424 100644 --- a/gtk/res/history.glade +++ b/gtk/res/history.glade @@ -8,306 +8,190 @@ 600 500 utility - True 2 2 - + True - True - 234 - + True - 2 + _File + True - + True - 2 - - - True - Sort by - - - False - False - 1 - 0 - - - + True - Name -Last Visited -Number of Visits - - - 1 - - - - - False - False - 0 - - - - - True - True - 1 - automatic - automatic - in - - - True - True - True + _Export + True + - - 1 - - - False - True - - + True - 2 + _Edit + True - + True - + True - <b>_Search for</b> - True + Deletes selected nodes + _Delete True + - - False - False - 1 - 0 - - + True - True - out + D_elete all + True - - 1 - - + True - False - True - none - False - 0 - 0 - - - True - Clear the search entry - gtk-clear - 1 - - + _Select all + True + + + + + + True + _Clear selection + True + - - False - False - 2 - - - False - False - 0 - + + + + + True + _View + True - + True - True - 1 - automatic - automatic - in - + True - True - True - False + _Expand + True + + + True + + + True + _All + True + + + + + True + _Directories + True + + + + + True + Add_resses + True + + + + + + + + + True + _Collapse + True + + + True + + + True + _All + True + + + + + True + _Directories + True + + + + + True + Add_resses + True + + + + - - 1 - - - False - True - + + + + True + Launches the selected addresses + _Launch + True + - 0 + False - + True - 5 + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC - + True - 1 - 3 - 2 - 5 - 5 - - - True - 0 - http://netsurf.sf.net/ - middle - - - 1 - 2 - - - - - - True - 0 - Fri Aug 09, 2006 - end - - - 1 - 2 - 1 - 2 - - - - - - True - 0 - 2 - end - - - 1 - 2 - 2 - 3 - - - + GTK_RESIZE_QUEUE - + True - 1 - Number of visits - - - 2 - 3 - GTK_FILL - GTK_EXPAND - - - - - True - 1 - Last visited - - - 1 - 2 - GTK_FILL - GTK_EXPAND - - - - - True - 1 - Address - - - GTK_FILL - GTK_EXPAND - - - - - 0 - - - - - 1 - 1 - in - - - 100 - 86 - True - gtk-file - 6 + True + True + GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_STRUCTURE_MASK - - - - label_item - - - - False - False - 1 - 1 - - - False - False - 1 - diff --git a/gtk/res/hotlist.glade b/gtk/res/hotlist.glade new file mode 100644 index 000000000..5a3b8f1d0 --- /dev/null +++ b/gtk/res/hotlist.glade @@ -0,0 +1,218 @@ + + + + + + NetSurf Hotlist + GTK_WIN_POS_CENTER + 600 + 500 + GDK_WINDOW_TYPE_HINT_UTILITY + + + True + 2 + 2 + + + True + + + True + _File + True + + + True + + + True + _Export + True + + + + + + True + New _folder + True + + + + + + True + New _entry + True + + + + + + + + + + True + _Edit + True + + + True + + + True + _Edit + True + + + + + True + Deletes selected nodes + _Delete + True + + + + + + True + _Select all + True + + + + + + True + _Clear selection + True + + + + + + + + + + True + _View + True + + + True + + + True + _Expand + True + + + True + + + True + _All + True + + + + + True + _Directories + True + + + + + True + Add_resses + True + + + + + + + + + True + _Collapse + True + + + True + + + True + _All + True + + + + + True + _Directories + True + + + + + True + Add_resses + True + + + + + + + + + + + + + True + Launches the selected addresses + _Launch + True + + + + + False + + + + + True + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + + + True + GTK_RESIZE_QUEUE + + + True + True + True + GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_STRUCTURE_MASK + + + + + + + 1 + + + + + + diff --git a/gtk/res/icons b/gtk/res/icons new file mode 120000 index 000000000..509ccd1d2 --- /dev/null +++ b/gtk/res/icons @@ -0,0 +1 @@ +../../!NetSurf/Resources/Icons/ \ No newline at end of file diff --git a/gtk/res/ssl.glade b/gtk/res/ssl.glade index 98d9f9bf3..5d0570987 100644 --- a/gtk/res/ssl.glade +++ b/gtk/res/ssl.glade @@ -6,6 +6,8 @@ 1 SSL certificate problem True + 500 + 250 GDK_WINDOW_TYPE_HINT_DIALOG @@ -50,17 +52,22 @@ True 12 - + True True GTK_SHADOW_IN - - 200 + True - True - False - (not implemented) + GTK_RESIZE_QUEUE + + + True + True + True + GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_STRUCTURE_MASK + + -- cgit v1.2.3