source: trunk/third/yelp/src/yelp-view-index.c @ 18397

Revision 18397, 14.7 KB checked in by ghudson, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18396, which included commits to RCS files with non-trunk default branches.
Line 
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2/*
3 * Copyright (C) 2001-2002 Mikael Hallendal <micke@codefactory.se>
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public
16 * License along with this program; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
19 *
20 * Author: Mikael Hallendal <micke@codefactory.se>
21 */
22
23#ifdef HAVE_CONFIG_H
24#include <config.h>
25#endif
26
27#include <atk/atk.h>
28#include <gtk/gtkaccessible.h>
29#include <gtk/gtkcellrenderertext.h>
30#include <gtk/gtkentry.h>
31#include <gtk/gtkframe.h>
32#include <gtk/gtkhbox.h>
33#include <gtk/gtkvbox.h>
34#include <gtk/gtklabel.h>
35#include <gtk/gtkscrolledwindow.h>
36#include <gtk/gtktreeview.h>
37#include <gtk/gtktreeselection.h>
38#include <libgnome/gnome-i18n.h>
39#include <string.h>
40
41#include "yelp-index-model.h"
42#include "yelp-html.h"
43#include "yelp-marshal.h"
44#include "yelp-reader.h"
45#include "yelp-view-index.h"
46
47#define d(x)
48
49static void     yvi_init                       (YelpViewIndex       *view);
50static void     yvi_class_init                 (YelpViewIndexClass  *klass);
51static void     yvi_index_selection_changed_cb (GtkTreeSelection    *selection,
52                                                YelpViewIndex       *content);
53static void     yvi_html_uri_selected_cb       (YelpHtml            *html,
54                                                YelpURI             *uri,
55                                                gboolean             handled,
56                                                YelpViewIndex       *view);
57static void     yvi_entry_changed_cb           (GtkEntry            *entry,
58                                                YelpViewIndex       *view);
59static void     yvi_entry_activated_cb         (GtkEntry            *entry,
60                                                YelpViewIndex       *view);
61static void     yvi_entry_text_inserted_cb     (GtkEntry            *entry,
62                                                const gchar         *text,
63                                                gint                 length,
64                                                gint                *position,
65                                                YelpViewIndex       *view);
66static gboolean yvi_complete_idle              (YelpViewIndex       *view);
67static gboolean yvi_filter_idle                (YelpViewIndex       *view);
68static gchar *  yvi_complete_func              (YelpSection         *section);
69static void     set_relation                   (GtkWidget           *widget,
70                                                GtkLabel            *label);
71static void     yvi_reader_data_cb             (YelpReader          *reader,
72                                                const gchar         *data,
73                                                gint                 len,
74                                                YelpViewIndex       *view);
75static void     yvi_reader_finished_cb         (YelpReader          *reader,
76                                                YelpURI             *uri,
77                                                YelpViewIndex       *view);
78
79
80struct _YelpViewIndexPriv {
81        /* List of keywords */
82        GtkWidget      *index_view;
83        YelpIndexModel *model;
84
85        /* Query entry */
86        GtkWidget      *entry;
87       
88        YelpReader     *reader;
89
90        /* Html view */
91        YelpHtml       *html_view;
92        GtkWidget      *html_widget;
93
94        GCompletion    *completion;
95
96        guint           idle_complete;
97        guint           idle_filter;
98
99        gboolean        first;
100};
101
102enum {
103        URI_SELECTED,
104        LAST_SIGNAL
105};
106
107static gint signals[LAST_SIGNAL] = { 0 };
108
109GType
110yelp_view_index_get_type (void)
111{
112        static GType view_type = 0;
113
114        if (!view_type)
115        {
116                static const GTypeInfo view_info =
117                        {
118                                sizeof (YelpViewIndexClass),
119                                NULL,
120                                NULL,
121                                (GClassInitFunc) yvi_class_init,
122                                NULL,
123                                NULL,
124                                sizeof (YelpViewIndex),
125                                0,
126                                (GInstanceInitFunc) yvi_init,
127                        };
128               
129                view_type = g_type_register_static (GTK_TYPE_HPANED,
130                                                    "YelpViewIndex",
131                                                    &view_info, 0);
132        }
133       
134        return view_type;
135}
136
137static void
138yvi_init (YelpViewIndex *view)
139{
140        YelpViewIndexPriv *priv;
141       
142        priv = g_new0 (YelpViewIndexPriv, 1);
143        view->priv = priv;
144       
145        priv->idle_complete = 0;
146        priv->idle_filter   = 0;
147
148        priv->completion =
149                g_completion_new ((GCompletionFunc) yvi_complete_func);
150
151        priv->index_view = gtk_tree_view_new ();
152        priv->model      = yelp_index_model_new ();
153
154        gtk_tree_view_set_model (GTK_TREE_VIEW (priv->index_view),
155                                 GTK_TREE_MODEL (priv->model));
156
157        priv->html_view = yelp_html_new ();
158        priv->html_widget = yelp_html_get_widget (priv->html_view);
159       
160        g_signal_connect (priv->html_view, "uri_selected",
161                          G_CALLBACK (yvi_html_uri_selected_cb),
162                          view);
163
164        priv->reader = yelp_reader_new ();
165       
166        g_signal_connect (G_OBJECT (priv->reader), "data",
167                          G_CALLBACK (yvi_reader_data_cb),
168                          view);
169        g_signal_connect (G_OBJECT (priv->reader), "finished",
170                          G_CALLBACK (yvi_reader_finished_cb),
171                          view);
172}
173
174static void
175yvi_class_init (YelpViewIndexClass *klass)
176{
177        signals[URI_SELECTED] =
178                g_signal_new ("uri_selected",
179                              G_TYPE_FROM_CLASS (klass),
180                              G_SIGNAL_RUN_LAST,
181                              G_STRUCT_OFFSET (YelpViewIndexClass,
182                                               uri_selected),
183                              NULL, NULL,
184                              yelp_marshal_VOID__POINTER_BOOLEAN,
185                              G_TYPE_NONE,
186                              2, G_TYPE_POINTER, G_TYPE_BOOLEAN);
187}
188
189static void
190yvi_index_selection_changed_cb (GtkTreeSelection *selection,
191                                YelpViewIndex    *view)
192{
193        YelpViewIndexPriv *priv;
194        GtkTreeIter        iter;
195        YelpSection       *section;
196       
197        g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
198        g_return_if_fail (YELP_IS_VIEW_INDEX (view));
199
200        priv = view->priv;
201
202        if (gtk_tree_selection_get_selected (selection, NULL, &iter)) {
203                YelpURI *index_uri;
204               
205                gtk_tree_model_get (GTK_TREE_MODEL (priv->model), &iter,
206                                    YELP_INDEX_MODEL_COL_SECTION, &section,
207                                    -1);
208
209                d(g_print ("Index View: selection changed: %s\n",
210                           yelp_uri_to_string (section->uri)));
211               
212                index_uri = yelp_uri_to_index (section->uri);
213
214                g_signal_emit (view, signals[URI_SELECTED], 0,
215                               index_uri, FALSE);
216
217                yelp_uri_unref (index_uri);
218        }
219}
220
221static void
222yvi_html_uri_selected_cb (YelpHtml      *html,
223                          YelpURI       *uri,
224                          gboolean       handled,
225                          YelpViewIndex *view)
226{
227        YelpURI *index_uri;
228
229        g_return_if_fail (YELP_IS_VIEW_INDEX (view));
230
231        d(g_print ("Index View: uri selected: %s\n",
232                   yelp_uri_to_string (uri)));
233
234        index_uri = yelp_uri_to_index (uri);
235        g_signal_emit (view, signals[URI_SELECTED], 0, index_uri, handled);
236        yelp_uri_unref (index_uri);
237}
238
239static void
240yvi_entry_changed_cb (GtkEntry *entry, YelpViewIndex *view)
241{
242        YelpViewIndexPriv *priv;
243       
244        g_return_if_fail (GTK_IS_ENTRY (entry));
245        g_return_if_fail (YELP_IS_VIEW_INDEX (view));
246       
247        priv = view->priv;
248 
249        d(g_print ("Entry changed\n"));
250
251        if (!priv->idle_filter) {
252                priv->idle_filter =
253                        g_idle_add ((GSourceFunc) yvi_filter_idle, view);
254        }
255}
256
257static void
258yvi_entry_activated_cb (GtkEntry *entry, YelpViewIndex *view)
259{
260        YelpViewIndexPriv *priv;
261        gchar             *str;
262       
263        g_return_if_fail (GTK_IS_ENTRY (entry));
264        g_return_if_fail (YELP_IS_VIEW_INDEX (view));
265
266        priv = view->priv;
267       
268        str = (gchar *) gtk_entry_get_text (GTK_ENTRY (priv->entry));
269       
270        yelp_index_model_filter (view->priv->model, str);
271}
272
273static void
274yvi_entry_text_inserted_cb (GtkEntry      *entry,
275                            const gchar   *text,
276                            gint           length,
277                            gint          *position,
278                            YelpViewIndex *view)
279{
280        YelpViewIndexPriv *priv;
281       
282        g_return_if_fail (YELP_IS_VIEW_INDEX (view));
283       
284        priv = view->priv;
285       
286        if (!priv->idle_complete) {
287                priv->idle_complete =
288                        g_idle_add ((GSourceFunc) yvi_complete_idle, view);
289        }
290}
291
292static gboolean
293yvi_complete_idle (YelpViewIndex *view)
294{
295        YelpViewIndexPriv *priv;
296        const gchar       *text;
297        gchar             *completed = NULL;
298        GList             *list;
299        gint               text_length;
300       
301        g_return_val_if_fail (YELP_IS_VIEW_INDEX (view), FALSE);
302       
303        priv = view->priv;
304       
305        text = gtk_entry_get_text (GTK_ENTRY (priv->entry));
306
307        list = g_completion_complete (priv->completion,
308                                      (gchar *)text,
309                                      &completed);
310
311        if (completed) {
312                text_length = strlen (text);
313               
314                gtk_entry_set_text (GTK_ENTRY (priv->entry), completed);
315                gtk_editable_set_position (GTK_EDITABLE (priv->entry),
316                                           text_length);
317                gtk_editable_select_region (GTK_EDITABLE (priv->entry),
318                                            text_length, -1);
319        }
320       
321        priv->idle_complete = 0;
322
323        return FALSE;
324}
325
326static gboolean
327yvi_filter_idle (YelpViewIndex *view)
328{
329        YelpViewIndexPriv *priv;
330        gchar             *str;
331       
332        g_return_val_if_fail (YELP_IS_VIEW_INDEX (view), FALSE);
333
334        priv = view->priv;
335
336        d(g_print ("Filter idle\n"));
337       
338        str = (gchar *) gtk_entry_get_text (GTK_ENTRY (priv->entry));
339       
340        yelp_index_model_filter (view->priv->model, str);
341
342        priv->idle_filter = 0;
343
344        return FALSE;
345}
346
347static gchar *
348yvi_complete_func (YelpSection *section)
349{
350        return section->name;
351}
352
353/**
354 * set_relation
355 * @widget : The Gtk widget which is labelled by @label
356 * @label : The label for the @widget.
357 * Description : This function establishes atk relation
358 * between a gtk widget and a label.
359 */
360
361static void
362set_relation (GtkWidget *widget, GtkLabel *label)
363{
364        AtkObject      *aobject;
365        AtkRelationSet *relation_set;
366        AtkRelation    *relation;
367        AtkObject      *targets[1];
368
369        g_return_if_fail (GTK_IS_WIDGET (widget));
370        g_return_if_fail (GTK_IS_LABEL (label));
371
372        aobject = gtk_widget_get_accessible (widget);
373
374        /* Return if GAIL is not loaded */
375        if (! GTK_IS_ACCESSIBLE (aobject)) {
376                return;
377        }
378       
379        /* Set the ATK_RELATION_LABEL_FOR relation */
380        gtk_label_set_mnemonic_widget (label, widget);
381
382        targets[0] = gtk_widget_get_accessible (GTK_WIDGET (label));
383
384        relation_set = atk_object_ref_relation_set (aobject);
385
386        relation = atk_relation_new (targets, 1, ATK_RELATION_LABELLED_BY);
387        atk_relation_set_add (relation_set, relation);
388        g_object_unref (G_OBJECT (relation));
389}
390
391static void
392yvi_reader_data_cb (YelpReader    *reader,
393                    const gchar   *data,
394                    gint           len,
395                    YelpViewIndex *view)
396{
397        YelpViewIndexPriv *priv;
398       
399        g_return_if_fail (YELP_IS_READER (reader));
400        g_return_if_fail (YELP_IS_VIEW_INDEX (view));
401       
402        priv = view->priv;
403
404        if (priv->first) {
405                yelp_html_clear (priv->html_view);
406                priv->first = FALSE;
407        }
408
409        if (len == -1) {
410                len = strlen (data);
411        }
412
413        if (len <= 0) {
414                return;
415        }
416
417        yelp_html_write (priv->html_view, data, len);
418}
419
420static void
421yvi_reader_finished_cb (YelpReader    *reader,
422                        YelpURI       *uri,
423                        YelpViewIndex *view)
424{
425        YelpViewIndexPriv *priv;
426       
427        g_return_if_fail (YELP_IS_READER (reader));
428        g_return_if_fail (YELP_IS_VIEW_INDEX (view));
429
430        priv = view->priv;
431 
432        if (!priv->first) {
433                yelp_html_close (priv->html_view);
434        }
435       
436        gdk_window_set_cursor (priv->html_widget->window, NULL);
437        gtk_widget_grab_focus (priv->html_widget);
438}
439
440GtkWidget *
441yelp_view_index_new (GList *index)
442{
443        YelpViewIndex     *view;
444        YelpViewIndexPriv *priv;
445        GtkTreeSelection  *selection;
446        GtkWidget         *html_sw;
447        GtkWidget         *list_sw;
448        GtkWidget         *frame;
449        GtkWidget         *box;
450        GtkWidget         *hbox;
451        GtkWidget         *label;
452               
453        view = g_object_new (YELP_TYPE_VIEW_INDEX, NULL);
454        priv = view->priv;
455
456        /* Setup the index box */
457        box = gtk_vbox_new (FALSE, 0);
458
459        hbox = gtk_hbox_new (FALSE, 0);
460       
461        label = gtk_label_new (_("Search for:"));
462
463        gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 4);
464
465        priv->entry = gtk_entry_new ();
466
467        set_relation (priv->entry, GTK_LABEL (label));
468
469        g_signal_connect (priv->entry, "changed",
470                          G_CALLBACK (yvi_entry_changed_cb),
471                          view);
472
473        gtk_box_pack_end (GTK_BOX (hbox), priv->entry, FALSE, FALSE, 0);
474       
475        g_signal_connect (priv->entry, "activate",
476                          G_CALLBACK (yvi_entry_activated_cb),
477                          view);
478       
479        g_signal_connect (priv->entry, "insert-text",
480                          G_CALLBACK (yvi_entry_text_inserted_cb),
481                          view);
482
483        gtk_box_pack_start (GTK_BOX (box), hbox,
484                            FALSE, FALSE, 0);
485
486        frame = gtk_frame_new (NULL);
487        gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
488       
489        list_sw = gtk_scrolled_window_new (NULL, NULL);
490        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (list_sw),
491                                        GTK_POLICY_AUTOMATIC,
492                                        GTK_POLICY_AUTOMATIC);
493
494        gtk_container_add (GTK_CONTAINER (frame), list_sw);
495       
496        gtk_tree_view_insert_column_with_attributes (
497                GTK_TREE_VIEW (priv->index_view), -1,
498                _("Section"), gtk_cell_renderer_text_new (),
499                "text", 0,
500                NULL);
501
502        gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (priv->index_view),
503                                           FALSE);
504
505        selection = gtk_tree_view_get_selection (
506                GTK_TREE_VIEW (priv->index_view));
507
508        g_signal_connect (selection, "changed",
509                          G_CALLBACK (yvi_index_selection_changed_cb),
510                          view);
511       
512        gtk_container_add (GTK_CONTAINER (list_sw), priv->index_view);
513
514        gtk_box_pack_end_defaults (GTK_BOX (box), frame);
515
516        /* Setup the Html view */
517        html_sw = gtk_scrolled_window_new (NULL, NULL);
518        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (html_sw),
519                                        GTK_POLICY_AUTOMATIC,
520                                        GTK_POLICY_AUTOMATIC);
521        frame = gtk_frame_new (NULL);
522        gtk_container_add (GTK_CONTAINER (frame), html_sw);
523        gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
524       
525        gtk_container_add (GTK_CONTAINER (html_sw), priv->html_widget);
526
527        /* Add the tree and html view to the paned */
528        gtk_paned_add1 (GTK_PANED (view), box);
529        gtk_paned_add2 (GTK_PANED (view), frame);
530        gtk_paned_set_position (GTK_PANED (view), 250);
531 
532        d(g_print ("List length: %d\n", g_list_length (index)));
533       
534        g_completion_add_items (priv->completion, index);
535        yelp_index_model_set_words (priv->model, index);
536
537        return GTK_WIDGET (view);
538}
539
540void
541yelp_view_index_show_uri (YelpViewIndex  *view,
542                          YelpURI        *index_uri,
543                          GError        **error)
544{
545        YelpViewIndexPriv *priv;
546        YelpURI           *uri;
547
548        g_return_if_fail (YELP_IS_VIEW_INDEX (view));
549        g_return_if_fail (index_uri != NULL);
550       
551        priv = view->priv;
552
553        d(g_print ("Index show Uri: %s\n", yelp_uri_to_string (index_uri)));
554
555        if (yelp_uri_no_path (index_uri)) {
556                return;
557        }
558
559        uri = yelp_uri_from_index (index_uri);
560
561        priv->first = TRUE;
562
563        yelp_html_set_base_uri (priv->html_view, uri);
564
565        if (!yelp_reader_start (priv->reader, uri)) {
566                gchar     *loading = _("Loading...");
567
568                yelp_html_clear (priv->html_view);
569
570                yelp_html_printf (priv->html_view,
571                                  "<html><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"><title>..</title><body><center>%s</center></body></html>",
572                                  loading);
573                yelp_html_close (priv->html_view);
574        }
575
576        /* FIXME: Handle the GError */
577/*      yelp_html_open_uri (priv->html_view, uri, error); */
578}
579
Note: See TracBrowser for help on using the repository browser.