📄 file-properties.c
字号:
#ifdef HAVE_CONFIG_H# include <config.h>#endif#include <gtk/gtk.h>#include "glib-mem.h"#include "file-properties.h"#include "file-properties-ui.h"#include "glade-support.h"#include "xdgmime.h"#include <sys/types.h>#include <pwd.h>#include <grp.h>#include <string.h>#include "ptk-file-task.h"#include "ptk-utils.h"#include "vfs-file-info.h"#include "vfs-app-desktop.h"const char* chmod_names[] = { "owner_r", "owner_w", "owner_x", "group_r", "group_w", "group_x", "others_r", "others_w", "others_x", "set_uid", "set_gid", "sticky" };typedef struct{ char* dir_path; GList* file_list; GtkWidget* dlg; GtkEntry* owner; GtkEntry* group; char* owner_name; char* group_name; GtkToggleButton* chmod_btns[ N_CHMOD_ACTIONS ]; guchar chmod_states[ N_CHMOD_ACTIONS ]; GtkLabel* total_size_label; GtkLabel* size_on_disk_label; off_t total_size; off_t size_on_disk; guint total_count; gboolean cancel; gboolean done; GThread* calc_size_thread; guint update_label_timer;}FilePropertiesDialogData;/** void get_total_size_of_dir( const char* path, off_t* size )* Recursively count total size of all files in the specified directory.* If the path specified is a file, the size of the file is directly returned.* cancel is used to cancel the operation. This function will check the value* pointed by cancel in every iteration. If cancel is set to TRUE, the* calculation is cancelled.* NOTE: path is encoded in on-disk encoding and not necessarily UTF-8.*/static void calc_total_size_of_files( const char* path, FilePropertiesDialogData* data ){ GDir * dir; const char* name; char* full_path; struct stat file_stat; if ( data->cancel ) return ; if ( lstat( path, &file_stat ) ) return ; data->total_size += file_stat.st_size; data->size_on_disk += ( file_stat.st_blocks << 9 ); /* block x 512 */ ++data->total_count; dir = g_dir_open( path, 0, NULL ); if ( dir ) { while ( !data->cancel && ( name = g_dir_read_name( dir ) ) ) { full_path = g_build_filename( path, name, NULL ); lstat( full_path, &file_stat ); if ( S_ISDIR( file_stat.st_mode ) ) { calc_total_size_of_files( full_path, data ); } else { data->total_size += file_stat.st_size; data->size_on_disk += ( file_stat.st_blocks << 9 ); ++data->total_count; } g_free( full_path ); } g_dir_close( dir ); }}static gpointer calc_size( gpointer user_data ){ FilePropertiesDialogData * data = ( FilePropertiesDialogData* ) user_data; GList* l; char* path; VFSFileInfo* file; for ( l = data->file_list; l; l = l->next ) { if ( data->cancel ) break; file = ( VFSFileInfo* ) l->data; path = g_build_filename( data->dir_path, vfs_file_info_get_name( file ), NULL ); if ( path ) { calc_total_size_of_files( path, data ); g_free( path ); } } data->done = TRUE; return NULL;}gboolean on_update_labels( FilePropertiesDialogData* data ){ char buf[ 64 ]; char buf2[ 32 ]; gdk_threads_enter(); file_size_to_string( buf2, data->total_size ); sprintf( buf, "%s (%llu Bytes)", buf2, ( guint64 ) data->total_size ); gtk_label_set_text( data->total_size_label, buf ); file_size_to_string( buf2, data->size_on_disk ); sprintf( buf, "%s (%llu Bytes)", buf2, ( guint64 ) data->size_on_disk ); gtk_label_set_text( data->size_on_disk_label, buf ); gdk_threads_leave(); return !data->done;}static void on_chmod_btn_toggled( GtkToggleButton* btn, FilePropertiesDialogData* data ){ /* Bypass the default handler */ g_signal_stop_emission_by_name( btn, "toggled" ); /* Block this handler while we are changing the state of buttons, or this handler will be called recursively. */ g_signal_handlers_block_matched( btn, G_SIGNAL_MATCH_FUNC, 0, 0, NULL, on_chmod_btn_toggled, NULL ); if ( gtk_toggle_button_get_inconsistent( btn ) ) { gtk_toggle_button_set_inconsistent( btn, FALSE ); gtk_toggle_button_set_active( btn, FALSE ); } else if ( ! gtk_toggle_button_get_active( btn ) ) { gtk_toggle_button_set_inconsistent( btn, TRUE ); } g_signal_handlers_unblock_matched( btn, G_SIGNAL_MATCH_FUNC, 0, 0, NULL, on_chmod_btn_toggled, NULL );}static gboolean combo_sep( GtkTreeModel *model, GtkTreeIter* it, gpointer user_data ){ int i; for( i = 2; i > 0; --i ) { char* tmp; gtk_tree_model_get( model, it, i, &tmp, -1 ); if( tmp ) { g_free( tmp ); return FALSE; } } return TRUE;}static void on_combo_change( GtkComboBox* combo, gpointer user_data ){ GtkTreeIter it; if( gtk_combo_box_get_active_iter(combo, &it) ) { const char* action; GtkTreeModel* model = gtk_combo_box_get_model( combo ); gtk_tree_model_get( model, &it, 2, &action, -1 ); if( ! action ) { char* action; GtkWidget* parent; VFSMimeType* mime = (VFSMimeType*)user_data; parent = gtk_widget_get_toplevel( GTK_WIDGET( combo ) ); action = ptk_choose_app_for_mime_type( GTK_WINDOW(parent), mime ); if( action ) { gboolean exist = FALSE; /* check if the action is already in the list */ if( gtk_tree_model_get_iter_first( model, &it ) ) { do { char* tmp; gtk_tree_model_get( model, &it, 2, &tmp, -1 ); if( !tmp ) continue; if( 0 == strcmp( tmp, action ) ) { exist = TRUE; g_free( tmp ); break; } g_free( tmp ); } while( gtk_tree_model_iter_next( model, &it ) ); } if( ! exist ) /* It didn't exist */ { VFSAppDesktop* app = vfs_app_desktop_new( action ); if( app ) { GdkPixbuf* icon; icon = vfs_app_desktop_get_icon( app, 20 ); gtk_list_store_insert_with_values( GTK_LIST_STORE( model ), &it, 0, 0, icon, 1, vfs_app_desktop_get_disp_name(app), 2, action, -1 ); if( icon ) gdk_pixbuf_unref( icon ); vfs_app_desktop_unref( app ); exist = TRUE; } } if( exist ) gtk_combo_box_set_active_iter( combo, &it ); g_free( action ); } else { int prev_sel; prev_sel = GPOINTER_TO_INT( g_object_get_data( combo, "prev_sel") ); gtk_combo_box_set_active( combo, prev_sel ); } } else { int prev_sel = gtk_combo_box_get_active( combo ); g_object_set_data( combo, "prev_sel", GINT_TO_POINTER(prev_sel) ); } } else { g_object_set_data( combo, "prev_sel", GINT_TO_POINTER(-1) ); }}GtkWidget* file_properties_dlg_new( GtkWindow* parent, const char* dir_path, GList* sel_files ){ GtkWidget * dlg = create_filePropertiesDlg(); FilePropertiesDialogData* data; gboolean need_calc_size = TRUE; VFSFileInfo *file, *file2; VFSMimeType* mime; const char* multiple_files = _( "Multiple files are selected" ); const char* calculating; GtkWidget* name = lookup_widget( dlg, "file_name" ); GtkWidget* location = lookup_widget( dlg, "location" ); GtkWidget* mime_type = lookup_widget( dlg, "mime_type" ); GtkWidget* open_with = lookup_widget( dlg, "open_with" ); GtkWidget* mtime = lookup_widget( dlg, "mtime" ); GtkWidget* atime = lookup_widget( dlg, "atime" ); char buf[ 64 ]; char buf2[ 32 ]; const char* time_format = "%Y-%m-%d %H:%M"; gchar* file_name; gchar* disp_path; gchar* file_path; gchar* file_type; int i; GList* l; gboolean same_type = TRUE; char *owner_group, *tmp; gtk_window_set_transient_for( GTK_WINDOW( dlg ), parent ); data = g_slice_new0( FilePropertiesDialogData ); /* FIXME: When will the data be freed??? */ g_object_set_data( G_OBJECT( dlg ), "DialogData", data ); data->file_list = sel_files; data->dlg = dlg; data->dir_path = g_strdup( dir_path ); disp_path = g_filename_display_name( dir_path ); gtk_label_set_text( GTK_LABEL( location ), disp_path ); g_free( disp_path ); data->total_size_label = GTK_LABEL( lookup_widget( dlg, "total_size" ) ); data->size_on_disk_label = GTK_LABEL( lookup_widget( dlg, "size_on_disk" ) ); data->owner = GTK_ENTRY( lookup_widget( dlg, "owner" ) ); data->group = GTK_ENTRY( lookup_widget( dlg, "group" ) ); for ( i = 0; i < N_CHMOD_ACTIONS; ++i ) { data->chmod_btns[ i ] = GTK_TOGGLE_BUTTON( lookup_widget( dlg, chmod_names[ i ] ) ); } for ( l = sel_files; l && l->next; l = l->next ) { VFSMimeType *type, *type2; file = ( VFSFileInfo* ) l->data; file2 = ( VFSFileInfo* ) l->next->data; type = vfs_file_info_get_mime_type( file ); type2 = vfs_file_info_get_mime_type( file2 ); if ( type != type2 ) { vfs_mime_type_unref( type ); vfs_mime_type_unref( type2 ); same_type = FALSE; break; } vfs_mime_type_unref( type ); vfs_mime_type_unref( type2 ); } file = ( VFSFileInfo* ) sel_files->data; if ( same_type ) { mime = vfs_file_info_get_mime_type( file ); file_type = g_strdup_printf( "%s (%s)", vfs_mime_type_get_description( mime ), vfs_mime_type_get_type( mime ) ); gtk_label_set_text( GTK_LABEL( mime_type ), file_type ); g_free( file_type ); vfs_mime_type_unref( mime ); } else { gtk_label_set_text( GTK_LABEL( mime_type ), _( "Multiple files of different types" ) ); } /* Open with... * Don't show this option menu if files of different types are selected, * ,the selected file is a folder, or its type is unknown. */ if( ! same_type || vfs_file_info_is_dir( file ) || vfs_file_info_is_unknown_type( file ) || vfs_file_info_is_executable( file, NULL ) ) { /* if open with shouldn't show, destroy it. */ gtk_widget_destroy( open_with );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -