summaryrefslogtreecommitdiffstats
path: root/src/nautilus-grid-cell.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/nautilus-grid-cell.c282
1 files changed, 282 insertions, 0 deletions
diff --git a/src/nautilus-grid-cell.c b/src/nautilus-grid-cell.c
new file mode 100644
index 0000000..9da7b78
--- /dev/null
+++ b/src/nautilus-grid-cell.c
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2022 The GNOME project contributors
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include "nautilus-grid-cell.h"
+
+struct _NautilusGridCell
+{
+ NautilusViewCell parent_instance;
+
+ GSignalGroup *item_signal_group;
+
+ GQuark *caption_attributes;
+
+ GtkWidget *fixed_height_box;
+ GtkWidget *icon;
+ GtkWidget *emblems_box;
+ GtkWidget *label;
+ GtkWidget *first_caption;
+ GtkWidget *second_caption;
+ GtkWidget *third_caption;
+};
+
+G_DEFINE_TYPE (NautilusGridCell, nautilus_grid_cell, NAUTILUS_TYPE_VIEW_CELL)
+
+static void
+update_icon (NautilusGridCell *self)
+{
+ g_autoptr (NautilusViewItem) item = NULL;
+ NautilusFileIconFlags flags;
+ g_autoptr (GdkPaintable) icon_paintable = NULL;
+ GtkStyleContext *style_context;
+ NautilusFile *file;
+ guint icon_size;
+ gint scale_factor;
+ g_autofree gchar *thumbnail_path = NULL;
+
+ item = nautilus_view_cell_get_item (NAUTILUS_VIEW_CELL (self));
+ g_return_if_fail (item != NULL);
+ file = nautilus_view_item_get_file (item);
+ icon_size = nautilus_view_item_get_icon_size (item);
+ scale_factor = gtk_widget_get_scale_factor (GTK_WIDGET (self));
+ flags = NAUTILUS_FILE_ICON_FLAGS_USE_THUMBNAILS;
+
+ icon_paintable = nautilus_file_get_icon_paintable (file, icon_size, scale_factor, flags);
+ gtk_picture_set_paintable (GTK_PICTURE (self->icon), icon_paintable);
+
+ /* Set the same height and width for all icons regardless of aspect ratio.
+ */
+ gtk_widget_set_size_request (self->fixed_height_box, icon_size, icon_size);
+ style_context = gtk_widget_get_style_context (self->icon);
+ thumbnail_path = nautilus_file_get_thumbnail_path (file);
+ if (thumbnail_path != NULL &&
+ nautilus_file_should_show_thumbnail (file))
+ {
+ gtk_style_context_add_class (style_context, "thumbnail");
+ }
+ else
+ {
+ gtk_style_context_remove_class (style_context, "thumbnail");
+ }
+}
+
+static void
+update_captions (NautilusGridCell *self)
+{
+ g_autoptr (NautilusViewItem) item = NULL;
+ NautilusFile *file;
+ GtkWidget * const caption_labels[] =
+ {
+ self->first_caption,
+ self->second_caption,
+ self->third_caption
+ };
+ G_STATIC_ASSERT (G_N_ELEMENTS (caption_labels) == NAUTILUS_GRID_CELL_N_CAPTIONS);
+
+ item = nautilus_view_cell_get_item (NAUTILUS_VIEW_CELL (self));
+ g_return_if_fail (item != NULL);
+ file = nautilus_view_item_get_file (item);
+ for (guint i = 0; i < NAUTILUS_GRID_CELL_N_CAPTIONS; i++)
+ {
+ GQuark attribute_q = self->caption_attributes[i];
+ gboolean show_caption;
+
+ show_caption = (attribute_q != 0);
+ gtk_widget_set_visible (caption_labels[i], show_caption);
+ if (show_caption)
+ {
+ g_autofree gchar *string = NULL;
+ string = nautilus_file_get_string_attribute_q (file, attribute_q);
+ gtk_label_set_text (GTK_LABEL (caption_labels[i]), string);
+ }
+ }
+}
+
+static void
+update_emblems (NautilusGridCell *self)
+{
+ g_autoptr (NautilusViewItem) item = NULL;
+ NautilusFile *file;
+ GtkWidget *child;
+ GtkIconTheme *theme;
+ g_autolist (GIcon) emblems = NULL;
+
+ item = nautilus_view_cell_get_item (NAUTILUS_VIEW_CELL (self));
+ g_return_if_fail (item != NULL);
+ file = nautilus_view_item_get_file (item);
+
+ /* Remove old emblems. */
+ while ((child = gtk_widget_get_first_child (self->emblems_box)) != NULL)
+ {
+ gtk_box_remove (GTK_BOX (self->emblems_box), child);
+ }
+
+ theme = gtk_icon_theme_get_for_display (gdk_display_get_default ());
+ emblems = nautilus_file_get_emblem_icons (file);
+ for (GList *l = emblems; l != NULL; l = l->next)
+ {
+ if (!gtk_icon_theme_has_gicon (theme, l->data))
+ {
+ g_autofree gchar *icon_string = g_icon_to_string (l->data);
+ g_warning ("Failed to add emblem. ā€œ%sā€ not found in the icon theme",
+ icon_string);
+ continue;
+ }
+
+ gtk_box_append (GTK_BOX (self->emblems_box),
+ gtk_image_new_from_gicon (l->data));
+ }
+}
+
+
+static void
+on_file_changed (NautilusGridCell *self)
+{
+ g_autoptr (NautilusViewItem) item = NULL;
+ NautilusFile *file;
+ g_autofree gchar *name = NULL;
+
+ item = nautilus_view_cell_get_item (NAUTILUS_VIEW_CELL (self));
+ g_return_if_fail (item != NULL);
+ file = nautilus_view_item_get_file (item);
+
+ update_icon (self);
+ update_emblems (self);
+
+ name = nautilus_file_get_display_name (file);
+
+ gtk_label_set_text (GTK_LABEL (self->label), name);
+ update_captions (self);
+}
+
+static void
+on_item_size_changed (NautilusGridCell *self)
+{
+ update_icon (self);
+ update_captions (self);
+}
+
+static void
+on_item_is_cut_changed (NautilusGridCell *self)
+{
+ gboolean is_cut;
+ g_autoptr (NautilusViewItem) item = NULL;
+
+ item = nautilus_view_cell_get_item (NAUTILUS_VIEW_CELL (self));
+ g_object_get (item,
+ "is-cut", &is_cut,
+ NULL);
+ if (is_cut)
+ {
+ gtk_widget_add_css_class (self->icon, "cut");
+ }
+ else
+ {
+ gtk_widget_remove_css_class (self->icon, "cut");
+ }
+}
+
+static gboolean
+on_label_query_tooltip (GtkWidget *widget,
+ int x,
+ int y,
+ gboolean keyboard_tip,
+ GtkTooltip *tooltip,
+ gpointer user_data)
+{
+ GtkLabel *label = GTK_LABEL (widget);
+
+ if (pango_layout_is_ellipsized (gtk_label_get_layout (label)))
+ {
+ gtk_tooltip_set_markup (tooltip, gtk_label_get_label (label));
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+finalize (GObject *object)
+{
+ NautilusGridCell *self = (NautilusGridCell *) object;
+
+ g_object_unref (self->item_signal_group);
+ G_OBJECT_CLASS (nautilus_grid_cell_parent_class)->finalize (object);
+}
+
+static void
+nautilus_grid_cell_class_init (NautilusGridCellClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->finalize = finalize;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/nautilus/ui/nautilus-grid-cell.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, NautilusGridCell, fixed_height_box);
+ gtk_widget_class_bind_template_child (widget_class, NautilusGridCell, icon);
+ gtk_widget_class_bind_template_child (widget_class, NautilusGridCell, emblems_box);
+ gtk_widget_class_bind_template_child (widget_class, NautilusGridCell, label);
+ gtk_widget_class_bind_template_child (widget_class, NautilusGridCell, first_caption);
+ gtk_widget_class_bind_template_child (widget_class, NautilusGridCell, second_caption);
+ gtk_widget_class_bind_template_child (widget_class, NautilusGridCell, third_caption);
+
+ gtk_widget_class_set_accessible_role (widget_class, GTK_ACCESSIBLE_ROLE_GRID_CELL);
+}
+
+static void
+nautilus_grid_cell_init (NautilusGridCell *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ g_signal_connect (self->label, "query-tooltip",
+ G_CALLBACK (on_label_query_tooltip), NULL);
+
+ /* Connect automatically to an item. */
+ self->item_signal_group = g_signal_group_new (NAUTILUS_TYPE_VIEW_ITEM);
+ g_signal_group_connect_swapped (self->item_signal_group, "notify::icon-size",
+ (GCallback) on_item_size_changed, self);
+ g_signal_group_connect_swapped (self->item_signal_group, "notify::is-cut",
+ (GCallback) on_item_is_cut_changed, self);
+ g_signal_group_connect_swapped (self->item_signal_group, "file-changed",
+ (GCallback) on_file_changed, self);
+ g_signal_connect_object (self->item_signal_group, "bind",
+ (GCallback) on_file_changed, self,
+ G_CONNECT_SWAPPED);
+
+ g_object_bind_property (self, "item",
+ self->item_signal_group, "target",
+ G_BINDING_SYNC_CREATE);
+
+#if PANGO_VERSION_CHECK (1, 44, 4)
+ {
+ PangoAttrList *attr_list;
+
+ /* GTK4 TODO: This attribute is set in the UI file but GTK 3 ignores it.
+ * Remove this block after the switch to GTK 4. */
+ attr_list = pango_attr_list_new ();
+ pango_attr_list_insert (attr_list, pango_attr_insert_hyphens_new (FALSE));
+ gtk_label_set_attributes (GTK_LABEL (self->label), attr_list);
+ pango_attr_list_unref (attr_list);
+ }
+#endif
+}
+
+NautilusGridCell *
+nautilus_grid_cell_new (NautilusListBase *view)
+{
+ return g_object_new (NAUTILUS_TYPE_GRID_CELL,
+ "view", view,
+ NULL);
+}
+
+void
+nautilus_grid_cell_set_caption_attributes (NautilusGridCell *self,
+ GQuark *attrs)
+{
+ self->caption_attributes = attrs;
+}