void fm_folder_model_file_deleted(FmFolderModel* model, FmFileInfo* file) { GSequenceIter *seq_it; /* not required for hidden files */ gboolean update_view; #if 0 /* If there is no file info, that means the dir itself was deleted. */ if( G_UNLIKELY(!file) ) { /* Clear the whole list */ GSequenceIter *items_it = g_sequence_get_begin_iter(model->items); path = gtk_tree_path_new_from_indices(0, -1); while( !g_sequence_iter_is_end(items_it) ) { gtk_tree_model_row_deleted(GTK_TREE_MODEL(model), path); file = (VFSFileInfo*)g_sequence_get(items_it); items_it = g_sequence_iter_next(it); vfs_file_info_unref(file); } for( l = model->items; l; l = model->items ) { gtk_tree_model_row_deleted(GTK_TREE_MODEL(model), path); file = (VFSFileInfo*)l->data; model->items = g_list_delete_link(model->items, l); vfs_file_info_unref(file); } g_sequence_remove_range( g_sequence_get_begin_iter(model->items), g_sequence_get_end_iter(model->items) ); gtk_tree_path_free(path); return; } #endif if( !model->show_hidden && fm_file_info_is_hidden(file) ) /* if this is a hidden file */ { update_view = FALSE; seq_it = g_sequence_get_begin_iter(model->hidden); } else { update_view = TRUE; seq_it = g_sequence_get_begin_iter(model->items); } while( !g_sequence_iter_is_end(seq_it) ) { FmFolderItem* item = (FmFolderItem*)g_sequence_get(seq_it); if( item->inf == file ) break; seq_it = g_sequence_iter_next(seq_it); } if( update_view ) { GtkTreePath* path = gtk_tree_path_new_from_indices(g_sequence_iter_get_position(seq_it), -1); gtk_tree_model_row_deleted(GTK_TREE_MODEL(model), path); gtk_tree_path_free(path); } model->iter_age++; g_sequence_remove(seq_it); }
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; }
void update_created_files( gpointer key, gpointer data, gpointer user_data ) { VFSDir* dir = (VFSDir*)data; GSList* l; char* full_path; VFSFileInfo* file; GList* ll; if ( dir->created_files ) { g_mutex_lock( dir->mutex ); for ( l = dir->created_files; l; l = l->next ) { if ( !( ll = vfs_dir_find_file( dir, (char*)l->data, NULL ) ) ) { // file is not in dir file_list full_path = g_build_filename( dir->path, (char*)l->data, NULL ); file = vfs_file_info_new(); if ( vfs_file_info_get( file, full_path, NULL ) ) { // add new file to dir file_list vfs_file_info_load_special_info( file, full_path ); dir->file_list = g_list_prepend( dir->file_list, vfs_file_info_ref( file ) ); ++dir->n_files; g_signal_emit( dir, signals[ FILE_CREATED_SIGNAL ], 0, file ); } // else file doesn't exist in filesystem vfs_file_info_unref( file ); g_free( full_path ); } else { // file already exists in dir file_list file = vfs_file_info_ref( (VFSFileInfo*)ll->data ); if ( update_file_info( dir, file ) ) { g_signal_emit( dir, signals[ FILE_CHANGED_SIGNAL ], 0, file ); vfs_file_info_unref( file ); } // else was deleted, signaled, and unrefed in update_file_info } g_free( (char*)l->data ); // free file_name string } g_slist_free( dir->created_files ); dir->created_files = NULL; g_mutex_unlock( dir->mutex ); } }
gboolean on_thumbnail_idle( VFSThumbnailLoader* loader ) { VFSFileInfo* file; /* g_debug( "ENTER ON_THUMBNAIL_IDLE" ); */ vfs_async_task_lock( loader->task ); while( ( file = (VFSFileInfo*)g_queue_pop_head(loader->update_queue) ) ) { GDK_THREADS_ENTER(); vfs_dir_emit_thumbnail_loaded( loader->dir, file ); vfs_file_info_unref( file ); GDK_THREADS_LEAVE(); } loader->idle_handler = 0; vfs_async_task_unlock( loader->task ); if( vfs_async_task_is_finished( loader->task ) ) { /* g_debug( "FREE LOADER IN IDLE HANDLER" ); */ loader->dir->thumbnail_loader = NULL; vfs_thumbnail_loader_free(loader); } /* g_debug( "LEAVE ON_THUMBNAIL_IDLE" ); */ return FALSE; }
static void process_found_files( FindFile* data, GQueue* queue, const char* path ) { char *name; gsize len, term; GtkTreeIter it; VFSFileInfo* fi; GdkPixbuf* icon; FoundFile* ff; if( path ) { name = g_filename_display_basename( path ); fi = vfs_file_info_new(); if( vfs_file_info_get( fi, path, name ) ) { ff = g_slice_new0( FoundFile ); ff->fi = fi; ff->dir_path = g_path_get_dirname( path ); g_queue_push_tail( queue, ff ); } else { vfs_file_info_unref( fi ); } g_free( name ); /* we queue the found files, and not add them to the tree view direclty. * when we queued more than 10 files, we add them at once. I think * this can prevent locking gtk+ too frequently and improve responsiveness. * FIXME: This could blocked the last queued files and delay their display * to the end of the whole search. A better method is needed. */ //MOD disabled this - causes last queued files to not display // if( g_queue_get_length( queue ) < 10 ) // return; } while( ff = (FoundFile*)g_queue_pop_head(queue) ) { GDK_THREADS_ENTER(); gtk_list_store_append( data->result_list, &it ); icon = vfs_file_info_get_small_icon( ff->fi ); gtk_list_store_set( data->result_list, &it, COL_ICON, icon, COL_NAME, vfs_file_info_get_disp_name(ff->fi), COL_DIR, ff->dir_path, /* FIXME: non-UTF8? */ COL_TYPE, vfs_file_info_get_mime_type_desc( ff->fi ), COL_SIZE, vfs_file_info_get_disp_size( ff->fi ), COL_MTIME, vfs_file_info_get_disp_mtime( ff->fi ), COL_INFO, ff->fi, -1 ); g_object_unref( icon ); GDK_THREADS_LEAVE(); g_slice_free( FoundFile, ff ); } }
void vfs_dir_emit_file_changed( VFSDir* dir, const char* file_name, VFSFileInfo* file, gboolean force ) { GList* l; //printf("vfs_dir_emit_file_changed dir=%s file_name=%s avoid=%s\n", dir->path, file_name, dir->avoid_changes ? "TRUE" : "FALSE" ); if ( !force && dir->avoid_changes ) return; if ( G_UNLIKELY( 0 == strcmp(file_name, dir->path) ) ) { // Special Case: The directory itself was changed g_signal_emit( dir, signals[ FILE_CHANGED_SIGNAL ], 0, NULL ); return; } g_mutex_lock( dir->mutex ); l = vfs_dir_find_file( dir, file_name, file ); if ( G_LIKELY( l ) ) { file = vfs_file_info_ref( ( VFSFileInfo* ) l->data ); if( !g_slist_find( dir->changed_files, file ) ) { if ( force ) { dir->changed_files = g_slist_prepend( dir->changed_files, file ); if ( 0 == change_notify_timeout ) { change_notify_timeout = g_timeout_add_full( G_PRIORITY_LOW, 100, notify_file_change, NULL, NULL ); } } else if( G_LIKELY( update_file_info( dir, file ) ) ) // update file info the first time { dir->changed_files = g_slist_prepend( dir->changed_files, file ); if ( 0 == change_notify_timeout ) { change_notify_timeout = g_timeout_add_full( G_PRIORITY_LOW, 500, notify_file_change, NULL, NULL ); } g_signal_emit( dir, signals[ FILE_CHANGED_SIGNAL ], 0, file ); } } else vfs_file_info_unref( file ); } g_mutex_unlock( dir->mutex ); }
void ptk_file_list_file_deleted( VFSDir* dir, VFSFileInfo* file, PtkFileList* list ) { GList* l; GtkTreePath* path; /* If there is no file info, that means the dir itself was deleted. */ if( G_UNLIKELY( ! file ) ) { /* Clear the whole list */ path = gtk_tree_path_new_from_indices(0, -1); for( l = list->files; l; l = list->files ) { gtk_tree_model_row_deleted( GTK_TREE_MODEL(list), path ); file = (VFSFileInfo*)l->data; list->files = g_list_delete_link( list->files, l ); vfs_file_info_unref( file ); --list->n_files; } gtk_tree_path_free( path ); return; } if( ! list->show_hidden && vfs_file_info_get_name(file)[0] == '.' ) return; l = g_list_find( list->files, file ); if( ! l ) return; path = gtk_tree_path_new_from_indices( g_list_index(list->files, l->data), -1 ); gtk_tree_model_row_deleted( GTK_TREE_MODEL(list), path ); gtk_tree_path_free( path ); list->files = g_list_delete_link( list->files, l ); vfs_file_info_unref( file ); --list->n_files; }
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 ); sel_files = g_list_prepend( NULL, vfs_file_info_ref(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; }
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; }
//MOD drag n drop static char* dir_tree_view_get_drop_dir( GtkWidget* view, int x, int y ) { GtkTreePath *tree_path = NULL; GtkTreeModel *model; GtkTreeIter it; VFSFileInfo* file; char* dest_path = NULL; // if drag is in progress, get the dest row path gtk_tree_view_get_drag_dest_row( GTK_TREE_VIEW( view ), &tree_path, NULL ); if ( !tree_path ) { // no drag in progress, get drop path if ( !gtk_tree_view_get_path_at_pos( GTK_TREE_VIEW( view ), x, y, &tree_path, NULL, NULL, NULL ) ) tree_path = NULL; } if ( tree_path ) { model = gtk_tree_view_get_model( GTK_TREE_VIEW( view ) ); if ( gtk_tree_model_get_iter( model, &it, tree_path ) ) { gtk_tree_model_get( model, &it, COL_DIR_TREE_INFO, &file, -1 ); if ( file ) { dest_path = ptk_dir_view_get_dir_path( model, &it ); vfs_file_info_unref( file ); } } gtk_tree_path_free( tree_path ); } /* this isn't needed? // dest_path is a link? resolve if ( dest_path && g_file_test( dest_path, G_FILE_TEST_IS_SYMLINK ) ) { char* old_dest = dest_path; dest_path = g_file_read_link( old_dest, NULL ); g_free( old_dest ); } */ return dest_path; }
gboolean update_file_info( VFSDir* dir, VFSFileInfo* file ) { char* full_path; char* file_name; gboolean ret = FALSE; /* gboolean is_desktop = is_dir_desktop(dir->path); */ /* FIXME: Dirty hack: steal the string to prevent memory allocation */ file_name = file->name; if( file->name == file->disp_name ) file->disp_name = NULL; file->name = NULL; full_path = g_build_filename( dir->path, file_name, NULL ); if ( G_LIKELY( full_path ) ) { if( G_LIKELY( vfs_file_info_get( file, full_path, file_name ) ) ) { ret = TRUE; /* if( G_UNLIKELY(is_desktop) ) */ vfs_file_info_load_special_info( file, full_path ); } else /* The file doesn't exist */ { GList* l; l = g_list_find( dir->file_list, file ); if( G_UNLIKELY(l) ) { dir->file_list = g_list_delete_link( dir->file_list, l ); --dir->n_files; if ( file ) { g_signal_emit( dir, signals[ FILE_DELETED_SIGNAL ], 0, file ); vfs_file_info_unref( file ); } } ret = FALSE; } g_free( full_path ); } g_free( file_name ); return ret; }
void vfs_dir_emit_thumbnail_loaded( VFSDir* dir, VFSFileInfo* file ) { GList* l; g_mutex_lock( dir->mutex ); l = vfs_dir_find_file( dir, file->name, file ); if( l ) { g_assert( file == (VFSFileInfo*)l->data ); file = vfs_file_info_ref( (VFSFileInfo*)l->data ); } else file = NULL; g_mutex_unlock( dir->mutex ); if ( G_LIKELY( file ) ) { g_signal_emit( dir, signals[ THUMBNAIL_LOADED_SIGNAL ], 0, file ); vfs_file_info_unref( file ); } }
void vfs_dir_emit_file_deleted( VFSDir* dir, const char* file_name, VFSFileInfo* file ) { GList* l; VFSFileInfo* file_found; if( G_UNLIKELY( 0 == strcmp(file_name, dir->path) ) ) { /* Special Case: The directory itself was deleted... */ file = NULL; /* clear the whole list */ g_mutex_lock( dir->mutex ); g_list_foreach( dir->file_list, (GFunc)vfs_file_info_unref, NULL ); g_list_free( dir->file_list ); dir->file_list = NULL; g_mutex_unlock( dir->mutex ); g_signal_emit( dir, signals[ FILE_DELETED_SIGNAL ], 0, file ); return; } l = vfs_dir_find_file( dir, file_name, file ); if ( G_LIKELY( l ) ) { file_found = vfs_file_info_ref( ( VFSFileInfo* ) l->data ); if( !g_slist_find( dir->changed_files, file_found ) ) { dir->changed_files = g_slist_prepend( dir->changed_files, file_found ); if ( 0 == change_notify_timeout ) { change_notify_timeout = g_timeout_add_full( G_PRIORITY_LOW, 200, notify_file_change, NULL, NULL ); } } else vfs_file_info_unref( file_found ); } }
void update_changed_files( gpointer key, gpointer data, gpointer user_data ) { VFSDir* dir = (VFSDir*)data; GSList* l; VFSFileInfo* file; if ( dir->changed_files ) { g_mutex_lock( dir->mutex ); for ( l = dir->changed_files; l; l = l->next ) { file = vfs_file_info_ref( ( VFSFileInfo* ) l->data ); /// if ( update_file_info( dir, file ) ) { g_signal_emit( dir, signals[ FILE_CHANGED_SIGNAL ], 0, file ); vfs_file_info_unref( file ); } // else was deleted, signaled, and unrefed in update_file_info } g_slist_free( dir->changed_files ); dir->changed_files = NULL; g_mutex_unlock( dir->mutex ); } }
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 ); if( dir[1] ) { 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; }
void thumbnail_request_free( ThumbnailRequest* req ) { vfs_file_info_unref( req->file ); g_slice_free( ThumbnailRequest, req ); /* g_debug( "FREE REQUEST!" ); */ }
gboolean on_dir_tree_view_key_press( GtkWidget* view, GdkEventKey* evt, PtkFileBrowser* browser ) { VFSFileInfo* file; GtkTreeModel *model; GtkTreeIter iter; GtkTreeSelection *select = gtk_tree_view_get_selection(GTK_TREE_VIEW(view)); if(!gtk_tree_selection_get_selected(select, &model, &iter)) return FALSE; int keymod = ( evt->state & ( GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK | GDK_SUPER_MASK | GDK_HYPER_MASK | GDK_META_MASK ) ); GtkTreePath *path = gtk_tree_model_get_path(model, &iter); switch( evt->keyval ) { case GDK_KEY_Left: if(gtk_tree_view_row_expanded(GTK_TREE_VIEW(view), path)) { gtk_tree_view_collapse_row(GTK_TREE_VIEW(view), path); } else if(gtk_tree_path_up(path)) { gtk_tree_selection_select_path(select, path); gtk_tree_view_set_cursor(GTK_TREE_VIEW(view), path, NULL, FALSE); } else { gtk_tree_path_free( path ); return FALSE; } break; case GDK_KEY_Right: if(!gtk_tree_view_row_expanded(GTK_TREE_VIEW(view), path)) { gtk_tree_view_expand_row(GTK_TREE_VIEW(view), path, FALSE); } else { gtk_tree_path_down(path); gtk_tree_selection_select_path(select, path); gtk_tree_view_set_cursor(GTK_TREE_VIEW(view), path, NULL, FALSE); } break; case GDK_KEY_F10: case GDK_KEY_Menu: if ( evt->keyval == GDK_KEY_F10 && keymod != GDK_SHIFT_MASK ) { gtk_tree_path_free( path ); return FALSE; } gtk_tree_model_get( gtk_tree_view_get_model( GTK_TREE_VIEW( view ) ), &iter, 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( gtk_tree_view_get_model( GTK_TREE_VIEW( view ) ), &iter ); sel_files = g_list_prepend( NULL, vfs_file_info_ref(file) ); dir_name = g_path_get_dirname( file_path ); popup = ptk_file_menu_new( NULL, browser, file_path, file, dir_name, sel_files ); g_free( dir_name ); g_free( file_path ); if ( popup ) gtk_menu_popup( GTK_MENU( popup ), NULL, NULL, NULL, NULL, 3, evt->time ); vfs_file_info_unref( file ); } break; default: gtk_tree_path_free( path ); return FALSE; } gtk_tree_path_free( path ); return TRUE; }
gpointer vfs_dir_load_thread( VFSAsyncTask* task, VFSDir* dir ) { const gchar * file_name; char* full_path; GDir* dir_content; VFSFileInfo* file; char* hidden = NULL; //MOD added dir->file_listed = 0; dir->load_complete = 0; dir->xhidden_count = 0; //MOD if ( dir->path ) { /* Install file alteration monitor */ dir->monitor = vfs_file_monitor_add_dir( dir->path, vfs_dir_monitor_callback, dir ); dir_content = g_dir_open( dir->path, 0, NULL ); if ( dir_content ) { GKeyFile* kf; if( G_UNLIKELY(dir->is_trash) ) kf = g_key_file_new(); // MOD dir contains .hidden file? hidden = gethidden( dir->path ); while ( ! vfs_async_task_is_cancelled( dir->task ) && ( file_name = g_dir_read_name( dir_content ) ) ) { full_path = g_build_filename( dir->path, file_name, NULL ); if ( !full_path ) continue; //MOD ignore if in .hidden if ( hidden && ishidden( hidden, file_name ) ) { dir->xhidden_count++; continue; } /* FIXME: Is locking GDK needed here? */ /* GDK_THREADS_ENTER(); */ file = vfs_file_info_new(); if ( G_LIKELY( vfs_file_info_get( file, full_path, file_name ) ) ) { g_mutex_lock( dir->mutex ); /* Special processing for desktop folder */ vfs_file_info_load_special_info( file, full_path ); /* FIXME: load info, too when new file is added to trash dir */ if( G_UNLIKELY( dir->is_trash ) ) /* load info of trashed files */ { gboolean info_loaded; char* info = g_strconcat( home_trash_dir, "/info/", file_name, ".trashinfo", NULL ); info_loaded = g_key_file_load_from_file( kf, info, 0, NULL ); g_free( info ); if( info_loaded ) { char* ori_path = g_key_file_get_string( kf, "Trash Info", "Path", NULL ); if( ori_path ) { /* Thanks to the stupid freedesktop.org spec, the filename is encoded * like a URL, which is insane. This add nothing more than overhead. */ char* fake_uri = g_strconcat( "file://", ori_path, NULL ); g_free( ori_path ); ori_path = g_filename_from_uri( fake_uri, NULL, NULL ); /* g_debug( ori_path ); */ if( file->disp_name && file->disp_name != file->name ) g_free( file->disp_name ); file->disp_name = g_filename_display_basename( ori_path ); g_free( ori_path ); } } } dir->file_list = g_list_prepend( dir->file_list, file ); g_mutex_unlock( dir->mutex ); ++dir->n_files; } else { vfs_file_info_unref( file ); } /* GDK_THREADS_LEAVE(); */ g_free( full_path ); } g_dir_close( dir_content ); if ( hidden ) g_free( hidden ); if( G_UNLIKELY(dir->is_trash) ) g_key_file_free( kf ); } } return NULL; }
gboolean on_dir_tree_view_button_press( GtkWidget* view, GdkEventButton* evt, PtkFileBrowser* browser ) { GtkTreeModel* model; GtkTreePath* tree_path; GtkTreeViewColumn* tree_col; GtkTreeIter it; if ( evt->type == GDK_BUTTON_PRESS && ( evt->button == 1 || evt->button == 3 ) ) { // middle click 2 handled in ptk-file-browser.c on_dir_tree_button_press 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, &tree_col, NULL, NULL ) ) { if ( gtk_tree_model_get_iter( model, &it, tree_path ) ) { gtk_tree_view_set_cursor( GTK_TREE_VIEW( view ), tree_path, tree_col, FALSE ); gtk_tree_view_row_activated( GTK_TREE_VIEW( view ), tree_path, tree_col ); if ( evt->button == 3 ) { // right click 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 ); sel_files = g_list_prepend( NULL, vfs_file_info_ref(file) ); dir_name = g_path_get_dirname( file_path ); /* FIXME: New|Tab Here and New|File etc work on the * wrong location because dir_name is really incorrect. * But if set to cur dir it breaks Copy, etc. */ popup = ptk_file_menu_new( NULL, browser, file_path, file, dir_name, sel_files ); g_free( dir_name ); g_free( file_path ); if ( popup ) 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 TRUE; } } } gtk_tree_path_free( tree_path ); } } else if ( evt->type == GDK_2BUTTON_PRESS && evt->button == 1 ) { // double click - expand/collapse if ( gtk_tree_view_get_path_at_pos( GTK_TREE_VIEW( view ), evt->x, evt->y, &tree_path, NULL, NULL, NULL ) ) { if ( gtk_tree_view_row_expanded( GTK_TREE_VIEW( view ), tree_path ) ) gtk_tree_view_collapse_row( GTK_TREE_VIEW( view ), tree_path ); else gtk_tree_view_expand_row( GTK_TREE_VIEW( view ), tree_path, FALSE ); gtk_tree_path_free( tree_path ); return TRUE; } } return FALSE; }