Gtk.Combobox displays two columns (instead of 1), Why? - c

I realize GTK-2 is now 'antique'. I have an old program I have to modify, and it's just too large to convert to GTK-3 for the time I have. This is the issue:
I added a ComboBox to which I assign a ListBox with 2 columns (G_TYPE_INT and G_TYPE_STRING).
For some reason, both columns are shown on the ComboBox, though I think the code shown below only assigns one.
void
fill_list(GtkComboBox *cbbox)
{
GtkListStore *store = gtk_list_store_new(2, G_TYPE_INT, G_TYPE_STRING);
GtkTreeIter iter;
GtkCellRenderer *renderer = gtk_cell_renderer_text_new();
gtk_combo_box_set_model(cbbox, GTK_TREE_MODEL(store));
gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(cbbox), renderer, TRUE);
gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(cbbox), renderer,
"text", 0, NULL);
gtk_combo_box_set_entry_text_column(cbbox, 0);
gtk_list_store_append(store, &iter);
// Col 0 Col 1
gtk_list_store_set(store, &iter, 0, 0, 1, "Kind 1", -1);
gtk_list_store_append(store, &iter);
gtk_list_store_set(store, &iter, 0, 1, 1, "Kind 2", -1);
gtk_list_store_append(store, &iter);
This is part of the function called on the 'realize' signal of the widget.
Changing ..."text", 0... to ..."text", 1... changes the second column of the
ComboBox to, as expected, the second column of the ListStore.
But, for unknown reason, I can't get rid of the first column. I've scanned the
entire project for signs of code that might influence - no luck. The interface was
generated using Glade-2.
For the last years, I've been working more from Python, so I'm suspecting there's something
I'm missing here. I even basically tested this code in Python, and had no problem there.
I'd appreciate suggestions!

The problem was solved!
I found out that Glade 2, when asked to add a GtkComboBox, actually inserted a GtkComboBoxText (even though in the Component editor it is shown as a GtkComboBox type). I've only detected this when browsing the automatically generated interface.c code.
This creates a widget with a 'model' in it, and (I suspect) the necessary code to render the single column in that model (for the 'text'). When adding a new column, by setting another model, the (original) renderer is rendering the first column.
To get rid of the original renderer, the solution seems to be to call gtk_cell_layout_clear, and only then add the new model + renderer:
gtk_cell_layout_clear(GTK_CELL_LAYOUT(cbbox));
Do this during a realize event handler for the ComboBox, don't modify interface.c, as it will be overwritten.
I'm not sure if this is enough to free any memory to the original renderer though.

Related

Using Pango Markup within a GTK+ TreeView in C

I have a completely hardcoded GtkTreeView and I am trying to use Pango Markup on one of the columns in the Treeview. This requires the use of a cell data function on the text renderer for that column. The cell data function has the form:
// This function uses pango markup on the Gtklabels shown in the TreeView
// A cell data function is a function that is called for a specific cell renderer for each single row before that row is rendered.
static void cell_data_func_label (__attribute__((unused)) GtkTreeViewColumn *column, GtkCellRenderer *renderer,
GtkTreeModel *model, GtkTreeIter *iter, __attribute__((unused)) gpointer user_data)
{
gchar *label;
gchar *markuptxt;
// Retrieve the current label
gtk_tree_model_get (model, iter, CURRENT, &label, -1);
markuptxt = g_strdup_printf("<i>%s</i>", label);
g_object_set(renderer, "markup", markuptxt, "text", NULL, NULL); // markup isn't showing and text field is blank due to "text" == NULL
g_free(markuptxt);
}
and within the function GtkWidget *create_view_and_model() I set the cell data function via:
// Sets the GtkTreeCellDataFunc to use for the column
gtk_tree_view_column_set_cell_data_func(column4, text, cell_data_func_label, NULL, NULL);
The problem is that the text cell renderer is now blank. I suspect it might have to do with passing NULL after "text" in g_object_set. The following link:
https://en.wikibooks.org/wiki/GTK%2B_By_Example/Tree_View/Columns_and_Renderers
states that:
When using the "markup" property, you need to take into account that the "markup" and "text" properties do not seem to be mutually exclusive (I suppose this could be called a bug). In other words: whenever you set "markup" (and have used the "text" property before), set the "text" property to NULL, and vice versa.
It may be that this is no longer the case (i.e. it is for GTK+ 2), but I am not sure what needs to be changed in order to render the column with markup, since anything other than NULL ends up being rendered without markup, and using NULL leaves the renderer empty. Any assitance would be appreciated.
What ended up working was simply not including any reference to "text" whatsoever in g_object_set:
g_object_set(renderer, "markup", markuptxt, NULL);

GtkSourceGutter - How to render icon or text on a specific line

