Yasumichi Akahoshi
yasum****@users*****
2005年 9月 5日 (月) 17:45:28 JST
Index: cxplorer/src/Makefile.am diff -u cxplorer/src/Makefile.am:1.23 cxplorer/src/Makefile.am:1.24 --- cxplorer/src/Makefile.am:1.23 Sat Sep 3 03:49:23 2005 +++ cxplorer/src/Makefile.am Mon Sep 5 17:45:28 2005 @@ -21,6 +21,8 @@ cxp-pref-dialog.h \ cxp-dir-view.h\ cxp-dir-view.c \ + cxp-file-list-store.h \ + cxp-file-list-store.c \ cxp-right-pane.h \ cxp-right-pane.c \ cxplorer-window.h \ Index: cxplorer/src/Makefile.in diff -u cxplorer/src/Makefile.in:1.28 cxplorer/src/Makefile.in:1.29 --- cxplorer/src/Makefile.in:1.28 Sat Sep 3 03:49:23 2005 +++ cxplorer/src/Makefile.in Mon Sep 5 17:45:28 2005 @@ -51,7 +51,8 @@ PROGRAMS = $(bin_PROGRAMS) am_cxplorer_OBJECTS = main.$(OBJEXT) cxp-property-dialog.$(OBJEXT) \ cxp-pref-dialog.$(OBJEXT) cxp-dir-view.$(OBJEXT) \ - cxp-right-pane.$(OBJEXT) cxplorer-window.$(OBJEXT) + cxp-file-list-store.$(OBJEXT) cxp-right-pane.$(OBJEXT) \ + cxplorer-window.$(OBJEXT) cxplorer_OBJECTS = $(am_cxplorer_OBJECTS) am__DEPENDENCIES_1 = cxplorer_DEPENDENCIES = $(am__DEPENDENCIES_1) @@ -59,6 +60,7 @@ depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles @AMDEP_TRUE @ DEP_FILES = ./$(DEPDIR)/cxp-dir-view.Po \ + @ AMDEP_TRUE@ ./$(DEPDIR)/cxp-file-list-store.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/cxp-pref-dialog.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/cxp-property-dialog.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/cxp-right-pane.Po \ @@ -208,6 +210,8 @@ cxp-pref-dialog.h \ cxp-dir-view.h\ cxp-dir-view.c \ + cxp-file-list-store.h \ + cxp-file-list-store.c \ cxp-right-pane.h \ cxp-right-pane.c \ cxplorer-window.h \ @@ -284,6 +288,7 @@ -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote @ ./$(DEPDIR)/cxp-dir-view.Po @ am__quote@ + @ AMDEP_TRUE@@am__include@ @am__quote @ ./$(DEPDIR)/cxp-file-list-store.Po @ am__quote@ @AMDEP_TRUE@@am__include@ @am__quote @ ./$(DEPDIR)/cxp-pref-dialog.Po @ am__quote@ @AMDEP_TRUE@@am__include@ @am__quote @ ./$(DEPDIR)/cxp-property-dialog.Po @ am__quote@ @AMDEP_TRUE@@am__include@ @am__quote @ ./$(DEPDIR)/cxp-right-pane.Po @ am__quote@ Index: cxplorer/src/cxp-file-list-store.c diff -u /dev/null cxplorer/src/cxp-file-list-store.c:1.1 --- /dev/null Mon Sep 5 17:45:28 2005 +++ cxplorer/src/cxp-file-list-store.c Mon Sep 5 17:45:28 2005 @@ -0,0 +1,689 @@ +/*************************************************************************** + * cxp-file-list-store.c + * + * 土 9月 3 23:50:52 2005 + * Copyright 2005 Yasumichi Akahoshi + * yasum****@users***** + ***************************************************************************/ + +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <glib/gi18n.h> +#include <gtk/gtk.h> +#include <cxp.h> +#include "cxp-file-list-store.h" + +static void cxp_file_list_store_class_init (CxpFileListStoreClass * klass); +static void cxp_file_list_store_model_init (GtkTreeModelIface * iface); +static void cxp_file_list_store_init (CxpFileListStore * sp); +static void cxp_file_list_store_finalize (GObject * object); + +static GtkTreeModelFlags cxp_file_list_store_get_flags (GtkTreeModel * + tree_model); +static gint cxp_file_list_store_get_n_columns (GtkTreeModel * tree_model); +static GType cxp_file_list_store_get_column_type (GtkTreeModel * tree_model, + gint index); +static gboolean cxp_file_list_store_get_iter (GtkTreeModel * tree_model, + GtkTreeIter * iter, + GtkTreePath * path); +static GtkTreePath *cxp_file_list_store_get_path (GtkTreeModel * tree_model, + GtkTreeIter * iter); +static void cxp_file_list_store_get_value (GtkTreeModel * tree_model, + GtkTreeIter * iter, + gint column, GValue * value); +static gboolean cxp_file_list_store_iter_next (GtkTreeModel * tree_model, + GtkTreeIter * iter); +static gboolean cxp_file_list_store_iter_children (GtkTreeModel * tree_model, + GtkTreeIter * iter, + GtkTreeIter * parent); +static gboolean cxp_file_list_store_iter_has_child (GtkTreeModel * tree_model, + GtkTreeIter * iter); +static gint cxp_file_list_store_iter_n_children (GtkTreeModel * tree_model, + GtkTreeIter * iter); +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_parent (GtkTreeModel * tree_model, + GtkTreeIter * iter, + GtkTreeIter * child); + + + +struct CxpFileListStorePrivate +{ + /* Place Private Members Here */ + GType column_types[FILE_LIST_N_COLUMNS]; + GPtrArray *store; + gint stamp; +}; + +typedef enum +{ + /* Place Signal Types Here */ + SIGNAL_TYPE_EXAMPLE, + LAST_SIGNAL +} CxpFileListStoreSignalType; + +typedef struct +{ + CxpFileListStore *object; +} CxpFileListStoreSignal; + +static guint cxp_file_list_store_signals[LAST_SIGNAL] = { 0 }; +static GObjectClass *parent_class = NULL; + +GType cxp_file_list_store_get_type () +{ + static GType type = 0; + + if (type == 0) + { + static const GTypeInfo our_info = { + sizeof (CxpFileListStoreClass), + NULL, + NULL, + (GClassInitFunc) cxp_file_list_store_class_init, + NULL, + NULL, + sizeof (CxpFileListStore), + 0, + (GInstanceInitFunc) cxp_file_list_store_init, + }; + + type = g_type_register_static (G_TYPE_OBJECT, + "CxpFileListStore", &our_info, + 0); + + static const GInterfaceInfo tree_model_info = { + (GInterfaceInitFunc) cxp_file_list_store_model_init, + NULL, + NULL + }; + + g_type_add_interface_static (type, GTK_TYPE_TREE_MODEL, + &tree_model_info); + } + + return type; +} + +static void cxp_file_list_store_class_init (CxpFileListStoreClass * klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + object_class->finalize = cxp_file_list_store_finalize; + + /* Create signals here: + cxp_file_list_store_signals[SIGNAL_TYPE_EXAMPLE] = g_signal_new(...) + */ +} + +static void cxp_file_list_store_model_init (GtkTreeModelIface * iface) +{ + iface->get_flags = cxp_file_list_store_get_flags; + iface->get_n_columns = cxp_file_list_store_get_n_columns; + iface->get_column_type = cxp_file_list_store_get_column_type; + iface->get_iter = cxp_file_list_store_get_iter; + iface->get_path = cxp_file_list_store_get_path; + iface->get_value = cxp_file_list_store_get_value; + iface->iter_next = cxp_file_list_store_iter_next; + iface->iter_children = cxp_file_list_store_iter_children; + iface->iter_has_child = cxp_file_list_store_iter_has_child; + iface->iter_n_children = cxp_file_list_store_iter_n_children; + iface->iter_nth_child = cxp_file_list_store_iter_nth_child; + iface->iter_parent = cxp_file_list_store_iter_parent; +} + + +static void cxp_file_list_store_init (CxpFileListStore * obj) +{ + obj->priv = g_new0 (CxpFileListStorePrivate, 1); + /* Initialize private members, etc. */ + obj->priv->store = g_ptr_array_new (); + obj->priv->column_types[0] = G_TYPE_POINTER; + obj->priv->column_types[1] = G_TYPE_STRING; + obj->priv->column_types[2] = G_TYPE_STRING; + obj->priv->column_types[3] = G_TYPE_UINT; + obj->priv->column_types[4] = G_TYPE_UINT; + obj->priv->column_types[5] = G_TYPE_UINT; + obj->priv->column_types[6] = G_TYPE_BOOLEAN; + + g_assert (FILE_LIST_N_COLUMNS == 7); + + obj->priv->stamp = g_random_int(); +} + +static void cxp_file_list_store_finalize (GObject * object) +{ + CxpFileListStore *cobj; + + cobj = CXP_FILE_LIST_STORE (object); + + /* Free private members, etc. */ + g_ptr_array_free (cobj->priv->store, TRUE); + + g_free (cobj->priv); + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +CxpFileListStore *cxp_file_list_store_new () +{ + CxpFileListStore *obj; + + obj = CXP_FILE_LIST_STORE (g_object_new + (CXP_TYPE_FILE_LIST_STORE, NULL)); + + return obj; +} + +/***************************************************************************** + * + * cxp_file_list_store_get_flags: tells the rest of the world whether our tree model + * has any special characteristics. In our case, + * we have a list model (instead of a tree), and each + * tree iter is valid as long as the row in question + * exists, as it only contains a pointer to our struct. + * + ******************************************************************************/ + +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); + + return (GTK_TREE_MODEL_LIST_ONLY | GTK_TREE_MODEL_ITERS_PERSIST); +} + + +/***************************************************************************** + * + * cxp_file_list_store_get_n_columns: tells the rest of the world how many data + * columns we export via the tree model interface + * + ******************************************************************************/ + +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); + + return FILE_LIST_N_COLUMNS; +} + + +/***************************************************************************** + * + * cxp_file_list_store_get_column_type: tells the rest of the world which type of + * data an exported model column contains + * + *****************************************************************************/ + +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); + + return CXP_FILE_LIST_STORE(tree_model)->priv->column_types[index]; +} + + +/***************************************************************************** + * + * cxp_file_list_store_get_iter: converts a tree path (physical position) into a + * tree iter structure (the content of the iter + * fields will only be used internally by our model). + * We simply store a pointer to our CustomRecord + * structure that represents that row in the tree iter. + * + ******************************************************************************/ + +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); + + obj = CXP_FILE_LIST_STORE(tree_model); + + 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 */ + + n = indices[0]; /* the n-th top level row */ + + if ( n >= obj->priv->store->len || n < 0 ) + return FALSE; + + 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 */ + + return TRUE; +} + + +/***************************************************************************** + * + * cxp_file_list_store_get_path: converts a tree iter into a tree path (ie. the + * physical position of that row in the list). + * + ******************************************************************************/ +static GtkTreePath * cxp_file_list_store_get_path (GtkTreeModel *tree_model, GtkTreeIter *iter) +{ + GtkTreePath *path; + CxpFileInfo *record; + CxpFileListStorePrivate *priv; + + 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; + + record = (CxpFileInfo*) iter->user_data; + + path = gtk_tree_path_new(); + gtk_tree_path_append_index(path, record->pos); + + return path; +} + +/***************************************************************************** + * + * cxp_file_list_store_get_value: Returns a row's exported data columns + * (_get_value is what gtk_tree_model_get uses) + * + ******************************************************************************/ + +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; + + 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; + + g_return_if_fail ( record != NULL ); + + if(record->pos >= priv->store->len) + g_return_if_reached(); + + 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; + } +} + + +/***************************************************************************** + * + * cxp_file_list_store_iter_next: Takes an iter structure and sets it to point + * to the next row. + * + ******************************************************************************/ +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; + + g_return_val_if_fail (CXP_IS_FILE_LIST_STORE(tree_model), FALSE); + + if (iter == NULL || iter->user_data == NULL) + return FALSE; + + record = (CxpFileInfo *) iter->user_data; + + /* Is this the last record in the list? */ + if ((record->pos + 1) >= priv->store->len) + return FALSE; + + nextrecord = g_ptr_array_index(priv->store, record->pos + 1); + + g_assert ( nextrecord != NULL ); + /* g_assert ( nextrecord->pos == (record->pos + 1) ); */ + nextrecord->pos = record->pos + 1; + + iter->stamp = priv->stamp; + iter->user_data = nextrecord; + + return TRUE; +} + + +/***************************************************************************** + * + * cxp_file_list_store_iter_children: Returns TRUE or FALSE depending on whether + * the row specified by 'parent' has any children. + * If it has children, then 'iter' is set to + * point to the first child. Special case: if + * 'parent' is NULL, then the first top-level + * row should be returned if it exists. + * + *****************************************************************************/ +static gboolean cxp_file_list_store_iter_children (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *parent) +{ + CxpFileListStorePrivate *priv = CXP_FILE_LIST_STORE(tree_model)->priv; + + g_return_val_if_fail (parent == NULL || parent->user_data != NULL, FALSE); + + /* this is a list, nodes have no children */ + if (parent) + return FALSE; + + /* parent == NULL is a special case; we need to return the first top-level row */ + + g_return_val_if_fail (CXP_IS_FILE_LIST_STORE (tree_model), FALSE); + + /* No rows => no first row */ + if (priv->store->len == 0) + return FALSE; + + /* Set iter to first item in list */ + iter->stamp = priv->stamp; + iter->user_data = g_ptr_array_index(priv->store, 0); + + return TRUE; +} + + +/***************************************************************************** + * + * cxp_file_list_store_iter_has_child: Returns TRUE or FALSE depending on whether + * the row specified by 'iter' has any children. + * We only have a list and thus no children. + * + ******************************************************************************/ +static gboolean cxp_file_list_store_iter_has_child (GtkTreeModel *tree_model, GtkTreeIter *iter) +{ + return FALSE; +} + + +/***************************************************************************** + * + * cxp_file_list_store_iter_n_children: Returns the number of children the row + * specified by 'iter' has. This is usually 0, + * as we only have a list and thus do not have + * any children to any rows. A special case is + * when 'iter' is NULL, in which case we need + * to return the number of top-level nodes, + * ie. the number of rows in our list. + * + ******************************************************************************/ + +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; + + /* 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 */ +} + + +/***************************************************************************** + * + * cxp_file_list_store_iter_nth_child: If the row specified by 'parent' has any + * children, set 'iter' to the n-th child and + * return TRUE if it exists, otherwise FALSE. + * A special case is when 'parent' is NULL, in + * which case we need to set 'iter' to the n-th + * row if it exists. + * + ******************************************************************************/ +static gboolean cxp_file_list_store_iter_nth_child (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *parent, gint n) +{ + CxpFileInfo *record; + CxpFileListStorePrivate *priv; + + g_return_val_if_fail (CXP_IS_FILE_LIST_STORE(tree_model), FALSE); + + priv = CXP_FILE_LIST_STORE(tree_model)->priv; + + /* a list has only top-level rows */ + if(parent) + return FALSE; + + /* special case: if parent == NULL, set iter to n-th top-level row */ + + if( n >= priv->store->len ) + return FALSE; + + record = g_ptr_array_index(priv->store, n); + + g_assert( record != NULL ); + record->pos = n; + + iter->stamp = priv->stamp; + iter->user_data = record; + + return TRUE; +} + + +/***************************************************************************** + * + * cxp_file_list_store_iter_parent: Point 'iter' to the parent node of 'child'. As + * we have a list and thus no children and no + * parents of children, we can just return FALSE. + * + ******************************************************************************/ +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 + * be used in your own code to add rows to the + * list. Note how we emit the "row-inserted" + * signal after we have appended the row + * internally, so the tree view and other + * interested objects know about the new row. + * + ******************************************************************************/ +void cxp_file_list_store_append_file (CxpFileListStore *obj, const gchar *fullpath, GtkTreeIter *iter) +{ + GtkTreePath *path; + CxpFileInfo *newrecord; + CxpFileListStorePrivate *priv; + guint pos; + struct stat status; + + 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->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; + } + newrecord->file_size = status.st_size; + newrecord->file_mode = status.st_mode; + newrecord->file_mtime = status.st_mtime; + newrecord->pos = pos; + newrecord->editable = FALSE; + + g_ptr_array_add (priv->store, newrecord); + + /* inform the tree view and other interested objects + * (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); + + 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_path_free(path); +} + +void cxp_file_list_store_clear (CxpFileListStore *obj) +{ + CxpFileListStorePrivate *priv; + + g_return_if_fail (CXP_IS_FILE_LIST_STORE(obj)); + + priv = obj->priv; + 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) +{ + CxpFileInfo *record; + + 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) + { + g_free (record->fullpath); + } + record->fullpath = g_strdup (fullpath); +} + +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 (iter != NULL); + + record = (CxpFileInfo*) iter->user_data; + record->editable = editable; +} + +gboolean cxp_file_list_store_remove (CxpFileListStore *obj, GtkTreeIter *iter) +{ + GtkTreePath *path; + CxpFileInfo *ptr, *next; + CxpFileListStorePrivate *priv; + guint pos; + + g_return_val_if_fail (CXP_IS_FILE_LIST_STORE (obj), FALSE); + g_return_val_if_fail (iter != NULL, FALSE); + + path = cxp_file_list_store_get_path (GTK_TREE_MODEL (obj), iter); + priv = obj->priv; + + ptr = iter->user_data; + pos = ptr->pos; + next = g_ptr_array_index (priv->store, pos + 1); + + g_ptr_array_remove (priv->store, ptr); + //ptr = (CxpFileInfo *) g_ptr_array_remove (priv->store, ptr); + gtk_tree_model_row_deleted (GTK_TREE_MODEL (obj), path); + gtk_tree_path_free (path); + g_free (ptr->fullpath); + g_free (ptr->mime_type); + g_free (ptr); + + if (next == NULL) + { + iter->stamp = 0; + return FALSE; + } + else + { + iter->stamp = priv->stamp; + next->pos = pos; + iter->user_data = next; + return TRUE; + } +} Index: cxplorer/src/cxp-file-list-store.h diff -u /dev/null cxplorer/src/cxp-file-list-store.h:1.1 --- /dev/null Mon Sep 5 17:45:28 2005 +++ cxplorer/src/cxp-file-list-store.h Mon Sep 5 17:45:28 2005 @@ -0,0 +1,89 @@ +/*************************************************************************** + * cxp-file-list-store.h + * + * 土 9月 3 23:50:52 2005 + * Copyright 2005 Yasumichi Akahoshi + * yasum****@users***** + ***************************************************************************/ + +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef CXP_FILE_LIST_STORE_H +#define CXP_FILE_LIST_STORE_H + +#include <glib.h> +#include <glib-object.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> + + +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 +{ + FILE_LIST_COL_RECORD = 0, + FILE_LIST_COL_FULLPATH, + FILE_LIST_COL_MIMETYPE, + FILE_LIST_COL_FILESIZE, + FILE_LIST_COL_FILEMODE, + FILE_LIST_COL_FILETIME, + FILE_LIST_COL_EDITABLE, + FILE_LIST_N_COLUMNS, +} ; + + +typedef struct CxpFileListStorePrivate CxpFileListStorePrivate; + +typedef struct { + GObject parent; + CxpFileListStorePrivate *priv; +} CxpFileListStore; + +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; + + /* admin stuff used by the custom list model */ + 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); + +#endif /* CXP_FILE_LIST_STORE_H */ Index: cxplorer/src/cxp-right-pane.c diff -u cxplorer/src/cxp-right-pane.c:1.58 cxplorer/src/cxp-right-pane.c:1.59 --- cxplorer/src/cxp-right-pane.c:1.58 Mon Sep 5 13:58:06 2005 +++ cxplorer/src/cxp-right-pane.c Mon Sep 5 17:45:28 2005 @@ -16,6 +16,7 @@ #include <time.h> #include <unistd.h> #include "cxp-right-pane.h" +#include "cxp-file-list-store.h" /* If you use Pimpls, include the private structure * definition here. Some people create a cxp-right_pane-private.h header @@ -46,23 +47,6 @@ CXP_RIGHT_PANE_GCONF_CLIENT = 1, }; -/* - * ツリーモデルの列番号を定義する列挙型 - * This enumeration define column number of tree model. - */ -enum -{ - COL_TERMINATOR = -1, /**< Terminator */ - COL_DISP_NAME, /**< displayname */ - COL_FILE_PATH, /**< Full path of file */ - COL_FILE_SIZE, /**< File size */ - COL_FILE_TYPE, /**< string of file type. */ - COL_FILE_MODE, /**< File type */ - COL_UPDATE_TIME, /**< Update time of file */ - COL_EDITABLE, - COL_COUNT /**< Count of columns */ -}; - /** * This enumeration define signal. */ @@ -96,6 +80,10 @@ GtkTreeViewColumn * column, gpointer user_data); static void cxp_right_pane_on_key_pressed (GtkWidget *widget, GdkEventKey *event, gpointer user_data); +static void cxp_right_pane_draw_filename (GtkTreeViewColumn * tree_column, + GtkCellRenderer * cell, + GtkTreeModel * tree_model, + GtkTreeIter * iter, gpointer data); static void cxp_right_pane_draw_icon (GtkTreeViewColumn * tree_column, GtkCellRenderer * cell, GtkTreeModel * tree_model, @@ -112,7 +100,7 @@ GtkTreeIter * iter_b, gpointer user_data); static GtkTreeIter cxp_right_pane_append_file (CxpRightPane * self, - GtkListStore * store, + CxpFileListStore * store, const gchar * fullpath); static void cxp_right_pane_show_preview (CxpRightPane * self, GtkTextBuffer * text_buffer, @@ -316,28 +304,34 @@ static GtkWidget *cxp_right_pane_file_list_new (CxpRightPane * self) { GtkWidget *file_list; - GtkListStore *store; + //GtkListStore *store; + CxpFileListStore *store; GtkTreeViewColumn *column; GtkTreeSelection *selection; GtkCellRenderer *renderer; - GtkTreeSortable *sortable; + //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)); selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (file_list)); gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE); /* Sort setting */ + /* sortable = GTK_TREE_SORTABLE (store); gtk_tree_sortable_set_sort_func (sortable, COL_DISP_NAME, cxp_right_pane_compare_by_default, NULL, NULL); gtk_tree_sortable_set_sort_column_id (sortable, COL_DISP_NAME, GTK_SORT_ASCENDING); + */ /* 1st column */ column = gtk_tree_view_column_new (); @@ -350,11 +344,14 @@ 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, COL_DISP_NAME); gtk_tree_view_column_pack_start (column, renderer, FALSE); - gtk_tree_view_column_set_attributes (column, renderer, "text", - COL_DISP_NAME, "editable", - COL_EDITABLE, NULL); + gtk_tree_view_column_set_attributes (column, renderer, + "editable", + FILE_LIST_COL_EDITABLE, NULL); + gtk_tree_view_column_set_cell_data_func (column, renderer, + cxp_right_pane_draw_filename, + self, NULL); g_signal_connect (renderer, "edited", G_CALLBACK (cxp_right_pane_cell_edited), self); @@ -363,20 +360,20 @@ g_object_set (renderer, "xalign", 1.0, NULL); column = gtk_tree_view_column_new_with_attributes (_("Size"), renderer, "text", - COL_FILE_SIZE, NULL); + FILE_LIST_COL_FILESIZE, NULL); gtk_tree_view_column_set_resizable (column, TRUE); - gtk_tree_view_column_set_sort_column_id (column, COL_FILE_SIZE); + //gtk_tree_view_column_set_sort_column_id (column, FILE_LIST_COL_FILESIZE); gtk_tree_view_append_column (GTK_TREE_VIEW (file_list), column); /* 3rd column */ renderer = gtk_cell_renderer_text_new (); column = gtk_tree_view_column_new_with_attributes (_("Type"), renderer, "text", - COL_FILE_TYPE, NULL); + FILE_LIST_COL_MIMETYPE, NULL); 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, COL_FILE_TYPE); + //gtk_tree_view_column_set_sort_column_id (column, FILE_LIST_COL_MIMETYPE); gtk_tree_view_append_column (GTK_TREE_VIEW (file_list), column); /* 4th column */ @@ -384,7 +381,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, COL_UPDATE_TIME); + //gtk_tree_view_column_set_sort_column_id (column, FILE_LIST_COL_FILETIME); gtk_tree_view_column_set_cell_data_func (column, renderer, cxp_right_pane_draw_update_time, NULL, NULL); @@ -430,8 +427,8 @@ model = gtk_tree_view_get_model (treeview); if (gtk_tree_model_get_iter (model, &iter, treepath)) { - gtk_tree_model_get (model, &iter, COL_FILE_PATH, - &fullpath, COL_TERMINATOR); + gtk_tree_model_get (model, &iter, FILE_LIST_COL_FULLPATH, + &fullpath, -1); cxp_right_pane_show_preview (self, text_buffer, fullpath); g_free (fullpath); @@ -467,8 +464,8 @@ model = gtk_tree_view_get_model (treeview); gtk_tree_model_get_iter (model, &iter, path); - gtk_tree_model_get (model, &iter, COL_FILE_PATH, &fullpath, - COL_TERMINATOR); + gtk_tree_model_get (model, &iter, FILE_LIST_COL_FULLPATH, &fullpath, + -1); if (g_file_test (fullpath, G_FILE_TEST_IS_DIR)) { @@ -507,6 +504,25 @@ } } +static void cxp_right_pane_draw_filename (GtkTreeViewColumn * tree_column, + GtkCellRenderer * cell, + GtkTreeModel * tree_model, + GtkTreeIter * iter, gpointer data) +{ + gchar *fullpath; + gchar *filename; + + gtk_tree_model_get (tree_model, iter, FILE_LIST_COL_FULLPATH, &fullpath, -1); + if ((filename = cxp_path_get_basename_of_utf8 (fullpath)) == NULL) + { + filename = g_strdup (_("(Invalid filename)")); + } + + g_object_set (cell, "text", filename, NULL); + + g_free (fullpath); +} + /** * This function is called back before pixbuf cell is painted. * @param tree_column [in] Pointer to instance fo GtkTreeViewColumn. @@ -525,8 +541,8 @@ GdkPixbuf *icon; struct stat status; - gtk_tree_model_get (tree_model, iter, COL_FILE_PATH, - &filename, COL_TERMINATOR); + gtk_tree_model_get (tree_model, iter, FILE_LIST_COL_FULLPATH, + &filename, -1); lstat (filename, &status); switch (status.st_mode & S_IFMT) { @@ -575,8 +591,8 @@ time_t updated; struct tm *tm; - gtk_tree_model_get (tree_model, iter, COL_UPDATE_TIME, - &updated, COL_TERMINATOR); + gtk_tree_model_get (tree_model, iter, FILE_LIST_COL_FILETIME, + &updated, -1); tm = localtime (&updated); time_string = g_new (gchar, 20); strftime (time_string, 20, "%Y/%m/%d %H:%M:%S", tm); @@ -602,13 +618,12 @@ gchar *error_msg; gtk_tree_model_get_iter (model, &iter, path); - gtk_tree_model_get (model, &iter, COL_FILE_PATH, &srcpath, - COL_TERMINATOR); + gtk_tree_model_get (model, &iter, FILE_LIST_COL_FULLPATH, &srcpath, + -1); srcbase = cxp_path_get_basename_of_utf8 (srcpath); if (strcmp (srcbase, new_text) == 0) { - gtk_list_store_set (GTK_LIST_STORE (model), &iter, COL_EDITABLE, - FALSE, -1); + cxp_file_list_store_set_editable (CXP_FILE_LIST_STORE(model), &iter, FALSE); g_free (srcbase); g_free (srcpath); gtk_tree_path_free (path); @@ -624,32 +639,18 @@ errno = 0; if (rename (srcpath, destpath) == 0) { - gtk_list_store_set (GTK_LIST_STORE (model), &iter, - COL_FILE_PATH, destpath, - COL_DISP_NAME, g_strdup (new_text), - COL_EDITABLE, FALSE, -1); + cxp_file_list_store_rename_file (CXP_FILE_LIST_STORE(model), &iter, destpath); + cxp_file_list_store_set_editable (CXP_FILE_LIST_STORE(model), &iter, FALSE); } else { - gtk_list_store_set (GTK_LIST_STORE (model), &iter, COL_EDITABLE, - FALSE, -1); + cxp_file_list_store_set_editable (CXP_FILE_LIST_STORE(model), &iter, FALSE); cxp_error_dialog_run_about_file (srcbase); - /* - dialog = gtk_message_dialog_new (NULL, - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_CLOSE, - "%s", - g_strerror (errno)); - gtk_dialog_run (GTK_DIALOG (dialog)); - gtk_widget_destroy (dialog); - */ } } else { - gtk_list_store_set (GTK_LIST_STORE (model), &iter, COL_EDITABLE, - FALSE, -1); + cxp_file_list_store_set_editable (CXP_FILE_LIST_STORE(model), &iter, FALSE); error_msg = g_strdup_printf (_("%s is already exists."), new_text); dialog = gtk_message_dialog_new (NULL, @@ -662,6 +663,7 @@ g_free (error_msg); } + g_free (destpath); g_free (destbase_locale); g_free (dirname); g_free (srcpath); @@ -687,10 +689,10 @@ gint mode_a, mode_b; gchar *name_a, *name_b; - gtk_tree_model_get (model, iter_a, COL_DISP_NAME, &name_a, - COL_FILE_MODE, &mode_a, COL_TERMINATOR); - gtk_tree_model_get (model, iter_b, COL_DISP_NAME, &name_b, - COL_FILE_MODE, &mode_b, COL_TERMINATOR); + gtk_tree_model_get (model, iter_a, FILE_LIST_COL_FULLPATH, &name_a, + FILE_LIST_COL_FILEMODE, &mode_a, -1); + gtk_tree_model_get (model, iter_b, FILE_LIST_COL_FULLPATH, &name_b, + FILE_LIST_COL_FILEMODE, &mode_b, -1); mode_a &= S_IFMT; mode_b &= S_IFMT; if (mode_a == mode_b) @@ -730,56 +732,14 @@ * @return GtkTreeIter of appendded row. */ static GtkTreeIter cxp_right_pane_append_file (CxpRightPane * self, - GtkListStore * store, + CxpFileListStore * store, const gchar * fullpath) { CxpRightPanePrivate *priv = CXP_RIGHT_PANE_GET_PRIVATE (self); GtkTreeIter iter; struct stat status; - gchar *dispname; - gchar *filetype; - gchar *mimetype; - if ((dispname = cxp_path_get_basename_of_utf8 (fullpath)) == NULL) - { - dispname = g_strdup (_("(Invalid filename)")); - } - lstat (fullpath, &status); - switch (status.st_mode & S_IFMT) - { - case S_IFSOCK: - filetype = g_strdup (_("socket")); - break; - case S_IFLNK: - filetype = g_strdup (_("symbolic link")); - break; - case S_IFREG: - mimetype = cxp_get_mime_type_for_file (fullpath); - filetype = cxp_get_mime_comment (mimetype); - g_free (mimetype); - break; - case S_IFBLK: - filetype = g_strdup (_("block device")); - break; - case S_IFDIR: - filetype = g_strdup (_("directory")); - break; - case S_IFCHR: - filetype = g_strdup (_("character device")); - break; - case S_IFIFO: - filetype = g_strdup (_("fifo")); - break; - default: - filetype = g_strdup (_("unknown")); - } - gtk_list_store_prepend (store, &iter); - gtk_list_store_set (store, &iter, COL_DISP_NAME, dispname, - COL_FILE_PATH, fullpath, COL_FILE_SIZE, - status.st_size, COL_FILE_TYPE, filetype, - COL_FILE_MODE, status.st_mode, COL_UPDATE_TIME, - status.st_mtime, COL_TERMINATOR); - g_free (dispname); + cxp_file_list_store_append_file (store, fullpath, &iter); return iter; } @@ -994,7 +954,7 @@ model = gtk_tree_view_get_model (file_list); g_object_ref (model); gtk_tree_view_set_model (file_list, NULL); - gtk_list_store_clear (GTK_LIST_STORE (model)); + cxp_file_list_store_clear (CXP_FILE_LIST_STORE (model)); dir = g_dir_open (dirname, 0, NULL); if (dir) { @@ -1006,7 +966,7 @@ } fullpath = g_build_filename (dirname, filename, NULL); cxp_right_pane_append_file (self, - GTK_LIST_STORE (model), + CXP_FILE_LIST_STORE (model), fullpath); g_free (fullpath); } @@ -1037,8 +997,8 @@ model = gtk_tree_view_get_model (treeview); if (gtk_tree_model_get_iter (model, &iter, treepath)) { - gtk_tree_model_get (model, &iter, COL_FILE_PATH, - &fullpath, COL_TERMINATOR); + gtk_tree_model_get (model, &iter, FILE_LIST_COL_FULLPATH, + &fullpath, -1); return fullpath; } @@ -1074,7 +1034,7 @@ model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->file_list)); iter = cxp_right_pane_append_file (right_pane, - GTK_LIST_STORE + CXP_FILE_LIST_STORE (model), fullpath); treepath = gtk_tree_model_get_path (model, &iter); gtk_tree_view_set_cursor (GTK_TREE_VIEW @@ -1127,10 +1087,10 @@ { if (gtk_tree_model_get_iter(model, &iter, path)) { - gtk_tree_model_get (model, &iter, COL_FILE_PATH, &fullpath, COL_TERMINATOR); + gtk_tree_model_get (model, &iter, FILE_LIST_COL_FULLPATH, &fullpath, -1); if (cxp_remove_file (fullpath) == TRUE) { - gtk_list_store_remove (GTK_LIST_STORE(model), &iter); + cxp_file_list_store_remove (CXP_FILE_LIST_STORE(model), &iter); } g_free (fullpath); } @@ -1205,12 +1165,11 @@ &treepath, NULL); column = gtk_tree_view_get_column (GTK_TREE_VIEW (priv->file_list), - COL_DISP_NAME); + 0); /* FIXME: */ model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->file_list)); gtk_tree_model_get_iter (model, &iter, treepath); - gtk_list_store_set (GTK_LIST_STORE (model), &iter, COL_EDITABLE, - TRUE, -1); + cxp_file_list_store_set_editable (CXP_FILE_LIST_STORE(model), &iter, TRUE); gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->file_list), treepath, column, TRUE); gtk_tree_path_free (treepath); @@ -1243,8 +1202,8 @@ while (cur != NULL) { gtk_tree_model_get_iter (model, &iter, cur->data); - gtk_tree_model_get (model, &iter, COL_FILE_PATH, &fullpath, - COL_TERMINATOR); + gtk_tree_model_get (model, &iter, FILE_LIST_COL_FULLPATH, &fullpath, + -1); g_string_append_printf (fullcmd, " '%s'", fullpath); g_free (fullpath); cur = g_list_next (cur);