/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* Pix
*
* Copyright (C) 2001-2008 The Free Software Foundation, Inc.
*
* This program 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; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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
#include
#include
#include "dlg-bookmarks.h"
typedef struct {
GthBrowser *browser;
GtkBuilder *builder;
GtkWidget *dialog;
GtkWidget *uri_list;
char *last_selected_uri;
gulong bookmarks_changed_id;
gboolean entry_changed;
} DialogData;
static void
entry_activate_cb (GtkEntry *entry,
DialogData *data);
static void
set_bookmark_data (DialogData *data,
const char *name,
const char *location)
{
g_signal_handlers_block_by_func (_gtk_builder_get_widget (data->builder, "entry_name"), entry_activate_cb, data);
g_signal_handlers_block_by_func (_gtk_builder_get_widget (data->builder, "entry_location"), entry_activate_cb, data);
gtk_entry_set_text (GTK_ENTRY (_gtk_builder_get_widget (data->builder, "entry_name")), name);
gtk_entry_set_text (GTK_ENTRY (_gtk_builder_get_widget (data->builder, "entry_location")), location);
g_signal_handlers_unblock_by_func (_gtk_builder_get_widget (data->builder, "entry_location"), entry_activate_cb, data);
g_signal_handlers_unblock_by_func (_gtk_builder_get_widget (data->builder, "entry_name"), entry_activate_cb, data);
data->entry_changed = FALSE;
}
static void
update_dialog_from_bookmark_file (DialogData *data,
const char *uri)
{
GBookmarkFile *bookmarks;
GFile *file;
char *location;
char *name;
bookmarks = gth_main_get_default_bookmarks ();
file = g_file_new_for_uri (uri);
location = g_file_get_parse_name (file);
name = g_bookmark_file_get_title (bookmarks, uri, NULL);
if (name == NULL)
name = g_file_get_basename (file);
set_bookmark_data (data, name, location);
g_free (name);
g_free (location);
g_object_unref (file);
}
static void
update_current_entry (DialogData *data,
gboolean *update_selected_uri)
{
const char *name;
const char *location;
GFile *file;
char *uri;
GBookmarkFile *bookmarks;
if (update_selected_uri != NULL)
*update_selected_uri = TRUE;
if (data->last_selected_uri == NULL)
return;
if (! data->entry_changed)
return;
data->entry_changed = FALSE;
name = gtk_entry_get_text (GTK_ENTRY (_gtk_builder_get_widget (data->builder, "entry_name")));
location = gtk_entry_get_text (GTK_ENTRY (_gtk_builder_get_widget (data->builder, "entry_location")));
file = g_file_parse_name (location);
uri = g_file_get_uri (file);
bookmarks = gth_main_get_default_bookmarks ();
gth_uri_list_update_uri (GTH_URI_LIST (data->uri_list), data->last_selected_uri, uri, name);
gth_uri_list_update_bookmarks (GTH_URI_LIST (data->uri_list), bookmarks);
gth_main_bookmarks_changed ();
if (g_strcmp0 (data->last_selected_uri, uri) != 0) {
g_free (data->last_selected_uri);
data->last_selected_uri = g_strdup (uri);
if (update_selected_uri != NULL)
*update_selected_uri = FALSE;
}
g_free (uri);
g_object_unref (file);
}
static void
uri_list_selection_changed_cb (GtkTreeSelection *treeselection,
gpointer user_data)
{
DialogData *data = user_data;
GtkTreeModel *model;
GtkTreeIter iter;
char *uri;
gboolean update_selected_uri;
model = gtk_tree_view_get_model (GTK_TREE_VIEW (data->uri_list));
if (! gtk_tree_selection_get_selected (treeselection,
&model,
&iter))
{
return;
}
uri = gth_uri_list_get_uri (GTH_URI_LIST (data->uri_list), &iter);
if (uri == NULL)
return;
update_current_entry (data, &update_selected_uri);
if (update_selected_uri) {
g_free (data->last_selected_uri);
data->last_selected_uri = uri;
}
update_dialog_from_bookmark_file (data, uri);
}
/* called when the main dialog is closed. */
static void
destroy_cb (GtkWidget *widget,
DialogData *data)
{
update_current_entry (data, NULL);
gth_browser_set_dialog (data->browser, "bookmarks", NULL);
g_signal_handler_disconnect (gth_main_get_default_monitor (), data->bookmarks_changed_id);
g_object_unref (data->builder);
g_free (data);
}
static void
remove_cb (GtkWidget *widget,
DialogData *data)
{
char *uri;
GBookmarkFile *bookmarks;
GError *error = NULL;
uri = gth_uri_list_get_selected (GTH_URI_LIST (data->uri_list));
if (uri == NULL)
return;
bookmarks = gth_main_get_default_bookmarks ();
if (g_bookmark_file_remove_item (bookmarks, uri, &error)) {
gth_uri_list_remove_uri (GTH_URI_LIST (data->uri_list), uri);
gth_main_bookmarks_changed ();
}
else {
_gtk_error_dialog_from_gerror_show (GTK_WINDOW (data->dialog), _("Could not remove the bookmark"), error);
g_clear_error (&error);
}
g_free (uri);
}
static void
go_to_cb (GtkWidget *widget,
DialogData *data)
{
char *uri;
uri = gth_uri_list_get_selected (GTH_URI_LIST (data->uri_list));
if (uri != NULL) {
GFile *location;
location = g_file_new_for_uri (uri);
gth_browser_go_to (data->browser, location, NULL);
g_object_unref (location);
g_free (uri);
}
}
static void
bookmarks_changed_cb (GthMonitor *monitor,
DialogData *data)
{
GBookmarkFile *bookmarks;
char *uri;
GtkTreeSelection *selection;
gboolean selected;
if (data->entry_changed)
return;
uri = gth_uri_list_get_selected (GTH_URI_LIST (data->uri_list));
g_free (data->last_selected_uri);
data->last_selected_uri = NULL; /* do no update the entry */
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (data->uri_list));
g_signal_handlers_block_by_func (selection, uri_list_selection_changed_cb, data);
bookmarks = gth_main_get_default_bookmarks ();
gth_uri_list_set_bookmarks (GTH_URI_LIST (data->uri_list), bookmarks);
g_signal_handlers_unblock_by_func (selection, uri_list_selection_changed_cb, data);
selected = FALSE;
if (uri != NULL)
selected = gth_uri_list_select_uri (GTH_URI_LIST (data->uri_list), uri);
if (! selected) {
/* select the last one */
char **uris;
char *last_uri;
int i;
uris = g_bookmark_file_get_uris (bookmarks, NULL);
last_uri = NULL;
for (i = 0; uris[i] != NULL; i++)
last_uri = uris[i];
if (last_uri != NULL)
gth_uri_list_select_uri (GTH_URI_LIST (data->uri_list), last_uri);
else
set_bookmark_data (data, "", "");
g_strfreev (uris);
}
g_free (uri);
}
static void
uri_list_order_changed_cb (GthUriList *uri_list,
DialogData *data)
{
GBookmarkFile *bookmarks;
bookmarks = gth_main_get_default_bookmarks ();
gth_uri_list_update_bookmarks (GTH_URI_LIST (data->uri_list), bookmarks);
gth_main_bookmarks_changed ();
}
static void
uri_list_row_activated_cb (GtkTreeView *tree_view,
GtkTreePath *path,
GtkTreeViewColumn *column,
gpointer user_data)
{
DialogData *data = user_data;
GtkTreeModel *tree_model;
GtkTreeIter iter;
char *uri;
GFile *location;
tree_model = gtk_tree_view_get_model (tree_view);
if (! gtk_tree_model_get_iter (tree_model, &iter, path))
return;
uri = gth_uri_list_get_uri (GTH_URI_LIST (tree_view), &iter);
if (uri == NULL)
return;
location = g_file_new_for_uri (uri);
gth_browser_go_to (data->browser, location, NULL);
g_object_unref (location);
g_free (uri);
}
static void
entry_activate_cb (GtkEntry *entry,
DialogData *data)
{
update_current_entry (data, NULL);
}
static void
entry_changed_cb (GtkEditable *editable,
DialogData *data)
{
data->entry_changed = TRUE;
}
void
dlg_bookmarks (GthBrowser *browser)
{
DialogData *data;
GtkWidget *bm_list_container;
GtkWidget *bm_bookmarks_label;
GtkWidget *bm_remove_button;
GtkWidget *bm_go_to_button;
GBookmarkFile *bookmarks;
GtkTreeSelection *selection;
if (gth_browser_get_dialog (browser, "bookmarks") != NULL) {
gtk_window_present (GTK_WINDOW (gth_browser_get_dialog (browser, "bookmarks")));
return;
}
data = g_new0 (DialogData, 1);
data->browser = browser;
data->builder = gtk_builder_new_from_resource ("/org/x/Pix/bookmarks/data/ui/bookmarks.ui");
data->last_selected_uri = NULL;
data->entry_changed = FALSE;
/* Get the widgets. */
data->dialog = g_object_new (GTK_TYPE_DIALOG,
"title", _("Bookmarks"),
"transient-for", GTK_WINDOW (browser),
"modal", FALSE,
"destroy-with-parent", FALSE,
"use-header-bar", _gtk_settings_get_dialogs_use_header (),
NULL);
gtk_container_add (GTK_CONTAINER (gtk_dialog_get_content_area (GTK_DIALOG (data->dialog))),
_gtk_builder_get_widget (data->builder, "dialog_content"));
gtk_dialog_add_buttons (GTK_DIALOG (data->dialog),
_GTK_LABEL_OK, GTK_RESPONSE_CLOSE,
NULL);
gth_browser_set_dialog (browser, "bookmarks", data->dialog);
g_object_set_data (G_OBJECT (data->dialog), "dialog_data", data);
bm_list_container = _gtk_builder_get_widget (data->builder, "bm_list_container");
bm_bookmarks_label = _gtk_builder_get_widget (data->builder, "bm_bookmarks_label");
bm_remove_button = _gtk_builder_get_widget (data->builder, "bm_remove_button");
bm_go_to_button = _gtk_builder_get_widget (data->builder, "bm_go_to_button");
data->uri_list = gth_uri_list_new ();
gtk_widget_show (data->uri_list);
gtk_widget_set_vexpand (data->uri_list, TRUE);
gtk_container_add (GTK_CONTAINER (bm_list_container), data->uri_list);
gtk_label_set_mnemonic_widget (GTK_LABEL (bm_bookmarks_label), data->uri_list);
/* Set widgets data. */
bookmarks = gth_main_get_default_bookmarks ();
gth_uri_list_set_bookmarks (GTH_URI_LIST (data->uri_list), bookmarks);
data->bookmarks_changed_id = g_signal_connect (gth_main_get_default_monitor (),
"bookmarks-changed",
G_CALLBACK (bookmarks_changed_cb),
data);
/* Set the signals handlers. */
g_signal_connect (G_OBJECT (data->dialog),
"destroy",
G_CALLBACK (destroy_cb),
data);
g_signal_connect_swapped (gtk_dialog_get_widget_for_response (GTK_DIALOG (data->dialog), GTK_RESPONSE_CLOSE),
"clicked",
G_CALLBACK (gtk_widget_destroy),
G_OBJECT (data->dialog));
g_signal_connect (G_OBJECT (bm_remove_button),
"clicked",
G_CALLBACK (remove_cb),
data);
g_signal_connect (G_OBJECT (bm_go_to_button),
"clicked",
G_CALLBACK (go_to_cb),
data);
g_signal_connect (G_OBJECT (data->uri_list),
"order-changed",
G_CALLBACK (uri_list_order_changed_cb),
data);
g_signal_connect (G_OBJECT (data->uri_list),
"row-activated",
G_CALLBACK (uri_list_row_activated_cb),
data);
g_signal_connect (_gtk_builder_get_widget (data->builder, "entry_location"),
"activate",
G_CALLBACK (entry_activate_cb),
data);
g_signal_connect (_gtk_builder_get_widget (data->builder, "entry_name"),
"activate",
G_CALLBACK (entry_activate_cb),
data);
g_signal_connect (_gtk_builder_get_widget (data->builder, "entry_location"),
"changed",
G_CALLBACK (entry_changed_cb),
data);
g_signal_connect (_gtk_builder_get_widget (data->builder, "entry_name"),
"changed",
G_CALLBACK (entry_changed_cb),
data);
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (data->uri_list));
g_signal_connect (selection,
"changed",
G_CALLBACK (uri_list_selection_changed_cb),
data);
/* run dialog. */
gtk_widget_show (data->dialog);
}