I have inserted custom gtk source gutter renderer pixbuf and I want to render icon on a specific line.
The reference API states that the interface is very similar to that on GtkTreeView, but doesn't work with a tree model.
So... how am I supposed to render data to a specific line if the GtkSourceGutter doesn't work with a tree model?
I checked every function in the entire library, every suggested api and child objects and nothing even hints about that.
It just doesn't make sense. The man page says that the GtkSourceGutterRendererPixbuf is used to display icon IN A CELL.
Doing gtk_source_gutter_renderer_pixbuf_set_pixbuf(renderer, pixbuf); will render the icon for all cells in the gutter.
And if the only way is to draw the pixbuf manually using cairo..what's the point in those renderers ?
How do I render pixbuf in a specific line using the gtksourcegutterrenderer?
I haven't worked with GtkSourceView, but I can give you some clues.
How it's done by GtkSourceView's author
First of all, we need some links:
GtkSourceGutterRendererMarks source code
GtkSourceGutterRendererPixbuf source code
GtkSourceGutterRenderer documentation
Let's start with GtkSourceGutterRendererPixbuf. From it's class_init method we find out, that it overrides only draw method. It's only purpose is to render a pixbuf or icon. Pure drawing.
However, GtkSourceGutterRenderer documentation says, that there is a query-data signal which can be used to tune Renderer's internal state. At this point we should take a look at GtkSourceGutterRendererMarks which is inherited from RendererPixbuf. It doesn't override draw, but overrides query_data. (For some reason GtkSourceGutterRendererClass is not described in the documentation. I don't know why.)
/* Read my comments. */
static void
gutter_renderer_query_data (GtkSourceGutterRenderer *renderer,
GtkTextIter *start,
GtkTextIter *end,
GtkSourceGutterRendererState state)
{
GSList *marks;
GdkPixbuf *pixbuf = NULL;
view = GTK_SOURCE_VIEW (gtk_source_gutter_renderer_get_view (renderer));
buffer = GTK_SOURCE_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)));
marks = gtk_source_buffer_get_source_marks_at_iter (buffer,
start,
NULL);
/* If there are marks, we find a pixbuf for one of them.
* Otherwise pixbuf is NULL. */
if (marks != NULL)
{
size = measure_line_height (view);
pixbuf = composite_marks (view, marks, size);
g_slist_free (marks);
}
/* Now tell parent class to render certain pixbuf
* It will render nothing if pixbuf is NULL. */
g_object_set (G_OBJECT (renderer),
"pixbuf", pixbuf,
NULL);
}
My recommendations.
You want to draw marks at certain lines (e.g. want to highlight current debugger line). If I were you, I would have inherited from RendererPixbuf, overriden query_data and use gtk_text_iter_get_line on GtkTextIter *start. Looks like that's the bare minimum.
Feel free to ask any further questions.
I personally cannot simply agree with the allegation that creating custom objects is easy. It isn't easy, not to everyone.
Mainly, because, this question is tagged c and people who don't know Object-Oriented programming might be unfamiliar with its concepts.
It is a matter of reading and practice.
So do not panic if you don't know how to, for instance create your own widget.
The easiest solution I can think of, doesn't involve creating your own renderer, but rather tell the renderer how to query rendering data.
Just connect the query-data signal on your GtkSourceGutterRenderer to a signal handler that looks like this:
G_MODULE_EXPORT void gutter_renderer_query_data (GtkSourceGutterRenderer *renderer, GtkTextIter *start, GtkTextIter *end, GtkSourceGutterRendererState state)
{
GtkSourceView* view = NULL;
GtkSourceBuffer* buffer = NULL;
GSList* marks = NULL;
GdkPixbuf* pixbuf = NULL;
view = GTK_SOURCE_VIEW(gtk_source_gutter_renderer_get_view(renderer));
buffer = GTK_SOURCE_BUFFER(gtk_text_view_get_buffer(GTK_TEXT_VIEW(view)));
marks = gtk_source_buffer_get_source_marks_at_iter(buffer, start, NULL);
if(marks != NULL)
{
char *category = gtk_source_mark_get_category(marks->data);
if(!g_strcmp0(category, "CERTAIN_CATEGORY")) /* See note 1) */
pixbuf = gtk_image_get_pixbuf(gtk_image_new_from_file("icon_file_here")); /* See note 2) */
g_slist_free(marks);
}
g_object_set(G_OBJECT(renderer), "pixbuf", pixbuf, "yalign", 0.5, NULL);
}
Notes:
GtkSourceMark shares the GtkSourceGutterRenderer interface so you might want to filter your other source marks, by specifying the category of a source mark that is applied to the certain line. Otherwise your custom renderer pixbuf will also be rendered left to your other source marks.
You should specify the exact pixbuf you want to render internally. Doing this, you won't have to call gtk_source_gutter_renderer_pixbuf_set_pixbuf() . You let the API do the resource handling.

GtkTreeView set selection to specific row

