⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ptk-dir-tree.c

📁 台湾人开发的Linux下的文件管理器
💻 C
📖 第 1 页 / 共 2 页
字号:
/**  C Implementation: ptk-dir-tree** Description: *** Author: Hong Jen Yee (PCMan) <pcman.tw (AT) gmail.com>, (C) 2006** Copyright: See COPYING file that comes with this distribution**/#include "ptk-dir-tree.h"#include <gdk/gdk.h>#include <glib/gi18n.h>#include <string.h>#include "vfs-file-info.h"#include "vfs-file-monitor.h"#include "glib-mem.h"struct _PtkDirTreeNode{    VFSFileInfo* file;    PtkDirTreeNode* children;    int n_children;    VFSFileMonitor* monitor;    int n_expand;    PtkDirTreeNode* parent;    PtkDirTreeNode* next;    PtkDirTreeNode* prev;    PtkDirTreeNode* last;    PtkDirTree* tree;   /* FIXME: This is a waste of memory :-( */};static void ptk_dir_tree_init ( PtkDirTree *tree );static void ptk_dir_tree_class_init ( PtkDirTreeClass *klass );static void ptk_dir_tree_tree_model_init ( GtkTreeModelIface *iface );static void ptk_dir_tree_drag_source_init ( GtkTreeDragSourceIface *iface );static void ptk_dir_tree_drag_dest_init ( GtkTreeDragDestIface *iface );static void ptk_dir_tree_finalize ( GObject *object );static GtkTreeModelFlags ptk_dir_tree_get_flags ( GtkTreeModel *tree_model );static gint ptk_dir_tree_get_n_columns ( GtkTreeModel *tree_model );static GType ptk_dir_tree_get_column_type ( GtkTreeModel *tree_model,                                            gint index );static gboolean ptk_dir_tree_get_iter ( GtkTreeModel *tree_model,                                        GtkTreeIter *iter,                                        GtkTreePath *path );static GtkTreePath *ptk_dir_tree_get_path ( GtkTreeModel *tree_model,                                            GtkTreeIter *iter );static void ptk_dir_tree_get_value ( GtkTreeModel *tree_model,                                     GtkTreeIter *iter,                                     gint column,                                     GValue *value );static gboolean ptk_dir_tree_iter_next ( GtkTreeModel *tree_model,                                         GtkTreeIter *iter );static gboolean ptk_dir_tree_iter_children ( GtkTreeModel *tree_model,                                             GtkTreeIter *iter,                                             GtkTreeIter *parent );static gboolean ptk_dir_tree_iter_has_child ( GtkTreeModel *tree_model,                                              GtkTreeIter *iter );static gint ptk_dir_tree_iter_n_children ( GtkTreeModel *tree_model,                                           GtkTreeIter *iter );static gboolean ptk_dir_tree_iter_nth_child ( GtkTreeModel *tree_model,                                              GtkTreeIter *iter,                                              GtkTreeIter *parent,                                              gint n );static gboolean ptk_dir_tree_iter_parent ( GtkTreeModel *tree_model,                                           GtkTreeIter *iter,                                           GtkTreeIter *child );static gint ptk_dir_tree_node_compare( PtkDirTree* tree,                                       PtkDirTreeNode* a,                                       PtkDirTreeNode* b );static void ptk_dir_tree_insert_child( PtkDirTree* tree,                                       PtkDirTreeNode* parent,                                       const char* file_path,                                       const char* name );static void ptk_dir_tree_delete_child( PtkDirTree* tree,                                       PtkDirTreeNode* child );/* signal handlers */static void on_file_monitor_event ( VFSFileMonitor* fm,                                    VFSFileMonitorEvent event,                                    const char* file_name,                                    gpointer user_data );static PtkDirTreeNode* ptk_dir_tree_node_new( PtkDirTree* tree,                                              PtkDirTreeNode* parent,                                              const char* path,                                              const char* base_name );static void ptk_dir_tree_node_free( PtkDirTreeNode* node );static GObjectClass* parent_class = NULL;static GType column_types[ N_DIR_TREE_COLS ];GType ptk_dir_tree_get_type ( void ){    static GType type = 0;    if ( G_UNLIKELY( !type ) )    {        static const GTypeInfo type_info =            {                sizeof ( PtkDirTreeClass ),                NULL,                                           /* base_init */                NULL,                                           /* base_finalize */                ( GClassInitFunc ) ptk_dir_tree_class_init,                NULL,                                           /* class finalize */                NULL,                                           /* class_data */                sizeof ( PtkDirTree ),                0,                                             /* n_preallocs */                ( GInstanceInitFunc ) ptk_dir_tree_init            };        static const GInterfaceInfo tree_model_info =            {                ( GInterfaceInitFunc ) ptk_dir_tree_tree_model_init,                NULL,                NULL            };        static const GInterfaceInfo drag_src_info =            {                ( GInterfaceInitFunc ) ptk_dir_tree_drag_source_init,                NULL,                NULL            };        static const GInterfaceInfo drag_dest_info =            {                ( GInterfaceInitFunc ) ptk_dir_tree_drag_dest_init,                NULL,                NULL            };        type = g_type_register_static ( G_TYPE_OBJECT, "PtkDirTree",                                        &type_info, ( GTypeFlags ) 0 );        g_type_add_interface_static ( type, GTK_TYPE_TREE_MODEL, &tree_model_info );        g_type_add_interface_static ( type, GTK_TYPE_TREE_DRAG_SOURCE, &drag_src_info );        g_type_add_interface_static ( type, GTK_TYPE_TREE_DRAG_DEST, &drag_dest_info );    }    return type;}void ptk_dir_tree_init ( PtkDirTree *tree ){    PtkDirTreeNode* child;    tree->root = g_slice_new0( PtkDirTreeNode );    tree->root->tree = tree;    tree->root->n_children = 1;    child = ptk_dir_tree_node_new( tree, tree->root, "/", "/" );    vfs_file_info_set_disp_name( child->file, _("File System") );    tree->root->children = child;    /*    child = ptk_dir_tree_node_new( tree, tree->root, g_get_home_dir(), NULL );    vfs_file_info_set_name( child->file, g_get_home_dir() );    tree->root->children->next = child;    */    /* Random int to check whether an iter belongs to our model */    tree->stamp = g_random_int();}void ptk_dir_tree_class_init ( PtkDirTreeClass *klass ){    GObjectClass * object_class;    parent_class = ( GObjectClass* ) g_type_class_peek_parent ( klass );    object_class = ( GObjectClass* ) klass;    object_class->finalize = ptk_dir_tree_finalize;}void ptk_dir_tree_tree_model_init ( GtkTreeModelIface *iface ){    iface->get_flags = ptk_dir_tree_get_flags;    iface->get_n_columns = ptk_dir_tree_get_n_columns;    iface->get_column_type = ptk_dir_tree_get_column_type;    iface->get_iter = ptk_dir_tree_get_iter;    iface->get_path = ptk_dir_tree_get_path;    iface->get_value = ptk_dir_tree_get_value;    iface->iter_next = ptk_dir_tree_iter_next;    iface->iter_children = ptk_dir_tree_iter_children;    iface->iter_has_child = ptk_dir_tree_iter_has_child;    iface->iter_n_children = ptk_dir_tree_iter_n_children;    iface->iter_nth_child = ptk_dir_tree_iter_nth_child;    iface->iter_parent = ptk_dir_tree_iter_parent;    column_types [ COL_DIR_TREE_ICON ] = GDK_TYPE_PIXBUF;    column_types [ COL_DIR_TREE_DISP_NAME ] = G_TYPE_STRING;    column_types [ COL_DIR_TREE_INFO ] = G_TYPE_POINTER;}void ptk_dir_tree_drag_source_init ( GtkTreeDragSourceIface *iface ){    /* FIXME: Unused. Will this cause any problem? */}void ptk_dir_tree_drag_dest_init ( GtkTreeDragDestIface *iface ){    /* FIXME: Unused. Will this cause any problem? */}void ptk_dir_tree_finalize ( GObject *object ){    PtkDirTree *tree = ( PtkDirTree* ) object;    if( tree->root )        ptk_dir_tree_node_free( tree->root );    /* must chain up - finalize parent */    ( * parent_class->finalize ) ( object );}PtkDirTree *ptk_dir_tree_new (){    PtkDirTree * tree;    tree = ( PtkDirTree* ) g_object_new ( PTK_TYPE_DIR_TREE, NULL );    return tree;}GtkTreeModelFlags ptk_dir_tree_get_flags ( GtkTreeModel *tree_model ){    g_return_val_if_fail ( PTK_IS_DIR_TREE( tree_model ), ( GtkTreeModelFlags ) 0 );    return GTK_TREE_MODEL_ITERS_PERSIST;}gint ptk_dir_tree_get_n_columns ( GtkTreeModel *tree_model ){    return N_DIR_TREE_COLS;}GType ptk_dir_tree_get_column_type ( GtkTreeModel *tree_model,                                     gint index ){    g_return_val_if_fail ( PTK_IS_DIR_TREE( tree_model ), G_TYPE_INVALID );    g_return_val_if_fail ( index < G_N_ELEMENTS( column_types ) && index >= 0, G_TYPE_INVALID );    return column_types[ index ];}static PtkDirTreeNode* get_nth_node( PtkDirTreeNode* parent, int n ){    PtkDirTreeNode* node;    if ( n >= parent->n_children || n < 0 )        return NULL;    node = parent->children;    while( n > 0 && node )    {        node = node->next;        --n;    }    return node;}gboolean ptk_dir_tree_get_iter ( GtkTreeModel *tree_model,                                 GtkTreeIter *iter,                                 GtkTreePath *path ){    PtkDirTree *tree;    gint *indices, i, depth;    PtkDirTreeNode* node;    g_assert(PTK_IS_DIR_TREE(tree_model));    g_assert(path!=NULL);    tree = PTK_DIR_TREE(tree_model);    if( !tree || !tree->root )        return FALSE;    indices = gtk_tree_path_get_indices(path);    depth   = gtk_tree_path_get_depth(path);    node = tree->root;    for( i = 0; i < depth; ++i )    {        node = get_nth_node( node, indices[i] );        if( !node )            return FALSE;    }    /* We simply store a pointer in the iter */    iter->stamp = tree->stamp;    iter->user_data  = node;    iter->user_data2 = NULL;    iter->user_data3 = NULL;   /* unused */    return TRUE;}static int get_node_index( PtkDirTreeNode* parent, PtkDirTreeNode* child ){    PtkDirTreeNode* node;    int i;    if( !parent || !child )        return -1;    for( i = 0, node = parent->children; node; node = node->next )    {        if( node == child )        {            return i;        }        ++i;    }    return -1;}GtkTreePath *ptk_dir_tree_get_path ( GtkTreeModel *tree_model,                                     GtkTreeIter *iter ){    PtkDirTreeNode* node;    GtkTreePath* path;    int i;    PtkDirTree* tree = PTK_DIR_TREE(tree_model);    g_return_val_if_fail (tree, NULL);    g_return_val_if_fail (iter->stamp == tree->stamp, NULL);    g_return_val_if_fail (iter != NULL, NULL);    g_return_val_if_fail (iter->user_data != NULL, NULL);    path = gtk_tree_path_new();    node = (PtkDirTreeNode*)iter->user_data;    g_return_val_if_fail( node->parent != NULL, (GtkTreePath *)(-1) );    while( node != tree->root )    {        i = get_node_index( node->parent, node );        if( i == -1 )        {            gtk_tree_path_free( path );            return NULL;        }        gtk_tree_path_prepend_index( path, i );        node = node->parent;    }    return path;}void ptk_dir_tree_get_value ( GtkTreeModel *tree_model,                              GtkTreeIter *iter,                              gint column,                              GValue *value ){    PtkDirTree* tree = PTK_DIR_TREE(tree_model);    VFSFileInfo* info;    GdkPixbuf* icon;    PtkDirTreeNode* node;    g_return_if_fail (PTK_IS_DIR_TREE (tree_model));    g_return_if_fail (iter != NULL);    g_return_if_fail (column < G_N_ELEMENTS(column_types) );    g_value_init (value, column_types[column] );    node = (PtkDirTreeNode*) iter->user_data;    g_return_if_fail ( node != NULL );    info = node->file;    switch(column)    {    case COL_DIR_TREE_ICON:        if( G_UNLIKELY( !info ) )            return;        icon = vfs_file_info_get_small_icon( info );        if( icon )        {            g_value_set_object( value, icon );            gdk_pixbuf_unref( icon );        }        break;    case COL_DIR_TREE_DISP_NAME:        if( G_LIKELY( info ) )            g_value_set_string( value, vfs_file_info_get_disp_name(info) );        else            g_value_set_string( value, _("No Sub Folder") );        break;    case COL_DIR_TREE_INFO:        if( G_UNLIKELY( !info ) )            return;        vfs_file_info_ref( info );        g_value_set_pointer( value, info );        break;    }}gboolean ptk_dir_tree_iter_next ( GtkTreeModel *tree_model,                                  GtkTreeIter *iter ){    PtkDirTreeNode* node;    PtkDirTree* tree;    g_return_val_if_fail (PTK_IS_DIR_TREE (tree_model), FALSE);    if (iter == NULL || iter->user_data == NULL)        return FALSE;    tree = PTK_DIR_TREE(tree_model);    node = (PtkDirTreeNode *) iter->user_data;    /* Is this the last child in the parent node? */    if ( ! node->next )        return FALSE;    iter->stamp = tree->stamp;    iter->user_data = node->next;    iter->user_data2 = NULL;    iter->user_data3 = NULL;    return TRUE;}gboolean ptk_dir_tree_iter_children ( GtkTreeModel *tree_model,                                      GtkTreeIter *iter,                                      GtkTreeIter *parent ){    PtkDirTree* tree;    PtkDirTreeNode* parent_node;    PtkDirTreeNode* node;    g_return_val_if_fail ( parent == NULL || parent->user_data != NULL, FALSE );    g_return_val_if_fail ( PTK_IS_DIR_TREE ( tree_model ), FALSE );    tree = PTK_DIR_TREE( tree_model );    if ( parent )        parent_node = (PtkDirTreeNode*)parent->user_data;    else    {        /* parent == NULL is a special case; we need to return the first top-level row */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -