ModelFilter trouble



Hi,

I'm having trouble with GtkModelFilter. I'm trying to make a shopping list using hildon and a gtknotebook with three tabs, all, have & need. All is the unfiltered model which has a boolean and a label.The need tab shows only items where the boolean is true and the have tabe shows an item only when the boolean is false.

The need tab appears correct when first displayed, but when I click a checkbox, it shows what the have tab shows.

My code is attached.right now, I'm working on the gui, which will eventually be connected to an sqlite backend. My target is maemo on the Nokia N800.

Any help is appreciated.

Thanks,
Jason
#include <hildon/hildon-program.h>
#include <gtk/gtkmain.h>
#include <gtk/gtkbox.h>
#include <gtk/gtklabel.h>
#include <gtk/gtkbutton.h>
#include <stdio.h>
#include <stdlib.h>

GtkTreeModel *create_and_fill_model (void);
GtkWidget *create_view_and_model (void);

void cell_toggled_callback (GtkCellRendererToggle *cell,
                            gchar                 *path_string,
                            GtkTreeView           *tree_view);
GtkTreeView *create_view_from_model( GtkTreeModel *model );
GtkTreeModel *create_model_filter( GtkTreeModel* model, 
                                   int condition );

gboolean tab_focus_callback( GtkNotebook *notebook,
                             gint *arg1,
                             gpointer model );


const true = 1;
const false = 0;

enum {
  COL_NAME = 0,
  COL_NEED,
  NUM_COLS
};

const FILTER_HAVE = 0;
const FILTER_NEED = 1;


gboolean filter_visible( GtkTreeModel *model, 
                         GtkTreeIter *iter, 
                         gpointer data );


int main(int argc, char *argv[])
{
    /* Create needed variables */
    HildonProgram *program;
    HildonWindow *window;
    GtkWidget *view;
    GtkTreeView *have_view;
    GtkTreeView *need_view;
    GtkTreeModel *model;
    GtkTreeModel *have_model;
    GtkTreeModel *need_model;
    GtkWidget *all_label, *need_label, *have_label;
    GtkWidget *scrolled_window, *have_scrolled_window, 
      *need_scrolled_window;
    GtkWidget *notebook;

    /* Initialize the GTK. */
    gtk_init(&argc, &argv);

    /* Create the hildon program and setup the title */
    program = HILDON_PROGRAM(hildon_program_get_instance());
    g_set_application_name("ShoppingList");

    /* Create HildonWindow and set it to HildonProgram */
    window = HILDON_WINDOW(hildon_window_new());
    hildon_program_add_window(program, window);

    scrolled_window = gtk_scrolled_window_new( GTK_ADJUSTMENT( NULL ),
                                               GTK_ADJUSTMENT( NULL ) );

    // setup the notebook
    notebook = gtk_notebook_new();
    gtk_notebook_set_tab_pos( GTK_NOTEBOOK( notebook ),
                              GTK_POS_BOTTOM );

    gtk_container_add (GTK_CONTAINER (window), notebook);

    view = create_view_and_model();
    model = gtk_tree_view_get_model( GTK_TREE_VIEW( view ) );

    gtk_container_add (GTK_CONTAINER (scrolled_window), view);

    // add the all tab
    all_label = gtk_label_new( "All" );
    gtk_notebook_append_page( GTK_NOTEBOOK( notebook ),
                              scrolled_window, 
                              all_label );

    /*
    // create the "have" filtered model
    have_scrolled_window = gtk_scrolled_window_new( NULL, NULL );
    have_model = create_model_filter(  model, FILTER_HAVE );
    have_view  = create_view_from_model( GTK_TREE_MODEL( have_model ) );
    
    gtk_container_add (GTK_CONTAINER( have_scrolled_window ), 
                       GTK_WIDGET( have_view ) );

    // add the Have tab
    have_label = gtk_label_new( "Have" );
    gtk_notebook_append_page( GTK_NOTEBOOK( notebook ), 
                              have_scrolled_window, 
                              have_label );


    // refilter HAVE tab on focus
    g_signal_connect( GTK_NOTEBOOK( notebook ), "switch-page", 
                     (GCallback) tab_focus_callback, have_model);
    
    */

    // create the "need" filtered model
    need_scrolled_window = gtk_scrolled_window_new( NULL, NULL );
    need_model = create_model_filter(  model, FILTER_NEED );
    gtk_tree_model_filter_refilter( need_model );
    need_view  = create_view_from_model( GTK_TREE_MODEL( need_model ) );
    
    gtk_container_add (GTK_CONTAINER( need_scrolled_window ), 
                       GTK_WIDGET( need_view ) );

    // add the Need tab
    need_label = gtk_label_new( "Need" );
    gtk_notebook_append_page( GTK_NOTEBOOK( notebook ), 
                              need_scrolled_window, 
                              need_label );

    // refilter NEED tab on focus
    //g_signal_connect( GTK_NOTEBOOK( notebook ), "switch-page", 
    //       (GCallback) tab_focus_callback, need_view);


    /* Connect signal to X in the upper corner */
    g_signal_connect( G_OBJECT( window ), "delete_event",
                      G_CALLBACK( gtk_main_quit ), NULL );

    /* Begin the main application */
    gtk_widget_show_all( GTK_WIDGET( window ) );
    gtk_main();

    /* Exit */
    return EXIT_SUCCESS;
}

