[baobab/wip/vala: 53/65] Decouple volume monitoring logic from its UI representation



commit c6c53e201414709fc079de9a004a21bb4c0fdb65
Author: Stefano Facchini <stefano facchini gmail com>
Date:   Sat Mar 31 14:11:51 2012 +0200

    Decouple volume monitoring logic from its UI representation
    
    Introduce a new class LocationMonitor giving a GList of locations,
    instead of using directly GtkListStore. This is more flexible and will
    allow to implement a custom view for the volume list, to match the new
    design.

 src/baobab-volume-list.vala |  209 ++++++++++++++++++++++++++-----------------
 src/baobab-window.vala      |   27 +++---
 2 files changed, 142 insertions(+), 94 deletions(-)
---
diff --git a/src/baobab-volume-list.vala b/src/baobab-volume-list.vala
index 77eeb2e..e41eb59 100644
--- a/src/baobab-volume-list.vala
+++ b/src/baobab-volume-list.vala
@@ -1,62 +1,73 @@
 namespace Baobab {
-	public class VolumeList : Gtk.ListStore {
-		public enum Columns {
-			NAME,
-			MOUNT_POINT,
-			SIZE_LABEL,
-			USAGE_PERCENT,
-			USAGE_LABEL,
-			ICON,
-			UDISKS_OBJECT,
-			COLUMNS
+	public class Location : Object {
+		public string name { get; private set; }
+		public string? mount_point { get; private set; }
+		public uint64? size { get; private set; }
+		public uint64? used { get; private set; }
+		public Icon? icon { get; private set; }
+		public UDisks.Object? udisks_volume { get; private set; }
+
+		public Location (string name_,
+				 string? mount_point_,
+				 uint64? size_,
+				 uint64? used_,
+				 Icon? icon_,
+				 UDisks.Object? udisks_volume_) {
+			name = name_;
+			mount_point = mount_point_;
+			size = size_;
+			used = used_;
+			icon = icon_;
+			udisks_volume = udisks_volume_;
 		}
 
+		public void mount () throws Error {
+			if (mount_point != null)
+				return;
+
+			string mount_point_;
+			var fs = udisks_volume.get_filesystem ();
+			fs.call_mount_sync (new GLib.Variant ("a{sv}", null), out mount_point_, null);
+			mount_point = mount_point_;
+		}
+	}
+
+	public class LocationMonitor {
 		private UDisks.Client client = null;
 		private VolumeMonitor monitor;
 
-		public VolumeList () {
-			set_column_types (new Type[] {
-					  typeof (string),   // NAME
-					  typeof (string),   // MOUNT_POINT
-					  typeof (string),   // SIZE_LABEL
-					  typeof (int),      // USAGE_PERCENT
-					  typeof (string),   // USAGE_LABEL
-					  typeof (Icon),     // ICON
-					  typeof (Object)}); // UDISKS_OBJECT
+		public signal void changed ();
 
-			try {
-				client = new UDisks.Client.sync (null);
-				client.changed.connect(() => { update (); });
-			} catch (Error e) {
-			}
+		public LocationMonitor () throws Error {
+			client = new UDisks.Client.sync (null);
+			client.changed.connect(() => { changed (); });
 
 			monitor = VolumeMonitor.get ();
-			monitor.mount_changed.connect ((mount) => { update (); });
-			monitor.mount_removed.connect ((mount) => { update (); });
-			monitor.mount_added.connect ((mount) => { update (); });
-
-			update ();
+			monitor.mount_changed.connect ((mount) => { changed (); });
+			monitor.mount_removed.connect ((mount) => { changed (); });
+			monitor.mount_added.connect ((mount) => { changed (); });
 		}
 
+
 		protected static const string FS_ATTRIBUTES =
 			FileAttribute.FILESYSTEM_SIZE + "," +
 			FileAttribute.FILESYSTEM_USED;
 
-		private void compute_usage (File file, ref uint64? size, ref int percent) {
+		private void compute_usage (File file, ref uint64? size, ref uint64? used) {
 			try {
 				var info = file.query_filesystem_info (FS_ATTRIBUTES, null);
 				if (size == null && info.has_attribute (FileAttribute.FILESYSTEM_SIZE))
 					size = info.get_attribute_uint64 (FileAttribute.FILESYSTEM_SIZE);
-				if (size != null && size > 0 && info.has_attribute (FileAttribute.FILESYSTEM_USED)) {
-					var used = info.get_attribute_uint64 (FileAttribute.FILESYSTEM_USED);
-					percent = (int) ((double) used / size * 100);
-				}
+				if (info.has_attribute (FileAttribute.FILESYSTEM_USED))
+					used = info.get_attribute_uint64 (FileAttribute.FILESYSTEM_USED);
 			} catch (Error e) {
 			}
 		}
 
-		private void update () {
-			clear ();
+		public List<Location> get_locations () {
+			List<Location> list = null;
+
+			var mount_points = new HashTable<string, unowned string> (str_hash, str_equal);
 
 			var pretty_names = new HashTable<string, string> (str_hash, str_equal);
 			var icons = new HashTable<string, Icon> (str_hash, str_equal);
@@ -75,8 +86,6 @@ namespace Baobab {
 				}
 			}
 
-			Gtk.TreeIter iter;
-
 			var dbus_objects = client.get_object_manager ().get_objects ();
 			foreach (var dbus_object in dbus_objects) {
 				UDisks.Object volume = (UDisks.Object) dbus_object;
@@ -85,68 +94,104 @@ namespace Baobab {
 				if (block == null || block.hint_ignore || volume.get_filesystem () == null)
 					continue;
 
-				append (out iter);
-
 				uint64? size = block.size;
+				uint64? used = null;
 
 				var mount_point = volume.get_filesystem ().mount_points[0];
-				int percent = -1;
 				if (mount_point != null) {
 					var file = File.new_for_path (mount_point);
-					compute_usage (file, ref size, ref percent);
+					compute_usage (file, ref size, ref used);
+
+					mount_points.add (mount_point);
 				}
 
-				if (mount_point != null && percent != -1)
-					set (iter, Columns.USAGE_PERCENT, percent);
-				else
-					set (iter, Columns.USAGE_LABEL, _("Unknown"));
+				var icon = icons.lookup (block.device);
+				var pretty_name = pretty_names.lookup (block.device);
+				var name = pretty_name != null ? pretty_name : block.device;
 
-				var name = block.device;
-				var icon = icons.lookup (name);
-				name = pretty_names.lookup (name);
 				if (mount_point == "/") {
 					name = _("Main volume");
 					icon = new ThemedIcon ("drive-harddisk-system");
 				}
 
-				set (iter,
-				     Columns.NAME, name,
-				     Columns.SIZE_LABEL, format_size (size),
-				     Columns.MOUNT_POINT, mount_point,
-				     Columns.ICON, icon,
-				     Columns.UDISKS_OBJECT, volume);
+				var location = new Location (name,
+							     mount_point,
+							     size,
+							     used,
+							     icon,
+							     volume);
+				list.append (location);
 			}
 
 			foreach (var mount in monitor.get_mounts ()) {
-				bool found = false;
 				var mount_point = mount.get_root ().get_path ();
 
-				get_iter_first (out iter);
-				do {
-					string other_mount;
-					get (iter, Columns.MOUNT_POINT, out other_mount);
-					if (mount_point == other_mount) {
-						found = true;
-						break;
-					}
-				} while (iter_next (ref iter));
-
-				if (!found) {
-					append (out iter);
-					set (iter,
-					     Columns.NAME, mount.get_name (),
-					     Columns.MOUNT_POINT, mount_point,
-					     Columns.ICON, mount.get_icon ());
-
-					int percent = -1;
-					uint64? size = null;
-					compute_usage (mount.get_root (), ref size, ref percent);
-					if (size != null)
-						set (iter, Columns.SIZE_LABEL, format_size (size));
-					if (percent != -1)
-						set (iter, Columns.USAGE_PERCENT, percent);
-					else
-						set (iter, Columns.USAGE_LABEL, _("Unknown"));
+				if (mount_point in mount_points)
+					continue;
+
+				uint64? size = null;
+				uint64? used = null;
+				compute_usage (mount.get_root (), ref size, ref used);
+
+				var location = new Location (mount.get_name (),
+							     mount_point,
+							     size,
+							     used,
+							     mount.get_icon (),
+							     null);
+				list.append (location);
+			}
+
+			return list;
+		}
+	}
+
+	public class VolumeList : Gtk.ListStore {
+		public enum Columns {
+			NAME,
+			MOUNT_POINT,
+			SIZE_LABEL,
+			USAGE_PERCENT,
+			USAGE_LABEL,
+			ICON,
+			LOCATION,
+			COLUMNS
+		}
+
+		public VolumeList () {
+			set_column_types (new Type[] {
+					  typeof (string),   // NAME
+					  typeof (string),   // MOUNT_POINT
+					  typeof (string),   // SIZE_LABEL
+					  typeof (int),      // USAGE_PERCENT
+					  typeof (string),   // USAGE_LABEL
+					  typeof (Icon),     // ICON
+					  typeof (Object)}); // LOCATION
+		}
+
+		public void update (List<Location> locations) {
+			clear ();
+
+			Gtk.TreeIter iter;
+
+			foreach (var location in locations) {
+				append (out iter);
+
+				set (iter,
+				     Columns.NAME, location.name,
+				     Columns.MOUNT_POINT, location.mount_point,
+				     Columns.ICON, location.icon,
+				     Columns.LOCATION, location);
+
+				if (location.size != null)
+					set (iter, Columns.SIZE_LABEL, format_size (location.size));
+
+				// Assuming that location.used != null implies location.size != null
+				if (location.used != null) {
+					var percent = (int) ((double) location.used / location.size * 100);
+					set (iter, Columns.USAGE_PERCENT, percent);
+				} else {
+					set (iter, Columns.USAGE_LABEL, _("Unknown"));
 				}
 			}
 		}
diff --git a/src/baobab-window.vala b/src/baobab-window.vala
index 828ef14..2fbce43 100644
--- a/src/baobab-window.vala
+++ b/src/baobab-window.vala
@@ -311,8 +311,15 @@ namespace Baobab {
 			var mount_renderer = builder.get_object ("mount-renderer") as Gtk.CellRendererText;
 			var scan_button = builder.get_object ("scan-button") as Gtk.Button;
 
-			VolumeList volumes = new VolumeList ();
-			volume_treeview.model = volumes;
+			var location_monitor = new LocationMonitor ();
+			var model = new VolumeList ();
+
+			location_monitor.changed.connect (() => {
+				model.update (location_monitor.get_locations ());
+			});
+			model.update (location_monitor.get_locations ());
+
+			volume_treeview.model = model;
 
 			mount_column.set_cell_data_func (mount_renderer, (layout, cell, model, iter) => {
 				string? mount_point = null;
@@ -325,20 +332,16 @@ namespace Baobab {
 					Gtk.TreePath path = volume_treeview.get_selection ().get_selected_rows (null).data;
 					Gtk.TreeIter iter;
 
-					volumes.get_iter (out iter, path);
+					model.get_iter (out iter, path);
 
-					string? mount_point = null;
-					volumes.get (iter, VolumeList.Columns.MOUNT_POINT, out mount_point);
+					Location location;
+					model.get (iter, VolumeList.Columns.LOCATION, out location);
 
-					if (mount_point == null) {
-						UDisks.Object volume;
-						volumes.get (iter, VolumeList.Columns.UDISKS_OBJECT, out volume);
-						var fs = volume.get_filesystem ();
-						fs.call_mount_sync (new GLib.Variant ("a{sv}", null), out mount_point, null);
-					}
+					location.mount ();
 
 					set_ui_page (UIPage.RESULT);
-					scan_directory (File.new_for_path (mount_point), ScanFlags.EXCLUDE_MOUNTS);
+					scan_directory (File.new_for_path (location.mount_point),
+							ScanFlags.EXCLUDE_MOUNTS);
 				} catch (Error e) {
 					message (_("Could not analyze volume."), e.message, Gtk.MessageType.ERROR);
 				}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]