Logo Search packages:      
Sourcecode: yelp version File versions  Download package

yelp-bookmarks.c

/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/*
 * Copyright (C) 2003 Shaun McCance  <shaunm@gnome.org>
 *
 * 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, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 *
 * Author: Shaun McCance  <shaunm@gnome.org>
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include "yelp-bookmarks.h"
#include "yelp-utils.h"
#include "yelp-window.h"

#include <string.h>
#include <gtk/gtkuimanager.h>
#include <gtk/gtkliststore.h>
#include <gtk/gtktreemodel.h>
#include <gdk/gdkkeysyms.h>
#include <glade/glade.h>
#include <libxml/parser.h>
#include <libxml/parserInternals.h>
#include <libxml/xpath.h>
#include <libxml/xpathInternals.h>
#include <libxml/xmlwriter.h>
#include <libgnome/gnome-config.h>

#ifdef YELP_DEBUG
#define d(x) x
#else
#define d(x)
#endif

#define COL_NAME   0
#define COL_LABEL  1
#define COL_EDIT   2
#define COL_HEADER 3
#define TOC_PATH "ui/menubar/BookmarksMenu/BookmarksTOC"
#define DOC_PATH "ui/menubar/BookmarksMenu/BookmarksDOC"
#define BK_CONFIG_WIDTH  "/yelp/Bookmarks/width"
#define BK_CONFIG_HEIGHT "/yelp/Bookmarks/height"
#define BK_CONFIG_WIDTH_DEFAULT  "360"
#define BK_CONFIG_HEIGHT_DEFAULT "360"

static GSList *windows;
static GtkTreeStore *actions_store;
static gchar *dup_title;

static GtkWidget *bookmarks_dialog = NULL;
static GtkWidget *edit_open_button = NULL;
static GtkWidget *edit_rename_button = NULL;
static GtkWidget *edit_remove_button = NULL;


static gboolean have_toc = FALSE;
static gboolean have_doc = FALSE;
static GtkTreeIter toc_iter;
static GtkTreeIter doc_iter;

typedef struct _YelpWindowData YelpWindowData;
struct _YelpWindowData {
    YelpWindow *window;
    guint merge_id;
    GtkActionGroup *toc_actions;
    GtkActionGroup *doc_actions;
};

static const char ui_description[] =
    "<ui>"
    "  <popup>"
    "    <menuitem action='OpenName'/>"
    "    <separator/>"
    "    <menuitem action='EditName'/>"
    "    <menuitem action='DeleteName'/>"
    "  </popup>"
    "</ui>";

static void      window_add_bookmark        (YelpWindowData *window,
                                   gchar          *name,
                                   const gchar    *label);
static void      bookmarks_add_bookmark     (const gchar    *uri,
                                   const gchar    *title,
                                   gboolean        save);
static void      bookmark_add_response_cb   (GtkDialog      *dialog,
                                   gint            id,
                                   gchar          *uri);
static void      window_remove_bookmark_menu(YelpWindowData *data);
static void      window_remove_action       (YelpWindowData *data,
                                   gchar          *name);
static gboolean  bookmarks_unregister       (YelpWindow     *window,
                                   GdkEvent       *event,
                                   gpointer        user_data);
static void      action_activated_cb        (GtkActionGroup *group,
                                   GtkAction      *action,
                                   YelpWindowData *data);
static void      bookmarks_rebuild_menus    (void);
static void      bookmarks_key_event_cb     (GtkWidget         *widget,
                                   GdkEventKey       *event,
                                   gpointer           user_data);
static void      bookmarks_open_button_cb   (GtkWidget         *widget,
                                   GtkTreeView       *view);
static void      bookmarks_rename_button_cb (GtkWidget         *widget,
                                   GtkTreeView       *view);
static void      bookmarks_remove_button_cb (GtkWidget         *widget,
                                   GtkTreeView       *view);
static void      bookmarks_ensure_valid     (void);
static gboolean  bookmarks_read             (const gchar       *filename);

static gboolean  bookmarks_dup_finder       (GtkTreeModel   *model,
                                   GtkTreePath    *path,
                                   GtkTreeIter    *iter,
                                   gpointer        data);
static void      bookmarks_open_cb          (GtkTreeView         *view,
                                   GtkTreePath         *path,
                                   GtkTreeViewColumn   *col,
                                   gpointer             user_data);
static void      bookmarks_cell_edited_cb   (GtkCellRendererText *cell,
                                   const gchar         *path_string,
                                   const gchar         *new_title,
                                   gpointer             user_data);
static void      bookmarks_popup_menu       (GtkWidget           *widget,
                                   GdkEventButton      *event);
static void      bookmarks_menu_edit_cb     (GtkAction           *action,
                                   GtkWidget           *widget);
static void      bookmarks_menu_remove_cb   (GtkAction           *action,
                                   GtkWidget           *widget);
static void      bookmarks_menu_open_cb     (GtkAction           *action,
                                   GtkWidget           *widget);
static gboolean  bookmarks_button_press_cb  (GtkWidget           *widget,
                                   GdkEventButton      *event);
static gboolean  bookmarks_configure_cb     (GtkWidget           *widget, 
                                   GdkEventConfigure   *event,
                                   gpointer             data);
static void      selection_changed_cb       (GtkTreeSelection    *selection,
                                   gpointer             data);

static const GtkActionEntry popup_entries[] = {
    { "OpenName", GTK_STOCK_OPEN,
      N_("Open Bookmark in New Window"),
      NULL, NULL,
      G_CALLBACK (bookmarks_menu_open_cb)},
    { "EditName", NULL,
      N_("Rename Bookmark"),
      NULL, NULL,
      G_CALLBACK (bookmarks_menu_edit_cb)},
    { "DeleteName", GTK_STOCK_REMOVE,
      N_("Remove Bookmark"),
      NULL, NULL,
      G_CALLBACK (bookmarks_menu_remove_cb)}
};


void
yelp_bookmarks_init (void)
{
    gchar   *filename = NULL;

    windows = NULL;
    actions_store = gtk_tree_store_new (4,
                              G_TYPE_STRING,
                              G_TYPE_STRING,
                              G_TYPE_BOOLEAN,
                              G_TYPE_BOOLEAN);

    filename = g_build_filename (g_get_home_dir (), ".gnome2",
                         "yelp-bookmarks.xbel", NULL);

    if (g_file_test (filename, G_FILE_TEST_EXISTS))
      bookmarks_read (filename);

    g_free (filename);
}

void
yelp_bookmarks_register (YelpWindow *window)
{
    GtkUIManager   *ui_manager;
    YelpWindowData *data;
    GtkTreeIter     top_iter, sub_iter;
    gboolean        top_valid, sub_valid;

    ui_manager = yelp_window_get_ui_manager (window);

    g_signal_connect (window, "delete-event",
                  G_CALLBACK (bookmarks_unregister), NULL);

    data = g_new0 (YelpWindowData, 1);
    data->window = window;
    data->toc_actions = gtk_action_group_new ("BookmarksTOC");
    data->doc_actions = gtk_action_group_new ("BookmarksDOC");
    data->merge_id = gtk_ui_manager_new_merge_id(ui_manager);

    gtk_ui_manager_insert_action_group (ui_manager, data->toc_actions, 1);
    gtk_ui_manager_insert_action_group (ui_manager, data->doc_actions, 2);

    g_signal_connect (data->toc_actions,
                  "post-activate",
                  G_CALLBACK (action_activated_cb),
                  data);
    g_signal_connect (data->doc_actions,
                  "post-activate",
                  G_CALLBACK (action_activated_cb),
                  data);

    top_valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (actions_store),
                                     &top_iter);
    while (top_valid) {
      if (gtk_tree_model_iter_has_child (GTK_TREE_MODEL (actions_store),
                                 &top_iter)) {
          sub_valid = gtk_tree_model_iter_children (GTK_TREE_MODEL (actions_store),
                                          &sub_iter, &top_iter);
          while (sub_valid) {
            gchar *label, *name;
            gtk_tree_model_get (GTK_TREE_MODEL (actions_store), &sub_iter,
                            COL_NAME,  &name,
                            COL_LABEL, &label,
                            -1);
            window_add_bookmark (data, name, label);
            g_free (name);
            g_free (label);

            sub_valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (actions_store),
                                          &sub_iter);
          }
      }
      top_valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (actions_store),
                                    &top_iter);
    }

    windows = g_slist_append (windows, data);
}

static void
bookmarks_ensure_valid (void)
{
      if (have_toc &&
          !gtk_tree_model_iter_has_child (GTK_TREE_MODEL (actions_store),
                                  &toc_iter)) {
          gtk_tree_store_remove (actions_store, &toc_iter);
          have_toc = FALSE;
      }
      if (have_doc &&
          !gtk_tree_model_iter_has_child (GTK_TREE_MODEL (actions_store),
                                  &doc_iter)) {
          gtk_tree_store_remove (actions_store, &doc_iter);
          have_doc = FALSE;
      }     
}

static gboolean 
bookmarks_dup_finder (GtkTreeModel *model, GtkTreePath *path,
                  GtkTreeIter *iter, gpointer data)
{
    gchar *uri = data;
    gchar *current_uri;

    gtk_tree_model_get (model, iter,
                  COL_NAME, &current_uri,
                  -1);

    if (current_uri && g_str_equal (current_uri, uri)) {
      gtk_tree_model_get (model, iter,
                      COL_LABEL, &dup_title,
                      -1);
      g_free (current_uri);
      return TRUE;
    }

    g_free (current_uri);
    return FALSE;
}


void
yelp_bookmarks_add (const gchar *uri, YelpWindow *window)
{
    GladeXML    *glade;
    GtkWidget   *dialog;
    GtkEntry    *entry;
    gchar       *title;
    gchar       *dup_uri;

    title = (gchar *) gtk_window_get_title (GTK_WINDOW (window));
    dup_uri = g_strdup (uri);
    
    if (dup_title)
      g_free (dup_title);
    dup_title = NULL;
    gtk_tree_model_foreach (GTK_TREE_MODEL (actions_store),
                      bookmarks_dup_finder, dup_uri);
    if (dup_title) {
      char *escaped_title, *markup;

      dialog = gtk_message_dialog_new_with_markup
          (GTK_WINDOW (window),
           GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
           GTK_MESSAGE_INFO,
           GTK_BUTTONS_OK,
           NULL);

      escaped_title = g_markup_printf_escaped
            ("<b>%s</b>", dup_title);
      markup = g_strdup_printf
            (_("A bookmark titled %s already exists for this page."),
            escaped_title);
      gtk_message_dialog_set_markup (GTK_MESSAGE_DIALOG (dialog), markup);
      g_free (markup);
      g_free (escaped_title);

      gtk_dialog_run (GTK_DIALOG (dialog));
      gtk_widget_destroy (dialog);

      g_free (dup_title);
      dup_title = NULL;
      return;
    }

    glade = glade_xml_new (DATADIR "/yelp/ui/yelp.glade",
                     "add_bookmark_dialog",
                     NULL);
    if (!glade) {
      g_warning ("Could not find necessary glade file "
               DATADIR "/yelp/ui/yelp.glade");
      return;
    }

    dialog = glade_xml_get_widget (glade, "add_bookmark_dialog");
    entry = GTK_ENTRY (glade_xml_get_widget (glade, "bookmark_title_entry"));
    gtk_entry_set_text (entry, title);
    gtk_editable_select_region (GTK_EDITABLE (entry), 0, -1);

    g_object_set_data (G_OBJECT (dialog), "title_entry", entry);

    g_signal_connect (G_OBJECT (dialog),
                  "response",
                  G_CALLBACK (bookmark_add_response_cb),
                  dup_uri);

    g_object_unref (glade);
    gtk_window_present (GTK_WINDOW (dialog));
}

static void
bookmark_add_response_cb (GtkDialog *dialog, gint id, gchar *uri)
{
    GtkEntry *entry;
    gchar *title;

    if (id == GTK_RESPONSE_OK) {
      entry = GTK_ENTRY (g_object_get_data (G_OBJECT (dialog), "title_entry"));
      title = (gchar *) gtk_entry_get_text (entry);

      bookmarks_add_bookmark (uri, title, TRUE);
    }

    g_free (uri);
    gtk_widget_destroy (GTK_WIDGET (dialog));
}

static void
bookmarks_add_bookmark (const gchar  *uri,
                  const gchar  *title,
                  gboolean      save)
{
    GtkTreeIter  iter;
    GSList      *cur;
    gboolean     tocQ;

    if (dup_title)
      g_free (dup_title);
    dup_title = NULL;
    gtk_tree_model_foreach (GTK_TREE_MODEL (actions_store),
                      bookmarks_dup_finder, (gpointer) uri);
    if (dup_title) {
      GtkWidget *dialog;
      dialog = gtk_message_dialog_new_with_markup
          (NULL,
           GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
           GTK_MESSAGE_ERROR,
           GTK_BUTTONS_OK,
           _("A bookmark titled <b>%s</b> already exists for this page."),
           dup_title);
      gtk_dialog_run (GTK_DIALOG (dialog));
      gtk_widget_destroy (dialog);
      g_free (dup_title);
      dup_title = NULL;
      return;
    }

    tocQ = g_str_has_prefix (uri, "x-yelp-toc:");
    if (tocQ) {
      if (!have_toc) {
          gchar *label = g_markup_printf_escaped ("<b>%s</b>",
                                        _("Help Topics"));
          gtk_tree_store_prepend (actions_store, &toc_iter, NULL);
          gtk_tree_store_set (actions_store, &toc_iter,
                        COL_NAME,   "",
                        COL_LABEL,  label,
                        COL_EDIT,   FALSE,
                        COL_HEADER, TRUE,
                        -1);
          have_toc = TRUE;
          g_free (label);
      }
      gtk_tree_store_append (actions_store, &iter, &toc_iter);
    } else {
      if (!have_doc) {
          gchar *label = g_markup_printf_escaped ("<b>%s</b>",
                                        _("Document Sections"));
          gtk_tree_store_append (actions_store, &doc_iter, NULL);
          gtk_tree_store_set (actions_store, &doc_iter,
                        COL_NAME,   "",
                        COL_LABEL,  label,
                        COL_EDIT,   FALSE,
                        COL_HEADER, TRUE,
                        -1);
          have_doc = TRUE;
          g_free (label);
      }
      gtk_tree_store_append (actions_store, &iter, &doc_iter);
    }

    gtk_tree_store_set (actions_store, &iter,
                  COL_NAME,   uri,
                  COL_LABEL,  title,
                  COL_EDIT,   TRUE,
                  COL_HEADER, FALSE,
                  -1);
    if (save) {
      for (cur = windows; cur != NULL; cur = cur->next) {
          window_add_bookmark ((YelpWindowData *) cur->data, (gchar *) uri, 
                         title);
      }
      yelp_bookmarks_write ();
    }
}

static void
window_remove_bookmark_menu (YelpWindowData *data)
{
    GtkUIManager *ui_manager;

    ui_manager = yelp_window_get_ui_manager (data->window);

    gtk_ui_manager_remove_ui (ui_manager, data->merge_id);

    data->merge_id = gtk_ui_manager_new_merge_id (ui_manager);

    gtk_ui_manager_ensure_update (ui_manager);
}

static void
window_remove_action (YelpWindowData *data, gchar *name)
{
    GtkAction *action = gtk_action_group_get_action (data->toc_actions, name);
    if (action) {
      gtk_action_group_remove_action (data->toc_actions, action);
    }
    else {
      action = gtk_action_group_get_action (data->doc_actions, name);
      if (action) {
          gtk_action_group_remove_action (data->doc_actions, action);
      }
    }
}

static void
bookmarks_rebuild_menus (void)
{
    GSList      *cur;
    GtkTreeIter top_iter, sub_iter;
    gboolean top_valid, sub_valid;

    for (cur = windows; cur != NULL; cur = cur->next) {
      window_remove_bookmark_menu ((YelpWindowData *) cur->data);
    }

    top_valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (actions_store), 
                                     &top_iter);
    while (top_valid) {
      if (gtk_tree_model_iter_has_child (GTK_TREE_MODEL (actions_store),
                                 &top_iter)) {
          sub_valid = gtk_tree_model_iter_children (GTK_TREE_MODEL (actions_store),
                                          &sub_iter, &top_iter);
          while (sub_valid) {
            gchar *name, *label;
            gtk_tree_model_get (GTK_TREE_MODEL (actions_store), &sub_iter,
                            COL_NAME,   &name,
                            COL_LABEL,  &label,
                            -1);
            for (cur = windows; cur != NULL; cur = cur->next) {
                window_remove_action (cur->data, name);
                window_add_bookmark (cur->data, name, label);
            }
            g_free (name);
            g_free (label);

            sub_valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (actions_store), 
                                          &sub_iter);
          }
      }
      top_valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (actions_store), 
                                    &top_iter);
    }

    yelp_bookmarks_write ();
}

static void
bookmarks_key_event_cb (GtkWidget   *widget,
                  GdkEventKey *event,
                  gpointer     user_data)
{
    GtkTreeView *view = GTK_TREE_VIEW (widget);
    GtkTreePath *path;
    GtkTreeSelection *sel;
    GtkTreeModel *model;
    GtkTreeIter iter;
    
    model = gtk_tree_view_get_model (view);
    sel = gtk_tree_view_get_selection (view);
    
    if (gtk_tree_selection_get_selected (sel, &model, &iter)) {
      path = gtk_tree_model_get_path (model, &iter);
      
      switch (event->keyval) {
      case GDK_BackSpace:
      case GDK_Delete:
          if (!gtk_tree_model_iter_has_child (GTK_TREE_MODEL (actions_store),
                                    &iter)) {
            gtk_tree_store_remove (actions_store, &iter);
            bookmarks_ensure_valid ();
            bookmarks_rebuild_menus ();
          }
          break;
      case GDK_Return:
      case GDK_KP_Enter:
          bookmarks_open_cb (view, path, NULL, NULL);
          break;
      case GDK_Up:
          gtk_tree_path_prev (path);
          gtk_tree_selection_select_path (sel, path);
          break;
      case GDK_Down:
          gtk_tree_path_next (path);
          gtk_tree_selection_select_path (sel, path);
          break;
      default:
          break;
      }
    }
}

static void
bookmarks_open_cb (GtkTreeView *view, GtkTreePath *path,
               GtkTreeViewColumn *col, gpointer user_data)
{
    GtkTreeIter iter;
    gchar *name;
    gchar *title;
    GSList *cur;
    YelpWindowData *data;

    gtk_tree_model_get_iter (GTK_TREE_MODEL (actions_store), &iter, path);
    if (!gtk_tree_model_iter_has_child (GTK_TREE_MODEL (actions_store),
                              &iter)) {
      gtk_tree_model_get (GTK_TREE_MODEL (actions_store), &iter,
                      COL_NAME, &name,
                      COL_LABEL, &title, -1);
      
      cur = windows;
      data = cur->data;
      
      g_signal_emit_by_name (data->window, "new_window_requested", name, NULL);
    }
}


static void
bookmarks_cell_edited_cb (GtkCellRendererText *cell, const gchar *path_string,
                    const gchar *new_title, gpointer user_data)
{
    GtkTreePath *path = gtk_tree_path_new_from_string (path_string);
    GtkTreeIter it;

    gtk_tree_model_get_iter (GTK_TREE_MODEL (actions_store), &it, path);

    gtk_tree_store_set (actions_store, &it,
                  COL_LABEL, new_title, -1);
    bookmarks_rebuild_menus ();

}

void
yelp_bookmarks_edit (void)
{
    GladeXML    *glade;
    GtkTreeView *view;
    GtkTreeSelection *select;
    GtkCellRenderer *renderer;
    gint width, height;
    
    if (!bookmarks_dialog) {
      glade = glade_xml_new (DATADIR "/yelp/ui/yelp.glade",
                         "bookmarks_dialog",
                         NULL);
      if (!glade) {
          g_warning ("Could not find necessary glade file "
                   DATADIR "/yelp/ui/yelp.glade");
          return;
      }

      bookmarks_dialog = glade_xml_get_widget (glade, "bookmarks_dialog");
      view = GTK_TREE_VIEW (glade_xml_get_widget (glade, "bookmarks_view"));
      width = gnome_config_get_int (BK_CONFIG_WIDTH
                              "=" BK_CONFIG_WIDTH_DEFAULT);
      height = gnome_config_get_int (BK_CONFIG_HEIGHT
                               "=" BK_CONFIG_HEIGHT_DEFAULT);
      gtk_window_set_default_size (GTK_WINDOW (bookmarks_dialog), 
                             width, height);

      g_signal_connect (G_OBJECT (bookmarks_dialog), "response",
                    G_CALLBACK (gtk_widget_hide), NULL);
      g_signal_connect (G_OBJECT (bookmarks_dialog), "delete_event",
                    G_CALLBACK (gtk_widget_hide_on_delete), NULL);
      
      renderer = gtk_cell_renderer_text_new ();
    
      gtk_tree_view_insert_column_with_attributes
          (view, -1,
           NULL, renderer,
           "markup", COL_LABEL,
           "editable", COL_EDIT,
           NULL);
      gtk_tree_view_set_model (view, GTK_TREE_MODEL (actions_store));

      select = gtk_tree_view_get_selection (GTK_TREE_VIEW (view));
      
      gtk_tree_selection_set_mode (select, GTK_SELECTION_SINGLE);
      gtk_tree_view_expand_all (GTK_TREE_VIEW (view));

      g_signal_connect (G_OBJECT (view), "row-activated",
                    G_CALLBACK (bookmarks_open_cb),
                    NULL); 
      g_signal_connect (G_OBJECT (view), "key-press-event",
                    G_CALLBACK (bookmarks_key_event_cb),
                    NULL);
      g_signal_connect (G_OBJECT (renderer), "edited",
                    G_CALLBACK (bookmarks_cell_edited_cb), NULL);

      edit_open_button = glade_xml_get_widget (glade, "open_button");
      g_signal_connect (G_OBJECT (edit_open_button), "clicked",
                    G_CALLBACK (bookmarks_open_button_cb),
                    view);
      edit_rename_button = glade_xml_get_widget (glade, "rename_button");
      g_signal_connect (G_OBJECT (edit_rename_button), "clicked",
                    G_CALLBACK (bookmarks_rename_button_cb),
                    view);
      edit_remove_button = glade_xml_get_widget (glade, "remove_button");
      g_signal_connect (G_OBJECT (edit_remove_button), "clicked",
                    G_CALLBACK (bookmarks_remove_button_cb),
                    view);
      g_signal_connect (G_OBJECT (select), "changed",
                    G_CALLBACK (selection_changed_cb),
                    NULL);
      g_signal_connect (G_OBJECT (view), "button-press-event",
                    G_CALLBACK (bookmarks_button_press_cb),
                    NULL);
      g_signal_connect (G_OBJECT (bookmarks_dialog), "configure-event",
                    G_CALLBACK (bookmarks_configure_cb),
                    NULL);

      g_object_unref (glade);
    }

    gtk_window_present (GTK_WINDOW (bookmarks_dialog));
}

static gboolean
bookmarks_configure_cb (GtkWidget *widget, GdkEventConfigure *event,
                  gpointer data)
{
    gint width, height;
    gtk_window_get_size (GTK_WINDOW (widget), &width, &height);
    gnome_config_set_int (BK_CONFIG_WIDTH, width);
    gnome_config_set_int (BK_CONFIG_HEIGHT, height);
    gnome_config_sync ();

    return FALSE;
}

static void
selection_changed_cb (GtkTreeSelection *selection, gpointer data)
{
    GtkTreeIter iter;
    if (gtk_tree_selection_get_selected (selection, NULL, &iter) &&
      !gtk_tree_model_iter_has_child (GTK_TREE_MODEL (actions_store), 
                              &iter)) {
      /*A row is highlighted - sensitise the various widgets*/
      gtk_widget_set_sensitive (GTK_WIDGET (edit_open_button), TRUE);
      gtk_widget_set_sensitive (GTK_WIDGET (edit_rename_button), TRUE);
      gtk_widget_set_sensitive (GTK_WIDGET (edit_remove_button), TRUE);
    }
    else {
      /*No row is highlighted - desensitise the various widgets*/
      gtk_widget_set_sensitive (GTK_WIDGET (edit_open_button), FALSE);
      gtk_widget_set_sensitive (GTK_WIDGET (edit_rename_button), FALSE);
      gtk_widget_set_sensitive (GTK_WIDGET (edit_remove_button), FALSE);
      
    }
}


