GTK+ Forums

Discussion forum for GTK+ and Programming. Ask questions, troubleshoot problems, view and post example code, or express your opinions.
It is currently Wed May 22, 2013 7:27 pm

All times are UTC




Post new topic Reply to topic  [ 8 posts ] 
Author Message
 Post subject: From GtkObject to GtkWidget
PostPosted: Fri Aug 05, 2011 8:16 am 
Offline
Familiar Face

Joined: Fri Jul 01, 2011 6:40 pm
Posts: 48
Location: Croatia
Hello,
In order to learning GtkTreeView I have few related questions.

1) When I delete row, or force rov with keyboard to go less than 1 or more then last row there is bell sound generated by system (I think). Is here a way to disable that sounds for my specific application.

2) Code for select next row:
Code:
G_MODULE_EXPORT void
selPlus_CB(GtkObject *object, gpointer user_data)
{
GtkTreePath *path = NULL;
GtkTreeViewColumn *col = NULL;

    gtk_tree_view_get_cursor(GTK_TREE_VIEW(treeview1), &path, &col);
if (path)
     {
     gint row = gtk_tree_path_get_indices(path)[0];
     if (row >= 0){
         row++;
         path = gtk_tree_path_new_from_indices (row, -1);
         gtk_tree_view_set_cursor(GTK_TREE_VIEW(treeview1), path, NULL, FALSE);
         }
     }
gtk_tree_path_free (path);
}


I have almost same code for select previous row in other function.
Now interesting me is somehow possible to know through GtkObject *object which button was pressed ("next" or "previous") to make my code more efficient and shorter if I connect those two buttons to same signal in glade?

3) I have such function for fill formatted data to column which I used im my treeview created by code and which works OK:
Code:
//--------------------------------------------------------------
void five_cell_data_function (GtkTreeViewColumn *col,
                              GtkCellRenderer   *renderer,
                              GtkTreeModel      *model,
                              GtkTreeIter       *iter,
                              gpointer           user_data)
{
gfloat value_in5;
gchar  buf[20];

gtk_tree_model_get(model, iter, C_FIVE, &value_in5, -1);
     g_snprintf(buf, sizeof(buf), "%.2f ", value_in5);
     g_object_set(renderer, "text", buf, NULL);
}

If is important renderer for this column in glade is called rendFifth.

Now I need help to connect same function to column created in glade.
I do not succeed with many attempts, so please help.


Top
 Profile  
 
 Post subject: Re: From GtkObject to GtkWidget
PostPosted: Sun Aug 07, 2011 10:15 am 
Offline
Never Seen the Sunlight

Joined: Mon Apr 28, 2008 5:52 am
Posts: 509
Location: UK
Hello,

The bell sound is probably part of a theme and would be part of a user setting.

Yes you could use GtkObject *object to detect which button has been clicked, but I do not think that would give you a more efficient or shorter signal handler. You would have to have a bit of code in your handler to first decide which button was pressed and then to do the action. My thought would be to used the gpointer user_data to pass how much to move the cursor, that way it can be made much more generic.

Code:
G_MODULE_EXPORT void
sel_Move_CB(GtkObject *object, gpointer user_data)
{
  GtkTreePath *path;
  GtkTreeViewColumn *col;

  gtk_tree_view_get_cursor(GTK_TREE_VIEW(treeview1), &path, &col);

  if (path) {
     gint row = gtk_tree_path_get_indices(path)[0];

     if (row >= 0) {
         GtkTreePath *new_path;

         row += GPOINTER_TO_INT(user_data);
         new_path = gtk_tree_path_new_from_indices (row, -1);
         gtk_tree_view_set_cursor(GTK_TREE_VIEW(treeview1), new_path, NULL, FALSE);
         gtk_tree_path_free(new_path);
    }
    gtk_tree_path_free (path);
  }
}


You will then connect to the handler manually and not using Glade auto-connect. You will need to obtain the pointer to the next and previous buttons.
Code:
  g_signal_connect(G_OBJECT(Button_next), "clicked", G_CALLBACK(sel_Move_CB), GINT_TO_POINTER(1));
  g_signal_connect(G_OBJECT(Button_prev), "clicked", G_CALLBACK(sel_Move_CB), GINT_TO_POINTER(-1));

  g_signal_connect(G_OBJECT(Button_next_10), "clicked", G_CALLBACK(sel_Move_CB), GINT_TO_POINTER(10));
  g_signal_connect(G_OBJECT(Button_back_10), "clicked", G_CALLBACK(sel_Move_CB), GINT_TO_POINTER(-10));


You will almost certainly want to add checks to bound the selection of the new row and maybe other things. But I hope that this would be of help to you, and make your code more generic.

As for your final question, I can not see a way of using the Glade auto connect feature for the cell renderer. This is probably because it is not a GTK+ signal, but a normal function which you set to be used by GtkTreeViewColumn using :-
Code:
void                gtk_tree_view_column_set_cell_data_func
                                                        (GtkTreeViewColumn *tree_column,
                                                         GtkCellRenderer *cell_renderer,
                                                         GtkTreeCellDataFunc func,
                                                         gpointer func_data,
                                                         GDestroyNotify destroy);


I hope this is of help to you. Also note I have not tried to compile any of this code, but do give it a try.

Errol

_________________
E.


Top
 Profile  
 
 Post subject: Re: From GtkObject to GtkWidget
PostPosted: Wed Aug 10, 2011 1:48 pm 
Offline
Familiar Face

Joined: Fri Jul 01, 2011 6:40 pm
Posts: 48
Location: Croatia
Hello errol,
I solved those issues a bit different but successfully. Also find a way to invoke sort column by code.
This code will be useful for someone who search for basic treeview example. You can scroll them with keys and mouse but without scrolled window.
Bell issue was fixed with manually control of navigating.
Btw, is it possible to have separate theme on application base?

Code:
/*  Compile with this linker options for builder to work:
   `pkg-config --cflags --libs gtk+-2.0 gmodule-2.0` -export-dynamic

    main.c
*/

#include <stdlib.h>
#include <string.h>
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>

GtkBuilder *builder;
GtkWidget *window;
GtkWidget *treeview1;
GtkLabel *label1, *label2, *label3;
GtkTreeViewColumn *col;
GtkCellRenderer *chkRend, *rendFifth;
GtkTreeModel *model;
GtkListStore *store;
GtkTreeSelection *treeselectmode;
GtkTreePath *path;
GtkTreeIter iter;

void ClearData();
void LoadData();
int getlastrow();
void DoEvents();
gboolean nTimeout (gpointer data);
gboolean time_handler(GtkWidget *widget);

int row_count;
short CtrlDown = 1, faststep = 2, idletimer;
short idle, idlesec = 3, playcycles = 5;

enum
{
  C_CHK = 0,
  C_ONE,
  C_TWO,
  C_THREE,
  C_FOUR,
  C_FIVE,
  C_SIX,
  C_SEVEN,
  NUM_COLS
};

G_MODULE_EXPORT
void on_gtk_main_quit (GtkObject *object, gpointer user_data)
{
    g_source_remove(idletimer);
    gtk_main_quit();
}

int scroll(char direction, gshort step)
{
  GtkTreePath *path = NULL;

     gtk_tree_view_get_cursor(GTK_TREE_VIEW(treeview1), &path, &col);
  if (path){
      gint row = gtk_tree_path_get_indices(path)[0];
      if ((row >= 0) && (direction == '1')){
       if (row <= row_count - step)
               row += step;
               else
               row = row_count;
           }
           else{
       if (row >= step)
               row -= step;
               else
               row = 0;
           }

       path = gtk_tree_path_new_from_string(g_strdup_printf("%d", row));
       gtk_tree_view_set_cursor(GTK_TREE_VIEW(treeview1), path, NULL, FALSE);
      }
      else{
        gtk_widget_grab_focus(treeview1);
        g_print("Set focus to treeview\n");
      }
  gtk_tree_path_free (path);
  return (1);
}

G_MODULE_EXPORT void
btnPlay_CB(GtkObject *object, gpointer user_data)
{
int lo, op;
  for (lo = 0; lo < playcycles; lo++){
       for (op = 0; op < row_count; op++){
             scroll('1', 1);
             DoEvents();
             g_usleep(20000);
             }
       for (op = row_count; op >=0; op--){
             scroll('0', 1);
             DoEvents();
             g_usleep(20000);
            }}
}

//--------------------------------------------------------------
G_MODULE_EXPORT void
view_selected_foreach_func(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer userdata)
{
    int first;
    char *third;

    gtk_tree_model_get(model, iter, C_THREE, &third, -1);
    gtk_tree_model_get(model, iter, C_ONE, &first, -1);

    g_print("\n%6d %s is entered\n", first, third);
    g_free(third);
}

G_MODULE_EXPORT void
on_dblclick(GtkObject *object, gpointer user_data)
{
    GtkTreeSelection *treeselectmode;
    treeselectmode = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview1));
    gtk_tree_selection_selected_foreach(treeselectmode, view_selected_foreach_func, NULL);

