Skip to content

Commit

Permalink
get mime type icon or generic-icon from XML files before guess
Browse files Browse the repository at this point in the history
  • Loading branch information
IgnorantGuru committed May 14, 2015
1 parent 7a862b0 commit dd1db2c
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 55 deletions.
3 changes: 2 additions & 1 deletion ChangeLog
@@ -1,4 +1,4 @@
1.0.1+
1.0.1+next
toolbar redesign with design mode right-click ability
fix Compact view sometimes fails to scroll to selected file #502
malloc_trim calls to flush out the free heap back to the OS when needed
Expand All @@ -10,6 +10,7 @@
add Run As Task option to file handlers
allow escape of underscore in item names #522
fix Item Prop context opposite of Disable is Show instead of Enable
get mime type icon or generic-icon from XML files before guess
1.0.1 2015-05-04:
extended bookmarks system
added users manual Bookmarks section
Expand Down
66 changes: 54 additions & 12 deletions src/mime-type/mime-type.c
Expand Up @@ -255,12 +255,49 @@ const char* mime_type_get_by_file( const char* filepath, struct stat64* statbuf,
return type && *type ? type : XDG_MIME_TYPE_UNKNOWN;
}

/* Get the name of mime-type */
/*const char* mime_type_get_type( MimeInfo* info )
{
return info->type_name;
static char* parse_xml_icon( const char* buf, size_t len )
{ // Note: This function modifies contents of buf
char *icon_tag, *end_tag;

// find <icon name=
icon_tag = g_strstr_len( buf, len, "<icon name=" );
if ( icon_tag )
{
icon_tag += 11;
len -= 11;
}
else
{
// otherwise find <generic-icon name=
icon_tag = g_strstr_len( buf, len, "<generic-icon name=" );
if ( icon_tag )
{
icon_tag += 19;
len -= 19;
}
else
return NULL; // no icon found
}

// find />
end_tag = g_strstr_len( icon_tag, len, "/>" );
if ( !end_tag )
return NULL;
end_tag[0] = '\0';
if ( strchr( end_tag, '\n' ) )
return NULL; // linefeed in tag

// remove quotes
if ( icon_tag[0] == '"' )
icon_tag++;
if ( end_tag[-1] == '"' )
end_tag[-1] = '\0';

if ( icon_tag == end_tag )
return NULL; // blank name

return g_strdup( icon_tag );
}
*/

static char* parse_xml_desc( const char* buf, size_t len, const char* locale )
{
Expand Down Expand Up @@ -301,7 +338,8 @@ static char* parse_xml_desc( const char* buf, size_t len, const char* locale )
return g_strndup( eng_comment, eng_comment_len );
}

static char* _mime_type_get_desc( const char* file_path, const char* locale )
static char* _mime_type_get_desc( const char* file_path, const char* locale,
gboolean get_icon )
{
int fd;
struct stat statbuf; // skip stat64
Expand Down Expand Up @@ -333,7 +371,7 @@ static char* _mime_type_get_desc( const char* file_path, const char* locale )
return NULL;

_locale = NULL;
if( ! locale )
if( ! locale && !get_icon )
{
const char* const * langs = g_get_language_names();
char* dot = strchr( langs[0], '.' );
Expand All @@ -342,7 +380,10 @@ static char* _mime_type_get_desc( const char* file_path, const char* locale )
else
locale = langs[0];
}
desc = parse_xml_desc( buffer, statbuf.st_size, locale );
if ( get_icon )
desc = parse_xml_icon( buffer, statbuf.st_size );
else
desc = parse_xml_desc( buffer, statbuf.st_size, locale );
g_free( _locale );

#ifdef HAVE_MMAP
Expand All @@ -354,11 +395,12 @@ static char* _mime_type_get_desc( const char* file_path, const char* locale )
}

