~ubuntu-branches/ubuntu/precise/gnome-bluetooth/precise-updates

« back to all changes in this revision

Viewing changes to common/bluetooth-chooser-button.c

  • Committer: Bazaar Package Importer
  • Author(s): Alexander Sack
  • Date: 2009-08-05 13:34:38 UTC
  • mto: (2.2.1 experimental) (1.4.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 23.
  • Revision ID: james.westby@ubuntu.com-20090805133438-791u4ywsppj71d9y
Tags: upstream-2.27.8
ImportĀ upstreamĀ versionĀ 2.27.8

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2
 
/*
3
 
 * (C) Copyright 2007-2009 Bastien Nocera <hadess@hadess.net>
4
 
 *
5
 
 * This library is free software; you can redistribute it and/or
6
 
 * modify it under the terms of the GNU Library General Public
7
 
 * License as published by the Free Software Foundation; either
8
 
 * version 2 of the License, or (at your option) any later version.
9
 
 *
10
 
 * This library 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
 
 * Library General Public License for more details.
14
 
 *
15
 
 * You should have received a copy of the GNU Library General Public
16
 
 * License along with this library; if not, write to the
17
 
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18
 
 * Boston, MA 02111-1307, USA.
19
 
 */
20
 
 
21
 
#ifdef HAVE_CONFIG_H
22
 
#include "config.h"
23
 
#endif
24
 
 
25
 
#include <glib/gi18n.h>
26
 
#include <gtk/gtk.h>
27
 
 
28
 
#include "bluetooth-chooser-button.h"
29
 
#include "bluetooth-client.h"
30
 
#include "bluetooth-chooser.h"
31
 
#include "marshal.h"
32
 
 
33
 
struct _BluetoothChooserButton {
34
 
        GtkButton          parent;
35
 
 
36
 
        BluetoothClient   *client;
37
 
        GtkWidget         *image;
38
 
        GtkWidget         *dialog;
39
 
        GtkWidget         *chooser;
40
 
        char              *bdaddr;
41
 
        guint              is_available : 1;
42
 
        guint              has_selection : 1;
43
 
};
44
 
 
45
 
enum {
46
 
        PROP_0,
47
 
        PROP_DEVICE,
48
 
        PROP_IS_AVAILABLE,
49
 
};
50
 
 
51
 
enum {
52
 
        CHOOSER_CREATED,
53
 
        LAST_SIGNAL
54
 
};
55
 
 
56
 
static int signals[LAST_SIGNAL] = { 0 };
57
 
 
58
 
static void     bluetooth_chooser_button_class_init     (BluetoothChooserButtonClass * klass);
59
 
static void     bluetooth_chooser_button_init           (BluetoothChooserButton      * button);
60
 
 
61
 
static GtkButtonClass *parent_class;
62
 
 
63
 
G_DEFINE_TYPE(BluetoothChooserButton, bluetooth_chooser_button, GTK_TYPE_BUTTON);
64
 
 
65
 
#define DEFAULT_STR N_("Click to select device...")
66
 
 
67
 
static void
68
 
set_btdevname (BluetoothChooserButton *button, const char *bdaddr, const char *name, const char *icon)
69
 
{
70
 
        char *found_name, *found_icon;
71
 
 
72
 
        found_name = NULL;
73
 
        found_icon = NULL;
74
 
 
75
 
        if (bdaddr != NULL && (name == NULL || icon == NULL)) {
76
 
                GtkTreeModel *model;
77
 
                GtkTreeIter iter;
78
 
                gboolean cont = FALSE;
79
 
 
80
 
                model = bluetooth_client_get_device_model (button->client, NULL);
81
 
                if (model != NULL) {
82
 
                        cont = gtk_tree_model_iter_children (GTK_TREE_MODEL(model),
83
 
                                                             &iter, NULL);
84
 
                }
85
 
 
86
 
                while (cont == TRUE) {
87
 
                        char *value;
88
 
 
89
 
                        gtk_tree_model_get(GTK_TREE_MODEL(model), &iter,
90
 
                                           BLUETOOTH_COLUMN_ADDRESS, &value, -1);
91
 
                        if (g_ascii_strcasecmp(bdaddr, value) == 0) {
92
 
                                gtk_tree_model_get(GTK_TREE_MODEL(model), &iter,
93
 
                                                   BLUETOOTH_COLUMN_ALIAS, &found_name,
94
 
                                                   BLUETOOTH_COLUMN_ICON, &found_icon,
95
 
                                                   -1);
96
 
                                g_free (value);
97
 
                                break;
98
 
                        }
99
 
                        g_free (value);
100
 
                        cont = gtk_tree_model_iter_next (GTK_TREE_MODEL(model), &iter);
101
 
                }
102
 
 
103
 
                if (model != NULL)
104
 
                        g_object_unref (model);
105
 
 
106
 
                if (found_name == NULL) {
107
 
                        found_name = g_strdup (bdaddr);
108
 
                        g_strdelimit (found_name, ":", '-');
109
 
                }
110
 
                if (found_icon == NULL)
111
 
                        found_icon = g_strdup ("bluetooth");
112
 
        }
113
 
 
114
 
        if (bdaddr != NULL) {
115
 
                /* Update the name */
116
 
                if (name == NULL)
117
 
                        gtk_button_set_label (GTK_BUTTON (button), found_name);
118
 
                else
119
 
                        gtk_button_set_label (GTK_BUTTON (button), name);
120
 
                /* And the icon */
121
 
                if (icon == NULL)
122
 
                        gtk_image_set_from_icon_name (GTK_IMAGE (button->image), found_icon, GTK_ICON_SIZE_MENU);
123
 
                else
124
 
                        gtk_image_set_from_icon_name (GTK_IMAGE (button->image), icon, GTK_ICON_SIZE_MENU);
125
 
 
126
 
                /* And our copy of the address, and notify if it's actually changed */
127
 
                if (button->bdaddr == NULL || strcmp (bdaddr, button->bdaddr) != 0) {
128
 
                        g_free (button->bdaddr);
129
 
                        button->bdaddr = g_strdup (bdaddr);
130
 
                        g_object_notify (G_OBJECT (button), "device");
131
 
                }
132
 
        } else {
133
 
                gtk_button_set_label (GTK_BUTTON (button), _(DEFAULT_STR));
134
 
                if (button->bdaddr != NULL) {
135
 
                        g_free (button->bdaddr);
136
 
                        button->bdaddr = NULL;
137
 
                        gtk_image_clear (GTK_IMAGE (button->image));
138
 
                        g_object_notify (G_OBJECT (button), "device");
139
 
                }
140
 
        }
141
 
 
142
 
        g_free (found_name);
143
 
        g_free (found_icon);
144
 
}
145
 
 
146
 
static void select_device_changed(BluetoothChooser *self, gchar *address, gpointer data)
147
 
{
148
 
        BluetoothChooserButton *button = BLUETOOTH_CHOOSER_BUTTON (data);
149
 
 
150
 
        button->has_selection = (address != NULL);
151
 
        gtk_dialog_set_response_sensitive(GTK_DIALOG (button->dialog), GTK_RESPONSE_ACCEPT,
152
 
                                          button->has_selection && button->is_available);
153
 
}
154
 
 
155
 
static void
156
 
dialog_response_cb (GtkDialog *dialog, int response_id, gpointer data)
157
 
{
158
 
        BluetoothChooserButton *button = BLUETOOTH_CHOOSER_BUTTON (data);
159
 
        char *bdaddr, *icon, *name;
160
 
 
161
 
        if (response_id == GTK_RESPONSE_ACCEPT) {
162
 
                g_object_get(button->chooser,
163
 
                             "device-selected", &bdaddr,
164
 
                             "device-selected-name", &name,
165
 
                             "device-selected-icon", &icon,
166
 
                             NULL);
167
 
        }
168
 
 
169
 
        gtk_widget_destroy (GTK_WIDGET (dialog));
170
 
        button->dialog = NULL;
171
 
 
172
 
        if (response_id != GTK_RESPONSE_ACCEPT)
173
 
                return;
174
 
 
175
 
        set_btdevname (button, bdaddr, name, icon);
176
 
        g_free (bdaddr);
177
 
        g_free (name);
178
 
        g_free (icon);
179
 
}
180
 
 
181
 
static void
182
 
bluetooth_chooser_button_clicked (GtkButton *widget)
183
 
{
184
 
        BluetoothChooserButton *button = BLUETOOTH_CHOOSER_BUTTON (widget);
185
 
        GtkWidget *parent;
186
 
 
187
 
        if (button->dialog != NULL) {
188
 
                gtk_window_present (GTK_WINDOW (button->dialog));
189
 
                return;
190
 
        }
191
 
 
192
 
        parent = gtk_widget_get_toplevel (GTK_WIDGET (button));
193
 
        //FIXME title
194
 
        button->dialog = gtk_dialog_new_with_buttons("", GTK_WINDOW (parent),
195
 
                                                     GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR,
196
 
                                                     GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
197
 
                                                     GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, NULL);
198
 
        g_signal_connect (button->dialog, "response",
199
 
                          G_CALLBACK (dialog_response_cb), button);
200
 
        gtk_dialog_set_response_sensitive (GTK_DIALOG(button->dialog),
201
 
                                           GTK_RESPONSE_ACCEPT, FALSE);
202
 
        gtk_window_set_default_size (GTK_WINDOW(button->dialog), 480, 400);
203
 
 
204
 
        gtk_container_set_border_width (GTK_CONTAINER (button->dialog), 5);
205
 
        gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (button->dialog)->vbox), 2);
