| 90 tableview->ondragcompletedata = args->ondragcompletedata; |
90 tableview->ondragcompletedata = args->ondragcompletedata; |
| 91 tableview->ondrop = args->ondrop; |
91 tableview->ondrop = args->ondrop; |
| 92 tableview->ondropdata = args->ondropdata; |
92 tableview->ondropdata = args->ondropdata; |
| 93 tableview->selection.count = 0; |
93 tableview->selection.count = 0; |
| 94 tableview->selection.rows = NULL; |
94 tableview->selection.rows = NULL; |
| |
95 tableview->current_row = -1; |
| |
96 tableview->getstyle = args->getstyle; |
| |
97 tableview->getstyledata = args->getstyledata; |
| |
98 tableview->onsave = args->onsave; |
| |
99 tableview->onsavedata = args->onsavedata; |
| 95 |
100 |
| 96 if(args->getvalue2) { |
101 if(args->getvalue2) { |
| 97 tableview->getvalue = args->getvalue2; |
102 tableview->getvalue = args->getvalue2; |
| 98 tableview->getvaluedata = args->getvalue2data; |
103 tableview->getvaluedata = args->getvalue2data; |
| 99 } else if(args->getvalue) { |
104 } else if(args->getvalue) { |
| 100 tableview->getvalue = getvalue_wrapper; |
105 tableview->getvalue = getvalue_wrapper; |
| 101 tableview->getvaluedata = (void*)args->getvalue; |
106 tableview->getvaluedata = (void*)args->getvalue; |
| 102 } else { |
107 } else { |
| 103 tableview->getvalue = null_getvalue; |
108 tableview->getvalue = null_getvalue; |
| 104 } |
109 } |
| 105 |
110 |
| 106 return tableview; |
111 return tableview; |
| 107 } |
112 } |
| 108 |
113 |
| 109 #if GTK_CHECK_VERSION(4, 10, 0) |
114 #if GTK_CHECK_VERSION(4, 10, 0) |
| 110 |
115 |
| 137 obj->i = i; |
142 obj->i = i; |
| 138 return obj; |
143 return obj; |
| 139 } |
144 } |
| 140 |
145 |
| 141 /* END GObject wrapper for generic pointers */ |
146 /* END GObject wrapper for generic pointers */ |
| |
147 |
| |
148 typedef struct UiCellEntry { |
| |
149 GtkEntry *entry; |
| |
150 UiListView *listview; |
| |
151 char *previous_value; |
| |
152 int row; |
| |
153 int col; |
| |
154 } UiCellEntry; |
| |
155 |
| |
156 static void cell_save_value(UiCellEntry *data, int restore) { |
| |
157 if(data->listview && data->listview->onsave) { |
| |
158 UiVar *var = data->listview->var; |
| |
159 UiList *list = var ? var->value : NULL; |
| |
160 const char *str = ENTRY_GET_TEXT(data->entry); |
| |
161 UiCellValue value; |
| |
162 value.string = str; |
| |
163 value.type = UI_STRING_EDITABLE; |
| |
164 if(data->listview->onsave(list, data->row, data->col, &value, data->listview->onsavedata)) { |
| |
165 free(data->previous_value); |
| |
166 data->previous_value = strdup(str); |
| |
167 } else if(restore) { |
| |
168 ENTRY_SET_TEXT(data->entry, data->previous_value); |
| |
169 } |
| |
170 } |
| |
171 } |
| |
172 |
| |
173 static void cell_entry_leave_focus( |
| |
174 GtkEventControllerFocus *self, |
| |
175 UiCellEntry *data) |
| |
176 { |
| |
177 // TODO: use a different singal to track focus |
| |
178 // we only want to call cell_save_value, when another entry is selected, |
| |
179 // not when the window loses focus or something like that |
| |
180 cell_save_value(data, TRUE); |
| |
181 } |
| |
182 |
| |
183 static void cell_entry_destroy(GtkWidget *object, UiCellEntry *data) { |
| |
184 free(data->previous_value); |
| |
185 free(data); |
| |
186 } |
| |
187 |
| |
188 static void cell_entry_unmap(GtkWidget *w, UiCellEntry *data) { |
| |
189 const char *text = ENTRY_GET_TEXT(w); |
| |
190 cell_save_value(data, FALSE); |
| |
191 } |
| |
192 |
| |
193 static void cell_entry_activate( |
| |
194 GtkEntry *self, |
| |
195 UiCellEntry *data) |
| |
196 { |
| |
197 cell_save_value(data, TRUE); |
| |
198 } |
| 142 |
199 |
| 143 static void column_factory_setup(GtkListItemFactory *factory, GtkListItem *item, gpointer userdata) { |
200 static void column_factory_setup(GtkListItemFactory *factory, GtkListItem *item, gpointer userdata) { |
| 144 UiColData *col = userdata; |
201 UiColData *col = userdata; |
| 145 UiModel *model = col->listview->model; |
202 UiModel *model = col->listview->model; |
| 146 UiModelType type = model->types[col->model_column]; |
203 UiModelType type = model->types[col->model_column]; |
| 154 g_object_set_data(G_OBJECT(hbox), "image", image); |
211 g_object_set_data(G_OBJECT(hbox), "image", image); |
| 155 g_object_set_data(G_OBJECT(hbox), "label", label); |
212 g_object_set_data(G_OBJECT(hbox), "label", label); |
| 156 } else if(type == UI_ICON) { |
213 } else if(type == UI_ICON) { |
| 157 GtkWidget *image = gtk_image_new(); |
214 GtkWidget *image = gtk_image_new(); |
| 158 gtk_list_item_set_child(item, image); |
215 gtk_list_item_set_child(item, image); |
| |
216 } else if(type == UI_STRING_EDITABLE) { |
| |
217 GtkWidget *textfield = gtk_entry_new(); |
| |
218 gtk_widget_add_css_class(textfield, "ui-table-entry"); |
| |
219 gtk_list_item_set_child(item, textfield); |
| |
220 |
| |
221 UiCellEntry *entry_data = malloc(sizeof(UiCellEntry)); |
| |
222 entry_data->entry = GTK_ENTRY(textfield); |
| |
223 entry_data->listview = NULL; |
| |
224 entry_data->previous_value = NULL; |
| |
225 entry_data->col = 0; |
| |
226 entry_data->row = 0; |
| |
227 g_object_set_data(G_OBJECT(textfield), "ui_entry_data", entry_data); |
| |
228 |
| |
229 g_signal_connect( |
| |
230 textfield, |
| |
231 "destroy", |
| |
232 G_CALLBACK(cell_entry_destroy), |
| |
233 entry_data); |
| |
234 g_signal_connect( |
| |
235 textfield, |
| |
236 "activate", |
| |
237 G_CALLBACK(cell_entry_activate), |
| |
238 entry_data); |
| |
239 g_signal_connect( |
| |
240 textfield, |
| |
241 "unmap", |
| |
242 G_CALLBACK(cell_entry_unmap), |
| |
243 entry_data); |
| |
244 |
| |
245 GtkEventController *focus_controller = gtk_event_controller_focus_new(); |
| |
246 g_signal_connect(focus_controller, "leave", G_CALLBACK(cell_entry_leave_focus), entry_data); |
| |
247 gtk_widget_add_controller(textfield, focus_controller); |
| 159 } else { |
248 } else { |
| 160 GtkWidget *label = gtk_label_new(NULL); |
249 GtkWidget *label = gtk_label_new(NULL); |
| 161 gtk_label_set_xalign(GTK_LABEL(label), 0); |
250 gtk_label_set_xalign(GTK_LABEL(label), 0); |
| 162 gtk_list_item_set_child(item, label); |
251 gtk_list_item_set_child(item, label); |
| 163 } |
252 } |
| 164 } |
253 } |
| 165 |
254 |
| 166 static void column_factory_bind(GtkListItemFactory *factory, GtkListItem *item, gpointer userdata) { |
255 PangoAttrList* textstyle2pangoattributes(UiTextStyle style) { |
| |
256 PangoAttrList *attr = pango_attr_list_new(); |
| |
257 |
| |
258 if(style.text_style & UI_TEXT_STYLE_BOLD) { |
| |
259 pango_attr_list_insert(attr, pango_attr_weight_new(PANGO_WEIGHT_BOLD)); |
| |
260 } |
| |
261 if(style.text_style & UI_TEXT_STYLE_ITALIC) { |
| |
262 pango_attr_list_insert(attr, pango_attr_style_new(PANGO_STYLE_ITALIC)); |
| |
263 } |
| |
264 if(style.text_style & UI_TEXT_STYLE_UNDERLINE) { |
| |
265 pango_attr_list_insert(attr, pango_attr_underline_new(PANGO_UNDERLINE_SINGLE)); |
| |
266 } |
| |
267 |
| |
268 // foreground color, convert from 8bit to 16bit |
| |
269 guint16 r = (guint16)style.fg.red * 257; |
| |
270 guint16 g = (guint16)style.fg.green * 257; |
| |
271 guint16 b = (guint16)style.fg.blue * 257; |
| |
272 pango_attr_list_insert(attr, pango_attr_foreground_new(r, g, b)); |
| |
273 |
| |
274 return attr; |
| |
275 } |
| |
276 |
| |
277 static void column_factory_bind(GtkListItemFactory *unused, GtkListItem *item, gpointer userdata) { |
| 167 UiColData *col = userdata; |
278 UiColData *col = userdata; |
| 168 UiList *list = col->listview->var ? col->listview->var->value : NULL; |
279 UiList *list = col->listview->var ? col->listview->var->value : NULL; |
| 169 UiListView *listview = col->listview; |
280 UiListView *listview = col->listview; |
| 170 |
281 |
| 171 ObjWrapper *obj = gtk_list_item_get_item(item); |
282 ObjWrapper *obj = gtk_list_item_get_item(item); |
| 172 UiModel *model = col->listview->model; |
283 UiModel *model = col->listview->model; |
| 173 UiModelType type = model->types[col->model_column]; |
284 UiModelType type = model->types[col->model_column]; |
| 174 |
285 |
| |
286 // cache the GtkListItem |
| |
287 CxHashKey row_key = cx_hash_key(&obj->i, sizeof(int)); |
| |
288 UiRowItems *row = cxMapGet(listview->bound_rows, row_key); |
| |
289 if(row) { |
| |
290 if(row->items[col->model_column] == NULL) { |
| |
291 row->bound++; |
| |
292 } |
| |
293 } else { |
| |
294 row = calloc(1, sizeof(UiRowItems) + listview->numcolumns * sizeof(GtkListItem*)); |
| |
295 cxMapPut(listview->bound_rows, row_key, row); |
| |
296 row->bound = 1; |
| |
297 } |
| |
298 row->items[col->model_column] = item; |
| |
299 |
| 175 UiBool freevalue = FALSE; |
300 UiBool freevalue = FALSE; |
| 176 void *data = listview->getvalue(list, obj->data, obj->i, col->data_column, listview->getvaluedata, &freevalue); |
301 void *data = listview->getvalue(list, obj->data, obj->i, col->data_column, listview->getvaluedata, &freevalue); |
| 177 GtkWidget *child = gtk_list_item_get_child(item); |
302 GtkWidget *child = gtk_list_item_get_child(item); |
| |
303 |
| |
304 PangoAttrList *attributes = NULL; |
| |
305 UiTextStyle style = { 0, 0 }; |
| |
306 if(listview->getstyle) { |
| |
307 // query current row style, if it wasn't already queried |
| |
308 if(obj->i != listview->current_row) { |
| |
309 listview->current_row = obj->i; |
| |
310 listview->row_style = (UiTextStyle){ 0, 0 }; |
| |
311 listview->apply_row_style = listview->getstyle(list, obj->data, obj->i, -1, listview->getstyledata, &listview->row_style); |
| |
312 style = listview->row_style; |
| |
313 if(listview->apply_row_style) { |
| |
314 pango_attr_list_unref(listview->current_row_attributes); |
| |
315 listview->current_row_attributes = textstyle2pangoattributes(style); |
| |
316 } |
| |
317 } |
| |
318 |
| |
319 int style_col = col->data_column; |
| |
320 if(type == UI_ICON_TEXT || type == UI_ICON_TEXT_FREE) { |
| |
321 style_col++; // col->data_column is the icon, we need the next col for the label |
| |
322 } |
| |
323 |
| |
324 // get the column style |
| |
325 if(listview->getstyle(list, obj->data, obj->i, style_col, listview->getstyledata, &style)) { |
| |
326 attributes = textstyle2pangoattributes(style); |
| |
327 } else if(listview->apply_row_style) { |
| |
328 attributes = listview->current_row_attributes; |
| |
329 } |
| |
330 } |
| 178 |
331 |
| 179 switch(type) { |
332 switch(type) { |
| 180 case UI_STRING_FREE: { |
333 case UI_STRING_FREE: { |
| 181 freevalue = TRUE; |
334 freevalue = TRUE; |
| 182 } |
335 } |
| 183 case UI_STRING: { |
336 case UI_STRING: { |
| 184 gtk_label_set_label(GTK_LABEL(child), data); |
337 gtk_label_set_label(GTK_LABEL(child), data); |
| 185 if(freevalue) { |
338 if(freevalue) { |
| 186 free(data); |
339 free(data); |
| 187 } |
340 } |
| |
341 gtk_label_set_attributes(GTK_LABEL(child), attributes); |
| 188 break; |
342 break; |
| 189 } |
343 } |
| 190 case UI_INTEGER: { |
344 case UI_INTEGER: { |
| 191 intptr_t intvalue = (intptr_t)data; |
345 intptr_t intvalue = (intptr_t)data; |
| 192 char buf[32]; |
346 char buf[32]; |
| 193 snprintf(buf, 32, "%d", (int)intvalue); |
347 snprintf(buf, 32, "%d", (int)intvalue); |
| 194 gtk_label_set_label(GTK_LABEL(child), buf); |
348 gtk_label_set_label(GTK_LABEL(child), buf); |
| |
349 gtk_label_set_attributes(GTK_LABEL(child), attributes); |
| 195 break; |
350 break; |
| 196 } |
351 } |
| 197 case UI_ICON: { |
352 case UI_ICON: { |
| 198 UiIcon *icon = data; |
353 UiIcon *icon = data; |
| 199 if(icon) { |
354 if(icon) { |
| 215 UiIcon *icon = data; |
370 UiIcon *icon = data; |
| 216 gtk_image_set_from_paintable(GTK_IMAGE(image), GDK_PAINTABLE(icon->info)); |
371 gtk_image_set_from_paintable(GTK_IMAGE(image), GDK_PAINTABLE(icon->info)); |
| 217 } |
372 } |
| 218 if(data2 && label) { |
373 if(data2 && label) { |
| 219 gtk_label_set_label(GTK_LABEL(label), data2); |
374 gtk_label_set_label(GTK_LABEL(label), data2); |
| |
375 gtk_label_set_attributes(GTK_LABEL(label), attributes); |
| 220 } |
376 } |
| 221 if(freevalue) { |
377 if(freevalue) { |
| 222 free(data2); |
378 free(data2); |
| 223 } |
379 } |
| 224 break; |
380 break; |
| 225 } |
381 } |
| 226 } |
382 case UI_STRING_EDITABLE: { |
| 227 } |
383 UiCellEntry *entry = g_object_get_data(G_OBJECT(child), "ui_entry_data"); |
| |
384 if(entry) { |
| |
385 entry->listview = col->listview; |
| |
386 entry->row = obj->i; |
| |
387 entry->col = col->data_column; |
| |
388 entry->previous_value = strdup(data); |
| |
389 } |
| |
390 ENTRY_SET_TEXT(child, data); |
| |
391 break; |
| |
392 } |
| |
393 } |
| |
394 |
| |
395 if(attributes != listview->current_row_attributes) { |
| |
396 pango_attr_list_unref(attributes); |
| |
397 } |
| |
398 } |
| |
399 |
| |
400 static void column_factory_unbind(GtkSignalListItemFactory *self, GtkListItem *item, UiColData *col) { |
| |
401 ObjWrapper *obj = gtk_list_item_get_item(item); |
| |
402 UiListView *listview = col->listview; |
| |
403 CxHashKey row_key = cx_hash_key(&obj->i, sizeof(int)); |
| |
404 UiRowItems *row = cxMapGet(listview->bound_rows, row_key); |
| |
405 if(row) { |
| |
406 row->items[col->model_column] = NULL; |
| |
407 row->bound--; |
| |
408 if(row->bound == 0) { |
| |
409 cxMapRemove(listview->bound_rows, row_key); |
| |
410 } |
| |
411 } // else: should not happen |
| |
412 |
| |
413 GtkWidget *child = gtk_list_item_get_child(item); |
| |
414 UiCellEntry *entry = g_object_get_data(G_OBJECT(child), "ui_entry_data"); |
| |
415 if(entry) { |
| |
416 cell_save_value(entry, FALSE); |
| |
417 entry->listview = NULL; |
| |
418 free(entry->previous_value); |
| |
419 entry->previous_value = NULL; |
| |
420 } |
| |
421 } |
| |
422 |
| 228 |
423 |
| 229 static GtkSelectionModel* create_selection_model(UiListView *listview, GListStore *liststore, bool multiselection) { |
424 static GtkSelectionModel* create_selection_model(UiListView *listview, GListStore *liststore, bool multiselection) { |
| 230 GtkSelectionModel *selection_model; |
425 GtkSelectionModel *selection_model; |
| 231 if(multiselection) { |
426 if(multiselection) { |
| 232 selection_model = GTK_SELECTION_MODEL(gtk_multi_selection_new(G_LIST_MODEL(liststore))); |
427 selection_model = GTK_SELECTION_MODEL(gtk_multi_selection_new(G_LIST_MODEL(liststore))); |
| 251 UiListView *listview = create_listview(obj, args); |
446 UiListView *listview = create_listview(obj, args); |
| 252 if(!args->getvalue && !args->getvalue2) { |
447 if(!args->getvalue && !args->getvalue2) { |
| 253 listview->getvalue = str_getvalue; |
448 listview->getvalue = str_getvalue; |
| 254 } |
449 } |
| 255 |
450 |
| |
451 listview->numcolumns = 1; |
| 256 listview->columns = malloc(sizeof(UiColData)); |
452 listview->columns = malloc(sizeof(UiColData)); |
| 257 listview->columns->listview = listview; |
453 listview->columns->listview = listview; |
| 258 listview->columns->data_column = 0; |
454 listview->columns->data_column = 0; |
| 259 listview->columns->model_column = 0; |
455 listview->columns->model_column = 0; |
| |
456 |
| |
457 listview->bound_rows = cxHashMapCreate(NULL, CX_STORE_POINTERS, 128); |
| |
458 listview->bound_rows->collection.simple_destructor = (cx_destructor_func)free; |
| 260 |
459 |
| 261 GtkListItemFactory *factory = gtk_signal_list_item_factory_new(); |
460 GtkListItemFactory *factory = gtk_signal_list_item_factory_new(); |
| 262 g_signal_connect(factory, "setup", G_CALLBACK(column_factory_setup), listview->columns); |
461 g_signal_connect(factory, "setup", G_CALLBACK(column_factory_setup), listview->columns); |
| 263 g_signal_connect(factory, "bind", G_CALLBACK(column_factory_bind), listview->columns); |
462 g_signal_connect(factory, "bind", G_CALLBACK(column_factory_bind), listview->columns); |
| 264 |
463 |
| 337 |
536 |
| 338 if(!args->getvalue && !args->getvalue2) { |
537 if(!args->getvalue && !args->getvalue2) { |
| 339 listview->getvalue = str_getvalue; |
538 listview->getvalue = str_getvalue; |
| 340 } |
539 } |
| 341 |
540 |
| |
541 listview->numcolumns = 1; |
| 342 listview->columns = malloc(sizeof(UiColData)); |
542 listview->columns = malloc(sizeof(UiColData)); |
| 343 listview->columns->listview = listview; |
543 listview->columns->listview = listview; |
| 344 listview->columns->data_column = 0; |
544 listview->columns->data_column = 0; |
| 345 listview->columns->model_column = 0; |
545 listview->columns->model_column = 0; |
| |
546 |
| |
547 listview->bound_rows = cxHashMapCreate(NULL, CX_STORE_POINTERS, 128); |
| |
548 listview->bound_rows->collection.simple_destructor = (cx_destructor_func)free; |
| 346 |
549 |
| 347 GtkListItemFactory *factory = gtk_signal_list_item_factory_new(); |
550 GtkListItemFactory *factory = gtk_signal_list_item_factory_new(); |
| 348 g_signal_connect(factory, "setup", G_CALLBACK(column_factory_setup), listview->columns); |
551 g_signal_connect(factory, "setup", G_CALLBACK(column_factory_setup), listview->columns); |
| 349 g_signal_connect(factory, "bind", G_CALLBACK(column_factory_bind), listview->columns); |
552 g_signal_connect(factory, "bind", G_CALLBACK(column_factory_bind), listview->columns); |
| 350 |
553 |
| 629 if(i < 0) { |
836 if(i < 0) { |
| 630 ui_update_liststore(view->liststore, list); |
837 ui_update_liststore(view->liststore, list); |
| 631 } else { |
838 } else { |
| 632 void *value = list->get(list, i); |
839 void *value = list->get(list, i); |
| 633 if(value) { |
840 if(value) { |
| 634 ObjWrapper *obj = obj_wrapper_new(value, i); |
841 ObjWrapper *obj = g_list_model_get_item(G_LIST_MODEL(view->liststore), i); |
| 635 UiListSelection sel = list->getselection(list); |
842 if(obj) { |
| 636 // TODO: if index i is selected, the selection is lost |
843 obj->data = value; |
| 637 // is it possible to update the item without removing it? |
|
| 638 // workaround: save selection and reapply it |
|
| 639 int count = g_list_model_get_n_items(G_LIST_MODEL(view->liststore)); |
|
| 640 if(count <= i) { |
|
| 641 g_list_store_splice(view->liststore, i, 0, (void **)&obj, 1); |
|
| 642 } else { |
|
| 643 g_list_store_splice(view->liststore, i, 1, (void **)&obj, 1); |
|
| 644 } |
844 } |
| 645 if(sel.count > 0) { |
845 |
| 646 list->setselection(list, sel); |
846 CxHashKey row_key = cx_hash_key(&i, sizeof(int)); |
| |
847 UiRowItems *row = cxMapGet(view->bound_rows, row_key); |
| |
848 if(row) { |
| |
849 for(int c=0;c<view->numcolumns;c++) { |
| |
850 if(row->items[c] != NULL) { |
| |
851 column_factory_bind(NULL, row->items[c], &view->columns[c]); |
| |
852 } |
| |
853 } |
| 647 } |
854 } |
| 648 ui_listselection_free(sel); |
|
| 649 } |
855 } |
| 650 } |
856 } |
| 651 } |
857 } |
| 652 |
858 |
| 653 UiListSelection ui_listview_getselection2(UiList *list) { |
859 UiListSelection ui_listview_getselection2(UiList *list) { |
| 707 |
913 |
| 708 #else |
914 #else |
| 709 |
915 |
| 710 static void update_list_row(UiListView *listview, GtkListStore *store, GtkTreeIter *iter, UiList *list, void *elm, int row) { |
916 static void update_list_row(UiListView *listview, GtkListStore *store, GtkTreeIter *iter, UiList *list, void *elm, int row) { |
| 711 UiModel *model = listview->model; |
917 UiModel *model = listview->model; |
| |
918 ui_getstylefunc getstyle = listview->getstyle; |
| |
919 |
| |
920 // get the row style |
| |
921 UiBool style_set = FALSE; |
| |
922 UiTextStyle style = { 0, 0 }; |
| |
923 if(getstyle) { |
| |
924 style_set = getstyle(list, elm, row, -1, listview->getstyledata, &style); |
| |
925 } |
| |
926 |
| 712 // set column values |
927 // set column values |
| 713 int c = 0; |
928 int c = 0; |
| 714 for(int i=0;i<model->columns;i++,c++) { |
929 for(int i=0;i<model->columns;i++,c++) { |
| 715 UiBool freevalue = FALSE; |
930 UiBool freevalue = FALSE; |
| 716 void *data = listview->getvalue(list, elm, row, c, listview->getvaluedata, &freevalue); |
931 void *data = listview->getvalue(list, elm, row, c, listview->getvaluedata, &freevalue); |
| |
932 |
| |
933 UiModelType type = model->types[i]; |
| |
934 |
| |
935 if(getstyle) { |
| |
936 // in case the column is icon+text, only get a style for the text column |
| |
937 int style_col = c; |
| |
938 if(type == UI_ICON_TEXT || type == UI_ICON_TEXT_FREE) { |
| |
939 style_col++; |
| |
940 } |
| |
941 |
| |
942 // Get the individual column style |
| |
943 // The column style overrides the row style, however if no column style |
| |
944 // is provided, we stick with the row style |
| |
945 if(getstyle(list, elm, row, style_col, listview->getstyledata, &style)) { |
| |
946 style_set = TRUE; |
| |
947 } |
| |
948 } |
| 717 |
949 |
| 718 GValue value = G_VALUE_INIT; |
950 GValue value = G_VALUE_INIT; |
| 719 switch(model->types[i]) { |
951 switch(type) { |
| 720 case UI_STRING_FREE: { |
952 case UI_STRING_FREE: { |
| 721 freevalue = TRUE; |
953 freevalue = TRUE; |
| 722 } |
954 } |
| 723 case UI_STRING: { |
955 case UI_STRING: { |
| 724 g_value_init(&value, G_TYPE_STRING); |
956 g_value_init(&value, G_TYPE_STRING); |
| 787 break; |
1019 break; |
| 788 } |
1020 } |
| 789 } |
1021 } |
| 790 |
1022 |
| 791 gtk_list_store_set_value(store, iter, c, &value); |
1023 gtk_list_store_set_value(store, iter, c, &value); |
| |
1024 |
| |
1025 if(style_set) { |
| |
1026 int soff = listview->style_offset + i*6; |
| |
1027 |
| |
1028 GValue style_set_value = G_VALUE_INIT; |
| |
1029 g_value_init(&style_set_value, G_TYPE_BOOLEAN); |
| |
1030 g_value_set_boolean(&style_set_value, TRUE); |
| |
1031 gtk_list_store_set_value(store, iter, soff, &style_set_value); |
| |
1032 |
| |
1033 GValue style_weight_value = G_VALUE_INIT; |
| |
1034 g_value_init(&style_weight_value, G_TYPE_INT); |
| |
1035 if(style.text_style & UI_TEXT_STYLE_BOLD) { |
| |
1036 g_value_set_int(&style_weight_value, 600); |
| |
1037 } else { |
| |
1038 g_value_set_int(&style_weight_value, 400); |
| |
1039 } |
| |
1040 gtk_list_store_set_value(store, iter, soff + 1, &style_weight_value); |
| |
1041 |
| |
1042 GValue style_underline_value = G_VALUE_INIT; |
| |
1043 g_value_init(&style_underline_value, G_TYPE_INT); |
| |
1044 if(style.text_style & UI_TEXT_STYLE_UNDERLINE) { |
| |
1045 g_value_set_int(&style_underline_value, PANGO_UNDERLINE_SINGLE); |
| |
1046 } else { |
| |
1047 g_value_set_int(&style_underline_value, PANGO_UNDERLINE_NONE); |
| |
1048 } |
| |
1049 gtk_list_store_set_value(store, iter, soff + 2, &style_underline_value); |
| |
1050 |
| |
1051 GValue style_italic_value = G_VALUE_INIT; |
| |
1052 g_value_init(&style_italic_value, G_TYPE_INT); |
| |
1053 if(style.text_style & UI_TEXT_STYLE_ITALIC) { |
| |
1054 g_value_set_int(&style_italic_value, PANGO_STYLE_ITALIC); |
| |
1055 } else { |
| |
1056 g_value_set_int(&style_italic_value, PANGO_STYLE_NORMAL); |
| |
1057 } |
| |
1058 gtk_list_store_set_value(store, iter, soff + 3, &style_italic_value); |
| |
1059 |
| |
1060 GValue style_fgset_value = G_VALUE_INIT; |
| |
1061 g_value_init(&style_fgset_value, G_TYPE_BOOLEAN); |
| |
1062 g_value_set_boolean(&style_fgset_value, style.fg_set); |
| |
1063 gtk_list_store_set_value(store, iter, soff + 4, &style_fgset_value); |
| |
1064 |
| |
1065 if(style.fg_set) { |
| |
1066 char buf[8]; |
| |
1067 snprintf(buf, 8, "#%02X%02X%02X", (int)style.fg.red, (int)style.fg.green, (int)style.fg.blue); |
| |
1068 |
| |
1069 GValue style_fg_value = G_VALUE_INIT; |
| |
1070 g_value_init(&style_fg_value, G_TYPE_STRING); |
| |
1071 g_value_set_string(&style_fg_value, buf); |
| |
1072 gtk_list_store_set_value(store, iter, soff + 5, &style_fg_value); |
| |
1073 } |
| |
1074 } |
| 792 } |
1075 } |
| 793 } |
1076 } |
| 794 |
1077 |
| 795 static GtkListStore* create_list_store(UiListView *listview, UiList *list) { |
1078 static GtkListStore* create_list_store(UiListView *listview, UiList *list) { |
| 796 UiModel *model = listview->model; |
1079 UiModel *model = listview->model; |
| 797 int columns = model->columns; |
1080 int columns = model->columns; |
| 798 GType types[2*columns]; |
1081 GType *types = calloc(columns*8, sizeof(GType)); |
| 799 int c = 0; |
1082 int c = 0; |
| 800 for(int i=0;i<columns;i++,c++) { |
1083 for(int i=0;i<columns;i++,c++) { |
| 801 switch(model->types[i]) { |
1084 switch(model->types[i]) { |
| 802 case UI_STRING: |
1085 case UI_STRING: |
| 803 case UI_STRING_FREE: types[c] = G_TYPE_STRING; break; |
1086 case UI_STRING_FREE: types[c] = G_TYPE_STRING; break; |
| 955 GtkWidget *view = gtk_tree_view_new(); |
1249 GtkWidget *view = gtk_tree_view_new(); |
| 956 |
1250 |
| 957 UiModel *model = args->model; |
1251 UiModel *model = args->model; |
| 958 int columns = model ? model->columns : 0; |
1252 int columns = model ? model->columns : 0; |
| 959 |
1253 |
| |
1254 // find the last data column index |
| 960 int addi = 0; |
1255 int addi = 0; |
| 961 for(int i=0;i<columns;i++) { |
1256 int style_offset = 0; |
| |
1257 int i = 0; |
| |
1258 for(;i<columns;i++) { |
| |
1259 if(model->types[i] == UI_ICON_TEXT || model->types[i] == UI_ICON_TEXT_FREE) { |
| |
1260 addi++; |
| |
1261 } |
| |
1262 } |
| |
1263 style_offset = i+addi; |
| |
1264 |
| |
1265 // create columns and init cell renderers |
| |
1266 addi = 0; |
| |
1267 for(i=0;i<columns;i++) { |
| 962 GtkTreeViewColumn *column = NULL; |
1268 GtkTreeViewColumn *column = NULL; |
| 963 if(model->types[i] == UI_ICON_TEXT) { |
1269 if(model->types[i] == UI_ICON_TEXT || model->types[i] == UI_ICON_TEXT_FREE) { |
| 964 column = gtk_tree_view_column_new(); |
1270 column = gtk_tree_view_column_new(); |
| 965 gtk_tree_view_column_set_title(column, model->titles[i]); |
1271 gtk_tree_view_column_set_title(column, model->titles[i]); |
| 966 |
1272 |
| 967 GtkCellRenderer *iconrenderer = gtk_cell_renderer_pixbuf_new(); |
1273 GtkCellRenderer *iconrenderer = gtk_cell_renderer_pixbuf_new(); |
| 968 GtkCellRenderer *textrenderer = gtk_cell_renderer_text_new(); |
1274 GtkCellRenderer *textrenderer = gtk_cell_renderer_text_new(); |
| 969 |
1275 |
| 970 gtk_tree_view_column_pack_end(column, textrenderer, TRUE); |
1276 gtk_tree_view_column_pack_end(column, textrenderer, TRUE); |
| 971 gtk_tree_view_column_pack_start(column, iconrenderer, FALSE); |
1277 gtk_tree_view_column_pack_start(column, iconrenderer, FALSE); |
| 972 |
1278 |
| 973 |
1279 |
| 974 gtk_tree_view_column_add_attribute(column, iconrenderer, "pixbuf", i); |
1280 gtk_tree_view_column_add_attribute(column, iconrenderer, "pixbuf", addi + i); |
| 975 gtk_tree_view_column_add_attribute(column, textrenderer, "text", i+1); |
1281 gtk_tree_view_column_add_attribute(column, textrenderer, "text", addi + i+1); |
| |
1282 |
| |
1283 if(args->getstyle) { |
| |
1284 int soff = style_offset + i*6; |
| |
1285 gtk_tree_view_column_add_attribute(column, textrenderer, "weight-set", soff); |
| |
1286 gtk_tree_view_column_add_attribute(column, textrenderer, "underline-set", soff); |
| |
1287 gtk_tree_view_column_add_attribute(column, textrenderer, "style-set", soff); |
| |
1288 |
| |
1289 gtk_tree_view_column_add_attribute(column, textrenderer, "weight", soff + 1); |
| |
1290 gtk_tree_view_column_add_attribute(column, textrenderer, "underline", soff + 2); |
| |
1291 gtk_tree_view_column_add_attribute(column, textrenderer, "style", soff + 3); |
| |
1292 gtk_tree_view_column_add_attribute(column, textrenderer, "foreground-set", soff + 4); |
| |
1293 gtk_tree_view_column_add_attribute(column, textrenderer, "foreground", soff + 5); |
| |
1294 } |
| 976 |
1295 |
| 977 addi++; |
1296 addi++; |
| 978 } else if (model->types[i] == UI_ICON) { |
1297 } else if (model->types[i] == UI_ICON) { |
| 979 GtkCellRenderer *iconrenderer = gtk_cell_renderer_pixbuf_new(); |
1298 GtkCellRenderer *iconrenderer = gtk_cell_renderer_pixbuf_new(); |
| 980 column = gtk_tree_view_column_new_with_attributes( |
1299 column = gtk_tree_view_column_new_with_attributes( |
| 982 iconrenderer, |
1301 iconrenderer, |
| 983 "pixbuf", |
1302 "pixbuf", |
| 984 i + addi, |
1303 i + addi, |
| 985 NULL); |
1304 NULL); |
| 986 } else { |
1305 } else { |
| 987 GtkCellRenderer *renderer = gtk_cell_renderer_text_new(); |
1306 GtkCellRenderer *textrenderer = gtk_cell_renderer_text_new(); |
| 988 column = gtk_tree_view_column_new_with_attributes( |
1307 column = gtk_tree_view_column_new_with_attributes( |
| 989 model->titles[i], |
1308 model->titles[i], |
| 990 renderer, |
1309 textrenderer, |
| 991 "text", |
1310 "text", |
| 992 i + addi, |
1311 i + addi, |
| 993 NULL); |
1312 NULL); |
| |
1313 |
| |
1314 if(args->getstyle) { |
| |
1315 int soff = style_offset + i*6; |
| |
1316 gtk_tree_view_column_add_attribute(column, textrenderer, "weight-set", soff); |
| |
1317 gtk_tree_view_column_add_attribute(column, textrenderer, "underline-set", soff); |
| |
1318 gtk_tree_view_column_add_attribute(column, textrenderer, "style-set", soff); |
| |
1319 |
| |
1320 gtk_tree_view_column_add_attribute(column, textrenderer, "weight", soff + 1); |
| |
1321 gtk_tree_view_column_add_attribute(column, textrenderer, "underline", soff + 2); |
| |
1322 gtk_tree_view_column_add_attribute(column, textrenderer, "style", soff + 3); |
| |
1323 gtk_tree_view_column_add_attribute(column, textrenderer, "foreground-set", soff + 4); |
| |
1324 gtk_tree_view_column_add_attribute(column, textrenderer, "foreground", soff + 5); |
| |
1325 } |
| 994 } |
1326 } |
| 995 |
1327 |
| 996 int colsz = model->columnsize[i]; |
1328 int colsz = model->columnsize[i]; |
| 997 if(colsz > 0) { |
1329 if(colsz > 0) { |
| 998 gtk_tree_view_column_set_fixed_width(column, colsz); |
1330 gtk_tree_view_column_set_fixed_width(column, colsz); |