--- a/ui/gtk/list.c Sun Aug 31 07:50:23 2025 +0200 +++ b/ui/gtk/list.c Sun Aug 31 09:44:53 2025 +0200 @@ -772,14 +772,40 @@ static void update_list_row(UiListView *listview, GtkListStore *store, GtkTreeIter *iter, UiList *list, void *elm, int row) { UiModel *model = listview->model; + ui_getstylefunc getstyle = listview->getstyle; + + // get the row style + UiBool style_set = FALSE; + UiTextStyle style = { 0, 0 }; + if(getstyle) { + style_set = getstyle(list, elm, row, -1, listview->getstyledata, &style); + } + // set column values int c = 0; for(int i=0;i<model->columns;i++,c++) { UiBool freevalue = FALSE; void *data = listview->getvalue(list, elm, row, c, listview->getvaluedata, &freevalue); + + UiModelType type = model->types[i]; + + if(getstyle) { + // in case the column is icon+text, only get a style for the text column + int style_col = c; + if(type == UI_ICON_TEXT || type == UI_ICON_TEXT_FREE) { + style_col++; + } + + // Get the individual column style + // The column style overrides the row style, however if no column style + // is provided, we stick with the row style + if(getstyle(list, elm, row, style_col, listview->getstyledata, &style)) { + style_set = TRUE; + } + } GValue value = G_VALUE_INIT; - switch(model->types[i]) { + switch(type) { case UI_STRING_FREE: { freevalue = TRUE; } @@ -852,13 +878,64 @@ } gtk_list_store_set_value(store, iter, c, &value); + + if(style_set) { + int soff = listview->style_offset + i*6; + + GValue style_set_value = G_VALUE_INIT; + g_value_init(&style_set_value, G_TYPE_BOOLEAN); + g_value_set_boolean(&style_set_value, TRUE); + gtk_list_store_set_value(store, iter, soff, &style_set_value); + + GValue style_weight_value = G_VALUE_INIT; + g_value_init(&style_weight_value, G_TYPE_INT); + if(style.text_style & UI_TEXT_STYLE_BOLD) { + g_value_set_int(&style_weight_value, 600); + } else { + g_value_set_int(&style_weight_value, 400); + } + gtk_list_store_set_value(store, iter, soff + 1, &style_weight_value); + + GValue style_underline_value = G_VALUE_INIT; + g_value_init(&style_underline_value, G_TYPE_INT); + if(style.text_style & UI_TEXT_STYLE_UNDERLINE) { + g_value_set_int(&style_underline_value, PANGO_UNDERLINE_SINGLE); + } else { + g_value_set_int(&style_underline_value, PANGO_UNDERLINE_NONE); + } + gtk_list_store_set_value(store, iter, soff + 2, &style_underline_value); + + GValue style_italic_value = G_VALUE_INIT; + g_value_init(&style_italic_value, G_TYPE_INT); + if(style.text_style & UI_TEXT_STYLE_ITALIC) { + g_value_set_int(&style_italic_value, PANGO_STYLE_ITALIC); + } else { + g_value_set_int(&style_italic_value, PANGO_STYLE_NORMAL); + } + gtk_list_store_set_value(store, iter, soff + 3, &style_italic_value); + + GValue style_fgset_value = G_VALUE_INIT; + g_value_init(&style_fgset_value, G_TYPE_BOOLEAN); + g_value_set_boolean(&style_fgset_value, style.fg_set); + gtk_list_store_set_value(store, iter, soff + 4, &style_fgset_value); + + if(style.fg_set) { + char buf[8]; + snprintf(buf, 8, "#%02X%02X%02X", (int)style.fg.red, (int)style.fg.green, (int)style.fg.blue); + + GValue style_fg_value = G_VALUE_INIT; + g_value_init(&style_fg_value, G_TYPE_STRING); + g_value_set_string(&style_fg_value, buf); + gtk_list_store_set_value(store, iter, soff + 5, &style_fg_value); + } + } } } static GtkListStore* create_list_store(UiListView *listview, UiList *list) { UiModel *model = listview->model; int columns = model->columns; - GType types[2*columns]; + GType *types = calloc(columns*8, sizeof(GType)); int c = 0; for(int i=0;i<columns;i++,c++) { switch(model->types[i]) { @@ -873,8 +950,18 @@ } } } + int s = 0; + for(int i=0;i<columns;i++) { + types[listview->style_offset+s] = G_TYPE_BOOLEAN; s++; // *-set + types[listview->style_offset+s] = G_TYPE_INT; s++; // weight + types[listview->style_offset+s] = G_TYPE_INT; s++; // underline + types[listview->style_offset+s] = G_TYPE_INT; s++; // style + types[listview->style_offset+s] = G_TYPE_BOOLEAN; s++; // foreground-set + types[listview->style_offset+s] = G_TYPE_STRING; s++; // foreground + } - GtkListStore *store = gtk_list_store_newv(c, types); + GtkListStore *store = gtk_list_store_newv(c+s, types); + free(types); if(list) { void *elm = list->first(list); @@ -920,6 +1007,7 @@ UiModel *model = ui_model(obj->ctx, UI_STRING, "", -1); UiListView *listview = create_listview(obj, args); + listview->style_offset = 1; if(!args->getvalue && !args->getvalue2) { listview->getvalue = str_getvalue; } @@ -1020,10 +1108,22 @@ UiModel *model = args->model; int columns = model ? model->columns : 0; + // find the last data column index int addi = 0; - for(int i=0;i<columns;i++) { + int style_offset = 0; + int i = 0; + for(;i<columns;i++) { + if(model->types[i] == UI_ICON_TEXT || model->types[i] == UI_ICON_TEXT_FREE) { + addi++; + } + } + style_offset = i+addi; + + // create columns and init cell renderers + addi = 0; + for(i=0;i<columns;i++) { GtkTreeViewColumn *column = NULL; - if(model->types[i] == UI_ICON_TEXT) { + if(model->types[i] == UI_ICON_TEXT || model->types[i] == UI_ICON_TEXT_FREE) { column = gtk_tree_view_column_new(); gtk_tree_view_column_set_title(column, model->titles[i]); @@ -1037,6 +1137,19 @@ gtk_tree_view_column_add_attribute(column, iconrenderer, "pixbuf", addi + i); gtk_tree_view_column_add_attribute(column, textrenderer, "text", addi + i+1); + if(args->getstyle) { + int soff = style_offset + i*6; + gtk_tree_view_column_add_attribute(column, textrenderer, "weight-set", soff); + gtk_tree_view_column_add_attribute(column, textrenderer, "underline-set", soff); + gtk_tree_view_column_add_attribute(column, textrenderer, "style-set", soff); + + gtk_tree_view_column_add_attribute(column, textrenderer, "weight", soff + 1); + gtk_tree_view_column_add_attribute(column, textrenderer, "underline", soff + 2); + gtk_tree_view_column_add_attribute(column, textrenderer, "style", soff + 3); + gtk_tree_view_column_add_attribute(column, textrenderer, "foreground-set", soff + 4); + gtk_tree_view_column_add_attribute(column, textrenderer, "foreground", soff + 5); + } + addi++; } else if (model->types[i] == UI_ICON) { GtkCellRenderer *iconrenderer = gtk_cell_renderer_pixbuf_new(); @@ -1047,13 +1160,26 @@ i + addi, NULL); } else { - GtkCellRenderer *renderer = gtk_cell_renderer_text_new(); + GtkCellRenderer *textrenderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes( model->titles[i], - renderer, + textrenderer, "text", i + addi, NULL); + + if(args->getstyle) { + int soff = style_offset + i*6; + gtk_tree_view_column_add_attribute(column, textrenderer, "weight-set", soff); + gtk_tree_view_column_add_attribute(column, textrenderer, "underline-set", soff); + gtk_tree_view_column_add_attribute(column, textrenderer, "style-set", soff); + + gtk_tree_view_column_add_attribute(column, textrenderer, "weight", soff + 1); + gtk_tree_view_column_add_attribute(column, textrenderer, "underline", soff + 2); + gtk_tree_view_column_add_attribute(column, textrenderer, "style", soff + 3); + gtk_tree_view_column_add_attribute(column, textrenderer, "foreground-set", soff + 4); + gtk_tree_view_column_add_attribute(column, textrenderer, "foreground", soff + 5); + } } int colsz = model->columnsize[i]; @@ -1083,6 +1209,7 @@ // data changes UiListView *tableview = create_listview(obj, args); tableview->widget = view; + tableview->style_offset = style_offset; g_signal_connect( view, "destroy", @@ -1218,6 +1345,7 @@ UiListView *listview = create_listview(obj, args); listview->widget = combobox; + listview->style_offset = 1; listview->model = ui_model(obj->ctx, UI_STRING, "", -1); g_signal_connect( combobox,