Customize Treeview sort

Source: Internet
Author: User
person.h#ifndef _MODEL_H#define _MODEL_H#include 
 
  #include 
  
   #include 
   
    #define PERSON_TYPE   (  person_get_type() )#define PERSON(obj)     ( G_TYPE_CHECK_INSTANCE_CAST((obj), PERSON_TYPE, CPerson) )#define PERSON_CLASS(klass)  ( G_TYPE_CHECK_CLASS_CAST((klass), PERSON_TYPE, CPersonClass ) )#define IS_PERSON(obj)      ( G_TYPE_CHECK_INSTANCE_TYPE((obj), PERSON_TYPE) )#define IS_PERSONCALSS(klass)    ( G_TYPE_CHECK_CLASS_TYPE((klass), PERSON_TYPE) )#define PERSON_GET_CLASS(obj)   ( G_TYPE_INSTANCE_GET_CLASS(), PERSON_TYPE, CPersonClass )enum{    PERSON_COL_RECORD = 0,    PERSON_COL_NAME,    PERSON_COL_AGE,    PERSON_COL_ALL,};typedef struct _PersonNode PersonNode;typedef struct _CPerson CPerson;typedef struct _CPersonClass CPersonClass;struct _PersonNode{    gchar* name;    gint age;};struct _CPerson{    GObject parent;        gint row_n;    GList* row;    gint col_n;    GType col_type[PERSON_COL_ALL];    GtkSortType type;    gint sort_id;        gint stamp;};struct _CPersonClass{    GObjectClass parent_class;    };/* all of internal interface */GType person_get_type(void);/*{@ property definition for person   */#define  PERSON_PROPERTY_INDEX_NAME 1/*@} end definition   */  /* print function name*/#define PERSON_PRINT_SELF() g_printf("%s/n",__FUNCTION__);/* user interface */CPerson* person_new();void person_append_record( CPerson* person, gchar* name, gint age );void person_preappend_record( CPerson* person, gchar* name, gint age );/*  *  sort   */enum{    SORT_PERSON_NONE,    SORT_PERSON_NAME,    SORT_PERSON_AGE,    };#endif/* person.h*/person.c#include "model.h"#include 
    
     #include 
     
      #include 
      
       static void person_init( CPerson* person){ PERSON_PRINT_SELF(); person->col_n = PERSON_COL_ALL; person->col_type[PERSON_COL_RECORD] = G_TYPE_POINTER; person->col_type[PERSON_COL_NAME] = G_TYPE_STRING; person->col_type[PERSON_COL_AGE] = G_TYPE_INT; person->row = NULL; person->row_n = 0; person->sort_id = 0; person->type = 0; person->stamp = g_random_int();}static void class_init(CPersonClass* klass){ GObjectClass* obj_class = G_OBJECT_CLASS(klass); }static GtkTreeModelFlags _get_flags(GtkTreeModel* tree_model){ g_return_val_if_fail( IS_PERSON(tree_model), (GtkTreeModelFlags)0 ); return GTK_TREE_MODEL_ITERS_PERSIST | GTK_TREE_MODEL_LIST_ONLY;}static gint _get_n_columns( GtkTreeModel* tree_model){ g_return_val_if_fail( IS_PERSON(tree_model), 0); g_print("%s num=%d/n", __FUNCTION__, PERSON(tree_model)->col_n); return PERSON(tree_model)->col_n;}static GType _get_column_type(GtkTreeModel* tree_model, gint index){ g_return_val_if_fail( IS_PERSON(tree_model), 0); g_return_val_if_fail( index < PERSON(tree_model)->col_n && index >=0, 0); g_print("%s %dth type=%d/n", __FUNCTION__,index, PERSON(tree_model)->col_type[index]); return PERSON(tree_model)->col_type[index];}gboolean _get_iter(GtkTreeModel* tree_model, GtkTreeIter* iter, GtkTreePath* path){ CPerson* pm =0; gint * indice = 0, depth = 0; gint n = 0; PersonNode* node; g_assert(IS_PERSON(tree_model)); g_assert(path!=NULL); pm = PERSON(tree_model); indice = gtk_tree_path_get_indices(path); depth = gtk_tree_path_get_depth(path); g_assert(depth==1); n = indice[0]; if( n >= PERSON(tree_model)->row_n || n < 0) return FALSE; node = (PersonNode*)g_list_nth_data(PERSON(tree_model)->row, n); g_assert(node); iter->stamp = pm->stamp; iter->user_data = node; iter->user_data2 = NULL; iter->user_data3 = NULL; return TRUE; }static GtkTreePath* _get_path(GtkTreeModel* tree_model, GtkTreeIter* iter){ GtkTreePath* path = 0; PersonNode* node = 0; CPerson* pm = 0; g_return_val_if_fail( IS_PERSON(tree_model), NULL); g_return_val_if_fail( iter, NULL); g_return_val_if_fail( iter->user_data, NULL); pm = PERSON(tree_model); node = (PersonNode*)iter->user_data; path = gtk_tree_path_new(); gtk_tree_path_append_index(path, g_list_index(pm->row, node) ); return path; }static void _get_value(GtkTreeModel* model, GtkTreeIter* iter, gint column, GValue* value){ CPerson* pm; PersonNode* node; g_return_if_fail( IS_PERSON(model)); g_return_if_fail( iter); g_return_if_fail(column< PERSON(model)->col_n && column >=0); g_value_init(value, PERSON(model)->col_type[column]); node = (PersonNode*) iter->user_data; switch(column) { case PERSON_COL_NAME: g_value_set_string(value, node->name); break; case PERSON_COL_AGE: g_value_set_int(value, node->age); break; default: break; } PERSON_PRINT_SELF();}static gboolean _iter_next(GtkTreeModel* model, GtkTreeIter* iter){ CPerson* pm; PersonNode* node, *next; g_return_val_if_fail( IS_PERSON(model), FALSE); g_return_val_if_fail( iter&&iter->user_data, FALSE); pm = PERSON(model); node = (PersonNode*) iter->user_data; next = (PersonNode*)g_list_nth_data(pm->row, g_list_index(pm->row, node)+1); g_print("free iter %d/n", g_list_index(pm->row, node)); if(!next) return FALSE; iter->stamp = pm->stamp; iter->user_data = next; return TRUE; }static gboolean _iter_children(GtkTreeModel* model, GtkTreeIter* iter, GtkTreeIter* parent){ CPerson* pm; g_return_val_if_fail( IS_PERSON(model), FALSE); g_return_val_if_fail( !parent, FALSE); pm = PERSON(model); if( pm->row_n == 0) return FALSE; iter->stamp = pm->stamp; iter->user_data = g_list_nth_data(pm->row, 0); PERSON_PRINT_SELF(); return TRUE; }static gboolean _iter_has_child(GtkTreeModel* model, GtkTreeIter* iter){ PERSON_PRINT_SELF(); return FALSE; }static gboolean _iter_n_child(GtkTreeModel* model, GtkTreeIter* iter){ CPerson* pm; PERSON_PRINT_SELF(); g_return_val_if_fail( IS_PERSON(model), FALSE); g_return_val_if_fail( iter==NULL || iter->user_data!=NULL, FALSE); pm = PERSON(model); if(!iter) return pm->row_n; return FALSE; }static gboolean _iter_nth_child(GtkTreeModel* model, GtkTreeIter* iter, GtkTreeIter* parent, gint n){ CPerson* pm; PersonNode* node = 0; PERSON_PRINT_SELF(); g_return_val_if_fail( IS_PERSON(model), FALSE); g_return_val_if_fail(!parent, FALSE); pm = PERSON(model); if( n >= pm->row_n ) return FALSE; g_print("%d/n", n); node = g_list_nth_data(pm->row, n); iter->stamp = pm->stamp; iter->user_data = node; return TRUE; }static gboolean _iter_parent(GtkTreeModel* model, GtkTreeIter* iter, GtkTreeIter* child){ return FALSE;}static void interface_init(GtkTreeModelIface* iface){ iface->get_flags = _get_flags; iface->get_n_columns = _get_n_columns; iface->get_column_type = _get_column_type; iface->get_iter = _get_iter; iface->get_path= _get_path; iface->get_value = _get_value; iface->iter_next = _iter_next; iface->iter_children = _iter_children; iface->iter_has_child = _iter_has_child; iface->iter_n_children = _iter_n_child; iface->iter_nth_child = _iter_nth_child; iface->iter_parent = _iter_parent; iface->ref_node = NULL; iface->unref_node = NULL; PERSON_PRINT_SELF();}static void sort_interface_init( GtkTreeSortableIface* iface);GType person_get_type(void){ static GType person_type = 0; if(!person_type){ GTypeInfo info = { sizeof(CPersonClass), /* base init&finalize*/ NULL, NULL, /*Class init & finalize*/ (GClassInitFunc)class_init, NULL, NULL, sizeof(CPerson), 0, (GInstanceInitFunc)person_init }; person_type = g_type_register_static( G_TYPE_OBJECT, "person", &info, 0); if(1) { static const GInterfaceInfo iface_info = { (GInterfaceInitFunc)interface_init, NULL, NULL}; g_type_add_interface_static( person_type, GTK_TYPE_TREE_MODEL, &iface_info); } if(1) { static const GInterfaceInfo sort_iface_info = { (GInterfaceInitFunc)sort_interface_init, NULL, NULL}; g_type_add_interface_static( person_type, GTK_TYPE_TREE_SORTABLE, &sort_iface_info); } } return person_type;}/* sort interface */static void person_model_resort(CPerson* model);static void _set_sort_column_id( GtkTreeSortable* sortable, gint sort_column_id, GtkSortType order){ CPerson* item = 0; PERSON_PRINT_SELF() g_return_if_fail(sortable); g_return_if_fail(IS_PERSON(sortable)); item = PERSON(sortable); if( item->sort_id==sort_column_id && item->type==order) return; item->sort_id = sort_column_id; item->type = order; person_model_resort(PERSON(sortable)); gtk_tree_sortable_sort_column_changed(sortable); }static gboolean _get_sort_column_id( GtkTreeSortable* sortable, gint* sort_column_id, GtkSortType* order){ CPerson* item = 0; PERSON_PRINT_SELF() g_return_val_if_fail(sortable, FALSE); g_return_val_if_fail(IS_PERSON(sortable), FALSE); item = PERSON(sortable); if(sort_column_id) *sort_column_id = item->sort_id; if(order) *order = item->type; return TRUE;}static void _set_sort_func(GtkTreeSortable* sortable, gint sort_column_id, GtkTreeIterCompareFunc func, gpointer data, GtkDestroyNotify destroy ){ PERSON_PRINT_SELF() return;}static void _set_default_sort_func(GtkTreeSortable* sortable, GtkTreeIterCompareFunc func, gpointer data, GtkDestroyNotify destroy ){ PERSON_PRINT_SELF() return;}static gboolean _has_default_sort_func(GtkTreeSortable* sortable){ PERSON_PRINT_SELF() return FALSE;}static void sort_interface_init( GtkTreeSortableIface* iface){ PERSON_PRINT_SELF(); iface->get_sort_column_id = _get_sort_column_id; iface->set_sort_column_id = _set_sort_column_id; iface->set_sort_func = _set_sort_func; iface->set_default_sort_func = _set_default_sort_func; iface->has_default_sort_func = _has_default_sort_func; }CPerson* person_new(){ CPerson* person = 0; //if used the gtype system, we'd call this API for init. //g_type_init(); person = g_object_new(PERSON_TYPE, NULL); return person;}void person_append_record( CPerson* person, gchar* name, gint age ){ GtkTreeModel* model; GtkTreePath* path; GtkTreeIter iter; PersonNode *new1; g_return_if_fail( person); g_return_if_fail(name); new1= g_new0(PersonNode, 1); new1->name = g_strdup(name); new1->age = age; person->row = g_list_append(person->row, new1); person->row_n++; path = gtk_tree_path_new(); gtk_tree_path_append_index(path, g_list_index(person->row, new1) ); _get_iter(GTK_TREE_MODEL(person), &iter, path); gtk_tree_model_row_inserted(GTK_TREE_MODEL(person), path, &iter); gtk_tree_path_free(path);}void person_preappend_record( CPerson* person, gchar* name, gint age ){ GtkTreeModel* model; GtkTreePath* path; GtkTreeIter iter; PersonNode *new1; g_return_if_fail( person); g_return_if_fail(name); person->row_n++; new1= g_new0(PersonNode, 1); new1->name = g_strdup(name); new1->age = age; person->row = g_list_prepend(person->row, new1); path = gtk_tree_path_new(); gtk_tree_path_append_index(path, 0); _get_iter(GTK_TREE_MODEL(person), &iter, path); gtk_tree_model_row_inserted(GTK_TREE_MODEL(person), path, &iter); gtk_tree_path_free(path);}static gint person_record_compare(gint sort_id, PersonNode* a, PersonNode* b){ switch(sort_id) { case SORT_PERSON_NONE: return 0; case SORT_PERSON_AGE: if(a->age == b->age) return 0; if(a->age > b->age) return 1; return -1; case SORT_PERSON_NAME: return g_utf8_collate(a->name, b->name); default: break; } return 0;}static gint person_qsort_compare_func(gpointer a, gpointer b, CPerson* list){ gint ret = 0; g_assert( a&&b&&list); ret = person_record_compare(list->sort_id, (PersonNode*)a, (PersonNode*)b); if(ret!=0 && list->type==GTK_SORT_DESCENDING) ret = ret>0?-1:1; return ret; }static void person_model_resort(CPerson* model){ GList* list_addr = 0, *temp = 0; gint* new = 0, i = 0; GtkTreePath *path = 0; GtkTreeIter iter ; g_return_if_fail(model); g_return_if_fail(IS_PERSON(model)); PERSON_PRINT_SELF() if(model->sort_id==0) return; if(model->row_n==0) return; list_addr = g_list_copy(model->row); new = g_new0(gint, g_list_length(model->row)); model->row = g_list_sort_with_data(model->row, (GCompareDataFunc)person_qsort_compare_func, model); temp = model->row; while(list_addr) { new[i++] = g_list_index(model->row, list_addr->data); list_addr = g_list_next(list_addr); } g_list_free(list_addr); gint k = 0; path = gtk_tree_path_new(); gtk_tree_model_rows_reordered(GTK_TREE_MODEL(model), path, NULL, new); gtk_tree_path_free(path); g_free(new); }main.c#include 
       
        #include 
        
         #include 
         
          #include "callback.h"#include "model.h"struct _GWindow{ GtkWidget* window; GtkWidget* main_image; GtkWidget* sub_image; GtkWidget* button_start; GtkWidget* button_stop; GtkWidget* tree;};typedef struct _GWindow GWindow;void lookup_widget(GladeXML* xml, GWindow* all){ all->window = glade_xml_get_widget(xml, "g_window"); g_assert(all->window!=NULL); all->main_image = glade_xml_get_widget(xml, "g_main_image"); g_assert(all->main_image!=NULL); all->sub_image= glade_xml_get_widget(xml, "g_sub_image"); g_assert(all->sub_image!=NULL); all->button_start= glade_xml_get_widget(xml, "button_start"); g_assert(all->button_start!=NULL); all->button_stop= glade_xml_get_widget(xml, "button_stop"); g_assert(all->button_stop!=NULL); all->tree= glade_xml_get_widget(xml, "treeview"); g_assert(all->tree!=NULL); }gboolean timeout(gpointer data){ gtk_widget_queue_draw(GTK_WIDGET(((GWindow*)(data))->main_image));}void append_data(CPerson * person){ person_append_record(person, "first", 12 ); person_append_record(person, "second", 14 );}void set_mode(GtkWidget* view){ CPerson* person; GtkTreeViewColumn* col; GtkCellRenderer* render; person = person_new(); append_data(person); gtk_tree_view_set_model(GTK_TREE_VIEW(view), GTK_TREE_MODEL(person)); render = gtk_cell_renderer_text_new(); col = gtk_tree_view_column_new(); gtk_tree_view_column_pack_start (col, render, TRUE); gtk_tree_view_column_add_attribute (col, render, "text", PERSON_COL_NAME); gtk_tree_view_column_set_title (col, "Name"); gtk_tree_view_append_column(GTK_TREE_VIEW(view),col); render = gtk_cell_renderer_text_new(); col = gtk_tree_view_column_new(); gtk_tree_view_column_pack_start (col, render, TRUE); gtk_tree_view_column_add_attribute (col, render, "text", PERSON_COL_AGE); gtk_tree_view_column_set_title (col, "age"); gtk_tree_view_append_column(GTK_TREE_VIEW(view),col); gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(person), 2, 0);}gboolean listview_add(gpointer data){ GtkWidget* tree = GTK_WIDGET(data); static gint i = 100; static gint sort[] = {0, 1}; person_preappend_record( PERSON( gtk_tree_view_get_model(tree)), "add", i++); gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(gtk_tree_view_get_model(tree)), 1, 0); return TRUE;}gint main(gint argc, gchar* argv[]){ GladeXML* xml=0; GWindow window; gint x, y; gtk_init(&argc, &argv); xml = glade_xml_new("rsc/g.glade",NULL,NULL); g_assert(xml!=NULL); glade_xml_signal_autoconnect(xml); lookup_widget(xml, &window); set_mode(window.tree); g_signal_connect (G_OBJECT (window.window), "delete_event", GTK_SIGNAL_FUNC (gtk_main_quit), NULL); g_timeout_add(3000, listview_add, window.tree); gtk_main();}
          

          

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.