gboolean filter_visible( GtkTreeModel *model, 
                         GtkTreeIter *iter, 
                         gpointer data ) {
  gint *filter = (gint *) data;
  gboolean column_value;
  gboolean result = FALSE;

  gtk_tree_model_get (GTK_TREE_MODEL (model), iter, 
                      COL_NEED, &column_value, -1);

  // if "need" view
  if ( *filter == FILTER_NEED ) {
    // "need" view, show rows where need_column is true
    result = column_value;
  } else {
    // "have" view, show rows where need_column is false
    result = column_value==TRUE ? FALSE : TRUE;
  }

  return result;
}


GtkTreeModel *create_model_filter( GtkTreeModel* model, 
                                   int condition ) {
    
  GtkTreeModel *model_filter = 
    gtk_tree_model_filter_new( model, NULL );
  
  gtk_tree_model_filter_set_visible_func( GTK_TREE_MODEL_FILTER( model_filter ),
                                          filter_visible,
                                          ( gpointer ) &condition, NULL );
  GtkWidget *view = gtk_tree_view_new();
  gtk_tree_view_set_model( GTK_TREE_VIEW( view ), 
                           GTK_TREE_MODEL( model_filter ) );
  return GTK_TREE_MODEL( model_filter );
}

GtkTreeModel *create_and_fill_model (void) {
  GtkListStore  *store;
  GtkTreeIter    iter;
  int i = 0;
  
  store = gtk_list_store_new (NUM_COLS, G_TYPE_STRING, G_TYPE_BOOLEAN);
  
  for( i=0; i < 25; i++ ) {
    /* Append a row and fill in some data */
    char number_string[30];
    char item_string[50] = "item";
    int checked = i % 2;

    snprintf( number_string, 30, "%i", i );

    strncat(item_string, number_string, 50);

    gtk_list_store_append (store, &iter);
    gtk_list_store_set (store, &iter,
                        COL_NAME, item_string,
                        COL_NEED, checked,
                        -1);
  }

  return GTK_TREE_MODEL (store);
}

GtkTreeView *create_view_from_model( GtkTreeModel *model ) {
  GtkCellRenderer     *name_renderer, *need_renderer;
  GtkWidget         *view;

  view = gtk_tree_view_new ();
  gtk_tree_view_set_model (GTK_TREE_VIEW (view), model);

  gtk_tree_view_set_headers_visible( GTK_TREE_VIEW( view ), true );
  /* --- Column #1 --- */

  need_renderer = gtk_cell_renderer_toggle_new ();
  g_object_set( need_renderer, "activatable", TRUE, NULL);
  gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (view),
                                               -1,      
                                               "Need",  
                                               need_renderer,
                                               "active", COL_NEED,
                                               NULL);


  /* --- Column #2 --- */

  name_renderer = gtk_cell_renderer_text_new ();
  gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (view),
                                               -1,      
                                               "Name",  
                                               name_renderer,
                                               "text", COL_NAME,
                                               NULL);


  g_signal_connect(need_renderer, "toggled", 
                   (GCallback) cell_toggled_callback, view);


  /* The tree view has acquired its own reference to the
   *  model, so we can drop ours. That way the model will
   *  be freed automatically when the tree view is destroyed */

  //g_object_unref (model);

  return GTK_TREE_VIEW( view );
}