static void
bookmarks_open_button_cb (GtkWidget *widget, GtkTreeView *view)
{
    GtkTreeIter iter;
    GtkTreePath *path;
    GtkTreeModel *model;
    GtkTreeSelection *select;

    model = gtk_tree_view_get_model (view);

    select = gtk_tree_view_get_selection (view);
    if (gtk_tree_selection_get_selected (select, NULL, &iter)) {
      path = gtk_tree_model_get_path (model, &iter);
      
      bookmarks_open_cb (view, path, NULL, NULL);
      
      gtk_tree_path_free (path);
    }
}

static void
bookmarks_rename_button_cb (GtkWidget *widget, GtkTreeView *view)
{
    GtkTreePath *path;
    GtkTreeSelection *sel;
    GtkTreeIter iter;
    GtkTreeViewColumn *col;
    GtkTreeModel *model = GTK_TREE_MODEL (actions_store);
    gboolean selection;

    sel = gtk_tree_view_get_selection (view);
    selection = gtk_tree_selection_get_selected (sel, &model, &iter);
    if (selection) {
      path = gtk_tree_model_get_path (model, &iter);
      col = gtk_tree_view_get_column (view, 0);
      
      gtk_tree_view_set_cursor (view, path, col, TRUE);
    }
}

static void
bookmarks_remove_button_cb (GtkWidget *widget, GtkTreeView *view)
{
    GtkTreeIter iter;
    GtkTreeSelection *select;

    select = gtk_tree_view_get_selection (GTK_TREE_VIEW (view));
    if (gtk_tree_selection_get_selected (select, NULL, &iter)) {

      gtk_tree_store_remove (actions_store, &iter);
      bookmarks_ensure_valid ();
      bookmarks_rebuild_menus ();
    }
}

