diff --git a/gtk/gtkplacesview.c b/gtk/gtkplacesview.c index 011334b803..958887732f 100644 --- a/gtk/gtkplacesview.c +++ b/gtk/gtkplacesview.c @@ -73,6 +73,7 @@ struct _GtkPlacesViewPrivate GtkWidget *network_placeholder_label; GtkSizeGroup *path_size_group; + GtkSizeGroup *space_size_group; GtkEntryCompletion *address_entry_completion; GtkListStore *completion_store; @@ -405,6 +406,7 @@ gtk_places_view_finalize (GObject *object) g_clear_object (&priv->cancellable); g_clear_object (&priv->networks_fetching_cancellable); g_clear_object (&priv->path_size_group); + g_clear_object (&priv->space_size_group); G_OBJECT_CLASS (gtk_places_view_parent_class)->finalize (object); } @@ -674,6 +676,7 @@ insert_row (GtkPlacesView *view, row); gtk_places_view_row_set_path_size_group (GTK_PLACES_VIEW_ROW (row), priv->path_size_group); + gtk_places_view_row_set_space_size_group (GTK_PLACES_VIEW_ROW (row), priv->space_size_group); gtk_container_add (GTK_CONTAINER (priv->listbox), row); } @@ -2258,6 +2261,7 @@ gtk_places_view_init (GtkPlacesView *self) priv->volume_monitor = g_volume_monitor_get (); priv->open_flags = GTK_PLACES_OPEN_NORMAL; priv->path_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); + priv->space_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); gtk_widget_init_template (GTK_WIDGET (self)); } diff --git a/gtk/gtkplacesviewrow.c b/gtk/gtkplacesviewrow.c index f6d5658f51..d797c18e8a 100644 --- a/gtk/gtkplacesviewrow.c +++ b/gtk/gtkplacesviewrow.c @@ -42,6 +42,7 @@ struct _GtkPlacesViewRow { GtkListBoxRow parent_instance; + GtkLabel *available_space_label; GtkSpinner *busy_spinner; GtkButton *eject_button; GtkImage *eject_icon; @@ -54,6 +55,8 @@ struct _GtkPlacesViewRow GMount *mount; GFile *file; + GCancellable *cancellable; + gint is_network : 1; }; @@ -73,14 +76,124 @@ enum { static GParamSpec *properties [LAST_PROP]; +static void +measure_available_space_finished (GObject *object, + GAsyncResult *res, + gpointer user_data) +{ + GtkPlacesViewRow *row = user_data; + GFileInfo *info; + GError *error; + guint64 free_space; + guint64 total_space; + gchar *formatted_free_size; + gchar *formatted_total_size; + gchar *label; + + error = NULL; + + info = g_file_query_filesystem_info_finish (G_FILE (object), + res, + &error); + + if (error) + { + if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) && + !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_MOUNTED)) + { + g_warning ("Failed to measure available space: %s", error->message); + } + + g_clear_error (&error); + goto out; + } + + if (!g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_FILESYSTEM_FREE) || + !g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_FILESYSTEM_SIZE)) + { + g_object_unref (info); + goto out; + } + + free_space = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_FILESYSTEM_FREE); + total_space = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_FILESYSTEM_SIZE); + + formatted_free_size = g_format_size (free_space); + formatted_total_size = g_format_size (total_space); + /* Translators: respectively, free and total space of the drive */ + label = g_strdup_printf (_("%s / %s available"), formatted_free_size, formatted_total_size); + + gtk_label_set_label (row->available_space_label, label); + + g_object_unref (info); + g_free (formatted_total_size); + g_free (formatted_free_size); + g_free (label); +out: + g_object_unref (object); +} + +static void +measure_available_space (GtkPlacesViewRow *row) +{ + gboolean should_measure; + + should_measure = (!row->is_network && (row->volume || row->mount || row->file)); + + gtk_label_set_label (row->available_space_label, ""); + gtk_widget_set_visible (GTK_WIDGET (row->available_space_label), should_measure); + + if (should_measure) + { + GFile *file = NULL; + + if (row->file) + { + file = g_object_ref (row->file); + } + else if (row->mount) + { + file = g_mount_get_root (row->mount); + } + else if (row->volume) + { + GMount *mount; + + mount = g_volume_get_mount (row->volume); + + if (mount) + file = g_mount_get_root (row->mount); + + g_clear_object (&mount); + } + + if (file) + { + g_cancellable_cancel (row->cancellable); + g_clear_object (&row->cancellable); + row->cancellable = g_cancellable_new (); + + g_file_query_filesystem_info_async (file, + G_FILE_ATTRIBUTE_FILESYSTEM_FREE "," G_FILE_ATTRIBUTE_FILESYSTEM_SIZE, + G_PRIORITY_DEFAULT, + row->cancellable, + measure_available_space_finished, + row); + } + } +} + static void gtk_places_view_row_finalize (GObject *object) { GtkPlacesViewRow *self = GTK_PLACES_VIEW_ROW (object); + g_cancellable_cancel (self->cancellable); + g_clear_object (&self->volume); g_clear_object (&self->mount); g_clear_object (&self->file); + g_clear_object (&self->cancellable); G_OBJECT_CLASS (gtk_places_view_row_parent_class)->finalize (object); } @@ -172,14 +285,17 @@ gtk_places_view_row_set_property (GObject *object, * size but it stays hidden when needed. */ gtk_widget_set_child_visible (GTK_WIDGET (self->eject_button), self->mount != NULL); + measure_available_space (self); break; case PROP_FILE: g_set_object (&self->file, g_value_get_object (value)); + measure_available_space (self); break; case PROP_IS_NETWORK: gtk_places_view_row_set_is_network (self, g_value_get_boolean (value)); + measure_available_space (self); break; default: @@ -250,6 +366,7 @@ gtk_places_view_row_class_init (GtkPlacesViewRowClass *klass) gtk_widget_class_set_template_from_resource (widget_class, "/org/gtk/libgtk/ui/gtkplacesviewrow.ui"); + gtk_widget_class_bind_template_child (widget_class, GtkPlacesViewRow, available_space_label); gtk_widget_class_bind_template_child (widget_class, GtkPlacesViewRow, busy_spinner); gtk_widget_class_bind_template_child (widget_class, GtkPlacesViewRow, eject_button); gtk_widget_class_bind_template_child (widget_class, GtkPlacesViewRow, eject_icon); @@ -352,3 +469,11 @@ gtk_places_view_row_set_path_size_group (GtkPlacesViewRow *row, if (group) gtk_size_group_add_widget (group, GTK_WIDGET (row->path_label)); } + +void +gtk_places_view_row_set_space_size_group (GtkPlacesViewRow *row, + GtkSizeGroup *group) +{ + if (group) + gtk_size_group_add_widget (group, GTK_WIDGET (row->available_space_label)); +} diff --git a/gtk/gtkplacesviewrowprivate.h b/gtk/gtkplacesviewrowprivate.h index 5389676d12..0233188977 100644 --- a/gtk/gtkplacesviewrowprivate.h +++ b/gtk/gtkplacesviewrowprivate.h @@ -54,9 +54,17 @@ gboolean gtk_places_view_row_get_is_network (GtkPlacesViewR void gtk_places_view_row_set_is_network (GtkPlacesViewRow *row, gboolean is_network); +gboolean gtk_places_view_row_get_show_disk_usage (GtkPlacesViewRow *row); + +void gtk_places_view_row_set_show_disk_usage (GtkPlacesViewRow *row, + gboolean show_disk_usage); + void gtk_places_view_row_set_path_size_group (GtkPlacesViewRow *row, GtkSizeGroup *group); +void gtk_places_view_row_set_space_size_group (GtkPlacesViewRow *row, + GtkSizeGroup *group); + G_END_DECLS #endif /* GTK_PLACES_VIEW_ROW_H */ diff --git a/gtk/ui/gtkplacesviewrow.ui b/gtk/ui/gtkplacesviewrow.ui index 8c888f0be8..89c840416d 100644 --- a/gtk/ui/gtkplacesviewrow.ui +++ b/gtk/ui/gtkplacesviewrow.ui @@ -27,11 +27,24 @@ 1 1 0 + end 1 + + + False + 1 + + + + 2 + + 1 @@ -44,7 +57,7 @@ - 2 + 3 @@ -66,7 +79,7 @@ - 3 + 4 @@ -74,7 +87,7 @@ 1 - 4 + 5