diff options
Diffstat (limited to '')
-rw-r--r-- | src/nautilus-grid-cell.c | 282 |
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; +} |