[gnome-bluetooth] Add new BluetoothChooserCombo widget
- From: Bastien Nocera <hadess src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gnome-bluetooth] Add new BluetoothChooserCombo widget
- Date: Tue, 29 Sep 2009 00:55:11 +0000 (UTC)
commit 1fa916c17322a16de83a04af95dcd25161e9b157
Author: Bastien Nocera <hadess hadess net>
Date: Mon Sep 28 16:44:24 2009 +0100
Add new BluetoothChooserCombo widget
Another device selection widget, similar in style to the
"Save" GtkFileChooser widget.
lib/Makefile.am | 10 +-
lib/bluetooth-chooser-combo.c | 366 +++++++++++++++++++++++++++++++++++++++++
lib/bluetooth-chooser-combo.h | 47 ++++++
lib/gnome-bluetooth.symbols | 2 +
4 files changed, 422 insertions(+), 3 deletions(-)
---
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 56f58cc..56839f8 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -31,9 +31,13 @@ libgnome_bluetooth_la_SOURCES = \
bling-spinner.c bling-spinner.h \
bluetooth-chooser.c bluetooth-chooser.h \
bluetooth-chooser-private.h \
- seahorse-bind.c seahorse-bind.h \
- bluetooth-filter-widget.c bluetooth-filter-widget.h \
- bluetooth-chooser-button.c bluetooth-chooser-button.h
+ seahorse-bind.c seahorse-bind.h \
+ bluetooth-filter-widget.c \
+ bluetooth-filter-widget.h \
+ bluetooth-chooser-button.c \
+ bluetooth-chooser-button.h \
+ bluetooth-chooser-combo.c \
+ bluetooth-chooser-combo.h
libgnome_bluetooth_la_LIBADD = $(LIBGNOMEBT_LIBS)
diff --git a/lib/bluetooth-chooser-combo.c b/lib/bluetooth-chooser-combo.c
new file mode 100644
index 0000000..d097b2d
--- /dev/null
+++ b/lib/bluetooth-chooser-combo.c
@@ -0,0 +1,366 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * (C) Copyright 2007-2009 Bastien Nocera <hadess hadess net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include "bluetooth-chooser-combo.h"
+#include "bluetooth-client.h"
+#include "bluetooth-chooser.h"
+#include "bluetooth-chooser-private.h"
+#include "seahorse-bind.h"
+#include "marshal.h"
+
+struct _BluetoothChooserCombo {
+ GtkVBox parent;
+
+ GtkWidget *chooser;
+ GtkWidget *drop_box;
+ GtkWidget *drop;
+ GtkTreeModel *model;
+ guint model_notify_id;
+ GtkTreeSelection *selection;
+
+ gpointer expander_state;
+ char *bdaddr;
+};
+
+enum {
+ PROP_0,
+ PROP_CHOOSER,
+ PROP_DEVICE,
+};
+
+enum {
+ CHOOSER_CREATED,
+ LAST_SIGNAL
+};
+
+static int signals[LAST_SIGNAL] = { 0 };
+
+static void bluetooth_chooser_combo_class_init (BluetoothChooserComboClass * klass);
+static void bluetooth_chooser_combo_init (BluetoothChooserCombo * combo);
+
+static GtkVBoxClass *parent_class;
+
+G_DEFINE_TYPE(BluetoothChooserCombo, bluetooth_chooser_combo, GTK_TYPE_VBOX);
+
+static void
+bluetooth_chooser_combo_set_device (BluetoothChooserCombo *combo,
+ const char *bdaddr)
+{
+ if (bdaddr == NULL || combo->model == NULL) {
+ g_free (combo->bdaddr);
+ gtk_widget_set_sensitive (combo->drop_box, FALSE);
+ } else {
+ GtkTreeIter iter;
+ gboolean cont = FALSE;
+
+ gtk_widget_set_sensitive (combo->drop_box, TRUE);
+
+ g_free (combo->bdaddr);
+ combo->bdaddr = g_strdup (bdaddr);
+
+ cont = gtk_tree_model_iter_children (combo->model, &iter, NULL);
+ while (cont == TRUE) {
+ char *value;
+
+ gtk_tree_model_get (GTK_TREE_MODEL (combo->model), &iter,
+ BLUETOOTH_COLUMN_ADDRESS, &value, -1);
+ if (g_ascii_strcasecmp(bdaddr, value) == 0) {
+ gtk_tree_selection_select_iter (combo->selection, &iter);
+ g_free (value);
+ break;
+ }
+ g_free (value);
+ cont = gtk_tree_model_iter_next (GTK_TREE_MODEL (combo->model), &iter);
+ }
+ }
+ g_object_notify (G_OBJECT (combo), "device");
+}
+
+static void
+bluetooth_chooser_combo_dispose (GObject *object)
+{
+ BluetoothChooserCombo *combo = BLUETOOTH_CHOOSER_COMBO (object);
+
+ if (combo->model_notify_id != 0) {
+ GtkWidget *treeview;
+
+ treeview = bluetooth_chooser_get_treeview (BLUETOOTH_CHOOSER (combo->chooser));
+ g_signal_handler_disconnect (treeview, combo->model_notify_id);
+ combo->model_notify_id = 0;
+ }
+ if (combo->model != NULL) {
+ g_object_unref (combo->model);
+ combo->model = NULL;
+ }
+
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+bluetooth_chooser_combo_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
+{
+ BluetoothChooserCombo *combo;
+
+ g_return_if_fail (BLUETOOTH_IS_CHOOSER_COMBO (object));
+ combo = BLUETOOTH_CHOOSER_COMBO (object);
+
+ switch (property_id)
+ case PROP_DEVICE: {
+ g_return_if_fail (bluetooth_verify_address (g_value_get_string (value)) || g_value_get_string (value) == NULL);
+ bluetooth_chooser_combo_set_device (combo, g_value_get_string (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ }
+}
+
+static void
+bluetooth_chooser_combo_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
+{
+ BluetoothChooserCombo *combo;
+
+ g_return_if_fail (BLUETOOTH_IS_CHOOSER_COMBO (object));
+ combo = BLUETOOTH_CHOOSER_COMBO (object);
+
+ switch (property_id) {
+ case PROP_CHOOSER:
+ g_value_set_object (value, combo->chooser);
+ break;
+ case PROP_DEVICE:
+ g_value_set_string (value, combo->bdaddr);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ }
+}
+
+static void
+bluetooth_chooser_combo_class_init (BluetoothChooserComboClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ object_class->dispose = bluetooth_chooser_combo_dispose;
+ object_class->set_property = bluetooth_chooser_combo_set_property;
+ object_class->get_property = bluetooth_chooser_combo_get_property;
+
+ /**
+ * BluetoothChooserCombo::chooser-created:
+ * @self: a #BluetoothChooserCombo widget
+ * @chooser: a #BluetoothChooser widget
+ *
+ * The signal is sent when a popup dialogue is created for the user to select
+ * a device. This signal allows you to change the configuration and filtering
+ * of the tree from its defaults.
+ **/
+ signals[CHOOSER_CREATED] =
+ g_signal_new ("chooser-created",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (BluetoothChooserComboClass, chooser_created),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1, G_TYPE_OBJECT);
+
+ /**
+ * BluetoothChooserCombo:chooser:
+ *
+ * The #BluetoothChooser used in the widget
+ **/
+ g_object_class_install_property (object_class, PROP_CHOOSER,
+ g_param_spec_object ("chooser", "Chooser", "The #BluetoothChooser used in the widget",
+ BLUETOOTH_TYPE_CHOOSER, G_PARAM_READABLE));
+ /**
+ * BluetoothChooserCombo:device:
+ *
+ * The Bluetooth address of the selected device or %NULL
+ **/
+ g_object_class_install_property (object_class, PROP_DEVICE,
+ g_param_spec_string ("device", "Device", "The Bluetooth address of the selected device.",
+ NULL, G_PARAM_READWRITE));
+}
+
+static void
+treeview_model_notify_cb (GObject *gobject,
+ GParamSpec *pspec,
+ gpointer user_data)
+{
+ BluetoothChooserCombo *combo = BLUETOOTH_CHOOSER_COMBO (user_data);
+ GtkTreeModel *model;
+
+ g_object_get (gobject, "model", &model, NULL);
+ gtk_combo_box_set_model (GTK_COMBO_BOX (combo->drop), model);
+ if (combo->model != NULL) {
+ g_object_unref (combo->model);
+ combo->model = NULL;
+ }
+ combo->model = model;
+}
+
+static void
+treeview_selection_changed_cb (GtkTreeSelection *treeselection,
+ gpointer user_data)
+{
+ BluetoothChooserCombo *combo = BLUETOOTH_CHOOSER_COMBO (user_data);
+ GtkTreeIter iter;
+ char *value = NULL;
+
+ if (gtk_tree_selection_get_selected (combo->selection, NULL, &iter)) {
+ gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combo->drop), &iter);
+ if (combo->model != NULL)
+ gtk_tree_model_get (GTK_TREE_MODEL (combo->model), &iter,
+ BLUETOOTH_COLUMN_ADDRESS, &value, -1);
+ } else {
+ if (combo->model != NULL)
+ gtk_combo_box_set_active (GTK_COMBO_BOX (combo->drop), -1);
+ }
+
+ if (g_strcmp0 (combo->bdaddr, value) != 0) {
+ g_free (combo->bdaddr);
+ combo->bdaddr = value;
+ g_object_notify (G_OBJECT (combo), "device");
+ } else {
+ g_free (value);
+ }
+}
+
+static void
+drop_changed_cb (GtkComboBox *widget,
+ gpointer user_data)
+{
+ BluetoothChooserCombo *combo = BLUETOOTH_CHOOSER_COMBO (user_data);
+ GtkTreeIter iter;
+ char *value = NULL;
+
+ if (gtk_combo_box_get_active_iter (widget, &iter)) {
+ gtk_tree_selection_select_iter (combo->selection, &iter);
+ if (combo->model != NULL)
+ gtk_tree_model_get (GTK_TREE_MODEL (combo->model), &iter,
+ BLUETOOTH_COLUMN_ADDRESS, &value, -1);
+ } else {
+ if (combo->model != NULL)
+ gtk_tree_selection_unselect_all (combo->selection);
+ }
+
+ if (g_strcmp0 (combo->bdaddr, value) != 0) {
+ g_free (combo->bdaddr);
+ combo->bdaddr = value;
+ g_object_notify (G_OBJECT (combo), "device");
+ } else {
+ g_free (value);
+ }
+}
+
+static gboolean
+invert_property (const GValue *src, GValue *dest)
+{
+ gboolean value;
+ value = g_value_get_boolean (src);
+ g_value_set_boolean (dest, !value);
+ return TRUE;
+}
+
+static void
+bluetooth_chooser_combo_init (BluetoothChooserCombo *combo)
+{
+ GtkWidget *triangle;
+ GtkWidget *treeview;
+ GtkCellRenderer *renderer;
+
+ combo->drop_box = gtk_hbox_new (TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (combo), combo->drop_box,
+ TRUE, FALSE, 0);
+ /* Setup the combo itself */
+ combo->drop = gtk_combo_box_new ();
+ gtk_box_pack_start (GTK_BOX (combo->drop_box), combo->drop,
+ TRUE, TRUE, 8);
+ renderer = gtk_cell_renderer_pixbuf_new ();
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo->drop),
+ renderer,
+ FALSE);
+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo->drop),
+ renderer,
+ "icon-name", BLUETOOTH_COLUMN_ICON,
+ NULL);
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo->drop),
+ renderer,
+ TRUE);
+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo->drop),
+ renderer,
+ "text", BLUETOOTH_COLUMN_ALIAS,
+ NULL);
+
+ triangle = gtk_expander_new_with_mnemonic (_("Show more widget options"));
+ gtk_container_add (GTK_CONTAINER (combo), triangle);
+ combo->expander_state = seahorse_bind_property_full ("expanded", triangle,
+ invert_property,
+ "sensitive", combo->drop, NULL);
+ combo->chooser = bluetooth_chooser_new ("");
+ gtk_container_add (GTK_CONTAINER (triangle), combo->chooser);
+
+ treeview = bluetooth_chooser_get_treeview (BLUETOOTH_CHOOSER (combo->chooser));
+ combo->model_notify_id = g_signal_connect (G_OBJECT (treeview), "notify::model",
+ G_CALLBACK (treeview_model_notify_cb), combo);
+ treeview_model_notify_cb (G_OBJECT (treeview), NULL, combo);
+ gtk_combo_box_set_active (GTK_COMBO_BOX (combo->drop), 0);
+
+ combo->selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
+ g_signal_connect (G_OBJECT (combo->selection), "changed",
+ G_CALLBACK (treeview_selection_changed_cb), combo);
+ g_signal_connect (G_OBJECT (combo->drop), "changed",
+ G_CALLBACK (drop_changed_cb), combo);
+
+ gtk_widget_show_all (GTK_WIDGET (combo));
+}
+
+/**
+ * bluetooth_chooser_combo_new:
+ *
+ * Return value: a #BluetoothChooserCombo
+ **/
+GtkWidget *
+bluetooth_chooser_combo_new (void)
+{
+ return g_object_new (BLUETOOTH_TYPE_CHOOSER_COMBO, NULL);
+}
+
+/**
+ * bluetooth_chooser_combo_available:
+ * @combo: a #BluetoothChooserCombo
+ *
+ * Return value: %TRUE if there is a powered Bluetooth adapter available, and the combo should be sensitive.
+ **/
+gboolean
+bluetooth_chooser_combo_available (BluetoothChooserCombo *combo)
+{
+ g_return_val_if_fail (BLUETOOTH_IS_CHOOSER_COMBO (combo), FALSE);
+
+ return combo->is_available;
+}
+
diff --git a/lib/bluetooth-chooser-combo.h b/lib/bluetooth-chooser-combo.h
new file mode 100644
index 0000000..70c2da0
--- /dev/null
+++ b/lib/bluetooth-chooser-combo.h
@@ -0,0 +1,47 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * (C) Copyright 2007 Bastien Nocera <hadess hadess net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __BLUETOOTH_CHOOSER_COMBO_H__
+#define __BLUETOOTH_CHOOSER_COMBO_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define BLUETOOTH_TYPE_CHOOSER_COMBO (bluetooth_chooser_combo_get_type ())
+#define BLUETOOTH_CHOOSER_COMBO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), BLUETOOTH_TYPE_CHOOSER_COMBO, BluetoothChooserCombo))
+#define BLUETOOTH_IS_CHOOSER_COMBO(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), BLUETOOTH_TYPE_CHOOSER_COMBO))
+
+typedef struct _BluetoothChooserCombo BluetoothChooserCombo;
+
+typedef struct _BluetoothChooserComboClass {
+ GtkVBoxClass parent_class;
+
+ void (*chooser_created) (BluetoothChooserCombo *self, GtkWidget *chooser);
+} BluetoothChooserComboClass;
+
+GType bluetooth_chooser_combo_get_type (void);
+
+GtkWidget * bluetooth_chooser_combo_new (void);
+gboolean bluetooth_chooser_combo_available (BluetoothChooserCombo *combo);
+
+G_END_DECLS
+
+#endif /* __BLUETOOTH_CHOOSER_COMBO_H__ */
diff --git a/lib/gnome-bluetooth.symbols b/lib/gnome-bluetooth.symbols
index a66fd1e..433eb9d 100644
--- a/lib/gnome-bluetooth.symbols
+++ b/lib/gnome-bluetooth.symbols
@@ -31,3 +31,5 @@ bluetooth_type_get_type
bluetooth_filter_widget_new
bluetooth_filter_widget_set_title
bluetooth_filter_widget_get_type
+bluetooth_chooser_combo_get_type
+bluetooth_chooser_combo_new
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]