~swem/totem/assignment

« back to all changes in this revision

Viewing changes to src/plugins/tracker/totem-tracker-widget.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastian Dröge
  • Date: 2010-01-27 09:40:18 UTC
  • mfrom: (1.4.2 upstream) (5.1.13 sid)
  • Revision ID: james.westby@ubuntu.com-20100127094018-q6rzt7va0y8ketwt
Tags: 2.29.4-1
* New upstream development release:
  + debian/patches/90_autotools.patch:
    - Refreshed for the new version.
  + debian/control.in:
    - Update build dependencies and dependencies.
    - Drop tracker plugin, it needs tracker 0.7.
  + debian/totem-mozilla.links:
    - Drop the complex plugin, it doesn't exist anymore.

Show diffs side-by-side

added added

removed removed

Lines of Context:
31
31
#include <glib/gi18n-lib.h>
32
32
#include <gio/gio.h>
33
33
#include <dbus/dbus.h>
34
 
#include <tracker.h>
 
34
#include <libtracker-client/tracker.h>
35
35
 
36
36
#include "totem-tracker-widget.h"
37
37
#include "totem-cell-renderer-video.h"
39
39
#include "totem-video-list.h"
40
40
#include "totem-interface.h"
41
41
 
42
 
#define TRACKER_SERVICE                 "org.freedesktop.Tracker"
43
 
#define TRACKER_OBJECT                  "/org/freedesktop/tracker"
44
 
#define TRACKER_INTERFACE               "org.freedesktop.Tracker.Search"
45
42
#define TOTEM_TRACKER_MAX_RESULTS_SIZE  20
46
43
 
47
44
G_DEFINE_TYPE (TotemTrackerWidget, totem_tracker_widget, GTK_TYPE_VBOX)
55
52
        GtkWidget *previous_button;
56
53
        GtkWidget *page_selector;
57
54
 
58
 
        int total_result_count;
59
 
        int current_result_page;
 
55
        guint total_result_count;
 
56
        guint current_result_page;
60
57
 
61
58
        GtkListStore *result_store;
62
59
        TotemVideoList *result_list;
63
60
};
64
61
 
 
62
typedef struct {
 
63
        TotemTrackerWidget *widget;
 
64
        TrackerClient *client;
 
65
        gchar *search_text;
 
66
        guint cookie;
 
67
} SearchResultsData;
 
68
 
65
69
enum {
66
70
        IMAGE_COLUMN,
67
71
        FILE_COLUMN,
132
136
}
133
137
 
134
138
static void
135
 
populate_result (TotemTrackerWidget *widget, char *result)
136
 