GtkWidget *create_view_and_model (void) {
  GtkCellRenderer     *name_renderer, *need_renderer;
  GtkListStore        *model;
  GtkWidget           *view;

  view = gtk_tree_view_new ();
  gtk_tree_view_set_headers_visible( GTK_TREE_VIEW( view ), true );
  /* --- Column #1 --- */

  need_renderer = gtk_cell_renderer_toggle_new ();
  g_object_set( need_renderer, "activatable", TRUE, NULL);
  gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (view),
                                               -1,      
                                               "Need",  
                                               need_renderer,
                                               "active", COL_NEED,
                                               NULL);


  /* --- Column #2 --- */

  name_renderer = gtk_cell_renderer_text_new ();
  gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (view),
                                               -1,      
                                               "Name",  
                                               name_renderer,
                                               "text", COL_NAME,
                                               NULL);

  model = create_and_fill_model ();

  g_signal_connect(need_renderer, "toggled", 
                   (GCallback) cell_toggled_callback, view);

  gtk_tree_view_set_model (GTK_TREE_VIEW (view), model);

  /* The tree view has acquired its own reference to the
   *  model, so we can drop ours. That way the model will
   *  be freed automatically when the tree view is destroyed */

  g_object_unref (model);

  return view;
}

void cell_toggled_callback (GtkCellRendererToggle *cell,
                            gchar                 *path_string,
                            GtkTreeView           *tree_view) {
  
  GtkTreeModel *model = gtk_tree_view_get_model (tree_view);
  GtkTreeModelFilter *filter_model;
  //g_print("CB(cell_toggled:tree_view %s\n",G_OBJECT_TYPE_NAME( model ) );
  char *model_class = G_OBJECT_TYPE_NAME( model );
  GtkTreeIter iter;
  GtkTreePath *path, *filter_path;
  gboolean column_value, new_column_value;
  
  path = gtk_tree_path_new_from_string( path_string );

  // get the real model, & path if model is a GtkTreeModelFilter
  if ( !strcmp( "GtkTreeModelFilter", model_class ) ) {
    filter_model = model;
    model = gtk_tree_model_filter_get_model( GTK_TREE_MODEL_FILTER( model ) );
    filter_path = path;

    path = gtk_tree_model_filter_convert_path_to_child_path( filter_model, 
                                                             filter_path);
  }

  if ( !gtk_tree_model_get_iter( GTK_TREE_MODEL( model ), &iter, path ) ) {
    g_warning ("%s: could not find path", G_STRLOC);
    return;
  }
  
  gtk_tree_model_get (GTK_TREE_MODEL (model), &iter, 
                      COL_NEED, &column_value, -1);

  // toggle the column_value 0=>1; 1=>0;
  new_column_value = column_value ? 0 : 1;

  gtk_list_store_set( GTK_LIST_STORE( model ), &iter, 
                      COL_NEED, new_column_value, -1);
  //gtk_list_store_set_value( GTK_LIST_STORE( model ), &iter, 
  //          COL_NEED, new_column_value );

  //gtk_tree_model_row_changed( model, path, &iter );
  gtk_tree_path_free (path);

  // get the real model, & path if model is a GtkTreeModelFilter
  if ( !strcmp( "GtkTreeModelFilter", model_class ) ) {
    gtk_tree_model_filter_refilter( filter_model );
    gtk_tree_path_free (filter_path);
    
  }


  return;
}


gboolean tab_focus_callback( GtkNotebook *notebook,
                             gint *arg1,
                             gpointer data ) {
  //  GtkTreeView* view = (GtkTreeView *)data;
  //g_print( "CB: tab_focus_callback:mode %s\n",G_OBJECT_TYPE_NAME( view ) );
  g_print( "CB: tab_focus_callback:begin\n" );
  //gtk_tree_model_filter_refilter( GTK_TREE_MODEL_FILTER( model ) );
  g_print( "CB: tab_focus_callback:end\n" );
  //  g_print( "CB: tab_focus_callback %i\n",  *arg1 );
  return true;
}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]