I'm building a GTK+ gui and I'm trying to use the GtkBuilder to do it.
There is a main window in which there is a notebook, a menu and two buttons. I want to fill the notebook with tabs when I click on a button.
So I created the main window from a file with a GtkBuilder, and then I try to add each tab to the builder.
For now, I did this (the unindented code are debug print):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gtk/gtk.h>
#include "main.h"
GtkBuilder* build;
int i;
#define TAB\
"<interface>\
<object class=\"GtkNotebook\" id=\"note\">\
<property name=\"scrollable\">t</property>\
<property name=\"show-border\">t</property>\
<property name=\"show-tabs\">t</property>\
<child>\
<object class=\"GtkLabel\" id=\"tab%d\">\
<property name=\"label\">Content%d</property>\
</object>\
</child>\
<child type=\"tab\">\
<object class=\"GtkLabel\" id=\"labTab%d\">\
<property name=\"label\">Label%d</property>\
</object>\
</child>\
</object>\
</interface>"
int main(int argc, char** argv) {
GtkWidget* window;
// GtkWidget* item;
GError* error=NULL;
GtkAccelGroup* accel_group;
i=0;
gtk_init(&argc, &argv);
build=gtk_builder_new();
if (gtk_builder_add_from_file(build, "gui.ui", &error)==0)
printf("erreur %s\n", error->message);
gtk_builder_add_callback_symbol(build, "quit", func);
gtk_builder_add_callback_symbol(build, "add", add);
gtk_builder_connect_signals(build, NULL);
window=(GtkWidget*)gtk_builder_get_object(build, "main");
gtk_window_maximize(GTK_WINDOW(window));
gtk_widget_show_all(window);
gtk_main();
return EXIT_SUCCESS;
}
void add() {
char* str;
GtkWidget* window;
GError* error=NULL;
FILE* file=NULL;
printf("in add 1\n");
if ((str=malloc(sizeof(TAB)+20))==NULL) {
perror("malloc");
exit(EXIT_FAILURE);
}
printf("in add 2\n");
snprintf(str, sizeof(TAB)+20, TAB, i, i, i, i);
printf("in add 3, str : %s\n", str);
if ((file=fopen("tmp.ui", "w"))==NULL) {
free(str);
perror("fopen");
exit(EXIT_FAILURE);
}
fprintf(file, TAB, i, i, i, i);
fclose(file);
/* if (gtk_builder_add_from_file(build, "tmp.ui", &error)==0)
printf("erreur %s\n", error->message);*/
if (gtk_builder_add_from_string(build, str, sizeof(str), &error)==0)
printf("erreur %s\n", error->message);
printf("in add 4\n");
if ((window=(GtkWidget*)gtk_builder_get_object(build, "main"))==NULL)
printf("Can't find\n");
else
gtk_widget_show_all(window);
sprintf(str, "tab%d", i);
if ((window=(GtkWidget*)gtk_builder_get_object(build, str))==NULL)
printf("in add, Does not exist (%s)\n", str);
else
printf("in add, Exist (%s)\n", str);
remove("tmp.ui");
free(str);
++i;
// free(error);
}
Here is my builder definition:
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<!-- Main window -->
<object class="GtkWindow" id="main">
<property name="title">Test Xml</property>
<property name="window-position">GTK_WIN_POS_CENTER</property>
<property name="default-width">1024</property>
<property name="default-height">512</property>
<signal name="delete-event" handler="quit"/>
<child>
<object class="GtkBox" id="mainBox">
<property name="orientation">GTK_ORIENTATION_VERTICAL</property>
<property name="spacing">5</property>
<!-- Menu -->
<child>
<object class="GtkMenuBar" id="menuBar">
<child>
<!-- Menu fichier -->
<object class="GtkMenuItem" id="m1">
<property name="label">_Fichier</property>
<property name="use_underline">True</property>
<child type="submenu">
<object class="GtkMenu" id="menu">
<property name="accel-group">accel_group</property>
<child>
<!-- Item Quitter -->
<object class="GtkMenuItem" id="i1">
<property name="accel-path"><Test>/FILE/QUIT</property>
<property name="label">_Quitter</property>
<property name="use_underline">True</property>
<signal name="activate" handler="quit"/>
</object>
<!-- End Item Quitter -->
</child>
</object>
</child>
</object>
<!-- End Menu fichier -->
</child>
</object>
</child>
<!-- End Menu -->
<!-- Frame -->
<child>
<object class="GtkFrame" id="mainframe">
<property name="expand">t</property>
<!-- Note book -->
<child>
<object class="GtkNotebook" id="note">
<property name="scrollable">t</property>
<property name="show-border">t</property>
<property name="show-tabs">t</property>
</object>
</child>
<!-- Note book -->
</object>
</child>
<!-- End Frame -->
<!-- Bottom box -->
<child>
<object class="GtkBox" id="bottomBox">
<property name="orientation">GTK_ORIENTATION_HORIZONTAL</property>
<property name="spacing">5</property>
<!-- Buttons -->
<child>
<object class="GtkButton" id="boutonPlus">
<property name="label">_Ajouter</property>
<property name="use-underline">t</property>
<signal name="activate" handler="add"/>
</object>
</child>
<child>
<object class="GtkButton" id="boutonMoins">
<property name="label">_Enlever</property>
<property name="use-underline">t</property>
</object>
</child>
<!-- End buttons -->
</object>
</child>
<!-- End Bottom box -->
</object>
</child>
</object>
</interface>
And here is the output:
in add 1
in add 2
in add 3, str : <interface>
<object class="GtkNotebook" id="note">
<property name="scrollable">t</property>
<property name="show-border">t</property>
<property name="show-tabs">t</property>
<child>
<object class="GtkLabel" id="tab0">
<property name="label">Content0</property>
</object>
</child>
<child type="tab">
<object class="GtkLabel" id="labTab0">
<property name="label">Label0</property>
</object>
</child>
</object>
</interface>
in add 4
in add, Does not exist (tab0)
As we can see, the tab is not add in the builder, but it seems there is no error when I add it.
- In the documentation it's said that, in case we want to merge some ui definitions we must use
gtk_builder_new(), and then usegtk_builder_add_from_...(). So I did it, and in myaddfunction, I try to add tab from string or from file just to see the problem was because I start to add from file and then from string, but it does not. - In the documentation, I didn't find anything about what it's needed to do the merge. So, to add the tab, I tried with/without the
<interface>and the nodebook definition. But it didn't change anything.
Is there some documentations about merging ui definitions with a GtkBulder, or can someone explain me what I'm doing wrong ?