Implement the bookmarks panel with editing capabilities.
The bookmarks panel can display a tree of bookmarks and allows editing and deleting of bookmarks via a context menu. The XBEL implementation has been altered to work with a reference count model to allow panels to update on their own.
This commit is contained in:
parent
cd8b1e5b22
commit
b6f248f344
7 changed files with 384 additions and 41 deletions
286
src/browser.c
286
src/browser.c
|
@ -414,8 +414,7 @@ void on_menu_tabsClosed_item_activate(GtkWidget* menuitem, CBrowser* browser)
|
||||||
const gchar* uri = xbel_bookmark_get_href(item);
|
const gchar* uri = xbel_bookmark_get_href(item);
|
||||||
CBrowser* curBrowser = browser_new(browser);
|
CBrowser* curBrowser = browser_new(browser);
|
||||||
webView_open(curBrowser->webView, uri);
|
webView_open(curBrowser->webView, uri);
|
||||||
xbel_folder_remove_item(tabtrash, item);
|
xbel_item_unref(item);
|
||||||
xbel_item_free(item);
|
|
||||||
update_browser_actions(curBrowser);
|
update_browser_actions(curBrowser);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -426,15 +425,14 @@ void on_action_tabsClosed_undo_activate(GtkAction* action, CBrowser* browser)
|
||||||
const gchar* uri = xbel_bookmark_get_href(item);
|
const gchar* uri = xbel_bookmark_get_href(item);
|
||||||
CBrowser* curBrowser = browser_new(browser);
|
CBrowser* curBrowser = browser_new(browser);
|
||||||
webView_open(curBrowser->webView, uri);
|
webView_open(curBrowser->webView, uri);
|
||||||
xbel_folder_remove_item(tabtrash, item);
|
xbel_item_unref(item);
|
||||||
xbel_item_free(item);
|
|
||||||
update_browser_actions(curBrowser);
|
update_browser_actions(curBrowser);
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_action_tabsClosed_clear_activate(GtkAction* action, CBrowser* browser)
|
void on_action_tabsClosed_clear_activate(GtkAction* action, CBrowser* browser)
|
||||||
{
|
{
|
||||||
// Clear the closed tabs list
|
// Clear the closed tabs list
|
||||||
xbel_item_free(tabtrash);
|
xbel_item_unref(tabtrash);
|
||||||
tabtrash = xbel_folder_new();
|
tabtrash = xbel_folder_new();
|
||||||
update_browser_actions(browser);
|
update_browser_actions(browser);
|
||||||
}
|
}
|
||||||
|
@ -494,7 +492,10 @@ static void browser_editBookmark_dialog_new(XbelItem* bookmark, CBrowser* browse
|
||||||
GtkWidget* entry_title = gtk_entry_new();
|
GtkWidget* entry_title = gtk_entry_new();
|
||||||
gtk_entry_set_activates_default(GTK_ENTRY(entry_title), TRUE);
|
gtk_entry_set_activates_default(GTK_ENTRY(entry_title), TRUE);
|
||||||
if(!newBookmark)
|
if(!newBookmark)
|
||||||
gtk_entry_set_text(GTK_ENTRY(entry_title), xbel_item_get_title(bookmark));
|
{
|
||||||
|
const gchar* title = xbel_item_get_title(bookmark);
|
||||||
|
gtk_entry_set_text(GTK_ENTRY(entry_title), title ? title : "");
|
||||||
|
}
|
||||||
gtk_box_pack_start(GTK_BOX(hbox), entry_title, TRUE, TRUE, 0);
|
gtk_box_pack_start(GTK_BOX(hbox), entry_title, TRUE, TRUE, 0);
|
||||||
gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox);
|
gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox);
|
||||||
gtk_widget_show_all(hbox);
|
gtk_widget_show_all(hbox);
|
||||||
|
@ -507,29 +508,37 @@ static void browser_editBookmark_dialog_new(XbelItem* bookmark, CBrowser* browse
|
||||||
GtkWidget* entry_desc = gtk_entry_new();
|
GtkWidget* entry_desc = gtk_entry_new();
|
||||||
gtk_entry_set_activates_default(GTK_ENTRY(entry_desc), TRUE);
|
gtk_entry_set_activates_default(GTK_ENTRY(entry_desc), TRUE);
|
||||||
if(!newBookmark)
|
if(!newBookmark)
|
||||||
gtk_entry_set_text(GTK_ENTRY(entry_desc), xbel_item_get_desc(bookmark));
|
{
|
||||||
|
const gchar* desc = xbel_item_get_desc(bookmark);
|
||||||
|
gtk_entry_set_text(GTK_ENTRY(entry_desc), desc ? desc : "");
|
||||||
|
}
|
||||||
gtk_box_pack_start(GTK_BOX(hbox), entry_desc, TRUE, TRUE, 0);
|
gtk_box_pack_start(GTK_BOX(hbox), entry_desc, TRUE, TRUE, 0);
|
||||||
gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox);
|
gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox);
|
||||||
gtk_widget_show_all(hbox);
|
gtk_widget_show_all(hbox);
|
||||||
|
|
||||||
|
GtkWidget* entry_uri = NULL;
|
||||||
|
if(xbel_item_is_bookmark(bookmark))
|
||||||
|
{
|
||||||
hbox = gtk_hbox_new(FALSE, 8);
|
hbox = gtk_hbox_new(FALSE, 8);
|
||||||
gtk_container_set_border_width(GTK_CONTAINER(hbox), 5);
|
gtk_container_set_border_width(GTK_CONTAINER(hbox), 5);
|
||||||
label = gtk_label_new_with_mnemonic("_Uri:");
|
label = gtk_label_new_with_mnemonic("_Uri:");
|
||||||
gtk_size_group_add_widget(sizegroup, label);
|
gtk_size_group_add_widget(sizegroup, label);
|
||||||
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
|
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
|
||||||
GtkWidget* entry_uri = gtk_entry_new();
|
entry_uri = gtk_entry_new();
|
||||||
gtk_entry_set_activates_default(GTK_ENTRY(entry_uri), TRUE);
|
gtk_entry_set_activates_default(GTK_ENTRY(entry_uri), TRUE);
|
||||||
if(!newBookmark)
|
if(!newBookmark)
|
||||||
gtk_entry_set_text(GTK_ENTRY(entry_uri), xbel_bookmark_get_href(bookmark));
|
gtk_entry_set_text(GTK_ENTRY(entry_uri), xbel_bookmark_get_href(bookmark));
|
||||||
gtk_box_pack_start(GTK_BOX(hbox), entry_uri, TRUE, TRUE, 0);
|
gtk_box_pack_start(GTK_BOX(hbox), entry_uri, TRUE, TRUE, 0);
|
||||||
gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox);
|
gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox);
|
||||||
gtk_widget_show_all(hbox);
|
gtk_widget_show_all(hbox);
|
||||||
|
}
|
||||||
|
|
||||||
gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT);
|
gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT);
|
||||||
if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
|
if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
|
||||||
{
|
{
|
||||||
xbel_item_set_title(bookmark, gtk_entry_get_text(GTK_ENTRY(entry_title)));
|
xbel_item_set_title(bookmark, gtk_entry_get_text(GTK_ENTRY(entry_title)));
|
||||||
xbel_item_set_desc(bookmark, gtk_entry_get_text(GTK_ENTRY(entry_desc)));
|
xbel_item_set_desc(bookmark, gtk_entry_get_text(GTK_ENTRY(entry_desc)));
|
||||||
|
if(xbel_item_is_bookmark(bookmark))
|
||||||
xbel_bookmark_set_href(bookmark, gtk_entry_get_text(GTK_ENTRY(entry_uri)));
|
xbel_bookmark_set_href(bookmark, gtk_entry_get_text(GTK_ENTRY(entry_uri)));
|
||||||
|
|
||||||
// FIXME: We want to choose a folder
|
// FIXME: We want to choose a folder
|
||||||
|
@ -539,6 +548,230 @@ static void browser_editBookmark_dialog_new(XbelItem* bookmark, CBrowser* browse
|
||||||
gtk_widget_destroy(dialog);
|
gtk_widget_destroy(dialog);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void on_panel_bookmarks_row_activated(GtkTreeView* treeview
|
||||||
|
, GtkTreePath* path, GtkTreeViewColumn* column, CBrowser* browser)
|
||||||
|
{
|
||||||
|
GtkTreeModel* model = gtk_tree_view_get_model(treeview);
|
||||||
|
GtkTreeIter iter;
|
||||||
|
if(gtk_tree_model_get_iter(model, &iter, path))
|
||||||
|
{
|
||||||
|
XbelItem* item;
|
||||||
|
gtk_tree_model_get(model, &iter, 0, &item, -1);
|
||||||
|
if(xbel_item_is_bookmark(item))
|
||||||
|
webView_open(get_nth_webView(-1, browser), xbel_bookmark_get_href(item));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void panel_bookmarks_popup(GtkWidget* widget, GdkEventButton* event
|
||||||
|
, XbelItem* item, CBrowser* browser)
|
||||||
|
{
|
||||||
|
gboolean isBookmark = xbel_item_is_bookmark(item);
|
||||||
|
gboolean isSeparator = xbel_item_is_separator(item);
|
||||||
|
|
||||||
|
action_set_sensitive("BookmarkOpen", isBookmark, browser);
|
||||||
|
action_set_sensitive("BookmarkOpenTab", isBookmark, browser);
|
||||||
|
action_set_sensitive("BookmarkOpenWindow", isBookmark, browser);
|
||||||
|
|
||||||
|
action_set_sensitive("BookmarkEdit", !isSeparator, browser);
|
||||||
|
|
||||||
|
sokoke_widget_popup(widget, GTK_MENU(browser->popup_bookmark), event);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean on_panel_bookmarks_button_release(GtkWidget* widget
|
||||||
|
, GdkEventButton* event, CBrowser* browser)
|
||||||
|
{
|
||||||
|
if(event->button != 2 && event->button != 3)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget));
|
||||||
|
if(selection)
|
||||||
|
{
|
||||||
|
GtkTreeModel* model;
|
||||||
|
GtkTreeIter iter;
|
||||||
|
gtk_tree_selection_get_selected(selection, &model, &iter);
|
||||||
|
XbelItem* item;
|
||||||
|
gtk_tree_model_get(model, &iter, 0, &item, -1);
|
||||||
|
if(event->button == 2 && xbel_item_is_bookmark(item))
|
||||||
|
{
|
||||||
|
CBrowser* newBrowser = browser_new(browser);
|
||||||
|
const gchar* uri = xbel_bookmark_get_href(item);
|
||||||
|
webView_open(newBrowser->webView, uri);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
panel_bookmarks_popup(widget, event, item, browser);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_panel_bookmarks_popup(GtkWidget* widget, CBrowser* browser)
|
||||||
|
{
|
||||||
|
GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget));
|
||||||
|
if(selection)
|
||||||
|
{
|
||||||
|
GtkTreeModel* model;
|
||||||
|
GtkTreeIter iter;
|
||||||
|
gtk_tree_selection_get_selected(selection, &model, &iter);
|
||||||
|
XbelItem* item;
|
||||||
|
gtk_tree_model_get(model, &iter, 0, &item, -1);
|
||||||
|
panel_bookmarks_popup(widget, NULL, item, browser);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_action_bookmarkOpen_activate(GtkAction* action, CBrowser* browser)
|
||||||
|
{
|
||||||
|
GtkTreeView* treeview = GTK_TREE_VIEW(browser->panel_bookmarks);
|
||||||
|
GtkTreeSelection* selection = gtk_tree_view_get_selection(treeview);
|
||||||
|
if(selection)
|
||||||
|
{
|
||||||
|
GtkTreeModel* model;
|
||||||
|
GtkTreeIter iter;
|
||||||
|
gtk_tree_selection_get_selected(selection, &model, &iter);
|
||||||
|
XbelItem* item;
|
||||||
|
gtk_tree_model_get(model, &iter, 0, &item, -1);
|
||||||
|
if(xbel_item_is_bookmark(item))
|
||||||
|
webView_open(get_nth_webView(-1, browser), xbel_bookmark_get_href(item));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_action_bookmarkOpenTab_activate(GtkAction* action, CBrowser* browser)
|
||||||
|
{
|
||||||
|
GtkTreeView* treeview = GTK_TREE_VIEW(browser->panel_bookmarks);
|
||||||
|
GtkTreeSelection* selection = gtk_tree_view_get_selection(treeview);
|
||||||
|
if(selection)
|
||||||
|
{
|
||||||
|
GtkTreeModel* model;
|
||||||
|
GtkTreeIter iter;
|
||||||
|
gtk_tree_selection_get_selected(selection, &model, &iter);
|
||||||
|
XbelItem* item;
|
||||||
|
gtk_tree_model_get(model, &iter, 0, &item, -1);
|
||||||
|
if(xbel_item_is_bookmark(item))
|
||||||
|
{
|
||||||
|
CBrowser* newBrowser = browser_new(browser);
|
||||||
|
const gchar* uri = xbel_bookmark_get_href(item);
|
||||||
|
webView_open(newBrowser->webView, uri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_action_bookmarkOpenWindow_activate(GtkAction* action, CBrowser* browser)
|
||||||
|
{
|
||||||
|
GtkTreeView* treeview = GTK_TREE_VIEW(browser->panel_bookmarks);
|
||||||
|
GtkTreeSelection* selection = gtk_tree_view_get_selection(treeview);
|
||||||
|
if(selection)
|
||||||
|
{
|
||||||
|
GtkTreeModel* model;
|
||||||
|
GtkTreeIter iter;
|
||||||
|
gtk_tree_selection_get_selected(selection, &model, &iter);
|
||||||
|
XbelItem* item;
|
||||||
|
gtk_tree_model_get(model, &iter, 0, &item, -1);
|
||||||
|
if(xbel_item_is_bookmark(item))
|
||||||
|
{
|
||||||
|
CBrowser* newBrowser = browser_new(NULL);
|
||||||
|
const gchar* uri = xbel_bookmark_get_href(item);
|
||||||
|
webView_open(newBrowser->webView, uri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_action_bookmarkEdit_activate(GtkAction* action, CBrowser* browser)
|
||||||
|
{
|
||||||
|
GtkTreeView* treeview = GTK_TREE_VIEW(browser->panel_bookmarks);
|
||||||
|
GtkTreeSelection* selection = gtk_tree_view_get_selection(treeview);
|
||||||
|
if(selection)
|
||||||
|
{
|
||||||
|
GtkTreeModel* model;
|
||||||
|
GtkTreeIter iter;
|
||||||
|
gtk_tree_selection_get_selected(selection, &model, &iter);
|
||||||
|
XbelItem* item;
|
||||||
|
gtk_tree_model_get(model, &iter, 0, &item, -1);
|
||||||
|
if(!xbel_item_is_separator(item))
|
||||||
|
browser_editBookmark_dialog_new(item, browser);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_action_bookmarkDelete_activate(GtkAction* action, CBrowser* browser)
|
||||||
|
{
|
||||||
|
GtkTreeView* treeview = GTK_TREE_VIEW(browser->panel_bookmarks);
|
||||||
|
GtkTreeSelection* selection = gtk_tree_view_get_selection(treeview);
|
||||||
|
if(selection)
|
||||||
|
{
|
||||||
|
GtkTreeModel* model;
|
||||||
|
GtkTreeIter iter;
|
||||||
|
gtk_tree_selection_get_selected(selection, &model, &iter);
|
||||||
|
XbelItem* item;
|
||||||
|
gtk_tree_model_get(model, &iter, 0, &item, -1);
|
||||||
|
XbelItem* parent = xbel_item_get_parent(item);
|
||||||
|
xbel_folder_remove_item(parent, item);
|
||||||
|
xbel_item_unref(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tree_store_insert_folder(GtkTreeStore* treestore, GtkTreeIter* parent
|
||||||
|
, XbelItem* folder)
|
||||||
|
{
|
||||||
|
guint n = xbel_folder_get_n_items(folder);
|
||||||
|
guint i;
|
||||||
|
for(i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
XbelItem* item = xbel_folder_get_nth_item(folder, i);
|
||||||
|
GtkTreeIter iter;
|
||||||
|
gtk_tree_store_insert_with_values(treestore, &iter, parent, n, 0, item, -1);
|
||||||
|
xbel_item_ref(item);
|
||||||
|
if(xbel_item_is_folder(item))
|
||||||
|
tree_store_insert_folder(treestore, &iter, item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_bookmarks_item_render_icon(GtkTreeViewColumn* column
|
||||||
|
, GtkCellRenderer* renderer, GtkTreeModel* model, GtkTreeIter* iter
|
||||||
|
, GtkWidget* treeview)
|
||||||
|
{
|
||||||
|
XbelItem* item;
|
||||||
|
gtk_tree_model_get(model, iter, 0, &item, -1);
|
||||||
|
|
||||||
|
if(!xbel_item_get_parent(item))
|
||||||
|
{
|
||||||
|
gtk_tree_store_remove(GTK_TREE_STORE(model), iter);
|
||||||
|
xbel_item_unref(item);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Would it be better to not do this on every redraw?
|
||||||
|
GdkPixbuf* pixbuf = NULL;
|
||||||
|
if(xbel_item_is_bookmark(item))
|
||||||
|
pixbuf = gtk_widget_render_icon(treeview, STOCK_BOOKMARK
|
||||||
|
, GTK_ICON_SIZE_MENU, NULL);
|
||||||
|
else if(xbel_item_is_folder(item))
|
||||||
|
pixbuf = gtk_widget_render_icon(treeview, GTK_STOCK_DIRECTORY
|
||||||
|
, GTK_ICON_SIZE_MENU, NULL);
|
||||||
|
g_object_set(renderer, "pixbuf", pixbuf, NULL);
|
||||||
|
if(pixbuf)
|
||||||
|
g_object_unref(pixbuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_bookmarks_item_render_text(GtkTreeViewColumn* column
|
||||||
|
, GtkCellRenderer* renderer, GtkTreeModel* model, GtkTreeIter* iter
|
||||||
|
, GtkWidget* treeview)
|
||||||
|
{
|
||||||
|
XbelItem* item;
|
||||||
|
gtk_tree_model_get(model, iter, 0, &item, -1);
|
||||||
|
|
||||||
|
if(!xbel_item_get_parent(item))
|
||||||
|
{
|
||||||
|
gtk_tree_store_remove(GTK_TREE_STORE(model), iter);
|
||||||
|
xbel_item_unref(item);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(xbel_item_is_separator(item))
|
||||||
|
g_object_set(renderer
|
||||||
|
, "markup", "<i>Separator</i>", NULL);
|
||||||
|
else
|
||||||
|
g_object_set(renderer
|
||||||
|
, "markup", NULL, "text", xbel_item_get_title(item), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static void create_bookmark_menu(XbelItem*, GtkWidget*, CBrowser*);
|
static void create_bookmark_menu(XbelItem*, GtkWidget*, CBrowser*);
|
||||||
|
|
||||||
static void on_bookmark_menu_folder_activate(GtkWidget* menuitem, CBrowser* browser)
|
static void on_bookmark_menu_folder_activate(GtkWidget* menuitem, CBrowser* browser)
|
||||||
|
@ -972,6 +1205,8 @@ CBrowser* browser_new(CBrowser* oldBrowser)
|
||||||
menuitem = gtk_separator_menu_item_new();
|
menuitem = gtk_separator_menu_item_new();
|
||||||
gtk_widget_show(menuitem);
|
gtk_widget_show(menuitem);
|
||||||
gtk_menu_shell_append(GTK_MENU_SHELL(browser->menu_bookmarks), menuitem);
|
gtk_menu_shell_append(GTK_MENU_SHELL(browser->menu_bookmarks), menuitem);
|
||||||
|
browser->popup_bookmark = gtk_ui_manager_get_widget(ui_manager, "/popup_bookmark");
|
||||||
|
g_object_ref(browser->popup_bookmark);
|
||||||
browser->menu_window = gtk_menu_item_get_submenu(
|
browser->menu_window = gtk_menu_item_get_submenu(
|
||||||
GTK_MENU_ITEM(gtk_ui_manager_get_widget(ui_manager, "/menubar/Window")));
|
GTK_MENU_ITEM(gtk_ui_manager_get_widget(ui_manager, "/menubar/Window")));
|
||||||
menuitem = gtk_separator_menu_item_new();
|
menuitem = gtk_separator_menu_item_new();
|
||||||
|
@ -1142,6 +1377,40 @@ CBrowser* browser_new(CBrowser* oldBrowser)
|
||||||
// Dummy: This is the "fallback" panel for now
|
// Dummy: This is the "fallback" panel for now
|
||||||
page = gtk_notebook_append_page(GTK_NOTEBOOK(browser->panels_notebook)
|
page = gtk_notebook_append_page(GTK_NOTEBOOK(browser->panels_notebook)
|
||||||
, gtk_label_new("empty"), NULL);
|
, gtk_label_new("empty"), NULL);
|
||||||
|
// Bookmarks
|
||||||
|
GtkTreeViewColumn* column;
|
||||||
|
GtkCellRenderer* renderer_text; GtkCellRenderer* renderer_pixbuf;
|
||||||
|
GtkTreeStore* treestore = gtk_tree_store_new(1, G_TYPE_XBEL_ITEM);
|
||||||
|
GtkWidget* treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(treestore));
|
||||||
|
gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(treeview), FALSE);
|
||||||
|
column = gtk_tree_view_column_new();
|
||||||
|
renderer_pixbuf = gtk_cell_renderer_pixbuf_new();
|
||||||
|
gtk_tree_view_column_pack_start(column, renderer_pixbuf, FALSE);
|
||||||
|
gtk_tree_view_column_set_cell_data_func(column, renderer_pixbuf
|
||||||
|
, (GtkTreeCellDataFunc)on_bookmarks_item_render_icon, treeview, NULL);
|
||||||
|
renderer_text = gtk_cell_renderer_text_new();
|
||||||
|
gtk_tree_view_column_pack_start(column, renderer_text, FALSE);
|
||||||
|
gtk_tree_view_column_set_cell_data_func(column, renderer_text
|
||||||
|
, (GtkTreeCellDataFunc)on_bookmarks_item_render_text, treeview, NULL);
|
||||||
|
gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
|
||||||
|
GtkWidget* scrolled = gtk_scrolled_window_new(NULL, NULL);
|
||||||
|
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled)
|
||||||
|
, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
|
||||||
|
gtk_container_add(GTK_CONTAINER(scrolled), treeview);
|
||||||
|
gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
|
||||||
|
tree_store_insert_folder(GTK_TREE_STORE(treestore), NULL, bookmarks);
|
||||||
|
g_object_unref(treestore);
|
||||||
|
g_signal_connect(treeview, "row-activated"
|
||||||
|
, G_CALLBACK(on_panel_bookmarks_row_activated), browser);
|
||||||
|
g_signal_connect(treeview, "button-release-event"
|
||||||
|
, G_CALLBACK(on_panel_bookmarks_button_release), browser);
|
||||||
|
g_signal_connect(treeview, "popup-menu"
|
||||||
|
, G_CALLBACK(on_panel_bookmarks_popup), browser);
|
||||||
|
browser->panel_bookmarks = treeview;
|
||||||
|
page = gtk_notebook_append_page(GTK_NOTEBOOK(browser->panels_notebook)
|
||||||
|
, scrolled, NULL);
|
||||||
|
action = gtk_action_group_get_action(browser->actiongroup, "PanelBookmarks");
|
||||||
|
g_object_set_data(G_OBJECT(action), "iPage", GINT_TO_POINTER(page));
|
||||||
// Pageholder
|
// Pageholder
|
||||||
browser->panel_pageholder = webView_new(&scrolled);
|
browser->panel_pageholder = webView_new(&scrolled);
|
||||||
page = gtk_notebook_append_page(GTK_NOTEBOOK(browser->panels_notebook)
|
page = gtk_notebook_append_page(GTK_NOTEBOOK(browser->panels_notebook)
|
||||||
|
@ -1242,6 +1511,7 @@ CBrowser* browser_new(CBrowser* oldBrowser)
|
||||||
browser->actiongroup = oldBrowser->actiongroup;
|
browser->actiongroup = oldBrowser->actiongroup;
|
||||||
browser->menubar = oldBrowser->menubar;
|
browser->menubar = oldBrowser->menubar;
|
||||||
browser->menu_bookmarks = oldBrowser->menu_bookmarks;
|
browser->menu_bookmarks = oldBrowser->menu_bookmarks;
|
||||||
|
browser->popup_bookmark = oldBrowser->popup_bookmark;
|
||||||
browser->menu_window = oldBrowser->menu_window;
|
browser->menu_window = oldBrowser->menu_window;
|
||||||
browser->popup_webView = oldBrowser->popup_webView;
|
browser->popup_webView = oldBrowser->popup_webView;
|
||||||
browser->popup_element = oldBrowser->popup_element;
|
browser->popup_element = oldBrowser->popup_element;
|
||||||
|
|
|
@ -26,6 +26,7 @@ typedef struct _CBrowser
|
||||||
// menus
|
// menus
|
||||||
GtkWidget* menubar;
|
GtkWidget* menubar;
|
||||||
GtkWidget* menu_bookmarks;
|
GtkWidget* menu_bookmarks;
|
||||||
|
GtkWidget* popup_bookmark;
|
||||||
GtkWidget* menu_window;
|
GtkWidget* menu_window;
|
||||||
GtkWidget* popup_webView;
|
GtkWidget* popup_webView;
|
||||||
GtkWidget* popup_element;
|
GtkWidget* popup_element;
|
||||||
|
@ -42,6 +43,7 @@ typedef struct _CBrowser
|
||||||
// panels
|
// panels
|
||||||
GtkWidget* panels;
|
GtkWidget* panels;
|
||||||
GtkWidget* panels_notebook;
|
GtkWidget* panels_notebook;
|
||||||
|
GtkWidget* panel_bookmarks;
|
||||||
GtkWidget* panel_pageholder;
|
GtkWidget* panel_pageholder;
|
||||||
GtkWidget* webViews;
|
GtkWidget* webViews;
|
||||||
// findbox
|
// findbox
|
||||||
|
@ -203,6 +205,21 @@ on_action_link_saveWith_activate(GtkAction*, CBrowser*);
|
||||||
void
|
void
|
||||||
on_action_link_copy_activate(GtkAction*, CBrowser*);
|
on_action_link_copy_activate(GtkAction*, CBrowser*);
|
||||||
|
|
||||||
|
void
|
||||||
|
on_action_bookmarkOpen_activate(GtkAction*, CBrowser*);
|
||||||
|
|
||||||
|
void
|
||||||
|
on_action_bookmarkOpenTab_activate(GtkAction*, CBrowser*);
|
||||||
|
|
||||||
|
void
|
||||||
|
on_action_bookmarkOpenWindow_activate(GtkAction*, CBrowser*);
|
||||||
|
|
||||||
|
void
|
||||||
|
on_action_bookmarkEdit_activate(GtkAction*, CBrowser*);
|
||||||
|
|
||||||
|
void
|
||||||
|
on_action_bookmarkDelete_activate(GtkAction*, CBrowser*);
|
||||||
|
|
||||||
void
|
void
|
||||||
on_menu_bookmarks_item_activate(GtkWidget*, CBrowser*);
|
on_menu_bookmarks_item_activate(GtkWidget*, CBrowser*);
|
||||||
|
|
||||||
|
@ -438,6 +455,21 @@ static const GtkActionEntry entries[] = {
|
||||||
{ "BookmarksManage", STOCK_BOOKMARKS
|
{ "BookmarksManage", STOCK_BOOKMARKS
|
||||||
, "_Manage Bookmarks", "<Ctrl>b"
|
, "_Manage Bookmarks", "<Ctrl>b"
|
||||||
, "hm?", NULL/*G_CALLBACK(on_action_bookmarks_manage_activate)*/ },
|
, "hm?", NULL/*G_CALLBACK(on_action_bookmarks_manage_activate)*/ },
|
||||||
|
{ "BookmarkOpen", GTK_STOCK_OPEN
|
||||||
|
, NULL, ""
|
||||||
|
, "hm?", G_CALLBACK(on_action_bookmarkOpen_activate) },
|
||||||
|
{ "BookmarkOpenTab", STOCK_TAB_NEW
|
||||||
|
, "Open in New _Tab", ""
|
||||||
|
, "hm?", G_CALLBACK(on_action_bookmarkOpenTab_activate) },
|
||||||
|
{ "BookmarkOpenWindow", STOCK_WINDOW_NEW
|
||||||
|
, "Open in New _Window", ""
|
||||||
|
, "hm?", G_CALLBACK(on_action_bookmarkOpenWindow_activate) },
|
||||||
|
{ "BookmarkEdit", GTK_STOCK_EDIT
|
||||||
|
, NULL, ""
|
||||||
|
, "hm?", G_CALLBACK(on_action_bookmarkEdit_activate) },
|
||||||
|
{ "BookmarkDelete", GTK_STOCK_DELETE
|
||||||
|
, NULL, ""
|
||||||
|
, "hm?", G_CALLBACK(on_action_bookmarkDelete_activate) },
|
||||||
|
|
||||||
{ "Tools", NULL, "_Tools" },
|
{ "Tools", NULL, "_Tools" },
|
||||||
|
|
||||||
|
|
12
src/main.c
12
src/main.c
|
@ -204,8 +204,8 @@ int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
config_free(config);
|
config_free(config);
|
||||||
search_engines_free(searchEngines);
|
search_engines_free(searchEngines);
|
||||||
xbel_item_free(bookmarks);
|
xbel_item_unref(bookmarks);
|
||||||
xbel_item_free(_session);
|
xbel_item_unref(_session);
|
||||||
g_string_free(errorMessages, TRUE);
|
g_string_free(errorMessages, TRUE);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -254,7 +254,7 @@ int main(int argc, char** argv)
|
||||||
browser = browser_new(browser);
|
browser = browser_new(browser);
|
||||||
webView_open(browser->webView, xbel_bookmark_get_href(item));
|
webView_open(browser->webView, xbel_bookmark_get_href(item));
|
||||||
}
|
}
|
||||||
xbel_item_free(_session);
|
xbel_item_unref(_session);
|
||||||
|
|
||||||
gtk_main();
|
gtk_main();
|
||||||
|
|
||||||
|
@ -277,7 +277,7 @@ int main(int argc, char** argv)
|
||||||
g_warning("Bookmarks couldn't be saved. %s", error->message);
|
g_warning("Bookmarks couldn't be saved. %s", error->message);
|
||||||
g_error_free(error);
|
g_error_free(error);
|
||||||
}
|
}
|
||||||
xbel_item_free(bookmarks);
|
xbel_item_unref(bookmarks);
|
||||||
g_free(configFile);
|
g_free(configFile);
|
||||||
configFile = g_build_filename(configPath, "tabtrash.xbel", NULL);
|
configFile = g_build_filename(configPath, "tabtrash.xbel", NULL);
|
||||||
error = NULL;
|
error = NULL;
|
||||||
|
@ -286,7 +286,7 @@ int main(int argc, char** argv)
|
||||||
g_warning("Tabtrash couldn't be saved. %s", error->message);
|
g_warning("Tabtrash couldn't be saved. %s", error->message);
|
||||||
g_error_free(error);
|
g_error_free(error);
|
||||||
}
|
}
|
||||||
xbel_item_free(tabtrash);
|
xbel_item_unref(tabtrash);
|
||||||
g_free(configFile);
|
g_free(configFile);
|
||||||
if(config->startup == CONFIG_STARTUP_SESSION)
|
if(config->startup == CONFIG_STARTUP_SESSION)
|
||||||
{
|
{
|
||||||
|
@ -299,7 +299,7 @@ int main(int argc, char** argv)
|
||||||
}
|
}
|
||||||
g_free(configFile);
|
g_free(configFile);
|
||||||
}
|
}
|
||||||
xbel_item_free(session);
|
xbel_item_unref(session);
|
||||||
configFile = g_build_filename(configPath, "config", NULL);
|
configFile = g_build_filename(configPath, "config", NULL);
|
||||||
error = NULL;
|
error = NULL;
|
||||||
if(!config_to_file(config, configFile, &error))
|
if(!config_to_file(config, configFile, &error))
|
||||||
|
|
8
src/ui.h
8
src/ui.h
|
@ -166,6 +166,14 @@ static const gchar* ui_markup =
|
||||||
"<toolitem action='PanelExtensions'/>"
|
"<toolitem action='PanelExtensions'/>"
|
||||||
"<toolitem action='PanelConsole'/>"
|
"<toolitem action='PanelConsole'/>"
|
||||||
"</toolbar>"
|
"</toolbar>"
|
||||||
|
"<popup name='popup_bookmark'>"
|
||||||
|
"<menuitem action='BookmarkOpen'/>"
|
||||||
|
"<menuitem action='BookmarkOpenTab'/>"
|
||||||
|
"<menuitem action='BookmarkOpenWindow'/>"
|
||||||
|
"<separator/>"
|
||||||
|
"<menuitem action='BookmarkEdit'/>"
|
||||||
|
"<menuitem action='BookmarkDelete'/>"
|
||||||
|
"</popup>"
|
||||||
"<popup name='popup_webView'>"
|
"<popup name='popup_webView'>"
|
||||||
"<menuitem action='Back'/>"
|
"<menuitem action='Back'/>"
|
||||||
"<menuitem action='Forward'/>"
|
"<menuitem action='Forward'/>"
|
||||||
|
|
|
@ -292,12 +292,18 @@ void on_webView_destroy(GtkWidget* widget, CBrowser* browser)
|
||||||
browsers = g_list_delete_link(browsers, tmp);
|
browsers = g_list_delete_link(browsers, tmp);
|
||||||
g_free(browser->elementUri);
|
g_free(browser->elementUri);
|
||||||
g_free(browser->statusMessage);
|
g_free(browser->statusMessage);
|
||||||
if(!g_list_length(browsers))
|
// FIXME: Multiple windows are not taken into account
|
||||||
|
if(!g_list_nth(browsers, 0))
|
||||||
{
|
{
|
||||||
g_object_unref(browser->actiongroup);
|
g_object_unref(browser->actiongroup);
|
||||||
|
g_object_unref(browser->popup_bookmark);
|
||||||
g_object_unref(browser->popup_webView);
|
g_object_unref(browser->popup_webView);
|
||||||
g_object_unref(browser->popup_element);
|
g_object_unref(browser->popup_element);
|
||||||
g_object_unref(browser->popup_editable);
|
g_object_unref(browser->popup_editable);
|
||||||
|
guint i;
|
||||||
|
guint n = xbel_folder_get_n_items(bookmarks);
|
||||||
|
for(i = 0; i < n; i++)
|
||||||
|
xbel_item_unref(xbel_folder_get_nth_item(bookmarks, i));
|
||||||
gtk_main_quit();
|
gtk_main_quit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -340,12 +346,11 @@ void webView_close(GtkWidget* webView, CBrowser* browser)
|
||||||
if(n > 10)
|
if(n > 10)
|
||||||
{
|
{
|
||||||
XbelItem* item = xbel_folder_get_nth_item(tabtrash, n - 1);
|
XbelItem* item = xbel_folder_get_nth_item(tabtrash, n - 1);
|
||||||
xbel_folder_remove_item(tabtrash, item);
|
xbel_item_unref(item);
|
||||||
xbel_item_free(item);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
xbel_item_free(browser->sessionItem);
|
xbel_item_unref(browser->sessionItem);
|
||||||
gtk_widget_destroy(browser->webView_menu);
|
gtk_widget_destroy(browser->webView_menu);
|
||||||
gtk_notebook_remove_page(GTK_NOTEBOOK(browser->webViews)
|
gtk_notebook_remove_page(GTK_NOTEBOOK(browser->webViews)
|
||||||
, get_webView_index(webView, browser));
|
, get_webView_index(webView, browser));
|
||||||
|
|
40
src/xbel.c
40
src/xbel.c
|
@ -38,6 +38,7 @@
|
||||||
static XbelItem* xbel_item_new(XbelItemKind kind)
|
static XbelItem* xbel_item_new(XbelItemKind kind)
|
||||||
{
|
{
|
||||||
XbelItem* item = g_new(XbelItem, 1);
|
XbelItem* item = g_new(XbelItem, 1);
|
||||||
|
item->refs = 1;
|
||||||
item->parent = NULL;
|
item->parent = NULL;
|
||||||
item->kind = kind;
|
item->kind = kind;
|
||||||
if(kind == XBEL_ITEM_FOLDER)
|
if(kind == XBEL_ITEM_FOLDER)
|
||||||
|
@ -220,18 +221,41 @@ static gboolean xbel_folder_from_xmlDocPtr(XbelItem* folder, xmlDocPtr doc)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xbel_item_free:
|
* xbel_item_ref:
|
||||||
* @item: a valid item
|
* @item: a valid item
|
||||||
*
|
*
|
||||||
* Free an XbelItem. If @item is a folder all of its children will also
|
* Ref an XbelItem.
|
||||||
* be freed automatically.
|
|
||||||
*
|
*
|
||||||
* The item must not be contained in a folder or attempting to free it will fail.
|
* Ref means that the reference count is increased by one.
|
||||||
|
*
|
||||||
|
* This has no effect on children of a folder.
|
||||||
**/
|
**/
|
||||||
void xbel_item_free(XbelItem* item)
|
void xbel_item_ref(XbelItem* item)
|
||||||
{
|
{
|
||||||
g_return_if_fail(item);
|
g_return_if_fail(item);
|
||||||
g_return_if_fail(!xbel_item_get_parent(item));
|
item->refs++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xbel_item_unref:
|
||||||
|
* @item: a valid item
|
||||||
|
*
|
||||||
|
* Unref an XbelItem. If @item is a folder all of its children will also
|
||||||
|
* be unreffed automatically.
|
||||||
|
*
|
||||||
|
* Unref means that the reference count is decreased. If there are no
|
||||||
|
* references left, the memory will be freed and if needed removed from
|
||||||
|
* its containing folder.
|
||||||
|
**/
|
||||||
|
void xbel_item_unref(XbelItem* item)
|
||||||
|
{
|
||||||
|
g_return_if_fail(item);
|
||||||
|
item->refs--;
|
||||||
|
if(item->refs)
|
||||||
|
return;
|
||||||
|
XbelItem* parent = xbel_item_get_parent(item);
|
||||||
|
if(parent)
|
||||||
|
xbel_folder_remove_item(parent, item);
|
||||||
if(xbel_item_is_folder(item))
|
if(xbel_item_is_folder(item))
|
||||||
{
|
{
|
||||||
guint n = xbel_folder_get_n_items(item);
|
guint n = xbel_folder_get_n_items(item);
|
||||||
|
@ -240,7 +264,7 @@ void xbel_item_free(XbelItem* item)
|
||||||
{
|
{
|
||||||
XbelItem* _item = xbel_folder_get_nth_item(item, i);
|
XbelItem* _item = xbel_folder_get_nth_item(item, i);
|
||||||
_item->parent = NULL;
|
_item->parent = NULL;
|
||||||
xbel_item_free(_item);
|
xbel_item_unref(_item);
|
||||||
}
|
}
|
||||||
g_list_free(item->items);
|
g_list_free(item->items);
|
||||||
}
|
}
|
||||||
|
@ -260,7 +284,7 @@ void xbel_item_free(XbelItem* item)
|
||||||
*
|
*
|
||||||
* Copy an XbelItem.
|
* Copy an XbelItem.
|
||||||
*
|
*
|
||||||
* The returned item must be freed eventually.
|
* The returned item must be unreffed eventually.
|
||||||
*
|
*
|
||||||
* Return value: a copy of @item
|
* Return value: a copy of @item
|
||||||
**/
|
**/
|
||||||
|
|
|
@ -37,6 +37,7 @@ typedef enum
|
||||||
// Note: This structure is entirely private.
|
// Note: This structure is entirely private.
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
guint refs;
|
||||||
XbelItemKind kind;
|
XbelItemKind kind;
|
||||||
struct XbelItem* parent;
|
struct XbelItem* parent;
|
||||||
|
|
||||||
|
@ -60,7 +61,10 @@ XbelItem*
|
||||||
xbel_folder_new(void);
|
xbel_folder_new(void);
|
||||||
|
|
||||||
void
|
void
|
||||||
xbel_item_free(XbelItem*);
|
xbel_item_ref(XbelItem*);
|
||||||
|
|
||||||
|
void
|
||||||
|
xbel_item_unref(XbelItem*);
|
||||||
|
|
||||||
XbelItem*
|
XbelItem*
|
||||||
xbel_item_copy(XbelItem*);
|
xbel_item_copy(XbelItem*);
|
||||||
|
|
Loading…
Reference in a new issue