206
 
 
207
 
        /* Create the button->chooser */
208
 
        button->chooser = bluetooth_chooser_new (NULL);
209
 
        g_signal_connect(button->chooser, "selected-device-changed",
210
 
                         G_CALLBACK(select_device_changed), button);
211
 
        g_signal_emit (G_OBJECT (button),
212
 
                       signals[CHOOSER_CREATED],
213
 
                       0, button->chooser);
214
 
        gtk_container_set_border_width (GTK_CONTAINER(button->chooser), 5);
215
 
        gtk_widget_show (button->chooser);
216
 
        gtk_container_add (GTK_CONTAINER(GTK_DIALOG(button->dialog)->vbox), button->chooser);
217
 
 
218
 
        gtk_widget_show (button->dialog);
219
 
}
220
 
 
221
 
static void
222
 
default_adapter_changed (GObject *object, GParamSpec *pspec, gpointer data)
223
 
{
224
 
        BluetoothChooserButton *button = BLUETOOTH_CHOOSER_BUTTON (data);
225
 
        char *adapter;
226
 
        gboolean powered;
227
 
 
228
 
        g_object_get (G_OBJECT (button->client),
229
 
                      "default-adapter", &adapter,
230
 
                      "default-adapter-powered", &powered,
231
 
                      NULL);
232
 
        if (adapter != NULL)
233
 
                button->is_available = powered;
234
 
        else
235
 
                button->is_available = FALSE;
236
 
 
237
 
        if (adapter != NULL)
238
 
                set_btdevname (button, button->bdaddr, NULL, NULL);
239
 
        g_free (adapter);
240
 
 
241
 
        if (button->dialog != NULL)
242
 
                gtk_dialog_set_response_sensitive (GTK_DIALOG (button->dialog), GTK_RESPONSE_ACCEPT,
243
 
                                                   button->has_selection && button->is_available);
244
 
 
245
 
        g_object_notify (G_OBJECT (button), "is-available");
246
 
}
247
 
 
248
 
