aboutsummaryrefslogblamecommitdiffstats
path: root/src/bookmarks/ephy-topics-selector.c
blob: d97a9449f3e236ec39ae706d0a0f621f8f8eddeb (plain) (tree)




















                                                                              
                           



                                      
                                 
                            
                          
                           























































                                                                             
                                                                                       















































































                                                                                                           
                      







































                                                                           
                                             
                             





                                                           







                                                                
                                                     
                                                               
                                                                              
 
                                                               



























                                                                         
                                              










































                                                                               
































                                                                        
































                                                                                      



                                                 





                                                                                      

                                                                                 
                                                             



                                                   

                                                              
                                                                     



                                                                   
                                                                     
        
                                                               
                                                                  
                                                                  
                                                              
                            










                                                             

                                                   







                                                   
                                              


                                      
        

                                   
/*
 *  Copyright (C) 2002 Marco Pesenti Gritti <mpeseng@tin.it>
 *
 *  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.
 *
 */

#include "ephy-topics-selector.h"
#include "ephy-debug.h"
#include "ephy-node-view.h"

#include <gtk/gtkliststore.h>
#include <gtk/gtkcellrenderertoggle.h>
#include <gtk/gtkcellrenderertext.h>
#include <gtk/gtktreeselection.h>
#include <gtk/gtktreeview.h>
#include <gtk/gtkwindow.h>
#include <gdk/gdkkeysyms.h>

static void ephy_topics_selector_class_init (EphyTopicsSelectorClass *klass);
static void ephy_topics_selector_init (EphyTopicsSelector *editor);
static void ephy_topics_selector_finalize (GObject *object);
static void ephy_topics_selector_set_property (GObject *object,
                                       guint prop_id,
                                       const GValue *value,
                                       GParamSpec *pspec);
static void ephy_topics_selector_get_property (GObject *object,
                                       guint prop_id,
                                       GValue *value,
                                       GParamSpec *pspec);

struct EphyTopicsSelectorPrivate
{
    EphyBookmarks *bookmarks;
    GtkTreeModel *model;
    EphyNode *bookmark;
};

enum
{
    PROP_0,
    PROP_BOOKMARKS,
    PROP_BOOKMARK
};

enum
{
    COL_HAS_TOPIC,
    COL_TOPIC,
    COL_NODE
};;

static GObjectClass *parent_class = NULL;

GType
ephy_topics_selector_get_type (void)
{
    static GType ephy_topics_selector_type = 0;

    if (ephy_topics_selector_type == 0)
    {
        static const GTypeInfo our_info =
        {
            sizeof (EphyTopicsSelectorClass),
            NULL,
            NULL,
            (GClassInitFunc) ephy_topics_selector_class_init,
            NULL,
            NULL,
            sizeof (EphyTopicsSelector),
            0,
            (GInstanceInitFunc) ephy_topics_selector_init
        };

        ephy_topics_selector_type = g_type_register_static (GTK_TYPE_TREE_VIEW,
                                        "EphyTopicsSelector",
                                        &our_info, 0);
    }

    return ephy_topics_selector_type;
}

static void
ephy_topics_selector_class_init (EphyTopicsSelectorClass *klass)
{
    GObjectClass *object_class = G_OBJECT_CLASS (klass);

    parent_class = g_type_class_peek_parent (klass);

    object_class->finalize = ephy_topics_selector_finalize;

    object_class->set_property = ephy_topics_selector_set_property;
    object_class->get_property = ephy_topics_selector_get_property;

    g_object_class_install_property (object_class,
                     PROP_BOOKMARKS,
                     g_param_spec_object ("bookmarks",
                                  "Bookmarks set",
                                  "Bookmarks set",
                                  EPHY_BOOKMARKS_TYPE,
                                  G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));

    g_object_class_install_property (object_class,
                     PROP_BOOKMARK,
                     g_param_spec_object ("bookmark",
                                  "Bookmark",
                                  "Bookmark",
                                  EPHY_TYPE_NODE,
                                  G_PARAM_READWRITE));
}

static void
ephy_topics_selector_finalize (GObject *object)
{
    EphyTopicsSelector *editor;

    g_return_if_fail (object != NULL);
    g_return_if_fail (EPHY_IS_TOPIC_SELECTOR (object));

    editor = EPHY_TOPICS_SELECTOR (object);

    g_return_if_fail (editor->priv != NULL);

    g_free (editor->priv);

    G_OBJECT_CLASS (parent_class)->finalize (object);
}

