[gnome-control-center/wip/applications] Keep up with changing mockups



commit 631ea2b4b819c5ef7b06fac1ba943122118f91d8
Author: Matthias Clasen <mclasen redhat com>
Date:   Mon Dec 3 00:13:49 2018 -0500

    Keep up with changing mockups

 panels/applications/cc-action-row.ui         |   3 +
 panels/applications/cc-applications-panel.c  | 453 ++++++++++++++++-----------
 panels/applications/cc-applications-panel.ui | 283 +++++++++++------
 panels/applications/cc-info-row.c            |  12 +
 panels/applications/cc-info-row.ui           |   3 +
 panels/applications/cc-toggle-row.c          |  17 -
 panels/applications/cc-toggle-row.ui         |  20 --
 panels/applications/utils.c                  |  49 +--
 panels/applications/utils.h                  |   5 +-
 9 files changed, 495 insertions(+), 350 deletions(-)
---
diff --git a/panels/applications/cc-action-row.ui b/panels/applications/cc-action-row.ui
index d20a98aee..76bffd836 100644
--- a/panels/applications/cc-action-row.ui
+++ b/panels/applications/cc-action-row.ui
@@ -19,6 +19,9 @@
                 <property name="xalign">0</property>
                 <property name="hexpand">True</property>
               </object>
+              <packing>
+                <property name="expand">True</property>
+              </packing>
             </child>
             <child>
               <object class="GtkLabel" id="subtitle">
diff --git a/panels/applications/cc-applications-panel.c b/panels/applications/cc-applications-panel.c
index 875b3dd13..7527bd3d8 100644
--- a/panels/applications/cc-applications-panel.c
+++ b/panels/applications/cc-applications-panel.c
@@ -38,12 +38,12 @@
  * - search
  * - mime type removal
  * - handle cache async
- * - undo for uninstall, data removal
+ * - empty state
  *
  * Missing in flatpak:
+ * - make portal write notification permissions
  * - background
  * - usb devices
- * - global settings for disabling camera, microphone
  *
  * Update privacy panel to match
  */
@@ -71,10 +71,14 @@ struct _CcApplicationsPanel
   GDBusProxy *perm_store;
   GSettings *notification_settings;
   GSettings *location_settings;
+  GSettings *privacy_settings;
 
   GtkListBox *stack;
   GtkWidget *permission_section;
   GtkWidget *permission_list;
+  GtkWidget *builtin_dialog;
+  GtkWidget *builtin_label;
+  GtkWidget *builtin_list;
 
   GtkWidget *camera;
   GtkWidget *no_camera;
@@ -83,17 +87,18 @@ struct _CcApplicationsPanel
   GtkWidget *microphone;
   GtkWidget *no_microphone;
 
-  GtkWidget *information_section;
-  GtkWidget *information_list;
+  GtkWidget *integration_section;
+  GtkWidget *integration_list;
   GtkWidget *notification;
   GtkWidget *sound;
+  GtkWidget *no_sound;
   GtkWidget *builtin;
 
   GtkWidget *device_section;
   GtkWidget *device_list;
 
-  GtkWidget *file_type_section;
-  GtkWidget *file_type_list;
+  GtkWidget *handler_section;
+  GtkWidget *handler_list;
   GtkWidget *hypertext;
   GtkWidget *text;
   GtkWidget *images;
@@ -103,13 +108,17 @@ struct _CcApplicationsPanel
   GtkWidget *audio;
   GtkWidget *video;
   GtkWidget *other;
-  GtkWidget *link_type_section;
-  GtkWidget *link_type_list;
-  GtkWidget *storage_section;
+  GtkWidget *link;
+  GtkWidget *usage_section;
+  GtkWidget *usage_list;
+  GtkWidget *storage;
+  GtkWidget *storage_dialog;
   GtkWidget *storage_list;
   GtkWidget *app;
   GtkWidget *data;
   GtkWidget *cache;
+  GtkWidget *total;
+  GtkWidget *clear_cache_button;
 };
 
 G_DEFINE_TYPE (CcApplicationsPanel, cc_applications_panel, CC_TYPE_PANEL)
@@ -134,6 +143,7 @@ cc_applications_panel_finalize (GObject *object)
 
   g_clear_object (&self->notification_settings);
   g_clear_object (&self->location_settings);
+  g_clear_object (&self->privacy_settings);
   g_clear_object (&self->cancellable);
 
   g_free (self->current_app_id);
@@ -214,6 +224,12 @@ set_flatpak_permissions (CcApplicationsPanel *self,
                           0, G_MAXINT, NULL, NULL);
 }
 
+static void
+search_cb (CcApplicationsPanel *self)
+{
+  g_print ("search not implemented\n");
+}
+
 static gboolean
 app_info_is_flatpak (GAppInfo *info)
 {
@@ -227,21 +243,22 @@ app_info_is_flatpak (GAppInfo *info)
   return FALSE;
 }
 
-static gboolean
+static void
 get_notification_allowed (CcApplicationsPanel *self,
-                          const char *app_id)
+                          const char *app_id,
+                          gboolean *set,
+                          gboolean *allowed)
 {
   if (self->notification_settings)
     {
-      return g_settings_get_boolean (self->notification_settings, "enable");
+      *set = TRUE; /* FIXME */
+      *allowed = g_settings_get_boolean (self->notification_settings, "enable");
     }
   else
     {
-      g_auto(GStrv) perms = get_flatpak_permissions (self,
-                                                     "notifications",
-                                                     "notification",
-                                                     app_id);
-      return perms == NULL || strcmp (perms[0], "no") != 0;
+      g_auto(GStrv) perms = get_flatpak_permissions (self, "notifications", "notification", app_id);
+      *set = TRUE; /* FIXME */
+      *allowed = perms == NULL || strcmp (perms[0], "no") != 0;
     }
 }
 
@@ -299,16 +316,19 @@ get_notification_settings (const char *app_id)
   return g_settings_new_with_path (APP_SCHEMA, path);
 }
 
-static gboolean
+static void
 get_device_allowed (CcApplicationsPanel *self,
                     const char *device,
-                    const char *app_id)
+                    const char *app_id,
+                    gboolean *set,
+                    gboolean *allowed)
 {
   g_auto(GStrv) perms = NULL;
 
   perms = get_flatpak_permissions (self, "devices", device, app_id);
 
-  return perms == NULL || strcmp (perms[0], "no") != 0;
+  *set = perms != NULL;
+  *allowed = perms == NULL || strcmp (perms[0], "no") != 0;
 }
 
 static void
@@ -345,15 +365,18 @@ camera_cb (CcApplicationsPanel *self)
     set_device_allowed (self, "camera", cc_toggle_row_get_allowed (CC_TOGGLE_ROW (self->camera)));
 }
 
-static gboolean
+static void
 get_location_allowed (CcApplicationsPanel *self,
-                      const char *app_id)
+                      const char *app_id,
+                      gboolean *set,
+                      gboolean *allowed)
 {
   g_auto(GStrv) perms = NULL;
 
   perms = get_flatpak_permissions (self, "location", "location", app_id);
 
-  return perms == NULL || strcmp (perms[0], "NONE") != 0;
+  *set = perms != NULL;
+  *allowed = perms == NULL || strcmp (perms[0], "NONE") != 0;
 }
 
 static void
@@ -396,8 +419,7 @@ calculate_dir_size (const char *app_id,
 }
 
 static void
