gerbv  2.6A
table.c
Go to the documentation of this file.
1 
6 #include <glib-object.h>
7 #include <gtk/gtk.h>
8 #include <string.h>
9 
10 #include "table.h"
11 
12 static gint compare_uint(GtkTreeModel *model,
13  GtkTreeIter *a, GtkTreeIter *b,
14  gpointer p)
15 {
16  gint sort_col = GPOINTER_TO_INT(p);
17  guint no1, no2;
18 
19  gtk_tree_model_get(model, a, sort_col, &no1, -1);
20  gtk_tree_model_get(model, b, sort_col, &no2, -1);
21 
22  return no1 - no2;
23 }
24 
25 static gint compare_int(GtkTreeModel *model,
26  GtkTreeIter *a, GtkTreeIter *b,
27  gpointer p)
28 {
29  gint sort_col = GPOINTER_TO_INT(p);
30  gint no1, no2;
31 
32  gtk_tree_model_get(model, a, sort_col, &no1, -1);
33  gtk_tree_model_get(model, b, sort_col, &no2, -1);
34 
35  return no1 - no2;
36 }
37 
38 static gint compare_double(GtkTreeModel *model,
39  GtkTreeIter *a, GtkTreeIter *b,
40  gpointer p)
41 {
42  gint sort_col = GPOINTER_TO_INT(p);
43  double no1, no2;
44 
45  gtk_tree_model_get(model, a, sort_col, &no1, -1);
46  gtk_tree_model_get(model, b, sort_col, &no2, -1);
47 
48  if (no1 > no2)
49  return 1;
50 
51  if (no1 < no2)
52  return -1;
53 
54  return 0;
55 }
56 
57 static gint compare_str(GtkTreeModel *model,
58  GtkTreeIter *a, GtkTreeIter *b,
59  gpointer p)
60 {
61  gint sort_col = GPOINTER_TO_INT(p);
62  gchar *str1, *str2;
63  gint ret;
64 
65  /* TODO: rewrite and sort D1 -- D10 */
66 
67  gtk_tree_model_get(model, a, sort_col, &str1, -1);
68  gtk_tree_model_get(model, b, sort_col, &str2, -1);
69 
70  if (str1 == NULL || str2 == NULL) {
71  if (str1 == NULL && str2 == NULL)
72  return 0;
73 
74  ret = (str1 == NULL) ? -1 : 1;
75  } else {
76  ret = g_utf8_collate(str1, str2);
77  }
78 
79  g_free(str1);
80  g_free(str2);
81 
82  return ret;
83 }
84 
85 /* ... is (char *)title / (GType)type pairs */
86 struct table *table_new_with_columns(gint col_nums, ...)
87 {
88  struct table *table;
89  GtkTreeViewColumn *column;
90  const char *titles[col_nums];
91  va_list args;
92  gint i;
93 
94  if (col_nums == 0)
95  return NULL;
96 
97  va_start(args, col_nums);
98  table = g_new(struct table, 1);
99  table->types = g_new(GType, col_nums);
100  for (i = 0; i < col_nums; i++) {
101  titles[i] = va_arg(args, const char *);
102  table->types[i] = va_arg(args, GType);
103  }
104  va_end(args);
105 
106  table->column_nums = col_nums;
107  table->list_store = gtk_list_store_newv(col_nums, table->types);
108  table->widget = gtk_tree_view_new_with_model(
109  GTK_TREE_MODEL(table->list_store));
110  /* Auto free tree_model at tree_view destruction */
111  g_object_unref(GTK_TREE_MODEL(table->list_store));
112 
113  table->renderers = g_new(GtkCellRenderer *, col_nums);
114  for (i = 0; i < col_nums; i++) {
115  table->renderers[i] = gtk_cell_renderer_text_new();
116  column = gtk_tree_view_column_new();
117  gtk_tree_view_column_set_title(column, titles[i]);
118  gtk_tree_view_column_pack_start(column,
119  table->renderers[i], FALSE);
120  /* TODO: get "text" attribute by types[i] function? */
121  gtk_tree_view_column_add_attribute(column,
122  table->renderers[i], "text", i);
123  gtk_tree_view_append_column(GTK_TREE_VIEW(table->widget), column);
124  }
125 
126  return table;
127 }
128 
129 void table_destroy(struct table *table)
130 {
131  gtk_widget_destroy(table->widget);
132  g_free(table->types);
133  g_free(table);
134 }
135 
136 void table_set_sortable(struct table *table)
137 {
138  GtkTreeSortable *sortable = GTK_TREE_SORTABLE(table->list_store);
139  GtkTreeViewColumn *column;
140  gint i, first_sort_col = -1;
141 
142  for (i = 0; i < table->column_nums; i++) {
143  column = gtk_tree_view_get_column(
144  GTK_TREE_VIEW(table->widget), i);
145  switch (table->types[i]) {
146  case G_TYPE_UINT:
147  gtk_tree_sortable_set_sort_func(sortable, i,
148  &compare_uint, GINT_TO_POINTER(i),
149  NULL);
150  if (first_sort_col == -1)
151  first_sort_col = i;
152  break;
153  case G_TYPE_INT:
154  gtk_tree_sortable_set_sort_func(sortable, i,
155  &compare_int, GINT_TO_POINTER(i),
156  NULL);
157  if (first_sort_col == -1)
158  first_sort_col = i;
159  break;
160  case G_TYPE_DOUBLE:
161  gtk_tree_sortable_set_sort_func(sortable, i,
162  &compare_double, GINT_TO_POINTER(i),
163  NULL);
164  if (first_sort_col == -1)
165  first_sort_col = i;
166  break;
167  case G_TYPE_STRING:
168  gtk_tree_sortable_set_sort_func(sortable, i,
169  &compare_str, GINT_TO_POINTER(i),
170  NULL);
171  if (first_sort_col == -1)
172  first_sort_col = i;
173  break;
174  }
175 
176  switch (table->types[i]) {
177  case G_TYPE_UINT:
178  case G_TYPE_INT:
179  case G_TYPE_DOUBLE:
180  case G_TYPE_STRING:
181  gtk_tree_view_column_set_sort_column_id(column, i);
182  }
183  }
184 
185  if (first_sort_col != -1)
186  gtk_tree_sortable_set_sort_column_id(sortable,
187  first_sort_col, GTK_SORT_ASCENDING);
188 }
189 
190 /* Set column alignment:
191  0.0 -- left, 0.5 -- center, 1.0 -- right */
192 void table_set_column_align(struct table *table, gint column_num, gfloat align)
193 {
194  g_object_set(G_OBJECT(table->renderers[column_num]),
195  "xalign", align, NULL);
196 }
197 
198 /* ... is values with types as in table_new_with_columns() */
199 int table_add_row(struct table *table, ...)
200 {
201  GtkTreeIter iter;
202  GValue val;
203  va_list args;
204  gint i;
205 
206  g_type_init();
207 
208  va_start(args, table);
209  gtk_list_store_append(table->list_store, &iter);
210  for (i = 0; i < table->column_nums; i++) {
211  memset(&val, 0, sizeof(GValue));
212  g_value_init(&val, table->types[i]);
213  switch (table->types[i]) {
214  case G_TYPE_STRING:
215  g_value_set_static_string(&val,
216  va_arg(args, const char *));
217  break;
218  case G_TYPE_INT:
219  g_value_set_int(&val, va_arg(args, int));
220  break;
221  case G_TYPE_UINT:
222  g_value_set_uint(&val, va_arg(args, unsigned int));
223  break;
224  case G_TYPE_DOUBLE:
225  g_value_set_double(&val, va_arg(args, double));
226  break;
227  default:
228  g_assert_not_reached();
229  }
230  gtk_list_store_set_value(table->list_store, &iter, i, &val);
231  }
232  va_end(args);
233 
234  return 0;
235 }