static void
bookmarks_popup_menu (GtkWidget *widget,GdkEventButton *event)
{
    GtkWidget *menu;
    gint button, event_time;
    GtkActionGroup *action_group;
    GtkUIManager *ui_manager;
    GError *error;

    action_group = gtk_action_group_new ("PopupActions");
    gtk_action_group_set_translation_domain (action_group,
                                            GETTEXT_PACKAGE);
    gtk_action_group_add_actions (action_group, popup_entries,
                                 G_N_ELEMENTS (popup_entries), widget);

    ui_manager = gtk_ui_manager_new ();
    gtk_ui_manager_insert_action_group (ui_manager, action_group, 0);

    if (!gtk_ui_manager_add_ui_from_string (ui_manager,
                                           ui_description, -1, &error)) {
       g_message ("Building menus failed: %s", error->message);
       g_error_free (error);
       exit (EXIT_FAILURE);
    }
    menu = gtk_ui_manager_get_widget (ui_manager, "/popup");

    if (event) {
       button = event->button;
       event_time = event->time;
    } else {
       button = 0;
       event_time = gtk_get_current_event_time ();
    }
    gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL,
                   button, event_time);

}

static void
bookmarks_menu_edit_cb (GtkAction *action, GtkWidget *widget)
{
    GtkTreeView *view = GTK_TREE_VIEW (widget);
    GtkTreePath *path;
    GtkTreeSelection *sel;
    GtkTreeIter iter;
    GtkTreeViewColumn *col;
    GtkTreeModel *model = GTK_TREE_MODEL (actions_store);

    sel = gtk_tree_view_get_selection (view);
    if (gtk_tree_selection_get_selected (sel, &model, &iter)) {
      path = gtk_tree_model_get_path (model, &iter);
      col = gtk_tree_view_get_column (view, 0);
      
      gtk_tree_view_set_cursor (view, path, col, TRUE);
    }
}

