How to pack widgets in a gtk_dialog window using gtk3 - c

In gtk2 the following code snippet works to pack widgets into a gtk_dialog window, using the vbox and action_area of the GtkDialog structure:
window=gtk_dialog_new();
gtk_container_set_border_width((GtkContainer *)window, 0);
scrolled_window=gtk_scrolled_window_new(NULL,NULL);
gtk_container_set_border_width((GtkContainer *)scrolled_window, 10);
gtk_scrolled_window_set_shadow_type((GtkScrolledWindow *)scrolled_window, GTK_SHADOW_IN);
gtk_scrolled_window_set_policy((GtkScrolledWindow *)scrolled_window, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_box_pack_start((GtkBox *) (GtkDialog *)window->vbox), scrolled_window, TRUE, TRUE, 0);
gtk_widget_show(scrolled_window);
label=gtk_label_new(text);
gtk_label_set_use_markup((GtkLabel *)label, TRUE);
gtk_label_set_selectable((GtkLabel *)label, TRUE);
gtk_label_set_line_wrap((GtkLabel *)label, FALSE);
gtk_scrolled_window_add_with_viewport((GtkScrolledWindow *)scrolled_window, label);
gtk_widget_show(label);
button=gtk_button_new_with_label("close");
g_signal_connect_swapped(button, "clicked", G_CALLBACK (gtk_widget_destroy), window);
gtk_widget_set_can_default(button, TRUE);
gtk_box_pack_start((GtkBox *) (GtkDialog *)window->action_area), button, TRUE, TRUE, 0);
gtk_widget_grab_default(button);
gtk_widget_show (button);
gtk_widget_show(window);
However in gtk3 this is not completely valid code any more. And it will not compile.
If I replace instances of:
(GtkBox *) (GtkDialog *)window->vbox
with:
(GtkBox *) (GtkDialog *)window
And do the same with instances of action_area the code will compile but the window will not show the extra packed widgets, just the ones the dialog comes with by default.
More information, which to me is a bit contradictory https://developer.gnome.org/gtk3/stable/GtkDialog.html#GtkDialog-struct
The GtkDialog contains only private fields and should not be directly
accessed.
But when I read this on the same page it seems to contradict the previous quote https://developer.gnome.org/gtk3/stable/GtkDialog.html#gtk-dialog-add-action-widget
If you want to add a non-activatable widget, simply pack it into the
action_area field of the GtkDialog struct.
Earlier in that document it states under GtkDialog as GtkBuildable
The GtkDialog implementation of the GtkBuildable interface exposes the
vbox and action_area as internal children with the names “vbox” and
“action_area”.
But I don't really know how to do that using the GtkBuildable interface neither do I want to. Or perhaps that is exactly what I did in gtk2 and it stopped working in gtk3...?
My question is how can I convert the gtk2 code to work with gtk3 with as few changes as possible. I have been searching for quite a while but found no answer yet. The existing gtk3 documentation leaves me going in circles. Maybe I just miss something totally obvious. Or perhaps you are not supposed to do this anymore and have to use a window instead of a dialog?
Thanks to the answer below I was able to change the code to this working one, it will also eliminate a deprecated warning about gtk_dialog_get_action_area() by using gtk_dialog_add_button()
window=gtk_dialog_new();
gtk_container_set_border_width((GtkContainer *)window, 0);
scrolled_window=gtk_scrolled_window_new(NULL,NULL);
gtk_container_set_border_width((GtkContainer *)scrolled_window, 10);
gtk_scrolled_window_set_shadow_type((GtkScrolledWindow *)scrolled_window, GTK_SHADOW_IN);
gtk_scrolled_window_set_policy((GtkScrolledWindow *)scrolled_window, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_box_pack_start((GtkBox *) (GtkDialog *) (gtk_dialog_get_content_area(window)), scrolled_window, TRUE, TRUE, 0);
gtk_widget_show(scrolled_window);
label=gtk_label_new(text);
gtk_label_set_use_markup((GtkLabel *)label, TRUE);
gtk_label_set_selectable((GtkLabel *)label, TRUE);
gtk_label_set_line_wrap((GtkLabel *)label, FALSE);
gtk_container_add((GtkContainer *)scrolled_window, label);
gtk_widget_show(label);
button=gtk_dialog_add_button((GtkDialog *)window, "close", GTK_RESPONSE_CLOSE);
g_signal_connect_swapped(button, "response", (GCallback *)gtk_widget_destroy, window);
gtk_widget_set_can_default(button, TRUE);
gtk_widget_grab_default(button);
gtk_widget_show(button);
gtk_widget_show(window);
gtk_dialog_run((GtkDialog*)window);
gtk_widget_destroy(window);

For the top section you gtk_dialog_get_content_area. This will return a VBox, where you can pack your own widgets.
For the bottom section you either gtk_dialog_add_button or gtk_dialog_add_action_widget.
The GtkDialog contains only private fields and should not be directly accessed.
If you want to add a non-activatable widget, simply pack it into the action_area field of the GtkDialog struct.
You should obtain a pointer to action_area with deprecated (!)gtk_dialog_get_action_area, but that will not allow to register a response id.

Related

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

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.

gtk_container_add function crashes

I have the following line in my GTK code:
gtk_container_add(GTK_CONTAINER(main_wind_ob->stack),
GTK_WIDGET(main_wind_ob->product_ob->swindow));
Where main_wind_on->stack is a GtkStack acquired this way
main_wind_ob->stack = GTK_STACK(
gtk_builder_get_object (
main_wind_ob->builder,
"stack"
)
);
Where main_wind_ob->builder is a GtkBuilder object associated with a .ui file where a GtkStack container is declared with the ID stack.
main_wind_ob->product_ob->swindow is a GtkScrolledWindow acquired like this:
main_wind_ob->product_ob->swindow =
gtk_scrolled_window_new(NULL, NULL);
I know neither main_wind_ob->product_ob->swindow or main_wind_ob->stack are not null as I've debugged and checked them.
What I wanted to do was make swindow be the child of the stack, but it just crashes when it reaches the gtk_container_add function call. I am not really sure why. Let me know if there is any extra details I can add to the post, thanks.

invoke row-activated with libgda-ui

Can someone provide a sample how to access to callbacks with Gnome-db libgda-ui, using this demo https://github.com/GNOME/libgda/blob/master/libgda-ui/demos/grid.c and I want to call a callback when I double click on a row like in gtktree with liststore
I think I've found a solution using the raw-grid
GtkWidget *grid;
GdauiRawGrid *raw_grid;
g_object_get (G_OBJECT (grid), "raw-grid", &raw_grid, NULL);
Then the raw_grid has the callback needed and it have methods like gtk treeview

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);