g_print("Row activated\n");
}

//--------------------------------------------------------------
gint
get_col_number_from_tree_view_column (GtkTreeViewColumn *col)
{
    GList *cols;
    gint num;
    g_return_val_if_fail(col != NULL, -1);
    g_return_val_if_fail(col->tree_view != NULL, -1);
    cols = gtk_tree_view_get_columns(GTK_TREE_VIEW(col->tree_view));
    num = g_list_index(cols, (gpointer) col);
    g_list_free(cols);
return num;
}

//--------------------------------------------------------------
G_MODULE_EXPORT gint
motion_notify_event (GtkWidget *widget, GdkEventMotion *event, gpointer user_data)
{
if (!gtk_tree_model_get_iter_first(model, &iter) == FALSE)
   {
   int x, y;
   GdkModifierType state;

   if (event->is_hint)
       gdk_window_get_pointer(event->window, &x, &y, &state);
   else
      {
       x = event->x;
       y = event->y;
       state = event->state;
      }

   GtkTreePath* path;
   GtkTreeViewColumn* col;
   gtk_tree_view_get_path_at_pos((GtkTreeView*)widget, x, y, &path, &col, &x, &y);

if (path)
    gtk_window_set_title(GTK_WINDOW(window),
               g_strdup_printf("Mouse over row %s column %d",
                                gtk_tree_path_to_string(path),
                                get_col_number_from_tree_view_column(col)));

    gtk_tree_path_free (path);
   return 1;
   }
return 0;
}

//--------------------------------------------------------------
void on_changed(GtkWidget *widget, gpointer data)
{
  GtkTreeIter iter;
  GtkTreeModel *model;
  GtkTreePath *path;
  int first;
  char *third;

  gtk_tree_view_get_cursor(GTK_TREE_VIEW(treeview1), &path, &col);
  if (path){
      gint selrow = gtk_tree_path_get_indices(path)[0];
  if (gtk_tree_selection_get_selected(GTK_TREE_SELECTION(widget), &model, &iter))
      {
       gtk_tree_model_get(model, &iter, C_THREE, &third, -1);
       gtk_tree_model_get(model, &iter, C_ONE, &first, -1);
       g_print ("selection changed to %6d %6d %s\n", selrow, first, third);
      }}
  gtk_tree_path_free(path);
}

//--------------------------------------------------------------
G_MODULE_EXPORT gboolean
on_view_scroll_event (GtkWidget *widget, GdkEvent *event, gpointer user_data)
{
    switch(((GdkEventScroll*)event)->direction)
    {
   case GDK_SCROLL_UP:
        scroll('0', CtrlDown);
        break;

   case GDK_SCROLL_DOWN:
         scroll('1', CtrlDown);
        break;

   default:
        break;
    }
    return FALSE;
}

//--------------------------------------------------------------
G_MODULE_EXPORT gboolean
tree_button_press (GtkWidget *widget, GdkEventButton *event, GdkWindowEdge edge, gpointer user_data)
{
  if (event->type == GDK_BUTTON_PRESS){
      switch(event->button)
      {
     case 1:
       g_print ("LEFT mouse button pressed\n");
       break;

     case 3:
        g_print ("RIGHT mouse button pressed\n");
        break;

     case 2:
        g_print ("MIDDLE mouse button pressed\n");
        break;

      default:
        break;
      }
    }
  return FALSE;
}

//--------------------------------------------------------------
G_MODULE_EXPORT gboolean
tree_key_press(GtkObject *object, GdkEventKey* pKey, gpointer user_data)
{
    if (pKey->type == GDK_KEY_PRESS){
       switch(pKey->keyval)
       {
        case GDK_Delete:
        gtk_tree_view_get_cursor(GTK_TREE_VIEW(treeview1), &path, NULL);
     if (path)
        {
         gint row = gtk_tree_path_get_indices(path)[0];
         if (gtk_tree_model_get_iter(model, &iter, path))
            {
             gtk_list_store_remove(store, &iter);
             gtk_tree_path_free(path);

             if (row) row--;
                 row_count--;
                 path = gtk_tree_path_new_from_indices(row, -1);
                 gtk_tree_view_set_cursor(GTK_TREE_VIEW(treeview1), path, NULL, FALSE);
                 gtk_tree_path_free(path);
            }
        }
        return TRUE;
        break;

        case GDK_Down:
            scroll('1', CtrlDown);
        return TRUE;
        break;

        case GDK_Up:
            scroll('0', CtrlDown);
        return TRUE;
        break;

        case GDK_End:
        case GDK_Home:
        if ((pKey->state) & GDK_CONTROL_MASK)
            {
             int setlist = 0;
         if (pKey->keyval == GDK_End) setlist = row_count;
             GtkTreePath *path = NULL;
             gtk_tree_view_get_cursor(GTK_TREE_VIEW(treeview1), &path, &col);
             if (path){
                 path = gtk_tree_path_new_from_string(g_strdup_printf("%d", setlist));
                 gtk_tree_view_set_cursor(GTK_TREE_VIEW(treeview1), path, NULL, FALSE);
            }}
        return TRUE;
        break;

        default:
        break;
       }
    }
return FALSE;
}

//--------------------------------------------------------------
void five_cell_data_function (GtkTreeViewColumn *col,
                              GtkCellRenderer   *rendFive,
                              GtkTreeModel      *model,
                              GtkTreeIter       *iter,
                              gpointer           user_data)
{
gfloat value_in5;
gtk_tree_model_get(model, iter, C_FIVE, &value_in5, -1);
g_object_set(rendFive, "text", g_strdup_printf( "%.2f", value_in5), NULL);
}

//--------------------------------------------------------------
G_MODULE_EXPORT void
FOUR_editing_started_cb(GtkCellRenderer *cell,
                        GtkCellEditable *editable,
                        gchar *pathtext, gpointer user_data)
{
    if(GTK_IS_ENTRY(editable))
    {
        gtk_entry_set_max_length(GTK_ENTRY(editable), 3);
     // To control edit...
     // g_signal_connect(editable, "changed", G_CALLBACK(editable_changed_cb), NULL);
    }
  g_print("PRESS ENTER TO ACCEPT EDITED VALUE, ESC TO CANCEL\n");
  g_print("Started editing %s\n", pathtext);
}

//--------------------------------------------------------------
G_MODULE_EXPORT
void FOUR_edited_callback (GtkCellRendererText *cell,
                           gchar               *path_string,
                           gchar               *new_text,
                           gpointer             user_data)
{
  path = gtk_tree_path_new_from_string(path_string);

  gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, path);
  gtk_list_store_set(GTK_LIST_STORE(model), &iter, C_FOUR, new_text, -1);
  g_print("edited %s in row %s\n", new_text, path_string);
  gtk_tree_path_free (path);
}

//--------------------------------------------------------------
G_MODULE_EXPORT void
chktoggled_CB (GtkCellRendererToggle *chkRend,
               gchar                 *path_str,
               gpointer               user_data)
{
  GtkTreeIter  iter;
  GtkTreePath *path = gtk_tree_path_new_from_string(path_str);
  gboolean fixed;

  gtk_tree_model_get_iter(model, &iter, path);
  gtk_tree_model_get(model, &iter, C_CHK, &fixed, -1);

  fixed ^= 1;
  gtk_list_store_set(GTK_LIST_STORE(model), &iter, C_CHK, fixed, -1);
  gtk_tree_path_free(path);
}

//--------------------------------------------------------------
G_MODULE_EXPORT void
win_keypress_CB(GtkObject *object, GdkEventKey* pKey, gpointer user_data)
{
// I can't check control key with pKey->state & GDK_CONTROL_MASK, why?
// This is some workaround, slower and not tested well
idle = 0;
    if(strstr(gdk_keyval_name(pKey->keyval), "Control")){
        CtrlDown = faststep;
       }
}

//--------------------------------------------------------------
G_MODULE_EXPORT void
win_keyrelease_CB(GtkObject *object, GdkEventKey* pKey, gpointer user_data)
{
idle = 0;
    if(strstr(gdk_keyval_name(pKey->keyval), "Control")){
        CtrlDown = 1;
       }
}

//--------------------------------------------------------------
G_MODULE_EXPORT void
kill_idle_CB (GtkObject *object, GdkEventMotion *event, gpointer user_data)
{
idle = 0;
   int x, y;
   GdkModifierType state;

   if (event->is_hint)
       gdk_window_get_pointer(event->window, &x, &y, &state);
   else
      {
       x = event->x;
       y = event->y;
       state = event->state;
      }

    gtk_label_set_text(label1, g_strdup_printf("%d", x));
    gtk_label_set_text(label2, g_strdup_printf("%d", y));
}

