37 #include <glib/gi18n.h>
38 #include <gdk/gdkkeysyms.h>
45 #include "gnc-cell-renderer-date.h"
51 #define STATE_KEY "state-key"
54 #define STATE_KEY_SORT_COLUMN "sort_column"
55 #define STATE_KEY_SORT_ORDER "sort_order"
56 #define STATE_KEY_COLUMN_ORDER "column_order"
61 #define STATE_KEY_SUFF_VISIBLE "visible"
62 #define STATE_KEY_SUFF_WIDTH "width"
68 PROP_SHOW_COLUMN_MENU,
79 static void gnc_tree_view_finalize (GObject *
object);
80 static void gnc_tree_view_destroy (GtkObject *
object);
81 static void gnc_tree_view_set_property (GObject *
object,
85 static void gnc_tree_view_get_property (GObject *
object,
89 static gboolean gnc_tree_view_drop_ok_cb (GtkTreeView *view,
90 GtkTreeViewColumn *column,
91 GtkTreeViewColumn *prev_column,
92 GtkTreeViewColumn *next_column,
94 static void gnc_tree_view_build_column_menu (
GncTreeView *view);
95 static void gnc_tree_view_select_column_cb (GtkTreeViewColumn *column,
97 static gchar *gnc_tree_view_get_sort_order (
GncTreeView *view);
98 static gchar *gnc_tree_view_get_sort_column (
GncTreeView *view);
99 static gchar **gnc_tree_view_get_column_order (
GncTreeView *view,
107 GtkTreeViewColumn *spacer_column;
108 GtkTreeViewColumn *selection_column;
111 GtkTreeViewColumn *column_menu_column;
112 GtkWidget *column_menu;
113 gboolean show_column_menu;
116 GtkTreeModel *sort_model;
119 gchar *state_section;
120 gboolean seen_state_visibility;
121 gulong columns_changed_cb_id;
122 gulong sort_column_changed_cb_id;
123 gulong size_allocate_cb_id;
126 #define GNC_TREE_VIEW_GET_PRIVATE(o) \
127 (G_TYPE_INSTANCE_GET_PRIVATE ((o), GNC_TYPE_TREE_VIEW, GncTreeViewPrivate))
137 static GObjectClass *parent_class = NULL;
148 static GType gnc_tree_view_type = 0;
150 if (gnc_tree_view_type == 0)
152 static const GTypeInfo our_info =
157 (GClassInitFunc) gnc_tree_view_class_init,
162 (GInstanceInitFunc) gnc_tree_view_init
165 gnc_tree_view_type = g_type_register_static (GTK_TYPE_TREE_VIEW,
170 return gnc_tree_view_type;
185 GObjectClass *gobject_class;
186 GtkObjectClass *gtkobject_class;
188 parent_class = g_type_class_peek_parent (klass);
190 gobject_class = G_OBJECT_CLASS (klass);
191 gtkobject_class = GTK_OBJECT_CLASS (klass);
193 gobject_class->set_property = gnc_tree_view_set_property;
194 gobject_class->get_property = gnc_tree_view_get_property;
198 g_object_class_install_property (gobject_class,
200 g_param_spec_string (
"state-section",
202 "The section name in the saved state to use for (re)storing the treeview's visual state (visible columns, sort order,...",
205 g_object_class_install_property (gobject_class,
206 PROP_SHOW_COLUMN_MENU,
207 g_param_spec_boolean (
"show-column-menu",
209 "Show the column menu so user can change what columns are visible.",
214 gobject_class->finalize = gnc_tree_view_finalize;
217 gtkobject_class->destroy = gnc_tree_view_destroy;
233 GtkTreeViewColumn *column;
235 GtkRequisition requisition;
239 priv = GNC_TREE_VIEW_GET_PRIVATE(view);
240 priv->column_menu = NULL;
241 priv->show_column_menu = FALSE;
242 priv->sort_model = NULL;
243 priv->state_section = NULL;
244 priv->seen_state_visibility = FALSE;
245 priv->columns_changed_cb_id = 0;
246 priv->sort_column_changed_cb_id = 0;
247 priv->size_allocate_cb_id = 0;
250 g_object_set(view,
"rules-hint", TRUE, NULL);
253 gtk_tree_view_set_column_drag_function(GTK_TREE_VIEW(view),
254 gnc_tree_view_drop_ok_cb, NULL, NULL);
261 g_object_set(G_OBJECT(column),
265 priv->spacer_column = column;
267 gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
272 icon = gtk_image_new_from_stock(GTK_STOCK_GO_DOWN,
273 GTK_ICON_SIZE_SMALL_TOOLBAR);
274 gtk_widget_show(icon);
275 gtk_widget_size_request(icon, &requisition);
278 g_object_set(G_OBJECT(column),
281 "fixed-width", requisition.width + 10,
283 priv->selection_column = column;
284 g_signal_connect(G_OBJECT(column),
"clicked",
285 G_CALLBACK (gnc_tree_view_select_column_cb),
287 priv->column_menu_column = column;
289 gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
303 gnc_tree_view_finalize (GObject *
object)
305 ENTER(
"view %p",
object);
306 g_return_if_fail (
object != NULL);
307 g_return_if_fail (GNC_IS_TREE_VIEW (
object));
311 if (G_OBJECT_CLASS (parent_class)->finalize)
312 G_OBJECT_CLASS (parent_class)->finalize (
object);
328 gnc_tree_view_destroy (GtkObject *
object)
333 ENTER(
"view %p",
object);
334 g_return_if_fail (
object != NULL);
335 g_return_if_fail (GNC_IS_TREE_VIEW (
object));
337 view = GNC_TREE_VIEW (
object);
339 priv = GNC_TREE_VIEW_GET_PRIVATE(view);
341 if (priv->state_section)
345 g_free(priv->state_section);
346 priv->state_section = NULL;
348 if (priv->column_menu)
350 DEBUG(
"removing column selection menu");
351 g_object_unref(priv->column_menu);
352 priv->column_menu = NULL;
355 if (GTK_OBJECT_CLASS (parent_class)->destroy)
356 GTK_OBJECT_CLASS (parent_class)->destroy (
object);
377 gnc_tree_view_get_property (GObject *
object,
385 priv = GNC_TREE_VIEW_GET_PRIVATE(view);
388 case PROP_STATE_SECTION:
389 g_value_set_string (value, priv->state_section);
391 case PROP_SHOW_COLUMN_MENU:
392 g_value_set_boolean (value, priv->show_column_menu);
395 G_OBJECT_WARN_INVALID_PROPERTY_ID (
object, prop_id, pspec);
410 gnc_tree_view_set_property (GObject *
object,
419 case PROP_STATE_SECTION:
422 case PROP_SHOW_COLUMN_MENU:
426 G_OBJECT_WARN_INVALID_PROPERTY_ID (
object, prop_id, pspec);
454 static GtkTreeViewColumn *
458 GtkTreeViewColumn *column, *found = NULL;
459 GList *column_list, *tmp;
463 column_list = gtk_tree_view_get_columns(GTK_TREE_VIEW(view));
464 for (tmp = column_list; tmp; tmp = g_list_next(tmp))
467 id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(column), MODEL_COLUMN));
473 g_list_free(column_list);
493 GtkTreeViewColumn *column, *found = NULL;
494 GList *column_list, *tmp;
498 column_list = gtk_tree_view_get_columns(GTK_TREE_VIEW(view));
499 for (tmp = column_list; tmp; tmp = g_list_next(tmp))
502 name = g_object_get_data(G_OBJECT(column), PREF_NAME);
503 if (!name || (strcmp(name, wanted) != 0))
508 g_list_free(column_list);
549 gnc_tree_view_drop_ok_cb (GtkTreeView *view,
550 GtkTreeViewColumn *column,
551 GtkTreeViewColumn *prev_column,
552 GtkTreeViewColumn *next_column,
555 const gchar *pref_name;
560 if (prev_column == NULL)
565 if (next_column == NULL)
573 pref_name = g_object_get_data(G_OBJECT(prev_column), PREF_NAME);
611 GtkTreeViewColumn *column,
612 const gchar *pref_name)
616 const gchar *col_name = pref_name;
618 ENTER(
"column %p, name %s", column, pref_name ? pref_name :
"(null)");
619 priv = GNC_TREE_VIEW_GET_PRIVATE(view);
622 if (g_object_get_data(G_OBJECT(column), ALWAYS_VISIBLE))
624 LEAVE(
"1, first column");
627 col_name = g_object_get_data(G_OBJECT(column), PREF_NAME);
628 DEBUG(
"col_name is %s", col_name ? col_name :
"(null)");
633 LEAVE(
"1, no pref name");
638 if (priv->state_section)
641 gchar *key = g_strdup_printf(
"%s_%s", col_name, STATE_KEY_SUFF_VISIBLE);
643 if (g_key_file_has_key (state_file, priv->state_section, key, NULL))
645 visible = g_key_file_get_boolean (state_file, priv->state_section, key, NULL);
647 LEAVE(
"%d, state defined visibility", visible);
654 (g_object_get_data(G_OBJECT(column), DEFAULT_VISIBLE) != NULL) : FALSE;
655 LEAVE(
"defaults says %d", visible);
670 gnc_tree_view_update_visibility (GtkTreeViewColumn *column,
677 g_return_if_fail(GTK_IS_TREE_VIEW_COLUMN(column));
678 g_return_if_fail(GNC_IS_TREE_VIEW(view));
681 priv = GNC_TREE_VIEW_GET_PRIVATE(view);
682 visible = gnc_tree_view_column_visible(view, column, NULL);
683 gtk_tree_view_column_set_visible(column, visible);
684 LEAVE(
"made %s", visible ?
"visible" :
"invisible");
701 GtkTreeModel *s_model;
704 gchar *order_str = NULL;
706 priv = GNC_TREE_VIEW_GET_PRIVATE(view);
707 s_model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
711 if (!gtk_tree_sortable_get_sort_column_id(GTK_TREE_SORTABLE(s_model),
715 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(s_model),
717 order_str = g_strdup (order == GTK_SORT_ASCENDING ?
"ascending" :
"descending");
718 DEBUG(
"current sort_order is %s", order_str);
734 GtkTreeModel *s_model;
735 GtkTreeViewColumn *column;
737 gint model_column, current;
740 s_model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
744 if (!gtk_tree_sortable_get_sort_column_id(GTK_TREE_SORTABLE(s_model),
748 column = view_column_find_by_model_id (view, current);
752 name = g_object_get_data(G_OBJECT(column), PREF_NAME);
753 DEBUG(
"current sort column is %s", name ? name :
"(NULL)");
754 return g_strdup (name);
776 gchar *col_names = NULL;
777 gchar **col_str_list;
782 columns = gtk_tree_view_get_columns (GTK_TREE_VIEW(view));
783 for (tmp = columns; tmp; tmp = g_list_next(tmp))
785 GtkTreeViewColumn *column = tmp->data;
786 const gchar *name = g_object_get_data(G_OBJECT(column), PREF_NAME);
788 col_names = g_strdup (name);
791 gchar *col_names_prev = col_names;
792 col_names = g_strjoin (
";", col_names_prev, name, NULL);
793 g_free (col_names_prev);
798 col_str_list = g_strsplit (col_names,
";", 0);
801 g_list_free(columns);
804 LEAVE(
"column order get");
824 GtkTreeModel *s_model;
825 GtkSortType order = GTK_SORT_ASCENDING;
828 priv = GNC_TREE_VIEW_GET_PRIVATE(view);
829 s_model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
832 if (g_strcmp0 (name,
"descending") == 0)
833 order = GTK_SORT_DESCENDING;
834 if (!gtk_tree_sortable_get_sort_column_id(GTK_TREE_SORTABLE(s_model),
836 current = GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID;
837 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(s_model),
839 DEBUG(
"sort_order set to %s", order == GTK_SORT_ASCENDING ?
"ascending" :
"descending");
854 GtkTreeModel *s_model;
855 GtkTreeViewColumn *column;
857 gint model_column, current;
859 s_model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
866 gtk_tree_sortable_set_sort_column_id(
867 GTK_TREE_SORTABLE(s_model), GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
873 GPOINTER_TO_INT(g_object_get_data(G_OBJECT(column), MODEL_COLUMN));
874 if (model_column == GNC_TREE_VIEW_COLUMN_DATA_NONE)
877 if (!gtk_tree_sortable_get_sort_column_id(GTK_TREE_SORTABLE(s_model),
879 order = GTK_SORT_ASCENDING;
881 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(s_model),
882 model_column, order);
883 DEBUG(
"sort column set to %s", name);
900 gchar **column_names,
904 GtkTreeViewColumn *column, *prev;
911 priv = GNC_TREE_VIEW_GET_PRIVATE(view);
913 for (idx = 0; idx < length; idx++)
915 const gchar *name = column_names[idx];
919 columns = g_slist_append(columns, column);
923 for (prev = NULL, tmp = columns; tmp; tmp = g_slist_next(tmp))
926 gtk_tree_view_move_column_after(GTK_TREE_VIEW(view), column, prev);
931 g_slist_free(columns);
932 LEAVE(
"column order set");
949 priv = GNC_TREE_VIEW_GET_PRIVATE(view);
950 if (!priv->state_section)
952 LEAVE(
"no state section");
956 g_key_file_remove_group (state_file, priv->state_section, NULL);
957 g_free(priv->state_section);
958 priv->state_section = NULL;
971 const gchar *section)
974 GKeyFile *state_file;
976 g_return_if_fail(GNC_IS_TREE_VIEW(view));
978 ENTER(
"view %p, section %s", view, section);
980 priv = GNC_TREE_VIEW_GET_PRIVATE(view);
983 if (priv->state_section)
988 LEAVE(
"cleared state section");
993 priv->state_section = g_strdup(section);
996 if (g_key_file_has_group (state_file, priv->state_section))
999 gchar **keys = g_key_file_get_keys (state_file, priv->state_section, &num_keys, NULL);
1000 for (idx = 0; idx < num_keys; idx++)
1002 gchar *key = keys[idx];
1003 if (g_strcmp0 (key, STATE_KEY_SORT_COLUMN) == 0)
1005 gnc_tree_view_set_sort_column (view,
1006 g_key_file_get_string (state_file, priv->state_section, key, NULL));
1008 else if (g_strcmp0 (key, STATE_KEY_SORT_ORDER) == 0)
1010 gnc_tree_view_set_sort_order (view,
1011 g_key_file_get_string (state_file, priv->state_section, key, NULL));
1013 else if (g_strcmp0 (key, STATE_KEY_COLUMN_ORDER) == 0)
1016 gchar **columns = g_key_file_get_string_list (state_file, priv->state_section,
1017 key, &length, NULL);
1018 gnc_tree_view_set_column_order (view, columns, length);
1019 g_strfreev (columns);
1025 gboolean known = FALSE;
1026 gchar *column_name = g_strdup (key);
1027 gchar *type_name = g_strrstr (column_name,
"_");
1028 *type_name++ =
'\0';
1030 if (g_strcmp0 (type_name, STATE_KEY_SUFF_VISIBLE) == 0)
1036 if (!g_object_get_data (G_OBJECT (column), ALWAYS_VISIBLE))
1038 gtk_tree_view_column_set_visible (column,
1039 g_key_file_get_boolean (state_file, priv->state_section, key, NULL));
1043 else if (g_strcmp0 (type_name, STATE_KEY_SUFF_WIDTH) == 0)
1045 gint width = g_key_file_get_integer (state_file, priv->state_section, key, NULL);
1050 if (width && (width != gtk_tree_view_column_get_width (column)))
1052 gtk_tree_view_column_set_fixed_width (column, width);
1057 DEBUG (
"Ignored key %s", key);
1059 g_free (column_name);
1065 gnc_tree_view_build_column_menu (view);
1066 LEAVE (
"set state section");
1080 g_return_val_if_fail (GNC_IS_TREE_VIEW (view), NULL);
1082 priv = GNC_TREE_VIEW_GET_PRIVATE (view);
1083 return priv->state_section;
1090 ENTER(
"view %p", view);
1091 g_return_if_fail (view != NULL);
1092 g_return_if_fail (GNC_IS_TREE_VIEW (view));
1094 priv = GNC_TREE_VIEW_GET_PRIVATE(view);
1096 if (priv->state_section)
1099 GList *column_list, *tmp;
1102 gchar *sort_column = gnc_tree_view_get_sort_column (view);
1103 gchar *sort_order = gnc_tree_view_get_sort_order (view);
1104 gchar **col_order = gnc_tree_view_get_column_order (view, &num_cols);
1109 gtk_tree_view_get_column (GTK_TREE_VIEW (view), 0)))
1110 g_key_file_set_string (state_file, priv->state_section, STATE_KEY_SORT_COLUMN, sort_column);
1111 else if (g_key_file_has_key (state_file, priv->state_section, STATE_KEY_SORT_COLUMN, NULL))
1112 g_key_file_remove_key (state_file, priv->state_section, STATE_KEY_SORT_COLUMN, NULL);
1113 g_free (sort_column);
1117 if (g_strcmp0 (sort_order,
"descending") == 0)
1118 g_key_file_set_string (state_file, priv->state_section, STATE_KEY_SORT_ORDER, sort_order);
1119 else if (g_key_file_has_key (state_file, priv->state_section, STATE_KEY_SORT_ORDER, NULL))
1120 g_key_file_remove_key (state_file, priv->state_section, STATE_KEY_SORT_ORDER, NULL);
1121 g_free (sort_order);
1123 if (col_order && (num_cols > 0))
1124 g_key_file_set_string_list (state_file, priv->state_section, STATE_KEY_COLUMN_ORDER,
1125 (
const gchar**) col_order, num_cols);
1126 else if (g_key_file_has_key (state_file, priv->state_section, STATE_KEY_COLUMN_ORDER, NULL))
1127 g_key_file_remove_key (state_file, priv->state_section, STATE_KEY_COLUMN_ORDER, NULL);
1131 column_list = gtk_tree_view_get_columns (GTK_TREE_VIEW (view));
1132 for (tmp = column_list; tmp; tmp = g_list_next (tmp))
1134 GtkTreeViewColumn *column = tmp->data;
1136 const gchar *name = g_object_get_data (G_OBJECT (column), PREF_NAME);
1140 if (!g_object_get_data (G_OBJECT (column), ALWAYS_VISIBLE))
1142 key = g_strjoin (
"_", name, STATE_KEY_SUFF_VISIBLE, NULL);
1143 g_key_file_set_boolean (state_file, priv->state_section, key,
1144 gtk_tree_view_column_get_visible (column));
1148 key = g_strjoin (
"_", name, STATE_KEY_SUFF_WIDTH, NULL);
1149 if (g_object_get_data (G_OBJECT(column),
"default-width") &&
1150 (GPOINTER_TO_INT((g_object_get_data (G_OBJECT(column),
"default-width")))
1151 != gtk_tree_view_column_get_width (column)))
1153 g_key_file_set_integer (state_file, priv->state_section, key,
1154 gtk_tree_view_column_get_width (column));
1156 else if (g_key_file_has_key (state_file, priv->state_section, key, NULL))
1157 g_key_file_remove_key (state_file, priv->state_section, key, NULL);
1160 g_list_free(column_list);
1192 gnc_tree_view_create_menu_item (GtkTreeViewColumn *column,
1197 const gchar *column_name, *pref_name;
1202 priv = GNC_TREE_VIEW_GET_PRIVATE(view);
1203 if (!priv->state_section)
1209 pref_name = g_object_get_data(G_OBJECT(column), PREF_NAME);
1217 if (!priv->column_menu)
1219 priv->column_menu = gtk_menu_new();
1220 g_object_ref_sink(priv->column_menu);
1224 column_name = g_object_get_data(G_OBJECT(column), REAL_TITLE);
1226 column_name = gtk_tree_view_column_get_title(column);
1227 widget = gtk_check_menu_item_new_with_label(column_name);
1228 gtk_menu_shell_append(GTK_MENU_SHELL(priv->column_menu), widget);
1231 if (g_object_get_data(G_OBJECT(column), ALWAYS_VISIBLE))
1233 g_object_set_data(G_OBJECT(widget), ALWAYS_VISIBLE, GINT_TO_POINTER(1));
1234 gtk_widget_set_sensitive(widget, FALSE);
1237 binding = g_object_bind_property (G_OBJECT (widget),
"active", G_OBJECT (column),
"visible", 0);
1238 g_object_set_data (G_OBJECT (widget),
"column-binding", binding);
1241 key = g_strdup_printf(
"%s_%s", pref_name, STATE_KEY_SUFF_VISIBLE);
1242 g_object_set_data_full(G_OBJECT(widget), STATE_KEY, key, g_free);
1258 gnc_tree_view_build_column_menu (
GncTreeView *view)
1263 g_return_if_fail(GNC_IS_TREE_VIEW(view));
1265 ENTER(
"view %p", view);
1266 priv = GNC_TREE_VIEW_GET_PRIVATE(view);
1269 if (priv->column_menu)
1271 g_object_unref(priv->column_menu);
1272 priv->column_menu = NULL;
1275 if (priv->show_column_menu && priv->state_section)
1278 if (priv->column_menu_column)
1279 gtk_tree_view_column_set_visible(priv->column_menu_column, TRUE);
1282 column_list = gtk_tree_view_get_columns(GTK_TREE_VIEW(view));
1283 g_list_foreach(column_list, (GFunc)gnc_tree_view_create_menu_item, view);
1284 g_list_free(column_list);
1289 if (priv->column_menu_column)
1290 gtk_tree_view_column_set_visible(priv->column_menu_column, FALSE);
1292 LEAVE(
"menu: show %d, section %s", priv->show_column_menu,
1293 priv->state_section ? priv->state_section :
"(null)");
1306 gnc_tree_view_update_column_menu_item (GtkCheckMenuItem *checkmenuitem,
1313 g_return_if_fail(GTK_IS_CHECK_MENU_ITEM(checkmenuitem));
1314 g_return_if_fail(GNC_IS_TREE_VIEW(view));
1316 priv = GNC_TREE_VIEW_GET_PRIVATE(view);
1317 key = g_object_get_data(G_OBJECT(checkmenuitem), STATE_KEY);
1318 if (g_object_get_data(G_OBJECT(checkmenuitem), ALWAYS_VISIBLE))
1324 GBinding *binding = g_object_get_data (G_OBJECT (checkmenuitem),
"column-binding");
1325 GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN(g_binding_get_target (binding));
1327 visible = gtk_tree_view_column_get_visible (column);
1330 gtk_check_menu_item_set_active(checkmenuitem, visible);
1346 gnc_tree_view_select_column_cb (GtkTreeViewColumn *column,
1352 g_return_if_fail(GTK_IS_TREE_VIEW_COLUMN(column));
1353 g_return_if_fail(GNC_IS_TREE_VIEW(view));
1355 priv = GNC_TREE_VIEW_GET_PRIVATE(view);
1356 menu = priv->column_menu;
1361 gtk_container_foreach(GTK_CONTAINER(menu),
1362 (GtkCallback)gnc_tree_view_update_column_menu_item,
1366 gtk_widget_show_all(menu);
1369 gtk_menu_popup(GTK_MENU(priv->column_menu), NULL, GTK_WIDGET(menu),
1370 NULL, NULL, 0, gtk_get_current_event_time());
1375 gchar *first_column_name,
1379 GtkTreeViewColumn *column;
1380 gboolean hide_spacer;
1381 GList *columns, *tmp;
1382 gchar *name, *pref_name;
1385 g_return_if_fail (GNC_IS_TREE_VIEW (view));
1387 va_start (args, first_column_name);
1388 priv = GNC_TREE_VIEW_GET_PRIVATE (view);
1389 name = first_column_name;
1390 hide_spacer = FALSE;
1393 columns = gtk_tree_view_get_columns(GTK_TREE_VIEW(view));
1394 for (tmp = columns; tmp; tmp = g_list_next(tmp))
1397 pref_name = g_object_get_data(G_OBJECT(column), PREF_NAME);
1398 if (pref_name != NULL)
1399 gtk_tree_view_column_set_expand(column, FALSE);
1401 g_list_free(columns);
1404 while (name != NULL)
1409 gtk_tree_view_column_set_expand(column, TRUE);
1412 name = va_arg (args, gchar*);
1416 gtk_tree_view_column_set_visible (priv->spacer_column, !hide_spacer);
1425 update_control_cell_renderers_background (
GncTreeView *view, GtkTreeViewColumn *col, gint column, GtkTreeCellDataFunc func )
1428 GtkCellRenderer *cell;
1431 renderers = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (col));
1434 for (node = renderers; node; node = node->next)
1438 gtk_tree_view_column_add_attribute (col, cell,
"cell-background", column);
1440 gtk_tree_view_column_set_cell_data_func (col, cell, func, view, NULL);
1442 g_list_free (renderers);
1453 g_return_if_fail (GNC_IS_TREE_VIEW (view));
1455 ENTER(
"view %p, column %d, func %p", view, column, func);
1456 priv = GNC_TREE_VIEW_GET_PRIVATE (view);
1458 update_control_cell_renderers_background (view, priv->spacer_column, column, func);
1459 update_control_cell_renderers_background (view, priv->selection_column, column, func);
1472 g_return_if_fail (GNC_IS_TREE_VIEW (view));
1474 ENTER(
"view %p, sort_model %p", view, s_model);
1475 priv = GNC_TREE_VIEW_GET_PRIVATE (view);
1477 priv->sort_model = s_model;
1494 g_return_if_fail(GNC_IS_TREE_VIEW(view));
1496 ENTER(
"view %p, show menu %d", view, visible);
1497 priv = GNC_TREE_VIEW_GET_PRIVATE(view);
1498 priv->show_column_menu = visible;
1499 gnc_tree_view_build_column_menu(view);
1514 g_return_val_if_fail(GNC_IS_TREE_VIEW(view), FALSE);
1516 priv = GNC_TREE_VIEW_GET_PRIVATE(view);
1517 return(priv->show_column_menu);
1527 gnc_tree_view_count_visible_columns(
GncTreeView *view)
1529 GList *columns, *node;
1532 columns = gtk_tree_view_get_columns(GTK_TREE_VIEW(view));
1533 for (node = columns; node; node = node->next)
1535 GtkTreeViewColumn *col = GTK_TREE_VIEW_COLUMN(node->data);
1537 if (g_object_get_data(G_OBJECT(col), DEFAULT_VISIBLE) ||
1538 g_object_get_data(G_OBJECT(col), ALWAYS_VISIBLE))
1541 g_list_free(columns);
1549 GtkTreeViewColumn *column;
1551 gboolean hide_spacer;
1553 g_return_if_fail(GNC_IS_TREE_VIEW(view));
1558 columns = gtk_tree_view_get_columns(GTK_TREE_VIEW(view));
1559 g_list_foreach(columns, (GFunc)gnc_tree_view_update_visibility, view);
1560 g_list_free(columns);
1562 priv = GNC_TREE_VIEW_GET_PRIVATE(view);
1563 if (priv->state_section)
1564 priv->seen_state_visibility = TRUE;
1568 hide_spacer = (gnc_tree_view_count_visible_columns(view) == 1);
1569 column = gtk_tree_view_get_column(GTK_TREE_VIEW(view), 0);
1570 gtk_tree_view_column_set_expand(column, hide_spacer);
1571 gtk_tree_view_column_set_visible(priv->spacer_column, !hide_spacer);
1572 gtk_tree_view_column_set_visible(priv->selection_column, !hide_spacer);
1608 gnc_tree_view_column_properties (
GncTreeView *view,
1609 GtkTreeViewColumn *column,
1610 const gchar *pref_name,
1614 GtkTreeIterCompareFunc column_sort_fn)
1617 GtkTreeModel *s_model;
1624 g_object_set_data(G_OBJECT(column), PREF_NAME, (gpointer)pref_name);
1625 if (data_column == 0)
1626 g_object_set_data(G_OBJECT(column), ALWAYS_VISIBLE, GINT_TO_POINTER(1));
1627 g_object_set_data(G_OBJECT(column), MODEL_COLUMN,
1628 GINT_TO_POINTER(data_column));
1631 visible = gnc_tree_view_column_visible(view, NULL, pref_name);
1634 g_object_set(G_OBJECT(column),
1636 "resizable", resizable && pref_name != NULL,
1637 "reorderable", pref_name != NULL,
1641 if (default_width == 0)
1644 g_object_set(G_OBJECT(column),
1645 "sizing", GTK_TREE_VIEW_COLUMN_AUTOSIZE,
1650 priv = GNC_TREE_VIEW_GET_PRIVATE(view);
1656 width = default_width + 10;
1661 g_object_set(G_OBJECT(column),
1662 "sizing", GTK_TREE_VIEW_COLUMN_FIXED,
1663 "fixed-width", width,
1670 g_object_set_data (G_OBJECT(column),
1671 "default-width", GINT_TO_POINTER (width));
1674 s_model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
1675 if (GTK_IS_TREE_SORTABLE(s_model))
1677 gtk_tree_view_column_set_sort_column_id (column, data_column);
1680 gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE(s_model),
1681 data_column, column_sort_fn,
1682 GINT_TO_POINTER(data_column),
1688 priv = GNC_TREE_VIEW_GET_PRIVATE(view);
1689 if (priv->sort_model != NULL)
1691 gtk_tree_view_column_set_sort_column_id (column, data_column);
1694 gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE(priv->sort_model),
1695 data_column, column_sort_fn,
1704 gnc_tree_view_create_menu_item(column, view);
1720 const gchar *column_title,
1721 const gchar *column_short_title,
1722 const gchar *pref_name,
1723 gint model_data_column,
1724 gint model_visibility_column,
1725 GtkTreeIterCompareFunc column_sort_fn,
1726 renderer_toggled toggle_edited_cb)
1728 GtkTreeViewColumn *column;
1729 GtkCellRenderer *renderer;
1731 g_return_val_if_fail (GNC_IS_TREE_VIEW(view), NULL);
1733 renderer = gtk_cell_renderer_toggle_new ();
1735 gtk_tree_view_column_new_with_attributes (column_short_title,
1737 "active", model_data_column,
1741 g_object_set_data_full(G_OBJECT(column), REAL_TITLE,
1742 g_strdup(column_title), g_free);
1743 if (toggle_edited_cb)
1744 g_signal_connect(G_OBJECT(renderer),
"toggled",
1745 G_CALLBACK(toggle_edited_cb), view);
1747 if (model_visibility_column != GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS)
1748 gtk_tree_view_column_add_attribute (column, renderer,
1749 "visible", model_visibility_column);
1752 gnc_tree_view_column_properties (view, column, pref_name, model_data_column,
1753 0, FALSE, column_sort_fn);
1758 gtk_widget_set_tooltip_text(column->button, column_title);
1773 const gchar *column_title,
1774 const gchar *pref_name,
1775 const gchar *stock_icon_name,
1776 const gchar *sizing_text,
1777 gint model_data_column,
1778 gint model_visibility_column,
1779 GtkTreeIterCompareFunc column_sort_fn)
1781 GtkTreeViewColumn *column;
1782 GtkCellRenderer *renderer;
1783 PangoLayout* layout;
1784 int default_width, title_width;
1786 g_return_val_if_fail (GNC_IS_TREE_VIEW(view), NULL);
1788 column = gtk_tree_view_column_new ();
1789 gtk_tree_view_column_set_title (column, column_title);
1792 if (stock_icon_name)
1794 renderer = gtk_cell_renderer_pixbuf_new ();
1795 g_object_set (renderer,
"stock-id", stock_icon_name, NULL);
1796 gtk_tree_view_column_pack_start (column, renderer, FALSE);
1800 renderer = gtk_cell_renderer_text_new ();
1801 gtk_tree_view_column_pack_start (column, renderer, TRUE);
1804 if (model_data_column != GNC_TREE_VIEW_COLUMN_DATA_NONE)
1805 gtk_tree_view_column_add_attribute (column, renderer,
1806 "text", model_data_column);
1807 if (model_visibility_column != GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS)
1808 gtk_tree_view_column_add_attribute (column, renderer,
1809 "visible", model_visibility_column);
1812 layout = gtk_widget_create_pango_layout (GTK_WIDGET(view), column_title);
1813 pango_layout_get_pixel_size(layout, &title_width, NULL);
1814 g_object_unref(layout);
1815 layout = gtk_widget_create_pango_layout (GTK_WIDGET(view), sizing_text);
1816 pango_layout_get_pixel_size(layout, &default_width, NULL);
1817 g_object_unref(layout);
1818 default_width = MAX(default_width, title_width);
1820 default_width += 10;
1821 gnc_tree_view_column_properties (view, column, pref_name, model_data_column,
1822 default_width, TRUE, column_sort_fn);
1840 const gchar *column_title,
1841 const gchar *pref_name,
1842 const gchar *stock_icon_name,
1843 const gchar *sizing_text,
1844 gint model_data_column,
1845 gint model_visibility_column,
1846 GtkTreeIterCompareFunc column_sort_fn)
1848 GtkTreeViewColumn *column;
1849 GtkCellRenderer *renderer;
1850 PangoLayout* layout;
1851 int default_width, title_width;
1853 g_return_val_if_fail (GNC_IS_TREE_VIEW(view), NULL);
1855 column = gtk_tree_view_column_new ();
1856 gtk_tree_view_column_set_title (column, column_title);
1859 if (stock_icon_name)
1861 renderer = gtk_cell_renderer_pixbuf_new ();
1862 g_object_set (renderer,
"stock-id", stock_icon_name, NULL);
1863 gtk_tree_view_column_pack_start (column, renderer, FALSE);
1867 renderer = gnc_cell_renderer_date_new(TRUE);
1868 gtk_tree_view_column_pack_start (column, renderer, TRUE);
1871 if (model_data_column != GNC_TREE_VIEW_COLUMN_DATA_NONE)
1872 gtk_tree_view_column_add_attribute (column, renderer,
1873 "text", model_data_column);
1874 if (model_visibility_column != GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS)
1875 gtk_tree_view_column_add_attribute (column, renderer,
1876 "visible", model_visibility_column);
1879 layout = gtk_widget_create_pango_layout (GTK_WIDGET(view), column_title);
1880 pango_layout_get_pixel_size(layout, &title_width, NULL);
1881 g_object_unref(layout);
1882 layout = gtk_widget_create_pango_layout (GTK_WIDGET(view), sizing_text);
1883 pango_layout_get_pixel_size(layout, &default_width, NULL);
1884 g_object_unref(layout);
1885 default_width = MAX(default_width, title_width);
1887 default_width += 10;
1888 gnc_tree_view_column_properties (view, column, pref_name, model_data_column,
1889 default_width, TRUE, column_sort_fn);
1898 const gchar *column_title,
1899 const gchar *pref_name,
1900 const gchar *sizing_text,
1901 gint model_data_column,
1902 gint model_visibility_column,
1903 GtkTreeModel *combo_tree_model,
1904 gint combo_model_text_column,
1905 GtkTreeIterCompareFunc column_sort_fn)
1907 GtkTreeViewColumn *column;
1908 GtkCellRenderer *renderer;
1909 PangoLayout* layout;
1910 int default_width, title_width;
1912 g_return_val_if_fail (GNC_IS_TREE_VIEW(view), NULL);
1914 column = gtk_tree_view_column_new ();
1915 gtk_tree_view_column_set_title (column, gettext(column_title));
1918 renderer = gtk_cell_renderer_combo_new ();
1919 gtk_tree_view_column_pack_start (column, renderer, TRUE);
1922 if (model_data_column != GNC_TREE_VIEW_COLUMN_DATA_NONE)
1923 gtk_tree_view_column_add_attribute (column, renderer,
1924 "text", model_data_column);
1925 if (model_visibility_column != GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS)
1926 gtk_tree_view_column_add_attribute (column, renderer,
1927 "visible", model_visibility_column);
1930 layout = gtk_widget_create_pango_layout (GTK_WIDGET(view), column_title);
1931 pango_layout_get_pixel_size(layout, &title_width, NULL);
1932 g_object_unref(layout);
1933 layout = gtk_widget_create_pango_layout (GTK_WIDGET(view), sizing_text);
1934 pango_layout_get_pixel_size(layout, &default_width, NULL);
1935 g_object_unref(layout);
1936 default_width = MAX(default_width, title_width);
1938 default_width += 10;
1940 gnc_tree_view_column_properties (view, column, pref_name, model_data_column,
1941 default_width, TRUE, column_sort_fn);
1944 if (combo_tree_model)
1946 g_object_set(G_OBJECT(renderer),
"model", combo_tree_model,
1947 "text-column", combo_model_text_column, NULL);
1959 GtkCellRenderer *cr = NULL;
1961 g_return_val_if_fail(GTK_TREE_VIEW_COLUMN(column), NULL);
1964 renderers = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(column));
1965 if (g_list_length(renderers) > 0)
1966 cr = GTK_CELL_RENDERER(renderers->data);
1967 g_list_free(renderers);
1984 const gchar *column_title,
1985 const gchar *pref_name,
1986 const gchar *sizing_text,
1987 gint model_data_column,
1988 gint model_color_column,
1989 gint model_visibility_column,
1990 GtkTreeIterCompareFunc column_sort_fn)
1992 GtkTreeViewColumn *column;
1993 GtkCellRenderer *renderer;
1996 NULL, sizing_text, model_data_column,
1997 model_visibility_column,
2003 g_object_set(G_OBJECT(column),
"alignment", 1.0, NULL);
2004 g_object_set(G_OBJECT(renderer),
"xalign", 1.0, NULL);
2007 if (model_color_column != GNC_TREE_VIEW_COLUMN_COLOR_NONE)
2008 gtk_tree_view_column_add_attribute (column, renderer,
2009 "foreground", model_color_column);
2024 GtkTreeViewColumn *column)
2030 columns = gtk_tree_view_get_columns(GTK_TREE_VIEW(view));
2031 n = g_list_length(columns);
2032 g_list_free(columns);
2037 return gtk_tree_view_insert_column (GTK_TREE_VIEW(view), column, n);
2041 get_column_next_to(GtkTreeView *tv, GtkTreeViewColumn **col, gboolean backward)
2044 GtkTreeViewColumn *c = NULL;
2046 gboolean wrapped = FALSE;
2048 cols = gtk_tree_view_get_columns(tv);
2049 g_return_val_if_fail(g_list_length(cols) > 0, FALSE);
2051 node = g_list_find(cols, *col);
2052 g_return_val_if_fail(node, FALSE);
2055 node = backward ? node->prev : node->next;
2059 node = backward ? g_list_last(cols) : cols;
2061 c = GTK_TREE_VIEW_COLUMN(node->data);
2062 if (c && gtk_tree_view_column_get_visible(c))
2064 if (c == *col)
break;
2074 gnc_tree_view_path_is_valid(
GncTreeView *view, GtkTreePath *path)
2076 GtkTreeView *tv = GTK_TREE_VIEW(view);
2077 GtkTreeModel *s_model;
2080 s_model = gtk_tree_view_get_model(tv);
2081 return gtk_tree_model_get_iter(s_model, &iter, path);
2085 gnc_tree_view_keynav(
GncTreeView *view, GtkTreeViewColumn **col,
2086 GtkTreePath *path, GdkEventKey *event)
2088 GtkTreeView *tv = GTK_TREE_VIEW(view);
2092 if (event->type != GDK_KEY_PRESS)
return;
2094 switch (event->keyval)
2097 case GDK_ISO_Left_Tab:
2099 shifted =
event->state & GDK_SHIFT_MASK;
2100 if (get_column_next_to(tv, col, shifted))
2103 depth = gtk_tree_path_get_depth(path);
2106 if (!gtk_tree_path_prev(path) && depth > 1)
2108 gtk_tree_path_up(path);
2111 else if (gtk_tree_view_row_expanded(tv, path))
2113 gtk_tree_path_down(path);
2117 gtk_tree_path_next(path);
2118 if (!gnc_tree_view_path_is_valid(view, path) && depth > 2)
2120 gtk_tree_path_prev(path);
2121 gtk_tree_path_up(path);
2122 gtk_tree_path_next(path);
2124 if (!gnc_tree_view_path_is_valid(view, path) && depth > 1)
2126 gtk_tree_path_prev(path);
2127 gtk_tree_path_up(path);
2128 gtk_tree_path_next(path);
2136 if (gtk_tree_view_row_expanded(tv, path))
2138 gtk_tree_path_down(path);
2142 depth = gtk_tree_path_get_depth(path);
2143 gtk_tree_path_next(path);
2144 if (!gnc_tree_view_path_is_valid(view, path) && depth > 1)
2146 gtk_tree_path_prev(path);
2147 gtk_tree_path_up(path);
2148 gtk_tree_path_next(path);
void gnc_tree_view_set_sort_user_data(GncTreeView *view, GtkTreeModel *s_model)
Functions to load, save and get gui state.
void gnc_tree_view_expand_columns(GncTreeView *view, gchar *first_column_name,...)
GtkTreeViewColumn * gnc_tree_view_add_text_column(GncTreeView *view, const gchar *column_title, const gchar *pref_name, const gchar *stock_icon_name, const gchar *sizing_text, gint model_data_column, gint model_visibility_column, GtkTreeIterCompareFunc column_sort_fn)
void gnc_gobject_tracking_remember(GObject *object, GObjectClass *klass)
void gnc_gobject_tracking_forget(GObject *object)
common utilities for manipulating a GtkTreeView within gnucash
#define DEBUG(format, args...)
gboolean gnc_tree_view_get_show_column_menu(GncTreeView *view)
GtkTreeViewColumn * gnc_tree_view_add_combo_column(GncTreeView *view, const gchar *column_title, const gchar *pref_name, const gchar *sizing_text, gint model_data_column, gint model_visibility_column, GtkTreeModel *combo_tree_model, gint combo_model_text_column, GtkTreeIterCompareFunc column_sort_fn)
void gnc_tree_view_remove_state_information(GncTreeView *view)
void gnc_tree_view_set_show_column_menu(GncTreeView *view, gboolean visible)
GtkTreeViewColumn * gnc_tree_view_add_numeric_column(GncTreeView *view, const gchar *column_title, const gchar *pref_name, const gchar *sizing_text, gint model_data_column, gint model_color_column, gint model_visibility_column, GtkTreeIterCompareFunc column_sort_fn)
GtkTreeViewColumn * gnc_tree_view_find_column_by_name(GncTreeView *view, const gchar *wanted)
#define ENTER(format, args...)
GKeyFile * gnc_state_get_current(void)
gint gnc_tree_view_append_column(GncTreeView *view, GtkTreeViewColumn *column)
GtkTreeViewColumn * gnc_tree_view_add_toggle_column(GncTreeView *view, const gchar *column_title, const gchar *column_short_title, const gchar *pref_name, gint model_data_column, gint model_visibility_column, GtkTreeIterCompareFunc column_sort_fn, renderer_toggled toggle_edited_cb)
GtkCellRenderer * gnc_tree_view_column_get_renderer(GtkTreeViewColumn *column)
GtkTreeViewColumn * gnc_tree_view_add_date_column(GncTreeView *view, const gchar *column_title, const gchar *pref_name, const gchar *stock_icon_name, const gchar *sizing_text, gint model_data_column, gint model_visibility_column, GtkTreeIterCompareFunc column_sort_fn)
void gnc_tree_view_configure_columns(GncTreeView *view)
void gnc_tree_view_save_state(GncTreeView *view)
void gnc_tree_view_set_control_column_background(GncTreeView *view, gint column, GtkTreeCellDataFunc func)
Gnome specific utility functions.
All type declarations for the whole Gnucash engine.
const gchar * gnc_tree_view_get_state_section(GncTreeView *view)
void gnc_tree_view_set_state_section(GncTreeView *view, const gchar *section)
GType gnc_tree_view_get_type(void)
struct GncTreeViewPrivate GncTreeViewPrivate
#define LEAVE(format, args...)
const gchar * QofLogModule