Does GtkAboutDialog crashes when trying to show for the second time - c

I am using a GtkAboutDialog to open on a button click. It works fine on the first click but on the second click it just crashes. On the button clicked signal I am just using gtk_widget_show() to display the dialog. The about dialog is described in a .ui file
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.38.1 -->
<interface>
<requires lib="gtk+" version="3.24"/>
<object class="GtkAboutDialog" id="about_warehouse_dialog">
<property name="name">about_warehouse</property>
<property name="can-focus">False</property>
<property name="destroy-with-parent">True</property>
<property name="type-hint">dialog</property>
<property name="program-name">Պահեստ</property>
<property name="version">1.0</property>
<property name="copyright" translatable="yes">
text
</property>
<property name="authors">Grigor Sargsyan <Mr.G.Sargsyan#master-mind.llc>
Int Elligence Group <IntElligence#master-mind.llc></property>
<property name="documenters">Artur Tarasyan <Mr.Tarasyan#master-mind.llc></property>
<property name="translator-credits" translatable="yes">Grigor Sargsyan <Mr.G.Sargsyan#master-mind.llc> </property>
<property name="artists">Janik Tarverdyan <Mr.J.Tarverdyan#master-mind.llc></property>
<property name="logo">../../data/media/image/Logo/Logo_About.png</property>
<property name="wrap-license">True</property>
<property name="license-type">custom</property>
<child internal-child="vbox">
<object class="GtkBox">
<property name="can-focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">2</property>
<child internal-child="action_area">
<object class="GtkButtonBox">
<property name="can-focus">False</property>
<property name="layout-style">end</property>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</object>
</child>
</object>
I am retrieving the GtkAboutDialog described there with a GtkBuilder object and assigning it to a pointer for which I am calling gtk_widget_show(). I am not sure why this happens. I have not defined any signals for destroying the object.
C code:
I am retrieving the object this way where main_wind_ob->pmenu_builder is the GtkBuilder object associated with the .ui file mentioned above.
main_wind_ob->about_dialog = GTK_WIDGET
(
gtk_builder_get_object
(
main_wind_ob->pmenu_builder,
"about_warehouse_dialog"
)
);
Here is the button clicked signal which is supposed to show the dialog.
static void
on_pmenu_about_dialog_clicked(GtkButton * button,
gpointer userdata)
{
#ifdef DEBUG
printf("\non_pmenu_about_dialog_clicked()\n");
#endif
mainwindow * main_wind = MAIN_WINDOW(userdata);
gtk_widget_show(main_wind->about_dialog);
}

Related

Gtk Tree View columns size to view

