Yasumichi Akahoshi
yasum****@users*****
2005年 1月 4日 (火) 23:45:32 JST
Index: cxplorer/src/Makefile.am diff -u cxplorer/src/Makefile.am:1.7 cxplorer/src/Makefile.am:1.8 --- cxplorer/src/Makefile.am:1.7 Mon Dec 6 22:58:20 2004 +++ cxplorer/src/Makefile.am Tue Jan 4 23:45:32 2005 @@ -38,7 +38,9 @@ property.c\ property.h\ cxp-profile.h\ - cxp-profile.c + cxp-profile.c\ + cxp-dir-view.h\ + cxp-dir-view.c cxplorer_LDFLAGS = Index: cxplorer/src/Makefile.in diff -u cxplorer/src/Makefile.in:1.8 cxplorer/src/Makefile.in:1.9 --- cxplorer/src/Makefile.in:1.8 Sat Dec 18 01:00:00 2004 +++ cxplorer/src/Makefile.in Tue Jan 4 23:45:32 2005 @@ -119,49 +119,20 @@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ -INCLUDES = \ - $(GTK_CFLAGS) +INCLUDES = $(GTK_CFLAGS) -AM_CFLAGS = \ - -Wall\ - -g +AM_CFLAGS = -Wall -g bin_PROGRAMS = cxplorer -cxplorer_SOURCES = \ - support.h\ - support.c\ - main.c\ - interface.h\ - interface.c\ - dirview.c\ - dirview.h\ - fileview.c\ - fileview.h\ - treecommon.c\ - treecommon.h\ - preview.c\ - preview.h\ - menubar.c\ - menubar.h\ - toolbar.h\ - toolbar.c\ - actcalls.c\ - actcalls.h\ - cxplorer.h\ - cxplorer.c\ - property.c\ - property.h\ - cxp-profile.h\ - cxp-profile.c +cxplorer_SOURCES = support.h support.c main.c interface.h interface.c dirview.c dirview.h fileview.c fileview.h treecommon.c treecommon.h preview.c preview.h menubar.c menubar.h toolbar.h toolbar.c actcalls.c actcalls.h cxplorer.h cxplorer.c property.c property.h cxp-profile.h cxp-profile.c cxp-dir-view.h cxp-dir-view.c cxplorer_LDFLAGS = -cxplorer_LDADD = \ - $(GTK_LIBS) +cxplorer_LDADD = $(GTK_LIBS) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = ../config.h @@ -178,7 +149,7 @@ dirview.$(OBJEXT) fileview.$(OBJEXT) treecommon.$(OBJEXT) \ preview.$(OBJEXT) menubar.$(OBJEXT) toolbar.$(OBJEXT) \ actcalls.$(OBJEXT) cxplorer.$(OBJEXT) property.$(OBJEXT) \ -cxp-profile.$(OBJEXT) +cxp-profile.$(OBJEXT) cxp-dir-view.$(OBJEXT) cxplorer_DEPENDENCIES = COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) @@ -189,12 +160,12 @@ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) -TAR = gtar +TAR = tar GZIP_ENV = --best -DEP_FILES = .deps/actcalls.P .deps/cxp-profile.P .deps/cxplorer.P \ -.deps/dirview.P .deps/fileview.P .deps/interface.P .deps/main.P \ -.deps/menubar.P .deps/preview.P .deps/property.P .deps/support.P \ -.deps/toolbar.P .deps/treecommon.P +DEP_FILES = .deps/actcalls.P .deps/cxp-dir-view.P .deps/cxp-profile.P \ +.deps/cxplorer.P .deps/dirview.P .deps/fileview.P .deps/interface.P \ +.deps/main.P .deps/menubar.P .deps/preview.P .deps/property.P \ +.deps/support.P .deps/toolbar.P .deps/treecommon.P SOURCES = $(cxplorer_SOURCES) OBJECTS = $(cxplorer_OBJECTS) Index: cxplorer/src/cxp-dir-view.c diff -u /dev/null cxplorer/src/cxp-dir-view.c:1.1 --- /dev/null Tue Jan 4 23:45:32 2005 +++ cxplorer/src/cxp-dir-view.c Tue Jan 4 23:45:32 2005 @@ -0,0 +1,548 @@ +#include "cxp-dir-view.h" + +/* + * define column number of directory view. + */ +enum +{ + COL_TERMINATOR = -1, /**< terminator */ + COL_FULL_PATH, /**< full path of directory */ + COL_IS_DUMMY, /**< Is node dummy? */ + NUM_COLS /**< Count of columns */ +}; + +struct _CxpDirViewPrivate +{ + GtkWidget *dirview; + GtkWidget *scrolledWin; + GdkPixbuf *icon; + gboolean showDotFile; + gboolean dispose_has_run; +}; + +static void cxp_dir_view_init (GTypeInstance * instance, gpointer g_class); +static void cxp_dir_view_class_init (CxpDirViewClass * klass); +static void cxp_dir_view_dispose (GObject * obj); +static void cxp_dir_view_finalize (GObject * object); +static GtkWidget *cxp_dir_view_tree_view_new (CxpDirView *self); +static GtkTreeModel *cxp_dir_view_model_new (void); +static gint cxp_dir_view_compare_node (GtkTreeModel * model, + GtkTreeIter * iterA, + GtkTreeIter * iterB, gpointer data); +static void cxp_dir_view_prepend_dummy (GtkTreeStore * store, + GtkTreeIter * parent_iter); +static void cxp_dir_view_set_child_dirctory (GtkTreeStore * treestore, GtkTreeIter * parent, + gchar * parentPath, gboolean showDotFile); +static void cxp_dir_view_on_row_expanded (GtkTreeView * treeview, + GtkTreeIter * iter, + GtkTreePath * path, gpointer user_data); +static void cxp_dir_view_draw_icon_cell (GtkTreeViewColumn * tree_column, + GtkCellRenderer * cell, + GtkTreeModel * tree_model, + GtkTreeIter * iter, gpointer data); +static void cxp_dir_view_draw_label_cell (GtkTreeViewColumn * tree_column, + GtkCellRenderer * cell, + GtkTreeModel * tree_model, + GtkTreeIter * iter, gpointer data); +static GtkTreeIter *cxp_dir_view_search_child_node (GtkTreeModel * model, GtkTreeIter * parent, gchar *label); + +/** + * cxp_dir_view_get_type + * + * Register CxpDirViewType. + **/ +GType cxp_dir_view_get_type (void) +{ + static GType type = 0; + + if (type == 0) + { + /* オブジェクトの型に関する情報を定義します。 */ + static const GTypeInfo info = { + sizeof (CxpDirViewClass), + NULL, /* base_init (クラスの初期化処理を行う関数) は無し */ + NULL, /* base_finalize (クラスの終了処理を行う関数) は無し */ + (GClassInitFunc) cxp_dir_view_class_init, + NULL, /* class_finalize (クラスの終了処理を行う関数) は無し */ + NULL, /* class_data (クラスのデータ) は無し */ + sizeof (CxpDirView), + 0, /* n_preallocs (インスタンスを生成する際のポリシー) は無し */ + (GInstanceInitFunc) cxp_dir_view_init + }; + type = g_type_register_static (G_TYPE_OBJECT, + "CxpDirViewType", &info, 0); + } + return type; +} + +/** + * cxp_dir_view_init + * @instance: + * @g_class: + * + * Initialize instance of CxpDirView. + **/ +static void cxp_dir_view_init (GTypeInstance * instance, gpointer g_class) +{ + CxpDirView *self = (CxpDirView *) instance; + + self->priv = g_new (CxpDirViewPrivate, 1); + self->priv->dirview = cxp_dir_view_tree_view_new (self); + /* signal connect */ + g_signal_connect (self->priv->dirview, "row_expanded", + G_CALLBACK (cxp_dir_view_on_row_expanded), + self); + /* + g_signal_connect (object->priv->dirview, "cursor_changed", + G_CALLBACK (cxp_dir_view_on_cursor_changed), + object); + */ + + + self->priv->scrolledWin = gtk_scrolled_window_new (NULL, NULL); + gtk_container_add (GTK_CONTAINER (self->priv->scrolledWin), + self->priv->dirview); + gtk_widget_show (self->priv->scrolledWin); + self->priv->icon = NULL; + self->priv->dispose_has_run = FALSE; +} + +/** + * cxp_dir_view_class_init + * @klass: + * + * Initialize CxpDirViewClass. + **/ +static void cxp_dir_view_class_init (CxpDirViewClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + klass->cd_signal_id = + g_signal_newv ("change_directory", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, + NULL /* class closure */, + NULL /* accumulator */, + NULL /* accu_data */, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE /* return_type */, + 0 /* n_params */, + NULL /* param_types */); + + /* メソッド dispose()/finalize() をオーバーライドします。 */ + gobject_class->dispose = cxp_dir_view_dispose; + gobject_class->finalize = cxp_dir_view_finalize; +} + +/** + * cxp_dir_view_dispose + * @obj: + * + * Dispose instance of CxpDirView. + **/ +static void cxp_dir_view_dispose (GObject * obj) +{ + CxpDirView *self = (CxpDirView *) obj; + + if (self->priv->dispose_has_run) + { + /* When dispose has run, return. */ + return; + } + /* メソッド dispose() が二度実行されることがないようチェックします。 */ + self->priv->dispose_has_run = TRUE; +} + +/** + * cxp_dir_view_finalize + * @object: + * + * Finalize instance of CxpDirView. + **/ +static void cxp_dir_view_finalize (GObject * object) +{ + CxpDirView *self = (CxpDirView *) object; + + g_free (self->priv); +} + +static GtkWidget *cxp_dir_view_tree_view_new (CxpDirView *self) +{ + GtkWidget *treeview; + GtkTreeModel *model; + GtkTreeViewColumn *column; + GtkCellRenderer *renderer; + + model = cxp_dir_view_model_new (); + treeview = gtk_tree_view_new_with_model (model); + gtk_widget_show (treeview); + + column = gtk_tree_view_column_new (); + gtk_tree_view_column_set_title (column, "Directory"); + gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column); + + renderer = gtk_cell_renderer_pixbuf_new (); + gtk_tree_view_column_pack_start (column, renderer, FALSE); + gtk_tree_view_column_set_cell_data_func (column, renderer, + cxp_dir_view_draw_icon_cell, + self, NULL); + + renderer = gtk_cell_renderer_text_new (); + gtk_tree_view_column_pack_start (column, renderer, TRUE); + gtk_tree_view_column_set_cell_data_func (column, renderer, + cxp_dir_view_draw_label_cell, + NULL, NULL); + + + return treeview; +} + +/** + * cxp_dir_view_model_new + * + * Creates a new tree store for CxpDirView. + **/ +static GtkTreeModel *cxp_dir_view_model_new (void) +{ + GtkTreeStore *store; + GtkTreeIter root; + GtkTreeSortable *sortable; + + store = gtk_tree_store_new (NUM_COLS, G_TYPE_STRING, G_TYPE_BOOLEAN); + + sortable = GTK_TREE_SORTABLE (store); + gtk_tree_sortable_set_default_sort_func (sortable, + cxp_dir_view_compare_node, + NULL, NULL); + gtk_tree_sortable_set_sort_column_id (sortable, COL_FULL_PATH, + GTK_SORT_ASCENDING); + + gtk_tree_store_append (store, &root, NULL); + gtk_tree_store_set (store, &root, + COL_FULL_PATH, "/", COL_IS_DUMMY, FALSE, -1); + cxp_dir_view_prepend_dummy (store, &root); + + return GTK_TREE_MODEL (store); +} + +/** + * (GtkTreeIterCompareFunc) + * + */ +static gint cxp_dir_view_compare_node (GtkTreeModel * model, + GtkTreeIter * iterA, + GtkTreeIter * iterB, gpointer data) +{ + gint retval = 0; + + gchar *nameA, *nameB; + + gtk_tree_model_get (model, iterA, COL_FULL_PATH, &nameA, + COL_TERMINATOR); + gtk_tree_model_get (model, iterB, COL_FULL_PATH, &nameB, + COL_TERMINATOR); + + if (nameA == NULL || nameB == NULL) + { + if (nameA == NULL && nameB == NULL) + { + retval = 0; + } + else + { + retval = (nameA == NULL) ? -1 : 1; + } + } + else + { + retval = strcmp (nameA, nameB); + } + + g_free (&nameA); + g_free (&nameB); + + return retval; +} + +/** + * + * + **/ +static void cxp_dir_view_prepend_dummy (GtkTreeStore * store, + GtkTreeIter * parent_iter) +{ + GtkTreeIter iter; + gboolean success; + + g_return_if_fail (store); + + gtk_tree_store_prepend (store, &iter, parent_iter); + gtk_tree_store_set (store, &iter, COL_IS_DUMMY, TRUE, -1); + + success = gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (store), + &iter, parent_iter, 1); + if (!success) + return; + + while (gtk_tree_store_is_ancestor (store, parent_iter, &iter)) + { + gtk_tree_store_remove (store, &iter); + } +} + +static void cxp_dir_view_set_child_dirctory (GtkTreeStore * treestore, GtkTreeIter * parent, + gchar * parentPath, gboolean showDotFile) +{ + const gchar *childName; + gchar *fullpath; + GDir *gdir; + GtkTreeIter child; + + /* open directory */ + gdir = g_dir_open (parentPath, 0, NULL); + g_return_if_fail (gdir); + + while ((childName = g_dir_read_name (gdir)) != NULL) + { + /* ToDo: when ShowDotFile is turned off, reconstruct tree. + And Cxplorer is referenced. */ + if ((childName[0] == '.') && (showDotFile == FALSE)) + { + continue; + } + fullpath = g_build_filename (parentPath, childName, NULL); + /* Child node is added if it is directory and not symlink */ + if (!g_file_test (fullpath, G_FILE_TEST_IS_SYMLINK) + && g_file_test (fullpath, G_FILE_TEST_IS_DIR)) + { + gtk_tree_store_append (treestore, &child, parent); + gtk_tree_store_set (treestore, &child, COL_FULL_PATH, + fullpath, COL_IS_DUMMY, FALSE, + COL_TERMINATOR); + cxp_dir_view_prepend_dummy (treestore, &child); + } + g_free (fullpath); + } + + /* Close directory */ + g_dir_close (gdir); +} + +static void cxp_dir_view_draw_icon_cell (GtkTreeViewColumn * tree_column, + GtkCellRenderer * cell, + GtkTreeModel * tree_model, + GtkTreeIter * iter, gpointer data) +{ + CxpDirView *self = CXP_DIR_VIEW (data); + + if (self->priv->icon) + { + g_object_set (cell, "pixbuf", self->priv->icon, NULL); + } + else + { + g_object_set (cell, "pixbuf", NULL, NULL); + } +} + +static void cxp_dir_view_draw_label_cell (GtkTreeViewColumn * tree_column, + GtkCellRenderer * cell, + GtkTreeModel * tree_model, + GtkTreeIter * iter, gpointer data) +{ + gchar *basename_locale; + gchar *basename_utf8; + gchar *fullpath; + + gtk_tree_model_get (tree_model, iter, COL_FULL_PATH, &fullpath, COL_TERMINATOR); + if(fullpath != NULL) + { + basename_locale = g_path_get_basename(fullpath); + basename_utf8 = g_locale_to_utf8(basename_locale, -1, NULL, NULL, NULL); + + g_object_set (cell, "text", basename_utf8, NULL); + + g_free(basename_locale); + g_free(fullpath); + } + else + { + g_object_set (cell, "text", "(NULL)", NULL); + } + +} + +/* + * private signal handler. + */ + +/** + * + * + **/ +static void cxp_dir_view_on_row_expanded (GtkTreeView * treeview, + GtkTreeIter * iter, + GtkTreePath * path, gpointer user_data) +{ + CxpDirView *self; + GtkTreeStore *store; + GtkTreeIter child; + gchar *fullpath; + gboolean isDummy; + + self = CXP_DIR_VIEW(user_data); + store = GTK_TREE_STORE (gtk_tree_view_get_model (treeview)); + gtk_tree_model_iter_children (GTK_TREE_MODEL (store), &child, iter); + gtk_tree_model_get (GTK_TREE_MODEL (store), &child, COL_IS_DUMMY, + &isDummy, COL_TERMINATOR); + + if (isDummy) + { + gtk_tree_model_get (GTK_TREE_MODEL (store), iter, + COL_FULL_PATH, &fullpath, COL_TERMINATOR); + cxp_dir_view_set_child_dirctory(store, iter, fullpath, + self->priv->showDotFile); + gtk_tree_store_remove (store, &child); + + g_free(fullpath); + } + +} + +static GtkTreeIter *cxp_dir_view_search_child_node (GtkTreeModel * model, GtkTreeIter * parent, gchar *label) +{ + gchar *parentpath; + gchar *searchpath; + gchar *currentpath; + GtkTreeIter *current; + + gtk_tree_model_get (model, parent, COL_FULL_PATH, &parentpath, COL_TERMINATOR); + searchpath = g_build_filename (parentpath, label, NULL); + + current = g_new (GtkTreeIter, 1); + if (gtk_tree_model_iter_children (model, current, parent)) + { + do + { + gtk_tree_model_get (model, current, + COL_FULL_PATH, ¤tpath, -1); + if (strcmp (searchpath, currentpath) == 0) + { + g_free (parentpath); + g_free (searchpath); + return current; + } + } + while (gtk_tree_model_iter_next (model, current)); + } + + g_free (parentpath); + g_free (searchpath); + g_free (current); + return NULL; +} + +/* + * public methods. + * + */ + +CxpDirView *cxp_dir_view_new (gboolean showDotFile, GdkPixbuf *icon) +{ + CxpDirView *object; + + object = CXP_DIR_VIEW (g_object_new (CXP_TYPE_DIR_VIEW, NULL)); + object->priv->showDotFile = showDotFile; + object->priv->icon = icon; + + return object; +} + +GtkWidget *cxp_dir_view_get_widget (CxpDirView * instance) +{ + return instance->priv->scrolledWin; +} + +gchar *cxp_dir_view_get_current_directory (CxpDirView *instance) +{ + gchar *fullpath = NULL; + GtkTreePath *path; + GtkTreeViewColumn *column; + GtkTreeIter iter; + GtkTreeModel *model; + + gtk_tree_view_get_cursor (GTK_TREE_VIEW(instance->priv->dirview), &path, &column); + + if (path) + { + model = gtk_tree_view_get_model (GTK_TREE_VIEW(instance->priv->dirview)); + if (gtk_tree_model_get_iter (model, &iter, path)) + { + gtk_tree_model_get (model, &iter, COL_FULL_PATH, &fullpath, -1); + } + + gtk_tree_path_free (path); + } + + return fullpath; +} + +gboolean cxp_dir_view_change_directory (CxpDirView *instance, const gchar *fullpath) +{ + gchar **elements; + gint index; + GtkWidget *treeview; + GtkTreeModel *model; + GtkTreeIter *parent; + GtkTreeIter *current; + GtkTreePath *currentPath; + + if (g_path_is_absolute (fullpath) != TRUE) + { + g_warning ("%s isn't absolute path.\n", fullpath); + return FALSE; + } + + treeview = instance->priv->dirview; + + parent = g_new (GtkTreeIter, 1); + model = gtk_tree_view_get_model (GTK_TREE_VIEW (treeview)); + gtk_tree_model_get_iter_first (model, parent); + currentPath = gtk_tree_model_get_path (model, parent); + gtk_tree_view_expand_to_path (GTK_TREE_VIEW (treeview), currentPath); + gtk_tree_path_free (currentPath); + + elements = g_strsplit (fullpath, "/", 0); + for (index = 0; elements[index] != NULL; index++) + { + if (strlen (elements[index]) == 0) + continue; + if ((current = cxp_dir_view_search_child_node (model, parent, + elements[index])) != NULL) + { + currentPath = + gtk_tree_model_get_path (model, current); + gtk_tree_view_expand_to_path (GTK_TREE_VIEW + (treeview), + currentPath); + gtk_tree_path_free (currentPath); + g_free (parent); + parent = current; + } + else + { + g_warning ("%s is not exists\n", fullpath); + break; + } + } + g_strfreev (elements); + currentPath = gtk_tree_model_get_path (model, parent); + gtk_tree_view_set_cursor (GTK_TREE_VIEW (treeview), + currentPath, NULL, FALSE); + gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (treeview), + currentPath, NULL, FALSE, 0.0, 0.0); + gtk_tree_path_free (currentPath); + g_free (parent); + + return TRUE; +} Index: cxplorer/src/cxp-dir-view.h diff -u /dev/null cxplorer/src/cxp-dir-view.h:1.1 --- /dev/null Tue Jan 4 23:45:32 2005 +++ cxplorer/src/cxp-dir-view.h Tue Jan 4 23:45:32 2005 @@ -0,0 +1,46 @@ +#ifndef CXP_DIR_VIEW_H +#define CXP_DIR_VIEW_H + +#include <glib-object.h> +#include <gtk/gtk.h> +#include <string.h> + +#define CXP_TYPE_DIR_VIEW (cxp_dir_view_get_type ()) +#define CXP_DIR_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CXP_TYPE_DIR_VIEW, CxpDirView)) +#define CXP_DIR_VIEW_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST ((vtable), CXP_TYPE_DIR_VIEW, CxpDirViewClass)) +#define CXP_IS_DIR_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CXP_TYPE_DIR_VIEW)) +#define CXP_IS_DIR_VIEW_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), CXP_TYPE_DIR_VIEW)) +#define CXP_DIR_VIEW_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), CXP_TYPE_DIR_VIEW, CxpDirViewClass)) + +/* + * 型のマクロです。 + */ + +typedef struct _CxpDirView CxpDirView; +typedef struct _CxpDirViewClass CxpDirViewClass; +typedef struct _CxpDirViewPrivate CxpDirViewPrivate; + +struct _CxpDirView +{ + GObject parent; + CxpDirViewPrivate *priv; +}; + +struct _CxpDirViewClass +{ + GObjectClass parent; + guint cd_signal_id; +}; + +/* マクロ CXP_TYPE_DIR_VIEW() が使用します。*/ +GType cxp_dir_view_get_type (void); + +/* + * ここに、メソッドを定義します。 + */ +CxpDirView *cxp_dir_view_new (gboolean showDotFile, GdkPixbuf *icon); +GtkWidget *cxp_dir_view_get_widget (CxpDirView * instance); +gchar *cxp_dir_view_get_current_directory (CxpDirView *instance); +gboolean cxp_dir_view_change_directory (CxpDirView *instance, const gchar *fullpath); + +#endif /* CXP_DIR_VIEW_H */