1
votes

I'm new at GUI development and I've been working on a project with gtk+ 3 for some days, but I'm stuck at this point.

My app contains two treeviews, the data in the rows is obtained from an sql query, by right clicking on a row a popup-menu appears, giving the option to set the data as "known", updating the database table.

The previous data now should belong in the other treeview, and so it does when the app is restarted, but I'm looking to do it in real time.

Is it possible to update/refresh the data in a treeview?

The model is obtained with the function:

static GtkTreeStore* create_and_fill(char* known)
{
  GtkTreeStore* store;
  GtkTreeIter iter;
  GtkWidget* tree;
  store = gtk_tree_store_new(2,G_TYPE_STRING,G_TYPE_STRING);

  char source_mac[50] = {0};
  char source_ip[50] = {0};
  int num_fields;

  char query[300] = {0};
  sprintf(query, "select mac,ip from hosts where known=%s", known);
  if(mysql_query(conn, query))
  {
    fprintf(stderr,"%s\n", mysql_error(conn));
  }
  res = mysql_store_result(conn);
  num_fields = mysql_num_fields(res);

  while((row = mysql_fetch_row(res)))
  {
    sprintf(source_mac,"%s", row[0]);
    sprintf(source_ip,"%s", row[1]);
    gtk_tree_store_append(store, &iter, NULL);
    gtk_tree_store_set(store, &iter, MAC_ADDRESS, source_mac, IP_ADDRESS, source_ip,-1);
  }
  gtk_tree_store_append(store, &iter, NULL);
  mysql_free_result(res);
  return store;
}
3
Please show us your current effort on that topic. What did you try so far. Which model is used to store the data.Gerhardh

3 Answers

0
votes

I never used gtk_tree_store, but only gtk_list_store. Nevertheless the logic should be applicable for gtk_tree_store as well.

Depending on the result of a new SQL-query some entries might be changed, added or deleted.

There are basically 2 ways to update your view.

If lines might be added and removed in your table, the easiest way might be to clean up your whole tree and populate it again.

GtkTreeIter       iter;
gboolean          iter_valid;

iter_valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter);
while (iter_valid)
{
  // Maybe additional cleanup of related data
  // gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, .... -1);
  iter_valid = gtk_tree_store_remove(store, &iter);
}
// Maybe update filtering and sorting afterwards
gtk_tree_model_filter_refilter(store_filtered);

// Populate again with result of SQL query.

If you can be sure that only the content changes, then you could just change it in the storage:

GtkTreeIter       iter;
gboolean          iter_valid;

iter_valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter);
while (iter_valid)
{
  gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, < add fields here >, -1);

  bool           update = FALSE;
  // Check if this entry needs to be updated
  // .... => set update = TRUE;

  if (update)
    gtk_tree_store_set(store, &iter, < field names and values here... > -1);

  iter_valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter);
}
// Optionally update filtering and sorting...
0
votes

I simply ended up doing an ugly patch. I created a function that removes the treeviews, rebuilds the stores and packs them again.

static void refresh()
{
gtk_container_remove(GTK_CONTAINER(box), tree_1);
gtk_container_remove(GTK_CONTAINER(box), tree_2);

tree_1 = create_view(create_and_fill("true")); // Rebuild the stores and views
tree_2 = create_view(create_and_fill("false"));

gtk_box_pack_start(GTK_BOX(box),tree_1,FALSE,FALSE,0);
gtk_box_pack_start(GTK_BOX(box),tree_2,FALSE,FALSE,0);

gtk_box_reorder_child(GTK_BOX(box), tree_1, x); // X being the relative position of your treeview
gtk_box_reorder_child(GTK_BOX(box), tree_2, x);
gtk_widget_show_all(box);
}
0
votes

I just wrote some code for a peer-to-peer bulletin board that can either populate a new tree or append new rows to a tree that's already populated. It uses a recursive function to get the existing iterators in the tree. An array in which to capture the iterators is passed by reference to this function. The iterator at index 0 is null, and a top-level post has 0 as its "inReplyTo" field.

Here I'm only showing the relevant code for brevity. Notice that the first call to updateTree populates the bare tree with the rows in $data, then the second call appends the rows in $more.

<?php

  $model = new GtkTreeStore(GObject::TYPE_STRING, GObject::TYPE_LONG);
  $tree  = new GtkTreeView($model);
  $renderer1 = new GtkCellRendererText();
  $column1 = new GtkTreeViewColumn('Title', $renderer1, 'text', 0);
  $renderer2 = new GtkCellRendererText();
  $column2 = new GtkTreeViewColumn('ID', $renderer2, 'text', 1);
  $tree->append_column($column1);
  $tree->append_column($column2);

  function getTreeIterators($model, &$iters, $iter = null)
  {
    if ($iter === null) {
      $iter = $model->get_iter_first();
    }
    while ($iter !== null) {
      $cols       = $model->get($iter, 1);
      $id         = $cols[0];
      $iters[$id] = $iter;
      if ($model->iter_has_child($iter)) {
        $child = $model->iter_children($iter);
        getTreeIterators($model, $iters, $child);
      }
      $iter = $model->iter_next($iter);
    }
  } // getTreeIterators

  function updateTree($treeView, $data)
  {
    $model    = $treeView->get_model();
    $iters    = array();
    $iters[0] = null;
    getTreeIterators($model, $iters);
    foreach($data as $item) {
      $iters[$item->id] = $model->append($iters[$item->inReplyTo], array($item->title, $item->id));
    }
    $tree->expand_all();
  } // updateTree

  $data = array(
            (object) array('id' => 1, 'inReplyTo' => 0, 'title' => 'First post'),
            (object) array('id' => 2, 'inReplyTo' => 1, 'title' => 'Re: First post'),
            (object) array('id' => 3, 'inReplyTo' => 0, 'title' => 'Second post'),
            (object) array('id' => 4, 'inReplyTo' => 2, 'title' => 'Re: Re: First post'),
            (object) array('id' => 5, 'inReplyTo' => 3, 'title' => 'Re: Second post'),
            (object) array('id' => 6, 'inReplyTo' => 0, 'title' => 'Third post')
          );


   $more = array(
            (object) array('id' => 7, 'inReplyTo' => 0, 'title' => 'Fourth post'),
            (object) array('id' => 8, 'inReplyTo' => 1, 'title' => 'Re: That first post'),
            (object) array('id' => 9, 'inReplyTo' => 5, 'title' => 'Re: Re: Second post')
           );

  updateTree($tree, $data);
  updateTree($tree, $more);

?>