static void
bookmarks_menu_remove_cb (GtkAction *action, GtkWidget *widget)
{
    GtkTreeView *view = GTK_TREE_VIEW (widget);
    GtkTreeSelection *sel;
    GtkTreeIter iter;

    sel = gtk_tree_view_get_selection (view);
    if (gtk_tree_selection_get_selected (sel, NULL, &iter)) {
      
      gtk_tree_store_remove (actions_store, &iter);
      bookmarks_ensure_valid ();
      bookmarks_rebuild_menus ();
    }
}

static void
bookmarks_menu_open_cb (GtkAction *action, GtkWidget *widget)
{
    GtkTreeView *view = GTK_TREE_VIEW (widget);
    GtkTreeSelection *sel = gtk_tree_view_get_selection (view);
    GtkTreeIter iter;
    GtkTreeModel *model = GTK_TREE_MODEL (actions_store);
    GtkTreePath *path;

    if (gtk_tree_selection_get_selected (sel, &model, &iter)) {
      path = gtk_tree_model_get_path (model, &iter);
      
      bookmarks_open_cb (view, path, NULL, NULL);
    }
}

static gboolean
bookmarks_button_press_cb (GtkWidget *widget, GdkEventButton *event)
{
    GtkTreeView *view = GTK_TREE_VIEW (widget);
    GtkTreeSelection *sel = gtk_tree_view_get_selection (view);
    gboolean selection;
    GtkTreeIter iter;
    GtkTreeModel *model = GTK_TREE_MODEL (actions_store);
    gboolean editable;

    selection = gtk_tree_selection_get_selected (sel,
                                                &model,
                                                &iter);
    if (selection) {
      gtk_tree_model_get (GTK_TREE_MODEL (actions_store), &iter,
                      COL_EDIT, &editable, -1);
       if (event->button == 3 && event->type == GDK_BUTTON_PRESS &&
         editable) {
           bookmarks_popup_menu (widget, event);
         return TRUE;
       }
    }
    return FALSE;
}