void
ephy_topics_selector_set_bookmark (EphyTopicsSelector *selector,
                   EphyNode *bookmark)
{
    LOG ("Set bookmark")

    selector->priv->bookmark = bookmark;

    g_object_notify (G_OBJECT (selector), "bookmark");
}

static void
ephy_topics_selector_set_property (GObject *object,
                           guint prop_id,
                           const GValue *value,
                           GParamSpec *pspec)
{
    EphyTopicsSelector *selector = EPHY_TOPICS_SELECTOR (object);

    switch (prop_id)
    {
    case PROP_BOOKMARKS:
        selector->priv->bookmarks = g_value_get_object (value);
        break;
    case PROP_BOOKMARK:
        ephy_topics_selector_set_bookmark
            (selector, g_value_get_object (value));
        break;
    default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
        break;
    }
}

static void
ephy_topics_selector_get_property (GObject *object,
                           guint prop_id,
                           GValue *value,
                           GParamSpec *pspec)
{
    EphyTopicsSelector *selector = EPHY_TOPICS_SELECTOR (object);

    switch (prop_id)
    {
    case PROP_BOOKMARK:
        g_value_set_object (value, selector);
        break;
    default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
        break;
    }
}

static void
fill_model (EphyTopicsSelector *editor)
{
    GPtrArray *children;
    int i;
    EphyNode *keywords;
    GtkListStore *model = GTK_LIST_STORE (editor->priv->model);

    keywords = ephy_bookmarks_get_keywords (editor->priv->bookmarks);

    children = ephy_node_get_children (keywords);
    for (i = 0; i < children->len; i++)
    {
        EphyNode *kid;
        const char *name;
        gboolean has_keyword = FALSE;
        int priority;
        GtkTreeIter iter;

        kid = g_ptr_array_index (children, i);

        name = ephy_node_get_property_string
            (kid, EPHY_NODE_KEYWORD_PROP_NAME);

        if (editor->priv->bookmark != NULL)
        {
            has_keyword = ephy_bookmarks_has_keyword
                (editor->priv->bookmarks, kid,
                 editor->priv->bookmark);
        }

        priority = ephy_node_get_property_int
            (kid, EPHY_NODE_KEYWORD_PROP_PRIORITY);
        if (priority == -1) priority = EPHY_NODE_VIEW_NORMAL_PRIORITY;

        if (priority == EPHY_NODE_VIEW_NORMAL_PRIORITY)
        {
            gtk_list_store_append (model, &iter);
            gtk_list_store_set (model, &iter,
                        COL_HAS_TOPIC, has_keyword,
                        COL_TOPIC, name,
                        COL_NODE, kid,
                        -1);
        }
    }
    ephy_node_thaw (keywords);
}

static void
topic_toggled (GtkCellRendererToggle *cell,
               char *path_str,
               EphyTopicsSelector *selector)
{
    GtkTreeModel *model = selector->priv->model;
    GtkTreePath *path = gtk_tree_path_new_from_string (path_str);
    GtkTreeIter iter;
    gboolean has_topic;

    gtk_tree_model_get_iter (model, &iter, path);
    gtk_tree_model_get (model, &iter, COL_HAS_TOPIC, &has_topic, -1);
    has_topic = !has_topic;

    gtk_list_store_set (GTK_LIST_STORE (model), &iter,
                COL_HAS_TOPIC, has_topic, -1);
    ephy_topics_selector_apply (selector);
}

void
ephy_topics_selector_apply (EphyTopicsSelector *editor)
{
    GtkTreeIter iter;
    GtkTreeModel *model = editor->priv->model;

    LOG ("Update topics")

    if (editor->priv->bookmark == NULL) return;

    gtk_tree_model_get_iter_first (model, &iter);
    do
    {
        GValue value = { 0, };
        gboolean has_topic;
        EphyNode *node;

        gtk_tree_model_get_value (model, &iter, COL_HAS_TOPIC, &value);
        has_topic = g_value_get_boolean (&value);
        g_value_unset (&value);

        gtk_tree_model_get_value (model, &iter, COL_NODE, &value);
        node = g_value_get_pointer (&value);
        g_value_unset (&value);

        if (has_topic)
        {
            ephy_bookmarks_set_keyword (editor->priv->bookmarks,
                            node,
                            editor->priv->bookmark);
        }
        else
        {
            ephy_bookmarks_unset_keyword (editor->priv->bookmarks,
                              node,
                              editor->priv->bookmark);
        }
    }
    while (gtk_tree_model_iter_next (model, &iter));
}