//--------------------------------------------------------------
gboolean time_handler(GtkWidget *widget)
{
    time_t rawtime;
    struct tm * timeinfo;
    char *buffer;

if ((idle/10) >= idlesec)
    {
    time (&rawtime);
    timeinfo = localtime(&rawtime);

if((buffer = malloc(16)) != NULL)
     strftime(buffer, 16, "IDLE %H:%M:%S\n", timeinfo);
     gtk_label_set_text(label3, buffer);
    }
     else
    {
     gtk_label_set_text(label3, "");
    }

    idle ++;
    return TRUE;
}

//--------------------------------------------------------------
int main (int argc, char *argv[])
{
    gtk_init (&argc, &argv);
    builder = gtk_builder_new ();
    gtk_builder_add_from_file(builder, "minGladeTW.glade", NULL);
    window = GTK_WIDGET(gtk_builder_get_object(builder, "window1"));
    idletimer = g_timeout_add(100, (GSourceFunc) time_handler, (gpointer) window);

    treeview1 = GTK_WIDGET(gtk_builder_get_object(builder, "treeview1"));

    rendFifth = GTK_CELL_RENDERER(gtk_builder_get_object(builder, "rendFifth"));
    chkRend = GTK_CELL_RENDERER(gtk_builder_get_object(builder, "chkRend"));
    label1 = GTK_LABEL(gtk_builder_get_object(builder, "label1"));
    label2 = GTK_LABEL(gtk_builder_get_object(builder, "label2"));
    label3 = GTK_LABEL(gtk_builder_get_object(builder, "label3"));

    treeselectmode = gtk_tree_view_get_selection (GTK_TREE_VIEW(treeview1));
    g_signal_connect(treeselectmode, "changed", G_CALLBACK(on_changed), NULL);

    gtk_tree_selection_set_mode(treeselectmode, GTK_SELECTION_SINGLE);
    store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(treeview1)));
    model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeview1));

    col = gtk_tree_view_get_column(GTK_TREE_VIEW (treeview1), C_FIVE);
    gtk_tree_view_column_set_cell_data_func(col, rendFifth, five_cell_data_function, NULL, NULL);

    gtk_builder_connect_signals(builder, NULL);
    g_object_unref(G_OBJECT(builder));

    LoadData();

    gtk_widget_show(window);
    gtk_main ();
    return (0);
}

void ClearData()
{
if (!gtk_tree_model_get_iter_first(model, &iter) == FALSE)
     gtk_list_store_clear(store);
row_count = 0;
}

void LoadData()
{
    model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeview1));
    g_object_ref(model);
    gtk_tree_view_set_model(GTK_TREE_VIEW(treeview1), NULL);

    gtk_list_store_append(store, &iter);
    gtk_list_store_set(store, &iter, C_CHK, TRUE,
                                     C_ONE, 1245,
                                     C_TWO, "SOME <b>NAME</b> LIKE NIME",
                                     C_THREE, "Some name like nime",
                                     C_FOUR, "KOM",
                                     C_FIVE, 1254.12568,
                                     C_SIX, 243.125689,
                                     C_SEVEN, "", -1);

    gtk_list_store_append(store, &iter);
    gtk_list_store_set(store, &iter, C_CHK, FALSE,
                                     C_ONE, 1,
                                     C_TWO, "NO <b>NAME</b>",
                                     C_THREE, "No name",
                                     C_FOUR, "NA",
                                     C_FIVE, 0.00,
                                     C_SIX, 0.00,
                                     C_SEVEN, "", -1);

    gtk_list_store_append(store, &iter);
    gtk_list_store_set(store, &iter, C_CHK, FALSE,
                                     C_ONE, 153,
                                     C_TWO, "INTERESTING <b>NAME</b>D ROW",
                                     C_THREE, "Interesting named row",
                                     C_FOUR, "ROW",
                                     C_FIVE, 22235.1101158,
                                     C_SIX, 1235.215,
                                     C_SEVEN, "", -1);

    gtk_list_store_append(store, &iter);
    gtk_list_store_set(store, &iter, C_CHK, FALSE,
                                     C_ONE, 84,
                                     C_TWO, "<b>NAME</b> OF THE GAME",
                                     C_THREE, "Name of the game",
                                     C_FOUR, "NAM",
                                     C_FIVE, 169.74521,
                                     C_SIX, 1.585236,
                                     C_SEVEN, "", -1);

    gtk_tree_view_set_model(GTK_TREE_VIEW(treeview1), model);
    g_object_unref(model);

    row_count = getlastrow();
//--------------------
    if (row_count)
        {
            path = gtk_tree_path_new_from_string("0");
            gtk_tree_selection_select_path(treeselectmode, path);
            gtk_tree_path_free(path);
        }
    gtk_widget_grab_focus(treeview1);
}

int getlastrow()
{
    GtkTreeIter iter1, swap;
    row_count = 0;

    gtk_tree_model_get_iter_first(model, &iter1);
    swap = iter1;
    while(gtk_tree_model_iter_next(model, &iter1)){
          swap = iter1;
          row_count++;
          }
    return row_count;
}

void DoEvents()
{
     while (gtk_events_pending ())
            gtk_main_iteration ();
}



