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