Replace the cell data computations

Previously custom functions were used to compute the data passed to the
cell renderers. Now that all this data is saved by the tree models with
compatible nodes, the usual default attribute-to-column mapping can be
used.
With this, caching of the values can happen in the tree model, which
avoids costly lookups of icons or computation of strings. Last but not
least it avoids spurious bugs that could happen when strings changed
without anyone noticing, like the mtime when a new day begins.
This commit is contained in:
Benjamin Otte 2009-06-30 22:58:55 +02:00
parent a5390ad49e
commit 30c1a1ee2c

View File

@ -399,26 +399,7 @@ static void remove_bookmark_button_clicked_cb (GtkButton *button,
static void save_folder_combo_changed_cb (GtkComboBox *combo, static void save_folder_combo_changed_cb (GtkComboBox *combo,
GtkFileChooserDefault *impl); GtkFileChooserDefault *impl);
static void list_icon_data_func (GtkTreeViewColumn *tree_column, static void update_cell_renderer_attributes (GtkFileChooserDefault *impl);
GtkCellRenderer *cell,
GtkTreeModel *tree_model,
GtkTreeIter *iter,
gpointer data);
static void list_name_data_func (GtkTreeViewColumn *tree_column,
GtkCellRenderer *cell,
GtkTreeModel *tree_model,
GtkTreeIter *iter,
gpointer data);
static void list_size_data_func (GtkTreeViewColumn *tree_column,
GtkCellRenderer *cell,
GtkTreeModel *tree_model,
GtkTreeIter *iter,
gpointer data);
static void list_mtime_data_func (GtkTreeViewColumn *tree_column,
GtkCellRenderer *cell,
GtkTreeModel *tree_model,
GtkTreeIter *iter,
gpointer data);
static GFileInfo *get_list_file_info (GtkFileChooserDefault *impl, static GFileInfo *get_list_file_info (GtkFileChooserDefault *impl,
GtkTreeIter *iter); GtkTreeIter *iter);
@ -4658,8 +4639,6 @@ create_file_list (GtkFileChooserDefault *impl)
renderer = gtk_cell_renderer_pixbuf_new (); renderer = gtk_cell_renderer_pixbuf_new ();
gtk_tree_view_column_pack_start (impl->list_name_column, renderer, FALSE); gtk_tree_view_column_pack_start (impl->list_name_column, renderer, FALSE);
gtk_tree_view_column_set_cell_data_func (impl->list_name_column, renderer,
list_icon_data_func, impl, NULL);
impl->list_name_renderer = gtk_cell_renderer_text_new (); impl->list_name_renderer = gtk_cell_renderer_text_new ();
g_object_set (impl->list_name_renderer, g_object_set (impl->list_name_renderer,
@ -4670,8 +4649,6 @@ create_file_list (GtkFileChooserDefault *impl)
g_signal_connect (impl->list_name_renderer, "editing-canceled", g_signal_connect (impl->list_name_renderer, "editing-canceled",
G_CALLBACK (renderer_editing_canceled_cb), impl); G_CALLBACK (renderer_editing_canceled_cb), impl);
gtk_tree_view_column_pack_start (impl->list_name_column, impl->list_name_renderer, TRUE); gtk_tree_view_column_pack_start (impl->list_name_column, impl->list_name_renderer, TRUE);
gtk_tree_view_column_set_cell_data_func (impl->list_name_column, impl->list_name_renderer,
list_name_data_func, impl, NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (impl->browse_files_tree_view), impl->list_name_column); gtk_tree_view_append_column (GTK_TREE_VIEW (impl->browse_files_tree_view), impl->list_name_column);
@ -4686,8 +4663,6 @@ create_file_list (GtkFileChooserDefault *impl)
"alignment", PANGO_ALIGN_RIGHT, "alignment", PANGO_ALIGN_RIGHT,
NULL); NULL);
gtk_tree_view_column_pack_start (column, renderer, TRUE); /* bug: it doesn't expand */ gtk_tree_view_column_pack_start (column, renderer, TRUE); /* bug: it doesn't expand */
gtk_tree_view_column_set_cell_data_func (column, renderer,
list_size_data_func, impl, NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (impl->browse_files_tree_view), column); gtk_tree_view_append_column (GTK_TREE_VIEW (impl->browse_files_tree_view), column);
impl->list_size_column = column; impl->list_size_column = column;
@ -4699,12 +4674,11 @@ create_file_list (GtkFileChooserDefault *impl)
renderer = gtk_cell_renderer_text_new (); renderer = gtk_cell_renderer_text_new ();
gtk_tree_view_column_pack_start (column, renderer, TRUE); gtk_tree_view_column_pack_start (column, renderer, TRUE);
gtk_tree_view_column_set_cell_data_func (column, renderer,
list_mtime_data_func, impl, NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (impl->browse_files_tree_view), column); gtk_tree_view_append_column (GTK_TREE_VIEW (impl->browse_files_tree_view), column);
impl->list_mtime_column = column; impl->list_mtime_column = column;
file_list_set_sort_column_ids (impl); file_list_set_sort_column_ids (impl);
update_cell_renderer_attributes (impl);
gtk_widget_show_all (swin); gtk_widget_show_all (swin);
@ -5603,6 +5577,7 @@ gtk_file_chooser_default_set_property (GObject *object,
set_select_multiple (impl, FALSE, TRUE); set_select_multiple (impl, FALSE, TRUE);
} }
impl->action = action; impl->action = action;
update_cell_renderer_attributes (impl);
update_appearance (impl); update_appearance (impl);
settings_load (impl); settings_load (impl);
} }
@ -10926,364 +10901,67 @@ get_list_file_info (GtkFileChooserDefault *impl,
} }
static void static void
list_icon_data_func (GtkTreeViewColumn *tree_column, update_cell_renderer_attributes (GtkFileChooserDefault *impl)
GtkCellRenderer *cell,
GtkTreeModel *tree_model,
GtkTreeIter *iter,
gpointer data)
{ {
GtkFileChooserDefault *impl = data; GtkTreeViewColumn *column;
GtkTreeIter child_iter; GtkCellRenderer *renderer;
GdkPixbuf *pixbuf = NULL; GList *walk, *list;
gboolean sensitive = TRUE; gboolean always_sensitive;
profile_start ("start", NULL); always_sensitive = impl->action != GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER &&
impl->action != GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER;
switch (impl->operation_mode)
/* name */
column = gtk_tree_view_get_column (GTK_TREE_VIEW (impl->browse_files_tree_view), 0);
list = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column));
for (walk = list; walk; walk = walk->next)
{ {
case OPERATION_MODE_SEARCH: renderer = walk->data;
{ if (GTK_IS_CELL_RENDERER_PIXBUF (renderer))
GtkTreeIter child_iter;
gboolean is_folder;
search_get_valid_child_iter (impl, &child_iter, iter);
gtk_tree_model_get (GTK_TREE_MODEL (impl->search_model), &child_iter,
MODEL_COL_PIXBUF, &pixbuf,
MODEL_COL_IS_FOLDER, &is_folder,
-1);
if (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ||
impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
sensitive = is_folder;
}
break;
case OPERATION_MODE_RECENT:
{
GtkTreeIter child_iter;
GtkRecentInfo *info;
gboolean is_folder;
recent_get_valid_child_iter (impl, &child_iter, iter);
gtk_tree_model_get (GTK_TREE_MODEL (impl->recent_model), &child_iter,
RECENT_MODEL_COL_INFO, &info,
MODEL_COL_IS_FOLDER, &is_folder,
-1);
pixbuf = gtk_recent_info_get_icon (info, impl->icon_size);
if (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ||
impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
sensitive = is_folder;
}
break;
case OPERATION_MODE_BROWSE:
{
GFileInfo *info;
GFile *file;
info = get_list_file_info (impl, iter);
gtk_tree_model_sort_convert_iter_to_child_iter (impl->sort_model,
&child_iter,
iter);
file = _gtk_file_system_model_get_file (impl->browse_files_model, &child_iter);
if (file)
{
if (info)
{
/* FIXME: NULL GError */
pixbuf = _gtk_file_info_render_icon (info, GTK_WIDGET (impl), impl->icon_size);
}
}
else
{
/* We are on the editable row */
pixbuf = NULL;
}
if (info &&
(impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ||
impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER))
sensitive = _gtk_file_info_consider_as_directory (info);
}
break;
}
g_object_set (cell,
"pixbuf", pixbuf,
"sensitive", sensitive,
NULL);
if (pixbuf)
g_object_unref (pixbuf);
profile_end ("end", NULL);
}
static void
list_name_data_func (GtkTreeViewColumn *tree_column,
GtkCellRenderer *cell,
GtkTreeModel *tree_model,
GtkTreeIter *iter,
gpointer data)
{
GtkFileChooserDefault *impl = data;
GFileInfo *info;
gboolean sensitive = TRUE;
if (impl->operation_mode == OPERATION_MODE_SEARCH)
{
GtkTreeIter child_iter;
gchar *display_name;
gboolean is_folder;
search_get_valid_child_iter (impl, &child_iter, iter);
gtk_tree_model_get (GTK_TREE_MODEL (impl->search_model), &child_iter,
MODEL_COL_NAME, &display_name,
MODEL_COL_IS_FOLDER, &is_folder,
-1);
if (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ||
impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
{ {
sensitive = is_folder; gtk_tree_view_column_set_attributes (column, renderer,
"pixbuf", MODEL_COL_PIXBUF,
NULL);
} }
else
g_object_set (cell,
"text", display_name,
"sensitive", sensitive,
"ellipsize", PANGO_ELLIPSIZE_END,
NULL);
return;
}
if (impl->operation_mode == OPERATION_MODE_RECENT)
{
GtkTreeIter child_iter;
GtkRecentInfo *recent_info;
gchar *display_name;
gboolean is_folder;
recent_get_valid_child_iter (impl, &child_iter, iter);
gtk_tree_model_get (GTK_TREE_MODEL (impl->recent_model), &child_iter,
RECENT_MODEL_COL_INFO, &recent_info,
MODEL_COL_IS_FOLDER, &is_folder,
-1);
display_name = gtk_recent_info_get_short_name (recent_info);
if (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ||
impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
{ {
sensitive = is_folder; gtk_tree_view_column_set_attributes (column, renderer,
"text", MODEL_COL_NAME,
"ellipsize", MODEL_COL_ELLIPSIZE,
NULL);
} }
if (always_sensitive)
g_object_set (cell, g_object_set (renderer, "sensitive", TRUE, NULL);
"text", display_name,
"sensitive", sensitive,
"ellipsize", PANGO_ELLIPSIZE_END,
NULL);
g_free (display_name);
return;
}
info = get_list_file_info (impl, iter);
sensitive = TRUE;
if (!info)
{
g_object_set (cell,
"text", DEFAULT_NEW_FOLDER_NAME,
"sensitive", TRUE,
"ellipsize", PANGO_ELLIPSIZE_NONE,
NULL);
return;
}
if (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ||
impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
{
sensitive = _gtk_file_info_consider_as_directory (info);
}
g_object_set (cell,
"text", g_file_info_get_display_name (info),
"sensitive", sensitive,
"ellipsize", PANGO_ELLIPSIZE_END,
NULL);
}
static void
list_size_data_func (GtkTreeViewColumn *tree_column,
GtkCellRenderer *cell,
GtkTreeModel *tree_model,
GtkTreeIter *iter,
gpointer data)
{
GtkFileChooserDefault *impl = data;
GFileInfo *info;
goffset size;
gchar *str;
gboolean sensitive = TRUE;
if (impl->operation_mode == OPERATION_MODE_RECENT)
return;
if (impl->operation_mode == OPERATION_MODE_SEARCH)
{
GtkTreeIter child_iter;
gboolean is_folder = FALSE;
search_get_valid_child_iter (impl, &child_iter, iter);
gtk_tree_model_get (GTK_TREE_MODEL (impl->search_model), &child_iter,
MODEL_COL_SIZE, &size,
MODEL_COL_IS_FOLDER, &is_folder,
-1);
if (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ||
impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
sensitive = is_folder ? TRUE : FALSE;
if (!is_folder)
str = g_format_size_for_display (size);
else else
str = NULL; gtk_tree_view_column_add_attribute (column, renderer, "sensitive", MODEL_COL_IS_FOLDER);
g_object_set (cell,
"text", str,
"sensitive", sensitive,
NULL);
g_free (str);
return;
} }
g_list_free (list);
info = get_list_file_info (impl, iter); /* size */
column = gtk_tree_view_get_column (GTK_TREE_VIEW (impl->browse_files_tree_view), 1);
if (!info || _gtk_file_info_consider_as_directory (info)) list = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column));
{ renderer = list->data;
g_object_set (cell, gtk_tree_view_column_set_attributes (column, renderer,
"text", NULL, "text", MODEL_COL_SIZE_TEXT,
"sensitive", sensitive, NULL);
NULL); if (always_sensitive)
return; g_object_set (renderer, "sensitive", TRUE, NULL);
}
size = g_file_info_get_size (info);
str = g_format_size_for_display (size);
if (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ||
impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
sensitive = FALSE;
g_object_set (cell,
"text", str,
"sensitive", sensitive,
NULL);
g_free (str);
}
/* Tree column data callback for the file list; fetches the mtime of a file */
static void
list_mtime_data_func (GtkTreeViewColumn *tree_column,
GtkCellRenderer *cell,
GtkTreeModel *tree_model,
GtkTreeIter *iter,
gpointer data)
{
GtkFileChooserDefault *impl;
GTimeVal timeval = { 0, };
time_t time_mtime;
gchar *date_str = NULL;
gboolean sensitive = TRUE;
#ifdef G_OS_WIN32
const char *locale, *dot = NULL;
gint64 codepage = -1;
char charset[20];
#endif
impl = data;
if (impl->operation_mode == OPERATION_MODE_SEARCH)
{
GtkTreeIter child_iter;
guint64 mtime;
gboolean is_folder;
search_get_valid_child_iter (impl, &child_iter, iter);
gtk_tree_model_get (GTK_TREE_MODEL (impl->search_model), &child_iter,
MODEL_COL_MTIME, &mtime,
MODEL_COL_IS_FOLDER, &is_folder,
-1);
time_mtime = (time_t) mtime;
if (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ||
impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
sensitive = is_folder;
}
else if (impl->operation_mode == OPERATION_MODE_RECENT)
{
GtkTreeIter child_iter;
GtkRecentInfo *info;
gboolean is_folder;
recent_get_valid_child_iter (impl, &child_iter, iter);
gtk_tree_model_get (GTK_TREE_MODEL (impl->recent_model), &child_iter,
RECENT_MODEL_COL_INFO, &info,
MODEL_COL_IS_FOLDER, &is_folder,
-1);
if (info)
time_mtime = gtk_recent_info_get_modified (info);
else
time_mtime = 0;
if (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ||
impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
sensitive = is_folder;
}
else else
{ gtk_tree_view_column_add_attribute (column, renderer, "sensitive", MODEL_COL_IS_FOLDER);
GFileInfo *info; g_list_free (list);
info = get_list_file_info (impl, iter); /* mtime */
if (!info) column = gtk_tree_view_get_column (GTK_TREE_VIEW (impl->browse_files_tree_view), 2);
{ list = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column));
g_object_set (cell, renderer = list->data;
"text", "", gtk_tree_view_column_set_attributes (column, renderer,
"sensitive", TRUE, "text", MODEL_COL_MTIME_TEXT,
NULL); NULL);
return; if (always_sensitive)
} g_object_set (renderer, "sensitive", TRUE, NULL);
g_file_info_get_modification_time (info, &timeval);
time_mtime = timeval.tv_sec;
if (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ||
impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
sensitive = _gtk_file_info_consider_as_directory (info);
}
if (G_UNLIKELY (time_mtime == 0))
date_str = g_strdup (_("Unknown"));
else else
date_str = my_g_format_time_for_display (time_mtime); gtk_tree_view_column_add_attribute (column, renderer, "sensitive", MODEL_COL_IS_FOLDER);
g_list_free (list);
g_object_set (cell,
"text", date_str,
"sensitive", sensitive,
NULL);
g_free (date_str);
} }
GtkWidget * GtkWidget *