-privacy_link_cb (CcToggleRow *row,
-                 CcApplicationsPanel *self)
+privacy_link_cb (CcApplicationsPanel *self)
 {
   CcShell *shell = cc_panel_get_shell (CC_PANEL (self));
   g_autoptr(GError) error = NULL;
@@ -406,56 +428,48 @@ privacy_link_cb (CcToggleRow *row,
     g_warning ("Failed to switch to privacy panel: %s", error->message);
 }
 
-static void
-update_app_row (CcActionRow *row,
+static guint64
+update_app_row (CcInfoRow *row,
                 const char *app_id)
 {
+  guint64 size;
   g_autofree char *formatted_size = NULL;
 
-  formatted_size = get_flatpak_app_size (app_id);
-  g_object_set (row, "subtitle", formatted_size, NULL);
+  size = get_flatpak_app_size (app_id);
+  formatted_size = g_format_size (size);
+  g_object_set (row, "info", formatted_size, NULL);
+
+  return size;
 }
 
-static void
-update_dir_row (CcActionRow *row,
+static guint64
+update_dir_row (CcInfoRow *row,
                 const char *app_id,
                 const char *subdir)
 {
   guint64 size;
   g_autofree char *formatted_size = NULL;
 
-  subdir = g_strdup (subdir);
-  g_object_set_data_full (G_OBJECT (row), "subdir", (gpointer)subdir, g_free);
-
   size = calculate_dir_size (app_id, subdir);
   formatted_size = g_format_size (size);
-  g_object_set (row,
-                "subtitle", formatted_size,
-                "enabled", size > 0,
-                NULL);
+  g_object_set (row, "info", formatted_size, NULL);
+
+  return size;
 }
 
+static void update_flatpak_sizes (CcApplicationsPanel *self, const char *app_id);
+
 static void
-clear_cb (CcActionRow *row, CcApplicationsPanel *self)
+clear_cache_cb (CcApplicationsPanel *self)
 {
   g_autoptr(GFile) dir = NULL;
-  const char *subdir;
 
   if (self->current_app_id == NULL)
     return;
 
-  subdir = (const char *) g_object_get_data (G_OBJECT (row), "subdir");
-  dir = get_app_dir (self->current_app_id, subdir);
+  dir = get_app_dir (self->current_app_id, "cache");
   file_remove_recursively (dir);
-  update_dir_row (CC_ACTION_ROW (row), self->current_app_id, subdir);
-}
-
-static void
-uninstall_cb (CcActionRow *row, CcApplicationsPanel *self)
-{
-  // FIXME: confirmation dialog ? undo notification ?
-
-  uninstall_flatpak_app (self->current_app_id);
+  update_flatpak_sizes (self, self->current_app_id);
 }
 
 static char *
@@ -469,31 +483,6 @@ get_app_id (GAppInfo *info)
   return app_id;
 }
 
-static FlatpakInstalledRef *
-find_flatpak_ref (const char *app_id)
-{
-  g_autoptr(FlatpakInstallation) inst = NULL;
-  g_autoptr(GPtrArray) array = NULL;
-  FlatpakInstalledRef *ref;
-  int i;
-
-  inst = flatpak_installation_new_user (NULL, NULL);
-  ref = flatpak_installation_get_current_installed_app (inst, app_id, NULL, NULL);
-  if (ref)
-    return ref;
-
-  array = flatpak_get_system_installations (NULL, NULL);
-  for (i = 0; i < array->len; i++)
-    {
-      FlatpakInstallation *si = g_ptr_array_index (array, i);
-      ref = flatpak_installation_get_current_installed_app (si, app_id, NULL, NULL);
-      if (ref)
-        return ref;
-    }
-
-  return NULL;
-}
-
 static int
 add_static_permission_row (CcApplicationsPanel *self,
                            const char *title,
@@ -505,10 +494,7 @@ add_static_permission_row (CcApplicationsPanel *self,
                       "title", title,
                       "info", subtitle,
                       NULL);
-  g_object_bind_property (self->builtin, "expanded",
-                          row, "visible",
-                          G_BINDING_SYNC_CREATE);
-  gtk_container_add (GTK_CONTAINER (self->permission_list), row);
+  gtk_container_add (GTK_CONTAINER (self->builtin_list), row);
 
   return 1;
 }
@@ -518,24 +504,20 @@ permission_row_activated_cb (GtkListBox    *list,
                              GtkListBoxRow *list_row,
                              CcApplicationsPanel *self)
 {
-  CcShell *shell = cc_panel_get_shell (CC_PANEL (self));
   GtkWidget *row = GTK_WIDGET (list_row);
   g_autoptr(GError) error = NULL;
 
   if (row == self->builtin)
-    cc_info_row_set_expanded (CC_INFO_ROW (self->builtin),
-                              !cc_info_row_get_expanded (CC_INFO_ROW (self->builtin)));
-  else if (row == self->no_camera ||
-           row == self->no_microphone ||
-           row == self->no_location)
     {
-      if (!cc_shell_set_active_panel_from_id (shell, "privacy", NULL, &error))
-        g_warning ("Failed to switch to privacy panel: %s", error->message);
+      gtk_window_set_transient_for (GTK_WINDOW (self->builtin_dialog),
+                                    GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (self))));
+      gtk_window_present (GTK_WINDOW (self->builtin_dialog));
     }
 }
 
