[gnome-control-center] thunderbolt: device dialog can handle parents



commit 077f16912980a39fc0cb91e69fe4a664ee48a52e
Author: Christian Kellner <christian kellner me>
Date:   Fri Feb 1 17:55:57 2019 +0100

    thunderbolt: device dialog can handle parents
    
    Add an expander that contains a list of all the parent devices of
    the dialog's target device. If any of the devices is not yet
    authorized, show a warning symbol next to it.
    Additionally the enroll/authorize function calls are replaced
    by a single bolt_client_connect_all call, so parents that need
    authorization can be authorized/enrolled too.

 panels/thunderbolt/cc-bolt-device-dialog.c  | 142 ++++++++++++++++++----------
 panels/thunderbolt/cc-bolt-device-dialog.h  |   4 +-
 panels/thunderbolt/cc-bolt-device-dialog.ui |  44 +++++++++
 panels/thunderbolt/cc-bolt-panel.c          |   4 +-
 4 files changed, 143 insertions(+), 51 deletions(-)
---
diff --git a/panels/thunderbolt/cc-bolt-device-dialog.c b/panels/thunderbolt/cc-bolt-device-dialog.c
index 11469d46c..a1683c414 100644
--- a/panels/thunderbolt/cc-bolt-device-dialog.c
+++ b/panels/thunderbolt/cc-bolt-device-dialog.c
@@ -19,6 +19,8 @@
 
 #include <config.h>
 
+#include <list-box-helper.h>
+
 #include <glib/gi18n.h>
 
 #include "bolt-device.h"
@@ -28,6 +30,7 @@
 #include "cc-thunderbolt-resources.h"
 
 #include "cc-bolt-device-dialog.h"
