gnome-control-center/panels/bluetooth/cc-bluetooth-panel.c
Robert Ancell 93b14a4339 panel: Move shared GCancellable code into panel class
Make the panel class provide a cancellable that will be cancelled when the panel
is destroyed. Panel implementations can use this and not have to mangage the
cancellable themselves. Consolidate cases where panels had multiple cancellables
that were all being used for this behaviour.
2020-02-03 09:36:24 +13:00

261 lines
9 KiB
C

/*
*
* Copyright (C) 2013 Bastien Nocera <hadess@hadess.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <shell/cc-shell.h>
#include <shell/cc-object-storage.h>
#include <bluetooth-settings-widget.h>
#include "cc-bluetooth-panel.h"
#include "cc-bluetooth-resources.h"
struct _CcBluetoothPanel {
CcPanel parent_instance;
GtkBox *airplane_box;
GtkBox *disabled_box;
GtkSwitch *enable_switch;
GtkBox *header_box;
GtkBox *hw_airplane_box;
GtkBox *no_devices_box;
BluetoothSettingsWidget *settings_widget;
GtkStack *stack;
/* Killswitch */
GDBusProxy *rfkill;
GDBusProxy *properties;
gboolean airplane_mode;
gboolean bt_airplane_mode;
gboolean hardware_airplane_mode;
gboolean has_airplane_mode;
};
CC_PANEL_REGISTER (CcBluetoothPanel, cc_bluetooth_panel)
static const char *
cc_bluetooth_panel_get_help_uri (CcPanel *panel)
{
return "help:gnome-help/bluetooth";
}
static void
cc_bluetooth_panel_finalize (GObject *object)
{
CcBluetoothPanel *self;
self = CC_BLUETOOTH_PANEL (object);
g_clear_object (&self->properties);
g_clear_object (&self->rfkill);
G_OBJECT_CLASS (cc_bluetooth_panel_parent_class)->finalize (object);
}
static void
cc_bluetooth_panel_constructed (GObject *object)
{
CcBluetoothPanel *self = CC_BLUETOOTH_PANEL (object);
G_OBJECT_CLASS (cc_bluetooth_panel_parent_class)->constructed (object);
/* add kill switch widgets */
cc_shell_embed_widget_in_header (cc_panel_get_shell (CC_PANEL (self)),
GTK_WIDGET (self->header_box), GTK_POS_RIGHT);
}
static void
enable_switch_changed_cb (CcBluetoothPanel *self)
{
gboolean state;
state = gtk_switch_get_active (self->enable_switch);
g_debug ("Power switched to %s", state ? "on" : "off");
g_dbus_proxy_call (self->properties,
"Set",
g_variant_new_parsed ("('org.gnome.SettingsDaemon.Rfkill', 'BluetoothAirplaneMode', %v)",
g_variant_new_boolean (!state)),
G_DBUS_CALL_FLAGS_NONE,
-1,
cc_panel_get_cancellable (CC_PANEL (self)),
NULL, NULL);
}
static void
adapter_status_changed_cb (CcBluetoothPanel *self)
{
GtkAlign valign;
gboolean sensitive, powered, change_powered;
GtkWidget *page;
g_debug ("Updating airplane mode: BluetoothHasAirplaneMode %d, BluetoothHardwareAirplaneMode %d, BluetoothAirplaneMode %d, AirplaneMode %d",
self->has_airplane_mode, self->hardware_airplane_mode, self->bt_airplane_mode, self->airplane_mode);
change_powered = TRUE;
valign = GTK_ALIGN_CENTER;
if (self->has_airplane_mode == FALSE) {
g_debug ("No Bluetooth available");
sensitive = FALSE;
powered = FALSE;
page = GTK_WIDGET (self->no_devices_box);
} else if (self->hardware_airplane_mode) {
g_debug ("Bluetooth is Hard blocked");
sensitive = FALSE;
powered = FALSE;
page = GTK_WIDGET (self->hw_airplane_box);
} else if (self->airplane_mode) {
g_debug ("Airplane mode is on, Wi-Fi and Bluetooth are disabled");
sensitive = FALSE;
powered = FALSE;
page = GTK_WIDGET (self->airplane_box);
} else if (self->bt_airplane_mode ||
!bluetooth_settings_widget_get_default_adapter_powered (self->settings_widget)) {
g_debug ("Default adapter is unpowered, but should be available");
sensitive = TRUE;
change_powered = FALSE;
page = GTK_WIDGET (self->disabled_box);
} else {
g_debug ("Bluetooth is available and powered");
sensitive = TRUE;
powered = TRUE;
page = GTK_WIDGET (self->settings_widget);
valign = GTK_ALIGN_FILL;
}
gtk_widget_set_valign (GTK_WIDGET (self->stack), valign);
gtk_widget_set_sensitive (GTK_WIDGET (self->header_box), sensitive);
if (change_powered) {
g_signal_handlers_block_by_func (self->enable_switch, enable_switch_changed_cb, self);
gtk_switch_set_active (self->enable_switch, powered);
g_signal_handlers_unblock_by_func (self->enable_switch, enable_switch_changed_cb, self);
}
gtk_stack_set_visible_child (self->stack, page);
}
static void
airplane_mode_changed (CcBluetoothPanel *self)
{
g_autoptr(GVariant) airplane_mode = NULL;
g_autoptr(GVariant) bluetooth_airplane_mode = NULL;
g_autoptr(GVariant) bluetooth_hardware_airplane_mode = NULL;
g_autoptr(GVariant) bluetooth_has_airplane_mode = NULL;
airplane_mode = g_dbus_proxy_get_cached_property (self->rfkill, "AirplaneMode");
self->airplane_mode = g_variant_get_boolean (airplane_mode);
bluetooth_airplane_mode = g_dbus_proxy_get_cached_property (self->rfkill, "BluetoothAirplaneMode");
self->bt_airplane_mode = g_variant_get_boolean (bluetooth_airplane_mode);
bluetooth_hardware_airplane_mode = g_dbus_proxy_get_cached_property (self->rfkill, "BluetoothHardwareAirplaneMode");
self->hardware_airplane_mode = g_variant_get_boolean (bluetooth_hardware_airplane_mode);
bluetooth_has_airplane_mode = g_dbus_proxy_get_cached_property (self->rfkill, "BluetoothHasAirplaneMode");
self->has_airplane_mode = g_variant_get_boolean (bluetooth_has_airplane_mode);
adapter_status_changed_cb (self);
}
static void
airplane_mode_off_button_clicked_cb (CcBluetoothPanel *self)
{
g_debug ("Airplane Mode Off clicked, disabling airplane mode");
g_dbus_proxy_call (self->rfkill,
"org.freedesktop.DBus.Properties.Set",
g_variant_new_parsed ("('org.gnome.SettingsDaemon.Rfkill',"
"'AirplaneMode', %v)",
g_variant_new_boolean (FALSE)),
G_DBUS_CALL_FLAGS_NONE,
-1,
cc_panel_get_cancellable (CC_PANEL (self)),
NULL, NULL);
}
static void
panel_changed_cb (CcBluetoothPanel *self,
const char *panel)
{
CcShell *shell;
g_autoptr(GError) error = NULL;
shell = cc_panel_get_shell (CC_PANEL (self));
if (cc_shell_set_active_panel_from_id (shell, panel, NULL, &error) == FALSE)
g_warning ("Failed to activate '%s' panel: %s", panel, error->message);
}
static void
cc_bluetooth_panel_class_init (CcBluetoothPanelClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
CcPanelClass *panel_class = CC_PANEL_CLASS (klass);
object_class->constructed = cc_bluetooth_panel_constructed;
object_class->finalize = cc_bluetooth_panel_finalize;
panel_class->get_help_uri = cc_bluetooth_panel_get_help_uri;
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/bluetooth/cc-bluetooth-panel.ui");
gtk_widget_class_bind_template_child (widget_class, CcBluetoothPanel, airplane_box);
gtk_widget_class_bind_template_child (widget_class, CcBluetoothPanel, disabled_box);
gtk_widget_class_bind_template_child (widget_class, CcBluetoothPanel, enable_switch);
gtk_widget_class_bind_template_child (widget_class, CcBluetoothPanel, header_box);
gtk_widget_class_bind_template_child (widget_class, CcBluetoothPanel, no_devices_box);
gtk_widget_class_bind_template_child (widget_class, CcBluetoothPanel, hw_airplane_box);
gtk_widget_class_bind_template_child (widget_class, CcBluetoothPanel, settings_widget);
gtk_widget_class_bind_template_child (widget_class, CcBluetoothPanel, stack);
gtk_widget_class_bind_template_callback (widget_class, adapter_status_changed_cb);
gtk_widget_class_bind_template_callback (widget_class, airplane_mode_off_button_clicked_cb);
gtk_widget_class_bind_template_callback (widget_class, enable_switch_changed_cb);
gtk_widget_class_bind_template_callback (widget_class, panel_changed_cb);
}
static void
cc_bluetooth_panel_init (CcBluetoothPanel *self)
{
bluetooth_settings_widget_get_type ();
g_resources_register (cc_bluetooth_get_resource ());
gtk_widget_init_template (GTK_WIDGET (self));
/* RFKill */
self->rfkill = cc_object_storage_create_dbus_proxy_sync (G_BUS_TYPE_SESSION,
G_DBUS_PROXY_FLAGS_NONE,
"org.gnome.SettingsDaemon.Rfkill",
"/org/gnome/SettingsDaemon/Rfkill",
"org.gnome.SettingsDaemon.Rfkill",
NULL, NULL);
self->properties = cc_object_storage_create_dbus_proxy_sync (G_BUS_TYPE_SESSION,
G_DBUS_PROXY_FLAGS_NONE,
"org.gnome.SettingsDaemon.Rfkill",
"/org/gnome/SettingsDaemon/Rfkill",
"org.freedesktop.DBus.Properties",
NULL, NULL);
airplane_mode_changed (self);
g_signal_connect_object (self->rfkill, "g-properties-changed",
G_CALLBACK (airplane_mode_changed), self, G_CONNECT_SWAPPED);
}