void
yelp_bookmarks_write (void)
{
    xmlTextWriterPtr file;
    GtkTreeIter top_iter, sub_iter;
    gboolean top_valid, sub_valid;
    gchar *filename;

    filename = g_build_filename (g_get_home_dir (), ".gnome2", 
                         "yelp-bookmarks.xbel", NULL);

    file = xmlNewTextWriterFilename (filename, 
                             0);
    if(!file) {
      g_warning ("Could not create bookmark file %s", filename);
      return;
    }

    xmlTextWriterStartDocument (file, NULL, NULL, NULL);
    xmlTextWriterStartElement (file, BAD_CAST "xbel");
    xmlTextWriterWriteAttribute(file, BAD_CAST "version",
                                     BAD_CAST "1.0");

    xmlTextWriterStartElement (file, BAD_CAST "info");
    xmlTextWriterStartElement (file, BAD_CAST "metadata");
    xmlTextWriterWriteAttribute(file, BAD_CAST "owner",
                                     BAD_CAST "http://live.gnome.org/Yelp");
    xmlTextWriterEndElement (file);
    xmlTextWriterEndElement (file);

    top_valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (actions_store),
                                     &top_iter);

    while (top_valid) {
      if (gtk_tree_model_iter_has_child (GTK_TREE_MODEL (actions_store),
                                 &top_iter)) {
          sub_valid = gtk_tree_model_iter_children (GTK_TREE_MODEL (actions_store),
                                          &sub_iter, &top_iter);
          while (sub_valid) {
            gchar *name;
            gchar *label;
            gtk_tree_model_get (GTK_TREE_MODEL (actions_store), &sub_iter,
                            COL_NAME, &name, 
                            COL_LABEL, &label,
                            -1);
            xmlTextWriterStartElement (file, BAD_CAST "bookmark");
            xmlTextWriterWriteAttribute (file, BAD_CAST "href", 
                                   BAD_CAST name);

            xmlTextWriterWriteElement (file,
                                 BAD_CAST "title",
                                 BAD_CAST label);

            xmlTextWriterStartElement (file, BAD_CAST "info");
            xmlTextWriterStartElement (file, BAD_CAST "metadata");
            xmlTextWriterWriteAttribute
                (file, BAD_CAST "owner",
                 BAD_CAST "http://live.gnome.org/Yelp");
            xmlTextWriterEndElement (file); /* metadata */
            xmlTextWriterEndElement (file); /* info */
            xmlTextWriterEndElement (file); /* bookmark */

            g_free (name);
            g_free (label);

            sub_valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (actions_store),
                                          &sub_iter);
          }
      }
      top_valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (actions_store),
                                    &top_iter);
    }

    xmlTextWriterEndDocument(file);
    xmlFreeTextWriter(file);
    g_free (filename);
    return;
}

