gtkfilechooser: improve file tooltips

This commit is contained in:
Daemonratte 2026-05-19 14:17:20 +02:00
commit 7b0f4f4b8a
2 changed files with 223 additions and 36 deletions

View file

@ -887,6 +887,18 @@ static void
gtk_file_chooser_default_finalize (GObject *object)
{
GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (object);
if (impl->list_tooltip_path)
{
gtk_tree_path_free (impl->list_tooltip_path);
impl->list_tooltip_path = NULL;
}
impl->list_tooltip_model = NULL;
g_free (impl->list_tooltip_text);
impl->list_tooltip_text = NULL;
GSList *l;
icon_view_scale_remove_timeout (impl);
@ -5553,6 +5565,112 @@ file_list_set_sort_column_ids (GtkFileChooserDefault *impl)
}
}
static gboolean file_name_needs_tooltip (GtkFileChooserDefault *impl,
const gchar *name,
gint available_width);
static void
file_list_tooltip_cache_clear (GtkFileChooserDefault *impl)
{
if (impl->list_tooltip_path)
{
gtk_tree_path_free (impl->list_tooltip_path);
impl->list_tooltip_path = NULL;
}
impl->list_tooltip_model = NULL;
g_free (impl->list_tooltip_text);
impl->list_tooltip_text = NULL;
impl->list_tooltip_width = 0;
impl->list_tooltip_visible = FALSE;
}
static gint
file_list_get_tooltip_width (GtkFileChooserDefault *impl)
{
GtkCellRenderer *text_renderer = NULL;
GList *cells;
GList *l;
gint width = 0;
gint start_pos = 0;
gint text_xpad = 0;
if (!impl->list_name_column)
return 0;
cells = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (impl->list_name_column));
for (l = cells; l; l = l->next)
{
if (GTK_IS_CELL_RENDERER_TEXT (l->data))
{
text_renderer = GTK_CELL_RENDERER (l->data);
break;
}
}
if (text_renderer &&
gtk_tree_view_column_cell_get_position (impl->list_name_column,
text_renderer,
&start_pos,
&width))
{
gtk_cell_renderer_get_padding (text_renderer, &text_xpad, NULL);
width -= text_xpad * 2;
width -= 12;
}
else
{
gint icon_size;
width = gtk_tree_view_column_get_width (impl->list_name_column);
icon_size = impl->list_view_icon_size;
if (icon_size <= 0)
icon_size = FALLBACK_LIST_VIEW_ICON_SIZE;
width -= icon_size + 16;
}
g_list_free (cells);
return MAX (1, width);
}
static gboolean
file_list_tooltip_cache_matches (GtkFileChooserDefault *impl,
GtkTreeModel *model,
GtkTreePath *path,
gint available_width)
{
return impl->list_tooltip_path &&
impl->list_tooltip_model == model &&
gtk_tree_path_compare (impl->list_tooltip_path, path) == 0 &&
impl->list_tooltip_width == available_width &&
impl->list_tooltip_operation_mode == impl->operation_mode;
}
static void
file_list_tooltip_cache_set (GtkFileChooserDefault *impl,
GtkTreeModel *model,
GtkTreePath *path,
gint available_width,
gboolean visible,
const gchar *tooltip_text)
{
file_list_tooltip_cache_clear (impl);
impl->list_tooltip_path = gtk_tree_path_copy (path);
impl->list_tooltip_model = model;
impl->list_tooltip_width = available_width;
impl->list_tooltip_operation_mode = impl->operation_mode;
impl->list_tooltip_visible = visible;
if (tooltip_text)
impl->list_tooltip_text = g_strdup (tooltip_text);
}
static gboolean
file_list_query_tooltip_cb (GtkWidget *widget,
gint x,
@ -5562,40 +5680,94 @@ file_list_query_tooltip_cb (GtkWidget *widget,
gpointer user_data)
{
GtkFileChooserDefault *impl = user_data;
GtkTreeView *tree_view;
GtkTreeViewColumn *column = NULL;
GtkTreeModel *model;
GtkTreePath *path;
GtkTreeIter iter;
GFile *file;
char *parse_name;
gchar *display_name;
gchar *tooltip_text;
gint available_width;
if (impl->operation_mode == OPERATION_MODE_BROWSE)
tree_view = GTK_TREE_VIEW (impl->browse_files_tree_view);
if (!gtk_tree_view_get_path_at_pos (tree_view, x, y, NULL, &column, NULL, NULL))
return FALSE;
if (column != impl->list_name_column)
return FALSE;
if (!gtk_tree_view_get_tooltip_context (GTK_TREE_VIEW (impl->browse_files_tree_view),
if (!gtk_tree_view_get_tooltip_context (tree_view,
&x, &y,
keyboard_tip,
&model, &path, &iter))
return FALSE;
available_width = file_list_get_tooltip_width (impl);
if (file_list_tooltip_cache_matches (impl, model, path, available_width))
{
if (!impl->list_tooltip_visible)
{
gtk_tree_path_free (path);
return FALSE;
}
gtk_tooltip_set_text (tooltip, impl->list_tooltip_text);
gtk_tree_view_set_tooltip_row (tree_view, tooltip, path);
gtk_tree_path_free (path);
return TRUE;
}
if (impl->operation_mode != OPERATION_MODE_BROWSE)
{
GFile *file = NULL;
gtk_tree_model_get (model, &iter,
MODEL_COL_FILE, &file,
-1);
if (!file)
{
file_list_tooltip_cache_set (impl, model, path, available_width, FALSE, NULL);
gtk_tree_path_free (path);
return FALSE;
}
tooltip_text = g_file_get_parse_name (file);
g_object_unref (file);
file_list_tooltip_cache_set (impl, model, path, available_width, TRUE, tooltip_text);
gtk_tooltip_set_text (tooltip, tooltip_text);
gtk_tree_view_set_tooltip_row (tree_view, tooltip, path);
g_free (tooltip_text);
gtk_tree_path_free (path);
return TRUE;
}
gtk_tree_model_get (model, &iter,
MODEL_COL_FILE, &file,
MODEL_COL_NAME, &display_name,
-1);
if (file == NULL)
if (!file_name_needs_tooltip (impl, display_name, available_width))
{
file_list_tooltip_cache_set (impl, model, path, available_width, FALSE, NULL);
g_free (display_name);
gtk_tree_path_free (path);
return FALSE;
}
parse_name = g_file_get_parse_name (file);
gtk_tooltip_set_text (tooltip, parse_name);
gtk_tree_view_set_tooltip_row (GTK_TREE_VIEW (impl->browse_files_tree_view),
tooltip,
path);
tooltip_text = display_name;
g_free (parse_name);
g_object_unref (file);
file_list_tooltip_cache_set (impl, model, path, available_width, TRUE, tooltip_text);
gtk_tooltip_set_text (tooltip, tooltip_text);
gtk_tree_view_set_tooltip_row (tree_view, tooltip, path);
g_free (tooltip_text);
gtk_tree_path_free (path);
return TRUE;
@ -5766,6 +5938,37 @@ file_icon_view_query_tooltip_cb (GtkWidget *widget,
return TRUE;
}
if (impl->operation_mode != OPERATION_MODE_BROWSE)
{
GFile *file = NULL;
gtk_tree_model_get (model, &iter,
MODEL_COL_FILE, &file,
-1);
if (!file)
{
file_icon_view_tooltip_cache_set (impl, path, available_width, FALSE, NULL);
gtk_tree_path_free (path);
return FALSE;
}
tooltip_text = g_file_get_parse_name (file);
g_object_unref (file);
file_icon_view_tooltip_cache_set (impl, path, available_width, TRUE, tooltip_text);
gtk_tooltip_set_text (tooltip, tooltip_text);
gtk_icon_view_set_tooltip_item (GTK_ICON_VIEW (impl->browse_files_icon_view),
tooltip,
path);
g_free (tooltip_text);
gtk_tree_path_free (path);
return TRUE;
}
gtk_tree_model_get (model, &iter,
MODEL_COL_NAME, &display_name,
-1);
@ -5778,29 +5981,7 @@ file_icon_view_query_tooltip_cb (GtkWidget *widget,
return FALSE;
}
if (impl->operation_mode == OPERATION_MODE_BROWSE)
{
tooltip_text = display_name;
}
else
{
GFile *file = NULL;
gtk_tree_model_get (model, &iter,
MODEL_COL_FILE, &file,
-1);
if (file)
{
tooltip_text = g_file_get_parse_name (file);
g_object_unref (file);
g_free (display_name);
}
else
{
tooltip_text = display_name;
}
}
tooltip_text = display_name;
file_icon_view_tooltip_cache_set (impl, path, available_width, TRUE, tooltip_text);

View file

@ -187,6 +187,12 @@ struct _GtkFileChooserDefault
ViewMode icon_tooltip_view_mode;
OperationMode icon_tooltip_operation_mode;
guint icon_tooltip_visible : 1;
GtkTreePath *list_tooltip_path;
GtkTreeModel *list_tooltip_model;
gchar *list_tooltip_text;
gint list_tooltip_width;
OperationMode list_tooltip_operation_mode;
guint list_tooltip_visible : 1;
GtkWidget *browse_files_popup_menu;
GtkWidget *browse_files_popup_menu_add_shortcut_item;
GtkWidget *browse_files_popup_menu_copy_location_item;