/*
* Get human-readable description of the mime-type
* Get human-readable description (or icon) of the mime-type
* If locale is NULL, current locale will be used.
* The returned string should be freed when no longer used.
*/
char* mime_type_get_desc( const char* type, const char* locale )
char* mime_type_get_desc( const char* type, const char* locale,
gboolean get_icon )
{
char* desc;
const gchar* const * dir;
Expand All @@ -383,7 +425,7 @@ char* mime_type_get_desc( const char* type, const char* locale )
#endif
if ( acc != -1 )
{
desc = _mime_type_get_desc( file_path, locale );
desc = _mime_type_get_desc( file_path, locale, get_icon );
if ( desc )
return desc;
}
Expand All @@ -403,7 +445,7 @@ char* mime_type_get_desc( const char* type, const char* locale )
#endif
if ( acc != -1 )
{
desc = _mime_type_get_desc( file_path, locale );
desc = _mime_type_get_desc( file_path, locale, get_icon );
if( G_LIKELY(desc) )
return desc;
}
Expand Down
5 changes: 3 additions & 2 deletions src/mime-type/mime-type.h
Expand Up @@ -111,11 +111,12 @@ char** mime_type_get_alias( const char* type );
//const char* mime_type_get_type( MimeInfo* info );

/*
* Get human-readable description of the mime-type
* Get human-readable description (or icon) of the mime-type
* If locale is NULL, current locale will be used.
* The returned string should be freed when no longer used.
*/
char* mime_type_get_desc( const char* type, const char* locale );
char* mime_type_get_desc( const char* type, const char* locale,
gboolean get_icon );

/*
* Iterate through all mime caches
Expand Down
2 changes: 1 addition & 1 deletion src/ptk/ptk-file-menu.c
Expand Up @@ -1964,7 +1964,7 @@ void app_job( GtkWidget* item, GtkWidget* app_item )
g_free( msg );

// need to create
msg = g_strdup_printf( "<?xml version='1.0' encoding='utf-8'?>\n<mime-info xmlns='http://www.freedesktop.org/standards/shared-mime-info'>\n<mime-type type='%s'>\n\n<!-- This file was generated by SpaceFM to allow you to change the name of the\n above mime type and to change the filename or magic patterns that define\n this type.\n \n IMPORTANT: After saving this file, restart SpaceFM. You may need to run:\n update-mime-database ~/.local/share/mime\n\n Delete this file from ~/.local/share/mime/packages/ to revert to default.\n \n To make this definition file apply to all users, copy this file to \n /usr/share/mime/packages/ and: sudo update-mime-database /usr/share/mime\n\n For help editing this file:\n http://library.gnome.org/admin/system-admin-guide/stable/mimetypes-source-xml.html.en\n http://www.freedesktop.org/wiki/Specifications/AddingMIMETutor\n\n Example to define the name of a PNG file (with optional translations):\n\n <comment>Portable Network Graphics file</comment>\n <comment xml:lang=\"en\">Portable Network Graphics file</comment>\n \n Example to detect PNG files by glob pattern:\n\n <glob pattern=\"*.png\"/>\n\n Example to detect PNG files by file contents:\n\n <magic priority=\"50\">\n <match type=\"string\" value=\"\\x89PNG\" offset=\"0\"/> \n </magic>\n-->", mime_type->type );
msg = g_strdup_printf( "<?xml version='1.0' encoding='utf-8'?>\n<mime-info xmlns='http://www.freedesktop.org/standards/shared-mime-info'>\n<mime-type type='%s'>\n\n<!-- This file was generated by SpaceFM to allow you to change the name of the\n above mime type and to change the filename or magic patterns that define\n this type.\n \n IMPORTANT: After saving this file, restart SpaceFM. You may need to run:\n update-mime-database ~/.local/share/mime\n\n Delete this file from ~/.local/share/mime/packages/ to revert to default.\n \n To make this definition file apply to all users, copy this file to \n /usr/share/mime/packages/ and: sudo update-mime-database /usr/share/mime\n\n For help editing this file:\n http://standards.freedesktop.org/shared-mime-info-spec/latest/ar01s02.html\n http://www.freedesktop.org/wiki/Specifications/AddingMIMETutor\n\n Example to define the name of a PNG file (with optional translations):\n\n <comment>Portable Network Graphics file</comment>\n <comment xml:lang=\"en\">Portable Network Graphics file</comment>\n \n Example to detect PNG files by glob pattern:\n\n <glob pattern=\"*.png\"/>\n\n Example to detect PNG files by file contents:\n\n <magic priority=\"50\">\n <match type=\"string\" value=\"\\x89PNG\" offset=\"0\"/> \n </magic>\n-->", mime_type->type );

// build from /usr/share/mime type ?
char* contents = NULL;
Expand Down
2 changes: 1 addition & 1 deletion src/settings.c
Expand Up @@ -1521,7 +1521,7 @@ void load_settings( char* config_dir )
xset_free( old_set );
}
}
if ( ver < 33 ) // < 1.0.2
if ( ver < 33 ) // also < 1.0.2
{
// Default Mount ISO file handler has new Run As Task option enabled
set = xset_is( "hand_f_+iso" );
Expand Down
95 changes: 57 additions & 38 deletions src/vfs/vfs-mime-type.c
Expand Up @@ -251,45 +251,62 @@ GdkPixbuf* vfs_mime_type_get_icon( VFSMimeType* mime_type, gboolean big )
return icon ? g_object_ref( icon ) : NULL;
}

sep = strchr( mime_type->type, '/' );
if ( sep )
// get icon from freedesktop XML
char* xml_icon = mime_type_get_desc( mime_type->type, NULL, TRUE );
if ( xml_icon )
{
/* 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 ) )
if ( xml_icon[0] )
icon = vfs_load_icon( icon_theme, xml_icon, size );
g_free( xml_icon );
}

if ( !icon )
{
sep = strchr( mime_type->type, '/' );
if ( sep )
{
strncpy( icon_name, mime_type->type, ( sep - mime_type->type ) );
icon_name[ (sep - mime_type->type) ] = '\0';
strcat( icon_name, "-x-generic" );
/* 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 );
}
}
}

Expand Down Expand Up @@ -381,12 +398,14 @@ const char* vfs_mime_type_get_description( VFSMimeType* mime_type )
{
if ( G_UNLIKELY( ! mime_type->description ) )
{
mime_type->description = mime_type_get_desc( mime_type->type, NULL );
mime_type->description = mime_type_get_desc( mime_type->type, NULL,
FALSE );
/* FIXME: should handle this better */
if ( G_UNLIKELY( ! mime_type->description || ! *mime_type->description ) )
{
g_warning( "mime-type %s has no desc", mime_type->type );
mime_type->description = mime_type_get_desc( XDG_MIME_TYPE_UNKNOWN, NULL );
mime_type->description = mime_type_get_desc( XDG_MIME_TYPE_UNKNOWN,
NULL, FALSE );
}
}
return mime_type->description;
Expand Down

0 comments on commit dd1db2c

Please sign in to comment.