I'm a newbie to Gtk3 but I can't find how to do what I want anywhere. I'm trying to get a tree view representing article citations.
Desired outcome:
columns are resizable
no horizontal scrollbar
columns take only as much space as needed, they don't expand the window if content is too long
in case a cell's content is too long, either break the text over several lines (best) or trim it and add "..." (ok), just trim it (I could settle for that)
As an example of what I want, here's Zotero trimming columns with "..."
This is my widget hierarchy:
What I tried (using Glade + C):
Default settings: a horizontal scrollbar appears
Set ScrolledWindow horizontal scroll policy to "Never", auto sizing to column: window expands to fit content, e.g.
Set ScrolledWindow horizontal scroll policy to "Never", fixed sizing columns, with maximum width: contents is trimmed (not "...", no text reflow), but I can only resize columns to the arbiratry size I've given them.
Set ScrolledWindow horizontal scroll policy to "External", auto sizing columns, columns set to resizable: columns are not resizable, contents is not trimmed.
Here's variation 4 with source + XML file generated by Glade:
#include <gtk/gtk.h>
void on_window_main_destroy();
enum {
AUTHORS_COLUMN = 0,
TITLE_COLUMN,
N_COLUMNS
};
static void init_reference_list(GtkBuilder* builder)
{
GtkCellRenderer* renderer;
GtkWidget* tree_widget;
tree_widget = GTK_WIDGET(gtk_builder_get_object(builder, "tree_view"));
// -- Add attributes to Glade-generated columns
GtkTreeViewColumn* column;
renderer = gtk_cell_renderer_text_new();
column = GTK_TREE_VIEW_COLUMN(gtk_builder_get_object(builder, "title"));
gtk_tree_view_column_pack_start(column, renderer, FALSE);
gtk_tree_view_column_add_attribute(column, renderer, "text", TITLE_COLUMN );
column = GTK_TREE_VIEW_COLUMN(gtk_builder_get_object(builder, "authors"));
gtk_tree_view_column_pack_start(column, renderer, FALSE);
gtk_tree_view_column_add_attribute(column, renderer, "text", AUTHORS_COLUMN );
// -- Set up store and connect it to view
GtkListStore* store;
store = gtk_list_store_new(N_COLUMNS, G_TYPE_STRING, G_TYPE_STRING );
gtk_tree_view_set_model(GTK_TREE_VIEW(tree_widget), GTK_TREE_MODEL(store));
// -- Placing fake data in store
char title[] = "A long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long title";
char authors[] = "Me You Us Them All of us";
GtkTreeIter iter;
int i;
for (int i = 0; i < 500; ++i)
{
gtk_list_store_append(store, &iter);
gtk_list_store_set(store, &iter, AUTHORS_COLUMN, authors, TITLE_COLUMN, title, -1 );
}
}
// called when window is closed
void on_window_main_destroy()
{
gtk_main_quit();
}
int main(int argc, char *argv[])
{
gtk_init(&argc, &argv);
// -- load builder
GtkBuilder* builder;
builder = gtk_builder_new();
gtk_builder_add_from_file (builder, "resources/ui/ref_search.glade", NULL);
gtk_builder_connect_signals(builder, NULL);
// -- Cell Renderer and fake data
init_reference_list(builder);
// -- Launch
GtkWidget *window;
window = GTK_WIDGET(gtk_builder_get_object(builder, "window_main"));
gtk_widget_show(window);
g_object_unref(builder);
gtk_main();
return 0;
}
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkEntryBuffer" id="search_buffer"/>
<object class="GtkWindow" id="window_main">
<property name="can_focus">False</property>
<property name="halign">baseline</property>
<property name="valign">baseline</property>
<property name="title" translatable="yes">Reference Manager</property>
<property name="resizable">False</property>
<property name="default_width">640</property>
<property name="default_height">480</property>
<signal name="destroy" handler="on_window_main_destroy" swapped="no"/>
<child type="titlebar">
<placeholder/>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkSearchEntry" id="search_bar">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="buffer">search_buffer</property>
<property name="primary_icon_name">edit-find-symbolic</property>
<property name="primary_icon_activatable">False</property>
<property name="primary_icon_sensitive">False</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">external</property>
<property name="shadow_type">in</property>
<property name="max_content_height">500</property>
<child>
<object class="GtkTreeView" id="tree_view">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="rules_hint">True</property>
<property name="enable_search">False</property>
<property name="show_expanders">False</property>
<property name="enable_grid_lines">horizontal</property>
<child internal-child="selection">
<object class="GtkTreeSelection"/>
</child>
<child>
<object class="GtkTreeViewColumn" id="authors">
<property name="resizable">True</property>
<property name="sizing">autosize</property>
<property name="title" translatable="yes">Author(s)</property>
<property name="expand">True</property>
<property name="clickable">True</property>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="title">
<property name="resizable">True</property>
<property name="sizing">autosize</property>
<property name="title" translatable="yes">Title</property>
<property name="expand">True</property>
<property name="clickable">True</property>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
</interface>
Apologies if I'm missing the obvious!
This might be closer to what you are looking for in the Glade file:
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.2 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkListStore" id="liststore1">
<columns>
<!-- column-name authors -->
<column type="gchararray"/>
<!-- column-name titles -->
<column type="gchararray"/>
</columns>
<data>
<row>
<col id="0" translatable="yes">Me You Us Them All of us</col>
<col id="1" translatable="yes">A long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long title</col>
</row>
</data>
</object>
<object class="GtkEntryBuffer" id="search_buffer"/>
<object class="GtkWindow" id="window_main">
<property name="can_focus">False</property>
<property name="halign">baseline</property>
<property name="valign">baseline</property>
<property name="title" translatable="yes">Reference Manager</property>
<property name="resizable">False</property>
<property name="default_width">640</property>
<property name="default_height">480</property>
<signal name="destroy" handler="on_window_main_destroy" swapped="no"/>
<child type="titlebar">
<placeholder/>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkSearchEntry" id="search_bar">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="buffer">search_buffer</property>
<property name="primary_icon_name">edit-find-symbolic</property>
<property name="primary_icon_activatable">False</property>
<property name="primary_icon_sensitive">False</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">external</property>
<property name="shadow_type">in</property>
<property name="max_content_height">500</property>
<child>
<object class="GtkTreeView" id="tree_view">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="model">liststore1</property>
<property name="rules_hint">True</property>
<property name="enable_search">False</property>
<property name="show_expanders">False</property>
<property name="enable_grid_lines">horizontal</property>
<child internal-child="selection">
<object class="GtkTreeSelection"/>
</child>
<child>
<object class="GtkTreeViewColumn" id="authors">
<property name="resizable">True</property>
<property name="sizing">fixed</property>
<property name="title" translatable="yes">Author(s)</property>
<property name="expand">True</property>
<property name="clickable">True</property>
<child>
<object class="GtkCellRendererText">
<property name="ellipsize">middle</property>
</object>
<attributes>
<attribute name="text">0</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="title">
<property name="resizable">True</property>
<property name="sizing">fixed</property>
<property name="title" translatable="yes">Title</property>
<property name="expand">True</property>
<property name="clickable">True</property>
<child>
<object class="GtkCellRendererText">
<property name="ellipsize">middle</property>
</object>
<attributes>
<attribute name="text">1</attribute>
</attributes>
</child>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
</interface>
Edit with another attempt:
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkListStore" id="liststore1">
<columns>
<!-- column-name authors -->
<column type="gchararray"/>
<!-- column-name titles -->
<column type="gchararray"/>
</columns>
<data>
<row>
<col id="0" translatable="yes">Me You Us Them All of us</col>
<col id="1" translatable="yes">A long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long title</col>
</row>
</data>
</object>
<object class="GtkEntryBuffer" id="search_buffer"/>
<object class="GtkWindow" id="window_main">
<property name="width_request">250</property>
<property name="can_focus">False</property>
<property name="title" translatable="yes">Reference Manager</property>
<property name="resizable">False</property>
<property name="default_width">640</property>
<property name="default_height">480</property>
<signal name="destroy" handler="on_window_main_destroy" swapped="no"/>
<child type="titlebar">
<placeholder/>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkSearchEntry" id="search_bar">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="buffer">search_buffer</property>
<property name="primary_icon_name">edit-find-symbolic</property>
<property name="primary_icon_activatable">False</property>
<property name="primary_icon_sensitive">False</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">never</property>
<property name="shadow_type">in</property>
<property name="max_content_height">500</property>
<child>
<object class="GtkTreeView" id="tree_view">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="model">liststore1</property>
<property name="rules_hint">True</property>
<property name="enable_search">False</property>
<property name="show_expanders">False</property>
<property name="enable_grid_lines">horizontal</property>
<child internal-child="selection">
<object class="GtkTreeSelection"/>
</child>
<child>
<object class="GtkTreeViewColumn" id="authors">
<property name="resizable">True</property>
<property name="sizing">fixed</property>
<property name="min_width">25</property>
<property name="title" translatable="yes">Author(s)</property>
<property name="expand">True</property>
<property name="clickable">True</property>
<child>
<object class="GtkCellRendererText">
<property name="ellipsize">middle</property>
</object>
<attributes>
<attribute name="text">0</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="title">
<property name="resizable">True</property>
<property name="min_width">25</property>
<property name="title" translatable="yes">Title</property>
<property name="expand">True</property>
<property name="clickable">True</property>
<child>
<object class="GtkCellRendererText">
<property name="ellipsize">middle</property>
</object>
<attributes>
<attribute name="text">1</attribute>
</attributes>
</child>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
</interface>

