[gnome-control-center/wip/gbsneto/new-wifi-panel] wifi: Introduce Wi-Fi panel



commit f7f7d10dec89dc4b88a2c295ee4c170500056126
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date:   Tue Jul 11 16:37:47 2017 -0300

    wifi: Introduce Wi-Fi panel
    
    The glory moment has come. The new Wi-Fi panel is finally
    introduced using a different code style from the rest of
    the Network panel, since Control Center itself is written
    using the GTK+ C code style.
    
    The Wi-Fi panel uses modern GTK+ features like template
    classes and new widgets. The files are stored together
    with the Network panel so that we can reuse the abstraction
    layer that the Network panel has to manage devices.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=784818

 configure.ac                                  |    1 +
 panels/network/Makefile.am                    |    6 +-
 panels/network/cc-wifi-panel.c                |  631 +++++++++++++++++++++++++
 panels/network/cc-wifi-panel.h                |   34 ++
 panels/network/gnome-wifi-panel.desktop.in.in |   18 +
 panels/network/network.gresource.xml          |    4 +
 panels/network/wifi.ui                        |  327 +++++++++++++
 shell/cc-panel-loader.c                       |    2 +
 8 files changed, 1021 insertions(+), 2 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 81e4df9..55f5ad3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -542,6 +542,7 @@ panels/network/Makefile
 panels/network/wireless-security/Makefile
 panels/network/connection-editor/Makefile
 panels/network/gnome-network-panel.desktop.in
+panels/network/gnome-wifi-panel.desktop.in
 panels/notifications/Makefile
 panels/notifications/gnome-notifications-panel.desktop.in
 panels/universal-access/Makefile
diff --git a/panels/network/Makefile.am b/panels/network/Makefile.am
index ed206d7..fb2b891 100644
--- a/panels/network/Makefile.am
+++ b/panels/network/Makefile.am
@@ -39,7 +39,9 @@ libnetwork_la_SOURCES =                                       \
        network-dialogs.c                               \
        network-dialogs.h                               \
        cc-network-panel.c                              \
-       cc-network-panel.h
+       cc-network-panel.h                              \
+       cc-wifi-panel.c                                 \
+       cc-wifi-panel.h
 
 libnetwork_la_LIBADD = $(PANEL_LIBS) $(NETWORK_PANEL_LIBS) $(NETWORK_MANAGER_LIBS) 
$(builddir)/connection-editor/libconnection-editor.la
 
@@ -54,7 +56,7 @@ cc-network-resources.h: network.gresource.xml $(resource_files)
 @INTLTOOL_DESKTOP_RULE@
 
 desktopdir = $(datadir)/applications
-desktop_in_files = gnome-network-panel.desktop.in
+desktop_in_files = gnome-network-panel.desktop.in gnome-wifi-panel.desktop.in
 desktop_DATA = $(desktop_in_files:.desktop.in=.desktop)
 
 CLEANFILES = $(desktop_in_files) $(desktop_DATA) $(BUILT_SOURCES)