And Glade3 file "minGladeTW.glade":
Code:
<?xml version="1.0" encoding="UTF-8"?>
<interface>
  <requires lib="gtk+" version="2.24"/>
  <!-- interface-naming-policy project-wide -->
  <object class="GtkListStore" id="liststore1">
    <columns>
      <!-- column-name colChk -->
      <column type="gboolean"/>
      <!-- column-name colOne -->
      <column type="gint"/>
      <!-- column-name colTwo -->
      <column type="gchararray"/>
      <!-- column-name colThree -->
      <column type="gchararray"/>
      <!-- column-name colFour -->
      <column type="gchararray"/>
      <!-- column-name colFive -->
      <column type="gfloat"/>
      <!-- column-name colSix -->
      <column type="gfloat"/>
      <!-- column-name colLast -->
      <column type="gchararray"/>
    </columns>
    <data>
      <row>
        <col id="0">False</col>
        <col id="1">28</col>
        <col id="2" translatable="yes">MY &lt;b&gt;NAME&lt;/b&gt; IS GLADE</col>
        <col id="3" translatable="yes">My name is Glade</col>
        <col id="4" translatable="yes">LIT</col>
        <col id="5">1244.056884765625</col>
        <col id="6">24.125690460205078</col>
        <col id="7" translatable="yes"> </col>
      </row>
      <row>
        <col id="0">False</col>
        <col id="1">1256</col>
        <col id="2" translatable="yes">SECOND ROW FROM GLADE</col>
        <col id="3" translatable="yes">Second row from glade</col>
        <col id="4" translatable="yes">ROW</col>
        <col id="5">1458.326904296875</col>
        <col id="6">0</col>
        <col id="7" translatable="yes"> </col>
      </row>
    </data>
  </object>
  <object class="GtkWindow" id="window1">
    <property name="height_request">400</property>
    <property name="can_focus">False</property>
    <property name="events">GDK_POINTER_MOTION_MASK | GDK_STRUCTURE_MASK</property>
    <signal name="key-press-event" handler="win_keypress_CB" swapped="no"/>
    <signal name="scroll-event" handler="kill_idle_CB" swapped="no"/>
    <signal name="key-release-event" handler="win_keyrelease_CB" swapped="no"/>
    <signal name="destroy" handler="on_gtk_main_quit" swapped="no"/>
    <signal name="button-press-event" handler="kill_idle_CB" swapped="no"/>
    <signal name="motion-notify-event" handler="kill_idle_CB" swapped="no"/>
    <signal name="button-release-event" handler="kill_idle_CB" swapped="no"/>
    <signal name="delete-event" handler="on_gtk_main_quit" swapped="no"/>
    <child>
      <object class="GtkHBox" id="hbox1">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <child>
          <object class="GtkVBox" id="vbox1">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="border_width">5</property>
            <child>
              <placeholder/>
            </child>
            <child>
              <placeholder/>
            </child>
            <child>
              <placeholder/>
            </child>
            <child>
              <object class="GtkHBox" id="hbox5">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="homogeneous">True</property>
                <child>
                  <object class="GtkButton" id="button1">
                    <property name="label" translatable="yes">Exit</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_gtk_main_quit" swapped="no"/>
                  </object>
                  <packing>
                    <property name="expand">True</property>
                    <property name="fill">True</property>
                    <property name="position">0</property>
                  </packing>
                </child>
                <child>
                  <placeholder/>
                </child>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">False</property>
                <property name="position">3</property>
              </packing>
            </child>
            <child>
              <object class="GtkHBox" id="hbox4">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="homogeneous">True</property>
                <child>
                  <object class="GtkButton" id="button2">
                    <property name="label" translatable="yes">Play</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="btnPlay_CB" swapped="no"/>
                  </object>
                  <packing>
                    <property name="expand">True</property>
                    <property name="fill">True</property>
                    <property name="position">0</property>
                  </packing>
                </child>
                <child>
                  <placeholder/>
                </child>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">False</property>
                <property name="position">4</property>
              </packing>
            </child>
            <child>
              <object class="GtkHSeparator" id="hseparator1">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">True</property>
                <property name="padding">10</property>
                <property name="position">5</property>
              </packing>
            </child>
            <child>
              <object class="GtkHBox" id="hbox3">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="homogeneous">True</property>
                <child>
                  <object class="GtkLabel" id="label1">
                    <property name="visible">True</property>
                    <property name="can_focus">False</property>
                    <property name="xalign">0</property>
                    <property name="label" translatable="yes">move mouse</property>
                  </object>
                  <packing>
                    <property name="expand">True</property>
                    <property name="fill">True</property>
                    <property name="position">0</property>
                  </packing>
                </child>
                <child>
                  <placeholder/>
                </child>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">False</property>
                <property name="position">6</property>
              </packing>
            </child>
            <child>
              <object class="GtkHBox" id="hbox2">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="homogeneous">True</property>
                <child>
                  <object class="GtkLabel" id="label2">
                    <property name="visible">True</property>
                    <property name="can_focus">False</property>
                    <property name="xalign">0</property>
                    <property name="label" translatable="yes">here</property>
                  </object>
                  <packing>
                    <property name="expand">True</property>
                    <property name="fill">True</property>
                    <property name="position">0</property>
                  </packing>
                </child>
                <child>
                  <placeholder/>
                </child>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">False</property>
                <property name="position">7</property>
              </packing>
            </child>
            <child>
              <object class="GtkHSeparator" id="hseparator2">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">True</property>
                <property name="padding">10</property>
                <property name="position">8</property>
              </packing>
            </child>
            <child>
              <object class="GtkLabel" id="label3">
                <property name="width_request">99</property>
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="xalign">0</property>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">False</property>
                <property name="position">9</property>
              </packing>
            </child>
            <child>
              <placeholder/>
            </child>
          </object>
          <packing>
            <property name="expand">True</property>
            <property name="fill">True</property>
            <property name="position">0</property>
          </packing>
        </child>
        <child>
          <object class="GtkTreeView" id="treeview1">
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="events">GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_MOTION_MASK | GDK_BUTTON1_MOTION_MASK | GDK_BUTTON2_MOTION_MASK | GDK_BUTTON3_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_FOCUS_CHANGE_MASK | GDK_STRUCTURE_MASK | GDK_PROPERTY_CHANGE_MASK | GDK_VISIBILITY_NOTIFY_MASK | GDK_PROXIMITY_IN_MASK | GDK_PROXIMITY_OUT_MASK | GDK_SUBSTRUCTURE_MASK | GDK_SCROLL_MASK</property>
            <property name="model">liststore1</property>
            <property name="headers_clickable">False</property>
            <property name="search_column">4</property>
            <property name="rubber_banding">True</property>
            <signal name="button-press-event" handler="tree_button_press" swapped="no"/>
            <signal name="key-press-event" handler="tree_key_press" swapped="no"/>
            <signal name="row-activated" handler="on_dblclick" swapped="no"/>
            <signal name="motion-notify-event" handler="motion_notify_event" swapped="no"/>
            <signal name="scroll-event" handler="on_view_scroll_event" swapped="no"/>
            <child>
              <object class="GtkTreeViewColumn" id="colChk">
                <property name="alignment">0.5</property>
                <child>
                  <object class="GtkCellRendererToggle" id="chkRend">
                    <signal name="toggled" handler="chktoggled_CB" swapped="no"/>
                  </object>
                  <attributes>
                    <attribute name="active">0</attribute>
                  </attributes>
                </child>
              </object>
            </child>
            <child>
              <object class="GtkTreeViewColumn" id="col1">
                <property name="sizing">fixed</property>
                <property name="fixed_width">70</property>
                <property name="title">First </property>
                <property name="alignment">1</property>
                <child>
                  <object class="GtkCellRendererText" id="rendFirst">
                    <property name="xalign">1</property>
                    <property name="alignment">right</property>
                  </object>
                  <attributes>
                    <attribute name="text">1</attribute>
                  </attributes>
                </child>
              </object>
            </child>
            <child>
              <object class="GtkTreeViewColumn" id="col2">
                <property name="sizing">fixed</property>
                <property name="fixed_width">230</property>
                <property name="title">Second</property>
                <child>
                  <object class="GtkCellRendererText" id="rendSecond"/>
                  <attributes>
                    <attribute name="markup">2</attribute>
                  </attributes>
                </child>
              </object>
            </child>
            <child>
              <object class="GtkTreeViewColumn" id="col3">
                <property name="visible">False</property>
                <property name="min_width">0</property>
                <property name="max_width">0</property>
                <property name="title">Third</property>
                <child>
                  <object class="GtkCellRendererText" id="rendThird"/>
                  <attributes>
                    <attribute name="text">3</attribute>
                  </attributes>
                </child>
              </object>
            </child>
            <child>
              <object class="GtkTreeViewColumn" id="col4">
                <property name="sizing">fixed</property>
                <property name="fixed_width">60</property>
                <property name="title">Fourth</property>
                <property name="alignment">0.5</property>
                <child>
                  <object class="GtkCellRendererText" id="rendFourth">
                    <property name="alignment">center</property>
                    <property name="editable">True</property>
                    <signal name="editing-started" handler="FOUR_editing_started_cb" swapped="no"/>
                    <signal name="edited" handler="FOUR_edited_callback" swapped="no"/>
                  </object>
                  <attributes>
                    <attribute name="text">4</attribute>
                  </attributes>
                </child>
              </object>
            </child>
            <child>
              <object class="GtkTreeViewColumn" id="col5">
                <property name="sizing">fixed</property>
                <property name="fixed_width">90</property>
                <property name="title">Fifth </property>
                <property name="alignment">1</property>
                <child>
                  <object class="GtkCellRendererText" id="rendFifth">
                    <property name="xalign">1</property>
                    <property name="alignment">right</property>
                  </object>
                  <attributes>
                    <attribute name="text">5</attribute>
                  </attributes>
                </child>
              </object>
            </child>
            <child>
              <object class="GtkTreeViewColumn" id="col6">
                <property name="sizing">fixed</property>
                <property name="fixed_width">90</property>
                <property name="title">Sixth </property>
                <property name="alignment">1</property>
                <property name="sort_indicator">True</property>
                <child>
                  <object class="GtkCellRendererText" id="rendSixth">
                    <property name="xalign">1</property>
                    <property name="alignment">right</property>
                  </object>
                  <attributes>
                    <attribute name="text">6</attribute>
                  </attributes>
                </child>
              </object>
            </child>
            <child>
              <object class="GtkTreeViewColumn" id="col7">
                <property name="clickable">True</property>
                <child>
                  <object class="GtkCellRendererText" id="rendSeventh"/>
                  <attributes>
                    <attribute name="text">7</attribute>
                  </attributes>
                </child>
              </object>
            </child>
          </object>
          <packing>
            <property name="expand">True</property>
            <property name="fill">True</property>
            <property name="position">1</property>
          </packing>
        </child>
        <child>
          <placeholder/>
        </child>
      </object>
    </child>
  </object>
</interface>


So, only two questions remains here.
1) I cant get columns 1, 5 and 6 to be right aligned and column 4 to be centered. Why?
2) I assign signal to motion event of window to control my idle counter and this works when I move over buttons, labels and window but not when I am over treeview. I try to get this event on whole window by adding event box what was also not good. How is possible that window don't see motion event when I am over treeview?
Is here a way to get this?

On example above is visible what I am talking about.
Thanks for helping!
nime.



