/* * * Copyright (C) 2013 Bastien Nocera * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * */ #include "config.h" #include #include #include #include "bluetooth-settings-row.h" #include "bluetooth-enums.h" #include "bluetooth-utils.h" #include "gnome-bluetooth-enum-types.h" struct _BluetoothSettingsRow { AdwActionRow parent_instance; /* Widget */ GtkWidget *status; GtkWidget *spinner; /* Properties */ GDBusProxy *proxy; BluetoothDevice *device; gboolean paired; gboolean trusted; BluetoothType type; gboolean connected; char *name; char *alias; char *bdaddr; gboolean legacy_pairing; gint64 time_created; gboolean pairing; }; enum { PROP_0, PROP_PROXY, PROP_DEVICE, PROP_PAIRED, PROP_TRUSTED, PROP_TYPE, PROP_CONNECTED, PROP_NAME, PROP_ALIAS, PROP_ADDRESS, PROP_PAIRING, PROP_LEGACY_PAIRING, PROP_TIME_CREATED }; G_DEFINE_TYPE(BluetoothSettingsRow, bluetooth_settings_row, ADW_TYPE_ACTION_ROW) static void label_might_change (BluetoothSettingsRow *self) { if (!self->paired && !self->trusted) gtk_label_set_text (GTK_LABEL (self->status), _("Not Set Up")); else if (self->connected) gtk_label_set_text (GTK_LABEL (self->status), _("Connected")); else gtk_label_set_text (GTK_LABEL (self->status), _("Disconnected")); if (self->pairing) { gtk_widget_hide (self->status); gtk_spinner_start (GTK_SPINNER (self->spinner)); gtk_widget_show (self->spinner); } else { gtk_spinner_stop (GTK_SPINNER (self->spinner)); gtk_widget_hide (self->spinner); gtk_widget_show (self->status); } } static void bluetooth_settings_row_init (BluetoothSettingsRow *self) { gtk_widget_init_template (GTK_WIDGET (self)); self->time_created = g_get_monotonic_time(); label_might_change (self); } static void bluetooth_settings_row_finalize (GObject *object) { BluetoothSettingsRow *self = BLUETOOTH_SETTINGS_ROW (object); g_clear_object (&self->proxy); g_clear_object (&self->device); g_clear_pointer (&self->name, g_free); g_clear_pointer (&self->alias, g_free); g_clear_pointer (&self->bdaddr, g_free); G_OBJECT_CLASS(bluetooth_settings_row_parent_class)->finalize(object); } static void bluetooth_settings_row_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { BluetoothSettingsRow *self = BLUETOOTH_SETTINGS_ROW (object); switch (property_id) { case PROP_PROXY: g_value_set_object (value, self->proxy); break; case PROP_DEVICE: g_value_set_object (value, self->device); break; case PROP_PAIRED: g_value_set_boolean (value, self->paired); break; case PROP_TRUSTED: g_value_set_boolean (value, self->trusted); break; case PROP_TYPE: g_value_set_flags (value, self->type); break; case PROP_CONNECTED: g_value_set_boolean (value, self->connected); break; case PROP_NAME: g_value_set_string (value, self->name); break; case PROP_ALIAS: g_value_set_string (value, self->alias); break; case PROP_ADDRESS: g_value_set_string (value, self->bdaddr); break; case PROP_PAIRING: g_value_set_boolean (value, self->pairing); break; case PROP_LEGACY_PAIRING: g_value_set_boolean (value, self->legacy_pairing); break; case PROP_TIME_CREATED: g_value_set_int64 (value, self->time_created); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); break; } } static void update_row (BluetoothSettingsRow *self) { if (self->name == NULL) { adw_preferences_row_set_title (ADW_PREFERENCES_ROW (self), bluetooth_type_to_string (self->type)); gtk_widget_set_sensitive (GTK_WIDGET (self), FALSE); } else { g_autofree char *escaped = NULL; if (self->alias != NULL) escaped = g_markup_escape_text (self->alias, -1); adw_preferences_row_set_title (ADW_PREFERENCES_ROW (self), escaped); gtk_widget_set_sensitive (GTK_WIDGET (self), TRUE); } } static void bluetooth_settings_row_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { BluetoothSettingsRow *self = BLUETOOTH_SETTINGS_ROW (object); switch (property_id) { case PROP_PROXY: g_clear_object (&self->proxy); self->proxy = g_value_dup_object (value); break; case PROP_DEVICE: g_assert (!self->device); self->device = g_value_dup_object (value); break; case PROP_PAIRED: self->paired = g_value_get_boolean (value); label_might_change (self); break; case PROP_TRUSTED: self->trusted = g_value_get_boolean (value); label_might_change (self); break; case PROP_TYPE: self->type = g_value_get_flags (value); update_row (self); break; case PROP_CONNECTED: self->connected = g_value_get_boolean (value); label_might_change (self); break; case PROP_NAME: g_free (self->name); self->name = g_value_dup_string (value); update_row (self); break; case PROP_ALIAS: g_free (self->alias); self->alias = g_value_dup_string (value); update_row (self); break; case PROP_ADDRESS: g_free (self->bdaddr); self->bdaddr = g_value_dup_string (value); break; case PROP_PAIRING: self->pairing = g_value_get_boolean (value); label_might_change (self); break; case PROP_LEGACY_PAIRING: self->legacy_pairing = g_value_get_boolean (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); break; } } static void bluetooth_settings_row_class_init (BluetoothSettingsRowClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); object_class->finalize = bluetooth_settings_row_finalize; object_class->get_property = bluetooth_settings_row_get_property; object_class->set_property = bluetooth_settings_row_set_property; g_object_class_install_property (object_class, PROP_PROXY, g_param_spec_object ("proxy", NULL, "The D-Bus proxy object of the device", G_TYPE_DBUS_PROXY, G_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_DEVICE, g_param_spec_object ("device", NULL, "a BluetoothDevice object", BLUETOOTH_TYPE_DEVICE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (object_class, PROP_PAIRED, g_param_spec_boolean ("paired", NULL, "Paired", FALSE, G_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_TRUSTED, g_param_spec_boolean ("trusted", NULL, "Trusted", FALSE, G_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_TYPE, g_param_spec_flags ("type", NULL, "Type", BLUETOOTH_TYPE_TYPE, BLUETOOTH_TYPE_ANY, G_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_CONNECTED, g_param_spec_boolean ("connected", NULL, "Connected", FALSE, G_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_NAME, g_param_spec_string ("name", NULL, "Name", NULL, G_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_ALIAS, g_param_spec_string ("alias", NULL, "Alias", NULL, G_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_ADDRESS, g_param_spec_string ("address", NULL, "Address", NULL, G_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_PAIRING, g_param_spec_boolean ("pairing", NULL, "Pairing", FALSE, G_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_LEGACY_PAIRING, g_param_spec_boolean ("legacy-pairing", NULL, "Legacy pairing", FALSE, G_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_TIME_CREATED, g_param_spec_int64 ("time-created", NULL, "Time Created", G_MININT64, G_MAXINT64, 0, G_PARAM_READABLE)); /* Bind class to template */ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/bluetooth/bluetooth-settings-row.ui"); gtk_widget_class_bind_template_child (widget_class, BluetoothSettingsRow, spinner); gtk_widget_class_bind_template_child (widget_class, BluetoothSettingsRow, status); } static gboolean name_to_visible (GBinding *binding, const GValue *from_value, GValue *to_value, gpointer user_data) { const char *name; name = g_value_get_string (from_value); g_value_set_boolean (to_value, name != NULL); return TRUE; } /** * bluetooth_settings_row_new_from_device: * * Returns a new #BluetoothSettingsRow widget populated from * the #BluetoothDevice passed. * * Return value: A #BluetoothSettingsRow widget **/ GtkWidget * bluetooth_settings_row_new_from_device (BluetoothDevice *device) { g_autoptr(GDBusProxy) proxy = NULL; GtkWidget *row; const char *props[] = { "name", "alias", "paired", "trusted", "connected", "address", "type", "legacy-pairing", "proxy" }; guint i; g_return_val_if_fail (BLUETOOTH_IS_DEVICE (device), NULL); g_object_get (G_OBJECT (device), "proxy", &proxy, NULL); row = g_object_new (BLUETOOTH_TYPE_SETTINGS_ROW, "device", device, NULL); for (i = 0; i < G_N_ELEMENTS (props); i++) { g_object_bind_property (G_OBJECT (device), props[i], G_OBJECT (row), props[i], G_BINDING_SYNC_CREATE); } g_object_bind_property_full (G_OBJECT (device), "name", G_OBJECT (row), "visible", G_BINDING_SYNC_CREATE, name_to_visible, NULL, NULL, NULL); return row; }