static void
249
 
bluetooth_chooser_button_finalize (GObject *object)
250
 
{
251
 
        BluetoothChooserButton *button = BLUETOOTH_CHOOSER_BUTTON (object);
252
 
 
253
 
        if (button->client != NULL) {
254
 
                g_object_unref (button->client);
255
 
                button->client = NULL;
256
 
        }
257
 
        if (button->dialog != NULL) {
258
 
                gtk_widget_destroy (button->dialog);
259
 
                button->dialog = NULL;
260
 
                button->chooser = NULL;
261
 
        }
262
 
 
263
 
        G_OBJECT_CLASS (parent_class)->finalize (object);
264
 
}
265
 
 
266
 
static void
267
 
bluetooth_chooser_button_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
268
 
{
269
 
        BluetoothChooserButton *button;
270
 
 
271
 
        g_return_if_fail (BLUETOOTH_IS_CHOOSER_BUTTON (object));
272
 
        button = BLUETOOTH_CHOOSER_BUTTON (object);
273
 
 
274
 
        switch (property_id)
275
 
        case PROP_DEVICE: {
276
 
                g_return_if_fail (bluetooth_verify_address (g_value_get_string (value)) || g_value_get_string (value) == NULL);
277
 
                set_btdevname (button, g_value_get_string (value), NULL, NULL);
278
 
                break;
279
 
        default:
280
 
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
281
 
        }
282
 
}
283
 
 
284
 
static void
285
 
bluetooth_chooser_button_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
286
 
{
287
 
        BluetoothChooserButton *button;
288
 
 
289
 
        g_return_if_fail (BLUETOOTH_IS_CHOOSER_BUTTON (object));
290
 
        button = BLUETOOTH_CHOOSER_BUTTON (object);
291
 
 
292
 
        switch (property_id) {
293
 
        case PROP_DEVICE:
294
 
                g_value_set_string (value, button->bdaddr);
295
 
                break;
296
 
        case PROP_IS_AVAILABLE:
297
 
                g_value_set_boolean (value, button->is_available);
298
 
                break;
299
 
        default:
300
 
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
301
 
        }
302
 
}
303
 
 
304
 
static void
305
 
bluetooth_chooser_button_class_init (BluetoothChooserButtonClass *klass)
306
 