+#include "cc-bolt-device-entry.h"
 
 struct _CcBoltDeviceDialog
 {
@@ -52,6 +55,11 @@ struct _CcBoltDeviceDialog
   GtkLabel *time_title;
   GtkLabel *time_label;
 
+  /* parents */
+  GtkExpander *parents_expander;
+  GtkLabel    *parents_label;
+  GtkListBox  *parents_devices;
+
   /* actions */
   GtkWidget  *button_box;
   GtkSpinner *spinner;
@@ -242,74 +250,72 @@ dialog_operation_done (CcBoltDeviceDialog *dialog,
 }
 
 static void
-dialog_authorize_done (CcBoltDeviceDialog *dialog,
-                       gboolean            ok,
-                       GError             *error)
-{
-  if (!ok)
-    g_prefix_error (&error, _("Failed to authorize device: "));
-
-  dialog_operation_done (dialog, GTK_WIDGET (dialog->connect_button), error);
-}
-
-static void
-on_device_authorized (GObject      *source,
-                      GAsyncResult *res,
-                      gpointer      user_data)
+on_connect_all_done (GObject      *source_object,
+                    GAsyncResult *res,
+                    gpointer      user_data)
 {
   g_autoptr(GError) err = NULL;
   CcBoltDeviceDialog *dialog = CC_BOLT_DEVICE_DIALOG (user_data);
   gboolean ok;
 
-  ok = bolt_device_authorize_finish (BOLT_DEVICE (source), res, &err);
-  dialog_authorize_done (dialog, ok, err);
-}
+  ok = bolt_client_connect_all_finish (dialog->client, res, &err);
 
-static void
-on_device_enrolled (GObject      *source_object,
-                    GAsyncResult *res,
-                    gpointer      user_data)
-{
-  g_autoptr(GError) err = NULL;
-  CcBoltDeviceDialog *dialog = CC_BOLT_DEVICE_DIALOG (user_data);
-  gboolean ok;
+  if (!ok)
+    g_prefix_error (&err, _("Failed to authorize device: "));
 
-  ok = bolt_client_enroll_device_finish (dialog->client, res, NULL, &err);
-  dialog_authorize_done (dialog, ok, err);
+  dialog_operation_done (dialog, GTK_WIDGET (dialog->connect_button), err);
 }
 
 static void
 on_connect_button_clicked_cb (CcBoltDeviceDialog *dialog)
 {
+  g_autoptr(GPtrArray) devices = NULL;
+  g_autoptr(GList) entries = NULL;
   BoltDevice *device = dialog->device;
-  gboolean stored;
+  GList *iter;
 
   g_return_if_fail (device != NULL);
 
   dialog_operation_start (dialog);
 
-  stored = bolt_device_is_stored (device);
-  if (stored)
-    {
-      bolt_device_authorize_async (device,
-                                   BOLT_AUTHCTRL_NONE,
-                                   dialog->cancel,
-                                   on_device_authorized,
-                                   dialog);
-    }
-  else
+  entries = gtk_container_get_children (GTK_CONTAINER (dialog->parents_devices));
+  devices = g_ptr_array_new ();
+
+  /* reverse the order, so to start with the devices closest to the host */
+  entries = g_list_reverse (entries);
+
+  for (iter = entries; iter; iter = iter->next)
     {
-      const char *uid = bolt_device_get_uid (device);
-
-      bolt_client_enroll_device_async (dialog->client,
-                                       uid,
-                                       BOLT_POLICY_DEFAULT,
-                                       BOLT_AUTHCTRL_NONE,
-                                       dialog->cancel,
-                                       on_device_enrolled,
-                                       dialog);
+      CcBoltDeviceEntry *entry;
+      BoltDevice *dev;
+      BoltStatus status;
+
+      entry = (CcBoltDeviceEntry *) iter->data;
+      dev = cc_bolt_device_entry_get_device (entry);
+      status = bolt_device_get_status (dev);
+
+      /* skip any devices down in the chain that are already authorized
+       * NB: it is not possible to have gaps of non-authorized devices
+       * in the chain, i.e. once we encounter a non-authorized device,
+       * all following device (down the chain, towards the target) will
+       * also be not authorized. */
+      if (!bolt_status_is_pending (status))
+       continue;
+
+      /* device is now either !stored || pending */
+      g_ptr_array_add (devices, dev);
     }
 
+  /* finally the actual device of the dialog */
+  g_ptr_array_add (devices, device);
+
+  bolt_client_connect_all_async (dialog->client,
+                                devices,
+                                BOLT_POLICY_DEFAULT,
+                                BOLT_AUTHCTRL_NONE,
+                                dialog->cancel,
+                                on_connect_all_done,
+                                dialog);
 }
 
 static void
@@ -388,6 +394,10 @@ cc_bolt_device_dialog_class_init (CcBoltDeviceDialogClass *klass)
   gtk_widget_class_bind_template_child (widget_class, CcBoltDeviceDialog, time_title);
   gtk_widget_class_bind_template_child (widget_class, CcBoltDeviceDialog, time_label);
 
+  gtk_widget_class_bind_template_child (widget_class, CcBoltDeviceDialog, parents_expander);
+  gtk_widget_class_bind_template_child (widget_class, CcBoltDeviceDialog, parents_label);
+  gtk_widget_class_bind_template_child (widget_class, CcBoltDeviceDialog, parents_devices);
+
   gtk_widget_class_bind_template_child (widget_class, CcBoltDeviceDialog, button_box);
   gtk_widget_class_bind_template_child (widget_class, CcBoltDeviceDialog, spinner);
   gtk_widget_class_bind_template_child (widget_class, CcBoltDeviceDialog, connect_button);
@@ -403,6 +413,11 @@ cc_bolt_device_dialog_init (CcBoltDeviceDialog *dialog)
 {
   g_resources_register (cc_thunderbolt_get_resource ());
   gtk_widget_init_template (GTK_WIDGET (dialog));
+
+  gtk_list_box_set_header_func (dialog->parents_devices,
+                                cc_list_box_update_header_func,
+                                NULL,
+                                NULL);
 }
 
 /* public functions */
@@ -427,8 +442,12 @@ cc_bolt_device_dialog_set_client (CcBoltDeviceDialog *dialog,
 
 void
 cc_bolt_device_dialog_set_device (CcBoltDeviceDialog *dialog,
-                                  BoltDevice         *device)
+                                  BoltDevice         *device,
+                                 GPtrArray          *parents)
 {
+  g_autofree char *msg = NULL;
+  guint i;
+
   if (device == dialog->device)
     return;
 
@@ -442,6 +461,10 @@ cc_bolt_device_dialog_set_device (CcBoltDeviceDialog *dialog,
                                             G_CALLBACK (on_device_notify_cb),
                                             dialog);
       g_clear_object (&dialog->device);
+
+      gtk_container_foreach (GTK_CONTAINER (dialog->parents_devices),
+                            (GtkCallback) gtk_widget_destroy, NULL);
+      gtk_widget_hide (GTK_WIDGET (dialog->parents_expander));
     }
 
   if (device == NULL)
@@ -460,6 +483,29 @@ cc_bolt_device_dialog_set_device (CcBoltDeviceDialog *dialog,
   gtk_widget_set_sensitive (GTK_WIDGET (dialog->forget_button), TRUE);
 
   dialog_update_from_device (dialog);
+
+  /* no parents, we are done here */
+  if (!parents || parents->len == 0)
+    return;
+
+  msg = g_strdup_printf (ngettext ("Depends on %u other device",
+                                  "Depends on %u other devices",
+                                  parents->len), parents->len);
+
+  gtk_label_set_label (dialog->parents_label, msg);
+  gtk_widget_show (GTK_WIDGET (dialog->parents_expander));
+
+  for (i = 0; i < parents->len; i++)
+    {
+      CcBoltDeviceEntry *entry;
+      BoltDevice *parent;
+
+      parent = g_ptr_array_index (parents, i);
+
+      entry = cc_bolt_device_entry_new (parent, TRUE);
+      gtk_widget_show (GTK_WIDGET (entry));
+      gtk_container_add (GTK_CONTAINER (dialog->parents_devices), GTK_WIDGET (entry));
+    }
 }
 
 BoltDevice *
diff --git a/panels/thunderbolt/cc-bolt-device-dialog.h b/panels/thunderbolt/cc-bolt-device-dialog.h
index bd91eac71..abdb46f87 100644
--- a/panels/thunderbolt/cc-bolt-device-dialog.h
+++ b/panels/thunderbolt/cc-bolt-device-dialog.h
@@ -36,7 +36,9 @@ void                 cc_bolt_device_dialog_set_client (CcBoltDeviceDialog *dialo
                                                        BoltClient         *client);
 
 void                 cc_bolt_device_dialog_set_device (CcBoltDeviceDialog *dialog,
-                                                       BoltDevice         *device);
+                                                       BoltDevice         *device,
+                                                      GPtrArray          *parents);
+
 BoltDevice *         cc_bolt_device_dialog_peek_device (CcBoltDeviceDialog *dialog);
 
 gboolean             cc_bolt_device_dialog_device_equal (CcBoltDeviceDialog *dialog,
diff --git a/panels/thunderbolt/cc-bolt-device-dialog.ui b/panels/thunderbolt/cc-bolt-device-dialog.ui
index 584915a31..49e2bbed8 100644
--- a/panels/thunderbolt/cc-bolt-device-dialog.ui
+++ b/panels/thunderbolt/cc-bolt-device-dialog.ui
@@ -255,6 +255,50 @@
                   </object>
                 </child>
                 <!-- end of grid -->
+               <child>
+                 <object class="GtkExpander" id="parents_expander">
+                   <property name="visible">False</property>
+                   <property name="halign">fill</property>
+                   <property name="margin-left">72</property>
+                    <property name="margin-right">72</property>
+                    <property name="margin-top">12</property>
+                    <property name="margin-bottom">0</property>
+                   <property name="spacing">12</property>
+                   <child type="label">
+                     <object class="GtkLabel" id="parents_label">
+                       <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="halign">end</property>
+                        <property name="hexpand">False</property>
+                        <property name="vexpand">False</property>
+                        <property name="label">Depends on other devices:</property>
+                        <property name="justify">center</property>
+                        <property name="xalign">1</property>
+                     </object>
+                   </child>
+                   <child>
+                      <object class="GtkFrame">
+                       <property name="margin-top">12</property>
+                        <property name="visible">True</property>
+                        <property name="valign">start</property>
+                        <property name="vexpand">False</property>
+                        <style>
+                          <class name="view" />
+                        </style>
+                       <child>
+                         <object class="GtkListBox" id="parents_devices">
+                           <property name="valign">start</property>
+                            <property name="vexpand">False</property>
+                           <property name="visible">True</property>
+                            <property name="selection-mode">none</property>
+                            <property name="can_focus">True</property>
+                         </object>
+                       </child>
+                     </object>
+                   </child>
+                 </object>
+               </child>
+               <!-- end of -->
                 <child>
                   <object class="GtkBox" id="button_box">
                     <property name="visible">True</property>
diff --git a/panels/thunderbolt/cc-bolt-panel.c b/panels/thunderbolt/cc-bolt-panel.c
index 0515b1614..0db263943 100644
--- a/panels/thunderbolt/cc-bolt-panel.c
+++ b/panels/thunderbolt/cc-bolt-panel.c
@@ -666,7 +666,7 @@ on_device_entry_row_activated_cb (CcBoltPanel   *panel,
   entry = CC_BOLT_DEVICE_ENTRY (row);
   device = cc_bolt_device_entry_get_device (entry);
 
-  cc_bolt_device_dialog_set_device (panel->device_dialog, device);
+  cc_bolt_device_dialog_set_device (panel->device_dialog, device, NULL);
   gtk_window_resize (GTK_WINDOW (panel->device_dialog), 1, 1);
   gtk_widget_show (GTK_WIDGET (panel->device_dialog));
 }
@@ -680,7 +680,7 @@ on_device_dialog_delete_event_cb (GtkWidget   *widget,
 
   dialog = CC_BOLT_DEVICE_DIALOG (widget);
 
-  cc_bolt_device_dialog_set_device (dialog, NULL);
+  cc_bolt_device_dialog_set_device (dialog, NULL, NULL);
   gtk_widget_hide (widget);
 
   return TRUE;


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