Binding Toggle Buttons to each other using Glade & GTK+ (in C)

I have two toggle buttons named RUN and KILL. When I toggle on (i.e. depress) the RUN button, I only want it to toggle off by depressing the KILL toggle button (NOT by toggling off the RUN button). I want any subsequent mouse clicks on the RUN button to do nothing unless the KILL button is depressed. Likewise, when the KILL button is toggled on, I only want it to toggle off by depressing the RUN button (again, NOT by toggling off the KILL button). I am not sure how to construct the event handlers that would bind the action of these two toggle buttons together. I am using GTK+ together with Glade and programming in C.
Since the GtkToggleButton is a generic button and it will toggle with all user interactions we must prevent it from toggling under certain conditions. In this case, the button after being toggled can't be toggled again on itself but via another toggle button. To achieve this, you must:
Prevent button events from toggling the button under certain conditions
Bind both buttons with inverted logic (mutually exclusive)
To achieve 1) we can connect a callback to the GtkWidget "button-press-event" signal and return according to the wanted conditions, with TRUE preventing the signal from propagating and FALSE otherwise.
Then, to handle 2), we can use g_object_bind_property for the GtkToggleButton "active" property with G_BINDING_INVERTED_BOOLEAN flag to get the desired behavior. Notice that we must set one of them active as a start condition.
So, a simple example could be:
#include <gtk/gtk.h>
gboolean on_toggle_button_press_event(GtkWidget *widget, GdkEventButton *event, gpointer user_data) {
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)) == TRUE) {
return TRUE;
}
return FALSE;
}
void on_run_toggle_active(GObject *obj, GParamSpec *pspec, gpointer user_data) {
g_return_if_fail (user_data != NULL);
GtkLabel *label = GTK_LABEL(user_data);
GtkToggleButton *button = GTK_TOGGLE_BUTTON(obj);
if (gtk_toggle_button_get_active(button) == TRUE) {
gtk_label_set_text (label, "Running...");
} else {
gtk_label_set_text (label, "Idle");
}
}
gint main(gint argc, gchar **argv) {
GtkLabel *status;
GtkWindow *window;
GtkBuilder *builder;
GtkToggleButton *run_toggle;
GtkToggleButton *kill_toggle;
gtk_init(&argc, &argv);
builder = gtk_builder_new_from_file("gui.ui");
window = GTK_WINDOW(gtk_builder_get_object(builder, "window1"));
status = GTK_LABEL(gtk_builder_get_object(builder, "status"));
run_toggle = GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "toggle"));
kill_toggle = GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "kill"));
g_object_bind_property (G_OBJECT(run_toggle), "active", G_OBJECT(kill_toggle), "active", G_BINDING_INVERT_BOOLEAN);
g_object_bind_property (G_OBJECT(kill_toggle), "active", G_OBJECT(run_toggle), "active", G_BINDING_INVERT_BOOLEAN);
g_signal_connect(G_OBJECT(run_toggle), "button-press-event", G_CALLBACK(on_toggle_button_press_event), NULL);
g_signal_connect(G_OBJECT(kill_toggle), "button-press-event", G_CALLBACK(on_toggle_button_press_event), NULL);
g_signal_connect(G_OBJECT(run_toggle), "notify::active", G_CALLBACK(on_run_toggle_active), status);
g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
gtk_widget_show_all(GTK_WIDGET(window));
gtk_main();
return 0;
}
To simplify, I've outlined the user interface with glade (gui.ui):
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.2 -->
<interface>
<requires lib="gtk+" version="3.18"/>
<object class="GtkWindow" id="window1">
<property name="can_focus">False</property>
<child>
<object class="GtkGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">center</property>
<property name="valign">center</property>
<property name="row_spacing">20</property>
<child>
<object class="GtkLabel" id="status">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Idle</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
<property name="width">2</property>
</packing>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkToggleButton" id="toggle">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="focus_on_click">False</property>
<property name="receives_default">True</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">3</property>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="icon_name">media-playback-start-symbolic</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Run</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkToggleButton" id="kill">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="active">True</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">3</property>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="icon_name">user-trash-symbolic</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Kill</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<style>
<class name="linked"/>
</style>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
<property name="width">2</property>
</packing>
</child>
</object>
</child>
<child type="titlebar">
<placeholder/>
</child>
</object>
<object class="GtkSizeGroup">
<widgets>
<widget name="label1"/>
<widget name="label2"/>
</widgets>
</object>
</interface>
Compile with:
gcc -o main main.c `pkg-config --cflags --libs gtk+-3.0`
And the output should be something like this:
The Toggle Buttons are mutually exclusive and pressing them while active won't have any visual effect.
PS: No keyboard handling is assumed, otherwise we must handle those signals and act accordingly.

