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

📄 ptk-dir-tree.c

📁 台湾人开发的Linux下的文件管理器
💻 C
📖 第 1 页 / 共 2 页
字号:
        parent_node = tree->root;    }    /* No rows => no first row */    if ( parent_node->n_children == 0 )        return FALSE;    /* Set iter to first item in tree */    iter->stamp = tree->stamp;    iter->user_data = parent_node->children;    iter->user_data2 = iter->user_data3 = NULL;    return TRUE;}gboolean ptk_dir_tree_iter_has_child ( GtkTreeModel *tree_model,                                       GtkTreeIter *iter ){    PtkDirTreeNode* node;    g_return_val_if_fail( iter != NULL, FALSE );    node = (PtkDirTreeNode*)iter->user_data;    return node->n_children != 0;}gint ptk_dir_tree_iter_n_children ( GtkTreeModel *tree_model,                                    GtkTreeIter *iter ){    PtkDirTreeNode* node;    PtkDirTree* tree;    g_return_val_if_fail ( PTK_IS_DIR_TREE ( tree_model ), -1 );    tree = PTK_DIR_TREE( tree_model );    /* special case: if iter == NULL, return number of top-level rows */    if ( !iter )        node = tree->root;    else        node = (PtkDirTreeNode*)iter->user_data;    g_return_val_if_fail ( node != NULL, -1 );    return node->n_children;}gboolean ptk_dir_tree_iter_nth_child ( GtkTreeModel *tree_model,                                       GtkTreeIter *iter,                                       GtkTreeIter *parent,                                       gint n ){    PtkDirTreeNode* parent_node;    PtkDirTreeNode* node;    PtkDirTree* tree;    g_return_val_if_fail (PTK_IS_DIR_TREE (tree_model), FALSE);    tree = PTK_DIR_TREE(tree_model);    if( G_LIKELY(parent) )    {        parent_node = ( PtkDirTreeNode* )parent->user_data;        g_return_val_if_fail( parent_node, FALSE );    }    else    {        /* special case: if parent == NULL, set iter to n-th top-level row */        parent_node = tree->root;    }    if( n >= parent_node->n_children || n < 0 )        return FALSE;    node = get_nth_node( parent_node, n );    iter->stamp = tree->stamp;    iter->user_data = node;    iter->user_data2 = iter->user_data3 = NULL;    return TRUE;}gboolean ptk_dir_tree_iter_parent ( GtkTreeModel *tree_model,                                    GtkTreeIter *iter,                                    GtkTreeIter *child ){    PtkDirTreeNode* node;    PtkDirTree* tree;    g_return_val_if_fail( iter != NULL && child != NULL, FALSE );    tree = PTK_DIR_TREE( tree_model );    node = (PtkDirTreeNode*)child->user_data;    if( G_LIKELY( node->parent != tree->root ) )    {        iter->user_data = node->parent;        iter->user_data2 = iter->user_data3 = NULL;        return TRUE;    }    return FALSE;}gint ptk_dir_tree_node_compare( PtkDirTree* tree,                                PtkDirTreeNode* a,                                PtkDirTreeNode* b ){    VFSFileInfo* file1 = a->file;    VFSFileInfo* file2 = b->file;    int ret;    if( ! file1 || !file2 )        return 0;    /* FIXME: UTF-8 strings should not be treated as ASCII when sorted  */    ret = g_ascii_strcasecmp( vfs_file_info_get_disp_name(file2),                              vfs_file_info_get_disp_name(file1) );    return ret;}PtkDirTreeNode* ptk_dir_tree_node_new( PtkDirTree* tree,                                       PtkDirTreeNode* parent,                                       const char* path,                                       const char* base_name ){    PtkDirTreeNode* node;    node = g_slice_new0( PtkDirTreeNode );    node->tree = tree;    node->parent = parent;    if( path )    {        node->file = vfs_file_info_new();        vfs_file_info_get( node->file, path, base_name );        node->n_children = 1;        node->children = ptk_dir_tree_node_new( tree, node, NULL, NULL );        node->last = node->children;    }    return node;}void ptk_dir_tree_node_free( PtkDirTreeNode* node ){    PtkDirTreeNode* child;    if( node->file )        vfs_file_info_unref( node->file );    for( child = node->children; child; child = child->next )        ptk_dir_tree_node_free( child );    if( node->monitor )    {        vfs_file_monitor_remove( node->monitor,                                 &on_file_monitor_event,                                 node );    }    g_slice_free( PtkDirTreeNode, node );}static char* dir_path_from_tree_node( PtkDirTree* tree, PtkDirTreeNode* node ){    GSList* names = NULL, *l;    const char* name;    int len;    char* dir_path, *p;    if( !node )        return NULL;    while( node != tree->root )    {        if( !node->file || ! (name = vfs_file_info_get_name( node->file )) )        {            g_slist_free( names );            return NULL;        }        names = g_slist_prepend( names, name );        node = node->parent;    }    for( len = 1, l = names; l; l = l->next )        len += strlen((char*)l->data) + 1;    dir_path = g_malloc( len );    for( p = dir_path, l = names; l; l = l->next )    {        name = (char*)l->data;        len = strlen( name );        memcpy( p, name, len * sizeof(char) );        p += len;        if( l->next && strcmp( name, "/" ) )        {            *p = '/';            ++p;        }    }    *p = '\0';    g_slist_free( names );    return dir_path;}void ptk_dir_tree_insert_child( PtkDirTree* tree,                                PtkDirTreeNode* parent,                                const char* file_path,                                const char* name ){    PtkDirTreeNode *child_node;    PtkDirTreeNode *node;    GtkTreeIter it;    GtkTreePath* tree_path;    child_node = ptk_dir_tree_node_new( tree, parent, file_path, name );    for( node = parent->children; node; node = node->next )    {        if( ptk_dir_tree_node_compare( tree, child_node, node ) >= 0 )            break;    }    if( node )    {        if( node->prev )        {            child_node->prev = node->prev;            node->prev->next = child_node;        }        child_node->next = node;        if( node == parent->children )            parent->children = child_node;        node->prev = child_node;    }    else    {        if( parent->children )        {            child_node->prev = parent->last;            parent->last->next = child_node;            parent->last = child_node;        }        else        {            parent->children = parent->last = child_node;        }    }    ++parent->n_children;    it.stamp = tree->stamp;    it.user_data = child_node;    it.user_data2 = it.user_data3 = NULL;    tree_path = ptk_dir_tree_get_path( GTK_TREE_MODEL(tree), &it );    gtk_tree_model_row_inserted( GTK_TREE_MODEL(tree), tree_path, &it );    gtk_tree_model_row_has_child_toggled( GTK_TREE_MODEL(tree), tree_path, &it );    gtk_tree_path_free( tree_path );}void ptk_dir_tree_delete_child( PtkDirTree* tree,                                PtkDirTreeNode* child ){    GtkTreeIter child_it;    GtkTreePath* tree_path;    PtkDirTreeNode* parent;    if( !child )        return;    child_it.stamp = tree->stamp;    child_it.user_data = child;    child_it.user_data2 = child_it.user_data3 = NULL;    tree_path = ptk_dir_tree_get_path( GTK_TREE_MODEL(tree), &child_it );    gtk_tree_model_row_deleted( GTK_TREE_MODEL(tree), tree_path );    gtk_tree_path_free( tree_path );    parent = child->parent;    --parent->n_children;    if( child == parent->children )        parent->children = parent->last = child->next;    else if( child == parent->last )        parent->last = child->prev;    if( child->prev )        child->prev->next = child->next;    if( child->next )        child->next->prev = child->prev;    ptk_dir_tree_node_free( child );    if( parent->n_children == 0 )    {        /* add place holder */        ptk_dir_tree_insert_child( tree, parent, NULL,NULL );    }}void ptk_dir_tree_expand_row ( PtkDirTree* tree,                               GtkTreeIter* iter,                               GtkTreePath *tree_path ){    PtkDirTreeNode *node, *place_holder;    GtkTreeIter child;    GDir *dir;    char *path, *file_path;    const char *name=NULL;    node = (PtkDirTreeNode*)iter->user_data;    ++node->n_expand;    if( node->n_expand > 1 || node->n_children > 1 )        return;    place_holder = node->children;    path = dir_path_from_tree_node( tree, node );    dir = g_dir_open( path, 0, NULL );    if( dir )    {        node->monitor = vfs_file_monitor_add( path,                                              &on_file_monitor_event,                                              node );        while( (name = g_dir_read_name( dir )) )        {            file_path = g_build_filename( path, name, NULL );            if( g_file_test( file_path, G_FILE_TEST_IS_DIR ) )            {                ptk_dir_tree_insert_child( tree, node, file_path, name );            }            g_free( file_path );        }        g_dir_close( dir );        if( node->n_children > 1 )        {            ptk_dir_tree_delete_child( tree, place_holder );        }    }    g_free( path );}void ptk_dir_tree_collapse_row ( PtkDirTree* tree,                                 GtkTreeIter* iter,                                 GtkTreePath *path ){    PtkDirTreeNode *node, *child, *next;    node = (PtkDirTreeNode*)iter->user_data;    --node->n_expand;    /* cache nodes containing more than 128 children */    /* FIXME: Is this useful? The nodes containing childrens              with 128+ children are still not cached. */    if( node->n_children > 128 || node->n_expand > 0 )        return;    if( node->n_children > 0 )    {        /* place holder */        if( node->n_children == 1 && ! node->children->file )            return;        if( G_LIKELY( node->monitor ) )        {            vfs_file_monitor_remove( node->monitor,                                     &on_file_monitor_event,                                     node );            node->monitor = NULL;        }        for( child = node->children; child; child = next )        {            next = child->next;            ptk_dir_tree_delete_child( tree, child );        }    }}char* ptk_dir_tree_get_dir_path( PtkDirTree* tree, GtkTreeIter* iter ){    g_return_val_if_fail( iter->user_data != NULL, NULL );    return dir_path_from_tree_node( tree, (PtkDirTreeNode*)iter->user_data );}static PtkDirTreeNode* find_node( PtkDirTreeNode* parent, const char* name ){    PtkDirTreeNode* child;    for( child = parent->children; child; child = child->next )    {        if( G_LIKELY(child->file )                && 0 == strcmp( vfs_file_info_get_name(child->file), name ) )        {            return child;        }    }    return NULL;}void on_file_monitor_event ( VFSFileMonitor* fm,                             VFSFileMonitorEvent event,                             const char* file_name,                             gpointer user_data ){    PtkDirTreeNode* node = (PtkDirTreeNode*)user_data;    PtkDirTreeNode* child;    GtkTreeIter it;    GtkTreePath* tree_path;    char* file_path;    g_return_if_fail( node );    GDK_THREADS_ENTER();    child = find_node( node, file_name );    switch( event )    {    case VFS_FILE_MONITOR_CREATE:        if( G_LIKELY( !child ) )        {            /* remove place holder */            if( node->n_children == 1 && !node->children->file )                child = node->children;            else                child = NULL;            file_path = g_build_filename( fm->path, file_name, NULL );            if( g_file_test( file_path, G_FILE_TEST_IS_DIR ) )            {                ptk_dir_tree_insert_child( node->tree,                                        node, fm->path,                                        file_name );                if( child )                    ptk_dir_tree_delete_child( node->tree, child );            }            g_free( file_path );        }        break;    case VFS_FILE_MONITOR_DELETE:        if( G_LIKELY( child ) )        {            ptk_dir_tree_delete_child( node->tree, child );        }        break;    case VFS_FILE_MONITOR_CHANGE:        if( G_LIKELY( child && child->file ) )        {            file_path = g_build_filename( fm->path, file_name, NULL );            if( ! g_file_test( file_path, G_FILE_TEST_IS_DIR ) )            {                g_free( file_path );                break;            }            vfs_file_info_get( child->file, file_path, file_name );            g_free( file_path );            it.stamp = node->tree->stamp;            it.user_data = child;            it.user_data2 = it.user_data3 = NULL;            tree_path = ptk_dir_tree_get_path(GTK_TREE_MODEL(node->tree), &it);            gtk_tree_model_row_changed( GTK_TREE_MODEL( node->tree ),                                        tree_path, &it );            gtk_tree_model_row_has_child_toggled( GTK_TREE_MODEL( node->tree ),                                                  tree_path, &it );            gtk_tree_path_free( tree_path );        }        break;    }    GDK_THREADS_LEAVE();}

⌨️ 快捷键说明

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