void vfs_file_info_reload_mime_type( VFSFileInfo* fi, const char* full_path ) { VFSMimeType * old_mime_type; struct stat64 file_stat; /* convert VFSFileInfo to struct stat */ /* In current implementation, only st_mode is used in mime-type detection, so let's save some CPU cycles and don't copy unused fields. */ file_stat.st_mode = fi->mode; /* file_stat.st_dev = fi->dev; file_stat.st_uid = fi->uid; file_stat.st_gid = fi->gid; file_stat.st_size = fi->size; file_stat.st_mtime = fi->mtime; file_stat.st_atime = fi->atime; file_stat.st_blksize = fi->blksize; file_stat.st_blocks = fi->blocks; */ old_mime_type = fi->mime_type; fi->mime_type = vfs_mime_type_get_from_file( full_path, fi->name, &file_stat ); vfs_file_info_load_special_info( fi, full_path ); vfs_mime_type_unref( old_mime_type ); /* FIXME: is vfs_mime_type_unref needed ?*/ }
static void vfs_file_info_clear( VFSFileInfo* fi ) { if ( fi->disp_name && fi->disp_name != fi->name ) { g_free( fi->disp_name ); fi->disp_name = NULL; } if ( fi->name ) { g_free( fi->name ); fi->name = NULL; } if ( fi->collate_key ) //sfm { g_free( fi->collate_key ); fi->collate_key = NULL; } if ( fi->collate_icase_key ) //sfm { g_free( fi->collate_icase_key ); fi->collate_icase_key = NULL; } if ( fi->disp_size ) { g_free( fi->disp_size ); fi->disp_size = NULL; } if ( fi->disp_owner ) { g_free( fi->disp_owner ); fi->disp_owner = NULL; } if ( fi->disp_mtime ) { g_free( fi->disp_mtime ); fi->disp_mtime = NULL; } if ( fi->big_thumbnail ) { g_object_unref( fi->big_thumbnail ); fi->big_thumbnail = NULL; } if ( fi->small_thumbnail ) { g_object_unref( fi->small_thumbnail ); fi->small_thumbnail = NULL; } fi->disp_perm[ 0 ] = '\0'; if ( fi->mime_type ) { vfs_mime_type_unref( fi->mime_type ); fi->mime_type = NULL; } fi->flags = VFS_FILE_INFO_NONE; }
/* * Run default action of specified file. * Full path of the file is required by this function. */ gboolean vfs_file_info_open_file( VFSFileInfo* fi, const char* file_path, GError** err ) { VFSMimeType * mime_type; char* app_name; VFSAppDesktop* app; GList* files = NULL; gboolean ret = FALSE; char* argv[ 2 ]; if ( vfs_file_info_is_executable( fi, file_path ) ) { argv[ 0 ] = (char *) file_path; argv[ 1 ] = '\0'; ret = g_spawn_async( NULL, argv, NULL, G_SPAWN_STDOUT_TO_DEV_NULL| G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, err ); } else { mime_type = vfs_file_info_get_mime_type( fi ); app_name = vfs_mime_type_get_default_action( mime_type ); if ( app_name ) { app = vfs_app_desktop_new( app_name ); if ( ! vfs_app_desktop_get_exec( app ) ) app->exec = g_strdup( app_name ); /* FIXME: app->exec */ files = g_list_prepend( files, (gpointer) file_path ); /* FIXME: working dir is needed */ ret = vfs_app_desktop_open_files( gdk_screen_get_default(), NULL, app, files, err ); g_list_free( files ); vfs_app_desktop_unref( app ); g_free( app_name ); } vfs_mime_type_unref( mime_type ); } return ret; }
static GdkPixbuf* _vfs_thumbnail_load( const char* file_path, const char* uri, int size, time_t mtime ) { #if GLIB_CHECK_VERSION(2, 16, 0) GChecksum *cs; #else md5_state_t md5_state; md5_byte_t md5[ 16 ]; #endif char file_name[ 40 ]; char* thumbnail_file; char mtime_str[ 32 ]; const char* thumb_mtime; int i, w, h; struct stat statbuf; GdkPixbuf* thumbnail, *result = NULL; int create_size; if ( size > 256 ) create_size = 512; else if ( size > 128 ) create_size = 256; else create_size = 128; gboolean file_is_video = FALSE; #ifdef HAVE_FFMPEG VFSMimeType* mimetype = vfs_mime_type_get_from_file_name( file_path ); if ( mimetype ) { if ( strncmp( vfs_mime_type_get_type( mimetype ), "video/", 6 ) == 0 ) file_is_video = TRUE; vfs_mime_type_unref( mimetype ); } #endif if ( file_is_video == FALSE ) { if ( !gdk_pixbuf_get_file_info( file_path, &w, &h ) ) return NULL; /* image format cannot be recognized */ /* If the image itself is very small, we should load it directly */ if ( w <= create_size && h <= create_size ) { if( w <= size && h <= size ) return gdk_pixbuf_new_from_file( file_path, NULL ); return gdk_pixbuf_new_from_file_at_size( file_path, size, size, NULL ); } } #if GLIB_CHECK_VERSION(2, 16, 0) cs = g_checksum_new(G_CHECKSUM_MD5); g_checksum_update(cs, uri, strlen(uri)); memcpy( file_name, g_checksum_get_string(cs), 32 ); g_checksum_free(cs); #else md5_init( &md5_state ); md5_append( &md5_state, ( md5_byte_t * ) uri, strlen( uri ) ); md5_finish( &md5_state, md5 ); for ( i = 0; i < 16; ++i ) sprintf( ( file_name + i * 2 ), "%02x", md5[ i ] ); #endif strcpy( ( file_name + 32 ), ".png" ); thumbnail_file = g_build_filename( g_get_home_dir(), ".thumbnails/normal", file_name, NULL ); if( G_UNLIKELY( 0 == mtime ) ) { if( stat( file_path, &statbuf ) != -1 ) mtime = statbuf.st_mtime; } if ( file_is_video && time( NULL ) - mtime < 5 ) /* if mod time of video being thumbnailed is less than 5 sec ago, * don't create a thumbnail (is copying?) * FIXME: This means that a newly saved file may not show a thumbnail * until refresh. */ return NULL; /* load existing thumbnail */ thumbnail = gdk_pixbuf_new_from_file( thumbnail_file, NULL ); if ( thumbnail ) { w = gdk_pixbuf_get_width( thumbnail ); h = gdk_pixbuf_get_height( thumbnail ); } if ( !thumbnail || ( w < size && h < size ) || !( thumb_mtime = gdk_pixbuf_get_option( thumbnail, "tEXt::Thumb::MTime" ) ) || atol( thumb_mtime ) != mtime ) { if( thumbnail ) g_object_unref( thumbnail ); /* create new thumbnail */ if ( file_is_video == FALSE ) { thumbnail = gdk_pixbuf_new_from_file_at_size( file_path, create_size, create_size, NULL ); if ( thumbnail ) { // Note: gdk_pixbuf_apply_embedded_orientation returns a new // pixbuf or same with incremented ref count, so unref GdkPixbuf* thumbnail_old = thumbnail; thumbnail = gdk_pixbuf_apply_embedded_orientation( thumbnail ); g_object_unref( thumbnail_old ); sprintf( mtime_str, "%lu", mtime ); gdk_pixbuf_save( thumbnail, thumbnail_file, "png", NULL, "tEXt::Thumb::URI", uri, "tEXt::Thumb::MTime", mtime_str, NULL ); chmod( thumbnail_file, 0600 ); /* only the owner can read it. */ } } #ifdef HAVE_FFMPEG else { video_thumbnailer* video_thumb = video_thumbnailer_create(); /* Setting a callback to allow silencing of stdout/stderr messages * from the library. This is no longer required since v2.0.11, where * silence is the default. It can be used for debugging in 2.0.11 * and later. */ //video_thumbnailer_set_log_callback(on_video_thumbnailer_log_message); if ( video_thumb ) { video_thumb->seek_percentage = 25; video_thumb->overlay_film_strip = 1; video_thumb->thumbnail_size = create_size; video_thumbnailer_generate_thumbnail_to_file( video_thumb, file_path, thumbnail_file ); video_thumbnailer_destroy( video_thumb ); chmod( thumbnail_file, 0600 ); /* only the owner can read it. */ thumbnail = gdk_pixbuf_new_from_file( thumbnail_file, NULL ); } } #endif } if ( thumbnail ) { w = gdk_pixbuf_get_width( thumbnail ); h = gdk_pixbuf_get_height( thumbnail ); if ( w > h ) { h = h * size / w; w = size; } else if ( h > w ) { w = w * size / h; h = size; } else { w = h = size; } if ( w > 0 && h > 0 ) result = gdk_pixbuf_scale_simple( thumbnail, w, h, GDK_INTERP_BILINEAR ); g_object_unref( thumbnail ); } g_free( thumbnail_file ); return result; }
void on_dlg_response ( GtkDialog *dialog, gint response_id, gpointer user_data ) { FilePropertiesDialogData * data; PtkFileTask* task; gboolean mod_change; uid_t uid = -1; gid_t gid = -1; const char* owner_name; const char* group_name; int i; GList* l; GList* file_list; char* file_path; GtkWidget* ask_recursive; VFSFileInfo* file; GtkAllocation allocation; gtk_widget_get_allocation ( GTK_WIDGET( dialog ), &allocation ); int width = allocation.width; int height = allocation.height; if ( width && height ) { char* str = g_strdup_printf( "%d", width ); xset_set( "app_dlg", "s", str ); g_free( str ); str = g_strdup_printf( "%d", height ); xset_set( "app_dlg", "z", str ); g_free( str ); } data = ( FilePropertiesDialogData* ) g_object_get_data( G_OBJECT( dialog ), "DialogData" ); if ( data ) { if ( data->update_label_timer ) g_source_remove( data->update_label_timer ); data->cancel = TRUE; if ( data->calc_size_thread ) g_thread_join( data->calc_size_thread ); if ( response_id == GTK_RESPONSE_OK ) { GtkWidget* open_with; /* Set default action for mimetype */ if( ( open_with = (GtkWidget*)g_object_get_data( G_OBJECT(dialog), "open_with" ) ) ) { GtkTreeModel* model = gtk_combo_box_get_model( GTK_COMBO_BOX(open_with) ); GtkTreeIter it; if( model && gtk_combo_box_get_active_iter( GTK_COMBO_BOX(open_with), &it ) ) { char* action; gtk_tree_model_get( model, &it, 2, &action, -1 ); if( action ) { file = ( VFSFileInfo* ) data->file_list->data; VFSMimeType* mime = vfs_file_info_get_mime_type( file ); vfs_mime_type_set_default_action( mime, action ); vfs_mime_type_unref( mime ); g_free( action ); } } } /* Check if we need chown */ owner_name = gtk_entry_get_text( data->owner ); if ( owner_name && *owner_name && (!data->owner_name || strcmp( owner_name, data->owner_name ) ) ) { uid = uid_from_name( owner_name ); if ( uid == -1 ) { ptk_show_error( GTK_WINDOW( dialog ), _("Error"), _( "Invalid User" ) ); return ; } } group_name = gtk_entry_get_text( data->group ); if ( group_name && *group_name && (!data->group_name || strcmp( group_name, data->group_name ) ) ) { gid = gid_from_name( group_name ); if ( gid == -1 ) { ptk_show_error( GTK_WINDOW( dialog ), _("Error"), _( "Invalid Group" ) ); return ; } } for ( i = 0; i < N_CHMOD_ACTIONS; ++i ) { if ( gtk_toggle_button_get_inconsistent( data->chmod_btns[ i ] ) ) { data->chmod_states[ i ] = 2; /* Don't touch this bit */ } else if ( data->chmod_states[ i ] != gtk_toggle_button_get_active( data->chmod_btns[ i ] ) ) { mod_change = TRUE; data->chmod_states[ i ] = gtk_toggle_button_get_active( data->chmod_btns[ i ] ); } else /* Don't change this bit */ { data->chmod_states[ i ] = 2; } } if ( uid != -1 || gid != -1 || mod_change ) { file_list = NULL; for ( l = data->file_list; l; l = l->next ) { file = ( VFSFileInfo* ) l->data; file_path = g_build_filename( data->dir_path, vfs_file_info_get_name( file ), NULL ); file_list = g_list_prepend( file_list, file_path ); } task = ptk_file_task_new( VFS_FILE_TASK_CHMOD_CHOWN, file_list, NULL, GTK_WINDOW(gtk_widget_get_parent( GTK_WIDGET( dialog ) )), NULL ); //MOD ptk_file_task_set_recursive( task, gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( data->recurse ) ) ); /* for ( l = data->file_list; l; l = l->next ) { file = ( VFSFileInfo* ) l->data; if ( vfs_file_info_is_dir( file ) ) { ask_recursive = gtk_message_dialog_new( GTK_WINDOW( data->dlg ), GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, _( "Do you want to recursively apply these changes to all files and sub-folders?" ) ); ptk_file_task_set_recursive( task, ( GTK_RESPONSE_YES == gtk_dialog_run( GTK_DIALOG( ask_recursive ) ) ) ); gtk_widget_destroy( ask_recursive ); break; } } */ if ( mod_change ) { /* If the permissions of file has been changed by the user */ ptk_file_task_set_chmod( task, data->chmod_states ); } /* For chown */ ptk_file_task_set_chown( task, uid, gid ); ptk_file_task_run( task ); /* * This file list will be freed by file operation, so we don't * need to do this. Just set the pointer to NULL. */ data->file_list = NULL; } } g_free( data->owner_name ); g_free( data->group_name ); /* *NOTE: File operation chmod/chown will free the list when it's done, *and we only need to free it when there is no file operation applyed. */ g_slice_free( FilePropertiesDialogData, data ); } gtk_widget_destroy( GTK_WIDGET( dialog ) ); }
GtkWidget* file_properties_dlg_new( GtkWindow* parent, const char* dir_path, GList* sel_files, int page ) { GtkBuilder* builder = _gtk_builder_new_from_file( PACKAGE_UI_DIR "/file_properties.ui", NULL ); GtkWidget * dlg = (GtkWidget*)gtk_builder_get_object( builder, "dlg" ); GtkNotebook* notebook = (GtkNotebook*)gtk_builder_get_object( builder, "notebook" ); FilePropertiesDialogData* data; gboolean need_calc_size = TRUE; VFSFileInfo *file, *file2; VFSMimeType* mime; const char* multiple_files = _( "( multiple files )" ); const char* calculating; GtkWidget* name = (GtkWidget*)gtk_builder_get_object( builder, "file_name" ); GtkWidget* location = (GtkWidget*)gtk_builder_get_object( builder, "location" ); gtk_editable_set_editable ( GTK_EDITABLE( location ), FALSE ); GtkWidget* mime_type = (GtkWidget*)gtk_builder_get_object( builder, "mime_type" ); GtkWidget* open_with = (GtkWidget*)gtk_builder_get_object( builder, "open_with" ); GtkWidget* mtime = (GtkWidget*)gtk_builder_get_object( builder, "mtime" ); GtkWidget* atime = (GtkWidget*)gtk_builder_get_object( builder, "atime" ); char buf[ 64 ]; char buf2[ 32 ]; const char* time_format = "%Y-%m-%d %H:%M"; gchar* disp_path; gchar* file_type; int i; GList* l; gboolean same_type = TRUE; gboolean is_dirs = FALSE; char *owner_group, *tmp; gtk_dialog_set_alternative_button_order( GTK_DIALOG(dlg), GTK_RESPONSE_OK, GTK_RESPONSE_CANCEL, -1 ); ptk_dialog_fit_small_screen( GTK_DIALOG(dlg) ); int width = xset_get_int( "app_dlg", "s" ); int height = xset_get_int( "app_dlg", "z" ); if ( width && height ) gtk_window_set_default_size( GTK_WINDOW( dlg ), width, height ); 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 ); gtk_entry_set_text( GTK_ENTRY( location ), disp_path ); g_free( disp_path ); data->total_size_label = GTK_LABEL( (GtkWidget*)gtk_builder_get_object( builder, "total_size" ) ); data->size_on_disk_label = GTK_LABEL( (GtkWidget*)gtk_builder_get_object( builder, "size_on_disk" ) ); data->count_label = GTK_LABEL( (GtkWidget*)gtk_builder_get_object( builder, "count" ) ); data->owner = GTK_ENTRY( (GtkWidget*)gtk_builder_get_object( builder, "owner" ) ); data->group = GTK_ENTRY( (GtkWidget*)gtk_builder_get_object( builder, "group" ) ); for ( i = 0; i < N_CHMOD_ACTIONS; ++i ) { data->chmod_btns[ i ] = GTK_TOGGLE_BUTTON( (GtkWidget*)gtk_builder_get_object( builder, chmod_names[ i ] ) ); } //MOD VFSMimeType* type; VFSMimeType* type2 = NULL; for ( l = sel_files; l ; l = l->next ) { file = ( VFSFileInfo* ) l->data; type = vfs_file_info_get_mime_type( file ); if ( !type2 ) type2 = vfs_file_info_get_mime_type( file ); if ( vfs_file_info_is_dir( file ) ) is_dirs = TRUE; if ( type != type2 ) same_type = FALSE; vfs_mime_type_unref( type ); if ( is_dirs && !same_type ) break; } if ( type2 ) vfs_mime_type_unref( type2 ); data->recurse = (GtkWidget*)gtk_builder_get_object( builder, "recursive" ); gtk_widget_set_sensitive( data->recurse, is_dirs ); /* //MOD 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 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_desktop_entry( 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 ); open_with = NULL; gtk_widget_destroy( (GtkWidget*)gtk_builder_get_object( builder, "open_with_label" ) ); } else /* Add available actions to the option menu */ { GtkTreeIter it; char **action, **actions; mime = vfs_file_info_get_mime_type( file ); actions = vfs_mime_type_get_actions( mime ); GtkCellRenderer* renderer; GtkListStore* model; gtk_cell_layout_clear( GTK_CELL_LAYOUT(open_with) ); renderer = gtk_cell_renderer_pixbuf_new(); gtk_cell_layout_pack_start( GTK_CELL_LAYOUT(open_with), renderer, FALSE); gtk_cell_layout_set_attributes( GTK_CELL_LAYOUT(open_with), renderer, "pixbuf", 0, NULL ); renderer = gtk_cell_renderer_text_new(); gtk_cell_layout_pack_start( GTK_CELL_LAYOUT(open_with), renderer, TRUE); gtk_cell_layout_set_attributes( GTK_CELL_LAYOUT(open_with),renderer, "text", 1, NULL ); model = gtk_list_store_new( 3, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING ); if( actions ) { for( action = actions; *action; ++action ) { VFSAppDesktop* desktop; GdkPixbuf* icon; desktop = vfs_app_desktop_new( *action ); gtk_list_store_append( model, &it ); icon = vfs_app_desktop_get_icon(desktop, 20, TRUE); gtk_list_store_set( model, &it, 0, icon, 1, vfs_app_desktop_get_disp_name(desktop), 2, *action, -1 ); if( icon ) g_object_unref( icon ); vfs_app_desktop_unref( desktop ); } } else { g_object_set_data( G_OBJECT(open_with), "prev_sel", GINT_TO_POINTER(-1) ); } /* separator */ gtk_list_store_append( model, &it ); gtk_list_store_append( model, &it ); gtk_list_store_set( model, &it, 0, NULL, 1, _("Choose..."), -1 ); gtk_combo_box_set_model( GTK_COMBO_BOX(open_with), GTK_TREE_MODEL(model) ); gtk_combo_box_set_row_separator_func( GTK_COMBO_BOX(open_with), combo_sep, NULL, NULL ); gtk_combo_box_set_active(GTK_COMBO_BOX(open_with), 0); g_signal_connect( open_with, "changed", G_CALLBACK(on_combo_change), mime ); /* vfs_mime_type_unref( mime ); */ /* We can unref mime when combo box gets destroyed */ g_object_weak_ref( G_OBJECT(open_with), (GWeakNotify)vfs_mime_type_unref, mime ); } g_object_set_data( G_OBJECT(dlg), "open_with", open_with ); /* Multiple files are selected */ if ( sel_files && sel_files->next ) { gtk_widget_set_sensitive( name, FALSE ); gtk_entry_set_text( GTK_ENTRY( name ), multiple_files ); gtk_label_set_text( GTK_LABEL( mtime ), "-" ); gtk_label_set_text( GTK_LABEL( atime ), "-" ); for ( i = 0; i < N_CHMOD_ACTIONS; ++i ) { gtk_toggle_button_set_inconsistent ( data->chmod_btns[ i ], TRUE ); data->chmod_states[ i ] = 2; /* Don't touch this bit */ g_signal_connect( G_OBJECT( data->chmod_btns[ i ] ), "toggled", G_CALLBACK( on_chmod_btn_toggled ), data ); } } else { /* special processing for files with special display names */ if( vfs_file_info_is_desktop_entry( file ) ) { char* disp_name = g_filename_display_name( file->name ); gtk_entry_set_text( GTK_ENTRY( name ), disp_name ); g_free( disp_name ); } else gtk_entry_set_text( GTK_ENTRY( name ), vfs_file_info_get_disp_name( file ) ); gtk_editable_set_editable ( GTK_EDITABLE( name ), FALSE ); if ( ! vfs_file_info_is_dir( file ) ) { /* Only single "file" is selected, so we don't need to caculate total file size */ need_calc_size = FALSE; sprintf( buf, _("%s ( %llu bytes )"), vfs_file_info_get_disp_size( file ), ( guint64 ) vfs_file_info_get_size( file ) ); gtk_label_set_text( data->total_size_label, buf ); vfs_file_size_to_string( buf2, vfs_file_info_get_blocks( file ) * 512 ); sprintf( buf, _("%s ( %llu bytes )"), buf2, ( guint64 ) vfs_file_info_get_blocks( file ) * 512 ); gtk_label_set_text( data->size_on_disk_label, buf ); gtk_label_set_text( data->count_label, _("1 file") ); } gtk_label_set_text( GTK_LABEL( mtime ), vfs_file_info_get_disp_mtime( file ) ); strftime( buf, sizeof( buf ), time_format, localtime( vfs_file_info_get_atime( file ) ) ); gtk_label_set_text( GTK_LABEL( atime ), buf ); owner_group = (char *) vfs_file_info_get_disp_owner( file ); tmp = strchr( owner_group, ':' ); data->owner_name = g_strndup( owner_group, tmp - owner_group ); gtk_entry_set_text( GTK_ENTRY( data->owner ), data->owner_name ); data->group_name = g_strdup( tmp + 1 ); gtk_entry_set_text( GTK_ENTRY( data->group ), data->group_name ); for ( i = 0; i < N_CHMOD_ACTIONS; ++i ) { if ( data->chmod_states[ i ] != 2 ) /* allow to touch this bit */ { data->chmod_states[ i ] = ( vfs_file_info_get_mode( file ) & chmod_flags[ i ] ? 1 : 0 ); gtk_toggle_button_set_active( data->chmod_btns[ i ], data->chmod_states[ i ] ); } } } if ( need_calc_size ) { /* The total file size displayed in "File Properties" is not completely calculated yet. So "Calculating..." is displayed. */ calculating = _( "Calculating..." ); gtk_label_set_text( data->total_size_label, calculating ); gtk_label_set_text( data->size_on_disk_label, calculating ); g_object_set_data( G_OBJECT( dlg ), "calc_size", data ); data->calc_size_thread = g_thread_create ( ( GThreadFunc ) calc_size, data, TRUE, NULL ); data->update_label_timer = g_timeout_add( 250, ( GSourceFunc ) on_update_labels, data ); } g_signal_connect( dlg, "response", G_CALLBACK(on_dlg_response), dlg ); g_signal_connect_swapped( gtk_builder_get_object(builder, "ok_button"), "clicked", G_CALLBACK(gtk_widget_destroy), dlg ); g_signal_connect_swapped( gtk_builder_get_object(builder, "cancel_button"), "clicked", G_CALLBACK(gtk_widget_destroy), dlg ); g_object_unref( builder ); gtk_notebook_set_current_page( notebook, page ); gtk_window_set_transient_for( GTK_WINDOW( dlg ), parent ); return dlg; }
GdkPixbuf* vfs_mime_type_get_icon( VFSMimeType* mime_type, gboolean big ) { GdkPixbuf * icon = NULL; const char* sep; char icon_name[ 100 ]; GtkIconTheme *icon_theme; int size; if ( big ) { if ( G_LIKELY( mime_type->big_icon ) ) /* big icon */ return g_object_ref( mime_type->big_icon ); size = big_icon_size; } else /* small icon */ { if ( G_LIKELY( mime_type->small_icon ) ) return g_object_ref( mime_type->small_icon ); size = small_icon_size; } icon_theme = gtk_icon_theme_get_default (); if ( G_UNLIKELY( 0 == strcmp( mime_type->type, XDG_MIME_TYPE_DIRECTORY ) ) ) { icon = vfs_load_icon ( icon_theme, "folder", size ); if( G_UNLIKELY( !icon) ) icon = vfs_load_icon ( icon_theme, "gnome-fs-directory", size ); if( G_UNLIKELY( !icon) ) icon = vfs_load_icon ( icon_theme, "gtk-directory", size ); if ( big ) mime_type->big_icon = icon; else mime_type->small_icon = icon; return icon ? g_object_ref( icon ) : NULL; } sep = strchr( mime_type->type, '/' ); if ( sep ) { /* convert mime-type foo/bar to foo-bar */ strcpy( icon_name, mime_type->type ); icon_name[ (sep - mime_type->type) ] = '-'; /* is there an icon named foo-bar? */ icon = vfs_load_icon ( icon_theme, icon_name, size ); if ( ! icon ) { /* maybe we can find a legacy icon named gnome-mime-foo-bar */ strcpy( icon_name, "gnome-mime-" ); strncat( icon_name, mime_type->type, ( sep - mime_type->type ) ); strcat( icon_name, "-" ); strcat( icon_name, sep + 1 ); icon = vfs_load_icon ( icon_theme, icon_name, size ); } // hack for x-xz-compressed-tar missing icon if ( !icon && strstr( mime_type->type, "compressed" ) ) { icon = vfs_load_icon ( icon_theme, "application-x-archive", size ); if ( !icon ) icon = vfs_load_icon ( icon_theme, "gnome-mime-application-x-archive", size ); } /* try gnome-mime-foo */ if ( G_UNLIKELY( ! icon ) ) { icon_name[ 11 ] = '\0'; /* strlen("gnome-mime-") = 11 */ strncat( icon_name, mime_type->type, ( sep - mime_type->type ) ); icon = vfs_load_icon ( icon_theme, icon_name, size ); } /* try foo-x-generic */ if ( G_UNLIKELY( ! icon ) ) { strncpy( icon_name, mime_type->type, ( sep - mime_type->type ) ); icon_name[ (sep - mime_type->type) ] = '\0'; strcat( icon_name, "-x-generic" ); icon = vfs_load_icon ( icon_theme, icon_name, size ); } } if( G_UNLIKELY( !icon ) ) { /* prevent endless recursion of XDG_MIME_TYPE_UNKNOWN */ if( G_LIKELY( strcmp(mime_type->type, XDG_MIME_TYPE_UNKNOWN) ) ) { /* FIXME: fallback to icon of parent mime-type */ VFSMimeType* unknown; unknown = vfs_mime_type_get_from_type( XDG_MIME_TYPE_UNKNOWN ); icon = vfs_mime_type_get_icon( unknown, big ); vfs_mime_type_unref( unknown ); } else /* unknown */ { icon = vfs_load_icon ( icon_theme, "unknown", size ); } } if ( big ) mime_type->big_icon = icon; else mime_type->small_icon = icon; return icon ? g_object_ref( icon ) : NULL; }