Trouble hiding and showing widgets in response to event

Problem
I have a problem where closing a widget with the delete event, via gtk_widget_hide_on_delete fails to show the menu widget again via a swapped gtk_widget_show_all with the corresponding widget passed to it as an argument.
Background
I'm creating a program consisting of a selection menu with a number of button widgets. Pressing one button will hide the menu, and show a window widget containing a label and a TextEntry, the delete event of this window widget will hide the widget, and show the menu again.
Example program
I've created a minimal example for this problem. The code simply loads the ui via GtkBuilder and then enters the main gtk loop.
I rely on gtk_widget_show_all, gtk_widget_hide and gtk_widget_hide_on_delete, but when I close the exercise widget using the delete-event, the window disappears, but the menu widget isn't shown.
#include <gtk/gtk.h>
#include <stdio.h>
int main(int argc, char **argv)
{
GtkBuilder * builder;
GtkWidget * menu;
GError *error = NULL;
gtk_init(&argc, &argv);
builder = gtk_builder_new();
if (!gtk_builder_add_from_file(builder, "example.glade", &error)) {
g_warning("%s", error->message);
g_free(error);
fprintf(stderr, "Failed to load build file");
}
menu = (GtkWidget *) gtk_builder_get_object(builder, "menu");
gtk_builder_connect_signals(builder, NULL);
gtk_widget_show(menu);
gtk_main();
return 0;
}
The XML file example.glade has been created using Glade.
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.16.1 -->
<interface>
<requires lib="gtk+" version="3.10"/>
<object class="GtkWindow" id="exercise">
<property name="can_focus">False</property>
<property name="window_position">center</property>
<signal name="delete-event" handler="gtk_widget_hide_on_delete" swapped="no"/>
<signal name="delete-event" handler="gtk_widget_show_all" object="menu" after="yes" swapped="yes"/>
<child>
<object class="GtkGrid" id="grid2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkEntry" id="entry1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hexpand">True</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="label" translatable="yes">A window where stuff will happen.</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
</object>
</child>
</object>
<object class="GtkWindow" id="menu">
<property name="can_focus">False</property>
<property name="window_position">center</property>
<signal name="destroy" handler="gtk_main_quit" swapped="no"/>
<child>
<object class="GtkGrid" id="grid1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkButton" id="button1">
<property name="label" translatable="yes">button1</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<signal name="clicked" handler="gtk_widget_hide" object="menu" swapped="yes"/>
<signal name="clicked" handler="gtk_widget_show_all" object="exercise" swapped="yes"/>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="button2">
<property name="label" translatable="yes">button2</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<signal name="clicked" handler="gtk_widget_hide" object="menu" swapped="yes"/>
<signal name="clicked" handler="gtk_widget_show_all" object="exercise" swapped="yes"/>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
</object>
</child>
</object>
</interface>
The problem is in these two lines of your Glade file:
<signal name="delete-event" handler="gtk_widget_hide_on_delete" swapped="no"/>
<signal name="delete-event" handler="gtk_widget_show_all" object="menu" after="yes" swapped="yes"/>
Looking at the manual page of gtk_widget_hide_on_delete(), we see:
Utility function; intended to be connected to the “delete-event” signal on a GtkWindow. The function calls gtk_widget_hide() on its argument, then returns TRUE.
If we look at the delete-event signal, we see:
Returns
TRUE to stop other handlers from being invoked for the event. FALSE to propagate the event further.
This means that after the gtk_widget_hide_on_delete() is called, TRUE is returned, and this stops the GTK runtime from calling gtk_widget_show_all().
To achieve what you want, you can use a custom-defined handler, as shown below:
Remove that two lines and replace with the following:
<signal name="delete-event" handler="my_custom_func" object="menu" swapped="no"/>
Add your custom handler to the C file:
G_MODULE_EXPORT gboolean
my_custom_func(GtkWidget *w, GdkEvent *e, gpointer u) {
gtk_widget_hide(w);
gtk_widget_show_all(GTK_WIDGET(u));
return TRUE;
}

