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

📄 ptk-dir-tree-view.c

📁 台湾人开发的Linux下的文件管理器
💻 C
字号:
/**  C Implementation: ptkdirtreeview** 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-view.h"#include "ptk-file-icon-renderer.h"#include <glib.h>#include <glib/gi18n.h>#include "glib-mem.h"#include <string.h>#include "ptk-dir-tree.h"#include "ptk-file-menu.h"#include "vfs-file-info.h"#include "vfs-file-monitor.h"static GQuark dir_tree_view_data = 0;static GtkTreeModel* get_dir_tree_model();static voidon_dir_tree_view_row_expanded( GtkTreeView *treeview,                               GtkTreeIter *iter,                               GtkTreePath *path,                               gpointer user_data );static voidon_dir_tree_view_row_collapsed( GtkTreeView *treeview,                                GtkTreeIter *iter,                                GtkTreePath *path,                                gpointer user_data );static gbooleanon_dir_tree_view_button_press( GtkWidget* view,                               GdkEventButton* evt,                               PtkFileBrowser* browser );static gboolean sel_func ( GtkTreeSelection *selection,                           GtkTreeModel *model,                           GtkTreePath *path,                           gboolean path_currently_selected,                           gpointer data );struct _DirTreeNode{    VFSFileInfo* file;    GList* children;    int n_children;    VFSFileMonitor* monitor;    int n_expand;};/*  Drag & Drop/Clipboard targets  */static GtkTargetEntry drag_targets[] =    {        { "text/uri-list", 0 , 0 }    };static gboolean filter_func( GtkTreeModel *model,                             GtkTreeIter *iter,                             gpointer data ){    VFSFileInfo * file;    const char* name;    GtkTreeView* view = ( GtkTreeView* ) data;    gboolean show_hidden = ( gboolean ) g_object_get_qdata( G_OBJECT( view ),                                                            dir_tree_view_data );    if ( show_hidden )        return TRUE;    gtk_tree_model_get( model, iter, COL_DIR_TREE_INFO, &file, -1 );    if ( G_LIKELY( file ) )    {        name = vfs_file_info_get_name( file );        if ( G_UNLIKELY( name && name[ 0 ] == '.' ) )        {            vfs_file_info_unref( file );            return FALSE;        }        vfs_file_info_unref( file );    }    return TRUE;}static void on_destroy(GtkWidget* w){    do{    }while( g_source_remove_by_user_data(w) );}/* Create a new dir tree view */GtkWidget* ptk_dir_tree_view_new( PtkFileBrowser* browser,                                  gboolean show_hidden ){    GtkTreeView * dir_tree_view;    GtkTreeViewColumn* col;    GtkCellRenderer* renderer;    GtkTreeModel* model;    GtkTreeSelection* tree_sel;    GtkTreePath* tree_path;    GtkTreeModel* filter;    dir_tree_view = GTK_TREE_VIEW( gtk_tree_view_new () );    gtk_tree_view_set_headers_visible( dir_tree_view, FALSE );    /*    FIXME: Temporarily disable drag & drop since it doesn't work right now.    gtk_tree_view_enable_model_drag_dest ( dir_tree_view,                                           drag_targets,                                           sizeof( drag_targets ) / sizeof( GtkTargetEntry ),                                           GDK_ACTION_DEFAULT | GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK );    gtk_tree_view_enable_model_drag_source ( dir_tree_view,                                             ( GDK_CONTROL_MASK | GDK_BUTTON1_MASK | GDK_BUTTON3_MASK ),                                             drag_targets,                                             sizeof( drag_targets ) / sizeof( GtkTargetEntry ),                                             GDK_ACTION_DEFAULT | GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK );    */    col = gtk_tree_view_column_new ();    renderer = ( GtkCellRenderer* ) ptk_file_icon_renderer_new();    gtk_tree_view_column_pack_start( col, renderer, FALSE );    gtk_tree_view_column_set_attributes( col, renderer, "pixbuf", COL_DIR_TREE_ICON,                                         "info", COL_DIR_TREE_INFO, NULL );    renderer = gtk_cell_renderer_text_new();    gtk_tree_view_column_pack_start( col, renderer, TRUE );    gtk_tree_view_column_set_attributes( col, renderer, "text", COL_DIR_TREE_DISP_NAME, NULL );    gtk_tree_view_append_column ( dir_tree_view, col );    tree_sel = gtk_tree_view_get_selection( dir_tree_view );    gtk_tree_selection_set_select_function( tree_sel, sel_func, NULL, NULL );    if ( G_UNLIKELY( !dir_tree_view_data ) )        dir_tree_view_data = g_quark_from_static_string( "show_hidden" );    g_object_set_qdata( G_OBJECT( dir_tree_view ),                        dir_tree_view_data, ( gpointer ) show_hidden );    model = get_dir_tree_model();    filter = gtk_tree_model_filter_new( model, NULL );    g_object_unref( G_OBJECT( model ) );    gtk_tree_model_filter_set_visible_func( GTK_TREE_MODEL_FILTER( filter ),                                            filter_func, dir_tree_view, NULL );    gtk_tree_view_set_model( dir_tree_view, filter );    g_object_unref( G_OBJECT( filter ) );    g_signal_connect ( dir_tree_view, "row-expanded",                       G_CALLBACK ( on_dir_tree_view_row_expanded ),                       model );    g_signal_connect_data ( dir_tree_view, "row-collapsed",                            G_CALLBACK ( on_dir_tree_view_row_collapsed ),                            model, NULL, G_CONNECT_AFTER );    g_signal_connect ( dir_tree_view, "button-press-event",                       G_CALLBACK ( on_dir_tree_view_button_press ),                       browser );    tree_path = gtk_tree_path_new_first();    gtk_tree_view_expand_row( dir_tree_view, tree_path, FALSE );    gtk_tree_path_free( tree_path );    g_signal_connect( dir_tree_view, "destroy", on_destroy, NULL );    return GTK_WIDGET( dir_tree_view );}gboolean ptk_dir_tree_view_chdir( GtkTreeView* dir_tree_view, const char* path ){    GtkTreeModel * model;    GtkTreeIter it, parent_it;    GtkTreePath* tree_path = NULL;    gchar **dirs, **dir;    gboolean found;    VFSFileInfo* info;    if ( !path || *path != '/' )        return FALSE;    dirs = g_strsplit( path + 1, "/", -1 );    if ( !dirs )        return FALSE;    model = gtk_tree_view_get_model( dir_tree_view );    if ( ! gtk_tree_model_iter_children ( model, &parent_it, NULL ) )    {        g_strfreev( dirs );        return FALSE;    }    /* special case: root dir */    if ( ! dirs[ 0 ] )    {        it = parent_it;        tree_path = gtk_tree_model_get_path ( model, &parent_it );        goto _found;    }    for ( dir = dirs; *dir; ++dir )    {        if ( ! gtk_tree_model_iter_children ( model, &it, &parent_it ) )        {            g_strfreev( dirs );            return FALSE;        }        found = FALSE;        do        {            gtk_tree_model_get( model, &it, COL_DIR_TREE_INFO, &info, -1 );            if ( !info )                continue;            if ( 0 == strcmp( vfs_file_info_get_name( info ), *dir ) )            {                tree_path = gtk_tree_model_get_path( model, &it );                gtk_tree_view_expand_row ( dir_tree_view, tree_path, FALSE );                gtk_tree_model_get_iter( model, &parent_it, tree_path );                found = TRUE;                vfs_file_info_unref( info );                break;            }            vfs_file_info_unref( info );        }        while ( gtk_tree_model_iter_next( model, &it ) );        if ( ! found )            return FALSE; /* Error! */        if ( tree_path && dir[ 1 ] )        {            gtk_tree_path_free( tree_path );            tree_path = NULL;        }    }_found:    g_strfreev( dirs );    gtk_tree_selection_select_path (        gtk_tree_view_get_selection( dir_tree_view ), tree_path );    gtk_tree_view_scroll_to_cell ( dir_tree_view, tree_path, NULL, FALSE, 0.5, 0.5 );    gtk_tree_path_free( tree_path );    return TRUE;}static char*ptk_dir_view_get_dir_path( GtkTreeModel* model, GtkTreeIter* it ){    GtkTreeModel * tree;    GtkTreeIter real_it;    char* dir_path = NULL;    gtk_tree_model_filter_convert_iter_to_child_iter(        GTK_TREE_MODEL_FILTER( model ), &real_it, it );    tree = gtk_tree_model_filter_get_model( GTK_TREE_MODEL_FILTER( model ) );    return ptk_dir_tree_get_dir_path( PTK_DIR_TREE( tree ), &real_it );}/* Return a newly allocated string containing path of current selected dir. */char* ptk_dir_tree_view_get_selected_dir( GtkTreeView* dir_tree_view ){    GtkTreeModel * model;    GtkTreeIter it;    GtkTreePath* tree_path;    GtkTreeSelection* tree_sel;    tree_sel = gtk_tree_view_get_selection( dir_tree_view );    if ( gtk_tree_selection_get_selected( tree_sel, &model, &it ) )        return ptk_dir_view_get_dir_path( model, &it );    return NULL;}GtkTreeModel* get_dir_tree_model(){    static PtkDirTree * dir_tree_model = NULL;    if ( G_UNLIKELY( ! dir_tree_model ) )    {        dir_tree_model = ptk_dir_tree_new( TRUE );        g_object_add_weak_pointer( G_OBJECT( dir_tree_model ),                                   ( gpointer * ) & dir_tree_model );    }    else    {        g_object_ref( G_OBJECT( dir_tree_model ) );    }    return GTK_TREE_MODEL( dir_tree_model );}gboolean sel_func ( GtkTreeSelection *selection,                    GtkTreeModel *model,                    GtkTreePath *path,                    gboolean path_currently_selected,                    gpointer data ){    GtkTreeIter it;    VFSFileInfo* file;    if ( ! gtk_tree_model_get_iter( model, &it, path ) )        return FALSE;    gtk_tree_model_get( model, &it, COL_DIR_TREE_INFO, &file, -1 );    if ( !file )        return FALSE;    vfs_file_info_unref( file );    return TRUE;}void ptk_dir_tree_view_show_hidden_files( GtkTreeView* dir_tree_view,                                          gboolean show_hidden ){    GtkTreeModel * filter;    g_object_set_qdata( G_OBJECT( dir_tree_view ),                        dir_tree_view_data, ( gpointer ) show_hidden );    filter = gtk_tree_view_get_model( dir_tree_view );    gtk_tree_model_filter_refilter( GTK_TREE_MODEL_FILTER( filter ) );}void on_dir_tree_view_row_expanded( GtkTreeView *treeview,                                    GtkTreeIter *iter,                                    GtkTreePath *path,                                    gpointer user_data ){    GtkTreeIter real_it;    GtkTreePath* real_path;    GtkTreeModel* filter = gtk_tree_view_get_model( treeview );    PtkDirTree* tree = PTK_DIR_TREE( user_data );    gtk_tree_model_filter_convert_iter_to_child_iter(        GTK_TREE_MODEL_FILTER( filter ), &real_it, iter );    real_path = gtk_tree_model_filter_convert_path_to_child_path(                    GTK_TREE_MODEL_FILTER( filter ), path );    ptk_dir_tree_expand_row( tree, &real_it, real_path );    gtk_tree_path_free( real_path );}void on_dir_tree_view_row_collapsed( GtkTreeView *treeview,                                     GtkTreeIter *iter,                                     GtkTreePath *path,                                     gpointer user_data ){    GtkTreeIter real_it;    GtkTreePath* real_path;    GtkTreeModel* filter = gtk_tree_view_get_model( treeview );    PtkDirTree* tree = PTK_DIR_TREE( user_data );    gtk_tree_model_filter_convert_iter_to_child_iter(        GTK_TREE_MODEL_FILTER( filter ), &real_it, iter );    real_path = gtk_tree_model_filter_convert_path_to_child_path(                    GTK_TREE_MODEL_FILTER( filter ), path );    ptk_dir_tree_collapse_row( tree, &real_it, real_path );    gtk_tree_path_free( real_path );}gboolean on_dir_tree_view_button_press( GtkWidget* view,                                        GdkEventButton* evt,                                        PtkFileBrowser* browser ){    if ( evt->type == GDK_BUTTON_PRESS && evt->button == 3 )    {        GtkTreeModel * model;        GtkTreePath* tree_path;        GtkTreeIter it;        model = gtk_tree_view_get_model( GTK_TREE_VIEW( view ) );        if ( gtk_tree_view_get_path_at_pos( GTK_TREE_VIEW( view ),                                            evt->x, evt->y, &tree_path, NULL, NULL, NULL ) )        {            if ( gtk_tree_model_get_iter( model, &it, tree_path ) )            {                VFSFileInfo * file;                gtk_tree_model_get( model, &it,                                    COL_DIR_TREE_INFO,                                    &file, -1 );                if ( file )                {                    GtkWidget * popup;                    char* file_path;                    GList* sel_files;                    char* dir_name;                    file_path = ptk_dir_view_get_dir_path( model, &it );                    vfs_file_info_ref( file );                    sel_files = g_list_prepend( NULL, file );                    dir_name = g_path_get_dirname( file_path );                    popup = ptk_file_menu_new(                                file_path, file,                                dir_name, sel_files, browser );                    g_free( dir_name );                    g_free( file_path );                    gtk_menu_popup( GTK_MENU( popup ), NULL, NULL,                                    NULL, NULL, 3, evt->time );                    vfs_file_info_unref( file );                }            }            gtk_tree_path_free( tree_path );        }    }    return FALSE;}

⌨️ 快捷键说明

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