{
307
 
        GObjectClass *object_class = G_OBJECT_CLASS (klass);
308
 
        GtkButtonClass *button_class = GTK_BUTTON_CLASS (klass);
309
 
 
310
 
        parent_class = g_type_class_peek_parent (klass);
311
 
 
312
 
        object_class->finalize = bluetooth_chooser_button_finalize;
313
 
        object_class->set_property = bluetooth_chooser_button_set_property;
314
 
        object_class->get_property = bluetooth_chooser_button_get_property;
315
 
 
316
 
        button_class->clicked = bluetooth_chooser_button_clicked;
317
 
 
318
 
        /**
319
 
         * BluetoothChooserButton:chooser-created:
320
 
         *
321
 
         * @bluetoothchooserbutton: a #BluetoothChooserButton widget
322
 
         * @arg1: a #BluetoothChooser widget
323
 
         *
324
 
         * The signal is sent when a popup dialogue is created for the user to select
325
 
         * a device. This signal allows you to change the configuration and filtering
326
 
         * of the tree from its defaults.
327
 
         *
328
 
         **/
329
 
        signals[CHOOSER_CREATED] =
330
 
                g_signal_new ("chooser-created",
331
 
                              G_TYPE_FROM_CLASS (klass),
332
 
                              G_SIGNAL_RUN_LAST,
333
 
                              G_STRUCT_OFFSET (BluetoothChooserButtonClass, chooser_created),
334
 
                              NULL, NULL,
335
 
                              g_cclosure_marshal_VOID__OBJECT,
336
 
                              G_TYPE_NONE, 1, G_TYPE_OBJECT);
337
 
 
338
 
        /**
339
 
         * BluetoothChooserButton:device:
340
 
         *
341
 
         * The Bluetooth address of the selected device or %NULL
342
 
         **/
343
 
        g_object_class_install_property (object_class, PROP_DEVICE,
344
 
                                         g_param_spec_string ("device", "Device", "The Bluetooth address of the selected device.",
345
 
                                                              NULL, G_PARAM_READWRITE));
346
 
        /**
347
 
         * BluetoothChooserButton:is-available:
348
 
         *
349
 
         * %TRUE if there is a powered Bluetooth adapter available.
350
 
         *
351
 
         * See also: bluetooth_chooser_button_available()
352
 
         **/
353
 
        g_object_class_install_property (object_class, PROP_IS_AVAILABLE,
354
 
                                         g_param_spec_boolean ("is-available", "Bluetooth is available", "Whether Bluetooth is available.",
355
 
                                                               TRUE, G_PARAM_READABLE));
356
 
}
357
 
 
358
 
static void
359
 
bluetooth_chooser_button_init (BluetoothChooserButton *button)
360
 
{
361
 
        gtk_button_set_label (GTK_BUTTON (button), _("Click to select device..."));
362
 
 
363
 
        button->image = gtk_image_new ();
364
 
        gtk_button_set_image (GTK_BUTTON (button), button->image);
365
 
 
366
 
        button->bdaddr = NULL;
367
 
        button->dialog = NULL;
368
 
 
369
 
        button->client = bluetooth_client_new ();
370
 
        g_signal_connect (G_OBJECT (button->client), "notify::default-adapter",
371
 
                          G_CALLBACK (default_adapter_changed), button);
372
 
        g_signal_connect (G_OBJECT (button->client), "notify::default-adapter-powered",
373
 
                          G_CALLBACK (default_adapter_changed), button);
374
 
 
375
 
        /* And set the default value already */
376
 
        default_adapter_changed (NULL, NULL, button);
377
 
 
378
 
        set_btdevname (button, NULL, NULL, NULL);
379
 
}
380
 
 
381
 
/**
382
 
 * bluetooth_chooser_button_new:
383
 
 *
384
 
 * Return value: a #BluetoothChooserButton
385
 
 **/
386
 
GtkWidget *
387
 
bluetooth_chooser_button_new (void)
388
 
{
389
 
        return g_object_new (BLUETOOTH_TYPE_CHOOSER_BUTTON,
390
 
                             "label", _(DEFAULT_STR),
391
 
                             NULL);
392
 
}
393
 
 
394
 
/**
395
 
 * bluetooth_chooser_button_available:
396
 
 * @button: a #BluetoothChooserButton
397
 
 *
398
 
 * Return value: %TRUE if there is a powered Bluetooth adapter available, and the button should be sensitive.
399
 
 **/
400
 
gboolean
401
 
bluetooth_chooser_button_available (BluetoothChooserButton *button)
402
 
{
403
 
        g_return_val_if_fail (BLUETOOTH_IS_CHOOSER_BUTTON (button), FALSE);
404
 
 
405
 
        return button->is_available;
406
 
}
407