-static void
+static gboolean
 add_static_permissions (CcApplicationsPanel *self,
+                        GAppInfo *info,
                         const char *app_id)
 {
   g_autoptr(FlatpakInstalledRef) ref = NULL;
@@ -545,6 +527,7 @@ add_static_permissions (CcApplicationsPanel *self,
   char **strv;
   char *str;
   int added = 0;
+  g_autofree char *text = NULL;
   
   ref = find_flatpak_ref (app_id);
   bytes = flatpak_installed_ref_load_metadata (ref, NULL, NULL);
@@ -555,7 +538,7 @@ add_static_permissions (CcApplicationsPanel *self,
                                   0, &error))
     {
       g_warning ("%s", error->message);
-      return;
+      return FALSE;
     }
 
   strv = g_key_file_get_string_list (keyfile, "Context", "sockets", NULL, NULL);
@@ -594,25 +577,17 @@ add_static_permissions (CcApplicationsPanel *self,
   g_free (str);
 
   gtk_widget_set_visible (self->builtin, added > 0);
+
+  text = g_strdup_printf (_("%s has the following permissions built-in. These cannot be altered. If you are 
concerned about these permissions, consider removing this application."), g_app_info_get_display_name (info));
+  gtk_label_set_label (GTK_LABEL (self->builtin_label), text);
+
+  return added > 0;
 }
 
 static void
 remove_static_permissions (CcApplicationsPanel *self)
 {
-  GList *children, *l;
-
-  children = gtk_container_get_children (GTK_CONTAINER (self->permission_list));
-  for (l = children; l; l = l->next)
-    {
-      if (CC_IS_INFO_ROW (l->data))
-        {
-          gboolean has_expander;
-          g_object_get (l->data, "has-expander", &has_expander, NULL);
-          if (!has_expander)
-            gtk_widget_destroy (GTK_WIDGET (l->data));
-        }
-    }
-  g_list_free (children);
+  container_remove_all (GTK_CONTAINER (self->builtin_list));
 }
 
 static void
@@ -620,7 +595,8 @@ update_permission_section (CcApplicationsPanel *self,
                            GAppInfo *info)
 {
   g_autofree char *app_id = get_app_id (info);
-  gboolean enabled;
+  gboolean disabled, allowed, set;
+  gboolean has_any = FALSE;
 
   if (!app_info_is_flatpak (info))
     {
@@ -628,50 +604,68 @@ update_permission_section (CcApplicationsPanel *self,
       return;
     }
 
-  gtk_widget_show (self->permission_section);
-
-  enabled = TRUE; /* FIXME add a camera-enabled setting */
-  gtk_widget_set_visible (self->camera, enabled);
-  gtk_widget_set_visible (self->no_camera, !enabled);
-
-  enabled = TRUE; /* FIXME add a microphone-enabled setting */
-  gtk_widget_set_visible (self->microphone, enabled);
-  gtk_widget_set_visible (self->no_microphone, !enabled);
-
-  enabled = g_settings_get_boolean (self->location_settings, "enabled");
-  gtk_widget_set_visible (self->location, enabled);
-  gtk_widget_set_visible (self->no_location, !enabled);
-
+  disabled = g_settings_get_boolean (self->privacy_settings, "disable-camera");
+  get_device_allowed (self, "camera", app_id, &set, &allowed);
+  cc_toggle_row_set_allowed (CC_TOGGLE_ROW (self->camera), allowed);
+  gtk_widget_set_visible (self->camera, set && !disabled);
+  gtk_widget_set_visible (self->no_camera, set && disabled);
+  has_any |= set;
+
+  disabled = g_settings_get_boolean (self->privacy_settings, "disable-microphone");
+  get_device_allowed (self, "microphone", app_id, &set, &allowed);
+  cc_toggle_row_set_allowed (CC_TOGGLE_ROW (self->microphone), allowed);
+  gtk_widget_set_visible (self->microphone, set && !disabled);
+  gtk_widget_set_visible (self->no_microphone, set && disabled);
+  has_any |= set;
+
+  disabled = !g_settings_get_boolean (self->location_settings, "enabled");
+  get_location_allowed (self, app_id, &set, &allowed);
+  cc_toggle_row_set_allowed (CC_TOGGLE_ROW (self->location), allowed);
+  gtk_widget_set_visible (self->location, set && !disabled);
+  gtk_widget_set_visible (self->no_location, set && disabled);
+  has_any |= set;
 
   remove_static_permissions (self);
-  add_static_permissions (self, app_id);
+  has_any |= add_static_permissions (self, info, app_id);
 
-  cc_toggle_row_set_allowed (CC_TOGGLE_ROW (self->camera), get_device_allowed (self, "camera", app_id));
-  cc_toggle_row_set_allowed (CC_TOGGLE_ROW (self->location), get_location_allowed (self, app_id));
-  cc_toggle_row_set_allowed (CC_TOGGLE_ROW (self->microphone), get_device_allowed (self, "microphone", 
app_id));
+  gtk_widget_set_visible (self->permission_section, has_any);
 }
 
 static void
-update_information_section (CcApplicationsPanel *self,
+update_integration_section (CcApplicationsPanel *self,
                             GAppInfo *info)
 {
   g_autofree char *app_id = get_app_id (info);
+  gboolean set, allowed, disabled;
+  gboolean has_any = FALSE;
 
   if (app_info_is_flatpak (info))
     {
       g_clear_object (&self->notification_settings);
-
-      gtk_widget_show (self->sound);
+      get_notification_allowed (self, app_id, &set, &allowed);
+      cc_toggle_row_set_allowed (CC_TOGGLE_ROW (self->notification), allowed);
+      gtk_widget_set_visible (self->notification, set);
+      has_any |= set;
+
+      disabled = g_settings_get_boolean (self->privacy_settings, "disable-sound-output");
+      get_device_allowed (self, "speakers", app_id, &set, &allowed);
+      cc_toggle_row_set_allowed (CC_TOGGLE_ROW (self->sound), allowed);
+      gtk_widget_set_visible (self->sound, set && !disabled);
+      gtk_widget_set_visible (self->no_sound, set && disabled);
     }
   else
     {
       g_set_object (&self->notification_settings, get_notification_settings (app_id));
+      get_notification_allowed (self, app_id, &set, &allowed);
+      cc_toggle_row_set_allowed (CC_TOGGLE_ROW (self->notification), allowed);
+      gtk_widget_set_visible (self->notification, set);
+      has_any |= set;
 
       gtk_widget_hide (self->sound);
+      gtk_widget_hide (self->no_sound);
     }
 
-  cc_toggle_row_set_allowed (CC_TOGGLE_ROW (self->notification), get_notification_allowed (self, app_id));
-  cc_toggle_row_set_allowed (CC_TOGGLE_ROW (self->sound), get_device_allowed (self, "speakers", app_id));
+  gtk_widget_set_visible (self->integration_section, has_any);
 }
 
 static void
@@ -683,10 +677,26 @@ update_device_section (CcApplicationsPanel *self,
 }
 
 static void
-add_link_type_row (CcApplicationsPanel *self,
-                   const char *type)
+update_group_row_count (GtkWidget *row,
+                        int delta)
+{
+  int count;
+  g_autofree char *text = NULL;
+
+  count = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (row), "count"));
+  count += delta;
+  g_object_set_data (G_OBJECT (row), "count", GINT_TO_POINTER (count));
+  text = g_strdup_printf ("%d", count);
+  g_object_set (row, "info", text, NULL);
+}
+
+static void
+add_scheme (CcApplicationsPanel *self,
+            GtkWidget *after,
+            const char *type)
 {
   CcActionRow *row = NULL;
+  int pos;
 
   if (g_str_has_suffix (type, "http"))
     {
@@ -718,8 +728,17 @@ add_link_type_row (CcApplicationsPanel *self,
       cc_action_row_set_action (row, _("Unset"), FALSE);
     }
 
-  gtk_list_box_insert (GTK_LIST_BOX (self->link_type_list), GTK_WIDGET (row), -1);
-  gtk_widget_show (self->link_type_section);
+  if (after)
+    {
+      pos = gtk_list_box_row_get_index (GTK_LIST_BOX_ROW (after)) + 1;
+      g_object_bind_property (after, "expanded",
+                              row, "visible",
+                              G_BINDING_SYNC_CREATE);
+    }
+  else
+    pos = -1;
+  gtk_list_box_insert (GTK_LIST_BOX (self->handler_list), GTK_WIDGET (row), pos);
+  update_group_row_count (after, 1);
 }
 
 static void
@@ -748,7 +767,8 @@ add_file_type (CcApplicationsPanel *self,
     }
   else
     pos = -1;
-  gtk_list_box_insert (GTK_LIST_BOX (self->file_type_list), GTK_WIDGET (row), pos);
+  gtk_list_box_insert (GTK_LIST_BOX (self->handler_list), GTK_WIDGET (row), pos);
+  update_group_row_count (after, 1);
 }
 
 static gboolean
@@ -767,9 +787,9 @@ is_hypertext_type (const char *type)
 }
 
 static void
-ensure_file_group_row (CcApplicationsPanel *self,
-                       GtkWidget **row,
-                       const char *title)
+ensure_group_row (CcApplicationsPanel *self,
+                  GtkWidget **row,
+                  const char *title)
 {
   if (*row == NULL)
     {
@@ -777,16 +797,24 @@ ensure_file_group_row (CcApplicationsPanel *self,
                                                 "title", title,
                                                 "has-expander", TRUE,
                                                 NULL));
-      gtk_list_box_insert (GTK_LIST_BOX (self->file_type_list), GTK_WIDGET (r), -1);
+      gtk_list_box_insert (GTK_LIST_BOX (self->handler_list), GTK_WIDGET (r), -1);
       *row = GTK_WIDGET (r);
     }
 }
 
+static void
+add_link_type (CcApplicationsPanel *self,
+               const char *type)
+{
+  ensure_group_row (self, &self->link, _("Links"));
+  add_scheme (self, self->link, type);
+}
+
 static void
 add_hypertext_type (CcApplicationsPanel *self,
                     const char *type)
 {
-  ensure_file_group_row (self, &self->hypertext, _("Hypertext Files"));
+  ensure_group_row (self, &self->hypertext, _("Hypertext Files"));
   add_file_type (self, self->hypertext, type);
 }
 
@@ -800,7 +828,7 @@ static void
 add_text_type (CcApplicationsPanel *self,
                const char *type)
 {
-  ensure_file_group_row (self, &self->text, _("Text Files"));
+  ensure_group_row (self, &self->text, _("Text Files"));
   add_file_type (self, self->text, type);
 }
 
@@ -814,7 +842,7 @@ static void
 add_image_type (CcApplicationsPanel *self,
                 const char *type)
 {
-  ensure_file_group_row (self, &self->images, _("Image Files"));
+  ensure_group_row (self, &self->images, _("Image Files"));
   add_file_type (self, self->images, type);
 }
 
@@ -830,7 +858,7 @@ static void
 add_font_type (CcApplicationsPanel *self,
                const char *type)
 {
-  ensure_file_group_row (self, &self->fonts, _("Font Files"));
+  ensure_group_row (self, &self->fonts, _("Font Files"));
   add_file_type (self, self->fonts, type);
 }
 
@@ -891,7 +919,7 @@ static void
 add_archive_type (CcApplicationsPanel *self,
                   const char *type)
 {
-  ensure_file_group_row (self, &self->archives, _("Archive Files"));
+  ensure_group_row (self, &self->archives, _("Archive Files"));
   add_file_type (self, self->archives, type);
 }
 
@@ -911,7 +939,7 @@ static void
 add_package_type (CcApplicationsPanel *self,
                   const char *type)
 {
-  ensure_file_group_row (self, &self->packages, _("Package Files"));
+  ensure_group_row (self, &self->packages, _("Package Files"));
   add_file_type (self, self->packages, type);
 }
 
@@ -934,7 +962,7 @@ static void
 add_audio_type (CcApplicationsPanel *self,
                 const char *type)
 {
-  ensure_file_group_row (self, &self->audio, _("Audio Files"));
+  ensure_group_row (self, &self->audio, _("Audio Files"));
   add_file_type (self, self->audio, type);
 }
 
@@ -951,7 +979,7 @@ static void
 add_video_type (CcApplicationsPanel *self,
                 const char *type)
 {
-  ensure_file_group_row (self, &self->video, _("Video Files"));
+  ensure_group_row (self, &self->video, _("Video Files"));
   add_file_type (self, self->video, type);
 }
 
@@ -959,17 +987,19 @@ static void
 add_other_type (CcApplicationsPanel *self,
                 const char *type)
 {
-  ensure_file_group_row (self, &self->other, _("Other Files"));
+  ensure_group_row (self, &self->other, _("Other Files"));
   add_file_type (self, self->other, type);
 }
 
 static void
-add_file_type_row (CcApplicationsPanel *self,
-                   const char *type)
+add_handler_row (CcApplicationsPanel *self,
+                 const char *type)
 {
-  gtk_widget_show (self->file_type_section);
+  gtk_widget_show (self->handler_section);
 
-  if (is_hypertext_type (type))
+  if (g_content_type_is_a (type, "x-scheme-handler/*"))
+    add_link_type (self, type);
+  else if (is_hypertext_type (type))
     add_hypertext_type (self, type);
   else if (is_font_type (type))
     add_font_type (self, type);
@@ -990,9 +1020,9 @@ add_file_type_row (CcApplicationsPanel *self,
 }
 
 static void
-file_type_row_activated_cb (GtkListBox    *list,
-                            GtkListBoxRow *list_row,
-                            CcApplicationsPanel *self)
+handler_row_activated_cb (GtkListBox    *list,
+                          GtkListBoxRow *list_row,
+                          CcApplicationsPanel *self)
 {
   GtkWidget *row = GTK_WIDGET (list_row);
 
@@ -1004,7 +1034,8 @@ file_type_row_activated_cb (GtkListBox    *list,
       row == self->packages ||
       row == self->audio ||
       row == self->video ||
-      row == self->other)
+      row == self->other ||
+      row == self->link)
     cc_info_row_set_expanded (CC_INFO_ROW (row),
                               !cc_info_row_get_expanded (CC_INFO_ROW (row)));
 }
@@ -1016,8 +1047,7 @@ update_handler_sections (CcApplicationsPanel *self,
   int i;
   g_autoptr(GHashTable) hash = NULL;
 
-  container_remove_all (GTK_CONTAINER (self->file_type_list));
-  container_remove_all (GTK_CONTAINER (self->link_type_list));
+  container_remove_all (GTK_CONTAINER (self->handler_list));
 
   self->hypertext = NULL;
   self->text = NULL;
@@ -1028,9 +1058,9 @@ update_handler_sections (CcApplicationsPanel *self,
   self->audio = NULL;
   self->video = NULL;
   self->other = NULL;
+  self->link = NULL;
 
-  gtk_widget_hide (self->file_type_section);
-  gtk_widget_hide (self->link_type_section);
+  gtk_widget_hide (self->handler_section);
 
   types = g_app_info_get_supported_types (info);
   if (types == NULL || types[0] == NULL)
@@ -1047,35 +1077,66 @@ update_handler_sections (CcApplicationsPanel *self,
           continue;
         }
       g_hash_table_add (hash, ctype);
-      if (g_content_type_is_a (ctype, "x-scheme-handler/*"))
-        add_link_type_row (self, ctype);
-      else
-        add_file_type_row (self, ctype);
+      add_handler_row (self, ctype);
     }
 }
 
 static void
-update_storage_section (CcApplicationsPanel *self,
-                        GAppInfo *info)
+storage_row_activated_cb (GtkListBox    *list,
+                          GtkListBoxRow *list_row,
+                          CcApplicationsPanel *self)
+{
+  GtkWidget *row = GTK_WIDGET (list_row);
+  g_autoptr(GError) error = NULL;
+
+  if (row == self->storage)
+    {
+      gtk_window_set_transient_for (GTK_WINDOW (self->storage_dialog),
+                                    GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (self))));
+      gtk_window_present (GTK_WINDOW (self->storage_dialog));
+    }
+}
+
+static void
+update_flatpak_sizes (CcApplicationsPanel *self,
+                      const char *app_id)
+{
+  g_autofree char *formatted_size = NULL;
+  guint64 total = 0;
+  guint64 cache_size;
+
+  gtk_widget_show (self->usage_section);
+  total += update_app_row (CC_INFO_ROW (self->app), app_id);
+  cache_size = update_dir_row (CC_INFO_ROW (self->data), app_id, "data");
+  total += cache_size;
+  total += update_dir_row (CC_INFO_ROW (self->cache), app_id, "cache");
+
+  formatted_size = g_format_size (total);
+  g_object_set (self->total, "info", formatted_size, NULL);
+  g_object_set (self->storage, "info", formatted_size, NULL);
+
+  gtk_widget_set_sensitive (self->clear_cache_button, cache_size > 0);
+}
+
+static void
+update_usage_section (CcApplicationsPanel *self,
+                      GAppInfo *info)
 {
   if (app_info_is_flatpak (info))
     {
       g_autofree char *app_id = get_app_id (info);
-      gtk_widget_show (self->storage_section);
-      update_app_row (CC_ACTION_ROW (self->app), app_id);
-      update_dir_row (CC_ACTION_ROW (self->data), app_id, "data");
-      update_dir_row (CC_ACTION_ROW (self->cache), app_id, "cache");
+      update_flatpak_sizes (self, app_id);
     }
   else
     {
-      gtk_widget_hide (self->storage_section);
+      gtk_widget_hide (self->usage_section);
     }
 }
 
 static void
-update_panel (CcApplicationsPanel *self)
+update_panel (CcApplicationsPanel *self,
+              GtkListBoxRow *row)
 {
-  GtkListBoxRow *row = gtk_list_box_get_selected_row (self->sidebar_listbox);
   GAppInfo *info;
 
   if (self->perm_store == NULL)
@@ -1100,10 +1161,10 @@ update_panel (CcApplicationsPanel *self)
   gtk_label_set_label (GTK_LABEL (self->title_label), g_app_info_get_display_name (info));
 
   update_permission_section (self, info);
-  update_information_section (self, info);
+  update_integration_section (self, info);
   update_device_section (self, info);
   update_handler_sections (self, info);
-  update_storage_section (self, info);
+  update_usage_section (self, info);
 
   self->current_app_id = get_app_id (info);
 }
@@ -1139,21 +1200,26 @@ prepare_content (CcApplicationsPanel *self)
                                 cc_list_box_update_header_func,
                                 NULL, NULL);
 
-  gtk_list_box_set_header_func (GTK_LIST_BOX (self->information_list),
+  gtk_list_box_set_header_func (GTK_LIST_BOX (self->integration_list),
                                 cc_list_box_update_header_func,
                                 NULL, NULL);
 
-  gtk_list_box_set_header_func (GTK_LIST_BOX (self->file_type_list),
+  gtk_list_box_set_header_func (GTK_LIST_BOX (self->handler_list),
                                 cc_list_box_update_header_func,
                                 NULL, NULL);
 
-  gtk_list_box_set_header_func (GTK_LIST_BOX (self->link_type_list),
+  gtk_list_box_set_header_func (GTK_LIST_BOX (self->usage_list),
+                                cc_list_box_update_header_func,
+                                NULL, NULL);
+
+  gtk_list_box_set_header_func (GTK_LIST_BOX (self->builtin_list),
                                 cc_list_box_update_header_func,
                                 NULL, NULL);
 
   gtk_list_box_set_header_func (GTK_LIST_BOX (self->storage_list),
                                 cc_list_box_update_header_func,
                                 NULL, NULL);
+
 }
 
 static int
@@ -1179,7 +1245,7 @@ row_selected_cb (GtkListBox *list,
                  GtkListBoxRow *row,
                  CcApplicationsPanel *self)
 {
-  update_panel (self);
+  update_panel (self, row);
 }
 
 static void
@@ -1216,7 +1282,7 @@ on_perm_store_ready (GObject *source_object,
 
   self->perm_store = proxy;
 
-  update_panel (self);
+  update_panel (self, gtk_list_box_get_selected_row (self->sidebar_listbox));
 }
 
 static void
@@ -1333,33 +1399,41 @@ cc_applications_panel_class_init (CcApplicationsPanelClass *klass)
   gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, no_location);
   gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, microphone);
   gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, no_microphone);
-  gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, information_section);
-  gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, information_list);
+  gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, builtin);
+  gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, builtin_dialog);
+  gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, builtin_label);
+  gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, builtin_list);
+  gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, integration_section);
+  gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, integration_list);
   gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, notification);
   gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, sound);
-  gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, builtin);
+  gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, no_sound);
   gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, device_section);
   gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, device_list);
-  gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, file_type_section);
-  gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, file_type_list);
-  gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, link_type_section);
-  gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, link_type_list);
-  gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, storage_section);
+  gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, handler_section);
+  gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, handler_list);
+  gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, usage_section);
+  gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, usage_list);
+  gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, storage);
+  gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, storage_dialog);
   gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, storage_list);
   gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, app);
   gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, data);
   gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, cache);
+  gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, total);
+  gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, clear_cache_button);
 
   gtk_widget_class_bind_template_callback (widget_class, camera_cb);
   gtk_widget_class_bind_template_callback (widget_class, location_cb);
   gtk_widget_class_bind_template_callback (widget_class, microphone_cb);
+  gtk_widget_class_bind_template_callback (widget_class, search_cb);
   gtk_widget_class_bind_template_callback (widget_class, notification_cb);
   gtk_widget_class_bind_template_callback (widget_class, privacy_link_cb);
   gtk_widget_class_bind_template_callback (widget_class, sound_cb);
   gtk_widget_class_bind_template_callback (widget_class, permission_row_activated_cb);
-  gtk_widget_class_bind_template_callback (widget_class, file_type_row_activated_cb);
-  gtk_widget_class_bind_template_callback (widget_class, clear_cb);
-  gtk_widget_class_bind_template_callback (widget_class, uninstall_cb);
+  gtk_widget_class_bind_template_callback (widget_class, handler_row_activated_cb);
+  gtk_widget_class_bind_template_callback (widget_class, clear_cache_cb);
+  gtk_widget_class_bind_template_callback (widget_class, storage_row_activated_cb);
 }
 
 static void
@@ -1386,6 +1460,7 @@ cc_applications_panel_init (CcApplicationsPanel *self)
   g_signal_connect (self->header_button, "clicked", G_CALLBACK (open_software_cb), self);
 
   self->location_settings = g_settings_new ("org.gnome.system.location");
+  self->privacy_settings = g_settings_new ("org.gnome.desktop.privacy");
 
   populate_applications (self);
 
diff --git a/panels/applications/cc-applications-panel.ui b/panels/applications/cc-applications-panel.ui
index c566053b9..381c80b43 100644
--- a/panels/applications/cc-applications-panel.ui
+++ b/panels/applications/cc-applications-panel.ui
@@ -54,7 +54,7 @@
                               <object class="GtkLabel">
                                 <property name="visible">1</property>
                                 <property name="xalign">0</property>
-                                <property name="label" translatable="yes">Access and Permissions</property>
+                                <property name="label" translatable="yes">Permissions &amp; Access</property>
                                 <style>
                                   <class name="section-title"/>
                                 </style>
@@ -64,7 +64,9 @@
                               <object class="GtkLabel">
                                 <property name="visible">1</property>
                                 <property name="xalign">0</property>
-                                <property name="label" translatable="yes">Data and services that this app 
has asked for access to and permissions that it requires</property>
+                                <property name="wrap">1</property>
+                                <property name="max-width-chars">50</property>
+                                <property name="label" translatable="yes">Data and services that this app 
has asked for access to and permissions that it requires.</property>
                                 <style>
                                   <class name="section-subtitle"/>
                                 </style>
@@ -81,45 +83,36 @@
                               <object class="CcToggleRow" id="camera">
                                 <property name="title" translatable="yes">Camera</property>
                                 <signal name="notify::allowed" handler="camera_cb" swapped="yes"/>
-                                <signal name="link-activated" handler="privacy_link_cb"/>
                               </object>
                             </child>
                             <child>
                               <object class="CcInfoRow" id="no_camera">
                                 <property name="title" translatable="yes">Camera</property>
                                 <property name="info" translatable="yes">Disabled</property>
-                                <property name="has-expander">True</property>
-                                <property name="is-link">True</property>
                               </object>
                             </child>
                             <child>
                               <object class="CcToggleRow" id="microphone">
                                 <property name="title" translatable="yes">Microphone</property>
                                 <signal name="notify::allowed" handler="microphone_cb" swapped="yes"/>
-                                <signal name="link-activated" handler="privacy_link_cb"/>
                               </object>
                             </child>
                             <child>
                               <object class="CcInfoRow" id="no_microphone">
                                 <property name="title" translatable="yes">Microphone</property>
                                 <property name="info" translatable="yes">Disabled</property>
-                                <property name="has-expander">True</property>
-                                <property name="is-link">True</property>
                               </object>
                             </child>
                             <child>
                               <object class="CcToggleRow" id="location">
                                 <property name="title" translatable="yes">Location Services</property>
                                 <signal name="notify::allowed" handler="location_cb" swapped="yes"/>
-                                <signal name="link-activated" handler="privacy_link_cb"/>
                               </object>
                             </child>
                             <child>
                               <object class="CcInfoRow" id="no_location">
                                 <property name="title" translatable="yes">Location Services</property>
                                 <property name="info" translatable="yes">Disabled</property>
-                                <property name="has-expander">True</property>
-                                <property name="is-link">True</property>
                               </object>
                             </child>
                             <child>
@@ -127,6 +120,7 @@
                                 <property name="title" translatable="yes">Built-in Permissions</property>
                                 <property name="info" translatable="yes">Cannot be changed</property>
                                 <property name="has-expander">True</property>
+                                <property name="is-link">True</property>
                               </object>
                             </child>
                             <style>
@@ -135,65 +129,15 @@
                             </style>
                           </object>
                         </child>
-                      </object>
-                    </child>
-                    <child>
-                      <object class="GtkBox" id="information_section">
-                        <property name="visible">1</property>
-                        <property name="orientation">vertical</property>
-                        <property name="spacing">12</property>
-                        <style>
-                          <class name="section"/>
-                        </style>
-                        <child>
-                          <object class="GtkBox">
-                            <property name="visible">1</property>
-                            <property name="orientation">vertical</property>
-                            <property name="spacing">6</property>
-                            <child>
-                              <object class="GtkLabel">
-                                <property name="visible">1</property>
-                                <property name="xalign">0</property>
-                                <property name="label" translatable="yes">Information</property>
-                                <style>
-                                  <class name="section-title"/>
-                                </style>
-                              </object>
-                            </child>
-                            <child>
-                              <object class="GtkLabel">
-                                <property name="visible">1</property>
-                                <property name="xalign">0</property>
-                                <property name="label" translatable="yes">How the application can 
communicate with you or provide information and feedback.</property>
-                                <style>
-                                  <class name="section-subtitle"/>
-                                </style>
-                              </object>
-                            </child>
-                          </object>
-                        </child>
                         <child>
-                          <object class="GtkListBox" id="information_list">
-                            <property name="visible">1</property>
-                            <property name="selection-mode">none</property>
-                            <child>
-                              <object class="CcToggleRow" id="notification">
-                                <property name="title" translatable="yes">Notifications</property>
-                                <signal name="notify::allowed" handler="notification_cb" swapped="yes"/>
-                                <signal name="link-activated" handler="privacy_link_cb"/>
-                              </object>
-                            </child>
-                            <child>
-                              <object class="CcToggleRow" id="sound">
-                                <property name="title" translatable="yes">Sounds</property>
-                                <signal name="notify::allowed" handler="sound_cb" swapped="yes"/>
-                                <signal name="link-activated" handler="privacy_link_cb"/>
-                              </object>
-                            </child>
-                            <style>
-                              <class name="view"/>
-                              <class name="frame"/>
-                            </style>
+                          <object class="GtkLabel">
+                            <property name="visible">True</property>
+                            <property name="xalign">0</property>
+                            <property name="wrap">1</property>
+                            <property name="max-width-chars">50</property>
+                            <property name="label" translatable="yes">Individual permissions for 
applications can be reviewed in the &lt;a href="privacy"&gt;Privacy&lt;/a&gt; Settings.</property>
+                            <property name="use-markup">True</property>
+                            <signal name="activate-link" handler="privacy_link_cb" swapped="yes"/>
                           </object>
                         </child>
                       </object>
@@ -225,6 +169,8 @@
                               <object class="GtkLabel">
                                 <property name="visible">1</property>
                                 <property name="xalign">0</property>
+                                <property name="wrap">1</property>
+                                <property name="max-width-chars">50</property>
                                 <property name="label" translatable="yes">USB Devices that this application 
has access to</property>
                                 <style>
                                   <class name="section-subtitle"/>
@@ -246,7 +192,7 @@
                       </object>
                     </child>
                     <child>
-                      <object class="GtkBox" id="file_type_section">
+                      <object class="GtkBox" id="integration_section">
                         <property name="visible">1</property>
                         <property name="orientation">vertical</property>
                         <property name="spacing">12</property>
@@ -262,7 +208,7 @@
                               <object class="GtkLabel">
                                 <property name="visible">1</property>
                                 <property name="xalign">0</property>
-                                <property name="label" translatable="yes">File Associations</property>
+                                <property name="label" translatable="yes">Integration</property>
                                 <style>
                                   <class name="section-title"/>
                                 </style>
@@ -272,7 +218,9 @@
                               <object class="GtkLabel">
                                 <property name="visible">1</property>
                                 <property name="xalign">0</property>
-                                <property name="label" translatable="yes">The types of files that this 
application opens.</property>
+                                <property name="wrap">1</property>
+                                <property name="max-width-chars">50</property>
+                                <property name="label" translatable="yes">System features used by this 
application.</property>
                                 <style>
                                   <class name="section-subtitle"/>
                                 </style>
@@ -281,10 +229,33 @@
                           </object>
                         </child>
                         <child>
-                          <object class="GtkListBox" id="file_type_list">
+                          <object class="GtkListBox" id="integration_list">
                             <property name="visible">1</property>
                             <property name="selection-mode">none</property>
-                            <signal name="row-activated" handler="file_type_row_activated_cb"/>
+                            <child>
+                              <object class="CcToggleRow" id="search">
+                                <property name="title" translatable="yes">Search</property>
+                                <signal name="notify::allowed" handler="search_cb" swapped="yes"/>
+                              </object>
+                            </child>
+                            <child>
+                              <object class="CcToggleRow" id="notification">
+                                <property name="title" translatable="yes">Notifications</property>
+                                <signal name="notify::allowed" handler="notification_cb" swapped="yes"/>
+                              </object>
+                            </child>
+                            <child>
+                              <object class="CcToggleRow" id="sound">
+                                <property name="title" translatable="yes">Sounds</property>
+                                <signal name="notify::allowed" handler="sound_cb" swapped="yes"/>
+                              </object>
+                            </child>
+                            <child>
+                              <object class="CcInfoRow" id="no_sound">
+                                <property name="title" translatable="yes">Sounds</property>
+                                <property name="info" translatable="yes">Disabled</property>
+                              </object>
+                            </child>
                             <style>
                               <class name="view"/>
                               <class name="frame"/>
@@ -294,7 +265,7 @@
                       </object>
                     </child>
                     <child>
-                      <object class="GtkBox" id="link_type_section">
+                      <object class="GtkBox" id="handler_section">
                         <property name="visible">1</property>
                         <property name="orientation">vertical</property>
                         <property name="spacing">12</property>
@@ -310,7 +281,7 @@
                               <object class="GtkLabel">
                                 <property name="visible">1</property>
                                 <property name="xalign">0</property>
-                                <property name="label" translatable="yes">Link Associations</property>
+                                <property name="label" translatable="yes">Default Handlers</property>
                                 <style>
                                   <class name="section-title"/>
                                 </style>
@@ -320,7 +291,9 @@
                               <object class="GtkLabel">
                                 <property name="visible">1</property>
                                 <property name="xalign">0</property>
-                                <property name="label" translatable="yes">The types of links that this 
application opens.</property>
+                                <property name="wrap">1</property>
+                                <property name="max-width-chars">50</property>
+                                <property name="label" translatable="yes">Types of files and links that this 
application opens.</property>
                                 <style>
                                   <class name="section-subtitle"/>
                                 </style>
@@ -329,9 +302,10 @@
                           </object>
                         </child>
                         <child>
-                          <object class="GtkListBox" id="link_type_list">
+                          <object class="GtkListBox" id="handler_list">
                             <property name="visible">1</property>
                             <property name="selection-mode">none</property>
+                            <signal name="row-activated" handler="handler_row_activated_cb"/>
                             <style>
                               <class name="view"/>
                               <class name="frame"/>
@@ -340,9 +314,8 @@
                         </child>
                       </object>
                     </child>
-FOO
                     <child>
