1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 // Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
24 // Alexander Olk xenomorph2@onlinehome.de
27 // short "how to" if you want to add an other platform handler, etc:
28 // - first add mime type names and icon names (best is without extension) to MimeIconEngine, for example:
29 // MimeIconEngine.AddMimeTypeAndIconName( "inode/directory", "gnome-fs-directory" );
30 // - next add the icon name (the same as used in AddMimeTypeAndIconName) and the full filename, for example:
31 // MimeIconEngine.AddIcon( "gnome-fs-directory", "/opt/gnome/share/icons/gnome/48x48/filesystems/gnome-fs-directory.png" );
32 // AddIcon adds the icon to the image lists SmallIconList and LargeIconList
33 // - provide always a "unknown/unknown" 'mime type' with a default icon for unkown mime types,
34 // "desktop/desktop" 'mime type' for the desktop icon, "directory/home" 'mime type for the home dir of the user and so on
35 // (look at the default platform handler)
38 // public static int GetIconIndexForFile( string full_filename )
39 // public static int GetIconIndexForMimeType( string mime_type )
40 // to get the image index in MimeIconEngine.SmallIcons and MimeIconEngine.LargeIcons
42 // public static Image GetIconForMimeTypeAndSize( string mime_type, Size size )
43 // to get the image itself for a mime type with a specific size
47 using System.Collections;
48 using System.Collections.Specialized;
52 namespace System.Windows.Forms
54 internal enum MimeExtensionHandlerStatus
63 internal enum EPlatformHandler
71 internal class MimeIconEngine
73 public static ImageList SmallIcons = new ImageList();
74 public static ImageList LargeIcons = new ImageList();
76 private static PlatformMimeIconHandler platformMimeHandler = null;
78 private static EPlatformHandler platform = EPlatformHandler.Default;
80 private static Hashtable MimeTypeIconIndexHash = new Hashtable();
82 private static NameValueCollection IconNameMimeTypeNameValueCollection = new NameValueCollection();
84 private static StringCollection added_icons = new StringCollection();
86 private static object lock_object = new Object();
88 static MimeIconEngine( )
90 // add some more aliases, kde for example uses other mime type names for some mime types...
91 MimeGenerated.Aliases.Add( "application/x-compressed-tar", "application/x-tgz" );
92 MimeGenerated.Aliases.Add( "application/x-bzip-compressed-tar", "application/x-tbz" );
93 MimeGenerated.Aliases.Add( "application/zip", "application/x-zip" );
94 MimeGenerated.Aliases.Add( "text/x-patch", "text/x-diff" );
96 SmallIcons.ColorDepth = ColorDepth.Depth32Bit;
97 SmallIcons.TransparentColor = Color.Transparent;
98 LargeIcons.ColorDepth = ColorDepth.Depth32Bit;
99 LargeIcons.TransparentColor = Color.Transparent;
101 string session = Environment.GetEnvironmentVariable( "DESKTOP_SESSION" );
103 if ( session != null )
105 session = session.ToUpper( );
107 if ( session == "DEFAULT" )
109 string helper = Environment.GetEnvironmentVariable( "KDE_FULL_SESSION" );
111 if ( helper != null )
115 helper = Environment.GetEnvironmentVariable( "GNOME_DESKTOP_SESSION_ID" );
117 if ( helper != null )
125 Console.WriteLine( "Desktop session is: " + session );
127 if ( session == "KDE" )
129 SmallIcons.ImageSize = new Size( 24, 24 );
130 LargeIcons.ImageSize = new Size( 48, 48 );
132 platformMimeHandler = new KdeHandler( );
133 if ( platformMimeHandler.Start( ) == MimeExtensionHandlerStatus.OK )
135 Console.WriteLine( "Kde icons ready..." );
136 platform = EPlatformHandler.KDE;
138 else // fallback to default
140 MimeIconEngine.LargeIcons.Images.Clear( );
141 MimeIconEngine.SmallIcons.Images.Clear( );
142 platformMimeHandler = new PlatformDefaultHandler( );
143 platformMimeHandler.Start( );
147 if ( session == "GNOME" )
149 SmallIcons.ImageSize = new Size( 24, 24 );
150 LargeIcons.ImageSize = new Size( 48, 48 );
152 platformMimeHandler = new GnomeHandler( );
153 if ( platformMimeHandler.Start( ) == MimeExtensionHandlerStatus.OK )
155 Console.WriteLine( "Gnome icons ready..." );
156 platform = EPlatformHandler.GNOME;
158 else // fallback to default
160 MimeIconEngine.LargeIcons.Images.Clear( );
161 MimeIconEngine.SmallIcons.Images.Clear( );
162 platformMimeHandler = new PlatformDefaultHandler( );
163 platformMimeHandler.Start( );
168 SmallIcons.ImageSize = new Size( 16, 16 );
169 LargeIcons.ImageSize = new Size( 48, 48 );
171 platformMimeHandler = new PlatformDefaultHandler( );
172 platformMimeHandler.Start( );
175 IconNameMimeTypeNameValueCollection = null;
179 public static int GetIconIndexForFile( string full_filename )
183 string mime_type = Mime.GetMimeTypeForFile( full_filename );
185 if ( platform == EPlatformHandler.Default )
187 if ( mime_type == "inode/directory" )
189 return (int)MimeTypeIconIndexHash[ "inode/directory" ];
193 return (int)MimeTypeIconIndexHash[ "unknown/unknown" ];
197 object oindex = GetIconIndex( mime_type );
199 if ( oindex == null )
200 oindex = MimeTypeIconIndexHash[ "unknown/unknown" ];
206 public static int GetIconIndexForMimeType( string mime_type )
210 if ( platform == EPlatformHandler.Default )
212 if ( mime_type == "inode/directory" )
214 return (int)MimeTypeIconIndexHash[ "inode/directory" ];
218 return (int)MimeTypeIconIndexHash[ "unknown/unknown" ];
222 object oindex = GetIconIndex( mime_type );
224 if ( oindex == null )
225 oindex = MimeTypeIconIndexHash[ "unknown/unknown" ];
231 public static Image GetIconForMimeTypeAndSize( string mime_type, Size size )
235 object oindex = GetIconIndex( mime_type );
237 if ( oindex == null )
238 oindex = MimeTypeIconIndexHash[ "unknown/unknown" ];
240 Bitmap bmp = new Bitmap( LargeIcons.Images[ (int)oindex ], size );
246 internal static void AddIcon( string name, string fullname )
248 if ( !CheckIfIconIsNeeded( name ) )
251 if ( added_icons.Contains( name ) )
254 added_icons.Add( name );
256 Bitmap bmp = new Bitmap( fullname );
258 int index = SmallIcons.Images.Add( bmp, Color.Transparent );
259 LargeIcons.Images.Add( bmp, Color.Transparent );
261 AddMimeTypeIconIndexHash( name, index );
264 private static bool CheckIfIconIsNeeded( string name )
266 string mime_types = IconNameMimeTypeNameValueCollection[ name ];
268 if ( mime_types != null )
274 internal static void AddMimeTypeIconIndexHash( string name, int index )
276 string mime_type = IconNameMimeTypeNameValueCollection[ name ];
278 if ( mime_type == null )
281 string[] split = mime_type.Split( new char[] { ',' } );
283 foreach ( string s in split )
285 if ( MimeTypeIconIndexHash.ContainsKey( s ) )
288 MimeTypeIconIndexHash.Add( s, index );
292 internal static void AddIconByImage( string name, Image image )
294 int index = SmallIcons.Images.Add( image, Color.Transparent );
295 LargeIcons.Images.Add( image, Color.Transparent );
297 AddMimeTypeIconIndexHash( name, index );
300 internal static void AddMimeTypeAndIconName( string mimetype, string iconname )
302 if ( iconname.Equals( String.Empty ) )
305 IconNameMimeTypeNameValueCollection.Add( iconname, mimetype );
308 private static object GetIconIndex( string mime_type )
310 object oindex = null;
312 if ( mime_type != null )
314 // first check if mime_type is available in the mimetype/icon hashtable
315 oindex = MimeTypeIconIndexHash[ mime_type ];
317 if ( oindex == null )
319 // it is not available, check if an alias exist for mime_type
320 string alias = Mime.GetMimeAlias( mime_type );
324 string[] split = alias.Split( new char[] { ',' } );
326 foreach ( string s in split )
328 oindex = MimeTypeIconIndexHash[ s ];
330 if ( oindex != null )
335 // if oindex is still null check if mime_type is a sub class of an other mime type
336 if ( oindex == null )
338 string sub_class = MimeGenerated.SubClasses[ mime_type ];
340 if ( sub_class != null )
341 oindex = MimeTypeIconIndexHash[ sub_class ];
350 internal abstract class PlatformMimeIconHandler
352 protected StringCollection mime_paths = new StringCollection();
354 protected StringCollection icon_paths = new StringCollection();
356 protected string icon_theme = "";
358 protected MimeExtensionHandlerStatus mimeExtensionHandlerStatus = MimeExtensionHandlerStatus.OK;
360 public MimeExtensionHandlerStatus MimeExtensionHandlerStatus
363 return mimeExtensionHandlerStatus;
367 public abstract MimeExtensionHandlerStatus Start( );
369 // check, if icon, mime, etc., directories exist
370 protected virtual bool CheckPlatformDirectories( )
376 internal class PlatformDefaultHandler : PlatformMimeIconHandler
378 public override MimeExtensionHandlerStatus Start( )
380 MimeIconEngine.AddMimeTypeAndIconName( "unknown/unknown", "paper" );
381 MimeIconEngine.AddMimeTypeAndIconName( "inode/directory", "folder" );
382 MimeIconEngine.AddMimeTypeAndIconName( "desktop/desktop", "desktop" );
383 MimeIconEngine.AddMimeTypeAndIconName( "directory/home", "folder_with_paper" );
384 MimeIconEngine.AddMimeTypeAndIconName( "network/network", "monitor-planet" );
386 MimeIconEngine.AddIconByImage( "folder", (Image)Locale.GetResource( "folder" ) );
387 MimeIconEngine.AddIconByImage( "paper", (Image)Locale.GetResource( "paper" ) );
388 MimeIconEngine.AddIconByImage( "desktop", (Image)Locale.GetResource( "desktop" ) );
389 MimeIconEngine.AddIconByImage( "folder_with_paper", (Image)Locale.GetResource( "folder_with_paper" ) );
390 MimeIconEngine.AddIconByImage( "monitor-planet", (Image)Locale.GetResource( "monitor-planet" ) );
392 return MimeExtensionHandlerStatus.OK; // return always ok
396 internal class KdeHandler : PlatformMimeIconHandler
398 string full_kdegloabals_filename = Environment.GetFolderPath( Environment.SpecialFolder.Personal )
400 + ".kde/share/config/kdeglobals";
402 public override MimeExtensionHandlerStatus Start( )
404 if ( !ReadKdeglobals( ) )
405 return mimeExtensionHandlerStatus;
407 if ( !CheckPlatformDirectories( ) )
408 return mimeExtensionHandlerStatus;
410 // check if the theme is svg only
411 // if true, use theme "default.kde"
412 // don't know if that is available in every linux distribution
413 // MWF has no svg support yet (cairo's libsvg!?!)
415 icon_theme = "default.kde";
421 return mimeExtensionHandlerStatus;
424 private bool SVGOnly( )
426 // check only the first path in icon_paths
427 if ( icon_paths.Count > 0 )
429 string icon_path = icon_paths[ 0 ] + icon_theme;
430 string[] dirs = Directory.GetDirectories( icon_path );
432 if ( dirs.Length == 1 && dirs[ 0 ] == "scalable" )
439 protected override bool CheckPlatformDirectories( )
441 bool icons_found = false;
444 if ( Directory.Exists( "/opt/kde3/share/icons/default.kde" ) )
446 icon_paths.Add( "/opt/kde3/share/icons" + "/" );
450 if ( Directory.Exists( "/usr/share/icons/default.kde" ) )
452 icon_paths.Add( "/usr/share/icons" + "/" );
456 if ( Directory.Exists( "/usr/local/share/icons/default.kde" ) )
458 icon_paths.Add( "/usr/local/share/icons" + "/" );
464 mimeExtensionHandlerStatus = MimeExtensionHandlerStatus.NO_ICONS;
468 bool mimelnk_found = false;
470 if ( Directory.Exists( "/usr/share/mimelnk" ) )
472 mime_paths.Add( "/usr/share/mimelnk" + "/" );
473 mimelnk_found = true;
476 if ( Directory.Exists( "/usr/local/share/mimelnk" ) )
478 mime_paths.Add( "/usr/local/share/mimelnk" + "/" );
479 mimelnk_found = true;
482 if ( Directory.Exists( "/opt/kde3/share/mimelnk" ) )
484 mime_paths.Add( "/opt/kde3/share/mimelnk" + "/" );
485 mimelnk_found = true;
488 if ( !mimelnk_found )
490 mimeExtensionHandlerStatus = MimeExtensionHandlerStatus.NO_MIMELNK;
497 private void ReadIcons( )
499 foreach ( string icon_path_in in icon_paths )
501 string icon_path = icon_path_in + icon_theme + "/48x48";
503 string[] directories = Directory.GetDirectories( icon_path );
505 foreach ( string d in directories )
507 DirectoryInfo di = new DirectoryInfo( d );
509 FileInfo[] fileinfo = di.GetFiles( );
511 foreach ( FileInfo fi in fileinfo )
513 string name = Path.GetFileNameWithoutExtension( fi.Name );
515 MimeIconEngine.AddIcon( name, fi.FullName );
521 private void ReadMimetypes( )
523 MimeIconEngine.AddMimeTypeAndIconName( "unknown/unknown", "unknown" );
524 MimeIconEngine.AddMimeTypeAndIconName( "desktop/desktop", "desktop" );
525 MimeIconEngine.AddMimeTypeAndIconName( "directory/home", "folder_home" );
526 MimeIconEngine.AddMimeTypeAndIconName( "network/network", "network" );
528 foreach ( string mime_path in mime_paths )
530 string[] directories = Directory.GetDirectories( mime_path );
532 foreach ( string d in directories )
534 string[] files = Directory.GetFiles( d );
536 foreach ( string f in files )
541 // Ignore errors if the file can not be read.
548 private void ReadDotDesktop( string filename )
550 StreamReader sr = new StreamReader( filename );
552 string line = sr.ReadLine( );
554 string icon_name = "";
556 string mime_type = "";
558 bool have_icon = false;
559 bool have_mimetype = false;
561 while ( line != null )
565 if ( line.StartsWith( "Icon" ) )
567 icon_name = line.Substring( line.IndexOf( '=' ) + 1 );
568 icon_name = icon_name.Trim( );
574 if ( line.StartsWith( "MimeType" ) )
576 mime_type = line.Substring( line.IndexOf( '=' ) + 1 );
577 mime_type = mime_type.Trim( );
580 have_mimetype = true;
583 line = sr.ReadLine( );
588 MimeIconEngine.AddMimeTypeAndIconName( mime_type, icon_name );
591 private bool ReadKdeglobals( )
593 if ( !File.Exists( full_kdegloabals_filename ) )
595 mimeExtensionHandlerStatus = MimeExtensionHandlerStatus.NO_KDEGLOBALS;
600 StreamReader sr = new StreamReader( full_kdegloabals_filename );
602 string line = sr.ReadLine( );
604 while ( line != null )
606 if ( line.IndexOf( "[Icons]" ) != -1 )
608 line = sr.ReadLine( );
610 if ( line != null && line.IndexOf( "Theme" ) != -1 )
614 icon_theme = line.Substring( line.IndexOf( '=' ) + 1 );
616 icon_theme = icon_theme.Trim( );
622 line = sr.ReadLine( );
631 // GnomeHandler uses the default gnome icon theme (many others are svg only)
632 internal class GnomeHandler : PlatformMimeIconHandler
634 public override MimeExtensionHandlerStatus Start( )
636 if ( !CheckPlatformDirectories( ) )
637 return mimeExtensionHandlerStatus;
639 CreateMimeTypeFromIconName( );
643 return MimeExtensionHandlerStatus.OK;
646 protected override bool CheckPlatformDirectories( )
648 // add more directories ???
649 if ( Directory.Exists( "/opt/gnome/share/icons/gnome/48x48" ) )
651 icon_paths.Add( "/opt/gnome/share/icons/gnome/48x48/" );
654 if ( Directory.Exists( "/usr/share/icons/gnome/48x48" ) )
656 icon_paths.Add( "/usr/share/icons/gnome/48x48/" );
659 if ( Directory.Exists( "/usr/local/share/icons/gnome/48x48" ) )
661 icon_paths.Add( "/usr/local/share/icons/gnome/48x48/" );
665 mimeExtensionHandlerStatus = MimeExtensionHandlerStatus.NO_ICONS;
672 private void CreateMimeTypeFromIconName( )
674 MimeIconEngine.AddMimeTypeAndIconName( "inode/directory", "gnome-fs-directory" );
675 MimeIconEngine.AddMimeTypeAndIconName( "unknown/unknown", "gnome-fs-regular" );
676 MimeIconEngine.AddMimeTypeAndIconName( "desktop/desktop", "gnome-fs-desktop" );
677 MimeIconEngine.AddMimeTypeAndIconName( "directory/home", "gnome-fs-home" );
678 MimeIconEngine.AddMimeTypeAndIconName( "network/network", "gnome-fs-network" );
680 foreach ( string ip in icon_paths )
682 string[] files = Directory.GetFiles( ip + "mimetypes" );
684 foreach ( string file in files )
686 string extension = Path.GetExtension( file );
688 if ( extension != ".png" )
691 string file_name = Path.GetFileNameWithoutExtension( file );
693 if ( !file_name.StartsWith( "gnome-mime-" ) )
696 StringBuilder mime_type = new StringBuilder( file_name.Replace( "gnome-mime-", "" ) );
698 for ( int i = 0; i < mime_type.Length; i++ )
699 if ( mime_type[ i ] == '-' )
701 mime_type[ i ] = '/';
705 MimeIconEngine.AddMimeTypeAndIconName( mime_type.ToString( ), file_name );
710 private void ReadIcons( )
712 foreach ( string icon_path in icon_paths )
714 string[] directories = Directory.GetDirectories( icon_path );
716 foreach ( string directory in directories )
718 DirectoryInfo di = new DirectoryInfo( directory );
720 FileInfo[] fileinfo = di.GetFiles( );
722 foreach ( FileInfo fi in fileinfo )
724 if ( fi.Extension != ".png" )
727 string name = Path.GetFileNameWithoutExtension( fi.Name );
729 MimeIconEngine.AddIcon( name, fi.FullName );