[gnome-control-center/wip/applications] Tweak to follow an alternative design
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-control-center/wip/applications] Tweak to follow an alternative design
- Date: Wed, 28 Nov 2018 16:05:41 +0000 (UTC)
commit 0978dba1917799f3003e1d67ef5b32b7ef0fccb6
Author: Matthias Clasen <mclasen redhat com>
Date: Wed Nov 28 11:05:05 2018 -0500
Tweak to follow an alternative design
panels/applications/applications.gresource.xml | 1 +
panels/applications/cc-applications-panel.c | 323 ++++++++++--------
panels/applications/cc-applications-panel.ui | 431 +++++++++++++++----------
panels/applications/cc-info-row.c | 145 +++++++++
panels/applications/cc-info-row.h | 32 ++
panels/applications/cc-info-row.ui | 48 +++
panels/applications/cc-toggle-row.c | 127 +++++---
panels/applications/cc-toggle-row.h | 6 +-
panels/applications/cc-toggle-row.ui | 27 +-
panels/applications/meson.build | 1 +
panels/applications/utils.c | 26 ++
panels/applications/utils.h | 2 +
12 files changed, 827 insertions(+), 342 deletions(-)
---
diff --git a/panels/applications/applications.gresource.xml b/panels/applications/applications.gresource.xml
index a8b996f49..2a8fd59b4 100644
--- a/panels/applications/applications.gresource.xml
+++ b/panels/applications/applications.gresource.xml
@@ -4,6 +4,7 @@
<file preprocess="xml-stripblanks">cc-applications-panel.ui</file>
<file preprocess="xml-stripblanks">cc-applications-row.ui</file>
<file preprocess="xml-stripblanks">cc-toggle-row.ui</file>
+ <file preprocess="xml-stripblanks">cc-info-row.ui</file>
<file preprocess="xml-stripblanks">cc-action-row.ui</file>
<file>cc-applications-panel.css</file>
</gresource>
diff --git a/panels/applications/cc-applications-panel.c b/panels/applications/cc-applications-panel.c
index f82a78fb8..5da724097 100644
--- a/panels/applications/cc-applications-panel.c
+++ b/panels/applications/cc-applications-panel.c
@@ -26,6 +26,7 @@
#include "cc-applications-panel.h"
#include "cc-applications-row.h"
#include "cc-toggle-row.h"
+#include "cc-info-row.h"
#include "cc-action-row.h"
#include "cc-applications-resources.h"
#include "list-box-helper.h"
@@ -59,24 +60,30 @@ struct _CcApplicationsPanel
GDBusProxy *perm_store;
GSettings *notification_settings;
+ GtkListBox *stack;
GtkWidget *permission_section;
GtkWidget *permission_list;
GtkWidget *camera;
GtkWidget *location;
GtkWidget *microphone;
+
+ GtkWidget *permission_footer;
+
+ GtkWidget *information_section;
+ GtkWidget *information_list;
GtkWidget *notification;
GtkWidget *sound;
- GtkWidget *static_permissions;
-
GtkWidget *device_section;
GtkWidget *device_list;
GtkWidget *handler_section;
GtkWidget *handler_list;
- GtkWidget *cache_section;
- GtkWidget *cache_list;
+ GtkWidget *storage_section;
+ GtkWidget *storage_list;
+ GtkWidget *app;
+ GtkWidget *data;
GtkWidget *cache;
};
@@ -198,7 +205,7 @@ get_notification_allowed (CcApplicationsPanel *self,
{
if (self->notification_settings)
{
- return g_settings_get_boolean (self->notification_settings, "enable");
+ return g_settings_get_boolean (self->notification_settings, "enable");
}
else
{
@@ -206,21 +213,17 @@ get_notification_allowed (CcApplicationsPanel *self,
"notifications",
"notification",
app_id);
- return perms == NULL || !g_strv_contains ((const char * const*)perms, "no");
+ return perms == NULL || strcmp (perms[0], "no") != 0;
}
}
static void
-notification_cb (CcToggleRow *row, CcApplicationsPanel *self)
+set_notification_allowed (CcApplicationsPanel *self,
+ gboolean allowed)
{
- gboolean allowed = cc_toggle_row_get_allowed (row);
-
- if (self->current_app_id == NULL)
- return;
-
if (self->notification_settings)
{
- g_settings_set_boolean (self->notification_settings, "enable", allowed);
+ g_settings_set_boolean (self->notification_settings, "enable", allowed);
}
else
{
@@ -231,6 +234,13 @@ notification_cb (CcToggleRow *row, CcApplicationsPanel *self)
}
}
+static void
+notification_cb (CcApplicationsPanel *self)
+{
+ if (self->current_app_id)
+ set_notification_allowed (self, cc_toggle_row_get_allowed (CC_TOGGLE_ROW (self->notification)));
+}
+
static char *
munge_app_id (const char *app_id)
{
@@ -270,7 +280,7 @@ get_device_allowed (CcApplicationsPanel *self,
perms = get_flatpak_permissions (self, "devices", device, app_id);
- return perms == NULL || !g_strv_contains ((const char * const*)perms, "no");
+ return perms == NULL || strcmp (perms[0], "no") != 0;
}
static void
@@ -280,9 +290,6 @@ set_device_allowed (CcApplicationsPanel *self,
{
const char *perms[2];
- if (self->current_app_id == NULL)
- return;
-
perms[0] = allowed ? "yes" : "no";
perms[1] = NULL;
@@ -290,21 +297,24 @@ set_device_allowed (CcApplicationsPanel *self,
}
static void
-microphone_cb (CcToggleRow *row, CcApplicationsPanel *self)
+microphone_cb (CcApplicationsPanel *self)
{
- set_device_allowed (self, "microphone", cc_toggle_row_get_allowed (row));
+ if (self->current_app_id)
+ set_device_allowed (self, "microphone", cc_toggle_row_get_allowed (CC_TOGGLE_ROW (self->microphone)));
}
static void
-sound_cb (CcToggleRow *row, CcApplicationsPanel *self)
+sound_cb (CcApplicationsPanel *self)
{
- set_device_allowed (self, "speakers", cc_toggle_row_get_allowed (row));
+ if (self->current_app_id)
+ set_device_allowed (self, "speakers", cc_toggle_row_get_allowed (CC_TOGGLE_ROW (self->sound)));
}
static void
-camera_cb (CcToggleRow *row, CcApplicationsPanel *self)
+camera_cb (CcApplicationsPanel *self)
{
- set_device_allowed (self, "camera", cc_toggle_row_get_allowed (row));
+ if (self->current_app_id)
+ set_device_allowed (self, "camera", cc_toggle_row_get_allowed (CC_TOGGLE_ROW (self->camera)));
}
static gboolean
@@ -315,7 +325,7 @@ get_location_allowed (CcApplicationsPanel *self,
perms = get_flatpak_permissions (self, "location", "location", app_id);
- return perms == NULL || !g_str_equal (perms[0], "NONE");
+ return perms == NULL || strcmp (perms[0], "NONE") != 0;
}
static void
@@ -325,9 +335,6 @@ set_location_allowed (CcApplicationsPanel *self,
const char *perms[3];
g_autofree char *time = NULL;
- if (self->current_app_id == NULL)
- return;
-
// FIXME allow setting accuracy
perms[0] = allowed ? "EXACT" : "NONE";
perms[1] = "0";
@@ -337,52 +344,79 @@ set_location_allowed (CcApplicationsPanel *self,
}
static void
-location_cb (CcToggleRow *row, CcApplicationsPanel *self)
+location_cb (CcApplicationsPanel *self)
{
- set_location_allowed (self, cc_toggle_row_get_allowed (row));
+ if (self->current_app_id)
+ set_location_allowed (self, cc_toggle_row_get_allowed (CC_TOGGLE_ROW (self->location)));
}
static GFile *
-get_cache_dir (const char *app_id)
+get_app_dir (const char *app_id,
+ const char *subdir)
{
g_autofree char *path = g_build_filename (g_get_home_dir (), ".var", "app", app_id, NULL);
g_autoptr(GFile) appdir = g_file_new_for_path (path);
- return g_file_get_child (appdir, "cache");
+ return g_file_get_child (appdir, subdir);
}
static guint64
-calculate_cache_size (const char *app_id)
+calculate_dir_size (const char *app_id,
+ const char *subdir)
{
- g_autoptr(GFile) cachedir = get_cache_dir (app_id);
+ g_autoptr(GFile) cachedir = get_app_dir (app_id, subdir);
return file_size_recursively (cachedir);
}
static void
-update_cache_row (CcActionRow *row,
- const char *app_id)
+update_app_row (CcActionRow *row,
+ const char *app_id)
+{
+ g_autofree char *formatted_size = NULL;
+
+ formatted_size = get_flatpak_app_size (app_id);
+ g_object_set (row, "subtitle", formatted_size, NULL);
+}
+
+static void
+update_dir_row (CcActionRow *row,
+ const char *app_id,
+ const char *subdir)
{
guint64 size;
g_autofree char *formatted_size = NULL;
- g_autofree char *name = NULL;
- size = calculate_cache_size (app_id);
+ 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);
- name = g_strdup_printf (_("Cache size: %s"), formatted_size);
- cc_action_row_set_name (row, name);
- cc_action_row_set_action (row, _("Clear…"), size > 0);
+ g_object_set (row,
+ "subtitle", formatted_size,
+ "enabled", size > 0,
+ NULL);
}
static void
-clear_cache_cb (CcActionRow *row, CcApplicationsPanel *self)
+clear_cb (CcActionRow *row, CcApplicationsPanel *self)
{
- g_autoptr(GFile) cachedir = NULL;
+ g_autoptr(GFile) dir = NULL;
+ const char *subdir;
if (self->current_app_id == NULL)
return;
- cachedir = get_cache_dir (self->current_app_id);
- file_remove_recursively (cachedir);
- update_cache_row (CC_ACTION_ROW (self->cache), self->current_app_id);
+ subdir = (const char *) g_object_get_data (G_OBJECT (row), "subdir");
+ dir = get_app_dir (self->current_app_id, subdir);
+ 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);
}
static char *
@@ -421,8 +455,25 @@ find_flatpak_ref (const char *app_id)
return NULL;
}
-static char *
-get_static_permissions (const char *app_id)
+static void
+add_static_permission_row (CcApplicationsPanel *self,
+ const char *title,
+ const char *subtitle)
+{
+ GtkWidget *row;
+
+ row = g_object_new (CC_TYPE_INFO_ROW,
+ "title", title,
+ "subtitle", subtitle,
+ "info", _("Built-in"),
+ "visible", TRUE,
+ NULL);
+ gtk_container_add (GTK_CONTAINER (self->permission_list), row);
+}
+
+static void
+add_static_permissions (CcApplicationsPanel *self,
+ const char *app_id)
{
g_autoptr(FlatpakInstalledRef) ref = NULL;
g_autoptr(GBytes) bytes = NULL;
@@ -430,12 +481,7 @@ get_static_permissions (const char *app_id)
g_autoptr(GKeyFile) keyfile = NULL;
char **strv;
char *str;
- GString *s;
- int len;
- s = g_string_new ("");
- g_string_append_printf (s, "<b>%s</b> ", _("Built-in permissions:"));
-
ref = find_flatpak_ref (app_id);
bytes = flatpak_installed_ref_load_metadata (ref, NULL, NULL);
keyfile = g_key_file_new ();
@@ -445,67 +491,57 @@ get_static_permissions (const char *app_id)
0, &error))
{
g_warning ("%s", error->message);
- g_string_append (s, _("Unknown."));
-
- return g_string_free (s, FALSE);
+ return;
}
- len = s->len;
-
strv = g_key_file_get_string_list (keyfile, "Context", "sockets", NULL, NULL);
if (strv && g_strv_contains ((const char * const*)strv, "system-bus"))
- {
- if (s->len > len) g_string_append (s, ", ");
- g_string_append (s, _("system bus"));
- }
+ add_static_permission_row (self, _("System Bus"), _("Has access to the system bus"));
if (strv && g_strv_contains ((const char * const*)strv, "x11"))
- {
- if (s->len > len) g_string_append (s, ", ");
- g_string_append (s, "X11");
- }
+ add_static_permission_row (self, _("X11"), _("Has access to the display server"));
g_strfreev (strv);
strv = g_key_file_get_string_list (keyfile, "Context", "devices", NULL, NULL);
if (strv && g_strv_contains ((const char * const*)strv, "all"))
- {
- if (s->len > len) g_string_append (s, ", ");
- g_string_append (s, "/dev");
- }
+ add_static_permission_row (self, _("Devices"), _("Has full access to /dev"));
g_strfreev (strv);
strv = g_key_file_get_string_list (keyfile, "Context", "shared", NULL, NULL);
if (strv && g_strv_contains ((const char * const*)strv, "network"))
- {
- if (s->len > len) g_string_append (s, ", ");
- g_string_append (s, _("network"));
- }
+ add_static_permission_row (self, _("Network"), _("Has network access"));
g_strfreev (strv);
strv = g_key_file_get_string_list (keyfile, "Context", "filesystems", NULL, NULL);
- if (strv && g_strv_contains ((const char * const *)strv, "home"))
- {
- if (s->len > len) g_string_append (s, ", ");
- g_string_append (s, _("home directory"));
- }
- if (strv && g_strv_contains ((const char * const *)strv, "host"))
- {
- if (s->len > len) g_string_append (s, ", ");
- g_string_append (s, _("host filesystem"));
- }
+ if (strv && (g_strv_contains ((const char * const *)strv, "home") ||
+ g_strv_contains ((const char * const *)strv, "home:rw")))
+ add_static_permission_row (self, _("Home"), _("Read-write access"));
+ else if (strv && g_strv_contains ((const char * const *)strv, "home:ro"))
+ add_static_permission_row (self, _("Home"), _("Readonly access"));
+ if (strv && (g_strv_contains ((const char * const *)strv, "host") ||
+ g_strv_contains ((const char * const *)strv, "host:rw")))
+ add_static_permission_row (self, _("Filesystem"), _("Full filesystem access"));
+ else if (strv && g_strv_contains ((const char * const *)strv, "host:ro"))
+ add_static_permission_row (self, _("Filesystem"), _("Readonly access"));
g_strfreev (strv);
str = g_key_file_get_string (keyfile, "Session Bus Policy", "ca.desrt.dconf", NULL);
if (str && g_str_equal (str, "talk"))
- {
- if (s->len > len) g_string_append (s, ", ");
- g_string_append (s, _("settings"));
- }
+ add_static_permission_row (self, _("Settings"), _("Can change settings"));
g_free (str);
+}
- g_string_append (s, ". ");
- g_string_append (s, _("These are set by the application and cannot be altered."));
+static void
+remove_static_permissions (CcApplicationsPanel *self)
+{
+ GList *children, *l;
- return g_string_free (s, FALSE);
+ children = gtk_container_get_children (GTK_CONTAINER (self->permission_list));
+ for (l = children; l; l = l->next)
+ {
+ if (CC_IS_INFO_ROW (l->data))
+ gtk_widget_destroy (GTK_WIDGET (l->data));
+ }
+ g_list_free (children);
}
static void
@@ -513,41 +549,43 @@ update_permission_section (CcApplicationsPanel *self,
GAppInfo *info)
{
g_autofree char *app_id = get_app_id (info);
+ g_autofree char *permissions = NULL;
- if (app_info_is_flatpak (info))
+ if (!app_info_is_flatpak (info))
{
- g_autofree char *permissions = NULL;
+ gtk_widget_hide (self->permission_section);
+ return;
+ }
- g_clear_object (&self->notification_settings);
+ gtk_widget_show (self->permission_section);
- gtk_widget_show (self->camera);
- gtk_widget_show (self->location);
- gtk_widget_show (self->microphone);
- gtk_widget_show (self->notification);
- gtk_widget_show (self->sound);
+ remove_static_permissions (self);
+ add_static_permissions (self, 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));
+}
- permissions = get_static_permissions (app_id);
- gtk_label_set_markup (GTK_LABEL (self->static_permissions), permissions);
+static void
+update_information_section (CcApplicationsPanel *self,
+ GAppInfo *info)
+{
+ g_autofree char *app_id = get_app_id (info);
- cc_toggle_row_set_allowed (CC_TOGGLE_ROW (self->notification), get_notification_allowed (self,
app_id));
+ if (app_info_is_flatpak (info))
+ {
+ g_clear_object (&self->notification_settings);
+ gtk_widget_show (self->sound);
}
else
{
g_set_object (&self->notification_settings, get_notification_settings (app_id));
- gtk_widget_hide (self->camera);
- gtk_widget_hide (self->location);
- gtk_widget_hide (self->microphone);
- gtk_widget_show (self->notification);
gtk_widget_hide (self->sound);
- gtk_label_set_label (GTK_LABEL (self->static_permissions),
- _("This application is not sandboxed and permissions cannot be fully enforced."));
}
- 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));
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));
}
@@ -570,7 +608,7 @@ add_handler_row (CcApplicationsPanel *self,
desc = g_content_type_get_description (type);
row = cc_action_row_new ();
- cc_action_row_set_name (row, desc);
+ cc_action_row_set_title (row, desc);
cc_action_row_set_action (row, _("Remove"), FALSE);
gtk_list_box_insert (GTK_LIST_BOX (self->handler_list), GTK_WIDGET (row), -1);
}
@@ -610,18 +648,20 @@ update_handler_section (CcApplicationsPanel *self,
}
static void
-update_cache_section (CcApplicationsPanel *self,
- GAppInfo *info)
+update_storage_section (CcApplicationsPanel *self,
+ GAppInfo *info)
{
if (app_info_is_flatpak (info))
{
g_autofree char *app_id = get_app_id (info);
- gtk_widget_show (self->cache_section);
- update_cache_row (CC_ACTION_ROW (self->cache), app_id);
+ 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");
}
else
{
- gtk_widget_hide (self->cache_section);
+ gtk_widget_hide (self->storage_section);
}
}
@@ -639,12 +679,13 @@ update_panel (CcApplicationsPanel *self)
if (row == NULL)
{
- g_print ("nothing selected\n");
gtk_label_set_label (GTK_LABEL (self->title_label), _("Applications"));
- // FIXME handle no-app case
+ gtk_stack_set_visible_child_name (GTK_STACK (self->stack), "empty");
return;
}
+ gtk_stack_set_visible_child_name (GTK_STACK (self->stack), "settings");
+
g_clear_pointer (&self->current_app_id, g_free);
info = cc_applications_row_get_info (CC_APPLICATIONS_ROW (row));
@@ -652,9 +693,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_device_section (self, info);
update_handler_section (self, info);
- update_cache_section (self, info);
+ update_storage_section (self, info);
self->current_app_id = get_app_id (info);
}
@@ -683,6 +725,26 @@ populate_applications (CcApplicationsPanel *self)
g_list_free_full (infos, g_object_unref);
}
+static void
+prepare_content (CcApplicationsPanel *self)
+{
+ gtk_list_box_set_header_func (GTK_LIST_BOX (self->permission_list),
+ cc_list_box_update_header_func,
+ NULL, NULL);
+
+ gtk_list_box_set_header_func (GTK_LIST_BOX (self->information_list),
+ cc_list_box_update_header_func,
+ NULL, NULL);
+
+ 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->storage_list),
+ cc_list_box_update_header_func,
+ NULL, NULL);
+}
+
static int
compare_rows (GtkListBoxRow *row1,
GtkListBoxRow *row2,
@@ -765,20 +827,25 @@ cc_applications_panel_class_init (CcApplicationsPanelClass *klass)
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, sidebar_listbox);
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, title_label);
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, header_button);
+ gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, stack);
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, permission_section);
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, permission_list);
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, camera);
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, location);
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, microphone);
+ gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, permission_footer);
+ 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, notification);
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, sound);
- gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, static_permissions);
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, handler_section);
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, handler_list);
- gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, cache_section);
- gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, cache_list);
+ gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, storage_section);
+ 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_callback (widget_class, camera_cb);
@@ -786,7 +853,8 @@ cc_applications_panel_class_init (CcApplicationsPanelClass *klass)
gtk_widget_class_bind_template_callback (widget_class, microphone_cb);
gtk_widget_class_bind_template_callback (widget_class, notification_cb);
gtk_widget_class_bind_template_callback (widget_class, sound_cb);
- gtk_widget_class_bind_template_callback (widget_class, clear_cache_cb);
+ gtk_widget_class_bind_template_callback (widget_class, clear_cb);
+ gtk_widget_class_bind_template_callback (widget_class, uninstall_cb);
}
static void
@@ -815,16 +883,9 @@ cc_applications_panel_init (CcApplicationsPanel *self)
populate_applications (self);
self->monitor = g_app_info_monitor_get ();
-
g_signal_connect (self->monitor, "changed", G_CALLBACK (apps_changed), self);
- gtk_list_box_set_header_func (GTK_LIST_BOX (self->permission_list),
- cc_list_box_update_header_func,
- NULL, NULL);
-
- gtk_list_box_set_header_func (GTK_LIST_BOX (self->handler_list),
- cc_list_box_update_header_func,
- NULL, NULL);
+ prepare_content (self);
g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
G_DBUS_PROXY_FLAGS_NONE,
diff --git a/panels/applications/cc-applications-panel.ui b/panels/applications/cc-applications-panel.ui
index 042f8a80f..b6dc32df9 100644
--- a/panels/applications/cc-applications-panel.ui
+++ b/panels/applications/cc-applications-panel.ui
@@ -8,265 +8,356 @@
<property name="visible">1</property>
<property name="hscrollbar-policy">never</property>
<child>
- <object class="GtkBox">
+ <object class="GtkStack" id="stack">
<property name="visible">1</property>
<child>
<object class="GtkBox">
<property name="visible">1</property>
- <property name="hexpand">1</property>
</object>
+ <packing>
+ <property name="name">empty</property>
+ </packing>
</child>
<child>
<object class="GtkBox">
<property name="visible">1</property>
- <property name="orientation">vertical</property>
- <property name="margin-top">32</property>
- <property name="margin-bottom">32</property>
- <property name="margin-left">24</property>
- <property name="margin-right">24</property>
- <property name="spacing">24</property>
- <property name="hexpand">1</property>
<child>
- <object class="GtkBox" id="permission_section">
+ <object class="GtkBox">
+ <property name="visible">1</property>
+ <property name="hexpand">1</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
<property name="visible">1</property>
<property name="orientation">vertical</property>
- <property name="spacing">12</property>
- <style>
- <class name="section"/>
- </style>
+ <property name="margin-top">32</property>
+ <property name="margin-bottom">32</property>
+ <property name="margin-left">24</property>
+ <property name="margin-right">24</property>
+ <property name="spacing">24</property>
+ <property name="hexpand">1</property>
<child>
- <object class="GtkBox">
+ <object class="GtkBox" id="permission_section">
<property name="visible">1</property>
<property name="orientation">vertical</property>
- <property name="spacing">6</property>
+ <property name="spacing">12</property>
+ <style>
+ <class name="section"/>
+ </style>
<child>
- <object class="GtkLabel">
+ <object class="GtkBox">
<property name="visible">1</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">Access and Permissions</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">Access and Permissions</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">Applications will ask for access
and permission that they require</property>
+ <style>
+ <class name="section-subtitle"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkListBox" id="permission_list">
+ <property name="visible">1</property>
+ <property name="selection-mode">none</property>
+ <child>
+ <object class="CcToggleRow" id="camera">
+ <property name="title" translatable="yes">Camera</property>
+ <property name="on-subtitle" translatable="yes">Only when using the
app</property>
+ <property name="off-subtitle" translatable="yes">Off</property>
+ <signal name="notify::allowed" handler="camera_cb" swapped="yes"/>
+ </object>
+ </child>
+ <child>
+ <object class="CcToggleRow" id="microphone">
+ <property name="title" translatable="yes">Microphone</property>
+ <property name="on-subtitle" translatable="yes">Only when using the
app</property>
+ <property name="off-subtitle" translatable="yes">Off</property>
+ <signal name="notify::allowed" handler="microphone_cb" swapped="yes"/>
+ </object>
+ </child>
+ <child>
+ <object class="CcToggleRow" id="location">
+ <property name="title" translatable="yes">Location Services</property>
+ <property name="on-subtitle" translatable="yes">Only when using the
app</property>
+ <property name="off-subtitle" translatable="yes">Off</property>
+ <signal name="notify::allowed" handler="location_cb" swapped="yes"/>
+ </object>
+ </child>
<style>
- <class name="section-title"/>
+ <class name="view"/>
+ <class name="frame"/>
</style>
</object>
</child>
<child>
- <object class="GtkLabel">
+ <object class="GtkLabel" id="permission_footer">
<property name="visible">1</property>
<property name="xalign">0</property>
- <property name="label" translatable="yes">Applications will ask for access and
permission that they require</property>
+ <property name="wrap">1</property>
+ <property name="label" translatable="yes">To manage access and
permission-related settings for all applications, go to the Privacy panel.</property>
<style>
- <class name="section-subtitle"/>
+ <class name="dim-label"/>
</style>
</object>
</child>
</object>
</child>
<child>
- <object class="GtkListBox" id="permission_list">
+ <object class="GtkBox" id="information_section">
<property name="visible">1</property>
- <property name="selection-mode">none</property>
- <child>
- <object class="CcToggleRow" id="camera">
- <property name="name" translatable="yes">Camera</property>
- <signal name="changed" handler="camera_cb"/>
- </object>
- </child>
- <child>
- <object class="CcToggleRow" id="location">
- <property name="name" translatable="yes">Location</property>
- <signal name="changed" handler="location_cb"/>
- </object>
- </child>
- <child>
- <object class="CcToggleRow" id="microphone">
- <property name="name" translatable="yes">Microphone</property>
- <signal name="changed" handler="microphone_cb"/>
- </object>
- </child>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <style>
+ <class name="section"/>
+ </style>
<child>
- <object class="CcToggleRow" id="notification">
- <property name="name" translatable="yes">Notifications</property>
- <signal name="changed" handler="notification_cb"/>
- </object>
+ <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="CcToggleRow" id="sound">
- <property name="name" translatable="yes">Sound</property>
- <signal name="changed" handler="sound_cb"/>
- </object>
+ <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>
+ <property name="on-subtitle" translatable="yes">Only on lock
screen</property>
+ <property name="off-subtitle" translatable="yes">Off</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>
+ <property name="on-subtitle" translatable="yes">Alerts only</property>
+ <property name="off-subtitle" translatable="yes">Off</property>
+ <signal name="notify::allowed" handler="sound_cb" swapped="yes"/>
+ </object>
+ </child>
+ <style>
+ <class name="view"/>
+ <class name="frame"/>
+ </style>
+ </object>
</child>
- <style>
- <class name="view"/>
- <class name="frame"/>
- </style>
</object>
</child>
<child>
- <object class="GtkLabel" id="static_permissions">
+ <object class="GtkBox" id="device_section">
<property name="visible">1</property>
- <property name="xalign">0</property>
- <property name="wrap">1</property>
- <property name="wrap-mode">word</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
<style>
- <class name="dim-label"/>
+ <class name="section"/>
</style>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkBox" id="device_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">
+ <object class="GtkBox">
<property name="visible">1</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">Device Access</property>
- <style>
- <class name="section-title"/>
- </style>
+ <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">Device Access</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">USB Devices that this application
has access to</property>
+ <style>
+ <class name="section-subtitle"/>
+ </style>
+ </object>
+ </child>
</object>
</child>
<child>
- <object class="GtkLabel">
+ <object class="GtkListBox" id="device_list">
<property name="visible">1</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">USB Devices that this application has
access to</property>
+ <property name="selection-mode">none</property>
<style>
- <class name="section-subtitle"/>
+ <class name="view"/>
+ <class name="frame"/>
</style>
</object>
</child>
</object>
</child>
<child>
- <object class="GtkListBox" id="device_list">
+ <object class="GtkBox" id="handler_section">
<property name="visible">1</property>
- <property name="selection-mode">none</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
<style>
- <class name="view"/>
- <class name="frame"/>
+ <class name="section"/>
</style>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkBox" id="handler_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">
+ <object class="GtkBox">
<property name="visible">1</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">Default Handler</property>
- <style>
- <class name="section-title"/>
- </style>
+ <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">Default Handler</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">Links and Files that are opened by
this application</property>
+ <style>
+ <class name="section-subtitle"/>
+ </style>
+ </object>
+ </child>
</object>
</child>
<child>
- <object class="GtkLabel">
+ <object class="GtkListBox" id="handler_list">
<property name="visible">1</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">Links and Files that are opened by
this application</property>
+ <property name="selection-mode">none</property>
<style>
- <class name="section-subtitle"/>
+ <class name="view"/>
+ <class name="frame"/>
</style>
</object>
</child>
</object>
</child>
<child>
- <object class="GtkListBox" id="handler_list">
+ <object class="GtkBox" id="storage_section">
<property name="visible">1</property>
- <property name="selection-mode">none</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
<style>
- <class name="view"/>
- <class name="frame"/>
+ <class name="section"/>
</style>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkBox" id="cache_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">
+ <object class="GtkBox">
<property name="visible">1</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">Cache</property>
- <style>
- <class name="section-title"/>
- </style>
+ <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">Storage</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 much disk space this
application is occupying with app data and caches</property>
+ <style>
+ <class name="section-subtitle"/>
+ </style>
+ </object>
+ </child>
</object>
</child>
<child>
- <object class="GtkLabel">
+ <object class="GtkListBox" id="storage_list">
<property name="visible">1</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">Maintained by the application and
cannot be altered</property>
+ <property name="selection-mode">none</property>
+ <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>
+ </child>
<style>
- <class name="section-subtitle"/>
+ <class name="view"/>
+ <class name="frame"/>
</style>
</object>
</child>
</object>
</child>
- <child>
- <object class="GtkListBox" id="cache_list">
- <property name="visible">1</property>
- <property name="selection-mode">none</property>
- <child>
- <object class="CcActionRow" id="cache">
- <signal name="activated" handler="clear_cache_cb"/>
- </object>
- </child>
- <style>
- <class name="view"/>
- <class name="frame"/>
- </style>
- </object>
- </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">1</property>
+ <property name="hexpand">1</property>
</object>
</child>
</object>
- </child>
- <child>
- <object class="GtkBox">
- <property name="visible">1</property>
- <property name="hexpand">1</property>
- </object>
+ <packing>
+ <property name="name">settings</property>
+ </packing>
</child>
</object>
</child>
diff --git a/panels/applications/cc-info-row.c b/panels/applications/cc-info-row.c
new file mode 100644
index 000000000..2f11e180c
--- /dev/null
+++ b/panels/applications/cc-info-row.c
@@ -0,0 +1,145 @@
+/* cc-info-row.c
+ *
+ * Copyright 2018 Matthias Clasen <matthias clasen 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 3 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include <config.h>
+#include <glib/gi18n.h>
+
+#include "cc-info-row.h"
+#include "cc-applications-resources.h"
+
+enum {
+ PROP_ZERO,
+ PROP_TITLE,
+ PROP_SUBTITLE,
+ PROP_INFO
+};
+
+struct _CcInfoRow
+{
+ GtkListBoxRow parent;
+
+ GtkWidget *title;
+ GtkWidget *subtitle;
+ GtkWidget *info;
+};
+
+G_DEFINE_TYPE (CcInfoRow, cc_info_row, GTK_TYPE_LIST_BOX_ROW)
+
+static void
+cc_info_row_finalize (GObject *object)
+{
+ //CcInfoRow *row = CC_INFO_ROW (object);
+
+ G_OBJECT_CLASS (cc_info_row_parent_class)->finalize (object);
+}
+
+static void
+cc_info_row_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ CcInfoRow *row = CC_INFO_ROW (object);
+
+ switch (prop_id)
+ {
+ case PROP_TITLE:
+ g_value_set_string (value, gtk_label_get_label (GTK_LABEL (row->title)));
+ break;
+ case PROP_SUBTITLE:
+ g_value_set_string (value, gtk_label_get_label (GTK_LABEL (row->subtitle)));
+ break;
+ case PROP_INFO:
+ g_value_set_string (value, gtk_label_get_label (GTK_LABEL (row->info)));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+cc_info_row_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ CcInfoRow *row = CC_INFO_ROW (object);
+
+ switch (prop_id)
+ {
+ case PROP_TITLE:
+ gtk_label_set_label (GTK_LABEL (row->title), g_value_get_string (value));
+ break;
+ case PROP_SUBTITLE:
+ gtk_label_set_label (GTK_LABEL (row->subtitle), g_value_get_string (value));
+ break;
+ case PROP_INFO:
+ gtk_label_set_label (GTK_LABEL (row->info), g_value_get_string (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+cc_info_row_class_init (CcInfoRowClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->finalize = cc_info_row_finalize;
+ object_class->get_property = cc_info_row_get_property;
+ object_class->set_property = cc_info_row_set_property;
+
+ gtk_widget_class_set_template_from_resource (widget_class,
"/org/gnome/control-center/applications/cc-info-row.ui");
+
+ g_object_class_install_property (object_class,
+ PROP_TITLE,
+ g_param_spec_string ("title", "title", "title",
+ NULL, G_PARAM_READWRITE));
+
+ g_object_class_install_property (object_class,
+ PROP_SUBTITLE,
+ g_param_spec_string ("subtitle", "subtitle", "subtitle",
+ NULL, G_PARAM_READWRITE));
+
+ g_object_class_install_property (object_class,
+ PROP_INFO,
+ g_param_spec_string ("info", "info", "info",
+ NULL, G_PARAM_READWRITE));
+
+ gtk_widget_class_bind_template_child (widget_class, CcInfoRow, title);
+ gtk_widget_class_bind_template_child (widget_class, CcInfoRow, subtitle);
+ gtk_widget_class_bind_template_child (widget_class, CcInfoRow, info);
+}
+
+static void
+cc_info_row_init (CcInfoRow *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+CcInfoRow *
+cc_info_row_new (void)
+{
+ return CC_INFO_ROW (g_object_new (CC_TYPE_INFO_ROW, NULL));
+}
diff --git a/panels/applications/cc-info-row.h b/panels/applications/cc-info-row.h
new file mode 100644
index 000000000..583de2e7f
--- /dev/null
+++ b/panels/applications/cc-info-row.h
@@ -0,0 +1,32 @@
+/* cc-info-row.h
+ *
+ * Copyright 2018 Matthias Clasen <matthias clasen 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 3 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_INFO_ROW (cc_info_row_get_type())
+G_DECLARE_FINAL_TYPE (CcInfoRow, cc_info_row, CC, INFO_ROW, GtkListBoxRow)
+
+CcInfoRow *cc_info_row_new (void);
+
+G_END_DECLS
diff --git a/panels/applications/cc-info-row.ui b/panels/applications/cc-info-row.ui
new file mode 100644
index 000000000..cb4b1c53e
--- /dev/null
+++ b/panels/applications/cc-info-row.ui
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="CcInfoRow" parent="GtkListBoxRow">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="activatable">False</property>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="border-width">12</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="spacing">4</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel" id="title">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="hexpand">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="subtitle">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="hexpand">True</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="info">
+ <property name="visible">True</property>
+ <property name="valign">center</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/applications/cc-toggle-row.c b/panels/applications/cc-toggle-row.c
index 7a4d9c53c..9060ad89a 100644
--- a/panels/applications/cc-toggle-row.c
+++ b/panels/applications/cc-toggle-row.c
@@ -26,16 +26,21 @@
enum {
PROP_ZERO,
- PROP_NAME
+ PROP_TITLE,
+ PROP_ON_SUBTITLE,
+ PROP_OFF_SUBTITLE,
+ PROP_ALLOWED
};
-static int changed_signal;
-
struct _CcToggleRow
{
GtkListBoxRow parent;
- GtkWidget *label;
+ char *on_subtitle;
+ char *off_subtitle;
+
+ GtkWidget *title;
+ GtkWidget *subtitle;
GtkWidget *toggle;
};
@@ -44,7 +49,10 @@ G_DEFINE_TYPE (CcToggleRow, cc_toggle_row, GTK_TYPE_LIST_BOX_ROW)
static void
cc_toggle_row_finalize (GObject *object)
{
- //CcToggleRow *row = CC_TOGGLE_ROW (object);
+ CcToggleRow *row = CC_TOGGLE_ROW (object);
+
+ g_free (row->on_subtitle);
+ g_free (row->off_subtitle);
G_OBJECT_CLASS (cc_toggle_row_parent_class)->finalize (object);
}
@@ -59,8 +67,17 @@ cc_toggle_row_get_property (GObject *object,
switch (prop_id)
{
- case PROP_NAME:
- g_value_set_string (value, gtk_label_get_label (GTK_LABEL (row->label)));
+ case PROP_TITLE:
+ g_value_set_string (value, gtk_label_get_label (GTK_LABEL (row->title)));
+ break;
+ case PROP_ON_SUBTITLE:
+ g_value_set_string (value, row->on_subtitle);
+ break;
+ case PROP_OFF_SUBTITLE:
+ g_value_set_string (value, row->off_subtitle);
+ break;
+ case PROP_ALLOWED:
+ g_value_set_boolean (value, cc_toggle_row_get_allowed (row));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -78,8 +95,17 @@ cc_toggle_row_set_property (GObject *object,
switch (prop_id)
{
- case PROP_NAME:
- gtk_label_set_label (GTK_LABEL (row->label), g_value_get_string (value));
+ case PROP_TITLE:
+ gtk_label_set_label (GTK_LABEL (row->title), g_value_get_string (value));
+ break;
+ case PROP_ON_SUBTITLE:
+ cc_toggle_row_set_on_subtitle (row, g_value_get_string (value));
+ break;
+ case PROP_OFF_SUBTITLE:
+ cc_toggle_row_set_off_subtitle (row, g_value_get_string (value));
+ break;
+ case PROP_ALLOWED:
+ cc_toggle_row_set_allowed (row, g_value_get_boolean (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -100,28 +126,44 @@ cc_toggle_row_class_init (CcToggleRowClass *klass)
gtk_widget_class_set_template_from_resource (widget_class,
"/org/gnome/control-center/applications/cc-toggle-row.ui");
g_object_class_install_property (object_class,
- PROP_NAME,
- g_param_spec_string ("name", "name", "name",
+ PROP_TITLE,
+ g_param_spec_string ("title", "title", "title",
+ NULL, G_PARAM_READWRITE));
+
+ g_object_class_install_property (object_class,
+ PROP_ON_SUBTITLE,
+ g_param_spec_string ("on-subtitle", "on-subtitle", "on-subtitle",
+ NULL, G_PARAM_READWRITE));
+
+ g_object_class_install_property (object_class,
+ PROP_OFF_SUBTITLE,
+ g_param_spec_string ("off-subtitle", "off-subtitle", "off-subtitle",
NULL, G_PARAM_READWRITE));
- changed_signal = g_signal_new ("changed",
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_FIRST,
- 0,
- NULL, NULL,
- NULL,
- G_TYPE_NONE, 0);
+ g_object_class_install_property (object_class,
+ PROP_ALLOWED,
+ g_param_spec_boolean ("allowed", "allowed", "allowed",
+ FALSE, G_PARAM_READWRITE));
- gtk_widget_class_bind_template_child (widget_class, CcToggleRow, label);
+ gtk_widget_class_bind_template_child (widget_class, CcToggleRow, title);
+ gtk_widget_class_bind_template_child (widget_class, CcToggleRow, subtitle);
gtk_widget_class_bind_template_child (widget_class, CcToggleRow, toggle);
}
static void
-changed_cb (GtkSwitch *toggle,
- GParamSpec *pspec,
- CcToggleRow *row)
+update_subtitle (CcToggleRow *row)
+{
+ if (gtk_switch_get_active (GTK_SWITCH (row->toggle)))
+ gtk_label_set_label (GTK_LABEL (row->subtitle), row->on_subtitle);
+ else
+ gtk_label_set_label (GTK_LABEL (row->subtitle), row->off_subtitle);
+}
+
+static void
+changed_cb (GtkSwitch *toggle, GParamSpec *pspec, CcToggleRow *row)
{
- g_signal_emit (row, changed_signal, 0);
+ update_subtitle (row);
+ g_object_notify (G_OBJECT (row), "allowed");
}
static void
@@ -129,31 +171,44 @@ cc_toggle_row_init (CcToggleRow *self)
{
gtk_widget_init_template (GTK_WIDGET (self));
- gtk_list_box_row_set_activatable (GTK_LIST_BOX_ROW (self), FALSE);
g_signal_connect (self->toggle, "notify::active", G_CALLBACK (changed_cb), self);
}
CcToggleRow *
-cc_toggle_row_new (const char *name)
+cc_toggle_row_new (void)
{
- CcToggleRow *row;
-
- row = g_object_new (CC_TYPE_TOGGLE_ROW, NULL);
-
- gtk_label_set_label (GTK_LABEL (row->label), name);
-
- return row;
+ return CC_TOGGLE_ROW (g_object_new (CC_TYPE_TOGGLE_ROW, NULL));
}
void
-cc_toggle_row_set_allowed (CcToggleRow *row,
+cc_toggle_row_set_allowed (CcToggleRow *self,
gboolean allowed)
{
- gtk_switch_set_active (GTK_SWITCH (row->toggle), allowed);
+ gtk_switch_set_active (GTK_SWITCH (self->toggle), allowed);
}
gboolean
-cc_toggle_row_get_allowed (CcToggleRow *row)
+cc_toggle_row_get_allowed (CcToggleRow *self)
+{
+ return gtk_switch_get_active (GTK_SWITCH (self->toggle));
+}
+
+void
+cc_toggle_row_set_on_subtitle (CcToggleRow *self,
+ const char *subtitle)
+{
+ g_free (self->on_subtitle);
+ self->on_subtitle = g_strdup (subtitle);
+ update_subtitle (self);
+ g_object_notify (G_OBJECT (self), "on-subtitle");
+}
+
+void
+cc_toggle_row_set_off_subtitle (CcToggleRow *self,
+ const char *subtitle)
{
- return gtk_switch_get_active (GTK_SWITCH (row->toggle));
+ g_free (self->off_subtitle);
+ self->off_subtitle = g_strdup (subtitle);
+ update_subtitle (self);
+ g_object_notify (G_OBJECT (self), "off-subtitle");
}
diff --git a/panels/applications/cc-toggle-row.h b/panels/applications/cc-toggle-row.h
index 44464db7b..316e3131a 100644
--- a/panels/applications/cc-toggle-row.h
+++ b/panels/applications/cc-toggle-row.h
@@ -27,9 +27,13 @@ G_BEGIN_DECLS
#define CC_TYPE_TOGGLE_ROW (cc_toggle_row_get_type())
G_DECLARE_FINAL_TYPE (CcToggleRow, cc_toggle_row, CC, TOGGLE_ROW, GtkListBoxRow)
-CcToggleRow *cc_toggle_row_new (const char *name);
+CcToggleRow *cc_toggle_row_new (void);
void cc_toggle_row_set_allowed (CcToggleRow *row,
gboolean allowed);
gboolean cc_toggle_row_get_allowed (CcToggleRow *row);
+void cc_toggle_row_set_on_subtitle (CcToggleRow *row,
+ const char *subtitle);
+void cc_toggle_row_set_off_subtitle (CcToggleRow *row,
+ const char *subtitle);
G_END_DECLS
diff --git a/panels/applications/cc-toggle-row.ui b/panels/applications/cc-toggle-row.ui
index 33dfe79e5..9de4a8ade 100644
--- a/panels/applications/cc-toggle-row.ui
+++ b/panels/applications/cc-toggle-row.ui
@@ -3,21 +3,40 @@
<template class="CcToggleRow" parent="GtkListBoxRow">
<property name="visible">True</property>
<property name="can_focus">True</property>
+ <property name="activatable">False</property>
<child>
- <object class="GtkBox" id="box">
+ <object class="GtkBox">
<property name="visible">True</property>
<property name="border-width">12</property>
<property name="spacing">12</property>
<child>
- <object class="GtkLabel" id="label">
+ <object class="GtkBox">
<property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="hexpand">True</property>
+ <property name="spacing">4</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel" id="title">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="hexpand">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="subtitle">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="hexpand">True</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
</object>
</child>
<child>
<object class="GtkSwitch" id="toggle">
<property name="visible">True</property>
+ <property name="valign">center</property>
</object>
</child>
</object>
diff --git a/panels/applications/meson.build b/panels/applications/meson.build
index 20c6eed39..e8f11eb4b 100644
--- a/panels/applications/meson.build
+++ b/panels/applications/meson.build
@@ -20,6 +20,7 @@ i18n.merge_file(
sources = files('cc-applications-panel.c',
'cc-applications-row.c',
'cc-toggle-row.c',
+ 'cc-info-row.c',
'cc-action-row.c',
'utils.c'
)
diff --git a/panels/applications/utils.c b/panels/applications/utils.c
index b2bc10cc6..35a37791f 100644
--- a/panels/applications/utils.c
+++ b/panels/applications/utils.c
@@ -66,3 +66,29 @@ container_remove_all (GtkContainer *container)
g_list_free (children);
}
+char *
+get_flatpak_app_size (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;
+
+ return g_strstrip (out);
+}
+
+void
+uninstall_flatpak_app (const char *app_id)
+{
+ const char *argv[] = { "flatpak", "uninstall", "--assumeyes", "appid", NULL };
+ g_autofree char *out = 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);
+}
diff --git a/panels/applications/utils.h b/panels/applications/utils.h
index c3e9e5425..c6dbd97eb 100644
--- a/panels/applications/utils.h
+++ b/panels/applications/utils.h
@@ -28,5 +28,7 @@ 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);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]