diff --git a/panels/network/cc-wifi-panel.c b/panels/network/cc-wifi-panel.c
new file mode 100644
index 0000000..89fcc3d
--- /dev/null
+++ b/panels/network/cc-wifi-panel.c
@@ -0,0 +1,631 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2017 Georges Basile Stavracas Neto <georges stavracas gmail com>
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "cc-network-resources.h"
+#include "cc-wifi-panel.h"
+#include "net-device.h"
+#include "net-device-wifi.h"
+#include "network-dialogs.h"
+
+#include "shell/list-box-helper.h"
+
+#include <glib/gi18n.h>
+#include <NetworkManager.h>
+
+typedef enum
+{
+  OPERATION_NULL,
+  OPERATION_SHOW_DEVICE,
+  OPERATION_CREATE_WIFI,
+  OPERATION_CONNECT_HIDDEN,
+  OPERATION_CONNECT_8021X
+} CmdlineOperation;
+
+struct _CcWifiPanel
+{
+  CcPanel             parent;
+
+  /* RFKill (Airplane Mode) */
+  GDBusProxy         *rfkill_proxy;
+  GtkSwitch          *rfkill_switch;
+  GtkWidget          *rfkill_widget;
+
+  /* Main widgets */
+  GtkStack           *center_stack;
+  GtkStack           *header_stack;
+  GtkStack           *main_stack;
+  GtkSizeGroup       *sizegroup;
+  GtkStack           *stack;
+
+  NMClient           *client;
+
+  GPtrArray          *devices;
+
+  GCancellable       *cancellable;
+
+  /* Command-line arguments */
+  CmdlineOperation    arg_operation;
+  gchar              *arg_device;
+  gchar              *arg_access_point;
+};
+
+static void          rfkill_switch_notify_activate_cb            (GtkSwitch          *rfkill_switch,
+                                                                  GParamSpec         *pspec,
+                                                                  CcWifiPanel        *self);
+
+static void          update_devices_names                        (CcWifiPanel        *self);
+
+G_DEFINE_TYPE (CcWifiPanel, cc_wifi_panel, CC_TYPE_PANEL)
+
+enum
+{
+  PROP_0,
+  PROP_PARAMETERS,
+  N_PROPS
+};
+
+/* Auxiliary methods */
+
+static void
+add_wifi_device (CcWifiPanel *self,
+                 NMDevice    *device)
+{
+  GtkWidget *header_widget;
+  NetObject *net_device;
+
+  /* Only manage Wi-Fi devices */
+  if (!NM_IS_DEVICE_WIFI (device))
+    return;
+
+  /* Create the NetDevice */
+  net_device = g_object_new (NET_TYPE_DEVICE_WIFI,
+                             "panel", self,
+                             "removable", FALSE,
+                             "cancellable", self->cancellable,
+                             "client", self->client,
+                             "nm-device", device,
+                             "id", nm_device_get_udi (device),
+                             NULL);
+
+  net_object_add_to_stack (net_device, self->stack, self->sizegroup);
+
+  /* And add to the header widgets */
+  header_widget = net_device_wifi_get_header_widget (NET_DEVICE_WIFI (net_device));
+
+  gtk_stack_add_named (self->header_stack, header_widget, net_object_get_id (net_device));
+
+  /* Setup custom title properties */
+  g_ptr_array_add (self->devices, net_device);
+
+  update_devices_names (self);
+}
+
+static void
+check_main_stack_page (CcWifiPanel *self)
+{
+  const gchar *nm_version;
+
+  nm_version = nm_client_get_version (self->client);
+
+  if (!nm_version)
+    gtk_stack_set_visible_child_name (self->main_stack, "nm-not-running");
+  else if (self->devices->len == 0)
+    gtk_stack_set_visible_child_name (self->main_stack, "no-wifi-devices");
+  else
+    gtk_stack_set_visible_child_name (self->main_stack, "wifi-connections");
+
+}
+
+static void
+load_wifi_devices (CcWifiPanel *self)
+{
+  const GPtrArray *devices;
+  guint i;
+
+  devices = nm_client_get_devices (self->client);
+
+  /* Cold-plug existing devices */
+  for (i = 0; i < devices->len; i++)
+    add_wifi_device (self, g_ptr_array_index (devices, i));
+
+  check_main_stack_page (self);
+}
+
+static inline gboolean
+get_cached_rfkill_property (CcWifiPanel *self,
+                            const gchar *property)
+{
+  g_autoptr (GVariant) result;
+
+  result = g_dbus_proxy_get_cached_property (self->rfkill_proxy, property);
+  return result ? g_variant_get_boolean (result) : FALSE;
+}
+
+static void
+sync_airplane_mode_switch (CcWifiPanel *self)
+{
+  gboolean enabled, should_show, hw_enabled;
+
+  enabled = get_cached_rfkill_property (self, "HasAirplaneMode");
+  should_show = get_cached_rfkill_property (self, "ShouldShowAirplaneMode");
+
+  gtk_widget_set_visible (GTK_WIDGET (self->rfkill_widget), enabled && should_show);
+  if (!enabled || !should_show)
+    return;
+
+  enabled = get_cached_rfkill_property (self, "AirplaneMode");
+  hw_enabled = get_cached_rfkill_property (self, "HardwareAirplaneMode");
+
+  enabled |= hw_enabled;
+
+  if (enabled != gtk_switch_get_active (self->rfkill_switch))
+    {
+      g_signal_handlers_block_by_func (self->rfkill_switch,
+                                       rfkill_switch_notify_activate_cb,
+                                       self);
+      gtk_switch_set_active (self->rfkill_switch, enabled);
+      g_signal_handlers_unblock_by_func (self->rfkill_switch,
+                                         rfkill_switch_notify_activate_cb,
+                                         self);
+  }
+
+  gtk_widget_set_sensitive (GTK_WIDGET (self->rfkill_switch), !hw_enabled);
+
+  check_main_stack_page (self);
+}
+
+static void
+update_devices_names (CcWifiPanel *self)
+{
+  guint number_of_devices = self->devices->len;
+
+  if (number_of_devices == 1)
+    {
+      GtkWidget *title_widget;
+      NetObject *net_device;
+
+      net_device = g_ptr_array_index (self->devices, 0);
+      title_widget = net_device_wifi_get_title_widget (NET_DEVICE_WIFI (net_device));
+
+      gtk_stack_add_named (self->center_stack, title_widget, "single");
+      gtk_stack_set_visible_child_name (self->center_stack, "single");
+
+      net_object_set_title (net_device, _("Wi-Fi"));
+    }
+  else
+    {
+      GtkWidget *single_page_widget;
+      guint i;
+
+      for (i = 0; i < number_of_devices; i++)
+        {
+          NetObject *object;
+          NMDevice *device;
+
+          object = g_ptr_array_index (self->devices, i);
+          device = net_device_get_nm_device (NET_DEVICE (object));
+
+          net_object_set_title (object, nm_device_get_product (device));
+        }
+
+      /* Remove the widget at the "single" page */
+      single_page_widget = gtk_stack_get_child_by_name (self->center_stack, "single");
+
+      if (single_page_widget)
+        {
+          g_object_ref (single_page_widget);
+          gtk_container_remove (GTK_CONTAINER (self->center_stack), single_page_widget);
+        }
+
+      /* Show the stack-switcher page */
+      gtk_stack_set_visible_child_name (self->center_stack, "many");
+    }
+}
+
+/* Command-line arguments */
+
+static void
+reset_command_line_args (CcWifiPanel *self)
+{
+  self->arg_operation = OPERATION_NULL;
+  g_clear_pointer (&self->arg_device, g_free);
+  g_clear_pointer (&self->arg_access_point, g_free);
+}
+
+static gboolean
+handle_argv_for_device (CcWifiPanel *self,
+                        NetObject   *net_object)
+{
+  GtkWidget *toplevel;
+  NMDevice *device;
+  gboolean ret;
+
+  toplevel = cc_shell_get_toplevel (cc_panel_get_shell (CC_PANEL (self)));
+  device = net_device_get_nm_device (NET_DEVICE (net_object));
+  ret = FALSE;
+
+  if (self->arg_operation == OPERATION_CREATE_WIFI)
+    {
+      cc_network_panel_create_wifi_network (toplevel, self->client);
+      ret = TRUE;
+    }
+  else if (self->arg_operation == OPERATION_CONNECT_HIDDEN)
+    {
+      cc_network_panel_connect_to_hidden_network (toplevel, self->client);
+      ret = TRUE;
+    }
+  else if (g_str_equal (nm_object_get_path (NM_OBJECT (device)), self->arg_device))
+    {
+      if (self->arg_operation == OPERATION_CONNECT_8021X)
+        {
+          cc_network_panel_connect_to_8021x_network (toplevel,
+                                                     self->client,
+                                                     device,
+                                                     self->arg_access_point);
+          ret = TRUE;
+        }
+      else if (self->arg_operation == OPERATION_SHOW_DEVICE)
+        {
+          gtk_stack_set_visible_child_name (self->stack, net_object_get_id (net_object));
+          ret = TRUE;
+        }
+    }
+
+  if (ret)
+    reset_command_line_args (self);
+
+  return ret;
+}
+
+static void
+handle_argv (CcWifiPanel *self)
+{
+  guint i;
+
+  if (self->arg_operation == OPERATION_NULL)
+    return;
+
+  for (i = 0; i < self->devices->len; i++)
+    {
+      if (handle_argv_for_device (self, g_ptr_array_index (self->devices, i)))
+        break;
+    }
+}
+
+static GPtrArray *
+variant_av_to_string_array (GVariant *array)
+{
+  GVariantIter iter;
+  GVariant *v;
+  GPtrArray *strv;
+  gsize count;
+
+  count = g_variant_iter_init (&iter, array);
+  strv = g_ptr_array_sized_new (count + 1);
+
+  while (g_variant_iter_next (&iter, "v", &v))
+    {
+      g_ptr_array_add (strv, (gpointer) g_variant_get_string (v, NULL));
+      g_variant_unref (v);
+    }
+
+  g_ptr_array_add (strv, NULL); /* NULL-terminate the strv data array */
+  return strv;
+}
+
+static gboolean
+verify_argv (CcWifiPanel  *self,
+             const char  **args)
+{
+  switch (self->arg_operation)
+    {
+    case OPERATION_CONNECT_8021X:
+    case OPERATION_SHOW_DEVICE:
+      if (!self->arg_device)
+        {
+          g_warning ("Operation %s requires an object path", args[0]);
+          return FALSE;
+        }
+    default:
+      return TRUE;
+    }
+}
+
+/* Callbacks */
+
+static void
+device_added_cb (NMClient    *client,
+                 NMDevice    *device,
+                 CcWifiPanel *self)
+{
+  add_wifi_device (self, device);
+  check_main_stack_page (self);
+}
+
+static void
+device_removed_cb (NMClient    *client,
+                   NMDevice    *device,
+                   CcWifiPanel *self)
+{
+  GtkWidget *child;
+  const gchar *id;
+  guint i;
+
+  if (!NM_IS_DEVICE_WIFI (device))
+    return;
+
+  id = nm_device_get_udi (device);
+
+  /* Destroy all stack pages related to this device */
+  child = gtk_stack_get_child_by_name (self->stack, id);
+  gtk_widget_destroy (child);
+
+  child = gtk_stack_get_child_by_name (self->header_stack, id);
+  gtk_widget_destroy (child);
+
+  /* Remove from the devices list */
+  for (i = 0; i < self->devices->len; i++)
+    {
+      NetObject *object = g_ptr_array_index (self->devices, 0);
+
+      if (g_strcmp0 (net_object_get_id (object), id) == 0)
+        {
+          g_ptr_array_remove (self->devices, object);
+          break;
+        }
+    }
+
+  /* Update the title widget */
+  update_devices_names (self);
+
+  /* And check which page should be visible */
+  check_main_stack_page (self);
+}
+
+static void
+rfkill_proxy_acquired_cb (GObject      *source_object,
+                          GAsyncResult *res,
+                          gpointer      user_data)
+{
+  CcWifiPanel *self = CC_WIFI_PANEL (user_data);
+  GError *error = NULL;
+
+  self->rfkill_proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
+
+  if (error)
+    {
+      if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+        g_printerr ("Error creating rfkill proxy: %s\n", error->message);
+
+      g_error_free (error);
+      return;
+    }
+
+  sync_airplane_mode_switch (self);
+}
+
+static void
+rfkill_switch_notify_activate_cb (GtkSwitch   *rfkill_switch,
+                                  GParamSpec  *pspec,
+                                  CcWifiPanel *self)
+{
+  gboolean enable;
+
+  enable = gtk_switch_get_active (rfkill_switch);
+
+  g_dbus_proxy_call (self->rfkill_proxy,
+                     "org.freedesktop.DBus.Properties.Set",
+                     g_variant_new_parsed ("('org.gnome.SettingsDaemon.Rfkill',"
+                                           "'AirplaneMode', %v)",
+                                           g_variant_new_boolean (enable)),
+                     G_DBUS_CALL_FLAGS_NONE,
+                     -1,
+                     self->cancellable,
+                     NULL,
+                     NULL);
+}
+
+/* Overrides */
+
+static const gchar *
+cc_wifi_panel_get_help_uri (CcPanel *panel)
+{
+  return "help:gnome-help/wifi";
+}
+
+static GtkWidget *
+cc_wifi_panel_get_title_widget (CcPanel *panel)
+{
+  CcWifiPanel *self = CC_WIFI_PANEL (panel);
+
+  return GTK_WIDGET (self->center_stack);
+}
+
+static void
+cc_wifi_panel_constructed (GObject *object)
+{
+  CcWifiPanel *self;
+  CcShell *shell;
+
+  self = CC_WIFI_PANEL (object);
+  shell = cc_panel_get_shell (CC_PANEL (object));
+
+  G_OBJECT_CLASS (cc_wifi_panel_parent_class)->constructed (object);
+
+  cc_shell_embed_widget_in_header (shell, GTK_WIDGET (self->header_stack));
+}
+
+static void
+cc_wifi_panel_finalize (GObject *object)
+{
+  CcWifiPanel *self = (CcWifiPanel *)object;
+
+  g_cancellable_cancel (self->cancellable);
+
+  g_clear_object (&self->cancellable);
+  g_clear_object (&self->client);
+  g_clear_object (&self->rfkill_proxy);
+
+  g_clear_pointer (&self->devices, g_ptr_array_unref);
+
+  reset_command_line_args (self);
+
+  G_OBJECT_CLASS (cc_wifi_panel_parent_class)->finalize (object);
+}
+
+static void
+cc_wifi_panel_get_property (GObject    *object,
+                            guint       prop_id,
+                            GValue     *value,
+                            GParamSpec *pspec)
+{
+  G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+}
+
+static void
+cc_wifi_panel_set_property (GObject      *object,
+                            guint         prop_id,
+                            const GValue *value,
+                            GParamSpec   *pspec)
+{
+  CcWifiPanel *self = CC_WIFI_PANEL (object);
+  GVariant *parameters;
+
+  switch (prop_id)
+    {
+    case PROP_PARAMETERS:
+      reset_command_line_args (self);
+
+      parameters = g_value_get_variant (value);
+
+      if (parameters)
+        {
+          GPtrArray *array;
+          const gchar **args;
+
+          array = variant_av_to_string_array (parameters);
+          args = (const gchar **) array->pdata;
+
+          if (args[0])
+            {
+              if (g_str_equal (args[0], "create-wifi"))
+                self->arg_operation = OPERATION_CREATE_WIFI;
+              else if (g_str_equal (args[0], "connect-hidden-wifi"))
+                self->arg_operation = OPERATION_CONNECT_HIDDEN;
+              else if (g_str_equal (args[0], "connect-8021x-wifi"))
+                self->arg_operation = OPERATION_CONNECT_8021X;
+              else if (g_str_equal (args[0], "show-device"))
+                self->arg_operation = OPERATION_SHOW_DEVICE;
+              else
+                self->arg_operation = OPERATION_NULL;
+            }
+
+          if (args[0] && args[1])
+            self->arg_device = g_strdup (args[1]);
+          if (args[0] && args[1] && args[2])
+            self->arg_access_point = g_strdup (args[2]);
+
+          if (!verify_argv (self, (const char **) args))
+            {
+              reset_command_line_args (self);
+              g_ptr_array_unref (array);
+              return;
+            }
+
+          g_ptr_array_unref (array);
+
+          handle_argv (self);
+        }
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+cc_wifi_panel_class_init (CcWifiPanelClass *klass)
+{
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  CcPanelClass *panel_class = CC_PANEL_CLASS (klass);
+
+  panel_class->get_help_uri = cc_wifi_panel_get_help_uri;
+  panel_class->get_title_widget = cc_wifi_panel_get_title_widget;
+
+  object_class->constructed = cc_wifi_panel_constructed;
+  object_class->finalize = cc_wifi_panel_finalize;
+  object_class->get_property = cc_wifi_panel_get_property;
+  object_class->set_property = cc_wifi_panel_set_property;
+
+  gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/network/wifi.ui");
+
+  gtk_widget_class_bind_template_child (widget_class, CcWifiPanel, center_stack);
+  gtk_widget_class_bind_template_child (widget_class, CcWifiPanel, header_stack);
+  gtk_widget_class_bind_template_child (widget_class, CcWifiPanel, main_stack);
+  gtk_widget_class_bind_template_child (widget_class, CcWifiPanel, rfkill_switch);
+  gtk_widget_class_bind_template_child (widget_class, CcWifiPanel, rfkill_widget);
+  gtk_widget_class_bind_template_child (widget_class, CcWifiPanel, sizegroup);
+  gtk_widget_class_bind_template_child (widget_class, CcWifiPanel, stack);
+
+  gtk_widget_class_bind_template_callback (widget_class, rfkill_switch_notify_activate_cb);
+
+  g_object_class_override_property (object_class, PROP_PARAMETERS, "parameters");
+}
+
+static void
+cc_wifi_panel_init (CcWifiPanel *self)
+{
+  g_resources_register (cc_network_get_resource ());
+
+  gtk_widget_init_template (GTK_WIDGET (self));
+
+  self->cancellable = g_cancellable_new ();
+  self->devices = g_ptr_array_new_with_free_func (g_object_unref);
+
+  /* Load NetworkManager */
+  self->client = nm_client_new (NULL, NULL);
+
+  g_signal_connect (self->client,
+                    "device-added",
+                    G_CALLBACK (device_added_cb),
+                    self);
+
+  g_signal_connect (self->client,
+                    "device-removed",
+                    G_CALLBACK (device_removed_cb),
+                    self);
+
+  /* Load Wi-Fi devices */
+  load_wifi_devices (self);
+
+  /* Acquire Airplane Mode proxy */
+  g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
+                            G_DBUS_PROXY_FLAGS_NONE,
+                            NULL,
+                            "org.gnome.SettingsDaemon.Rfkill",
+                            "/org/gnome/SettingsDaemon/Rfkill",
+                            "org.gnome.SettingsDaemon.Rfkill",
+                            self->cancellable,
+                            rfkill_proxy_acquired_cb,
+                            self);
+
+  /* Handle comment-line arguments after loading devices */
+  handle_argv (self);
+}
diff --git a/panels/network/cc-wifi-panel.h b/panels/network/cc-wifi-panel.h
new file mode 100644
index 0000000..43ad4bf
--- /dev/null
+++ b/panels/network/cc-wifi-panel.h
@@ -0,0 +1,34 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2017 Georges Basile Stavracas Neto <georges stavracas gmail com>
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef CC_WIFI_PANEL_H
+#define CC_WIFI_PANEL_H
+
+#include <shell/cc-panel.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_WIFI_PANEL (cc_wifi_panel_get_type())
+
+G_DECLARE_FINAL_TYPE (CcWifiPanel, cc_wifi_panel, CC, WIFI_PANEL, CcPanel)
+
+G_END_DECLS
+
+#endif /* CC_WIFI_PANEL_H */
+
diff --git a/panels/network/gnome-wifi-panel.desktop.in.in b/panels/network/gnome-wifi-panel.desktop.in.in
new file mode 100644
index 0000000..b37e650
--- /dev/null
+++ b/panels/network/gnome-wifi-panel.desktop.in.in
@@ -0,0 +1,18 @@
+[Desktop Entry]
+# Translators: Add soft hyphens to your translations so that the icon view won't clip your translations. See 
https://bugzilla.gnome.org/show_bug.cgi?id=647087#c13 for details
+_Name=Wi-Fi
+_Comment=Control how you connect to Wi-Fi networks
+Exec=gnome-control-center wifi
+Icon=network-wireless
+Terminal=false
+Type=Application
+NoDisplay=true
+StartupNotify=true
+Categories=GNOME;GTK;Settings;HardwareSettings;X-GNOME-Settings-Panel;X-GNOME-ConnectivitySettings;
+OnlyShowIn=GNOME;Unity;
+X-GNOME-Bugzilla-Bugzilla=GNOME
+X-GNOME-Bugzilla-Product=gnome-control-center
+X-GNOME-Bugzilla-Component=network
+X-GNOME-Bugzilla-Version=@VERSION@
+# Translators: those are keywords for the wi-fi control-center panel
+_Keywords=Network;Wireless;Wi-Fi;Wifi;IP;LAN;Broadband;DNS;
diff --git a/panels/network/network.gresource.xml b/panels/network/network.gresource.xml
index 9dbb815..3532b7c 100644
--- a/panels/network/network.gresource.xml
+++ b/panels/network/network.gresource.xml
@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <gresources>
   <gresource prefix="/org/gnome/control-center/network">
+    <!-- Network panel -->
     <file preprocess="xml-stripblanks">network.ui</file>
     <file preprocess="xml-stripblanks">network-proxy.ui</file>
     <file preprocess="xml-stripblanks">network-vpn.ui</file>
@@ -8,5 +9,8 @@
     <file preprocess="xml-stripblanks">network-simple.ui</file>
     <file preprocess="xml-stripblanks">network-mobile.ui</file>
     <file preprocess="xml-stripblanks">network-ethernet.ui</file>
+
+    <!-- Wi-Fi panel -->
+    <file preprocess="xml-stripblanks">wifi.ui</file>
   </gresource>
 </gresources>
diff --git a/panels/network/wifi.ui b/panels/network/wifi.ui
new file mode 100644
index 0000000..7252748
--- /dev/null
+++ b/panels/network/wifi.ui
@@ -0,0 +1,327 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <requires lib="gtk+" version="3.20"/>
+  <template class="CcWifiPanel" parent="CcPanel">
+    <property name="visible">True</property>
+    <property name="can-focus">False</property>
+    <child>
+      <object class="GtkStack" id="main_stack">
+        <property name="visible">True</property>
+        <property name="can-focus">True</property>
+        <property name="homogeneous">False</property>
+        <property name="transition_type">crossfade</property>
+
+        <!-- "No Wi-Fi Adapter" page -->
+        <child>
+          <object class="GtkBox">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="expand">True</property>
+            <property name="halign">center</property>
+            <property name="valign">center</property>
+            <property name="orientation">vertical</property>
+            <property name="margin">18</property>
+            <property name="spacing">18</property>
+            <child type="center">
+              <object class="GtkImage">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="icon_name">network-wireless-no-route-symbolic</property>
+                <property name="pixel_size">128</property>
+                <style>
+                  <class name="dim-label" />
+                </style>
+              </object>
+            </child>
+            <child>
+              <object class="GtkLabel">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="wrap">True</property>
+                <property name="label" translatable="yes">Make sure you have a Wi-Fi adapter plugged and 
turned on</property>
+              </object>
+              <packing>
+                <property name="pack-type">end</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="wrap">True</property>
+                <property name="label" translatable="yes">No Wi-Fi Adapter Found</property>
+                <attributes>
+                  <attribute name="scale" value="1.42" />
+                </attributes>
+              </object>
+              <packing>
+                <property name="pack-type">end</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="name">no-wifi-devices</property>
+          </packing>
+        </child>
+
+        <!-- Wi-Fi connections and devices -->
+        <child>
+          <object class="GtkScrolledWindow">
+            <property name="visible">True</property>
+            <property name="can-focus">True</property>
+            <property name="hscrollbar-policy">never</property>
+            <child>
+              <object class="GtkViewport">
+                <property name="visible">True</property>
+                <property name="shadow-type">none</property>
+                <child>
+                  <object class="GtkGrid">
+                    <property name="visible">True</property>
+                    <property name="border-width">24</property>
+                    <property name="row-spacing">18</property>
+
+                    <!-- Empty boxes to enforce 1/3 width for the main widgets -->
+                    <child>
+                      <object class="GtkBox">
+                        <property name="visible">True</property>
+                        <property name="hexpand">True</property>
+                      </object>
+                      <packing>
+                        <property name="left-attach">0</property>
+                        <property name="top-attach">0</property>
+                        <property name="height">3</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkBox">
+                        <property name="visible">True</property>
+                        <property name="hexpand">True</property>
+                      </object>
+                      <packing>
+                        <property name="left-attach">2</property>
+                        <property name="top-attach">0</property>
+                        <property name="height">3</property>
+                      </packing>
+                    </child>
+
+                    <!-- Airplane Mode -->
+                    <child>
+                      <object class="GtkFrame" id="rfkill_widget">
+                        <property name="visible">True</property>
+                        <property name="vexpand">False</property>
+                        <child>
+                          <object class="GtkListBox">
+                            <property name="visible">True</property>
+                            <property name="selection-mode">none</property>
+                            <child>
+                              <object class="GtkListBoxRow">
+                                <property name="visible">True</property>
+                                <property name="can-focus">True</property>
+                                <property name="activatable">False</property>
+                                <child>
+                                  <object class="GtkGrid">
+                                    <property name="visible">True</property>
+                                    <property name="border-width">12</property>
+                                    <property name="column-spacing">12</property>
+                                    <child>
+                                      <object class="GtkLabel">
+                                        <property name="visible">True</property>
+                                        <property name="hexpand">True</property>
+                                        <property name="label" translatable="yes">Airplane Mode</property>
+                                        <property name="xalign">0.0</property>
+                                        <attributes>
+                                          <attribute name="weight" value="bold"/>
+                                        </attributes>
+                                      </object>
+                                      <packing>
+                                        <property name="left-attach">0</property>
+                                        <property name="top-attach">0</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkLabel">
+                                        <property name="visible">True</property>
+                                        <property name="hexpand">True</property>
+                                        <property name="label" translatable="yes">Disables Wi-Fi, Bluetooth 
and mobile broadband</property>
+                                        <property name="xalign">0.0</property>
+                                        <attributes>
+                                          <attribute name="scale" value="0.88"/>
+                                        </attributes>
+                                        <style>
+                                          <class name="dim-label"/>
+                                        </style>
+                                      </object>
+                                      <packing>
+                                        <property name="left-attach">0</property>
+                                        <property name="top-attach">1</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkSwitch" id="rfkill_switch">
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">True</property>
+                                        <property name="valign">center</property>
+                                        <signal name="notify::active" 
handler="rfkill_switch_notify_activate_cb" object="CcWifiPanel" swapped="no" />
+                                      </object>
+                                      <packing>
+                                        <property name="left-attach">1</property>
+                                        <property name="top-attach">0</property>
+                                        <property name="height">2</property>
+                                      </packing>
+                                    </child>
+                                  </object>
+                                </child>
+                              </object>
+                            </child>
+                          </object>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="left-attach">1</property>
+                        <property name="top-attach">0</property>
+                      </packing>
+                    </child>
+
+                    <!-- Visible Networks label & spinner -->
+                    <child>
+                      <object class="GtkBox">
+                        <property name="visible">True</property>
+                        <property name="hexpand">True</property>
+                        <property name="halign">start</property>
+                        <property name="spacing">6</property>
+                        <child>
+                          <object class="GtkLabel">
+                            <property name="visible">True</property>
+                            <property name="label" translatable="yes">Visible Networks</property>
+                            <property name="xalign">0.0</property>
+                            <attributes>
+                              <attribute name="weight" value="bold"/>
+                            </attributes>
+                          </object>
+                        </child>
+                        <child>
+                          <object class="GtkSpinner" id="spinner">
+                            <property name="hexpand">True</property>
+                          </object>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="left-attach">1</property>
+                        <property name="top-attach">1</property>
+                      </packing>
+                    </child>
+
+                    <!-- Stack with a listbox for each Wi-Fi device -->
+                    <child>
+                      <object class="GtkFrame">
+                        <property name="visible">True</property>
+                        <property name="valign">start</property>
+                        <style>
+                          <class name="view" />
+                        </style>
+                        <child>
+                          <object class="GtkStack" id="stack">
+                            <property name="visible">True</property>
+                            <property name="hexpand">True</property>
+                            <property name="vexpand">True</property>
+                            <property name="transition_type">crossfade</property>
+                          </object>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="left-attach">1</property>
+                        <property name="top-attach">2</property>
+                      </packing>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="name">wifi-connections</property>
+          </packing>
+        </child>
+
+        <!-- "NetworkManager Not Running" page -->
+        <child>
+          <object class="GtkBox">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="expand">True</property>
+            <property name="halign">center</property>
+            <property name="valign">center</property>
+            <property name="orientation">vertical</property>
+            <property name="margin">18</property>
+            <property name="spacing">18</property>
+            <child type="center">
+              <object class="GtkImage">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="icon_name">face-sad-symbolic</property>
+                <property name="pixel_size">128</property>
+                <style>
+                  <class name="dim-label" />
+                </style>
+              </object>
+            </child>
+            <child>
+              <object class="GtkLabel">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="wrap">True</property>
+                <property name="label" translatable="yes">NetworkManager needs to be running</property>
+              </object>
+              <packing>
+                <property name="pack-type">end</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="wrap">True</property>
+                <property name="label" translatable="yes">Oops, something has gone wrong. Please contact 
your software vendor.</property>
+                <attributes>
+                  <attribute name="scale" value="1.42" />
+                </attributes>
+              </object>
+              <packing>
+                <property name="pack-type">end</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="name">nm-not-running</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+  </template>
+
+  <!-- End Stack -->
+  <object class="GtkStack" id="header_stack">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="halign">end</property>
+  </object>
+
+  <!-- Center Widget -->
+  <object class="GtkStack" id="center_stack">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="halign">center</property>
+    <child>
+      <object class="GtkStackSwitcher">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="stack">stack</property>
+      </object>
+      <packing>
+        <property name="name">many</property>
+      </packing>
+    </child>
+  </object>
+
+  <object class="GtkSizeGroup" id="sizegroup" />
+</interface>
diff --git a/shell/cc-panel-loader.c b/shell/cc-panel-loader.c
index 20ebb85..9582d80 100644
--- a/shell/cc-panel-loader.c
+++ b/shell/cc-panel-loader.c
@@ -41,6 +41,7 @@ extern GType cc_keyboard_panel_get_type (void);
 extern GType cc_mouse_panel_get_type (void);
 #ifdef BUILD_NETWORK
 extern GType cc_network_panel_get_type (void);
+extern GType cc_wifi_panel_get_type (void);
 #endif /* BUILD_NETWORK */
 extern GType cc_notifications_panel_get_type (void);
 extern GType cc_goa_panel_get_type (void);
@@ -83,6 +84,7 @@ static struct {
   PANEL_TYPE("mouse",            cc_mouse_panel_get_type        ),
 #ifdef BUILD_NETWORK
   PANEL_TYPE("network",          cc_network_panel_get_type      ),
+  PANEL_TYPE("wifi",             cc_wifi_panel_get_type         ),
 #endif
   PANEL_TYPE("notifications",    cc_notifications_panel_get_type),
   PANEL_TYPE("online-accounts",  cc_goa_panel_get_type          ),



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]