How can I set the GtkTreeSelection to a specific row, to the row number 3?
I can set the selection to the GtkTreeIter, but how can i set the iter to the row number 3?
I didn't find anything useful at the google search, so I didn't try anything yet because I don't know what.
I hope you can help me and give me information about my questions!
EDIT:
GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeview));
GtkTreePath *path = gtk_tree_path_new_from_indices(3, -1);
gtk_tree_model_get_iter(model, &iter, path);
gtk_tree_path_free(path);
gtk_tree_selection_select_path(treeview_selection, path);
-> Don't work
You don't need to use a GtkTreeIter for this, the GtkTreePath API is enough. You're throwing your path away before using it, which creates problems.
Here's how to do it:
GtkTreePath *path = gtk_tree_path_new_from_indices(3, -1);
gtk_tree_selection_select_path(treeview_selection, path);
gtk_tree_path_free(path);
UPDATE: I rewrote the code completely to drop use of GtkTreeIter, I originally thought that you wanted a solution using an iter since that was what you were trying to do.
If you just want to do a selection (and don't, for instance, need a GtKTreeIter for something else) the above is the simplest way using just a GtkTreePath.
Take care not do destroy the path before using it in the select-call, of course.

Difficulty in editable GtkTreeView

I am writing a piece of software where my user should be able to add data to a table-like editing widget, which I managed to render by using a GtkTreeView. I was able to render my cell editable by setting its editable property via this call
g_object_set(content_renderer,
"editable", TRUE,
NULL);
However, my GtkTreeView not only doesn't retain values entered as it's not even showing the data I've added before rendering. I saw a few examples in the web where the developer manually set the user input data to the model but all of these were either written in Python or C++ using offered bindings for these languages and therefore don't address my issue directly.
I've written this (not so) small example where the problem is successfully shown.
How can I make user input data persistent in a GtkTreeView?
P.S.: my problem is somehow related to this one, however this solution doesn't apply to me.
EDIT:
I followed #PhillipWood hint and connected my GtkCellRendererText to the edited signal, and also set by hand the new data into the model.
HOWEVER, neither the data I've entered prior to the edition nor the data I've entered during the edition appear in the grid.
I am under Fedora 19, with GTK+ 3.8.8.
You need to connect to the 'edited' signal of the cell renderer. This is emitted when the user finishes editing, it is up to the application (i.e. your code) to store the new value in the correct column of the model.
Update:
Looking at your updated code there are a few things that stand out.
Firstly when you use a GtkListStore or a GtkTreeStore it is a good idea to create an enum for indexing the columns.
enum {COLUMN_LABEL, COLUMN_CONTENT, COLUMN_LAST};
Then when you create the list store do
list_store = gtk_list_store_new(COLUMN_LAST, G_TYPE_STRING, G_TYPE_INT);
When you create a tree column you need to tell it which column(s) of the model to display with the cellrenderer. You do this by binding properties of the cellrenderer to columns in the model
label_col = gtk_tree_view_column_new_with_attributes ("Layer",
gtk_cell_renderer_text_new(),
"text", COLUMN_LABEL,
NULL);
Now the content column the model stores an int so we cannot just bind the text property of the renderer as it expects a string. We need to map the column contents onto the text property using
content_column = gtk_tree_view_column_new ();
gtk_tree_view_column_set_cell_data_func (content_column,
gtk_cell_renderer_text_new (),
content_column_data_func,
NULL, NULL);
with
static void
content_column_data_func (GtkTreeViewColumn *tree_column,
GtkCellRenderer *cell,
GtkTreeModel *tree_model,
GtkTreeIter *iter,
gpointer data)
{
int value;
gchar text;
gtk_tree_model_get (tree_model, iter, COLUMN_CONTENT, &value, -1);
text = g_strdup_printf ("%d", value);
g_object_set (cell, "text", text);
g_free (text);
}
Finally in the edited callback you need to convert the string to an integer before you store it
int value = atoi (new_text);
gtk_list_store_set (list_store, &iter, COLUMN_CONTENT, value, -1);

Change text color of label in GTK in C

I am using Gtk 2.0.
I am trying to change the text color/font color of the label.
How difficult can it get? I am just trying things like gtk_widget_modify_text etc to no avail. I want to go the "android" or "Qt" way by say adding a simple resource file with all the styles. Where and as what(.rc?) should I add this file? How to parse this file?
I already wrote my App with a lot of widgets and I do not want to change/redo them all. Can somebody show me a simple example?
I even tried a Pango example from the web but the problem is the text in my label keeps changing and therefore I could not follow this.
Please help. Here is what I have tried so far and without success.
GtkWidget *label1;
label1= gtk_label_new(" ");
gtk_box_pack_start (GTK_BOX(box1), label1,TRUE,TRUE, 0);
GdkColor color;
gdk_color_parse ("white", &color);
gtk_widget_modify_text ( GTK_WIDGET(label1), GTK_STATE_NORMAL, &color);
gchar *stringMarkupText = "<span foreground=\"white\"> <b>Bold</b></span>"; //white color and bold--> the length of this text is fixed by number of spaces. I need to call a function that would set this text on a g_signal_connect so do not want to fix spaces!!
gchar *stringPlainText;
PangoAttrList *attrList;
pango_parse_markup(stringMarkupText, -1, 0, &attrList, &stringPlainText, NULL, NULL);
gtk_label_set_attributes(GTK_LABEL(label1), attrList);
From my point of view, you may use GTK resource file(rc file) in this case.
You can use the gtk_rc_parse function to load your rc file.
void gtk_rc_parse(const gchar *filename);

Resources