c - Passing multiple arguments to a callback function in GTK

So, I'm trying to achieve the following: The user shall be able to fill out multiple gtk_entry's and click Apply after that, on being clicked I want the Apply button to emit a signal, something like this:
g_signal_connect (G_OBJECT (Apply), "clicked",
G_CALLBACK(apply_clicked), # an argument #);
Afterwards, in apply_clicked(), I want the entered text to be saved.
My question is: How do I pass those gtk_entry's to my callback function apply_clicked?
If it were only one I'd just set it as # an argument #, but what should I do with multiple entries ?
The typical way of doing this is to do:
g_object_set_data (context_object, "entry1", entry1);
g_object_set_data (context_object, "entry2", entry2);
g_signal_connect (G_OBJECT (Apply), "clicked", G_CALLBACK (apply_clicked), context_object);
and then in apply_clicked:
GtkEntry *entry1 = g_object_get_data (context_object, "entry1");
...
Usually the context_object will be the GtkDialog or whatever these widgets exist on.
Alternatively, if you subclass the GtkDialog, you can do:
struct _MyDialog {
GtkDialog parent_object;
GtkEntry *entry1;
GtkEntry *entry2;
...
};
Then, when constructing your dialog, just set entry1, 2, 3, etc... and you don't need to use the g_object_[g,s]et_data() hack.
create a data structure (a linked list perhaps) to contain pointers to the gtk_entrys and pass that instead. Or better yet, why not just pass a pointer to the object which contains all of thise gtk_entrys?

Resources