GTK pass user data to callback using Glade

I notice that Glade only allows you to set an object to be passed within the user data part of a GTK callback.
Is there any way I can pass an integer value instead?
I have a set of menu items which I would like to point at the same callback function, however for a small section of the code I need to identify which menu item was the one which called the callback.
Note:
All my signals are setup automatically with glade_xml_signal_autoconnect, and I would perfer to keep it this way.
In my opinion with respect to glade and callbacks one have to say goodbye to the notion of passing just one single element to callbacks. And thus stop using glade in order to configure the user data that is passed to a specific callback.
I get used to pass a struct named App to all callbacks that contains a pointer to every ui element that is loaded from the ui definitions file and already instantiated by GtkBuilder. This also stops the tedious task in glade of clicking back and forth between widgets only to set up the user data of the callbacks. In addition to the ui elements, most of the time this struct contains further elements that are important at runtime on application level.
A benefit of this approach is that you are not tempted to think about how to implement an individual callback that should act upon more than one element which is often the case. Some people tackle this by grouping the widgets of interest into a container. In order to pass all widgets to the callback they just pass the container. Then in the callback they get the widgets by calling gtk_container_get_children or similar functions. This approach makes callbacks illegible and reduce the fun while editing the code.
If every callback has all elements available that should be manipulated at runtime you don't have to care about implementing a single callback since every callback shares the same structure.
Further i created a helper macro that defines a pointer to an already instantiated element with the name of its glade id. This way the elements definitions in the code are always in sync with those that are displayed in glade. That makes renaming of widgets very easy (substitute the name in all sources + the glade file).
To illustrate this approach i have appended files of a sample program. Don't be scared of the number of files. Dividing a program into logical units/modules makes programming much simpler. To get a quick view of the whole project i created a git repository on github:
https://github.com/o8i12398z12h9h/gtk-sample-app
Just compare my callbacks.c with your callback file(s). I would be interested to know how they compare with respect to legibility and structure and taking into account that you may have the element-ids from glade still in mind.
callbacks.c:
#include "app.h"
void
button1_clicked_cb (GtkButton * button, App * app)
{
GET_UI_ELEMENT (GtkEntry, entry1);
if (gtk_entry_get_text_length (entry1) == 0)
gtk_entry_set_text (entry1, "test");
else
gtk_entry_set_text (entry1, "");
}
void
button2_clicked_cb (GtkButton * button, App * app)
{
gboolean active;
GET_UI_ELEMENT (GtkSpinner, spinner1);
GET_UI_ELEMENT (GtkWidget, eventbox1);
g_object_get (G_OBJECT (spinner1), "active", &active,
NULL);
if (active) {
gtk_spinner_stop (spinner1);
gtk_widget_override_background_color (eventbox1,
GTK_STATE_FLAG_NORMAL,
app->
active_color);
}
else {
gtk_spinner_start (spinner1);
gtk_widget_override_background_color (eventbox1,
GTK_STATE_FLAG_NORMAL,
app->
inactive_color);
}
}
void
button3_clicked_cb (GtkButton * button, App * app)
{
GdkRGBA bg = { 0, 0, 1, 1 };
GET_UI_ELEMENT (GtkWidget, eventbox1);
gtk_widget_override_background_color (eventbox1,
GTK_STATE_FLAG_NORMAL,
&bg);
}
void
button4_clicked_cb (GtkButton * button, App * app)
{
const gchar *str;
GET_UI_ELEMENT (GtkLabel, label1);
str = gtk_label_get_text (label1);
if (strcmp (str, "label") == 0) {
gtk_label_set_text (label1, "NewText");
}
else {
gtk_label_set_text (label1, "label");
}
}
void
button5_clicked_cb (GtkButton * button, App * app)
{
GET_UI_ELEMENT (GtkWidget, button1);
GET_UI_ELEMENT (GtkWidget, button2);
GET_UI_ELEMENT (GtkWidget, button4);
g_signal_emit_by_name (button1, "clicked", app);
g_signal_emit_by_name (button2, "clicked", app);
g_signal_emit_by_name (button4, "clicked", app);
}
main.c:
#include "app.h"
int
main (int argc, char *argv[])
{
App *app;
app = (App *) g_new (App, 1);
gtk_init (&argc, &argv);
app_init (app);
GET_UI_ELEMENT (GtkWidget, window1);
gtk_widget_show_all (window1);
gtk_main ();
return 0;
}
app.c:
#include "app.h"
GObject *
app_get_ui_element (App * app, const gchar * name)
{
const gchar *s;
GSList *list;
list = app->objects;
do {
s = gtk_buildable_get_name (list->data);
if (strcmp (s, name) == 0) {
return list->data;
}
} while (list = g_slist_next (list));
return NULL;
}
void
app_init_colors (App * app)
{
GdkRGBA active_color = { 1, 0, 0, 1 };
GdkRGBA inactive_color = { 0, 1, 0, 1 };
app->active_color = g_new0 (GdkRGBA, 1);
app->inactive_color = g_new0 (GdkRGBA, 1);
app->active_color = gdk_rgba_copy (&active_color);
app->inactive_color = gdk_rgba_copy (&inactive_color);
}
void
app_init (App * app)
{
GError *err = NULL;
app->definitions = gtk_builder_new ();
gtk_builder_add_from_file (app->definitions,
UI_DEFINITIONS_FILE, &err);
if (err != NULL) {
g_printerr
("Error while loading app definitions file: %s\n",
err->message);
g_error_free (err);
gtk_main_quit ();
}
gtk_builder_connect_signals (app->definitions, app);
app->objects = gtk_builder_get_objects (app->definitions);
app_init_colors (app);
}
app.h:
#ifndef __APP__
#define __APP__
#include <gtk/gtk.h>
#define UI_DEFINITIONS_FILE "ui.glade"
#define GET_UI_ELEMENT(TYPE, ELEMENT) TYPE *ELEMENT = (TYPE *) \
app_get_ui_element(app, #ELEMENT);
typedef struct app_
{
GtkBuilder *definitions;
GSList *objects;
GdkRGBA *active_color;
GdkRGBA *inactive_color;
} App;
void app_init (App * );
GObject * app_get_ui_element (App * , const gchar * );
#endif
ui.glade:
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<!-- interface-requires gtk+ 3.0 -->
<object class="GtkWindow" id="window1">
<property name="can_focus">False</property>
<property name="border_width">20</property>
<signal name="destroy" handler="gtk_main_quit" swapped="no"/>
<child>
<object class="GtkGrid" id="grid1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="row_spacing">10</property>
<property name="column_spacing">20</property>
<child>
<object class="GtkSpinner" id="spinner1">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
<property name="width">2</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkEventBox" id="eventbox1">
<property name="height_request">50</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">2</property>
<property name="width">2</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="entry1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="invisible_char">•</property>
<property name="invisible_char_set">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
<property name="width">2</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">label</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">3</property>
<property name="width">2</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkButtonBox" id="buttonbox1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">10</property>
<property name="layout_style">center</property>
<child>
<object class="GtkButton" id="button1">
<property name="label" translatable="yes">toggle entry</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<signal name="clicked" handler="button1_clicked_cb" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="button2">
<property name="label" translatable="yes">toggle spinner + bg</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<signal name="clicked" handler="button2_clicked_cb" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="button3">
<property name="label" translatable="yes">set bg</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<signal name="clicked" handler="button3_clicked_cb" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkButton" id="button4">
<property name="label" translatable="yes">toggle label</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<signal name="clicked" handler="button4_clicked_cb" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">3</property>
</packing>
</child>
<child>
<object class="GtkButton" id="button5">
<property name="label" translatable="yes">toggle everything</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<signal name="clicked" handler="button5_clicked_cb" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">4</property>
</packing>
</child>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">5</property>
<property name="width">4</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkSeparator" id="separator1">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">4</property>
<property name="width">4</property>
<property name="height">1</property>
</packing>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</object>
</child>
</object>
</interface>

Programmatically Adding Data to a GtkTreeView/GtkListStore Created in Glade 3.12.1

I've been teaching myself how to code in C and utilize GTK for writing applications in Linux, using Glade to design the UI before implementing it. I've been trying to utilize a GtkTreeView coupled with a GtkListStore to display data, but I seem to be running into issues. I can get my application to launch fine and it shows the window and dialog correctly, but I cannot figure out how to add rows of data to the List Store programmatically and have them appear in the Tree View; most tutorials I find seem to prefer to make the rows in Glade, or to design the whole interface through the code. With the code as it is I receive no errors when running the program, but I cannot see anything being added in GtkTreeView. I don't see any blank rows being added either.
By writing some code to forcibly generate an error, I can see that the signal for postingButton is being connected (I think) so that should be fine. I'm just missing something in my actual implementation of GtkTreeView. If anyone can help me out, I'd greatly appreciate it!
Edit: The GtkEntries that are present will be implemented later; I'm just trying to get data to show up at all.
C Code:
/* I'd give objects better names normally, no worries!
* Just goofing around for now.*/
#include <gtk-3.0/gtk/gtk.h> // Needed for interface.
#include <gtk-3.0/gdk/gdk.h>
#include <glib-2.0/glib-object.h>
void on_mainWindow_destroy(GObject *object, gpointer user_data)
{
gtk_main_quit();
}
void on_stupidButton_clicked(GtkButton *button, gpointer *user_data)
{
gtk_dialog_run(GTK_DIALOG(user_data));
}
void on_postingButton_clicked(GtkButton *button, gpointer *user_data)
{
GtkListStore *liststore1;
GtkWidget *treeview1; // I've tried defining this as a GtkTreeView as well.
GtkTreeIter iter;
GtkBuilder *listStoreBuilder;
listStoreBuilder = gtk_builder_new();
gtk_builder_add_from_file(listStoreBuilder,
"../testing_interface.glade", 0);
treeview1 = GTK_WIDGET(gtk_builder_get_object(listStoreBuilder,
"treeview1")); // I'd change this to GTK_TREE_VIEW if the
// above is a GtkTreeView.
liststore1 = GTK_LIST_STORE(
gtk_tree_view_get_model((GtkTreeView *)treeview1));
gtk_list_store_append(liststore1, &iter);
gtk_list_store_set(liststore1, &iter, 0, "c", 1, "d", -1);
gtk_builder_connect_signals(listStoreBuilder, 0);
g_object_unref(G_OBJECT(listStoreBuilder));
g_object_unref(G_OBJECT(liststore1));
}
void on_cancelButton_clicked(GtkButton *button, gpointer *user_data)
{
gtk_widget_destroy((GtkWidget *)user_data);
}
int main(int argc, char *argv[])
{
GtkBuilder *builder;
GtkWidget *mainWindow, *dumbDialog;
GtkButton *stupidButton;
gtk_init(&argc, &argv);
builder = gtk_builder_new();
gtk_builder_add_from_file(builder, "../testing_interface.glade",
0);
mainWindow = GTK_WIDGET(gtk_builder_get_object(builder, "mainWindow"));
stupidButton = GTK_BUTTON(gtk_builder_get_object(builder, "stupidButton"));
dumbDialog = GTK_WIDGET(gtk_builder_get_object(builder, "dumbDialog"));
gtk_builder_connect_signals(builder, 0);
g_object_unref(G_OBJECT(builder));
gtk_widget_show(mainWindow);
gtk_main();
return 0;
}
Glade File (testing_interface.glade):
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<!-- interface-requires gtk+ 3.0 -->
<object class="GtkDialog" id="dumbDialog">
<property name="can_focus">False</property>
<property name="border_width">5</property>
<property name="type_hint">dialog</property>
<child internal-child="vbox">
<object class="GtkBox" id="dialog-vbox1">
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">2</property>
<child internal-child="action_area">
<object class="GtkButtonBox" id="dialog-action_area1">
<property name="can_focus">False</property>
<property name="layout_style">end</property>
<child>
<object class="GtkButton" id="postingButton">
<property name="label" translatable="yes">Post</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<signal name="clicked" handler="on_postingButton_clicked" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="cancelButton">
<property name="label" translatable="yes">Cancel</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<signal name="clicked" handler="on_cancelButton_clicked" object="dumbDialog" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkBox" id="box2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkEntry" id="entry1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="invisible_char">●</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="entry2">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="invisible_char">●</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
<action-widgets>
<action-widget response="0">postingButton</action-widget>
<action-widget response="0">cancelButton</action-widget>
</action-widgets>
</object>
<object class="GtkListStore" id="liststore1">
<columns>
<!-- column-name Testing -->
<column type="gchararray"/>
<!-- column-name Testing1 -->
<column type="gchararray"/>
</columns>
</object>
<object class="GtkWindow" id="mainWindow">
<property name="can_focus">False</property>
<signal name="destroy" handler="on_mainWindow_destroy" swapped="no"/>
<child>
<object class="GtkBox" id="box1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkTreeView" id="treeview1">
<property name="height_request">183</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="model">liststore1</property>
<child internal-child="selection">
<object class="GtkTreeSelection" id="treeview-selection1"/>
</child>
<child>
<object class="GtkTreeViewColumn" id="testing1Col">
<property name="title" translatable="yes">column</property>
<child>
<object class="GtkCellRendererText" id="cellrenderertext1"/>
<attributes>
<attribute name="text">0</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="testing2Col">
<property name="title" translatable="yes">column</property>
<child>
<object class="GtkCellRendererText" id="cellrenderertext2"/>
<attributes>
<attribute name="text">1</attribute>
</attributes>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="stupidButton">
<property name="label" translatable="yes">button</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<signal name="clicked" handler="on_stupidButton_clicked" object="dumbDialog" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
</interface>
Your code that appends rows to the tree view is basically okay, but several problems prevent it from working.
You are creating and populating a new builder on each entry to on_postingButton_clicked. This is obviously incorrect, because it means that you're creating a new tree and a new store on each click of the Post button. This is easily fixed by sending treeview1 as user_data to the on_postingButton_clicked callback. You do that already in dialog, so I simply modified <signal name="clicked" handler="on_postingButton_clicked" ...> in your XML to also include object="treeview1".
You are being too liberal with g_object_unref. gtk_tree_view_get_model doesn't increase the refcount of its model, so you shouldn't unref the liststore you get. Unrefing the builder in main is probably a bad idea if you want to pass it around and retrieve objects from it (and it's a singleton anyway).
You're supposed to #include <gtk/gtk.h>, without the intervening gtk-3.0 directory. If your compilation fails without that, you are probably not setting up pkg-flags correctly.
Here is a modified version of your code that works for me. It requires XML to be modified as described above.
/* compile with:
gcc -O2 -Wall glade-test.c $(pkg-config gtk+-3.0 gmodule-export-2.0 --cflags --libs) */
#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include <glib-object.h>
void on_mainWindow_destroy(GObject *object, gpointer user_data)
{
gtk_main_quit();
}
void on_stupidButton_clicked(GtkButton *button, gpointer *user_data)
{
gtk_dialog_run(GTK_DIALOG(user_data));
}
void on_postingButton_clicked(GtkButton *button, gpointer *user_data)
{
GtkTreeIter iter;
GtkTreeView *treeview1 = GTK_TREE_VIEW(user_data);
GtkListStore *liststore1 = GTK_LIST_STORE(gtk_tree_view_get_model(treeview1));
gtk_list_store_append(liststore1, &iter);
gtk_list_store_set(liststore1, &iter, 0, "c", 1, "d", -1);
}
void on_cancelButton_clicked(GtkButton *button, gpointer *user_data)
{
gtk_widget_destroy((GtkWidget *)user_data);
}
int main(int argc, char *argv[])
{
GtkBuilder *builder;
gtk_init(&argc, &argv);
builder = gtk_builder_new();
gtk_builder_add_from_file(builder, "testing_interface.glade", 0);
gtk_builder_connect_signals(builder, 0);
gtk_widget_show(GTK_WIDGET(gtk_builder_get_object(builder, "mainWindow")));
g_object_unref(G_OBJECT(builder));
gtk_main();
return 0;
}

Resources