static gboolean
set_sort_column_id (GtkListStore *model)
{
    gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model),
                          COL_TOPIC,
                          GTK_SORT_ASCENDING);
    return FALSE;
}

static gboolean
topic_clicked (GtkTreeView *tree_view, 
        GdkEventButton *event,
        EphyTopicsSelector *selector)
{
    GtkTreePath *path;

    if (event->window != gtk_tree_view_get_bin_window (tree_view))
        return FALSE;
    
    if (gtk_tree_view_get_path_at_pos (tree_view,
                       (gint) event->x,
                       (gint) event->y,
                       &path, NULL,
                       NULL, NULL))
    {
        gchar *path_str = gtk_tree_path_to_string (path);
        topic_toggled (NULL, path_str, selector);
        g_free(path_str);
    }
    
    return FALSE;
}

static gboolean
topic_key_pressed (GtkTreeView *tree_view, 
           GdkEventKey *event,
           EphyTopicsSelector *selector)
{
    GtkTreeSelection *sel = NULL;
    GtkTreeIter iter;
    GtkTreePath *path = NULL;
    gchar *path_str;

    switch (event->keyval) 
    {
    case GDK_space:
    case GDK_Return:
    case GDK_KP_Enter:
        sel = gtk_tree_view_get_selection (tree_view);
        
        if (gtk_tree_selection_get_selected (sel, NULL, &iter))
        {
            path = gtk_tree_model_get_path (selector->priv->model, &iter);
            path_str = gtk_tree_path_to_string (path);
            topic_toggled (NULL, path_str, selector);
            g_free(path_str);
        }
        return TRUE;

    default:
        break;
    }
    
    return FALSE;   
}

static void
ephy_topics_build_ui (EphyTopicsSelector *editor)
{
    GtkListStore *model;
    GtkCellRenderer *renderer;
    GtkTreeViewColumn *column;

    model = gtk_list_store_new (3, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_POINTER);
    editor->priv->model = GTK_TREE_MODEL (model);

    gtk_tree_view_set_model (GTK_TREE_VIEW (editor), GTK_TREE_MODEL (model));
    gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (editor), FALSE);
    g_idle_add ((GSourceFunc) set_sort_column_id, model);
    g_object_unref (model);

    /* Has topic column */
    renderer = gtk_cell_renderer_toggle_new ();
    column = gtk_tree_view_column_new_with_attributes
        ("", renderer, "active", COL_HAS_TOPIC, NULL);
    gtk_tree_view_append_column (GTK_TREE_VIEW (editor), column);

    renderer = gtk_cell_renderer_text_new ();
    column = gtk_tree_view_column_new_with_attributes
        ("Description", renderer, "text", COL_TOPIC, NULL);
    gtk_tree_view_append_column (GTK_TREE_VIEW (editor), column);
    
    g_signal_connect (G_OBJECT (editor), "key_press_event",
              G_CALLBACK (topic_key_pressed), editor);
    g_signal_connect (G_OBJECT (editor), "button_press_event",
              G_CALLBACK (topic_clicked), editor);
    fill_model (editor);
}

static void
ephy_topics_selector_init (EphyTopicsSelector *editor)
{
    editor->priv = g_new0 (EphyTopicsSelectorPrivate, 1);

    editor->priv->bookmark = NULL;
}

GtkWidget *
ephy_topics_selector_new (EphyBookmarks *bookmarks,
              EphyNode *bookmark)
{
    EphyTopicsSelector *editor;

    g_assert (bookmarks != NULL);

    editor = EPHY_TOPICS_SELECTOR (g_object_new
            (EPHY_TYPE_TOPIC_SELECTOR,
             "bookmarks", bookmarks,
             "bookmark", bookmark,
             NULL));

    ephy_topics_build_ui (editor);
    
    return GTK_WIDGET (editor);
}