📄 vfs-mime-type.c
字号:
/** C Implementation: vfs-mime_type-type** Description:*** Author: Hong Jen Yee (PCMan) <pcman.tw (AT) gmail.com>, (C) 2006** Copyright: See COPYING file that comes with this distribution**/#include "vfs-mime-type.h"#include "vfs-file-monitor.h"#include <sys/types.h>#include <sys/stat.h>#include <unistd.h>#include <fcntl.h>#include <string.h>#include <gtk/gtk.h>#include "glib-mem.h"static GHashTable *mime_hash = NULL;static guint reload_callback_id = 0;static int big_icon_size = 32, small_icon_size = 16;const char mime_actions_group[] = "MIME Cache";static GKeyFile *mime_actions = NULL;static GKeyFile *user_actions = NULL;VFSFileMonitor* mime_actions_monitor = NULL;static guint theme_change_notify = 0;static void on_icon_theme_changed( GtkIconTheme *icon_theme, gpointer user_data );#if 0/* FIXME: Don't cache mime actions since they change often */static void free_old_actions( gpointer key, gpointer value, gpointer user_data ){ VFSMimeType * mime_type = ( VFSMimeType* ) value; g_strfreev( mime_type->actions ); mime_type->actions = NULL;}#endifstatic void reload_mime_actions( VFSFileMonitor* fm, VFSFileMonitorEvent event, const char* file_name, gpointer user_data ){#if 0 /* unload all old cached data */ /* FIXME: Why sometimes this callback gets called twice? */ g_hash_table_foreach( mime_hash, free_old_actions, NULL );#endif GDK_THREADS_ENTER(); if ( mime_actions ) { g_key_file_free( mime_actions ); /* reload data */ mime_actions = g_key_file_new(); g_key_file_load_from_file( mime_actions, fm->path, G_KEY_FILE_NONE, NULL ); } GDK_THREADS_LEAVE();}static void init_mime_actions(){ /* FIXME: Paths of directories shouldn't be hardcoded */ gchar * full_path = g_build_filename( "/usr/share", "applications/mimeinfo.cache", NULL ); mime_actions = g_key_file_new(); g_key_file_load_from_file( mime_actions, full_path, G_KEY_FILE_NONE, NULL ); /* FIXME: using file monitors for this purpose is a waste and should be changed */ mime_actions_monitor = vfs_file_monitor_add( full_path, reload_mime_actions, mime_hash ); g_free( full_path ); full_path = g_build_filename( g_get_home_dir(), ".pcmanfm/mime_info", NULL ); user_actions = g_key_file_new(); g_key_file_load_from_file( user_actions, full_path, G_KEY_FILE_NONE, NULL ); g_free( full_path );}/* Final clean up */void finalize_mime_actions(){ if ( mime_actions ) g_key_file_free( mime_actions ); if ( user_actions ) g_key_file_free( user_actions ); if ( mime_actions_monitor ) vfs_file_monitor_remove( mime_actions_monitor, reload_mime_actions, mime_hash );}/* Save user profile */static void save_mime_actions(){ gchar * full_path; gchar* data; gsize len; int file; if ( ! mime_actions && ! user_actions ) init_mime_actions(); if ( user_actions ) { if ( (data = g_key_file_to_data ( user_actions, &len, NULL )) ) { full_path = g_build_filename( g_get_home_dir(), ".pcmanfm/mime_info", NULL ); file = creat( full_path, S_IWUSR | S_IRUSR | S_IRGRP ); g_free( full_path ); if ( file != -1 ) { write( file, data, len ); close( file ); } else { g_warning( "Cannot save mime actions\n" ); } g_free( data ); } }}static void vfs_mime_type_reload( void* user_data ){ /* FIXME: process mime database reloading properly. */ /* Remove all items in the hash table */ GDK_THREADS_ENTER(); g_hash_table_foreach_remove ( mime_hash, ( GHRFunc ) gtk_true, NULL ); GDK_THREADS_LEAVE();}void vfs_mime_type_init(){ GtkIconTheme * theme; xdg_mime_init(); reload_callback_id = xdg_mime_register_reload_callback( vfs_mime_type_reload, NULL, NULL ); mime_hash = g_hash_table_new_full( g_str_hash, g_str_equal, NULL, vfs_mime_type_unref ); theme = gtk_icon_theme_get_default(); theme_change_notify = g_signal_connect( theme, "changed", G_CALLBACK( on_icon_theme_changed ), NULL );}void vfs_mime_type_clean(){ GtkIconTheme * theme; theme = gtk_icon_theme_get_default(); g_signal_handler_disconnect( theme, theme_change_notify ); xdg_mime_remove_callback( reload_callback_id ); xdg_mime_shutdown(); g_hash_table_destroy( mime_hash ); if ( mime_actions || user_actions ) finalize_mime_actions();}VFSMimeType* vfs_mime_type_get_from_file_name( const char* ufile_name ){ const char * type; type = xdg_mime_get_mime_type_from_file_name( ufile_name ); return vfs_mime_type_get_from_type( type );}VFSMimeType* vfs_mime_type_get_from_file( const char* file_path, const char* base_name, struct stat* pstat ){ struct stat file_stat; const char* type; /* We have to get the mime-type of target path when the file itself is a symlink */ if ( !pstat || S_ISLNK( pstat->st_mode ) ) { /* FIXME: If the file doesn't exist, should we return NULL? */ if ( stat( file_path, &file_stat ) == 0 ) pstat = &file_stat; } if ( S_ISDIR( pstat->st_mode ) ) { type = XDG_MIME_TYPE_DIRECTORY; } else { if ( !base_name ) { base_name = strrchr( file_path, '/' ); if ( base_name ) { ++base_name; } else { base_name = file_path; } } type = xdg_mime_get_mime_type_for_file( file_path, base_name, pstat ); } return vfs_mime_type_get_from_type( type );}VFSMimeType* vfs_mime_type_get_from_type( const char* type ){ VFSMimeType * mime_type; mime_type = g_hash_table_lookup( mime_hash, type ); if ( !mime_type ) { mime_type = vfs_mime_type_new( type ); g_hash_table_insert( mime_hash, mime_type->type, mime_type ); } vfs_mime_type_ref( mime_type ); return mime_type;}VFSMimeType* vfs_mime_type_new( const char* type_name ){ VFSMimeType * mime_type = g_slice_new0( VFSMimeType ); mime_type->type = g_strdup( type_name ); mime_type->n_ref = 1; return mime_type;}void vfs_mime_type_ref( VFSMimeType* mime_type ){ ++mime_type->n_ref;}void vfs_mime_type_unref( gpointer mime_type_ ){ VFSMimeType* mime_type = (VFSMimeType*)mime_type_; --mime_type->n_ref; if ( mime_type->n_ref == 0 ) { g_free( mime_type->type ); if ( mime_type->big_icon ) gdk_pixbuf_unref( mime_type->big_icon ); if ( mime_type->small_icon ) gdk_pixbuf_unref( mime_type->small_icon ); /* g_strfreev( mime_type->actions ); */ g_slice_free( VFSMimeType, mime_type ); }}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 gdk_pixbuf_ref( mime_type->big_icon ); size = big_icon_size; } else /* small icon */ { if ( G_LIKELY( mime_type->small_icon ) ) return gdk_pixbuf_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 = gtk_icon_theme_load_icon ( icon_theme, "gnome-fs-directory", size, 0, NULL ); if ( big ) mime_type->big_icon = icon; else mime_type->small_icon = icon; return icon ? gdk_pixbuf_ref( icon ) : NULL; } sep = strchr( mime_type->type, '/' ); if ( !sep ) return NULL; strcpy( icon_name, "gnome-mime-" ); strncat( icon_name, mime_type->type, ( sep - mime_type->type ) ); strcat( icon_name, "-" ); strcat( icon_name, sep + 1 ); icon = gtk_icon_theme_load_icon ( icon_theme, icon_name, size, 0, NULL ); if ( ! icon ) { icon_name[ 11 ] = 0; strncat( icon_name, mime_type->type, ( sep - mime_type->type ) ); icon = gtk_icon_theme_load_icon ( icon_theme, icon_name, size, 0, NULL ); } 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 = gtk_icon_theme_load_icon ( icon_theme, "unknown", size, 0, NULL ); } } if ( big ) mime_type->big_icon = icon; else mime_type->small_icon = icon; return icon ? gdk_pixbuf_ref( icon ) : NULL;}static void free_cached_icons ( gpointer key, gpointer value, gpointer user_data ){ VFSMimeType * mime_type = ( VFSMimeType* ) value; gboolean big = ( gboolean ) user_data; if ( big ) { if ( mime_type->big_icon ) { gdk_pixbuf_unref( mime_type->big_icon ); mime_type->big_icon = NULL; } } else { if ( mime_type->small_icon ) { gdk_pixbuf_unref( mime_type->small_icon ); mime_type->small_icon = NULL; } }}void vfs_mime_type_set_icon_size( int big, int small ){ if ( big != big_icon_size ) { big_icon_size = big; /* Unload old cached icons */ g_hash_table_foreach( mime_hash, free_cached_icons, ( gpointer ) TRUE ); } if ( small != small_icon_size ) { small_icon_size = small; /* Unload old cached icons */ g_hash_table_foreach( mime_hash, free_cached_icons, ( gpointer ) FALSE ); }}void vfs_mime_type_get_icon_size( int* big, int* small ){ if ( big ) * big = big_icon_size; if ( small ) * small = small_icon_size;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -