2
2
* arch-tag: Implementation of search entry/browse toggle container
4
* Copyright (C) 2003 Colin Walters <walters@debian.org>
5
4
* Copyright (C) 2003 Jorn Baayen <jorn@nl.linux.org>
5
* Copyright (C) 2003,2004 Colin Walters <walters@redhat.com>
7
7
* This program is free software; you can redistribute it and/or modify
8
8
* it under the terms of the GNU General Public License as published by
26
26
#include <stdlib.h>
27
27
#include <string.h>
28
28
#include <libgnome/gnome-i18n.h>
29
#include <bonobo/bonobo-ui-util.h>
31
30
#include "disclosure-widget.h"
32
31
#include "rb-source-header.h"
33
32
#include "rb-stock-icons.h"
34
#include "rb-thread-helpers.h"
35
#include "rb-bonobo-helpers.h"
36
33
#include "rb-preferences.h"
37
34
#include "rb-search-entry.h"
38
35
#include "rb-debug.h"
39
36
#include "rb-remote.h"
37
#include "rb-entry-view.h"
40
38
#include "eel-gconf-extensions.h"
42
40
static void rb_source_header_class_init (RBSourceHeaderClass *klass);
55
53
static void rb_source_header_search_cb (RBSearchEntry *search,
57
55
RBSourceHeader *header);
58
static void rb_source_header_disclosure_toggled_cb (GtkToggleButton *disclosure,
56
static void rb_source_header_disclosure_toggled_cb (GObject *object,
57
GParamSpec *param_spec,
60
static void rb_source_header_gconf_search_text_changed_cb (GConfClient *client,
63
RBSourceHeader *header);
59
static void rb_source_header_search_activate_cb (RBSearchEntry *search,
60
RBSourceHeader *header);
64
61
static void rb_source_header_gconf_disclosure_changed_cb (GConfClient *client,
67
64
RBSourceHeader *header);
68
static void rb_source_header_view_browser_changed_cb (BonoboUIComponent *component,
70
Bonobo_UIComponent_EventType type,
65
static void rb_source_header_view_browser_changed_cb (GtkAction *action,
72
66
RBSourceHeader *header);
67
static void rb_source_header_source_weak_destroy_cb (RBSourceHeader *header, RBSource *source);
74
69
struct RBSourceHeaderPrivate
76
71
RBSource *selected_source;
78
BonoboUIComponent *component;
73
GtkActionGroup *actiongroup;
80
75
GtkTooltips *tooltips;
85
80
guint browser_notify_id;
86
81
guint search_notify_id;
87
83
const char *browser_key;
88
const char *search_key;
85
GHashTable *source_search_text;
98
#define CMD_PATH_VIEW_BROWSER "/commands/ViewBrowser"
99
#define CMD_PATH_VIEW_STATUSBAR "/commands/ViewStatusbar"
101
static RBBonoboUIListener rb_source_header_listeners[] =
95
static GtkToggleActionEntry rb_source_header_toggle_entries [] =
103
RB_BONOBO_UI_LISTENER ("ViewBrowser", (BonoboUIListenerFn) rb_source_header_view_browser_changed_cb),
104
RB_BONOBO_UI_LISTENER_END
97
{ "ViewBrowser", NULL, N_("_Browser"), "<control>B",
98
N_("Change the visibility of the browser"),
99
G_CALLBACK (rb_source_header_view_browser_changed_cb) }
107
static GObjectClass *parent_class = NULL;
110
rb_source_header_get_type (void)
112
static GType rb_source_header_type = 0;
114
if (rb_source_header_type == 0)
116
static const GTypeInfo our_info =
118
sizeof (RBSourceHeaderClass),
121
(GClassInitFunc) rb_source_header_class_init,
124
sizeof (RBSourceHeader),
126
(GInstanceInitFunc) rb_source_header_init
129
rb_source_header_type = g_type_register_static (GTK_TYPE_TABLE,
134
return rb_source_header_type;
101
static guint rb_source_header_n_toggle_entries = G_N_ELEMENTS (rb_source_header_toggle_entries);
104
G_DEFINE_TYPE (RBSourceHeader, rb_source_header, GTK_TYPE_TABLE)
138
107
rb_source_header_class_init (RBSourceHeaderClass *klass)
140
109
GObjectClass *object_class = G_OBJECT_CLASS (klass);
142
parent_class = g_type_class_peek_parent (klass);
144
111
object_class->finalize = rb_source_header_finalize;
146
113
object_class->set_property = rb_source_header_set_property;
155
122
G_PARAM_READWRITE));
156
123
g_object_class_install_property (object_class,
158
g_param_spec_object ("component",
160
"BonoboUIComponent object",
161
BONOBO_TYPE_UI_COMPONENT,
125
g_param_spec_object ("action-group",
127
"GtkActionGroup object",
128
GTK_TYPE_ACTION_GROUP,
162
129
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
187
154
g_signal_connect_object (G_OBJECT (header->priv->search), "search",
188
155
G_CALLBACK (rb_source_header_search_cb), header, 0);
156
g_signal_connect_object (G_OBJECT (header->priv->search), "activate",
157
G_CALLBACK (rb_source_header_search_activate_cb), header, 0);
190
159
header->priv->disclosure = cddb_disclosure_new (_("Show _Browser"),
191
160
_("Hide _Browser"));
192
161
gtk_widget_set_sensitive (header->priv->disclosure, FALSE);
193
g_signal_connect_object (G_OBJECT (header->priv->disclosure), "toggled",
162
g_signal_connect_object (G_OBJECT (header->priv->disclosure), "notify::expanded",
194
163
G_CALLBACK (rb_source_header_disclosure_toggled_cb), header, 0);
196
165
gtk_table_attach_defaults (GTK_TABLE (header),
199
168
align = gtk_alignment_new (1.0, 0.5, 1.0, 1.0);
200
169
gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET (ebox));
201
gtk_table_attach_defaults (GTK_TABLE (header),
170
gtk_table_attach (GTK_TABLE (header),
172
GTK_EXPAND | GTK_FILL,
173
GTK_EXPAND | GTK_FILL,
176
header->priv->source_search_text = g_hash_table_new_full (g_direct_hash, g_direct_equal,
177
NULL, (GDestroyNotify)g_free);
181
rb_source_header_source_weak_unref (RBSource *source, char *text, RBSourceHeader *header)
183
g_object_weak_unref (G_OBJECT (source),
184
(GWeakNotify)rb_source_header_source_weak_destroy_cb,
215
198
g_return_if_fail (header->priv != NULL);
200
g_hash_table_foreach (header->priv->source_search_text,
201
(GHFunc) rb_source_header_source_weak_unref,
203
g_hash_table_destroy (header->priv->source_search_text);
217
205
g_free (header->priv);
219
G_OBJECT_CLASS (parent_class)->finalize (object);
207
G_OBJECT_CLASS (rb_source_header_parent_class)->finalize (object);
235
223
if (header->priv->browser_key)
236
224
eel_gconf_notification_remove (header->priv->browser_notify_id);
237
if (header->priv->search_key)
238
eel_gconf_notification_remove (header->priv->search_notify_id);
240
225
g_signal_handlers_disconnect_by_func (G_OBJECT (header->priv->selected_source),
241
226
G_CALLBACK (rb_source_header_filter_changed_cb),
248
233
if (header->priv->selected_source != NULL)
235
const char *text = g_hash_table_lookup (header->priv->source_search_text,
236
header->priv->selected_source);
250
238
header->priv->browser_key = rb_source_get_browser_key (header->priv->selected_source);
251
header->priv->search_key = rb_source_get_search_key (header->priv->selected_source);
252
239
if (header->priv->browser_key)
253
240
header->priv->browser_notify_id
254
241
= eel_gconf_notification_add (header->priv->browser_key,
255
242
(GConfClientNotifyFunc) rb_source_header_gconf_disclosure_changed_cb,
257
if (header->priv->search_key) {
258
gchar *temp = eel_gconf_get_string (header->priv->search_key);
260
header->priv->search_notify_id
261
= eel_gconf_notification_add (header->priv->search_key,
262
(GConfClientNotifyFunc) rb_source_header_gconf_search_text_changed_cb,
265
rb_search_entry_set_text (RB_SEARCH_ENTRY (header->priv->search),
244
rb_search_entry_set_text (RB_SEARCH_ENTRY (header->priv->search), text);
269
245
g_signal_connect_object (G_OBJECT (header->priv->selected_source),
270
246
"filter_changed",
271
247
G_CALLBACK (rb_source_header_filter_changed_cb),
273
249
gtk_widget_set_sensitive (GTK_WIDGET (header->priv->search),
274
250
rb_source_can_search (header->priv->selected_source));
275
if (!header->priv->browser_key &&
276
!rb_source_can_search (header->priv->selected_source))
251
header->priv->have_search = rb_source_can_search (header->priv->selected_source);
252
if (!header->priv->browser_key && !header->priv->have_search)
277
253
gtk_widget_hide (GTK_WIDGET (header));
279
255
gtk_widget_show (GTK_WIDGET (header));
281
257
rb_source_header_sync_control_state (header);
285
header->priv->component = g_value_get_object (value);
286
rb_bonobo_add_listener_list_with_data (header->priv->component,
287
rb_source_header_listeners,
260
case PROP_ACTION_GROUP:
261
header->priv->actiongroup = g_value_get_object (value);
262
gtk_action_group_add_toggle_actions (header->priv->actiongroup,
263
rb_source_header_toggle_entries,
264
rb_source_header_n_toggle_entries,
291
268
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
306
283
case PROP_SOURCE:
307
284
g_value_set_object (value, header->priv->selected_source);
310
g_value_set_object (value, header->priv->component);
286
case PROP_ACTION_GROUP:
287
g_value_set_object (value, header->priv->actiongroup);
313
290
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
331
rb_source_header_new (BonoboUIComponent *component)
308
rb_source_header_new (GtkActionGroup *actiongroup)
333
310
RBSourceHeader *header = g_object_new (RB_TYPE_SOURCE_HEADER,
334
"component", component,
311
"action-group", actiongroup,
337
314
g_return_val_if_fail (header->priv != NULL, NULL);
356
rb_source_header_gconf_search_text_changed_cb (GConfClient *client,
359
RBSourceHeader *header)
333
rb_source_header_source_weak_destroy_cb (RBSourceHeader *header, RBSource *source)
363
g_return_if_fail (header->priv->search_key != NULL);
365
rb_debug ("gconf search text changed");
367
searchtext = eel_gconf_get_string (header->priv->search_key);
369
rb_search_entry_set_text (RB_SEARCH_ENTRY (header->priv->search),
372
rb_source_search (header->priv->selected_source, searchtext);
335
g_hash_table_remove (header->priv->source_search_text, source);
382
343
rb_debug ("searching for \"%s\"", text);
384
eel_gconf_set_string (header->priv->search_key, text);
345
/* if we haven't seen the source before, monitor it for deletion */
346
if (g_hash_table_lookup (header->priv->source_search_text, header->priv->selected_source) == NULL) {
347
g_object_weak_ref (G_OBJECT (header->priv->selected_source),
348
(GWeakNotify)rb_source_header_source_weak_destroy_cb,
352
g_hash_table_insert (header->priv->source_search_text,
353
header->priv->selected_source,
355
rb_source_search (header->priv->selected_source, text);
356
rb_source_header_sync_control_state (header);
395
367
if (header->priv->selected_source)
396
368
rb_source_search (header->priv->selected_source, NULL);
397
369
rb_search_entry_clear (RB_SEARCH_ENTRY (header->priv->search));
370
rb_source_header_sync_control_state (header);
401
rb_source_header_disclosure_toggled_cb (GtkToggleButton *disclosure,
374
rb_source_header_disclosure_toggled_cb (GObject *object,
375
GParamSpec *param_spec,
404
378
RBSourceHeader *header = RB_SOURCE_HEADER (data);
405
gboolean disclosed = gtk_toggle_button_get_active (disclosure);
379
GtkExpander *expander = GTK_EXPANDER (object);
380
gboolean disclosed = gtk_expander_get_expanded (expander);
407
382
rb_debug ("disclosed: %s", disclosed ? "TRUE" : "FALSE");
427
rb_source_header_view_browser_changed_cb (BonoboUIComponent *component,
429
Bonobo_UIComponent_EventType type,
402
rb_source_header_view_browser_changed_cb (GtkAction *action,
431
403
RBSourceHeader *header)
433
405
rb_debug ("got view browser toggle");
434
406
eel_gconf_set_boolean (header->priv->browser_key,
435
rb_bonobo_get_active (component, CMD_PATH_VIEW_BROWSER));
407
gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)));
439
411
rb_source_header_sync_control_state (RBSourceHeader *header)
413
GtkAction *viewbrowser_action;
414
GtkAction *viewstatusbar_action;
415
GtkAction *viewall_action;
441
416
gboolean have_browser = header->priv->selected_source != NULL
442
417
&& header->priv->browser_key != NULL;
443
418
gboolean not_small = !eel_gconf_get_boolean (CONF_UI_SMALL_DISPLAY);
445
420
gtk_widget_set_sensitive (header->priv->disclosure,
447
rb_bonobo_set_sensitive (header->priv->component, CMD_PATH_VIEW_BROWSER,
448
have_browser && not_small);
449
rb_bonobo_set_sensitive (header->priv->component,
450
CMD_PATH_VIEW_STATUSBAR, not_small);
422
viewbrowser_action = gtk_action_group_get_action (header->priv->actiongroup,
424
g_object_set (G_OBJECT (viewbrowser_action), "sensitive",
425
have_browser && not_small, NULL);
426
viewstatusbar_action = gtk_action_group_get_action (header->priv->actiongroup,
428
g_object_set (G_OBJECT (viewstatusbar_action), "sensitive",
430
viewall_action = gtk_action_group_get_action (header->priv->actiongroup,
432
g_object_set (G_OBJECT (viewall_action), "sensitive",
433
have_browser && not_small, NULL);
451
434
if (have_browser) {
452
435
gboolean shown = eel_gconf_get_boolean (header->priv->browser_key);
453
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (header->priv->disclosure),
455
rb_bonobo_set_active (header->priv->component,
456
CMD_PATH_VIEW_BROWSER,
436
gtk_expander_set_expanded (GTK_EXPANDER (header->priv->disclosure),
438
gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (viewbrowser_action),
444
rb_source_header_search_activate_cb (RBSearchEntry *search,
445
RBSourceHeader *header)
447
RBEntryView *entry_view;
449
entry_view = rb_source_get_entry_view (header->priv->selected_source);
450
gtk_widget_grab_focus (GTK_WIDGET (entry_view));