-                      <object class="GtkBox" id="storage_section">
+                      <object class="GtkBox" id="usage_section">
                         <property name="visible">1</property>
                         <property name="orientation">vertical</property>
                         <property name="spacing">12</property>
@@ -358,7 +331,7 @@ FOO
                               <object class="GtkLabel">
                                 <property name="visible">1</property>
                                 <property name="xalign">0</property>
-                                <property name="label" translatable="yes">Storage</property>
+                                <property name="label" translatable="yes">Usage</property>
                                 <style>
                                   <class name="section-title"/>
                                 </style>
@@ -368,7 +341,9 @@ FOO
                               <object class="GtkLabel">
                                 <property name="visible">1</property>
                                 <property name="xalign">0</property>
-                                <property name="label" translatable="yes">How much disk space this 
application is occupying with app data and caches</property>
+                                <property name="wrap">1</property>
+                                <property name="max-width-chars">50</property>
+                                <property name="label" translatable="yes">How much resources this 
application is using.</property>
                                 <style>
                                   <class name="section-subtitle"/>
                                 </style>
@@ -377,30 +352,16 @@ FOO
                           </object>
                         </child>
                         <child>
-                          <object class="GtkListBox" id="storage_list">
+                          <object class="GtkListBox" id="usage_list">
                             <property name="visible">1</property>
                             <property name="selection-mode">none</property>
+                            <signal name="row-activated" handler="storage_row_activated_cb"/>
                             <child>
-                              <object class="CcActionRow" id="app">
-                                <property name="title" translatable="yes">App Size</property>
-                                <property name="subtitle" translatable="yes">Unknown</property>
-                                <property name="action" translatable="yes">Uninstall App…</property>
-                                <property name="destructive">True</property>
-                                <signal name="activated" handler="uninstall_cb"/>
-                              </object>
-                            </child>
-                            <child>
-                              <object class="CcActionRow" id="data">
-                                <property name="title" translatable="yes">Data</property>
-                                <property name="action" translatable="yes">Clear Data…</property>
-                                <signal name="activated" handler="clear_cb"/>
-                              </object>
-                            </child>
-                            <child>
-                              <object class="CcActionRow" id="cache">
-                                <property name="title" translatable="yes">Cache</property>
-                                <property name="action" translatable="yes">Clear Cache…</property>
-                                <signal name="activated" handler="clear_cb"/>
+                              <object class="CcInfoRow" id="storage">
+                                <property name="title" translatable="yes">Storage</property>
+                                <property name="info">unknown</property>
+                                <property name="has-expander">1</property>
+                                <property name="is-link">1</property>
                               </object>
                             </child>
                             <style>
@@ -444,4 +405,120 @@ FOO
     <property name="visible">1</property>
     <property name="selection-mode">browse</property>
   </object>
+  <object class="GtkDialog" id="builtin_dialog">
+    <property name="title" translatable="yes">Built-in Permissions</property>
+    <property name="modal">1</property>
+    <property name="type_hint">dialog</property>
+    <property name="use_header_bar">1</property>
+    <property name="resizable">0</property>
+    <property name="border-width">24</property>
+    <signal name="delete-event" handler="gtk_widget_hide_on_delete"/>
+    <child internal-child="vbox">
+      <object class="GtkBox">
+        <property name="visible">1</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">12</property>
+        <child>
+          <object class="GtkLabel" id="builtin_label">
+            <property name="visible">1</property>
+            <property name="wrap">1</property>
+            <property name="max-width-chars">50</property>
+            <property name="label">Yadda Yadda</property>
+          </object>
+        </child>
+        <child>
+          <object class="GtkListBox" id="builtin_list">
+            <property name="visible">1</property>
+            <property name="selection-mode">none</property>
+            <style>
+              <class name="view"/>
+              <class name="frame"/>
+            </style>
+          </object>
+        </child>
+      </object>
+    </child>
+  </object>
+  <object class="GtkDialog" id="storage_dialog">
+    <property name="title" translatable="yes">Storage</property>
+    <property name="modal">1</property>
+    <property name="type_hint">dialog</property>
+    <property name="use_header_bar">1</property>
+    <property name="resizable">0</property>
+    <property name="border-width">24</property>
+    <signal name="delete-event" handler="gtk_widget_hide_on_delete"/>
+    <child internal-child="vbox">
+      <object class="GtkBox">
+        <property name="visible">1</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">12</property>
+        <child>
+          <object class="GtkLabel">
+            <property name="visible">1</property>
+            <property name="wrap">1</property>
+            <property name="max-width-chars">50</property>
+            <property name="label">Yadda Yadda</property>
+          </object>
+        </child>
+        <child>
+          <object class="GtkListBox" id="storage_list">
+            <property name="visible">1</property>
+            <property name="selection-mode">none</property>
+            <child>
+              <object class="CcInfoRow" id="app">
+                <property name="title" translatable="yes">Application</property>
+                <property name="info">Unknown</property>
+              </object>
+            </child>
+            <child>
+              <object class="CcInfoRow" id="data">
+                <property name="title" translatable="yes">Data</property>
+                <property name="info">Unknown</property>
+              </object>
+            </child>
+            <child>
+              <object class="CcInfoRow" id="cache">
+                <property name="title" translatable="yes">Cache</property>
+                <property name="info">Unknown</property>
+              </object>
+            </child>
+            <child>
+              <object class="CcInfoRow" id="total">
+                <property name="title" translatable="yes">&lt;b&gt;Total&lt;/b&gt;</property>
+                <property name="use-markup">1</property>
+                <property name="info">Unknown</property>
+              </object>
+            </child>
+            <style>
+              <class name="view"/>
+              <class name="frame"/>
+            </style>
+          </object>
+        </child>
+        <child>
+          <object class="GtkLabel">
+            <property name="visible">1</property>
+            <property name="wrap">1</property>
+            <property name="max-width-chars">50</property>
+            <property name="label">Yadda Yadda</property>
+          </object>
+        </child>
+        <child>
+          <object class="GtkBox">
+            <property name="visible">1</property>
+            <child>
+              <object class="GtkButton" id="clear_cache_button">
+                <property name="visible">1</property>
+                <property name="label" translatable="yes">Clear Cache…</property>
+                <signal name="clicked" handler="clear_cache_cb" swapped="yes"/>
+              </object>
+              <packing>
+                <property name="pack-type">end</property>
+              </packing>
+            </child>
+          </object>
+        </child>
+      </object>
+    </child>
+  </object>
 </interface>