{
137
 
        GtkTreeIter iter;
 
139
search_results_populate (TotemTrackerWidget *widget, 
 
140
                         const gchar        *uri)
 
141
{       
138
142
        GFile *file;
139
143
        GFileInfo *info;
140
144
        GError *error = NULL;
141
 
        GdkPixbuf *thumbnail = NULL;
142
 
        const char *thumbnail_path;
143
 
        char *file_uri;
144
145
 
145
 
        file = g_file_new_for_path (result);
 
146
        file = g_file_new_for_uri (uri);
146
147
        info = g_file_query_info (file, "standard::display-name,thumbnail::path", G_FILE_QUERY_INFO_NONE, NULL, &error);
147
148
 
148
149
        if (error == NULL) {
 
150
                GtkTreeIter iter;
 
151
                GdkPixbuf *thumbnail = NULL;
 
152
                const gchar *thumbnail_path;
 
153
 
149
154
                gtk_list_store_append (GTK_LIST_STORE (widget->priv->result_store), &iter);  /* Acquire an iterator */
150
 
                file_uri = g_file_get_uri (file);
151
155
                thumbnail_path = g_file_info_get_attribute_byte_string (info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH);
152
156
 
153
157
                if (thumbnail_path != NULL)
155
159
 
156
160
                gtk_list_store_set (GTK_LIST_STORE (widget->priv->result_store), &iter,
157
161
                                    IMAGE_COLUMN, thumbnail,
158
 
                                    FILE_COLUMN, file_uri,
 
162
                                    FILE_COLUMN, uri,
159
163
                                    NAME_COLUMN, g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME),
160
164
                                    -1);
161
165
 
162
 
                g_free (file_uri);
163
166
                if (thumbnail != NULL)
164
167
                        g_object_unref (thumbnail);
165
168
        } else {
166
169
                /* Display an error */
167
 
                char *message = g_strdup_printf (_("Could not get metadata for file %s: %s"), result, error->message);
 
170
                gchar *message = g_strdup_printf (_("Could not get name and thumbnail for %s: %s"), uri, error->message);
168
171
                totem_interface_error_blocking  (_("File Error"), message, NULL);
169
172
                g_free (message);
170
173
                g_error_free (error);
174
177
        g_object_unref (file);
175
178
}
176
179
 
177
 
static int
178
 
get_search_count (TrackerClient *client, const char *search)
179
 
{
180
 
        GError *error = NULL;
181
 
        int count = 0;
182
 
 
183
 
        dbus_g_proxy_call (client->proxy_search, "GetHitCount", &error, G_TYPE_STRING, "Videos", 
184
 
                           G_TYPE_STRING, search,
185
 
                           G_TYPE_INVALID, G_TYPE_INT, &count, G_TYPE_INVALID);
 
180
static SearchResultsData *
 
181
search_results_new (TotemTrackerWidget *widget,
 
182
                    const gchar        *search_text)
 
183
{
 
184
        SearchResultsData *srd;
 
185
        TrackerClient *client;
 
186
 
 
187
        if (!widget) {
 
188
                return NULL;
 
189
        }
 
190
 
 
191
        client = tracker_connect (TRUE, G_MAXINT);
 
192
        if (!client) {
 
193
                return NULL;
 
194
        }
 
195
 
 
196
        srd = g_slice_new0 (SearchResultsData);
 
197
 
 
198
        srd->widget = g_object_ref (widget);
 
199
        srd->client = client;
 
200
        srd->search_text = g_strdup (search_text);
 
201
 
 
202
        return srd;
 
203
}
 
204
 
 
205
static void
 
206
search_results_free (SearchResultsData *srd)
 
207
{
 
208
        if (!srd) {
 
209
                return;
 
210
        }
 
211
 
 
212
        if (srd->widget) {
 
213
                g_object_unref (srd->widget);
 
214
        }
 
215
 
 
216
        if (srd->client) {
 
217
                tracker_disconnect (srd->client);
 
218
        }
 
219
 
 
220
        g_free (srd->search_text);
 
221
        g_slice_free (SearchResultsData, srd);
 
222
}
 
223
 
 
224
static void
 
225
search_results_cb (GPtrArray *results, 
 
226
                   GError    *error, 
 
227
                   gpointer   userdata)
 
228
{
 
229
        TotemTrackerWidgetPrivate *priv;
 
230
        SearchResultsData *srd;
 
231
        gchar *str;
 
232
        guint i, next_page, total_pages;
 
233
 
 
234
        srd = userdata;
 
235
        priv = srd->widget->priv;
 
236
 
 
237
        gtk_widget_set_sensitive (priv->search_entry, TRUE);
186
238
 
187
239
        if (error) {
188
 
                g_warning ("%s", error->message);
189
 
                g_error_free (error);
190
 
                return -1;
191
 
        }
192
 
 
193
 
        return count;
 
240
                g_warning ("Error getting the search results for '%s': %s", 
 
241
                           srd->search_text, 
 
242
                           error->message ? error->message : "No reason");
 
243
 
 
244
                gtk_label_set_text (GTK_LABEL (priv->status_label), _("Could not connect to Tracker"));
 
245
                search_results_free (srd);
 
246
 
 
247
                return;
 
248
        }
 
249
 
 
250
        if (!results || results->len < 1) {
 
251
                gtk_label_set_text (GTK_LABEL (priv->status_label), _("No results"));
 
252
                search_results_free (srd);
 
253
 
 
254
                return;
 
255
        }
 
256
 
 
257
        for (i = 0; i < results->len; i++) {
 
258
                GStrv details;
 
259
 
 
260
                details = g_ptr_array_index (results, i);
 
261
                search_results_populate (srd->widget, details[0]);
 
262
        }
 
263
        
 
264
        next_page = (priv->current_result_page + 1) * TOTEM_TRACKER_MAX_RESULTS_SIZE;
 
265
        total_pages = priv->total_result_count / TOTEM_TRACKER_MAX_RESULTS_SIZE + 1;
 
266
        
 
267
        /* Set the new range on the page selector's adjustment and ensure the current page is correct */
 
268
        gtk_spin_button_set_range (GTK_SPIN_BUTTON (priv->page_selector), 1, total_pages);
 
269
        priv->current_result_page = gtk_spin_button_get_value (GTK_SPIN_BUTTON (priv->page_selector)) - 1;
 
270
        
 
271
        /* Translators:
 
272
         * This is used to show which items are listed in the list view, for example:
 
273
         * Showing 10-20 of 128 matches
 
274
         * This is similar to what web searches use, eg. Google on the top-right of their search results page show:
 
275
         * Personalized Results 1 - 10 of about 4,130,000 for foobar */
 
276
        str = g_strdup_printf (ngettext ("Showing %i - %i of %i match", "Showing %i - %i of %i matches", priv->total_result_count),
 
277
                               priv->current_result_page * TOTEM_TRACKER_MAX_RESULTS_SIZE, 
 
278
                               next_page > priv->total_result_count ? priv->total_result_count : next_page,
 
279
                               priv->total_result_count);
 
280
        gtk_label_set_text (GTK_LABEL (priv->status_label), str);
 
281
        g_free (str);
 
282
        
 
283
        /* Enable or disable the pager buttons */
 
284
        if (priv->current_result_page < priv->total_result_count / TOTEM_TRACKER_MAX_RESULTS_SIZE) {
 
285
                gtk_widget_set_sensitive (GTK_WIDGET (priv->page_selector), TRUE);
 
286
                gtk_widget_set_sensitive (GTK_WIDGET (priv->next_button), TRUE);
 
287
        }
 
288
        
 
289
        if (priv->current_result_page > 0) {
 
290
                gtk_widget_set_sensitive (GTK_WIDGET (priv->page_selector), TRUE);
 
291
                gtk_widget_set_sensitive (GTK_WIDGET (priv->previous_button), TRUE);
 
292
        }
 
293
 
 
294
        if (priv->current_result_page >= total_pages - 1) {
 
295
                gtk_widget_set_sensitive (GTK_WIDGET (priv->next_button), FALSE);
 
296
        }
 
297
        
 
298
        g_signal_handlers_unblock_by_func (priv->page_selector, page_selector_value_changed_cb, srd->widget);
 
299
        search_results_free (srd);
194
300
}
195
301
 
196
 
struct SearchResultsData {
197
 
        TotemTrackerWidget *widget;
198
 
        char *search_text;
199
 
        TrackerClient *client;
200
 
};
201
 
 
202
 
static void
203
 
search_results_cb (char **result, GError *error, gpointer userdata)
 
302
static gchar *
 
303
get_fts_string (GStrv    search_words,
 
304
                gboolean use_or_operator)
204
305
{
205
 
        struct SearchResultsData *data = (struct SearchResultsData*) userdata;
206
 
        char *label;
207
 
        int i, next_page;
208
 
        TotemTrackerWidgetPrivate *priv = data->widget->priv;
209
 
 
210
 
        if (!error && result) {
211
 
                for (i = 0; result [i] != NULL; i++)
212
 
                        populate_result (data->widget, result [i]);
213
 
        
214
 
                next_page = (priv->current_result_page + 1) * TOTEM_TRACKER_MAX_RESULTS_SIZE;
215
 
 
216
 
                /* Set the new range on the page selector's adjustment and ensure the current page is correct */
217
 
                gtk_spin_button_set_range (GTK_SPIN_BUTTON (priv->page_selector), 1,
218
 
                                           priv->total_result_count / TOTEM_TRACKER_MAX_RESULTS_SIZE + 1);
219
 
                priv->current_result_page = gtk_spin_button_get_value (GTK_SPIN_BUTTON (priv->page_selector)) - 1;
220
 
 
221
 
                if (priv->total_result_count == 0) {
222
 
                        gtk_label_set_text (GTK_LABEL (priv->status_label), _("No results"));
223
 
                } else {
224
 
                        /* Translators:
225
 
                         * This is used to show which items are listed in the list view, for example:
226
 
                         * Showing 10-20 of 128 matches
227
 
                         * This is similar to what web searches use, eg. Google on the top-right of their search results page show:
228
 
                         * Personalized Results 1 - 10 of about 4,130,000 for foobar */
229
 
                        label = g_strdup_printf (ngettext ("Showing %i - %i of %i match", "Showing %i - %i of %i matches", priv->total_result_count),
230
 
                                                 priv->current_result_page * TOTEM_TRACKER_MAX_RESULTS_SIZE, 
231
 
                                                 next_page > priv->total_result_count ? priv->total_result_count : next_page,
232
 
                                                 priv->total_result_count);
233
 
                        gtk_label_set_text (GTK_LABEL (priv->status_label), label);
234
 
                        g_free (label);
235
 
                }
236
 
 
237
 
                /* Enable or disable the pager buttons */
238
 
                if (priv->current_result_page < priv->total_result_count / TOTEM_TRACKER_MAX_RESULTS_SIZE) {
239
 
                        gtk_widget_set_sensitive (GTK_WIDGET (priv->page_selector), TRUE);
240
 
                        gtk_widget_set_sensitive (GTK_WIDGET (priv->next_button), TRUE);
241
 
                }
242
 
 
243
 
                if (priv->current_result_page > 0) {
244
 
                        gtk_widget_set_sensitive (GTK_WIDGET (priv->page_selector), TRUE);
245
 
                        gtk_widget_set_sensitive (GTK_WIDGET (priv->previous_button), TRUE);
246
 
                }
247
 
 
248
 
                g_signal_handlers_unblock_by_func (priv->page_selector, page_selector_value_changed_cb, data->widget);
249
 
        } else {
250
 
                g_warning ("Error getting the search results for '%s': %s", data->search_text, error->message ? error->message : "No reason");
251
 
        }
252
 
 
253
 
        g_free (data->search_text);
254
 
        tracker_disconnect (data->client);
255
 
        g_free (data);
 
306
        GString *fts;
 
307
        gint i, len;
 
308
 
 
309
        if (!search_words) {
 
310
                return NULL;
 
311
        }
 
312
 
 
313
        fts = g_string_new ("");
 
314
        len = g_strv_length (search_words);
 
315
 
 
316
        for (i = 0; i < len; i++) {
 
317
                g_string_append (fts, search_words[i]);
 
318
                g_string_append_c (fts, '*');
 
319
 
 
320
                if (i < len - 1) { 
 
321
                        if (use_or_operator) {
 
322
                                g_string_append (fts, " OR ");
 
323
                        } else {
 
324
                                g_string_append (fts, " ");
 
325
                        }
 
326
                }
 
327
        }
 
328
 
 
329
        return g_string_free (fts, FALSE);
256
330
}
257
331
 
258
332
static void
259
333
do_search (TotemTrackerWidget *widget)
260
334
{
261
 
        TrackerClient *client;
262
 
        struct SearchResultsData *data;
 
335
        SearchResultsData *srd;
 
336
        GPtrArray *results;
 
337
        GError *error = NULL;
 
338
        const gchar *search_text;
 
339
        gchar *fts, *query;
 
340
        guint offset;
263
341
 
264
342
        /* Clear the list store */
265
343
        gtk_list_store_clear (GTK_LIST_STORE (widget->priv->result_store));
270
348
        gtk_widget_set_sensitive (GTK_WIDGET (widget->priv->next_button), FALSE);
271
349
 
272
350
        /* Stop after clearing the list store if they're just emptying the search entry box */
273
 
        if (strcmp (gtk_entry_get_text (GTK_ENTRY (widget->priv->search_entry)), "") == 0) {
274
 
                gtk_label_set_text (GTK_LABEL (widget->priv->status_label), _("No results"));
275
 
                return;
276
 
        }
 
351
        search_text = gtk_entry_get_text (GTK_ENTRY (widget->priv->search_entry));
277
352
 
278
353
        g_signal_handlers_block_by_func (widget->priv->page_selector, page_selector_value_changed_cb, widget);
279
354
 
280
355
        /* Get the tracker client */
281
 
        client = tracker_connect (TRUE);
282
 
        if (!client) {
283
 
                g_warning ("Error trying to get the Tracker client.");
 
356
        srd = search_results_new (widget, search_text);
 
357
        if (!srd) {
 
358
                gtk_label_set_text (GTK_LABEL (widget->priv->status_label), _("Could not connect to Tracker"));
284
359
                return;
285
360
        }
286
361
 
287
 
        data = g_new0 (struct SearchResultsData, 1);
288
 
        data->widget = widget;
289
 
        data->client = client;
290
 
 
291
 
        /* Search text */
292
 
        data->search_text = g_strdup (gtk_entry_get_text (GTK_ENTRY (widget->priv->search_entry)));
293
 
 
294
 
        widget->priv->total_result_count = get_search_count (client, data->search_text);
295
 
 
296
 
        tracker_search_text_async (data->client, -1, SERVICE_VIDEOS, data->search_text, 
297
 
                                   widget->priv->current_result_page * TOTEM_TRACKER_MAX_RESULTS_SIZE, 
298
 
                                   TOTEM_TRACKER_MAX_RESULTS_SIZE, 
299
 
                                   search_results_cb, data);
 
362
        offset = widget->priv->current_result_page * TOTEM_TRACKER_MAX_RESULTS_SIZE;
 
363
 
 
364
        if (search_text && search_text[0] != '\0') {
 
365
                GStrv strv;
 
366
 
 
367
                strv = g_strsplit (search_text, " ", -1);
 
368
                fts = get_fts_string (strv, FALSE);
 
369
                g_strfreev (strv);
 
370
        } else {
 
371
                fts = NULL;
 
372
        }
 
373
 
 
374
        /* NOTE: We use FILTERS here for the type because we may want
 
375
         * to show more items than just videos in the future - like
 
376
         * music or some other specialised content.
 
377
         */
 
378
        if (fts) {
 
379
                query = g_strdup_printf ("SELECT COUNT(?urn) AS items "
 
380
                                         "WHERE {"
 
381
                                         "  ?urn a ?type ."
 
382
                                         "  ?urn fts:match \"%s\" "
 
383
                                         "  FILTER (?type = nmm:Video) "
 
384
                                         "}",
 
385
                                         fts);
 
386
        } else {
 
387
                query = g_strdup_printf ("SELECT COUNT(?urn) AS items "
 
388
                                         "WHERE {"
 
389
                                         "  ?urn a ?type ."
 
390
                                         "  FILTER (?type = nmm:Video) "
 
391
                                         "}");
 
392
        }
 
393
 
 
394
        results = tracker_resources_sparql_query (srd->client, query, &error);
 
395
        g_free (query);
 
396
 
 
397
        if (results && results->pdata && results->pdata[0]) {
 
398
                GStrv count;
 
399
 
 
400
                count = g_ptr_array_index (results, 0);
 
401
                widget->priv->total_result_count = atoi (count[0]);
 
402
        } else {
 
403
                widget->priv->total_result_count = 0;
 
404
 
 
405
                g_warning ("Could not get count for videos available, %s",
 
406
                           error ? error->message : "no error given"); 
 
407
                g_clear_error (&error);
 
408
        }
 
409
 
 
410
        if (fts) {
 
411
                query = g_strdup_printf ("SELECT ?urn "
 
412
                                         "WHERE {"
 
413
                                         "  ?urn a ?type ."
 
414
                                         "  ?urn fts:match \"%s\" "
 
415
                                         "  FILTER (?type = nmm:Video) "
 
416
                                         "} "
 
417
                                         "ORDER BY ASC(?urn) "
 
418
                                         "OFFSET %d "
 
419
                                         "LIMIT %d",
 
420
                                         fts,
 
421
                                         offset,
 
422
                                         TOTEM_TRACKER_MAX_RESULTS_SIZE);
 
423
        } else {
 
424
                query = g_strdup_printf ("SELECT ?urn "
 
425
                                         "WHERE {"
 
426
                                         "  ?urn a ?type ."
 
427
                                         "  FILTER (?type = nmm:Video) "
 
428
                                         "} "
 
429
                                         "ORDER BY ASC(?urn) "
 
430
                                         "OFFSET %d "
 
431
                                         "LIMIT %d",
 
432
                                         offset,
 
433
                                         TOTEM_TRACKER_MAX_RESULTS_SIZE);
 
434
        }
 
435
 
 
436
        g_free (fts);
 
437
 
 
438
        gtk_widget_set_sensitive (widget->priv->search_entry, FALSE);
 
439
 
 
440
        /* Cookie is used for cancelling */
 
441
        srd->cookie = tracker_resources_sparql_query_async (srd->client, 
 
442
                                                            query, 
 
443
                                                            search_results_cb, 
 
444
                                                            srd);
 
445
        g_free (query);
300
446
}
301
447
 
302
448
static void
371
517
}
372
518
 
373
519
static void
 
520
search_entry_changed_cb (GtkWidget *entry,
 
521
                         gpointer   user_data)
 
522
{
 
523
        TotemTrackerWidget *widget = user_data;
 
524
 
 
525
        gtk_label_set_text (GTK_LABEL (widget->priv->status_label), "");
 
526
}
 
527
 
 
528
static void
374
529
totem_tracker_widget_init (TotemTrackerWidget *widget)
375
530
{
376
531
        GtkWidget *v_box;               /* the main vertical box of the widget */
 
532
        GtkWidget *h_box;
377
533
        GtkWidget *pager_box;           /* box that holds the next and previous buttons */
378
534
        GtkScrolledWindow *scroll;      /* make the result list scrollable */
379
535
        GtkAdjustment *adjust;          /* adjustment for the page selector spin button */
383
539
        init_result_list (widget);
384
540
 
385
541
        v_box = gtk_vbox_new (FALSE, 6);
 
542
        h_box = gtk_hbox_new (FALSE, 6);
386
543
 
387
544
        /* Search entry */
388
545
        widget->priv->search_entry = gtk_entry_new ();
389
546
 
390
547
        /* Search button */
391
548
        widget->priv->search_button = gtk_button_new_from_stock (GTK_STOCK_FIND);
392
 
        gtk_box_pack_start (GTK_BOX (v_box), widget->priv->search_entry, FALSE, TRUE, 0);
393
 
        gtk_box_pack_start (GTK_BOX (v_box), widget->priv->search_button, FALSE, TRUE, 0);
 
549
        gtk_box_pack_start (GTK_BOX (h_box), widget->priv->search_entry, TRUE, TRUE, 0);
 
550
        gtk_box_pack_start (GTK_BOX (h_box), widget->priv->search_button, FALSE, TRUE, 0);
 
551
        gtk_box_pack_start (GTK_BOX (v_box), h_box, FALSE, TRUE, 0);
394
552
 
395
553
        /* Insert the result list and initialize the viewport */
396
554
        scroll = GTK_SCROLLED_WINDOW (gtk_scrolled_window_new (NULL, NULL));
398
556
        gtk_scrolled_window_add_with_viewport (scroll, GTK_WIDGET (widget->priv->result_list));
399
557
        gtk_container_add (GTK_CONTAINER (v_box), GTK_WIDGET (scroll));
400
558
 
 
559
        /* Status label */
 
560
        widget->priv->status_label = gtk_label_new ("");
 
561
        gtk_misc_set_alignment (GTK_MISC (widget->priv->status_label), 0.0, 0.5);
 
562
        gtk_box_pack_start (GTK_BOX (v_box), widget->priv->status_label, FALSE, TRUE, 2);
 
563
 
401
564
        /* Initialise the pager box */
402
 
        pager_box = gtk_hbox_new (FALSE, 2);
 
565
        pager_box = gtk_hbox_new (FALSE, 6);
403
566
        widget->priv->next_button = gtk_button_new_from_stock (GTK_STOCK_GO_FORWARD);
404
567
        widget->priv->previous_button = gtk_button_new_from_stock (GTK_STOCK_GO_BACK);
405
568
        adjust = GTK_ADJUSTMENT (gtk_adjustment_new (1, 1, 1, 1, 5, 0));
406
569
        widget->priv->page_selector = gtk_spin_button_new (adjust, 1, 0);
407
 
        gtk_box_pack_start (GTK_BOX (pager_box), widget->priv->previous_button, FALSE, FALSE, 2);
408
 
        gtk_box_pack_start (GTK_BOX (pager_box), gtk_label_new (_("Page")), FALSE, FALSE, 2);
409
 
        gtk_box_pack_start (GTK_BOX (pager_box), widget->priv->page_selector, TRUE, TRUE, 2);
410
 
        gtk_box_pack_start (GTK_BOX (pager_box), widget->priv->next_button, FALSE, FALSE, 2);
411
 
        gtk_box_pack_start (GTK_BOX (v_box), pager_box, FALSE, FALSE, 2);
 
570
        gtk_box_pack_start (GTK_BOX (pager_box), widget->priv->previous_button, TRUE, TRUE, 0);
 
571
        gtk_box_pack_start (GTK_BOX (pager_box), gtk_label_new (_("Page")), TRUE, TRUE, 0);
 
572
        gtk_box_pack_start (GTK_BOX (pager_box), widget->priv->page_selector, TRUE, TRUE, 0);
 
573
        gtk_box_pack_start (GTK_BOX (pager_box), widget->priv->next_button, TRUE, TRUE, 0);
 
574
        gtk_box_pack_start (GTK_BOX (v_box), pager_box, FALSE, TRUE, 0);
412
575
 
413
576
        gtk_widget_set_sensitive (GTK_WIDGET (widget->priv->previous_button), FALSE);
414
577
        gtk_widget_set_sensitive (GTK_WIDGET (widget->priv->page_selector), FALSE);
415
578
        gtk_widget_set_sensitive (GTK_WIDGET (widget->priv->next_button), FALSE);
416
579
 
417
 
        /* Status label */
418
 
        widget->priv->status_label = gtk_label_new ("");
419
 
        gtk_box_pack_start (GTK_BOX (v_box), widget->priv->status_label, FALSE, FALSE, 2);
420
 
 
421
580
        /* Add the main container to the widget */
422
581
        gtk_container_add (GTK_CONTAINER (widget), v_box);
423
582
 
424
583
        gtk_widget_show_all (GTK_WIDGET (widget));
425
584
 
426
585
        /* Connect the search button clicked signal and the search entry  */
 
586
        g_signal_connect (widget->priv->search_entry, "changed", 
 
587
                          G_CALLBACK (search_entry_changed_cb), widget);
427
588
        g_signal_connect (widget->priv->search_button, "clicked",
428
589
                          G_CALLBACK (new_search), widget);
429
590
        g_signal_connect (widget->priv->search_entry, "activate",