[Gtk-sharp-list] VfsNodeView
Jeroen Zwartepoorte
jeroen.zwartepoorte at gmail.com
Wed Sep 28 03:16:12 EDT 2005
Hey guys,
I've written a little widget that creates a custom Gtk.TreeView that
displays the same folders/drives/volumes as the FileChooser. See the
attached code & screenshot. Feel free to use the code in other
projects.
The code isn't bug free. Atm it crashes when you try to access the CD
drive when there's no volume mounted. I plan to fix this real soon.
This is also a good example on how to "lazy load" he nodes in a
treeview.
I propose using this widget in MonoDevelop instead of the current
filebrowser widget. Comments?
Jeroen
-------------- next part --------------
A non-text attachment was scrubbed...
Name: Screenshot-VfsNodeView.png
Type: image/png
Size: 33880 bytes
Desc: not available
Url : http://lists.ximian.com/pipermail/gtk-sharp-list/attachments/20050928/547b4d9f/Screenshot-VfsNodeView-0001.png
-------------- next part --------------
using Gtk;
using Gnome.Vfs;
using System;
using System.Collections;
using System.Runtime.InteropServices;
namespace Utils {
public class VfsNodeView : TreeView {
internal enum NodeType {
Desktop,
Home,
Uri,
Volume,
Drive,
Loading
}
internal class NodeData : IComparable {
private static NodeData emptyNode = null;
private NodeType type;
private Gnome.Vfs.Uri uri;
private Drive drive;
private Gnome.Vfs.FileInfo info;
private Volume volume;
private string shortName;
public static NodeData Empty {
get {
if (emptyNode == null)
emptyNode = new NodeData (NodeType.Loading, null);
return emptyNode;
}
}
public NodeData (Gnome.Vfs.Uri uri) : this (NodeType.Uri, uri) {}
public NodeData (NodeType type, Gnome.Vfs.Uri uri)
{
this.type = type;
this.uri = uri;
}
public NodeData (Drive drive)
{
type = NodeType.Drive;
this.drive = drive;
if (drive.ActivationUri == null)
uri = new Gnome.Vfs.Uri (drive.DevicePath);
else
uri = new Gnome.Vfs.Uri (drive.ActivationUri);
}
public NodeData (Gnome.Vfs.Uri uri, Gnome.Vfs.FileInfo info)
{
type = NodeType.Uri;
this.uri = uri;
this.info = info;
}
public NodeData (Volume volume)
{
type = NodeType.Volume;
this.uri = new Gnome.Vfs.Uri (volume.ActivationUri);
this.volume = volume;
}
public NodeType NodeType {
get {
return type;
}
}
public Gnome.Vfs.Uri Uri {
get {
return uri;
}
}
public Drive Drive {
get {
return drive;
}
}
public Gnome.Vfs.FileInfo FileInfo {
get {
if (uri != null && info == null)
info = uri.GetFileInfo (FileInfoOptions.Default |
FileInfoOptions.GetMimeType);
return info;
}
}
public Volume Volume {
get {
return volume;
}
}
public string ShortName {
get {
if (uri != null && shortName == null)
shortName = uri.ExtractShortName ();
return shortName;
}
}
public int CompareTo (object obj)
{
NodeData node = obj as NodeData;
if (type == node.NodeType) {
if (FileInfo.Type == node.FileInfo.Type) {
return String.Compare (ShortName, node.ShortName, true);
} else {
return info.Type == FileType.Directory ? -1 : 1;
}
} else {
return type.CompareTo (node.NodeType);
}
}
}
private TreeStore store = null;
private TreeModelFilter filter;
private Gtk.IconTheme theme = null;
private int iconSize;
private Hashtable iconCache = null;
private Gnome.Vfs.Uri desktopUri;
private Gnome.Vfs.Uri homeUri;
public VfsNodeView () : base ()
{
if (!Vfs.Initialized)
Vfs.Initialize ();
theme = Gtk.IconTheme.GetForScreen (Screen);
int width, height;
Settings settings = Settings.GetForScreen (Screen);
Gtk.Icon.SizeLookupForSettings (settings, IconSize.Menu, out width, out height);
iconSize = Math.Max (width, height);
PopulateStore ();
store.SetSortFunc (0, new TreeIterCompareFunc (SortFunc));
store.SetSortColumnId (0, SortType.Ascending);
filter = new TreeModelFilter (store, null);
filter.VisibleFunc = new TreeModelFilterVisibleFunc (FilterVisibleFunc);
Model = filter;
HeadersVisible = false;
RowExpanded += new RowExpandedHandler (OnRowExpanded);
TreeViewColumn column = new TreeViewColumn ();
CellRenderer renderer = new CellRendererPixbuf ();
column.PackStart (renderer, false);
column.SetCellDataFunc (renderer, new TreeCellDataFunc (IconDataFunc));
renderer = new CellRendererText ();
column.PackEnd (renderer, true);
column.SetCellDataFunc (renderer, new TreeCellDataFunc (TextDataFunc));
AppendColumn (column);
}
private bool FilterVisibleFunc (TreeModel model, TreeIter iter)
{
NodeData node = (NodeData) store.GetValue (iter, 0);
// Why is node null sometimes?
if (node == null)
return true;
if (node.NodeType == NodeType.Loading)
return true;
else
// FIXME: Make show hidden files an option.
return !node.ShortName.StartsWith (".");
}
private int SortFunc (TreeModel model, TreeIter a, TreeIter b)
{
NodeData nodeA = (NodeData) store.GetValue (a, 0);
NodeData nodeB = (NodeData) store.GetValue (b, 0);
return nodeA.CompareTo (nodeB);
}
private void OnRowExpanded (object o, RowExpandedArgs args)
{
TreeIter iter = filter.ConvertIterToChildIter (args.Iter);
NodeData node = (NodeData) store.GetValue (iter, 0);
TreeIter childIter;
store.IterChildren (out childIter, iter);
NodeData child = (NodeData)store.GetValue (childIter, 0);
if (child.NodeType == NodeType.Loading) {
Gnome.Vfs.FileInfo[] entries = Directory.GetEntries (node.Uri,
FileInfoOptions.Default | FileInfoOptions.GetMimeType);
foreach (FileInfo info in entries) {
// Skip "." and "..".
if (info.Name.Equals (".") || info.Name.Equals (".."))
continue;
child = new NodeData (node.Uri.AppendPath (info.Name), info);
TreeIter nodeIter = store.AppendValues (iter, child);
if (info.Type == FileType.Directory)
store.AppendValues (nodeIter, NodeData.Empty);
}
store.Remove (ref childIter);
}
}
private Gdk.Pixbuf GetCachedIcon (string icon)
{
if (iconCache == null)
iconCache = new Hashtable ();
if (!iconCache.Contains (icon)) {
Gdk.Pixbuf pixbuf = theme.LoadIcon (icon, iconSize, 0);
if (pixbuf != null)
iconCache.Add (icon, pixbuf);
return pixbuf;
} else {
return (Gdk.Pixbuf)iconCache[icon];
}
}
[DllImport ("gnomeui-2")]
private static extern string gnome_icon_lookup (IntPtr icon_theme,
IntPtr thumbnail_factory,
string file_uri,
string custom_icon,
IntPtr file_info,
string mimetype,
Gnome.IconLookupFlags flags,
out Gnome.IconLookupResultFlags result);
private void IconDataFunc (TreeViewColumn column, CellRenderer cell, TreeModel model, TreeIter iter)
{
CellRendererPixbuf renderer = cell as CellRendererPixbuf;
NodeData node = (NodeData) filter.GetValue (iter, 0);
switch (node.NodeType) {
case NodeType.Drive:
if (node.Drive.IsMounted) {
Volume volume = node.Drive.MountedVolume;
renderer.Pixbuf = GetCachedIcon (volume.Icon);
} else {
renderer.Pixbuf = GetCachedIcon (node.Drive.Icon);
}
break;
case NodeType.Loading:
renderer.Pixbuf = null;
break;
case NodeType.Volume:
string uri = node.Volume.ActivationUri;
if (uri.StartsWith ("file:///"))
renderer.Pixbuf = GetCachedIcon ("gnome-dev-harddisk");
else
renderer.Pixbuf = GetCachedIcon (node.Volume.Icon);
break;
default:
string icon = null;
if (node.Uri.Equals (desktopUri)) {
icon = "gnome-fs-desktop";
} else if (node.Uri.Equals (homeUri)) {
icon = "gnome-fs-home";
} else {
Gnome.IconLookupResultFlags result;
icon = gnome_icon_lookup (theme.Handle, IntPtr.Zero,
null, null,
node.FileInfo.Handle,
node.FileInfo.MimeType,
0, out result);
}
renderer.Pixbuf = GetCachedIcon (icon);
break;
}
}
private void TextDataFunc (TreeViewColumn column, CellRenderer cell, TreeModel model, TreeIter iter)
{
CellRendererText renderer = cell as CellRendererText;
NodeData node = (NodeData) filter.GetValue (iter, 0);
switch (node.NodeType) {
case NodeType.Drive:
renderer.Text = node.Drive.DisplayName;
break;
case NodeType.Home:
renderer.Text = "Home";
break;
case NodeType.Loading:
renderer.Text = "Retrieving file list...";
break;
case NodeType.Volume:
if (node.Volume.ActivationUri.Equals ("file:///"))
renderer.Text = "File System";
else
renderer.Text = node.Volume.DisplayName;
break;
default:
renderer.Text = node.ShortName;
break;
}
}
private void AddRootNode (NodeData node)
{
TreeIter iter = store.AppendValues (node);
store.AppendValues (iter, NodeData.Empty);
}
private void PopulateStore ()
{
if (store != null)
return;
store = new TreeStore (typeof (NodeData));
// Add both the Desktop and Home custom node types.
desktopUri = new Gnome.Vfs.Uri (Environment.GetFolderPath (Environment.SpecialFolder.Desktop));
homeUri = new Gnome.Vfs.Uri (Environment.GetFolderPath (Environment.SpecialFolder.Personal));
AddRootNode (new NodeData (NodeType.Desktop, desktopUri));
AddRootNode (new NodeData (NodeType.Home, homeUri));
VolumeMonitor monitor = VolumeMonitor.Get ();
// Add root filesystem.
AddRootNode (new NodeData (monitor.GetVolumeForPath ("/")));
foreach (Drive d in monitor.ConnectedDrives) {
if (d.IsUserVisible) {
AddRootNode (new NodeData (d));
}
}
foreach (Volume v in monitor.MountedVolumes) {
if (v.Drive == null && v.IsUserVisible) {
AddRootNode (new NodeData (v));
}
}
}
}
}
More information about the Gtk-sharp-list
mailing list