[gnome-control-center/wip/applications] more work in progress
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-control-center/wip/applications] more work in progress
- Date: Sun, 9 Dec 2018 06:38:06 +0000 (UTC)
commit 0d7d2ee8211df09107c65d5bd46b65d667549ccf
Author: Matthias Clasen <mclasen redhat com>
Date: Sun Dec 9 01:16:51 2018 -0500
more work in progress
panels/applications/cc-applications-panel.c | 176 +++++++++++++++++++--------
panels/applications/cc-applications-panel.ui | 102 +++++++++++++---
panels/applications/utils.c | 81 +++++++++---
panels/applications/utils.h | 4 +-
4 files changed, 278 insertions(+), 85 deletions(-)
---
diff --git a/panels/applications/cc-applications-panel.c b/panels/applications/cc-applications-panel.c
index 5aec31877..311077eb2 100644
--- a/panels/applications/cc-applications-panel.c
+++ b/panels/applications/cc-applications-panel.c
@@ -36,14 +36,8 @@
/* Todo
* - search
- * - undo for mime type removal
- * - reset per section ?
- * - handle cache async
- * - notification visibility
- * - empty state
*
* Missing in flatpak:
- * - make portal write notification permissions
* - background
* - usb devices
*
@@ -63,6 +57,7 @@ struct _CcApplicationsPanel
GtkWidget *header_button;
GtkWidget *title_label;
GAppInfoMonitor *monitor;
+ gulong monitor_id;
GCancellable *cancellable;
@@ -100,6 +95,7 @@ struct _CcApplicationsPanel
GtkWidget *device_list;
GtkWidget *handler_section;
+ GtkWidget *handler_reset;
GtkWidget *handler_list;
GtkWidget *hypertext;
GtkWidget *text;
@@ -121,6 +117,10 @@ struct _CcApplicationsPanel
GtkWidget *cache;
GtkWidget *total;
GtkWidget *clear_cache_button;
+
+ guint64 app_size;
+ guint64 cache_size;
+ guint64 data_size;
};
G_DEFINE_TYPE (CcApplicationsPanel, cc_applications_panel, CC_TYPE_PANEL)
@@ -412,14 +412,6 @@ get_app_dir (const char *app_id,
return g_file_get_child (appdir, subdir);
}
-static guint64
-calculate_dir_size (const char *app_id,
- const char *subdir)
-{
- g_autoptr(GFile) cachedir = get_app_dir (app_id, subdir);
- return file_size_recursively (cachedir);
-}
-
static void
privacy_link_cb (CcApplicationsPanel *self)
{
@@ -430,36 +422,82 @@ privacy_link_cb (CcApplicationsPanel *self)
g_warning ("Failed to switch to privacy panel: %s", error->message);
}
-static guint64
-update_app_row (CcInfoRow *row,
- const char *app_id)
+static void
+update_total_size (CcApplicationsPanel *self)
+{
+ guint64 total;
+ g_autofree char *formatted_size = NULL;
+
+ total = self->app_size + self->data_size + self->cache_size;
+ formatted_size = g_format_size (total);
+ g_object_set (self->total, "info", formatted_size, NULL);
+ g_object_set (self->storage, "info", formatted_size, NULL);
+}
+
+static void
+set_cache_size (GObject *source,
+ GAsyncResult *res,
+ gpointer data)
{
- guint64 size;
+ CcApplicationsPanel *self = data;
+ guint64 *size;
g_autofree char *formatted_size = NULL;
- size = get_flatpak_app_size (app_id);
- formatted_size = g_format_size (size);
- g_object_set (row, "info", formatted_size, NULL);
+ size = g_object_get_data (G_OBJECT (res), "size");
+ self->cache_size = *size;
+
+ formatted_size = g_format_size (self->cache_size);
+ g_object_set (self->cache, "info", formatted_size, NULL);
- return size;
+ gtk_widget_set_sensitive (self->clear_cache_button, self->cache_size > 0);
+
+ update_total_size (self);
}
-static guint64
-update_dir_row (CcInfoRow *row,
- const char *app_id,
- const char *subdir)
+static void
+update_cache_row (CcApplicationsPanel *self,
+ const char *app_id)
{
- guint64 size;
+ g_autoptr(GFile) dir = get_app_dir (app_id, "cache");
+ g_object_set (self->cache, "info", "...", NULL);
+ file_size_async (dir, set_cache_size, self);
+}
+
+static void
+set_data_size (GObject *source,
+ GAsyncResult *res,
+ gpointer data)
+{
+ CcApplicationsPanel *self = data;
+ guint64 *size;
g_autofree char *formatted_size = NULL;
- size = calculate_dir_size (app_id, subdir);
- formatted_size = g_format_size (size);
- g_object_set (row, "info", formatted_size, NULL);
+ size = g_object_get_data (G_OBJECT (res), "size");
+ self->data_size = *size;
- return size;
+ formatted_size = g_format_size (self->data_size);
+ g_object_set (self->data, "info", formatted_size, NULL);
+
+ update_total_size (self);
}
-static void update_flatpak_sizes (CcApplicationsPanel *self, const char *app_id);
+static void
+update_data_row (CcApplicationsPanel *self,
+ const char *app_id)
+{
+ g_autoptr(GFile) dir = get_app_dir (app_id, "data");
+ g_object_set (self->data, "info", "...", NULL);
+ file_size_async (dir, set_data_size, self);
+}
+
+static void
+cache_cleared (GObject *source,
+ GAsyncResult *res,
+ gpointer data)
+{
+ CcApplicationsPanel *self = data;
+ update_cache_row (self, self->current_app_id);
+}
static void
clear_cache_cb (CcApplicationsPanel *self)
@@ -470,8 +508,7 @@ clear_cache_cb (CcApplicationsPanel *self)
return;
dir = get_app_dir (self->current_app_id, "cache");
- file_remove_recursively (dir);
- update_flatpak_sizes (self, self->current_app_id);
+ file_remove_async (dir, cache_cleared, self);
}
static char *
@@ -1087,6 +1124,31 @@ app_info_recommended_for (GAppInfo *info,
return ret;
}
+static void
+handler_reset_cb (GtkButton *button, CcApplicationsPanel *self)
+{
+ GtkListBoxRow *selected;
+ GAppInfo *info;
+ const char **types;
+ int i;
+
+ selected = gtk_list_box_get_selected_row (GTK_LIST_BOX (self->sidebar_listbox));
+ info = cc_applications_row_get_info (CC_APPLICATIONS_ROW (selected));
+
+ types = g_app_info_get_supported_types (info);
+ if (types == NULL || types[0] == NULL)
+ return;
+
+ g_signal_handler_block (self->monitor, self->monitor_id);
+ for (i = 0; types[i]; i++)
+ {
+ char *ctype = g_content_type_from_mime_type (types[i]);
+ g_app_info_add_supports_type (info, ctype, NULL);
+ }
+ g_signal_handler_unblock (self->monitor, self->monitor_id);
+ g_signal_emit_by_name (self->monitor, "changed");
+}
+
static void
update_handler_sections (CcApplicationsPanel *self,
GAppInfo *info)
@@ -1116,6 +1178,7 @@ update_handler_sections (CcApplicationsPanel *self,
hash = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
+ gtk_widget_set_sensitive (self->handler_reset, FALSE);
for (i = 0; types[i]; i++)
{
char *ctype = g_content_type_from_mime_type (types[i]);
@@ -1126,6 +1189,7 @@ update_handler_sections (CcApplicationsPanel *self,
}
if (!app_info_recommended_for (info, ctype))
{
+ gtk_widget_set_sensitive (self->handler_reset, TRUE);
g_free (ctype);
continue;
}
@@ -1151,24 +1215,28 @@ storage_row_activated_cb (GtkListBox *list,
}
static void
-update_flatpak_sizes (CcApplicationsPanel *self,
- const char *app_id)
+update_app_row (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");
+ self->app_size = get_flatpak_app_size (app_id);
+ formatted_size = g_format_size (self->app_size);
+ g_object_set (self->app, "info", formatted_size, NULL);
+ update_total_size (self);
+}
- formatted_size = g_format_size (total);
- g_object_set (self->total, "info", formatted_size, NULL);
- g_object_set (self->storage, "info", formatted_size, NULL);
+static void
+update_flatpak_sizes (CcApplicationsPanel *self,
+ const char *app_id)
+{
+ gtk_widget_set_sensitive (self->clear_cache_button, FALSE);
- gtk_widget_set_sensitive (self->clear_cache_button, cache_size > 0);
+ self->app_size = self->data_size = self->cache_size = 0;
+
+ update_app_row (self, app_id);
+ update_cache_row (self, app_id);
+ update_data_row (self, app_id);
}
static void
@@ -1178,6 +1246,7 @@ update_usage_section (CcApplicationsPanel *self,
if (app_info_is_flatpak (info))
{
g_autofree char *app_id = get_app_id (info);
+ gtk_widget_show (self->usage_section);
update_flatpak_sizes (self, app_id);
}
else
@@ -1201,10 +1270,12 @@ update_panel (CcApplicationsPanel *self,
if (row == NULL)
{
gtk_label_set_label (GTK_LABEL (self->title_label), _("Applications"));
+ gtk_widget_hide (self->header_button);
gtk_stack_set_visible_child_name (GTK_STACK (self->stack), "empty");
return;
}
+ gtk_widget_show (self->header_button);
gtk_stack_set_visible_child_name (GTK_STACK (self->stack), "settings");
g_clear_pointer (&self->current_app_id, g_free);
@@ -1313,9 +1384,9 @@ open_software_cb (GtkButton *button,
const char *argv[] = { "gnome-software", "--details", "appid", NULL };
if (self->current_app_id == NULL)
- return;
-
- argv[2] = self->current_app_id;
+ argv[1] = NULL;
+ else
+ argv[2] = self->current_app_id;
g_spawn_async (NULL, (char **)argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, NULL);
}
@@ -1469,6 +1540,7 @@ cc_applications_panel_class_init (CcApplicationsPanelClass *klass)
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_reset);
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);
@@ -1492,6 +1564,8 @@ cc_applications_panel_class_init (CcApplicationsPanelClass *klass)
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);
+ gtk_widget_class_bind_template_callback (widget_class, open_software_cb);
+ gtk_widget_class_bind_template_callback (widget_class, handler_reset_cb);
}
static void
@@ -1523,7 +1597,7 @@ 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);
+ self->monitor_id = g_signal_connect (self->monitor, "changed", G_CALLBACK (apps_changed), self);
prepare_content (self);
diff --git a/panels/applications/cc-applications-panel.ui b/panels/applications/cc-applications-panel.ui
index b00846203..438bf4bde 100644
--- a/panels/applications/cc-applications-panel.ui
+++ b/panels/applications/cc-applications-panel.ui
@@ -13,6 +13,60 @@
<child>
<object class="GtkBox">
<property name="visible">1</property>
+ <property name="orientation">vertical</property>
+ <property name="valign">center</property>
+
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="valign">start</property>
+ <property name="pixel_size">80</property>
+ <property name="icon_name">org.gnome.Software-symbolic</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="margin_bottom">15</property>
+ <property name="label" translatable="yes">No applications</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ <attributes>
+ <attribute name="scale" value="1.2"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton">
+ <property name="label" translatable="yes">Install someā¦</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="halign">center</property>
+ <property name="relief">normal</property>
+ <signal name="clicked" handler="open_software_cb"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+
+
</object>
<packing>
<property name="name">empty</property>
@@ -275,28 +329,46 @@
<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 Handlers</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 Handlers</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="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>
+ </object>
+ </child>
</object>
+ <packing>
+ <property name="expand">1</property>
+ </packing>
</child>
<child>
- <object class="GtkLabel">
+ <object class="GtkButton" id="handler_reset">
<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">Types of files and links that this
application opens.</property>
- <style>
- <class name="section-subtitle"/>
- </style>
+ <property name="halign">end</property>
+ <property name="valign">center</property>
+ <property name="label" translatable="yes">Reset</property>
+ <signal name="clicked" handler="handler_reset_cb"/>
</object>
</child>
</object>
diff --git a/panels/applications/utils.c b/panels/applications/utils.c
index 5d46cdee4..a468963b6 100644
--- a/panels/applications/utils.c
+++ b/panels/applications/utils.c
@@ -18,39 +18,86 @@
* SPDX-License-Identifier: GPL-3.0-or-later
*/
+#ifndef _XOPEN_SOURCE
+#define _XOPEN_SOURCE 600
+#endif
+
#include <config.h>
#include <glib/gi18n.h>
#include <flatpak/flatpak.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <ftw.h>
#include "utils.h"
+static int
+ftw_remove_cb (const char *path, const struct stat *sb, int typeflags, struct FTW *ftwbuf)
+{
+ remove (path);
+ return 0;
+}
+
+static void
+file_remove_thread_func (GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ GFile *file = source_object;
+ g_autofree char *path = g_file_get_path (file);
+
+ nftw (path, ftw_remove_cb, 20, FTW_DEPTH);
+}
+
void
-file_remove_recursively (GFile *file)
+file_remove_async (GFile *file,
+ GAsyncReadyCallback callback,
+ gpointer data)
{
- const char *argv[] = { "rm", "-rf", "path", NULL };
+ g_autoptr(GTask) task = g_task_new (file, NULL, callback, data);
+ g_task_run_in_thread (task, file_remove_thread_func);
+}
- /* FIXME: async, in process */
- argv[2] = g_file_peek_path (file);
+static GPrivate size_key = G_PRIVATE_INIT (g_free);
- g_spawn_sync (NULL, (char **)argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, NULL, NULL, NULL);
+static int
+ftw_size_cb (const char *path, const struct stat *sb, int typeflags, struct FTW *ftwbuf)
+{
+ guint64 *size = (guint64*)g_private_get (&size_key);
+ if (typeflags == FTW_F)
+ *size += sb->st_size;
+ return 0;
}
-guint64
-file_size_recursively (GFile *file)
+static void
+file_size_thread_func (GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
{
- const char *argv[] = { "du", "-s", "path", NULL };
- g_autofree char *out = NULL;
- guint64 size = 0;
-
- /* FIXME: async, in process */
- argv[2] = g_file_peek_path (file);
+ GFile *file = source_object;
+ g_autofree char *path = g_file_get_path (file);
+ guint64 *total;
+
+ g_private_replace (&size_key, g_new0 (guint64, 1));
- if (!g_spawn_sync (NULL, (char **)argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, &out, NULL, NULL, NULL))
- return 0;
+ nftw (path, ftw_size_cb, 20, FTW_DEPTH);
- size = strtoul (out, NULL, 10);
+ total = g_new0 (guint64, 1);
+ *total = *(guint64*)g_private_get (&size_key);
- return size;
+ g_object_set_data_full (G_OBJECT (task), "size", total, g_free);
+}
+
+void
+file_size_async (GFile *file,
+ GAsyncReadyCallback callback,
+ gpointer data)
+{
+ g_autoptr(GTask) task = g_task_new (file, NULL, callback, data);
+ g_task_run_in_thread (task, file_size_thread_func);
}
void
diff --git a/panels/applications/utils.h b/panels/applications/utils.h
index e2acc5ec3..9e2060b34 100644
--- a/panels/applications/utils.h
+++ b/panels/applications/utils.h
@@ -26,8 +26,8 @@
G_BEGIN_DECLS
-void file_remove_recursively (GFile *file);
-guint64 file_size_recursively (GFile *file);
+void file_remove_async (GFile *file, GAsyncReadyCallback callback, gpointer data);
+void file_size_async (GFile *file, GAsyncReadyCallback callback, gpointer data);
void container_remove_all (GtkContainer *container);
FlatpakInstalledRef *find_flatpak_ref (const char *app_id);
guint64 get_flatpak_app_size (const char *app_id);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]