ssuarezbe
ssuarezbe

Reputation: 191

Set Tree Store model in glade by code - GTK Glade TreeStore C++

I have read some manual of Glade and I create a GUI in which there is a TreeView which i want to populate by code. The glade file is:

<?xml version="1.0" encoding="UTF-8"?>
<interface>
  <!-- interface-requires gtk+ 3.0 -->
  <!-- interface-naming-policy toplevel-contextual -->
  <object class="GtkWindow" id="tree_window">
    <property name="can_focus">False</property>
    <property name="border_width">3</property>
    <property name="title" translatable="yes">Tree Viewer</property>
    <property name="default_width">400</property>
    <property name="default_height">600</property>
    <signal name="destroy" handler="gtk_main_quit" swapped="no"/>
    <child>
      <object class="GtkVBox" id="vbox1">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <child>
          <object class="GtkTreeView" id="treeview1">
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <child>
              <object class="GtkTreeViewColumn" id="aColumn">
                <property name="title" translatable="yes">A</property>
              </object>
            </child>
            <child>
              <object class="GtkTreeViewColumn" id="bColumn">
                <property name="title" translatable="yes">B</property>
              </object>
            </child>
          </object>
          <packing>
            <property name="expand">True</property>
            <property name="fill">True</property>
            <property name="position">0</property>
          </packing>
        </child>
      </object>
    </child>
  </object>
</interface>

So the idea is populate the "treeview1" with a GtkTreeStore that I define in the code below:

#include <gtk/gtk.h>
enum{
A_COL=0,
B_COL
};
GtkTreeModel * fill_gtk_tree_store_from_xml_file()
{
GtkTreeStore * t_model;
t_model=gtk_tree_store_new(2,G_TYPE_UINT,G_TYPE_UINT);
GtkTreeIter toplevel,childlevel;
gtk_tree_store_append(t_model,&toplevel,NULL);
gtk_tree_store_append(t_model,&toplevel,NULL);
gtk_tree_store_append(t_model,&toplevel,NULL);
gtk_tree_store_set(t_model,&toplevel,A_COL,(guint)12,B_COL,(guint)14,-1);
gtk_tree_store_append(t_model, &childlevel, &toplevel);
gtk_tree_store_set(t_model,&childlevel,0,(guint)20,
                1,(guint)22,-1);
    gtk_tree_store_append(t_model, &childlevel, &toplevel);
    return GTK_TREE_MODEL (t_model);
}

#include <gtk/gtk.h>
#include <stdlib.h>

int launchGUI(GtkBuilder *builder,GError *error=NULL)
{
    GtkWidget *ventanaPrincipal;

    if( ! gtk_builder_add_from_file( builder,"treeStore.glade", &error ) )
    {
        g_warning( "%s", error->message );
        g_free( error );
        return( 1 );
    }
    ventanaPrincipal = GTK_WIDGET(gtk_builder_get_object(builder, "tree_window"));
    GtkTreeModel *model;
    GtkWidget *view;
    model=fill_gtk_tree_store_from_xml_file();
    view=GTK_WIDGET(gtk_builder_get_object(builder, "treeview1"));
    gtk_tree_view_set_model (GTK_TREE_VIEW (view), model);
    gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(view)),
        GTK_SELECTION_NONE);
    gtk_signal_connect(GTK_OBJECT(ventanaPrincipal), "destroy",
        G_CALLBACK(gtk_main_quit), NULL);
    gtk_widget_show_all(ventanaPrincipal);
    gtk_main();
    return 0;
}

int main(int argc,char **argv)
{
GtkBuilder *gtkBuilder;
GError     *error = NULL;
gtk_init(&argc, &argv);
gtkBuilder= gtk_builder_new();
launchGUI(gtkBuilder,error);
return EXIT_SUCCESS;
}

I have tried different approaches, using enum, not using enum... The empty rows appear empty (OK), but the rows that should not be empty also appear empty. When I run the code this happens: image

I don't know what I'm doing wrong, Can anyone help me?

Upvotes: 3

Views: 1688

Answers (1)

user1146332
user1146332

Reputation: 2770

Your code has many construction sides. I will work down a list of those issues that attracted my particular attention.

Don't call it c++ if you stick with gtk+ and use plain c instead

You tagged your question with c++. However you don't use gtkmm but rather gtk+. Therefore you shouldn't intersperse c++ features that are not compatible with standard c.

Related to your code you shouldn't specify default function arguments. That feature is not part of the c programming language and will confuse fellow programmers who work on your code.

Declare variables where you need them and keep your function prototypes clean

Don't unnecessarily pass variables to functions that actually belongs only to the logical scope of the function itself.

For example the function

int launchGUI(GtkBuilder *builder,GError *error=NULL)

uses builder and error only locally so you shouldn't implement them as function arguments.

Furthermore you rarely need the GtkBuilder instance anywhere outside the function that initialize your user interface. So don't mess up functions with unnecessary definitions of local variables.

Check the reference manual not only for function descriptions but also for a conceptual understanding of library features