diff --git a/panels/applications/cc-info-row.c b/panels/applications/cc-info-row.c
index 1370cf653..75dd601a9 100644
--- a/panels/applications/cc-info-row.c
+++ b/panels/applications/cc-info-row.c
@@ -27,6 +27,7 @@
 enum {
   PROP_ZERO,
   PROP_TITLE,
+  PROP_USE_MARKUP,
   PROP_INFO,
   PROP_HAS_EXPANDER,
   PROP_IS_LINK,
@@ -74,6 +75,9 @@ cc_info_row_get_property (GObject    *object,
     case PROP_HAS_EXPANDER:
       g_value_set_boolean (value, gtk_widget_get_visible (row->expander));
       break;
+    case PROP_USE_MARKUP:
+      g_value_set_boolean (value, gtk_label_get_use_markup (GTK_LABEL (row->title)));
+      break;
     case PROP_IS_LINK:
       g_value_set_boolean (value, row->link);
       break;
@@ -117,6 +121,9 @@ cc_info_row_set_property (GObject      *object,
       gtk_widget_set_visible (row->expander, g_value_get_boolean (value));
       gtk_list_box_row_set_activatable (GTK_LIST_BOX_ROW (row), g_value_get_boolean (value));
       break;
+    case PROP_USE_MARKUP:
+      gtk_label_set_use_markup (GTK_LABEL (row->title), g_value_get_boolean (value));
+      break;
     case PROP_IS_LINK:
       row->link = g_value_get_boolean (value);
       update_expander (row);
@@ -152,6 +159,11 @@ cc_info_row_class_init (CcInfoRowClass *klass)
                                    g_param_spec_string ("info", "info", "info",
                                                         NULL, G_PARAM_READWRITE));
 
+  g_object_class_install_property (object_class,
+                                   PROP_USE_MARKUP,
+                                   g_param_spec_boolean ("use-markup", "use-markup", "use-markup",
+                                                         FALSE, G_PARAM_READWRITE));
+
   g_object_class_install_property (object_class,
                                    PROP_HAS_EXPANDER,
                                    g_param_spec_boolean ("has-expander", "has-expander", "has-expander",
diff --git a/panels/applications/cc-info-row.ui b/panels/applications/cc-info-row.ui
index fa3d5ea34..dc7a3a2a7 100644
--- a/panels/applications/cc-info-row.ui
+++ b/panels/applications/cc-info-row.ui
@@ -29,6 +29,9 @@
           <object class="GtkImage" id="expander">
             <property name="valign">center</property>
             <property name="icon-name">pan-end-symbolic</property>
+            <style>
+              <class name="dim-label"/>
+            </style>
           </object>
         </child>
       </object>
diff --git a/panels/applications/cc-toggle-row.c b/panels/applications/cc-toggle-row.c
index faef63c6f..2653d9429 100644
--- a/panels/applications/cc-toggle-row.c
+++ b/panels/applications/cc-toggle-row.c
@@ -36,7 +36,6 @@ struct _CcToggleRow
 
   GtkWidget *title;
   GtkWidget *toggle;
-  GtkWidget *link;
 };
 
 G_DEFINE_TYPE (CcToggleRow, cc_toggle_row, GTK_TYPE_LIST_BOX_ROW)
@@ -93,20 +92,12 @@ cc_toggle_row_set_property (GObject      *object,
     }
 }
 
-static guint link_activated;
-
 static void
 changed_cb (CcToggleRow *row)
 {
   g_object_notify (G_OBJECT (row), "allowed");
 }
 
-static void
-link_clicked (CcToggleRow *row)
-{
-  g_signal_emit (row, link_activated, 0);
-}
-
 static void
 cc_toggle_row_class_init (CcToggleRowClass *klass)
 {
@@ -129,18 +120,10 @@ cc_toggle_row_class_init (CcToggleRowClass *klass)
                                    g_param_spec_boolean ("allowed", "allowed", "allowed",
                                                          FALSE, G_PARAM_READWRITE));
 
-  link_activated = g_signal_new ("link-activated",
-                                 CC_TYPE_TOGGLE_ROW,
-                                 G_SIGNAL_RUN_FIRST,
-                                 0, NULL, NULL, NULL,
-                                 G_TYPE_NONE, 0);
-
   gtk_widget_class_bind_template_child (widget_class, CcToggleRow, title);
   gtk_widget_class_bind_template_child (widget_class, CcToggleRow, toggle);
-  gtk_widget_class_bind_template_child (widget_class, CcToggleRow, link);
 
   gtk_widget_class_bind_template_callback (widget_class, changed_cb);
-  gtk_widget_class_bind_template_callback (widget_class, link_clicked);
 }
 
 static void
diff --git a/panels/applications/cc-toggle-row.ui b/panels/applications/cc-toggle-row.ui
index f18cdffd6..144684dca 100644
--- a/panels/applications/cc-toggle-row.ui
+++ b/panels/applications/cc-toggle-row.ui
@@ -23,26 +23,6 @@
             <signal name="notify::active" handler="changed_cb" swapped="yes"/>
           </object>
         </child>
-        <child>
-          <object class="GtkSeparator">
-            <property name="visible">True</property>
-            <property name="orientation">vertical</property>
-          </object>
-        </child>
-        <child>
-          <object class="GtkButton" id="link">
-            <property name="visible">True</property>
-            <property name="valign">center</property>
-            <signal name="clicked" handler="link_clicked" swapped="yes"/>
-            <child>
-              <object class="GtkImage">
-                <property name="visible">True</property>
-                <property name="icon-name">view-more-symbolic</property>
-                <property name="icon-size">4</property>
-              </object>
-            </child>
-          </object>
-        </child>
       </object>
     </child>
   </template>
diff --git a/panels/applications/utils.c b/panels/applications/utils.c
index 35a37791f..5d46cdee4 100644
--- a/panels/applications/utils.c
+++ b/panels/applications/utils.c
@@ -20,6 +20,7 @@
 
 #include <config.h>
 #include <glib/gi18n.h>
+#include <flatpak/flatpak.h>
 
 #include "utils.h"
 
@@ -66,29 +67,39 @@ container_remove_all (GtkContainer *container)
   g_list_free (children);
 }
 
-char *
-get_flatpak_app_size (const char *app_id)
+FlatpakInstalledRef *
+find_flatpak_ref (const char *app_id)
 {
-  const char *argv[] = { "flatpak", "info", "-s", "appid", NULL };
-  char *out;
-
-  /* FIXME: use libflatpak */
-  argv[3] = app_id;
-  
-  if (!g_spawn_sync (NULL, (char **)argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, &out, NULL, NULL, NULL))
-    return NULL;
+  g_autoptr(FlatpakInstallation) inst = NULL;
+  g_autoptr(GPtrArray) array = NULL;
+  FlatpakInstalledRef *ref;
+  int i;
+
+  inst = flatpak_installation_new_user (NULL, NULL);
+  ref = flatpak_installation_get_current_installed_app (inst, app_id, NULL, NULL);
+  if (ref)
+    return ref;
+
+  array = flatpak_get_system_installations (NULL, NULL);
+  for (i = 0; i < array->len; i++)
+    {
+      FlatpakInstallation *si = g_ptr_array_index (array, i);
+      ref = flatpak_installation_get_current_installed_app (si, app_id, NULL, NULL);
+      if (ref)
+        return ref;
+    }
 
-  return g_strstrip (out);
+  return NULL;
 }
 
-void
-uninstall_flatpak_app (const char *app_id)
+guint64
+get_flatpak_app_size (const char *app_id)
 {
-  const char *argv[] = { "flatpak", "uninstall", "--assumeyes", "appid", NULL };
-  g_autofree char *out = NULL;
+  g_autoptr(FlatpakInstalledRef) ref = NULL;
 
-  /* FIXME: use libflatpak, error handling */
-  argv[3] = app_id;
-  
-  g_spawn_sync (NULL, (char **)argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, &out, NULL, NULL, NULL);
+  ref = find_flatpak_ref (app_id);
+  if (ref)
+    return flatpak_installed_ref_get_installed_size (ref);
+
+  return 0;
 }
diff --git a/panels/applications/utils.h b/panels/applications/utils.h
index c6dbd97eb..e2acc5ec3 100644
--- a/panels/applications/utils.h
+++ b/panels/applications/utils.h
@@ -22,13 +22,14 @@
 
 #include <gio/gio.h>
 #include <gtk/gtk.h>
+#include <flatpak/flatpak.h>
 
 G_BEGIN_DECLS
 
 void    file_remove_recursively (GFile *file);
 guint64 file_size_recursively (GFile *file);
 void    container_remove_all (GtkContainer *container);
-char *get_flatpak_app_size (const char *app_id);
-void uninstall_flatpak_app (const char *app_id);
+FlatpakInstalledRef *find_flatpak_ref (const char *app_id);
+guint64 get_flatpak_app_size (const char *app_id);
 
 G_END_DECLS


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