1 | /* Tree View/Filter Model |
2 | * #Keywords: GtkTreeView |
3 | * |
4 | * This example demonstrates how GtkTreeModelFilter can be used not |
5 | * just to show a subset of the rows, but also to compute columns |
6 | * that are not actually present in the underlying model. |
7 | */ |
8 | |
9 | #include <gtk/gtk.h> |
10 | #include <stdlib.h> |
11 | |
12 | enum { |
13 | WIDTH_COLUMN, |
14 | HEIGHT_COLUMN, |
15 | AREA_COLUMN, |
16 | SQUARE_COLUMN |
17 | }; |
18 | |
19 | static void |
20 | format_number (GtkTreeViewColumn *col, |
21 | GtkCellRenderer *cell, |
22 | GtkTreeModel *model, |
23 | GtkTreeIter *iter, |
24 | gpointer data) |
25 | { |
26 | int num; |
27 | char *text; |
28 | |
29 | gtk_tree_model_get (tree_model: model, iter, GPOINTER_TO_INT (data), &num, -1); |
30 | text = g_strdup_printf (format: "%d" , num); |
31 | g_object_set (object: cell, first_property_name: "text" , text, NULL); |
32 | g_free (mem: text); |
33 | } |
34 | |
35 | static void |
36 | filter_modify_func (GtkTreeModel *model, |
37 | GtkTreeIter *iter, |
38 | GValue *value, |
39 | int column, |
40 | gpointer data) |
41 | { |
42 | GtkTreeModelFilter *filter_model = GTK_TREE_MODEL_FILTER (model); |
43 | int width, height; |
44 | GtkTreeModel *child_model; |
45 | GtkTreeIter child_iter; |
46 | |
47 | child_model = gtk_tree_model_filter_get_model (filter: filter_model); |
48 | gtk_tree_model_filter_convert_iter_to_child_iter (filter: filter_model, child_iter: &child_iter, filter_iter: iter); |
49 | |
50 | gtk_tree_model_get (tree_model: child_model, iter: &child_iter, |
51 | WIDTH_COLUMN, &width, |
52 | HEIGHT_COLUMN, &height, |
53 | -1); |
54 | |
55 | switch (column) |
56 | { |
57 | case WIDTH_COLUMN: |
58 | g_value_set_int (value, v_int: width); |
59 | break; |
60 | case HEIGHT_COLUMN: |
61 | g_value_set_int (value, v_int: height); |
62 | break; |
63 | case AREA_COLUMN: |
64 | g_value_set_int (value, v_int: width * height); |
65 | break; |
66 | case SQUARE_COLUMN: |
67 | g_value_set_boolean (value, v_boolean: width == height); |
68 | break; |
69 | default: |
70 | g_assert_not_reached (); |
71 | } |
72 | } |
73 | |
74 | static gboolean |
75 | visible_func (GtkTreeModel *model, |
76 | GtkTreeIter *iter, |
77 | gpointer data) |
78 | { |
79 | int width; |
80 | |
81 | gtk_tree_model_get (tree_model: model, iter, |
82 | WIDTH_COLUMN, &width, |
83 | -1); |
84 | |
85 | return width < 10; |
86 | } |
87 | |
88 | static void |
89 | cell_edited (GtkCellRendererSpin *cell, |
90 | const char *path_string, |
91 | const char *new_text, |
92 | GtkListStore *store) |
93 | { |
94 | int val; |
95 | GtkTreePath *path; |
96 | GtkTreeIter iter; |
97 | int column; |
98 | |
99 | path = gtk_tree_path_new_from_string (path: path_string); |
100 | gtk_tree_model_get_iter (GTK_TREE_MODEL (store), iter: &iter, path); |
101 | gtk_tree_path_free (path); |
102 | |
103 | column = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (cell), "column" )); |
104 | |
105 | val = atoi (nptr: new_text); |
106 | |
107 | gtk_list_store_set (list_store: store, iter: &iter, column, val, -1); |
108 | } |
109 | |
110 | GtkWidget * |
111 | do_filtermodel (GtkWidget *do_widget) |
112 | { |
113 | static GtkWidget *window; |
114 | GtkWidget *tree; |
115 | GtkListStore *store; |
116 | GtkTreeModel *model; |
117 | GtkTreeViewColumn *column; |
118 | GtkCellRenderer *cell; |
119 | GType types[4]; |
120 | |
121 | if (!window) |
122 | { |
123 | GtkBuilder *builder; |
124 | |
125 | builder = gtk_builder_new_from_resource (resource_path: "/filtermodel/filtermodel.ui" ); |
126 | window = GTK_WIDGET (gtk_builder_get_object (builder, "window1" )); |
127 | gtk_window_set_display (GTK_WINDOW (window), |
128 | display: gtk_widget_get_display (widget: do_widget)); |
129 | g_object_add_weak_pointer (G_OBJECT (window), weak_pointer_location: (gpointer *)&window); |
130 | |
131 | store = (GtkListStore*)gtk_builder_get_object (builder, name: "liststore1" ); |
132 | |
133 | column = (GtkTreeViewColumn*)gtk_builder_get_object (builder, name: "treeviewcolumn1" ); |
134 | cell = (GtkCellRenderer*)gtk_builder_get_object (builder, name: "cellrenderertext1" ); |
135 | gtk_tree_view_column_set_cell_data_func (tree_column: column, cell_renderer: cell, |
136 | func: format_number, GINT_TO_POINTER (WIDTH_COLUMN), NULL); |
137 | g_object_set_data (G_OBJECT (cell), key: "column" , GINT_TO_POINTER (WIDTH_COLUMN)); |
138 | g_signal_connect (cell, "edited" , G_CALLBACK (cell_edited), store); |
139 | |
140 | column = (GtkTreeViewColumn*)gtk_builder_get_object (builder, name: "treeviewcolumn2" ); |
141 | cell = (GtkCellRenderer*)gtk_builder_get_object (builder, name: "cellrenderertext2" ); |
142 | gtk_tree_view_column_set_cell_data_func (tree_column: column, cell_renderer: cell, |
143 | func: format_number, GINT_TO_POINTER (HEIGHT_COLUMN), NULL); |
144 | g_object_set_data (G_OBJECT (cell), key: "column" , GINT_TO_POINTER (HEIGHT_COLUMN)); |
145 | g_signal_connect (cell, "edited" , G_CALLBACK (cell_edited), store); |
146 | |
147 | column = (GtkTreeViewColumn*)gtk_builder_get_object (builder, name: "treeviewcolumn3" ); |
148 | cell = (GtkCellRenderer*)gtk_builder_get_object (builder, name: "cellrenderertext3" ); |
149 | gtk_tree_view_column_set_cell_data_func (tree_column: column, cell_renderer: cell, |
150 | func: format_number, GINT_TO_POINTER (WIDTH_COLUMN), NULL); |
151 | |
152 | column = (GtkTreeViewColumn*)gtk_builder_get_object (builder, name: "treeviewcolumn4" ); |
153 | cell = (GtkCellRenderer*)gtk_builder_get_object (builder, name: "cellrenderertext4" ); |
154 | gtk_tree_view_column_set_cell_data_func (tree_column: column, cell_renderer: cell, |
155 | func: format_number, GINT_TO_POINTER (HEIGHT_COLUMN), NULL); |
156 | |
157 | column = (GtkTreeViewColumn*)gtk_builder_get_object (builder, name: "treeviewcolumn5" ); |
158 | cell = (GtkCellRenderer*)gtk_builder_get_object (builder, name: "cellrenderertext5" ); |
159 | gtk_tree_view_column_set_cell_data_func (tree_column: column, cell_renderer: cell, |
160 | func: format_number, GINT_TO_POINTER (AREA_COLUMN), NULL); |
161 | |
162 | column = (GtkTreeViewColumn*)gtk_builder_get_object (builder, name: "treeviewcolumn6" ); |
163 | cell = (GtkCellRenderer*)gtk_builder_get_object (builder, name: "cellrendererpixbuf1" ); |
164 | gtk_tree_view_column_add_attribute (tree_column: column, cell_renderer: cell, attribute: "visible" , column: SQUARE_COLUMN); |
165 | |
166 | tree = (GtkWidget*)gtk_builder_get_object (builder, name: "treeview2" ); |
167 | |
168 | types[WIDTH_COLUMN] = G_TYPE_INT; |
169 | types[HEIGHT_COLUMN] = G_TYPE_INT; |
170 | types[AREA_COLUMN] = G_TYPE_INT; |
171 | types[SQUARE_COLUMN] = G_TYPE_BOOLEAN; |
172 | model = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL); |
173 | gtk_tree_model_filter_set_modify_func (GTK_TREE_MODEL_FILTER (model), |
174 | G_N_ELEMENTS (types), types, |
175 | func: filter_modify_func, NULL, NULL); |
176 | |
177 | gtk_tree_view_set_model (GTK_TREE_VIEW (tree), model); |
178 | |
179 | column = (GtkTreeViewColumn*)gtk_builder_get_object (builder, name: "treeviewcolumn7" ); |
180 | cell = (GtkCellRenderer*)gtk_builder_get_object (builder, name: "cellrenderertext6" ); |
181 | gtk_tree_view_column_set_cell_data_func (tree_column: column, cell_renderer: cell, |
182 | func: format_number, GINT_TO_POINTER (WIDTH_COLUMN), NULL); |
183 | |
184 | column = (GtkTreeViewColumn*)gtk_builder_get_object (builder, name: "treeviewcolumn8" ); |
185 | cell = (GtkCellRenderer*)gtk_builder_get_object (builder, name: "cellrenderertext7" ); |
186 | gtk_tree_view_column_set_cell_data_func (tree_column: column, cell_renderer: cell, |
187 | func: format_number, GINT_TO_POINTER (HEIGHT_COLUMN), NULL); |
188 | |
189 | tree = (GtkWidget*)gtk_builder_get_object (builder, name: "treeview3" ); |
190 | |
191 | model = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL); |
192 | gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (model), |
193 | func: visible_func, NULL, NULL); |
194 | gtk_tree_view_set_model (GTK_TREE_VIEW (tree), model); |
195 | |
196 | g_object_unref (object: builder); |
197 | } |
198 | |
199 | if (!gtk_widget_get_visible (widget: window)) |
200 | gtk_widget_show (widget: window); |
201 | else |
202 | gtk_window_destroy (GTK_WINDOW (window)); |
203 | |
204 | return window; |
205 | } |
206 | |