static gboolean
bookmarks_read (const gchar *filename)
{
    xmlParserCtxtPtr   parser;
    xmlXPathContextPtr xpath;
    xmlXPathObjectPtr  obj;
    xmlDocPtr          doc;

    gboolean  ret = TRUE;
    gint      i;

    parser = xmlNewParserCtxt ();
    doc = xmlCtxtReadFile (parser, filename, NULL,
                     XML_PARSE_NOBLANKS | XML_PARSE_NOCDATA  |
                     XML_PARSE_NOENT    | XML_PARSE_NOERROR  |
                     XML_PARSE_NONET    );

    if (doc == NULL) {
      if (parser)
            xmlFreeParserCtxt (parser);
      return FALSE;
    }

    xpath = xmlXPathNewContext (doc);
    obj = xmlXPathEvalExpression (BAD_CAST "/xbel/bookmark", xpath);
    for (i = 0; i < obj->nodesetval->nodeNr; i++) {
      xmlNodePtr node = obj->nodesetval->nodeTab[i];
      gchar *uri;
      uri = (gchar *) xmlGetProp (node, BAD_CAST "href");
      if (uri) {
          xmlXPathObjectPtr title_obj;
          xpath->node = node;
          title_obj = xmlXPathEvalExpression (BAD_CAST "string(title[1])", 
                                    xpath);
          xpath->node = NULL;

          if (title_obj->stringval)
            bookmarks_add_bookmark ((const gchar *) uri, 
                              (const gchar *) title_obj->stringval, 
                              FALSE);

          xmlXPathFreeObject (title_obj);
          xmlFree (uri);
      }
    }
    
    if (obj)
      xmlXPathFreeObject (obj);
    if (xpath)
      xmlXPathFreeContext (xpath);
    if (parser)
      xmlFreeParserCtxt (parser);
    if (doc)
      xmlFreeDoc (doc);
    return ret;
}

