gnome-control-center/panels/bluetooth/cc-bluetooth-panel.c
Miguel Vaello Martínez 88b6561c8e bluetooth: Center empty states in the panel
For the new or alternative version of Control Center, the Bluetooth
empty state will be vertically alligned to the center for any
app window size. Otherwise when the Bluetooh is powered and available,
the align will be as always.

This changes do not affect to the old version because the windows
size (for the old version) is always the same and small
enought to be in the center in any case.

https://bugzilla.gnome.org/show_bug.cgi?id=784720
2017-07-11 21:02:21 -03:00

357 lines
12 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 <glib/gi18n-lib.h>
#include <shell/cc-shell.h>
#include <bluetooth-settings-widget.h>
#include "cc-bluetooth-panel.h"
#include "cc-bluetooth-resources.h"
CC_PANEL_REGISTER (CcBluetoothPanel, cc_bluetooth_panel)
#define BLUETOOTH_PANEL_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CC_TYPE_BLUETOOTH_PANEL, CcBluetoothPanelPrivate))
#define WID(s) GTK_WIDGET (gtk_builder_get_object (self->priv->builder, s))
#define BLUETOOTH_NO_DEVICES_PAGE "no-devices-page"
#define BLUETOOTH_DISABLED_PAGE "disabled-page"
#define BLUETOOTH_AIRPLANE_PAGE "airplane-page"
#define BLUETOOTH_HW_AIRPLANE_PAGE "hw-airplane-page"
#define BLUETOOTH_WORKING_PAGE "working-page"
struct CcBluetoothPanelPrivate {
GtkBuilder *builder;
GtkWidget *stack;
GtkWidget *widget;
GCancellable *cancellable;
/* Killswitch */
GtkWidget *kill_switch_header;
GDBusProxy *rfkill, *properties;
gboolean airplane_mode;
gboolean bt_airplane_mode;
gboolean hardware_airplane_mode;
gboolean has_airplane_mode;
};
static void cc_bluetooth_panel_finalize (GObject *object);
static void cc_bluetooth_panel_constructed (GObject *object);
static const char *
cc_bluetooth_panel_get_help_uri (CcPanel *panel)
{
return "help:gnome-help/bluetooth";
}
static void
cc_bluetooth_panel_class_init (CcBluetoothPanelClass *klass)
{
GObjectClass *object_class = G_OBJECT_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;
g_type_class_add_private (klass, sizeof (CcBluetoothPanelPrivate));
}
static void
cc_bluetooth_panel_finalize (GObject *object)
{
CcBluetoothPanel *self;
self = CC_BLUETOOTH_PANEL (object);
g_cancellable_cancel (self->priv->cancellable);
g_clear_object (&self->priv->cancellable);
g_clear_object (&self->priv->properties);
g_clear_object (&self->priv->rfkill);
g_clear_object (&self->priv->kill_switch_header);
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 */
self->priv->kill_switch_header = g_object_ref (WID ("box_power"));
cc_shell_embed_widget_in_header (cc_panel_get_shell (CC_PANEL (self)),
self->priv->kill_switch_header);
gtk_widget_show_all (self->priv->kill_switch_header);
}
static void
power_callback (GObject *object,
GParamSpec *spec,
CcBluetoothPanel *self)
{
gboolean state;
state = gtk_switch_get_active (GTK_SWITCH (WID ("switch_bluetooth")));
g_debug ("Power switched to %s", state ? "on" : "off");
g_dbus_proxy_call (self->priv->properties,
"Set",
g_variant_new_parsed ("('org.gnome.SettingsDaemon.Rfkill', 'BluetoothAirplaneMode', %v)",
g_variant_new_boolean (!state)),
G_DBUS_CALL_FLAGS_NONE,
-1,
self->priv->cancellable,
NULL, NULL);
}
static void
cc_bluetooth_panel_update_power (CcBluetoothPanel *self)
{
GtkAlign valign;
GObject *toggle;
gboolean sensitive, powered, change_powered;
const char *page;
g_debug ("Updating airplane mode: BluetoothHasAirplaneMode %d, BluetoothHardwareAirplaneMode %d, BluetoothAirplaneMode %d, AirplaneMode %d",
self->priv->has_airplane_mode, self->priv->hardware_airplane_mode, self->priv->bt_airplane_mode, self->priv->airplane_mode);
change_powered = TRUE;
valign = GTK_ALIGN_CENTER;
if (self->priv->has_airplane_mode == FALSE) {
g_debug ("No Bluetooth available");
sensitive = FALSE;
powered = FALSE;
page = BLUETOOTH_NO_DEVICES_PAGE;
} else if (self->priv->hardware_airplane_mode) {
g_debug ("Bluetooth is Hard blocked");
sensitive = FALSE;
powered = FALSE;
page = BLUETOOTH_HW_AIRPLANE_PAGE;
} else if (self->priv->airplane_mode) {
g_debug ("Airplane mode is on, Wi-Fi and Bluetooth are disabled");
sensitive = FALSE;
powered = FALSE;
page = BLUETOOTH_AIRPLANE_PAGE;
} else if (self->priv->bt_airplane_mode ||
!bluetooth_settings_widget_get_default_adapter_powered (BLUETOOTH_SETTINGS_WIDGET (self->priv->widget))) {
g_debug ("Default adapter is unpowered, but should be available");
sensitive = TRUE;
change_powered = FALSE;
page = BLUETOOTH_DISABLED_PAGE;
} else {
g_debug ("Bluetooth is available and powered");
sensitive = TRUE;
powered = TRUE;
page = BLUETOOTH_WORKING_PAGE;
valign = GTK_ALIGN_FILL;
}
gtk_widget_set_valign (self->priv->stack, valign);
gtk_widget_set_sensitive (WID ("box_power") , sensitive);
toggle = G_OBJECT (WID ("switch_bluetooth"));
if (change_powered) {
g_signal_handlers_block_by_func (toggle, power_callback, self);
gtk_switch_set_active (GTK_SWITCH (toggle), powered);
g_signal_handlers_unblock_by_func (toggle, power_callback, self);
}
gtk_stack_set_visible_child_name (GTK_STACK (self->priv->stack), page);
}
static void
airplane_mode_changed (GDBusProxy *proxy,
GVariant *changed_properties,
GStrv invalidated_properties,
CcBluetoothPanel *self)
{
GVariant *v;
v = g_dbus_proxy_get_cached_property (self->priv->rfkill, "AirplaneMode");
self->priv->airplane_mode = g_variant_get_boolean (v);
g_variant_unref (v);
v = g_dbus_proxy_get_cached_property (self->priv->rfkill, "BluetoothAirplaneMode");
self->priv->bt_airplane_mode = g_variant_get_boolean (v);
g_variant_unref (v);
v = g_dbus_proxy_get_cached_property (self->priv->rfkill, "BluetoothHardwareAirplaneMode");
self->priv->hardware_airplane_mode = g_variant_get_boolean (v);
g_variant_unref (v);
v = g_dbus_proxy_get_cached_property (self->priv->rfkill, "BluetoothHasAirplaneMode");
self->priv->has_airplane_mode = g_variant_get_boolean (v);
g_variant_unref (v);
cc_bluetooth_panel_update_power (self);
}
static void
on_airplane_mode_off_clicked (GtkButton *button,
CcBluetoothPanel *self)
{
g_debug ("Airplane Mode Off clicked, disabling airplane mode");
g_dbus_proxy_call (self->priv->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,
self->priv->cancellable,
NULL, NULL);
}
static void
add_stack_page (CcBluetoothPanel *self,
const char *message,
const char *explanation,
const char *name)
{
GtkWidget *label, *image, *box;
char *str;
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
g_object_set (G_OBJECT (box), "margin-top", 64, "margin-bottom", 64, NULL);
if (g_str_equal (name, BLUETOOTH_AIRPLANE_PAGE) ||
g_str_equal (name, BLUETOOTH_HW_AIRPLANE_PAGE)) {
image = gtk_image_new_from_icon_name ("airplane-mode-symbolic",
GTK_ICON_SIZE_DIALOG);
} else {
image = gtk_image_new_from_icon_name ("bluetooth-active-symbolic",
GTK_ICON_SIZE_DIALOG);
}
gtk_image_set_pixel_size (GTK_IMAGE (image), 192);
gtk_style_context_add_class (gtk_widget_get_style_context (image), "dim-label");
gtk_box_pack_start (GTK_BOX (box), image, FALSE, FALSE, 24);
str = g_strdup_printf ("<span size=\"larger\" weight=\"bold\">%s</span>", message);
label = gtk_label_new ("");
gtk_label_set_markup (GTK_LABEL (label), str);
g_free (str);
gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 0);
label = gtk_label_new (explanation);
gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 0);
if (g_str_equal (name, BLUETOOTH_AIRPLANE_PAGE)) {
GtkWidget *button, *alignment;
button = gtk_button_new_with_label (_("Turn Off Airplane Mode"));
alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
gtk_container_add (GTK_CONTAINER (alignment), button);
g_signal_connect (G_OBJECT (button), "clicked",
G_CALLBACK (on_airplane_mode_off_clicked), self);
gtk_box_pack_start (GTK_BOX (box), alignment, FALSE, FALSE, 24);
}
gtk_stack_add_named (GTK_STACK (self->priv->stack), box, name);
gtk_widget_show_all (box);
}
static void
panel_changed (GtkWidget *settings_widget,
const char *panel,
CcBluetoothPanel *self)
{
CcShell *shell;
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);
g_error_free (error);
}
}
static void
cc_bluetooth_panel_init (CcBluetoothPanel *self)
{
GError *error = NULL;
self->priv = BLUETOOTH_PANEL_PRIVATE (self);
g_resources_register (cc_bluetooth_get_resource ());
self->priv->builder = gtk_builder_new ();
gtk_builder_set_translation_domain (self->priv->builder, GETTEXT_PACKAGE);
gtk_builder_add_from_resource (self->priv->builder,
"/org/gnome/control-center/bluetooth/bluetooth.ui",
&error);
if (error != NULL) {
g_warning ("Could not load ui: %s", error->message);
g_error_free (error);
return;
}
self->priv->cancellable = g_cancellable_new ();
/* RFKill */
self->priv->rfkill = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
G_DBUS_PROXY_FLAGS_NONE,
NULL,
"org.gnome.SettingsDaemon.Rfkill",
"/org/gnome/SettingsDaemon/Rfkill",
"org.gnome.SettingsDaemon.Rfkill",
NULL, NULL);
self->priv->properties = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
G_DBUS_PROXY_FLAGS_NONE,
NULL,
"org.gnome.SettingsDaemon.Rfkill",
"/org/gnome/SettingsDaemon/Rfkill",
"org.freedesktop.DBus.Properties",
NULL, NULL);
self->priv->stack = gtk_stack_new ();
gtk_stack_set_homogeneous (GTK_STACK (self->priv->stack), TRUE);
add_stack_page (self, _("No Bluetooth Found"), _("Plug in a dongle to use Bluetooth."), BLUETOOTH_NO_DEVICES_PAGE);
add_stack_page (self, _("Bluetooth Turned Off"), _("Turn on to connect devices and receive file transfers."), BLUETOOTH_DISABLED_PAGE);
add_stack_page (self, _("Airplane Mode is on"), _("Bluetooth is disabled when airplane mode is on."), BLUETOOTH_AIRPLANE_PAGE);
add_stack_page (self, _("Hardware Airplane Mode is on"), _("Turn off the Airplane mode switch to enable Bluetooth."), BLUETOOTH_HW_AIRPLANE_PAGE);
self->priv->widget = bluetooth_settings_widget_new ();
g_signal_connect (G_OBJECT (self->priv->widget), "panel-changed",
G_CALLBACK (panel_changed), self);
gtk_stack_add_named (GTK_STACK (self->priv->stack),
self->priv->widget, BLUETOOTH_WORKING_PAGE);
gtk_widget_show (self->priv->widget);
gtk_widget_show (self->priv->stack);
gtk_container_add (GTK_CONTAINER (self), self->priv->stack);
airplane_mode_changed (NULL, NULL, NULL, self);
g_signal_connect (self->priv->rfkill, "g-properties-changed",
G_CALLBACK (airplane_mode_changed), self);
g_signal_connect_swapped (G_OBJECT (self->priv->widget), "adapter-status-changed",
G_CALLBACK (cc_bluetooth_panel_update_power), self);
g_signal_connect (G_OBJECT (WID ("switch_bluetooth")), "notify::active",
G_CALLBACK (power_callback), self);
}