Yasumichi Akahoshi
yasum****@users*****
2005年 9月 6日 (火) 20:45:12 JST
Index: cxplorer/src/cxp-file-list-store.c diff -u cxplorer/src/cxp-file-list-store.c:1.1 cxplorer/src/cxp-file-list-store.c:1.2 --- cxplorer/src/cxp-file-list-store.c:1.1 Mon Sep 5 17:45:28 2005 +++ cxplorer/src/cxp-file-list-store.c Tue Sep 6 20:45:11 2005 @@ -1,7 +1,7 @@ /*************************************************************************** * cxp-file-list-store.c * - * 土 9月 3 23:50:52 2005 + * å 9æ 3 23:50:52 2005 * Copyright 2005 Yasumichi Akahoshi * yasum****@users***** ***************************************************************************/ @@ -29,6 +29,7 @@ #include <glib/gi18n.h> #include <gtk/gtk.h> #include <cxp.h> +#include <string.h> #include "cxp-file-list-store.h" static void cxp_file_list_store_class_init (CxpFileListStoreClass * klass); @@ -66,14 +67,46 @@ GtkTreeIter * iter, GtkTreeIter * child); +/* -- GtkTreeSortable interface functions -- */ + +static gboolean cxp_file_list_store_sortable_get_sort_column_id (GtkTreeSortable * + sortable, + gint * sort_col_id, + GtkSortType * order); + +static void cxp_file_list_store_sortable_set_sort_column_id (GtkTreeSortable * sortable, + gint sort_col_id, + GtkSortType order); + +static void cxp_file_list_store_sortable_set_sort_func (GtkTreeSortable * sortable, + gint sort_col_id, + GtkTreeIterCompareFunc + sort_func, gpointer user_data, + GtkDestroyNotify destroy_func); + +static void cxp_file_list_store_sortable_set_default_sort_func (GtkTreeSortable * + sortable, + GtkTreeIterCompareFunc + sort_func, + gpointer user_data, + GtkDestroyNotify + destroy_func); + +static gboolean cxp_file_list_store_sortable_has_default_sort_func (GtkTreeSortable * + sortable); + +static void cxp_file_list_store_resort (CxpFileListStore * cxp_file_list_store); +static void cxp_file_list_store_sortable_init (GtkTreeSortableIface * iface); struct CxpFileListStorePrivate { /* Place Private Members Here */ - GType column_types[FILE_LIST_N_COLUMNS]; + GType column_types[FILE_LIST_N_COLUMNS]; GPtrArray *store; - gint stamp; + gint sort_id; + GtkSortType sort_order; + gint stamp; }; typedef enum @@ -121,6 +154,16 @@ g_type_add_interface_static (type, GTK_TYPE_TREE_MODEL, &tree_model_info); + + static const GInterfaceInfo tree_sortable_info = { + (GInterfaceInitFunc) cxp_file_list_store_sortable_init, + NULL, + NULL + }; + + g_type_add_interface_static (type, + GTK_TYPE_TREE_SORTABLE, + &tree_sortable_info); } return type; @@ -134,7 +177,7 @@ object_class->finalize = cxp_file_list_store_finalize; /* Create signals here: - cxp_file_list_store_signals[SIGNAL_TYPE_EXAMPLE] = g_signal_new(...) + * cxp_file_list_store_signals[SIGNAL_TYPE_EXAMPLE] = g_signal_new(...) */ } @@ -154,6 +197,14 @@ iface->iter_parent = cxp_file_list_store_iter_parent; } +static void cxp_file_list_store_sortable_init (GtkTreeSortableIface * iface) +{ + iface->get_sort_column_id = cxp_file_list_store_sortable_get_sort_column_id; + iface->set_sort_column_id = cxp_file_list_store_sortable_set_sort_column_id; + iface->set_sort_func = cxp_file_list_store_sortable_set_sort_func; /* NOT SUPPORTED */ + iface->set_default_sort_func = cxp_file_list_store_sortable_set_default_sort_func; /* NOT SUPPORTED */ + iface->has_default_sort_func = cxp_file_list_store_sortable_has_default_sort_func; /* NOT SUPPORTED */ +} static void cxp_file_list_store_init (CxpFileListStore * obj) { @@ -170,7 +221,10 @@ g_assert (FILE_LIST_N_COLUMNS == 7); - obj->priv->stamp = g_random_int(); + obj->priv->stamp = g_random_int (); + + obj->priv->sort_id = SORT_ID_NONE; + obj->priv->sort_order = GTK_SORT_ASCENDING; } static void cxp_file_list_store_finalize (GObject * object) @@ -206,9 +260,11 @@ * ******************************************************************************/ -static GtkTreeModelFlags cxp_file_list_store_get_flags (GtkTreeModel *tree_model) +static GtkTreeModelFlags cxp_file_list_store_get_flags (GtkTreeModel * + tree_model) { - g_return_val_if_fail (CXP_IS_FILE_LIST_STORE(tree_model), (GtkTreeModelFlags)0); + g_return_val_if_fail (CXP_IS_FILE_LIST_STORE (tree_model), + (GtkTreeModelFlags) 0); return (GTK_TREE_MODEL_LIST_ONLY | GTK_TREE_MODEL_ITERS_PERSIST); } @@ -221,9 +277,9 @@ * ******************************************************************************/ -static gint cxp_file_list_store_get_n_columns (GtkTreeModel *tree_model) +static gint cxp_file_list_store_get_n_columns (GtkTreeModel * tree_model) { - g_return_val_if_fail (CXP_IS_FILE_LIST_STORE(tree_model), 0); + g_return_val_if_fail (CXP_IS_FILE_LIST_STORE (tree_model), 0); return FILE_LIST_N_COLUMNS; } @@ -236,12 +292,15 @@ * *****************************************************************************/ -static GType cxp_file_list_store_get_column_type (GtkTreeModel *tree_model, gint index) +static GType cxp_file_list_store_get_column_type (GtkTreeModel * tree_model, + gint index) { - g_return_val_if_fail (CXP_IS_FILE_LIST_STORE(tree_model), G_TYPE_INVALID); - g_return_val_if_fail (index < FILE_LIST_N_COLUMNS && index >= 0, G_TYPE_INVALID); + g_return_val_if_fail (CXP_IS_FILE_LIST_STORE (tree_model), + G_TYPE_INVALID); + g_return_val_if_fail (index < FILE_LIST_N_COLUMNS + && index >= 0, G_TYPE_INVALID); - return CXP_FILE_LIST_STORE(tree_model)->priv->column_types[index]; + return CXP_FILE_LIST_STORE (tree_model)->priv->column_types[index]; } @@ -255,37 +314,39 @@ * ******************************************************************************/ -static gboolean cxp_file_list_store_get_iter (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreePath *path) +static gboolean cxp_file_list_store_get_iter (GtkTreeModel * tree_model, + GtkTreeIter * iter, + GtkTreePath * path) { CxpFileListStore *obj; CxpFileInfo *record; gint *indices, n, depth; - g_assert(CXP_IS_FILE_LIST_STORE(tree_model)); - g_assert(path!=NULL); + g_assert (CXP_IS_FILE_LIST_STORE (tree_model)); + g_assert (path != NULL); - obj = CXP_FILE_LIST_STORE(tree_model); + obj = CXP_FILE_LIST_STORE (tree_model); - indices = gtk_tree_path_get_indices(path); - depth = gtk_tree_path_get_depth(path); + indices = gtk_tree_path_get_indices (path); + depth = gtk_tree_path_get_depth (path); /* we do not allow children */ - g_assert(depth == 1); /* depth 1 = top level; a list only has top level nodes and no children */ + g_assert (depth == 1); /* depth 1 = top level; a list only has top level nodes and no children */ - n = indices[0]; /* the n-th top level row */ + n = indices[0]; /* the n-th top level row */ - if ( n >= obj->priv->store->len || n < 0 ) + if (n >= obj->priv->store->len || n < 0) return FALSE; - record = g_ptr_array_index(obj->priv->store, n); - g_assert(record != NULL); + record = g_ptr_array_index (obj->priv->store, n); + g_assert (record != NULL); record->pos = n; /* We simply store a pointer to our custom record in the iter */ - iter->stamp = obj->priv->stamp; - iter->user_data = record; - iter->user_data2 = NULL; /* unused */ - iter->user_data3 = NULL; /* unused */ + iter->stamp = obj->priv->stamp; + iter->user_data = record; + iter->user_data2 = NULL; /* unused */ + iter->user_data3 = NULL; /* unused */ return TRUE; } @@ -297,22 +358,23 @@ * physical position of that row in the list). * ******************************************************************************/ -static GtkTreePath * cxp_file_list_store_get_path (GtkTreeModel *tree_model, GtkTreeIter *iter) +static GtkTreePath *cxp_file_list_store_get_path (GtkTreeModel * tree_model, + GtkTreeIter * iter) { - GtkTreePath *path; + GtkTreePath *path; CxpFileInfo *record; CxpFileListStorePrivate *priv; - g_return_val_if_fail (CXP_IS_FILE_LIST_STORE(tree_model), NULL); + g_return_val_if_fail (CXP_IS_FILE_LIST_STORE (tree_model), NULL); g_return_val_if_fail (iter != NULL, NULL); g_return_val_if_fail (iter->user_data != NULL, NULL); - priv = CXP_FILE_LIST_STORE(tree_model)->priv; + priv = CXP_FILE_LIST_STORE (tree_model)->priv; - record = (CxpFileInfo*) iter->user_data; + record = (CxpFileInfo *) iter->user_data; - path = gtk_tree_path_new(); - gtk_tree_path_append_index(path, record->pos); + path = gtk_tree_path_new (); + gtk_tree_path_append_index (path, record->pos); return path; } @@ -324,47 +386,49 @@ * ******************************************************************************/ -static void cxp_file_list_store_get_value (GtkTreeModel *tree_model, GtkTreeIter *iter, gint column, GValue *value) +static void cxp_file_list_store_get_value (GtkTreeModel * tree_model, + GtkTreeIter * iter, gint column, + GValue * value) { CxpFileInfo *record; - CxpFileListStorePrivate *priv = CXP_FILE_LIST_STORE(tree_model)->priv; + CxpFileListStorePrivate *priv = CXP_FILE_LIST_STORE (tree_model)->priv; - g_return_if_fail (CXP_IS_FILE_LIST_STORE(tree_model)); + g_return_if_fail (CXP_IS_FILE_LIST_STORE (tree_model)); g_return_if_fail (iter != NULL); g_return_if_fail (column < FILE_LIST_N_COLUMNS); g_value_init (value, priv->column_types[column]); - record = (CxpFileInfo*) iter->user_data; + record = (CxpFileInfo *) iter->user_data; - g_return_if_fail ( record != NULL ); + g_return_if_fail (record != NULL); - if(record->pos >= priv->store->len) - g_return_if_reached(); + if (record->pos >= priv->store->len) + g_return_if_reached (); - switch(column) + switch (column) { - case FILE_LIST_COL_RECORD: - g_value_set_pointer(value, record); - break; - case FILE_LIST_COL_FULLPATH: - g_value_set_string(value, record->fullpath); - break; - case FILE_LIST_COL_MIMETYPE: - g_value_set_string(value, record->mime_type); - break; - case FILE_LIST_COL_FILESIZE: - g_value_set_uint(value, record->file_size); - break; - case FILE_LIST_COL_FILEMODE: - g_value_set_uint(value, record->file_mode); - break; - case FILE_LIST_COL_FILETIME: - g_value_set_uint(value, record->file_mtime); - break; - case FILE_LIST_COL_EDITABLE: - g_value_set_boolean(value, record->editable); - break; + case FILE_LIST_COL_RECORD: + g_value_set_pointer (value, record); + break; + case FILE_LIST_COL_FULLPATH: + g_value_set_string (value, record->fullpath); + break; + case FILE_LIST_COL_MIMETYPE: + g_value_set_string (value, record->mime_type); + break; + case FILE_LIST_COL_FILESIZE: + g_value_set_uint (value, record->file_size); + break; + case FILE_LIST_COL_FILEMODE: + g_value_set_uint (value, record->file_mode); + break; + case FILE_LIST_COL_FILETIME: + g_value_set_uint (value, record->file_mtime); + break; + case FILE_LIST_COL_EDITABLE: + g_value_set_boolean (value, record->editable); + break; } } @@ -375,12 +439,13 @@ * to the next row. * ******************************************************************************/ -static gboolean cxp_file_list_store_iter_next (GtkTreeModel *tree_model, GtkTreeIter *iter) +static gboolean cxp_file_list_store_iter_next (GtkTreeModel * tree_model, + GtkTreeIter * iter) { - CxpFileInfo *record, *nextrecord; - CxpFileListStorePrivate *priv = CXP_FILE_LIST_STORE(tree_model)->priv; + CxpFileInfo *record, *nextrecord; + CxpFileListStorePrivate *priv = CXP_FILE_LIST_STORE (tree_model)->priv; - g_return_val_if_fail (CXP_IS_FILE_LIST_STORE(tree_model), FALSE); + g_return_val_if_fail (CXP_IS_FILE_LIST_STORE (tree_model), FALSE); if (iter == NULL || iter->user_data == NULL) return FALSE; @@ -391,13 +456,13 @@ if ((record->pos + 1) >= priv->store->len) return FALSE; - nextrecord = g_ptr_array_index(priv->store, record->pos + 1); + nextrecord = g_ptr_array_index (priv->store, record->pos + 1); - g_assert ( nextrecord != NULL ); + g_assert (nextrecord != NULL); /* g_assert ( nextrecord->pos == (record->pos + 1) ); */ nextrecord->pos = record->pos + 1; - iter->stamp = priv->stamp; + iter->stamp = priv->stamp; iter->user_data = nextrecord; return TRUE; @@ -414,11 +479,14 @@ * row should be returned if it exists. * *****************************************************************************/ -static gboolean cxp_file_list_store_iter_children (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *parent) +static gboolean cxp_file_list_store_iter_children (GtkTreeModel * tree_model, + GtkTreeIter * iter, + GtkTreeIter * parent) { - CxpFileListStorePrivate *priv = CXP_FILE_LIST_STORE(tree_model)->priv; + CxpFileListStorePrivate *priv = CXP_FILE_LIST_STORE (tree_model)->priv; - g_return_val_if_fail (parent == NULL || parent->user_data != NULL, FALSE); + g_return_val_if_fail (parent == NULL + || parent->user_data != NULL, FALSE); /* this is a list, nodes have no children */ if (parent) @@ -433,8 +501,8 @@ return FALSE; /* Set iter to first item in list */ - iter->stamp = priv->stamp; - iter->user_data = g_ptr_array_index(priv->store, 0); + iter->stamp = priv->stamp; + iter->user_data = g_ptr_array_index (priv->store, 0); return TRUE; } @@ -447,7 +515,8 @@ * We only have a list and thus no children. * ******************************************************************************/ -static gboolean cxp_file_list_store_iter_has_child (GtkTreeModel *tree_model, GtkTreeIter *iter) +static gboolean cxp_file_list_store_iter_has_child (GtkTreeModel * tree_model, + GtkTreeIter * iter) { return FALSE; } @@ -465,20 +534,21 @@ * ******************************************************************************/ -static gint cxp_file_list_store_iter_n_children (GtkTreeModel *tree_model, GtkTreeIter *iter) +static gint cxp_file_list_store_iter_n_children (GtkTreeModel * tree_model, + GtkTreeIter * iter) { CxpFileListStorePrivate *priv; g_return_val_if_fail (CXP_IS_FILE_LIST_STORE (tree_model), -1); g_return_val_if_fail (iter == NULL || iter->user_data != NULL, FALSE); - priv = CXP_FILE_LIST_STORE(tree_model)->priv; + priv = CXP_FILE_LIST_STORE (tree_model)->priv; /* special case: if iter == NULL, return number of top-level rows */ if (!iter) return priv->store->len; - return 0; /* otherwise, this is easy again for a list */ + return 0; /* otherwise, this is easy again for a list */ } @@ -492,27 +562,30 @@ * row if it exists. * ******************************************************************************/ -static gboolean cxp_file_list_store_iter_nth_child (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *parent, gint n) +static gboolean cxp_file_list_store_iter_nth_child (GtkTreeModel * tree_model, + GtkTreeIter * iter, + GtkTreeIter * parent, + gint n) { - CxpFileInfo *record; + CxpFileInfo *record; CxpFileListStorePrivate *priv; - g_return_val_if_fail (CXP_IS_FILE_LIST_STORE(tree_model), FALSE); + g_return_val_if_fail (CXP_IS_FILE_LIST_STORE (tree_model), FALSE); - priv = CXP_FILE_LIST_STORE(tree_model)->priv; + priv = CXP_FILE_LIST_STORE (tree_model)->priv; /* a list has only top-level rows */ - if(parent) + if (parent) return FALSE; /* special case: if parent == NULL, set iter to n-th top-level row */ - if( n >= priv->store->len ) + if (n >= priv->store->len) return FALSE; - record = g_ptr_array_index(priv->store, n); + record = g_ptr_array_index (priv->store, n); - g_assert( record != NULL ); + g_assert (record != NULL); record->pos = n; iter->stamp = priv->stamp; @@ -529,11 +602,16 @@ * parents of children, we can just return FALSE. * ******************************************************************************/ -static gboolean cxp_file_list_store_iter_parent (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *child) +static gboolean cxp_file_list_store_iter_parent (GtkTreeModel * tree_model, + GtkTreeIter * iter, + GtkTreeIter * child) { return FALSE; } + + + /***************************************************************************** * * cxp_file_list_store_append_file: Empty lists are boring. This function can @@ -544,48 +622,50 @@ * interested objects know about the new row. * ******************************************************************************/ -void cxp_file_list_store_append_file (CxpFileListStore *obj, const gchar *fullpath, GtkTreeIter *iter) +void cxp_file_list_store_append_file (CxpFileListStore * obj, + const gchar * fullpath, + GtkTreeIter * iter) { - GtkTreePath *path; + GtkTreePath *path; CxpFileInfo *newrecord; CxpFileListStorePrivate *priv; - guint pos; + guint pos; struct stat status; - g_return_if_fail (CXP_IS_FILE_LIST_STORE(obj)); + g_return_if_fail (CXP_IS_FILE_LIST_STORE (obj)); g_return_if_fail (fullpath != NULL); priv = obj->priv; pos = priv->store->len; - newrecord = g_new0(CxpFileInfo, 1); + newrecord = g_new0 (CxpFileInfo, 1); - newrecord->fullpath = g_strdup(fullpath); + newrecord->fullpath = g_strdup (fullpath); stat (fullpath, &status); switch (status.st_mode & S_IFMT) { - case S_IFSOCK: - newrecord->mime_type = g_strdup ("inode/socket"); - break; - case S_IFLNK: - newrecord->mime_type = g_strdup ("inode/symlink"); - break; - case S_IFREG: - newrecord->mime_type = cxp_get_mime_type_for_file(fullpath);; - break; - case S_IFBLK: - newrecord->mime_type = g_strdup ("inode/blockdevice"); - break; - case S_IFDIR: - newrecord->mime_type = g_strdup ("inode/directory"); - break; - case S_IFCHR: - newrecord->mime_type = g_strdup ("inode/chardevice"); - break; - case S_IFIFO: - newrecord->mime_type = g_strdup ("inode/fifo"); - break; + case S_IFSOCK: + newrecord->mime_type = g_strdup ("inode/socket"); + break; + case S_IFLNK: + newrecord->mime_type = g_strdup ("inode/symlink"); + break; + case S_IFREG: + newrecord->mime_type = cxp_get_mime_type_for_file (fullpath);; + break; + case S_IFBLK: + newrecord->mime_type = g_strdup ("inode/blockdevice"); + break; + case S_IFDIR: + newrecord->mime_type = g_strdup ("inode/directory"); + break; + case S_IFCHR: + newrecord->mime_type = g_strdup ("inode/chardevice"); + break; + case S_IFIFO: + newrecord->mime_type = g_strdup ("inode/fifo"); + break; } newrecord->file_size = status.st_size; newrecord->file_mode = status.st_mode; @@ -599,57 +679,60 @@ * (e.g. tree row references) that we have inserted * a new row, and where it was inserted */ - path = gtk_tree_path_new(); - gtk_tree_path_append_index(path, newrecord->pos); + path = gtk_tree_path_new (); + gtk_tree_path_append_index (path, newrecord->pos); - cxp_file_list_store_get_iter(GTK_TREE_MODEL(obj), iter, path); + cxp_file_list_store_get_iter (GTK_TREE_MODEL (obj), iter, path); - gtk_tree_model_row_inserted(GTK_TREE_MODEL(obj), path, iter); + gtk_tree_model_row_inserted (GTK_TREE_MODEL (obj), path, iter); - gtk_tree_path_free(path); + gtk_tree_path_free (path); } -void cxp_file_list_store_clear (CxpFileListStore *obj) +void cxp_file_list_store_clear (CxpFileListStore * obj) { CxpFileListStorePrivate *priv; - g_return_if_fail (CXP_IS_FILE_LIST_STORE(obj)); + g_return_if_fail (CXP_IS_FILE_LIST_STORE (obj)); priv = obj->priv; - if(priv->store->len != 0) + if (priv->store->len != 0) { g_ptr_array_remove_range (priv->store, 0, priv->store->len); } } -void cxp_file_list_store_rename_file (CxpFileListStore *obj, GtkTreeIter *iter, const gchar *fullpath) +void cxp_file_list_store_rename_file (CxpFileListStore * obj, + GtkTreeIter * iter, + const gchar * fullpath) { CxpFileInfo *record; - g_return_if_fail (CXP_IS_FILE_LIST_STORE(obj)); + g_return_if_fail (CXP_IS_FILE_LIST_STORE (obj)); g_return_if_fail (iter != NULL); - record = (CxpFileInfo*) iter->user_data; - if(record->fullpath != NULL) + record = (CxpFileInfo *) iter->user_data; + if (record->fullpath != NULL) { g_free (record->fullpath); } record->fullpath = g_strdup (fullpath); } -void cxp_file_list_store_set_editable (CxpFileListStore *obj, GtkTreeIter *iter, gboolean editable) +void cxp_file_list_store_set_editable (CxpFileListStore * obj, + GtkTreeIter * iter, gboolean editable) { CxpFileInfo *record; - g_return_if_fail (CXP_IS_FILE_LIST_STORE(obj)); + g_return_if_fail (CXP_IS_FILE_LIST_STORE (obj)); g_return_if_fail (iter != NULL); - record = (CxpFileInfo*) iter->user_data; + record = (CxpFileInfo *) iter->user_data; record->editable = editable; } -gboolean cxp_file_list_store_remove (CxpFileListStore *obj, GtkTreeIter *iter) +gboolean cxp_file_list_store_remove (CxpFileListStore * obj, GtkTreeIter * iter) { GtkTreePath *path; CxpFileInfo *ptr, *next; @@ -687,3 +770,176 @@ return TRUE; } } + +/* + * ToDo:以下、要修正 + */ +static gboolean cxp_file_list_store_sortable_get_sort_column_id (GtkTreeSortable * sortable, gint * sort_col_id, GtkSortType * order) +{ + CxpFileListStore *obj; + + g_return_val_if_fail (sortable != NULL, FALSE); + g_return_val_if_fail (CXP_IS_FILE_LIST_STORE (sortable), FALSE); + + obj = CXP_FILE_LIST_STORE (sortable); + + if (sort_col_id) + *sort_col_id = obj->priv->sort_id; + + if (order) + *order = obj->priv->sort_order; + + return TRUE; +} + + +static void +cxp_file_list_store_sortable_set_sort_column_id (GtkTreeSortable * sortable, gint sort_col_id, GtkSortType order) +{ + CxpFileListStore *obj; + + g_return_if_fail (sortable != NULL); + g_return_if_fail (CXP_IS_FILE_LIST_STORE (sortable)); + + obj = CXP_FILE_LIST_STORE (sortable); + + if (obj->priv->sort_id == sort_col_id + && obj->priv->sort_order == order) + return; + + obj->priv->sort_id = sort_col_id; + obj->priv->sort_order = order; + + cxp_file_list_store_resort (obj); + + /* emit "sort-column-changed" signal to tell any tree views + * that the sort column has changed (so the little arrow + * in the column header of the sort column is drawn + * in the right column) */ + + gtk_tree_sortable_sort_column_changed (sortable); +} + + +static void +cxp_file_list_store_sortable_set_sort_func (GtkTreeSortable * sortable, + gint sort_col_id, + GtkTreeIterCompareFunc sort_func, + gpointer user_data, + GtkDestroyNotify destroy_func) +{ + g_warning ("%s is not supported by the CxpFileListStore model.\n", + __FUNCTION__); +} + + +static void +cxp_file_list_store_sortable_set_default_sort_func (GtkTreeSortable * sortable, + GtkTreeIterCompareFunc sort_func, + gpointer user_data, + GtkDestroyNotify destroy_func) +{ + g_warning ("%s is not supported by the CxpFileListStore model.\n", + __FUNCTION__); +} + + +static gboolean +cxp_file_list_store_sortable_has_default_sort_func (GtkTreeSortable * sortable) +{ + return FALSE; +} + + +static gint cxp_file_list_store_compare_records (gint sort_id, CxpFileInfo * a, CxpFileInfo * b) +{ + switch (sort_id) + { + case SORT_ID_NONE: + return 0; + + case SORT_ID_NAME: + if ((a->fullpath) && (b->fullpath)) + return strcmp (a->fullpath, b->fullpath); + + if (a->fullpath == b->fullpath) + return 0; /* both are NULL */ + else + return (a->fullpath == NULL) ? -1 : 1; + case SORT_ID_SIZE: + return a->file_size - b->file_size; + case SORT_ID_TYPE: + if ((a->mime_type) && (b->mime_type)) + return strcmp (a->mime_type, b->mime_type); + + if (a->mime_type == b->mime_type) + return 0; /* both are NULL */ + else + return (a->mime_type == NULL) ? -1 : 1; + case SORT_ID_TIME: + return a->file_mtime - b->file_mtime; + } + + + g_return_val_if_reached (0); +} + + +static gint cxp_file_list_store_qsort_compare_func (CxpFileInfo ** a, CxpFileInfo ** b, CxpFileListStore * obj) +{ + gint ret; + + g_assert ((a) && (b) && (obj)); + + ret = cxp_file_list_store_compare_records (obj->priv->sort_id, *a, *b); + + /* Swap -1 and 1 if sort order is reverse */ + if (ret != 0 && obj->priv->sort_order == GTK_SORT_DESCENDING) + ret = (ret < 0) ? 1 : -1; + + return ret; +} + + +static void cxp_file_list_store_resort (CxpFileListStore * obj) +{ + GtkTreePath *path; + gint *neworder, i; + CxpFileInfo *info; + + g_return_if_fail (obj != NULL); + g_return_if_fail (CXP_IS_FILE_LIST_STORE (obj)); + + if (obj->priv->sort_id == SORT_ID_NONE) + return; + + if (obj->priv->store->len == 0) + return; + + /* resort */ + g_ptr_array_sort_with_data (obj->priv->store, (GCompareDataFunc)cxp_file_list_store_qsort_compare_func, obj); + + /* let other objects know about the new order */ + neworder = g_new0 (gint, obj->priv->store->len); + + for (i = 0; i < obj->priv->store->len; ++i) + { + /* Note that the API reference might be wrong about + * this, see bug number 124790 on bugs.gnome.org. + * Both will work, but one will give you 'jumpy' + * selections after row reordering. */ + /* neworder[(cxp_file_list_store->rows[i])->pos] = i; */ + info = g_ptr_array_index(obj->priv->store, i); + neworder[i] = info->pos; + info->pos = i; + } + + path = gtk_tree_path_new (); + + gtk_tree_model_rows_reordered (GTK_TREE_MODEL (obj), path, NULL, + neworder); + + gtk_tree_path_free (path); + g_free (neworder); +} + Index: cxplorer/src/cxp-file-list-store.h diff -u cxplorer/src/cxp-file-list-store.h:1.1 cxplorer/src/cxp-file-list-store.h:1.2 --- cxplorer/src/cxp-file-list-store.h:1.1 Mon Sep 5 17:45:28 2005 +++ cxplorer/src/cxp-file-list-store.h Tue Sep 6 20:45:11 2005 @@ -33,15 +33,13 @@ G_BEGIN_DECLS - #define CXP_TYPE_FILE_LIST_STORE (cxp_file_list_store_get_type ()) #define CXP_FILE_LIST_STORE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CXP_TYPE_FILE_LIST_STORE, CxpFileListStore)) #define CXP_FILE_LIST_STORE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), CXP_TYPE_FILE_LIST_STORE, CxpFileListStoreClass)) #define CXP_IS_FILE_LIST_STORE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CXP_TYPE_FILE_LIST_STORE)) #define CXP_IS_FILE_LIST_STORE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CXP_TYPE_FILE_LIST_STORE)) #define CXP_FILE_LIST_STORE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CXP_TYPE_FILE_LIST_STORE, CxpFileListStoreClass)) - -enum + enum { FILE_LIST_COL_RECORD = 0, FILE_LIST_COL_FULLPATH, @@ -51,39 +49,56 @@ FILE_LIST_COL_FILETIME, FILE_LIST_COL_EDITABLE, FILE_LIST_N_COLUMNS, -} ; +}; +enum +{ + SORT_ID_NONE = 0, + SORT_ID_NAME, + SORT_ID_SIZE, + SORT_ID_TYPE, + SORT_ID_TIME, +}; typedef struct CxpFileListStorePrivate CxpFileListStorePrivate; -typedef struct { +typedef struct +{ GObject parent; CxpFileListStorePrivate *priv; } CxpFileListStore; -typedef struct { +typedef struct +{ GObjectClass parent_class; /* Add Signal Functions Here */ } CxpFileListStoreClass; -typedef struct { - gchar *fullpath; - gchar *mime_type; - off_t file_size; - mode_t file_mode; - time_t file_mtime; +typedef struct +{ + gchar *fullpath; + gchar *mime_type; + off_t file_size; + mode_t file_mode; + time_t file_mtime; /* admin stuff used by the custom list model */ - guint pos; /* pos within the array */ + guint pos; /* pos within the array */ gboolean editable; } CxpFileInfo; -GType cxp_file_list_store_get_type(); -CxpFileListStore *cxp_file_list_store_new(); -void cxp_file_list_store_append_file (CxpFileListStore *obj, const gchar *fullpath, GtkTreeIter *iter); -void cxp_file_list_store_clear (CxpFileListStore *obj); -void cxp_file_list_store_rename_file (CxpFileListStore *obj, GtkTreeIter *iter, const gchar *fullpath); -void cxp_file_list_store_set_editable (CxpFileListStore *obj, GtkTreeIter *iter, gboolean editable); -gboolean cxp_file_list_store_remove (CxpFileListStore *obj, GtkTreeIter *iter); +GType cxp_file_list_store_get_type (); +CxpFileListStore *cxp_file_list_store_new (); +void cxp_file_list_store_append_file (CxpFileListStore * obj, + const gchar * fullpath, + GtkTreeIter * iter); +void cxp_file_list_store_clear (CxpFileListStore * obj); +void cxp_file_list_store_rename_file (CxpFileListStore * obj, + GtkTreeIter * iter, + const gchar * fullpath); +void cxp_file_list_store_set_editable (CxpFileListStore * obj, + GtkTreeIter * iter, gboolean editable); +gboolean cxp_file_list_store_remove (CxpFileListStore * obj, + GtkTreeIter * iter); #endif /* CXP_FILE_LIST_STORE_H */ Index: cxplorer/src/cxp-right-pane.c diff -u cxplorer/src/cxp-right-pane.c:1.59 cxplorer/src/cxp-right-pane.c:1.60 --- cxplorer/src/cxp-right-pane.c:1.59 Mon Sep 5 17:45:28 2005 +++ cxplorer/src/cxp-right-pane.c Tue Sep 6 20:45:11 2005 @@ -304,7 +304,6 @@ static GtkWidget *cxp_right_pane_file_list_new (CxpRightPane * self) { GtkWidget *file_list; - //GtkListStore *store; CxpFileListStore *store; GtkTreeViewColumn *column; GtkTreeSelection *selection; @@ -312,11 +311,6 @@ //GtkTreeSortable *sortable; file_list = gtk_tree_view_new (); - /* - store = gtk_list_store_new (COL_COUNT, G_TYPE_STRING, G_TYPE_STRING, - G_TYPE_UINT, G_TYPE_STRING, G_TYPE_UINT, - G_TYPE_UINT, G_TYPE_BOOLEAN); - */ store = cxp_file_list_store_new (); gtk_tree_view_set_model (GTK_TREE_VIEW (file_list), GTK_TREE_MODEL (store)); @@ -326,10 +320,10 @@ /* Sort setting */ /* sortable = GTK_TREE_SORTABLE (store); - gtk_tree_sortable_set_sort_func (sortable, COL_DISP_NAME, + gtk_tree_sortable_set_sort_func (sortable, SORT_ID_NAME, cxp_right_pane_compare_by_default, NULL, NULL); - gtk_tree_sortable_set_sort_column_id (sortable, COL_DISP_NAME, + gtk_tree_sortable_set_sort_column_id (sortable, SORT_ID_NAME, GTK_SORT_ASCENDING); */ @@ -344,7 +338,7 @@ cxp_right_pane_draw_icon, self, NULL); renderer = gtk_cell_renderer_text_new (); - //gtk_tree_view_column_set_sort_column_id (column, COL_DISP_NAME); + gtk_tree_view_column_set_sort_column_id (column, SORT_ID_NAME); gtk_tree_view_column_pack_start (column, renderer, FALSE); gtk_tree_view_column_set_attributes (column, renderer, "editable", @@ -362,7 +356,7 @@ "text", FILE_LIST_COL_FILESIZE, NULL); gtk_tree_view_column_set_resizable (column, TRUE); - //gtk_tree_view_column_set_sort_column_id (column, FILE_LIST_COL_FILESIZE); + gtk_tree_view_column_set_sort_column_id (column, SORT_ID_SIZE); gtk_tree_view_append_column (GTK_TREE_VIEW (file_list), column); /* 3rd column */ @@ -373,7 +367,7 @@ gtk_tree_view_column_set_resizable (column, TRUE); gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED); gtk_tree_view_column_set_fixed_width (column, 100); - //gtk_tree_view_column_set_sort_column_id (column, FILE_LIST_COL_MIMETYPE); + gtk_tree_view_column_set_sort_column_id (column, SORT_ID_TYPE); gtk_tree_view_append_column (GTK_TREE_VIEW (file_list), column); /* 4th column */ @@ -381,7 +375,7 @@ column = gtk_tree_view_column_new_with_attributes (_("Update Time"), renderer, NULL); gtk_tree_view_append_column (GTK_TREE_VIEW (file_list), column); - //gtk_tree_view_column_set_sort_column_id (column, FILE_LIST_COL_FILETIME); + gtk_tree_view_column_set_sort_column_id (column, SORT_ID_TIME); gtk_tree_view_column_set_cell_data_func (column, renderer, cxp_right_pane_draw_update_time, NULL, NULL); Index: cxplorer/src/cxplorer-window.c diff -u cxplorer/src/cxplorer-window.c:1.61 cxplorer/src/cxplorer-window.c:1.62 --- cxplorer/src/cxplorer-window.c:1.61 Sat Sep 3 21:55:35 2005 +++ cxplorer/src/cxplorer-window.c Tue Sep 6 20:45:11 2005 @@ -805,7 +805,6 @@ static void cxplorer_window_pref_action (GtkWidget *widget, gpointer user_data) { - CxplorerWindowPrivate *private = CXPLORER_WINDOW_GET_PRIVATE (user_data); GtkWidget *dialog; dialog = cxp_pref_dialog_new (GTK_WINDOW(user_data)); @@ -923,7 +922,6 @@ static void cxplorer_window_bookmark_edit_action (GtkWidget *widget, gpointer user_data) { CxplorerWindow *self = CXPLORER_WINDOW (user_data); - CxplorerWindowPrivate *private = CXPLORER_WINDOW_GET_PRIVATE (self); GtkWidget *window; window = cxp_gconf_pair_editor_new (GTK_WINDOW(self), _("Edit Bookmark"), "/apps/cxp/cxplorer/bookmark", _("Caption"), _("Directory"));