static void
window_add_bookmark (YelpWindowData *data,
                 gchar          *name,
                 const gchar    *label)
{
    GtkUIManager *ui_manager;
    GtkAction    *action;
    gboolean tocQ;

    tocQ = g_str_has_prefix (name, "x-yelp-toc:");
    ui_manager = yelp_window_get_ui_manager (data->window);
    action = gtk_action_new (name, label, label, NULL);

    gtk_action_group_add_action (tocQ ? data->toc_actions : data->doc_actions,
                         action);

    gtk_ui_manager_add_ui (ui_manager,
                     data->merge_id,
                     tocQ ? TOC_PATH : DOC_PATH,
                     label, name,
                     GTK_UI_MANAGER_MENUITEM,
                     FALSE);
    g_object_unref (action);
}

static gboolean
bookmarks_unregister (YelpWindow *window,
                  GdkEvent   *event,
                  gpointer    user_data)
{
    GSList *cur;

    for (cur = windows; cur != NULL; cur = cur->next) {
      YelpWindowData *data = (YelpWindowData *) cur->data;;
      if (data->window == window) {
          g_object_unref (data->toc_actions);
          g_object_unref (data->doc_actions);
          g_free (data);
          windows = g_slist_delete_link (windows, cur);
          break;
      }
    }

    return FALSE;
}

static void
action_activated_cb (GtkActionGroup *group,
                 GtkAction      *action,
                 YelpWindowData *data)
{
    gchar *uri;

    g_object_get (action, "name", &uri, NULL);
    yelp_window_load (data->window, uri);

    g_free (uri);
}

Generated by  Doxygen 1.6.0   Back to index