EDIT: Now I try this on windows and there i have error message
Quote:
...exe:5532): Gtk-CRITICAL **: gtk_label_set_text: assertion `GTK_IS_LABEL
//label)' failed


which running in console, from timer handler.
What can this mean?


Top
 Profile  
 
 Post subject: Re: From GtkObject to GtkWidget
PostPosted: Wed Aug 10, 2011 8:13 pm 
Offline
Never Seen the Sunlight

Joined: Mon Apr 28, 2008 5:52 am
Posts: 509
Location: UK
Hi,

I have only had a very quick look at your code. It compiles OK and runs without errors. But there are many places in your code where there are memory leaks, many of the call-backs have the incorrect function proto-type. There are probably other problems in the code.

I have been doing some research and you can turn off the bell and yes it is possible to have separate themes for an application. But it is better to leave the theme for the user to choose.

As for the alignment you will need to set the "alignment" property of GtkCellRendererText for the actual data. In your Glade file you have only aligned the headers.

Due to the incorrect use of the call-backs I will have to do some work on the code find find out what is happening with the motion event.

I do not use Windows, so can not reproduce the final error.

Errol.

_________________
E.


Top
 Profile  
 
 Post subject: Re: From GtkObject to GtkWidget
PostPosted: Wed Aug 10, 2011 9:23 pm 
Offline
Familiar Face

Joined: Fri Jul 01, 2011 6:40 pm
Posts: 48
Location: Croatia
Hello errol,
Thank you for remarks!

I can do fix function prototypes by using GTK manual, but can't memory leaks, coz I learns C in parallel with GTK, so please I would like to see this. Is here any simple tool for monitoring, catching memory leaks?

I agree with your opinion to global theme, but sometimes it could be good choice for use separate one.
How to do this?

I understand now regard alignment and I assure you that I set align to renderers properly by setting Alignment property to Right in "properties and attributes" and Horizontal alignment to 1,00 in "common properties and attributes"!
Maybe I missed something more or is something with my Glade??
Finally, in worst case I can do references to my columns and set "xalign" by hand but now I would better like to do all possible job with Glade.

I have to see yet what is in windows, most possible something incorrect with gtklabel's code.

And we do not discuss to end those situation how to find which is sender (caller) object from (GtkObject *object).

Cheers,
nime.


Top
 Profile  
 
 Post subject: Re: From GtkObject to GtkWidget
PostPosted: Fri Aug 19, 2011 11:29 am 
Offline
Never Seen the Sunlight

Joined: Mon Apr 28, 2008 5:52 am
Posts: 509
Location: UK
Hi,

Bit of a late reply, but hope this will help you. I have re-written your code a bit and adjusted the Glade file. This I hope gets closer to what you really want and corrects many other problems.

Code:
/*  Compile with this linker options for builder to work:
   `pkg-config --cflags --libs gtk+-2.0 gmodule-2.0` -export-dynamic

    main.c
*/

#include <stdlib.h>
#include <string.h>
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>

GtkBuilder *builder;
GtkWidget *window;
GtkWidget *treeview1;
GtkLabel *label1, *label2, *label3;
GtkTreeViewColumn *col;
GtkCellRenderer *chkRend, *rendFifth;
GtkTreeModel *model;
GtkListStore *store;
GtkTreeSelection *treeselectmode;
GtkTreePath *path;
GtkTreeIter iter;

void ClearData();
void LoadData();
int getlastrow();
void DoEvents();

int row_count;
short CtrlDown = 1, faststep = 2;
short idle, idlesec = 3, playcycles = 5;

enum {
    C_CHK = 0,
    C_ONE,
    C_TWO,
    C_THREE,
    C_FOUR,
    C_FIVE,
    C_SIX,
    C_SEVEN,
    NUM_COLS
};

enum {
    SCROLL_UP, SCROLL_DOWN
};

G_MODULE_EXPORT
void on_gtk_main_quit (GtkWidget *object, gpointer user_data)
{
    gtk_main_quit();
}

int scroll(int direction, int step)
{
    GtkTreePath *path;

    gtk_tree_view_get_cursor(GTK_TREE_VIEW(treeview1), &path, &col);
    if (path) {
        gchar s[20];
        gint row = gtk_tree_path_get_indices(path)[0];

        if ((row >= 0) && (direction == SCROLL_DOWN)) {
            if (row <= row_count - step)
                row += step;
            else
                row = row_count;
        } else {
            if (row >= step)
                row -= step;
            else
                row = 0;
        }
        g_snprintf(s, sizeof(s), "%d", row);
        path = gtk_tree_path_new_from_string(s);
        gtk_tree_view_set_cursor(GTK_TREE_VIEW(treeview1), path, NULL, FALSE);
    } else {
        gtk_widget_grab_focus(treeview1);
        g_print("Set focus to treeview\n");
    }
    gtk_tree_path_free (path);
    return (1);
}

G_MODULE_EXPORT void
btnPlay_CB(GtkWidget *widget, gpointer user_data)
{
    int lo, op;
    for (lo = 0; lo < playcycles; lo++) {
        for (op = 0; op < row_count; op++) {
            scroll(SCROLL_DOWN, 1);
            DoEvents();
            g_usleep(20000);
        }
        for (op = row_count; op >=0; op--) {
            scroll(SCROLL_UP, 1);
            DoEvents();
            g_usleep(20000);
        }
    }
}

//--------------------------------------------------------------
G_MODULE_EXPORT void
view_selected_foreach_func(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer userdata)
{
    int first;
    gchar *third;

    gtk_tree_model_get(model, iter, C_THREE, &third, -1);
    gtk_tree_model_get(model, iter, C_ONE, &first, -1);

    g_print("\n%6d %s is entered\n", first, third);
    g_free(third);
}

G_MODULE_EXPORT void
on_dblclick(GtkTreeView *tree_view, GtkTreePath *path, GtkTreeViewColumn *column, gpointer user_data)
{
    GtkTreeSelection *treeselectmode;
    treeselectmode = gtk_tree_view_get_selection(tree_view);
    gtk_tree_selection_selected_foreach(treeselectmode, view_selected_foreach_func, NULL);

    g_print("Row activated\n");
}

//--------------------------------------------------------------
gint
get_col_number_from_tree_view_column (GtkTreeViewColumn *col)
{
    GList *cols;
    gint num;

    g_return_val_if_fail(col != NULL, -1);
    g_return_val_if_fail(treeview1 != NULL, -1);

    cols = gtk_tree_view_get_columns(GTK_TREE_VIEW(treeview1));
    num = g_list_index(cols, (gpointer) col);
    g_list_free(cols);

    return num;
}

//--------------------------------------------------------------
G_MODULE_EXPORT gboolean
motion_notify_event (GtkWidget *widget, GdkEvent *event, gpointer user_data)
{
    int x, y;
    GdkModifierType state;
    gchar s[40];

    if (!gtk_tree_model_get_iter_first(model, &iter) == FALSE) {

        GtkTreePath *path;
        GtkTreeViewColumn *col;

        if (event->motion.is_hint)
            gdk_window_get_pointer(event->motion.window, &x, &y, &state);
        else {
            x = event->motion.x;
            y = event->motion.y;
            state = event->motion.state;
        }

        gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget), x, y, &path, &col, &x, &y);

        if (path) {
            gchar *p = gtk_tree_path_to_string(path);
            g_snprintf(s, sizeof(s), "Mouse over row %s column %d", p, get_col_number_from_tree_view_column(col));
            gtk_window_set_title(GTK_WINDOW(window), s);
            g_free(p);
        }
        gtk_tree_path_free (path);
    }

    idle = 0;
    gdk_window_get_pointer(gtk_widget_get_window(window), &x, &y, &state);
    g_snprintf(s, sizeof(s), "%d", x);
    gtk_label_set_text(label1, s);
    g_snprintf(s, sizeof(s), "%d", y);
    gtk_label_set_text(label2, s);

    gdk_event_request_motions (&event->motion);

    return FALSE;
}

//--------------------------------------------------------------
void on_changed(GtkWidget *widget, gpointer data)
{
    GtkTreeIter iter;
    GtkTreeModel *model;
    GtkTreePath *path;
    int first;
    gchar *third;

    gtk_tree_view_get_cursor(GTK_TREE_VIEW(treeview1), &path, &col);
    if (path) {
        gint selrow = gtk_tree_path_get_indices(path)[0];
        if (gtk_tree_selection_get_selected(GTK_TREE_SELECTION(widget), &model, &iter)) {
            gtk_tree_model_get(model, &iter, C_THREE, &third, -1);
            gtk_tree_model_get(model, &iter, C_ONE, &first, -1);
            g_print ("selection changed to %6d %6d %s\n", selrow, first, third);
            g_free(third);
        }
    }
    gtk_tree_path_free(path);
}

//--------------------------------------------------------------
G_MODULE_EXPORT gboolean
on_view_scroll_event (GtkWidget *widget, GdkEvent *event, gpointer user_data)
{
    switch(event->scroll.direction) {
    case GDK_SCROLL_UP:
        scroll(SCROLL_UP, CtrlDown);
        break;

    case GDK_SCROLL_DOWN:
        scroll(SCROLL_DOWN, CtrlDown);
        break;

    default:
        break;
    }
    return FALSE;
}

//--------------------------------------------------------------
G_MODULE_EXPORT gboolean
tree_button_press (GtkWidget *widget, GdkEvent *event, gpointer user_data)
{
    if (event->type == GDK_BUTTON_PRESS) {
        switch(event->button.button) {
        case 1:
            g_print ("LEFT mouse button pressed\n");
            break;

        case 3:
            g_print ("RIGHT mouse button pressed\n");
            break;

        case 2:
            g_print ("MIDDLE mouse button pressed\n");
            break;

        default:
            break;
        }
    }
    return FALSE;
}

//--------------------------------------------------------------
G_MODULE_EXPORT gboolean
tree_key_press(GtkWidget *widget, GdkEvent *ev, gpointer user_data)
{
    if (ev->type == GDK_KEY_PRESS) {
        switch(ev->key.keyval) {
        case GDK_KEY_Delete:
            gtk_tree_view_get_cursor(GTK_TREE_VIEW(treeview1), &path, NULL);
            if (path) {
                gint row = gtk_tree_path_get_indices(path)[0];
                if (gtk_tree_model_get_iter(model, &iter, path)) {
                    gtk_list_store_remove(store, &iter);
                    gtk_tree_path_free(path);

                    if (row) row--;
                    row_count--;
                    path = gtk_tree_path_new_from_indices(row, -1);
                    gtk_tree_view_set_cursor(GTK_TREE_VIEW(treeview1), path, NULL, FALSE);
                }
                gtk_tree_path_free(path);

            }
            return TRUE;

        case GDK_KEY_Down:
            scroll(SCROLL_DOWN, CtrlDown);
            return TRUE;

        case GDK_KEY_Up:
            scroll(SCROLL_UP, CtrlDown);
            return TRUE;

        case GDK_KEY_End:
        case GDK_KEY_Home:
            if ((ev->key.state) & GDK_CONTROL_MASK) {
                int setlist = 0;
                GtkTreePath *path;

                if (ev->key.keyval == GDK_KEY_End) setlist = row_count;

                gtk_tree_view_get_cursor(GTK_TREE_VIEW(treeview1), &path, &col);
                if (path) {
                    gchar s[20];
                    g_snprintf(s, 20, "%d", setlist);
                    path = gtk_tree_path_new_from_string(s);
                    gtk_tree_view_set_cursor(GTK_TREE_VIEW(treeview1), path, NULL, FALSE);
                    gtk_tree_path_free(path);
                }
            }
            return TRUE;

        default:
            break;
        }
    }
    return FALSE;
}

//--------------------------------------------------------------
void five_cell_data_function (GtkTreeViewColumn *col,
                              GtkCellRenderer   *rendFive,
                              GtkTreeModel      *model,
                              GtkTreeIter       *iter,
                              gpointer           user_data)
{
    gfloat value_in5;
    gchar s[20];

    gtk_tree_model_get(model, iter, C_FIVE, &value_in5, -1);
    g_snprintf(s, sizeof(s), "%.2f", value_in5);
    g_object_set(rendFive, "text", s, NULL);
}

//--------------------------------------------------------------
G_MODULE_EXPORT void
FOUR_editing_started_cb(GtkCellRenderer *cell,
                        GtkCellEditable *editable,
                        gchar *pathtext, gpointer user_data)
{
    if(GTK_IS_ENTRY(editable)) {
        gtk_entry_set_max_length(GTK_ENTRY(editable), 3);
        // To control edit...
        // g_signal_connect(editable, "changed", G_CALLBACK(editable_changed_cb), NULL);
    }
    g_print("PRESS ENTER TO ACCEPT EDITED VALUE, ESC TO CANCEL\n");
    g_print("Started editing %s\n", pathtext);
}

//--------------------------------------------------------------
G_MODULE_EXPORT
void FOUR_edited_callback (GtkCellRendererText *cell,
                           gchar               *path_string,
                           gchar               *new_text,
                           gpointer             user_data)
{
    path = gtk_tree_path_new_from_string(path_string);

    gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, path);
    gtk_list_store_set(GTK_LIST_STORE(model), &iter, C_FOUR, new_text, -1);
    g_print("edited %s in row %s\n", new_text, path_string);
    gtk_tree_path_free (path);
}

//--------------------------------------------------------------
G_MODULE_EXPORT void
chktoggled_CB (GtkCellRendererToggle *chkRend,
               gchar                 *path_str,
               gpointer               user_data)
{
    GtkTreeIter  iter;
    GtkTreePath *path = gtk_tree_path_new_from_string(path_str);
    gboolean fixed;

    gtk_tree_model_get_iter(model, &iter, path);
    gtk_tree_model_get(model, &iter, C_CHK, &fixed, -1);

    fixed ^= 1;
    gtk_list_store_set(GTK_LIST_STORE(model), &iter, C_CHK, fixed, -1);
    gtk_tree_path_free(path);
}

/*--------------------------------------------------------------
* If looking for just the Control key, we must check for it by key value
*/
G_MODULE_EXPORT gboolean
win_keypress_CB(GtkWidget *object, GdkEvent *ev, gpointer user_data)
{
    idle = 0;

    if (ev->key.keyval == GDK_KEY_Control_L || ev->key.keyval == GDK_KEY_Control_R) {
        CtrlDown = faststep;
        g_print("Control Press\n");
    }
    return FALSE;
}

/*--------------------------------------------------------------
* If looking for just the Control key, we must check for it by key value
*/
G_MODULE_EXPORT gboolean
win_keyrelease_CB(GtkWidget *object, GdkEvent *ev, gpointer user_data)
{
    idle = 0;

    if (ev->key.keyval == GDK_KEY_Control_L || ev->key.keyval == GDK_KEY_Control_R) {
        CtrlDown = 1;
        g_print("Control release\n");
    }

    return FALSE;
}

//--------------------------------------------------------------
G_MODULE_EXPORT gboolean
kill_idle_CB (GtkWidget *widget, GdkEvent *event, gpointer user_data)
{
    int x, y;
    GdkModifierType state;
    gchar s[20];

    idle = 0;

    if (event->motion.is_hint) {
        gdk_window_get_pointer(event->motion.window, &x, &y, &state);
    } else {
        x = event->motion.x;
        y = event->motion.y;
        state = event->motion.state;
    }

    g_snprintf(s, sizeof(s), "%d", x);
    gtk_label_set_text(label1, s);
    g_snprintf(s, sizeof(s), "%d", y);
    gtk_label_set_text(label2, s);

    return FALSE;
}

//--------------------------------------------------------------
gboolean time_handler(gpointer user_data)
{
    time_t rawtime;
    struct tm * timeinfo;
    char buffer[16];

    if ((idle/10) >= idlesec) {
        time (&rawtime);
        timeinfo = localtime(&rawtime);

        strftime(buffer, 16, "IDLE %H:%M:%S\n", timeinfo);
        gtk_label_set_text(label3, buffer);
    } else {
        gtk_label_set_text(label3, "");
        idle++;
    }

    return TRUE;
}

//--------------------------------------------------------------
int main (int argc, char *argv[])
{
    gtk_init (&argc, &argv);
    builder = gtk_builder_new ();
    gtk_builder_add_from_file(builder, "minGladeTW.glade", NULL);
    window = GTK_WIDGET(gtk_builder_get_object(builder, "window1"));
    g_timeout_add(100, time_handler, NULL);

    treeview1 = GTK_WIDGET(gtk_builder_get_object(builder, "treeview1"));

    chkRend   = GTK_CELL_RENDERER(gtk_builder_get_object(builder, "chkRend"));
    rendFifth = GTK_CELL_RENDERER(gtk_builder_get_object(builder, "rendFifth"));

    label1 = GTK_LABEL(gtk_builder_get_object(builder, "label1"));
    label2 = GTK_LABEL(gtk_builder_get_object(builder, "label2"));
    label3 = GTK_LABEL(gtk_builder_get_object(builder, "label3"));

    treeselectmode = gtk_tree_view_get_selection (GTK_TREE_VIEW(treeview1));

    gtk_tree_selection_set_mode(treeselectmode, GTK_SELECTION_SINGLE);
    store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(treeview1)));
    model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeview1));

    col = gtk_tree_view_get_column(GTK_TREE_VIEW (treeview1), C_FIVE);
    gtk_tree_view_column_set_cell_data_func(col, rendFifth, five_cell_data_function, NULL, NULL);

    gtk_builder_connect_signals(builder, NULL);
    g_object_unref(G_OBJECT(builder));

    LoadData();

    gtk_widget_show_all(window);
    gtk_main ();
    return (0);
}

void ClearData()
{
    if (!gtk_tree_model_get_iter_first(model, &iter) == FALSE)
        gtk_list_store_clear(store);
    row_count = 0;
}

void LoadData()
{
    model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeview1));
    g_object_ref(model);
    gtk_tree_view_set_model(GTK_TREE_VIEW(treeview1), NULL);

    gtk_list_store_append(store, &iter);
    gtk_list_store_set(store, &iter, C_CHK, TRUE,
                       C_ONE, 1245,
                       C_TWO, "SOME <b>NAME</b> LIKE NIME",
                       C_THREE, "Some name like nime",
                       C_FOUR, "KOM",
                       C_FIVE, 1254.12568,
                       C_SIX, 243.125689,
                       C_SEVEN, "", -1);

    gtk_list_store_append(store, &iter);
    gtk_list_store_set(store, &iter, C_CHK, FALSE,
                       C_ONE, 1,
                       C_TWO, "NO <b>NAME</b>",
                       C_THREE, "No name",
                       C_FOUR, "NA",
                       C_FIVE, 0.00,
                       C_SIX, 0.00,
                       C_SEVEN, "", -1);

    gtk_list_store_append(store, &iter);
    gtk_list_store_set(store, &iter, C_CHK, FALSE,
                       C_ONE, 153,
                       C_TWO, "INTERESTING <b>NAME</b>D ROW",
                       C_THREE, "Interesting named row",
                       C_FOUR, "ROW",
                       C_FIVE, 22235.1101158,
                       C_SIX, 1235.215,
                       C_SEVEN, "", -1);

    gtk_list_store_append(store, &iter);
    gtk_list_store_set(store, &iter, C_CHK, FALSE,
                       C_ONE, 84,
                       C_TWO, "<b>NAME</b> OF THE GAME",
                       C_THREE, "Name of the game",
                       C_FOUR, "NAM",
                       C_FIVE, 169.74521,
                       C_SIX, 1.585236,
                       C_SEVEN, "", -1);

    gtk_tree_view_set_model(GTK_TREE_VIEW(treeview1), model);
    g_object_unref(model);

    row_count = getlastrow();
//--------------------
    if (row_count) {
        path = gtk_tree_path_new_from_string("0");
        gtk_tree_selection_select_path(treeselectmode, path);
        gtk_tree_path_free(path);
    }
    gtk_widget_grab_focus(treeview1);
}

int getlastrow()
{
    GtkTreeIter iter1;
    row_count = 0;

    gtk_tree_model_get_iter_first(model, &iter1);

    while(gtk_tree_model_iter_next(model, &iter1)) {

        row_count++;
    }
    return row_count;
}

void DoEvents()
{
    while (gtk_events_pending ())
        gtk_main_iteration ();
}

Code:
<?xml version="1.0" encoding="UTF-8"?>
<interface>
  <requires lib="gtk+" version="2.24"/>
  <object class="GtkListStore" id="liststore1">
    <columns>
      <!-- column-name colChk -->
      <column type="gboolean"/>
      <!-- column-name colOne -->
      <column type="gint"/>
      <!-- column-name colTwo -->
      <column type="gchararray"/>
      <!-- column-name colThree -->
      <column type="gchararray"/>
      <!-- column-name colFour -->
      <column type="gchararray"/>
      <!-- column-name colFive -->
      <column type="gfloat"/>
      <!-- column-name colSix -->
      <column type="gfloat"/>
      <!-- column-name colLast -->
      <column type="gchararray"/>
    </columns>
    <data>
      <row>
        <col id="0">False</col>
        <col id="1">28</col>
        <col id="2" translatable="yes">MY &lt;b&gt;NAME&lt;/b&gt; IS GLADE</col>
        <col id="3" translatable="yes">My name is Glade</col>
        <col id="4" translatable="yes">LIT</col>
        <col id="5">1244.056884765625</col>
        <col id="6">24.125690460205078</col>
        <col id="7" translatable="yes"> </col>
      </row>
      <row>
        <col id="0">False</col>
        <col id="1">1256</col>
        <col id="2" translatable="yes">SECOND ROW FROM GLADE</col>
        <col id="3" translatable="yes">Second row from glade</col>
        <col id="4" translatable="yes">ROW</col>
        <col id="5">1458.326904296875</col>
        <col id="6">0</col>
        <col id="7" translatable="yes"> </col>
      </row>
    </data>
  </object>
  <object class="GtkWindow" id="window1">
    <property name="height_request">400</property>
    <property name="can_focus">False</property>
    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_STRUCTURE_MASK</property>
    <signal name="destroy" handler="on_gtk_main_quit" swapped="no"/>
    <signal name="key-release-event" handler="win_keyrelease_CB" swapped="no"/>
    <signal name="key-press-event" handler="win_keypress_CB" swapped="no"/>
    <signal name="button-release-event" handler="kill_idle_CB" swapped="no"/>
    <signal name="motion-notify-event" handler="kill_idle_CB" swapped="no"/>
    <signal name="button-press-event" handler="kill_idle_CB" swapped="no"/>
    <signal name="delete-event" handler="on_gtk_main_quit" swapped="no"/>
    <child>
      <object class="GtkHBox" id="hbox1">
        <property name="can_focus">False</property>
        <child>
          <object class="GtkVBox" id="vbox1">
            <property name="can_focus">False</property>
            <property name="border_width">5</property>
            <child>
              <placeholder/>
            </child>
            <child>
              <placeholder/>
            </child>
            <child>
              <placeholder/>
            </child>
            <child>
              <object class="GtkHBox" id="hbox5">
                <property name="can_focus">False</property>
                <property name="homogeneous">True</property>
                <child>
                  <object class="GtkButton" id="button1">
                    <property name="label" translatable="yes">Exit</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_gtk_main_quit" swapped="no"/>
                  </object>
                  <packing>
                    <property name="expand">True</property>
                    <property name="fill">True</property>
                    <property name="position">0</property>
                  </packing>
                </child>
                <child>
                  <placeholder/>
                </child>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">False</property>
                <property name="position">3</property>
              </packing>
            </child>
            <child>
              <object class="GtkHBox" id="hbox4">
                <property name="can_focus">False</property>
                <property name="homogeneous">True</property>
                <child>
                  <object class="GtkButton" id="button2">
                    <property name="label" translatable="yes">Play</property>
                    <property name="can_focus">True</property>
                    <property name="receives_default">True</property>
                    <property name="use_action_appearance">False</property>
                    <signal name="clicked" handler="btnPlay_CB" swapped="no"/>
                  </object>
                  <packing>
                    <property name="expand">True</property>
                    <property name="fill">True</property>
                    <property name="position">0</property>
                  </packing>
                </child>
                <child>
                  <placeholder/>
                </child>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">False</property>
                <property name="position">4</property>
              </packing>
            </child>
            <child>
              <object class="GtkHSeparator" id="hseparator1">
                <property name="can_focus">False</property>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">True</property>
                <property name="padding">10</property>
                <property name="position">5</property>
              </packing>
            </child>
            <child>
              <object class="GtkHBox" id="hbox3">
                <property name="can_focus">False</property>
                <property name="homogeneous">True</property>
                <child>
                  <object class="GtkLabel" id="label1">
                    <property name="can_focus">False</property>
                    <property name="xalign">0</property>
                    <property name="label" translatable="yes">move mouse</property>
                  </object>
                  <packing>
                    <property name="expand">True</property>
                    <property name="fill">True</property>
                    <property name="position">0</property>
                  </packing>
                </child>
                <child>
                  <placeholder/>
                </child>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">False</property>
                <property name="position">6</property>
              </packing>
            </child>
            <child>
              <object class="GtkHBox" id="hbox2">
                <property name="can_focus">False</property>
                <property name="homogeneous">True</property>
                <child>
                  <object class="GtkLabel" id="label2">
                    <property name="can_focus">False</property>
                    <property name="xalign">0</property>
                    <property name="label" translatable="yes">here</property>
                  </object>
                  <packing>
                    <property name="expand">True</property>
                    <property name="fill">True</property>
                    <property name="position">0</property>
                  </packing>
                </child>
                <child>
                  <placeholder/>
                </child>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">False</property>
                <property name="position">7</property>
              </packing>
            </child>
            <child>
              <object class="GtkHSeparator" id="hseparator2">
                <property name="can_focus">False</property>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">True</property>
                <property name="padding">10</property>
                <property name="position">8</property>
              </packing>
            </child>
            <child>
              <object class="GtkLabel" id="label3">
                <property name="width_request">99</property>
                <property name="can_focus">False</property>
                <property name="xalign">0</property>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">False</property>
                <property name="position">9</property>
              </packing>
            </child>
            <child>
              <placeholder/>
            </child>
          </object>
          <packing>
            <property name="expand">True</property>
            <property name="fill">True</property>
            <property name="position">0</property>
          </packing>
        </child>
        <child>
          <object class="GtkTreeView" id="treeview1">
            <property name="can_focus">True</property>
            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_STRUCTURE_MASK | GDK_SCROLL_MASK</property>
            <property name="model">liststore1</property>
            <property name="search_column">4</property>
            <property name="rubber_banding">True</property>
            <signal name="button-press-event" handler="tree_button_press" swapped="no"/>
            <signal name="key-press-event" handler="tree_key_press" swapped="no"/>
            <signal name="row-activated" handler="on_dblclick" swapped="no"/>
            <signal name="motion-notify-event" handler="motion_notify_event" swapped="no"/>
            <signal name="scroll-event" handler="on_view_scroll_event" swapped="no"/>
            <child internal-child="selection">
              <object class="GtkTreeSelection" id="treeview-selection1">
                <signal name="changed" handler="on_changed" swapped="no"/>
              </object>
            </child>
            <child>
              <object class="GtkTreeViewColumn" id="colChk">
                <property name="alignment">0.5</property>
                <child>
                  <object class="GtkCellRendererToggle" id="chkRend">
                    <signal name="toggled" handler="chktoggled_CB" swapped="no"/>
                  </object>
                  <attributes>
                    <attribute name="active">0</attribute>
                  </attributes>
                </child>
              </object>
            </child>
            <child>
              <object class="GtkTreeViewColumn" id="col1">
                <property name="sizing">fixed</property>
                <property name="fixed_width">70</property>
                <property name="title">First </property>
                <property name="alignment">1</property>
                <child>
                  <object class="GtkCellRendererText" id="rendFirst">
                    <property name="width">70</property>
                    <property name="xalign">1</property>
                  </object>
                  <attributes>
                    <attribute name="text">1</attribute>
                  </attributes>
                </child>
              </object>
            </child>
            <child>
              <object class="GtkTreeViewColumn" id="col2">
                <property name="sizing">fixed</property>
                <property name="fixed_width">230</property>
                <property name="title">Second</property>
                <child>
                  <object class="GtkCellRendererText" id="rendSecond"/>
                  <attributes>
                    <attribute name="markup">2</attribute>
                  </attributes>
                </child>
              </object>
            </child>
            <child>
              <object class="GtkTreeViewColumn" id="col3">
                <property name="visible">False</property>
                <property name="title">Third</property>
                <child>
                  <object class="GtkCellRendererText" id="rendThird"/>
                  <attributes>
                    <attribute name="text">3</attribute>
                  </attributes>
                </child>
              </object>
            </child>
            <child>
              <object class="GtkTreeViewColumn" id="col4">
                <property name="sizing">fixed</property>
                <property name="fixed_width">60</property>
                <property name="title">Fourth</property>
                <property name="alignment">0.5</property>
                <child>
                  <object class="GtkCellRendererText" id="rendFourth">
                    <property name="width">60</property>
                    <property name="xalign">0.50999999046325684</property>
                    <property name="alignment">center</property>
                    <property name="editable">True</property>
                    <signal name="editing-started" handler="FOUR_editing_started_cb" swapped="no"/>
                    <signal name="edited" handler="FOUR_edited_callback" swapped="no"/>
                  </object>
                  <attributes>
                    <attribute name="text">4</attribute>
                  </attributes>
                </child>
              </object>
            </child>
            <child>
              <object class="GtkTreeViewColumn" id="col5">
                <property name="sizing">fixed</property>
                <property name="fixed_width">90</property>
                <property name="title">Fifth </property>
                <property name="alignment">1</property>
                <child>
                  <object class="GtkCellRendererText" id="rendFifth">
                    <property name="width">90</property>
                    <property name="xalign">1</property>
                  </object>
                  <attributes>
                    <attribute name="text">5</attribute>
                  </attributes>
                </child>
              </object>
            </child>
            <child>
              <object class="GtkTreeViewColumn" id="col6">
                <property name="sizing">fixed</property>
                <property name="fixed_width">90</property>
                <property name="title">Sixth </property>
                <property name="alignment">1</property>
                <property name="sort_indicator">True</property>
                <child>
                  <object class="GtkCellRendererText" id="rendSixth">
                    <property name="xalign">1</property>
                  </object>
                  <attributes>
                    <attribute name="text">6</attribute>
                  </attributes>
                </child>
              </object>
            </child>
            <child>
              <object class="GtkTreeViewColumn" id="col7">
                <child>
                  <object class="GtkCellRendererText" id="rendSeventh"/>
                  <attributes>
                    <attribute name="text">7</attribute>
                  </attributes>
                </child>
              </object>
            </child>
          </object>
          <packing>
            <property name="expand">True</property>
            <property name="fill">True</property>
            <property name="position">1</property>
          </packing>
        </child>
        <child>
          <placeholder/>
        </child>
      </object>
    </child>
  </object>
</interface>


The first thing I did was to run the code through astyle to re-format to code to make it easier to read. I also rearranged the code to remove the C99 style code, but have left the C++ style comments, this should allow the code to compile in more places.

Next I dealt with the memory leaks. These were mainly the use of g_strdup_printf() with the string not being freed. As well as other places such as allocating a GtkTreePath and not freeing it, obtaining a string and not freeing. These were mainly fixed by adding the correct freeing, but in some places because the expected string is small I allocated it on the stack and used bound check formatting of the strings using g_snprintf().

I changed the input parameters of scroll() to int as that is what the compiler would have done anyway internally and the use of char would be doing a fair bit of conversion in the back ground.

I then fixed the proto-types of all the call-backs and corrected the return values.

I also removed a large amount of deprecated code such as GDK_Home should now be GDK_KEY_Home. But have left some code that is deprecated in GTK+ 3.

I then looked at the Glade file. To do the alignment of the cell renderers you need to set both the "xalign" and "width" properties to get the expected alignment you want. For the text cell renderer the default "xalign" is 0.0 even though in Glade it shows up as 0.5. To get around this I used 0.51 , so that it is not a default value, which is probably close enough, but enough to tell GTK+/Glade to set "xalign" to centre-ish.

As for the problem with the TreeView. I did take a bit of time to try and work this out. it seams that it is not always passing the motion events from the TreeView to Widgets below it. This could be that GtkTreeView uses "motion-notify-event" internally. I have done a work around for it by adding extra code to motion_notify_event() in your code. This basically gets the pointer position for the window and sets the labels. It still does not work for when the mouse pointer is over the header of the TreeView.

As for tools for checking for memory leaks there are many out there, one of the most famous is valgrind. Valgrind can be very slow and with GTK+ does emit a fair amount of false positives so a suppression file will need to be generated.

Errol.

_________________
E.


Top
 Profile  
 
 Post subject: Re: From GtkObject to GtkWidget
PostPosted: Sat Aug 20, 2011 7:00 pm 
Offline
Familiar Face

Joined: Fri Jul 01, 2011 6:40 pm
Posts: 48
Location: Croatia
Hello errol,
Yes, you are absent for some time and I find "width property" is important in aligning. But setting a middle with value 0,51 I didn't find. So thank you for that. In meantime i post new topic in order to get help on window mouse movement.

Well, I'm not new in programming but I am new in C and GTK so thank you very much for common advices and code which I studied very carefully. Regarding code I use code::blocks and they have astyle integrated and also valgrind but I dont know to use this.

1) Is here some simple way like: "you have %ld" bytes of free memory so I can watch memory corruption through debugging?

2) Regarding strdup: Is this regular solution?
Code:
    char* fstr = g_strdup_printf( "%.2f", value_in5);
    g_object_set(rendFive, "text", fstr, NULL);
    g_free(fstr);


3) Why is important to not use deprecated expressions if they work?

4) I don't like this solution for catching motion position because I can have 5 or more treeviews on window and then there would be much of error prone coding. Something similar happens with MS controls and "forms". I also take a time on this problem and didn't find a solution but I find interesting behaviors. More on this on my next post "Signals from window".

5) Is here some way to get kind of "anykeyboardevent" and "anymouseevent" to controll idle timer instead with mouse motion?

6) Anyway, I would like to get help on recognizing which widget calls signal handler if two of them have connected to same callback like we talk before.

Thank you for helping.
nime.


Top
 Profile  
 
 Post subject: Re: From GtkObject to GtkWidget
PostPosted: Sun Aug 21, 2011 12:01 am 
Offline
Never Seen the Sunlight

Joined: Mon Apr 28, 2008 5:52 am
Posts: 509
Location: UK
Hi,

Been busy with work :) Need to do that to pay the bills.

The having to do the 0,51 is a little bug in Glade, but does force it to not use the default setting. I do not use an IDE as such. "astyle" is a programme that formats your code to a style set by an option. I did this because your original code used several different styles which made it a bit harder to read. It is a very simple programme to use just have a look at the man page for it and experiment.

Valgrind is basically a memory allocation debugging tool. To be honest I do not use it as I find it too slow on my computer. I found the memory allocation errors the old way, by just looking at the code. There are other tools out there that can help find problems with your code. "rats" and "flawfinder" are similar tools that look at the code and list what could be a problem, such as security flaws etc. "splint" is another tool that looks at the code, but tries to look for bugs in the code. "leaktracer" works on a running programme and then outputs a file that can show where the memory leaks have happened. "duma" works on a running programme and can show memory leaks, mismatched allocation/deallocation buffer over/under flow, etc. Also Glib has very basic memory debugging built in so have a look at the manual page for that.

So basically there is a lot of tools that can help you, but no simple way of saying "you have %d bytes corrupt". The best way is to find a combination of tools that you find works for you (I use flawfinder, splint and leaktracer). Just have a read of the manuals to see which suits you more.

With regards to g_strdup_printf() and g_free(), this is absolutely fine to use. I used a fixed sized buffer on the stack as I knew the text was going to be small and not having to allocate and then deallocate the memory would be faster.

It is always best to avoid deprecated stuff when writing new code, even if it does work. What may happen is that in the next version of GTK+ it may well be removed and your code will not be able to be compiled without reworking. This has already happened with the change from GTK+ v2 to GTK+ v3. Think of any thing that is marked as deprecated as a warning that it will be removed at sometime and is only there for old code to be kept working until it can be re-written.

As for motion events and treeviews it seams to need some very complex handling. But 1am is not really the time to think about this!!!!

Errol.

_________________
E.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 8 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group