Don't apply g_free on a GError resource. Structures like GError aren't necessarily flat. Instead use a valid function. With respect to GError you should use g_error_free.

Study the conceptual overview of the GtkTreeModel widget and how to populate it. If you don't do this or study a similar description i see hard times will come upon you.

Don't use deprecated features

Check the code for deprecated features and replace them with the counterparts of the new version of the library.

For example don't use GTK_OBJECT in programs that depends on gtk+-3.0 (I conclude that from your ui definitions file). You can almost always replace gtk_object_ with g_object_ in your code.

Think about what should be defined in the ui definitions file and what should stay in the sources

GtkTreeView is one of the most complex widgets in gtk+ at least in my opinion. It is not enough to set the model of the widgets and create some columns.

At this point it is essential to pack the columns with cell renderers and link colums from your data store/model to specific properties of the particular renderers. Only this way content of the data store will be displayed directly or indirectly on the screen.

That being said you should consider what part of the tree view should be instantiated by methods of GtkBuilder and what should be defined in the code. With respect to your code you have to either get both columns or respectively get the treeview with gtk_builder_get_object or you implement the whole tree view in glade.

To show you a minimal working example of what i guess you want to achieve i decided to delete the columns in glade and just get the instantiated treeview widget in the code. Of course this example is not necessary the last word on the subject. However it displays the tree view with the content of the store on the screen.

I appended a screenshot of the working program and the code.


enter image description here

modfied source code:

#include <gtk/gtk.h>
#include <stdlib.h>

enum
{
    A_COL = 0,
    B_COL,
    COL_NUMBER
};

gchar *title[] = { "Column A", "Column B" };

void
fill_gtk_tree_store (GtkTreeView * view)
{
    GtkTreeStore *model;
    GtkTreeIter toplevel, childlevel;
    GtkTreeViewColumn *column;
    GtkTreeSelection *selection;
    GtkCellRenderer *renderer;
    guint i;

    model = gtk_tree_store_new (COL_NUMBER, G_TYPE_UINT, G_TYPE_UINT);

    gtk_tree_store_append (model, &toplevel, NULL);
    gtk_tree_store_append (model, &toplevel, NULL);
    gtk_tree_store_append (model, &toplevel, NULL);
    gtk_tree_store_set (model, &toplevel, A_COL, 12, B_COL, 14, -1);
    gtk_tree_store_append (model, &childlevel, &toplevel);
    gtk_tree_store_set (model, &childlevel, A_COL, 20, B_COL, 22, -1);
    gtk_tree_store_append (model, &childlevel, &toplevel);

    gtk_tree_view_set_model (view, GTK_TREE_MODEL (model));

    selection = gtk_tree_view_get_selection(view);

    gtk_tree_selection_set_mode (selection, GTK_SELECTION_NONE);

    for (i = 0; i < COL_NUMBER; i++) {

        renderer = gtk_cell_renderer_text_new ();

        column =
            gtk_tree_view_column_new_with_attributes (title[i], renderer,
                                                      "text", i, NULL);

        gtk_tree_view_append_column (view, column);

    }
}

void
launchGUI ()
{
    GtkWidget *ventanaPrincipal;
    GtkBuilder *builder;
    GError *error = NULL;
    GtkTreeView *view;

    builder = gtk_builder_new ();
    gtk_builder_add_from_file (builder, "treeStoreMod.glade", &error);

    if (error != NULL) {
        g_warning ("%s", error->message);
        g_error_free (error);
        exit(1);
    }

    ventanaPrincipal =
        GTK_WIDGET (gtk_builder_get_object (builder, "tree_window"));

    view = GTK_TREE_VIEW (gtk_builder_get_object (builder, "treeview1"));

    g_object_unref(builder);

    fill_gtk_tree_store (view);

    g_signal_connect (G_OBJECT (ventanaPrincipal),
                      "destroy", G_CALLBACK (gtk_main_quit), NULL);

    gtk_widget_show_all (ventanaPrincipal);

    gtk_main ();
}

int
main (int argc, char **argv)
{
    gtk_init (&argc, &argv);
    launchGUI ();
    return 0;
}

modified ui definitions file treeStoreMod.glade:

<?xml version="1.0" encoding="UTF-8"?>
<interface>
  <!-- interface-requires gtk+ 3.0 -->
  <object class="GtkWindow" id="tree_window">
    <property name="can_focus">False</property>
    <property name="border_width">3</property>
    <property name="title" translatable="yes">Tree Viewer</property>
    <property name="default_width">400</property>
    <property name="default_height">600</property>
    <signal name="destroy" handler="gtk_main_quit" swapped="no"/>
    <child>
      <object class="GtkVBox" id="vbox1">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <child>
          <object class="GtkTreeView" id="treeview1">
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <child internal-child="selection">
              <object class="GtkTreeSelection" id="treeview-selection1"/>
            </child>
          </object>
          <packing>
            <property name="expand">True</property>
            <property name="fill">True</property>
            <property name="position">0</property>
          </packing>
        </child>
      </object>
    </child>
  </object>
</interface>

Upvotes: 1

Related Questions