[gtk/gbsneto/filechooser-column-view: 49/105] filechooserwidget: Move file icon to column view
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/gbsneto/filechooser-column-view: 49/105] filechooserwidget: Move file icon to column view
- Date: Wed, 12 Oct 2022 20:42:35 +0000 (UTC)
commit 5c837137c0055ab907531503c24ca1847c5a23fc
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date: Sat Oct 8 08:15:09 2022 -0300
filechooserwidget: Move file icon to column view
This commit moves the icon loading code into a new private
widget called GtkFileThumbnail, which is bound to the GFileInfo
of the model, and asynchronously loads the file icon from that.
gtk/gtkfilechooserwidget.c | 145 +----------------------
gtk/gtkfilethumbnail.c | 261 +++++++++++++++++++++++++++++++++++++++++
gtk/gtkfilethumbnail.h | 46 ++++++++
gtk/meson.build | 1 +
gtk/ui/gtkfilechooserwidget.ui | 14 ++-
5 files changed, 320 insertions(+), 147 deletions(-)
---
diff --git a/gtk/gtkfilechooserwidget.c b/gtk/gtkfilechooserwidget.c
index 4edc6c87ae..d2908fa186 100644
--- a/gtk/gtkfilechooserwidget.c
+++ b/gtk/gtkfilechooserwidget.c
@@ -38,6 +38,7 @@
#include "gtkfilechooserutils.h"
#include "gtkfilechooser.h"
#include "gtkfilesystemmodel.h"
+#include "gtkfilethumbnail.h"
#include "gtkgrid.h"
#include "gtkicontheme.h"
#include "gtklabel.h"
@@ -271,7 +272,6 @@ struct _GtkFileChooserWidget
GFile *renamed_file;
GtkTreeViewColumn *list_name_column;
- GtkCellRenderer *list_pixbuf_renderer;
GtkTreeViewColumn *list_time_column;
GtkCellRenderer *list_date_renderer;
GtkCellRenderer *list_time_renderer;
@@ -359,7 +359,6 @@ enum {
MODEL_COL_NAME_COLLATED,
MODEL_COL_IS_FOLDER,
MODEL_COL_IS_SENSITIVE,
- MODEL_COL_ICON,
MODEL_COL_SIZE_TEXT,
MODEL_COL_DATE_TEXT,
MODEL_COL_TIME_TEXT,
@@ -379,7 +378,6 @@ enum {
G_TYPE_STRING, /* MODEL_COL_NAME_COLLATED */ \
G_TYPE_BOOLEAN, /* MODEL_COL_IS_FOLDER */ \
G_TYPE_BOOLEAN, /* MODEL_COL_IS_SENSITIVE */ \
- G_TYPE_ICON, /* MODEL_COL_ICON */ \
G_TYPE_STRING, /* MODEL_COL_SIZE_TEXT */ \
G_TYPE_STRING, /* MODEL_COL_DATE_TEXT */ \
G_TYPE_STRING, /* MODEL_COL_TIME_TEXT */ \
@@ -2143,17 +2141,6 @@ file_list_query_tooltip_cb (GtkWidget *widget,
return TRUE;
}
-static void
-set_icon_cell_renderer_fixed_size (GtkFileChooserWidget *impl)
-{
- int xpad, ypad;
-
- gtk_cell_renderer_get_padding (impl->list_pixbuf_renderer, &xpad, &ypad);
- gtk_cell_renderer_set_fixed_size (impl->list_pixbuf_renderer,
- xpad * 2 + ICON_SIZE,
- ypad * 2 + ICON_SIZE);
-}
-
static GtkWidget *
get_accept_action_widget (GtkDialog *dialog,
gboolean sensitive_only)
@@ -3210,10 +3197,6 @@ gtk_file_chooser_widget_unroot (GtkWidget *widget)
static void
change_icon_theme (GtkFileChooserWidget *impl)
{
- /* the first cell in the first column is the icon column, and we have a fixed size there */
- set_icon_cell_renderer_fixed_size (impl);
-
- clear_model_cache (impl, MODEL_COL_ICON);
gtk_widget_queue_resize (impl->browse_files_tree_view);
}
@@ -4282,53 +4265,6 @@ my_g_format_time_for_display (GtkFileChooserWidget *impl,
return date_str;
}
-static void
-copy_attribute (GFileInfo *to,
- GFileInfo *from,
- const char *attribute)
-{
- GFileAttributeType type;
- gpointer value;
-
- if (g_file_info_get_attribute_data (from, attribute, &type, &value, NULL))
- g_file_info_set_attribute (to, attribute, type, value);
-}
-
-static void
-file_system_model_got_thumbnail (GObject *object,
- GAsyncResult *res,
- gpointer data)
-{
- GtkFileSystemModel *model = data; /* might be unreffed if operation was cancelled */
- GFile *file = G_FILE (object);
- GFileInfo *queried, *info;
- GtkTreeIter iter;
-
- queried = g_file_query_info_finish (file, res, NULL);
- if (queried == NULL)
- return;
-
- /* now we know model is valid */
-
- /* file was deleted */
- if (!_gtk_file_system_model_get_iter_for_file (model, &iter, file))
- {
- g_object_unref (queried);
- return;
- }
-
- info = g_file_info_dup (_gtk_file_system_model_get_info (model, &iter));
-
- copy_attribute (info, queried, G_FILE_ATTRIBUTE_THUMBNAIL_PATH);
- copy_attribute (info, queried, G_FILE_ATTRIBUTE_THUMBNAILING_FAILED);
- copy_attribute (info, queried, G_FILE_ATTRIBUTE_STANDARD_ICON);
-
- _gtk_file_system_model_update_file (model, file, info);
-
- g_object_unref (info);
- g_object_unref (queried);
-}
-
/* Copied from src/nautilus_file.c:get_description() */
struct {
const char *icon_name;
@@ -4478,71 +4414,6 @@ file_system_model_set (GtkFileSystemModel *model,
else
g_value_set_boolean (value, TRUE);
break;
- case MODEL_COL_ICON:
- if (info)
- {
- if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_ICON))
- {
- int scale;
- GtkIconTheme *icon_theme;
-
- scale = gtk_widget_get_scale_factor (GTK_WIDGET (impl));
- icon_theme = gtk_icon_theme_get_for_display (gtk_widget_get_display (GTK_WIDGET (impl)));
-
- g_value_take_object (value, _gtk_file_info_get_icon (info, ICON_SIZE, scale, icon_theme));
- }
- else
- {
- GtkTreeModel *tree_model;
- GtkTreePath *start, *end;
- GtkTreeIter iter;
- gboolean visible;
-
- if (impl->browse_files_tree_view == NULL ||
- g_file_info_has_attribute (info, "filechooser::queried"))
- return FALSE;
-
- tree_model = gtk_tree_view_get_model (GTK_TREE_VIEW (impl->browse_files_tree_view));
- if (tree_model != GTK_TREE_MODEL (model))
- return FALSE;
-
- if (!_gtk_file_system_model_get_iter_for_file (model, &iter, file))
- g_assert_not_reached ();
-
- if (gtk_tree_view_get_visible_range (GTK_TREE_VIEW (impl->browse_files_tree_view), &start,
&end))
- {
- GtkTreePath *path;
-
- gtk_tree_path_prev (start);
- gtk_tree_path_next (end);
- path = gtk_tree_model_get_path (tree_model, &iter);
- visible = gtk_tree_path_compare (start, path) != 1 &&
- gtk_tree_path_compare (path, end) != 1;
- gtk_tree_path_free (path);
- gtk_tree_path_free (start);
- gtk_tree_path_free (end);
- }
- else
- visible = TRUE;
- if (visible)
- {
- g_file_info_set_attribute_boolean (info, "filechooser::queried", TRUE);
- g_file_query_info_async (file,
- G_FILE_ATTRIBUTE_THUMBNAIL_PATH ","
- G_FILE_ATTRIBUTE_THUMBNAILING_FAILED ","
- G_FILE_ATTRIBUTE_STANDARD_ICON,
- G_FILE_QUERY_INFO_NONE,
- G_PRIORITY_DEFAULT,
- _gtk_file_system_model_get_cancellable (model),
- file_system_model_got_thumbnail,
- model);
- }
- return FALSE;
- }
- }
- else
- g_value_set_boxed (value, NULL);
- break;
case MODEL_COL_SIZE:
g_value_set_int64 (value, info ? g_file_info_get_size (info) : 0);
break;
@@ -7094,12 +6965,6 @@ path_bar_clicked (GtkPathBar *path_bar,
static void
update_cell_renderer_attributes (GtkFileChooserWidget *impl)
{
- gtk_tree_view_column_set_attributes (impl->list_name_column,
- impl->list_pixbuf_renderer,
- "gicon", MODEL_COL_ICON,
- "sensitive", MODEL_COL_IS_SENSITIVE,
- NULL);
-
gtk_tree_view_column_set_attributes (impl->list_size_column,
impl->list_size_renderer,
"text", MODEL_COL_SIZE_TEXT,
@@ -7322,6 +7187,8 @@ gtk_file_chooser_widget_class_init (GtkFileChooserWidgetClass *class)
widget_class->grab_focus = gtk_widget_grab_focus_child;
widget_class->focus = gtk_widget_focus_child;
+ g_type_ensure (GTK_TYPE_FILE_THUMBNAIL);
+
/*
* Signals
*/
@@ -7720,7 +7587,6 @@ gtk_file_chooser_widget_class_init (GtkFileChooserWidgetClass *class)
gtk_widget_class_bind_template_child (widget_class, GtkFileChooserWidget, search_entry);
gtk_widget_class_bind_template_child (widget_class, GtkFileChooserWidget, search_spinner);
gtk_widget_class_bind_template_child (widget_class, GtkFileChooserWidget, list_name_column);
- gtk_widget_class_bind_template_child (widget_class, GtkFileChooserWidget, list_pixbuf_renderer);
gtk_widget_class_bind_template_child (widget_class, GtkFileChooserWidget, list_time_column);
gtk_widget_class_bind_template_child (widget_class, GtkFileChooserWidget, list_date_renderer);
gtk_widget_class_bind_template_child (widget_class, GtkFileChooserWidget, list_time_renderer);
@@ -7842,11 +7708,6 @@ post_process_ui (GtkFileChooserWidget *impl)
_gtk_path_bar_set_file (GTK_PATH_BAR (impl->browse_path_bar), file, FALSE);
g_object_unref (file);
- /* Set the fixed size icon renderer, this requires
- * that impl->icon_size be already setup.
- */
- set_icon_cell_renderer_fixed_size (impl);
-
gtk_popover_set_default_widget (GTK_POPOVER (impl->new_folder_popover), impl->new_folder_create_button);
gtk_popover_set_default_widget (GTK_POPOVER (impl->rename_file_popover), impl->rename_file_rename_button);
diff --git a/gtk/gtkfilethumbnail.c b/gtk/gtkfilethumbnail.c
new file mode 100644
index 0000000000..633b6be912
--- /dev/null
+++ b/gtk/gtkfilethumbnail.c
@@ -0,0 +1,261 @@
+/* gtkfilethumbnail.c
+ *
+ * Copyright 2022 Georges Basile Stavracas Neto <georges stavracas gmail com>
+ *
+ * This file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This file 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.0-or-later
+ */
+
+#include "config.h"
+
+#include "gtkfilethumbnail.h"
+
+#include "gtkbinlayout.h"
+#include "gtkfilechooserutils.h"
+#include "gtkimage.h"
+#include "gtkprivate.h"
+#include "gtkwidget.h"
+
+#define ICON_SIZE 16
+
+struct _GtkFileThumbnail
+{
+ GtkWidget parent;
+
+ GtkWidget *image;
+
+ GtkFileSystemItem *item;
+ GCancellable *cancellable;
+};
+
+typedef struct
+{
+ GtkWidgetClass parent;
+} GtkFileThumbnailClass;
+
+G_DEFINE_FINAL_TYPE (GtkFileThumbnail, _gtk_file_thumbnail, GTK_TYPE_WIDGET)
+
+enum {
+ PROP_0,
+ PROP_ITEM,
+ N_PROPS,
+};
+
+static GParamSpec *properties [N_PROPS];
+
+static void
+copy_attribute (GFileInfo *to,
+ GFileInfo *from,
+ const char *attribute)
+{
+ GFileAttributeType type;
+ gpointer value;
+
+ if (g_file_info_get_attribute_data (from, attribute, &type, &value, NULL))
+ g_file_info_set_attribute (to, attribute, type, value);
+}
+
+static gboolean
+update_image (GtkFileThumbnail *self)
+{
+ GtkIconTheme *icon_theme;
+ GFileInfo *info;
+ GIcon *icon;
+ int scale;
+
+ info = _gtk_file_system_item_get_file_info (self->item);
+ if (!g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_ICON))
+ return FALSE;
+
+ scale = gtk_widget_get_scale_factor (GTK_WIDGET (self));
+ icon_theme = gtk_icon_theme_get_for_display (gtk_widget_get_display (GTK_WIDGET (self)));
+
+ icon = _gtk_file_info_get_icon (info, ICON_SIZE, scale, icon_theme);
+
+ gtk_image_set_from_gicon (GTK_IMAGE (self->image), icon);
+
+ g_object_unref (icon);
+
+ return TRUE;
+
+}
+
+static void
+thumbnail_queried_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GtkFileThumbnail *self = user_data; /* might be unreffed if operation was cancelled */
+ GFile *file = G_FILE (object);
+ GFileInfo *queried;
+ GFileInfo *info;
+
+ queried = g_file_query_info_finish (file, result, NULL);
+ if (queried == NULL)
+ return;
+
+ info = _gtk_file_system_item_get_file_info (self->item);
+ copy_attribute (info, queried, G_FILE_ATTRIBUTE_THUMBNAIL_PATH);
+ copy_attribute (info, queried, G_FILE_ATTRIBUTE_THUMBNAILING_FAILED);
+ copy_attribute (info, queried, G_FILE_ATTRIBUTE_STANDARD_ICON);
+
+ update_image (self);
+
+ g_clear_object (&queried);
+
+ g_clear_object (&self->cancellable);
+}
+
+static void
+cancel_thumbnail (GtkFileThumbnail *self)
+{
+ g_cancellable_cancel (self->cancellable);
+ g_clear_object (&self->cancellable);
+}
+
+static void
+get_thumbnail (GtkFileThumbnail *self)
+{
+ if (!self->item)
+ return;
+
+ if (!update_image (self))
+ {
+ GFileInfo *info;
+ GFile *file;
+
+ info = _gtk_file_system_item_get_file_info (self->item);
+ if (g_file_info_has_attribute (info, "filechooser::queried"))
+ return;
+
+ g_assert (self->cancellable == NULL);
+ self->cancellable = g_cancellable_new ();
+
+ file = _gtk_file_system_item_get_file (self->item);
+ g_file_info_set_attribute_boolean (info, "filechooser::queried", TRUE);
+ g_file_query_info_async (file,
+ G_FILE_ATTRIBUTE_THUMBNAIL_PATH ","
+ G_FILE_ATTRIBUTE_THUMBNAILING_FAILED ","
+ G_FILE_ATTRIBUTE_STANDARD_ICON,
+ G_FILE_QUERY_INFO_NONE,
+ G_PRIORITY_DEFAULT,
+ self->cancellable,
+ thumbnail_queried_cb,
+ self);
+ }
+}
+
+static void
+_gtk_file_thumbnail_dispose (GObject *object)
+{
+ GtkFileThumbnail *self = (GtkFileThumbnail *)object;
+
+ _gtk_file_thumbnail_set_item (self, NULL);
+
+ g_clear_pointer (&self->image, gtk_widget_unparent);
+
+ G_OBJECT_CLASS (_gtk_file_thumbnail_parent_class)->dispose (object);
+}
+
+static void
+_gtk_file_thumbnail_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GtkFileThumbnail *self = GTK_FILE_THUMBNAIL (object);
+
+ switch (prop_id)
+ {
+ case PROP_ITEM:
+ g_value_set_object (value, self->item);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+_gtk_file_thumbnail_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GtkFileThumbnail *self = GTK_FILE_THUMBNAIL (object);
+
+ switch (prop_id)
+ {
+ case PROP_ITEM:
+ _gtk_file_thumbnail_set_item (self, g_value_get_object (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+_gtk_file_thumbnail_class_init (GtkFileThumbnailClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = _gtk_file_thumbnail_dispose;
+ object_class->get_property = _gtk_file_thumbnail_get_property;
+ object_class->set_property = _gtk_file_thumbnail_set_property;
+
+ properties[PROP_ITEM] =
+ g_param_spec_object ("item", NULL, NULL,
+ GTK_TYPE_FILE_SYSTEM_ITEM,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+
+ gtk_widget_class_set_css_name (widget_class, I_("filethumbnail"));
+
+ gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
+}
+
+static void
+_gtk_file_thumbnail_init (GtkFileThumbnail *self)
+{
+ self->image = gtk_image_new ();
+ gtk_widget_set_parent (self->image, GTK_WIDGET (self));
+}
+
+GtkFileSystemItem *
+_gtk_file_thumbnail_get_item (GtkFileThumbnail *self)
+{
+ g_assert (GTK_IS_FILE_THUMBNAIL (self));
+
+ return self->item;
+}
+
+void
+_gtk_file_thumbnail_set_item (GtkFileThumbnail *self,
+ GtkFileSystemItem *item)
+{
+ g_assert (GTK_IS_FILE_THUMBNAIL (self));
+ g_assert (item == NULL || GTK_IS_FILE_SYSTEM_ITEM (item));
+
+ if (g_set_object (&self->item, item))
+ {
+ cancel_thumbnail (self);
+ get_thumbnail (self);
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ITEM]);
+ }
+}
+
diff --git a/gtk/gtkfilethumbnail.h b/gtk/gtkfilethumbnail.h
new file mode 100644
index 0000000000..12ffadefb0
--- /dev/null
+++ b/gtk/gtkfilethumbnail.h
@@ -0,0 +1,46 @@
+/* gtkfilethumbnail.h
+ *
+ * Copyright 2022 Georges Basile Stavracas Neto <georges stavracas gmail com>
+ *
+ * This file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This file 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.0-or-later
+ */
+
+
+#ifndef __GTK_FILE_THUMBNAIL_H__
+#define __GTK_FILE_THUMBNAIL_H__
+
+#include <gio/gio.h>
+
+#include "gtkfilesystemmodel.h"
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_FILE_THUMBNAIL (_gtk_file_thumbnail_get_type ())
+#define GTK_FILE_THUMBNAIL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_FILE_THUMBNAIL,
GtkFileThumbnail))
+#define GTK_IS_FILE_THUMBNAIL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_FILE_THUMBNAIL))
+
+typedef struct _GtkFileThumbnail GtkFileThumbnail;
+
+GType _gtk_file_thumbnail_get_type (void) G_GNUC_CONST;
+
+GtkFileSystemItem *_gtk_file_thumbnail_get_item (GtkFileThumbnail *self);
+void _gtk_file_thumbnail_set_item (GtkFileThumbnail *self,
+ GtkFileSystemItem *item);
+
+G_END_DECLS
+
+#endif /* __GTK_FILE_THUMBNAIL_H__ */
+
diff --git a/gtk/meson.build b/gtk/meson.build
index 4e7325ad57..4acc62e223 100644
--- a/gtk/meson.build
+++ b/gtk/meson.build
@@ -109,6 +109,7 @@ gtk_private_sources = files([
'gtkfilechoosernativeportal.c',
'gtkfilechooserutils.c',
'gtkfilesystemmodel.c',
+ 'gtkfilethumbnail.c',
'gtkgizmo.c',
'gtkiconcache.c',
'gtkiconcachevalidator.c',
diff --git a/gtk/ui/gtkfilechooserwidget.ui b/gtk/ui/gtkfilechooserwidget.ui
index 4e0090f9f7..09fb17af36 100644
--- a/gtk/ui/gtkfilechooserwidget.ui
+++ b/gtk/ui/gtkfilechooserwidget.ui
@@ -155,6 +155,15 @@
<template class="GtkListItem">
<property name="child">
<object class="GtkBox">
+ <child>
+ <object class="GtkFileThumbnail">
+ <property name="margin-start">6</property>
+ <property name="margin-end">6</property>
+ <binding name="item">
+ <lookup name="item">GtkListItem</lookup>
+ </binding>
+ </object>
+ </child>
<child>
<object class="GtkInscription">
<property name="hexpand">1</property>
@@ -234,11 +243,6 @@
<property name="title" translatable="yes">Name</property>
<property name="resizable">1</property>
<property name="expand">1</property>
- <child>
- <object class="GtkCellRendererPixbuf"
id="list_pixbuf_renderer">
- <property name="xpad">6</property>
- </object>
- </child>
</object>
</child>
<child>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]