From 63dd27c4f593fd7c75aa9508a5ff6d0745762ff4 Mon Sep 17 00:00:00 2001 From: Giovanni Campagna Date: Mon, 23 May 2011 23:25:02 +0200 Subject: [PATCH] drive-menu: rework to use PlacesManager from the Shell Rewrite to use similar code to that used by places-menu, and the mounts shown by searching in the overview. Should fix the issue in bug #650076 that prevented remounting the drives after ejecting, and should be compatible with what Nautilus does by default. --- extensions/drive-menu/extension.js | 158 +++++------------------------ 1 file changed, 23 insertions(+), 135 deletions(-) diff --git a/extensions/drive-menu/extension.js b/extensions/drive-menu/extension.js index bda87066..20c78b46 100644 --- a/extensions/drive-menu/extension.js +++ b/extensions/drive-menu/extension.js @@ -12,22 +12,20 @@ const Panel = imports.ui.panel; const PanelMenu = imports.ui.panelMenu; const PopupMenu = imports.ui.popupMenu; -function DriveMenuItem(drive) { - this._init(drive); +function DriveMenuItem(place) { + this._init(place); } DriveMenuItem.prototype = { __proto__: PopupMenu.PopupBaseMenuItem.prototype, - _init: function(drive) { + _init: function(place) { PopupMenu.PopupBaseMenuItem.prototype._init.call(this); - this.label = new St.Label(); - this.addActor(this.label); + this.place = place; - this.drive = drive; - this._driveChangedId = this.drive.connect('changed', Lang.bind(this, this._updatePrimaryVolume)); - this._updatePrimaryVolume(); + this.label = new St.Label({ text: place.name }); + this.addActor(this.label); let ejectIcon = new St.Icon({ icon_name: 'media-eject', icon_type: St.IconType.SYMBOLIC, @@ -37,92 +35,12 @@ DriveMenuItem.prototype = { this.addActor(ejectButton); }, - _updatePrimaryVolume: function() { - // this should never fail, for the kind of GDrives we support - this._volumes = this.drive.get_volumes(); - - if (this._volumes && this._volumes.length) { - // any better idea, in case an external USB drive is partitioned? - this._primaryVolume = this._volumes[0]; - this.label.text = this._primaryVolume.get_name(); - } else { - this._primaryVolume = null; - this.label.text = this.drive.get_name(); - } - }, - _eject: function() { - if (this.drive.can_eject()) - this.drive.eject_with_operation(Gio.MountUnmountFlags.NONE, - null, // Gio.MountOperation - null, // Gio.Cancellable - Lang.bind(this, this._ejectFinish)); - else - this.drive.stop(Gio.MountUnmountFlags.NONE, - null, // Gio.MountOperation - null, // Gio.Cancellable - Lang.bind(this, this._stopFinish)); - }, - - _stopFinish: function(drive, result) { - try { - drive.stop_finish(result); - } catch(e) { - this._reportFailure(e); - } - }, - - _ejectFinish: function(drive, result) { - try { - drive.eject_with_operation_finish(result); - } catch(e) { - this._reportFailure(e); - } - }, - - _reportFailure: function(exception) { - let msg = _("Ejecting drive '%s' failed:").format(this.drive.get_name()); - Main.notifyError(msg, exception.message); - }, - - _launchMount: function(mount) { - let root = mount.get_root(); - // most of times will be nautilus, but it can change depending of volume contents - let appInfo = root.query_default_handler(null); - appInfo.launch([root], new Gio.AppLaunchContext()); - }, - - destroy: function() { - if (this._driveChangedId) { - this.drive.disconnect(this._driveChangedId); - this._driveChangedId = 0; - } - - PopupMenu.PopupBaseMenuItem.prototype.destroy.call(this); + this.place.remove(); }, activate: function(event) { - if (!this._primaryVolume) { - // can't do anything - PopupMenu.PopupBaseMenuItem.prototype.activate.call(this, event); - return; - } - - let mount = this._primaryVolume.get_mount(); - if (mount) { - this._launchMount(mount); - } else { - // try mounting the volume - this._primaryVolume.mount(Gio.MountMountFlags.NONE, null, null, Lang.bind(this, function(volume, result) { - try { - volume.mount_finish(result); - this._launchMount(volume.get_mount()); - } catch(e) { - let msg = _("Mounting drive '%s' failed:").format(this.drive.get_name()); - Main.notifyError(msg, e.message); - } - })); - } + this.place.launch({ timestamp: event.get_time() }); PopupMenu.PopupBaseMenuItem.prototype.activate.call(this, event); } @@ -139,19 +57,13 @@ DriveMenu.prototype = { // is 'media-eject' better? PanelMenu.SystemStatusButton.prototype._init.call(this, 'media-optical'); - this._monitor = Gio.VolumeMonitor.get(); - this._monitor.connect('drive-connected', Lang.bind(this, function(monitor, drive) { - this._addDrive(drive); - this._updateMenuVisibility(); - })); - this._monitor.connect('drive-disconnected', Lang.bind(this, function(monitor, drive) { - this._removeDrive(drive); - this._updateMenuVisibility(); - })); + this._manager = Main.placesManager; + this._manager.connect('mounts-updated', Lang.bind(this, this._update)); - this._drives = [ ]; + this._contentSection = new PopupMenu.PopupMenuSection(); + this.menu.addMenuItem(this._contentSection); - this._monitor.get_connected_drives().forEach(Lang.bind(this, this._addDrive)); + this._update(); this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); this.menu.addAction(_("Open file manager"), function(event) { @@ -159,46 +71,22 @@ DriveMenu.prototype = { let app = appSystem.get_app('nautilus.desktop'); app.activate(-1); }); - - this._updateMenuVisibility(); }, - _isDriveInteresting: function(drive) { - // We show only drives that are physically removable - // (no network drives, no lvm/mdraid, no optical drives) - return drive.can_stop() && drive.get_start_stop_type() == Gio.DriveStartStopType.SHUTDOWN; - }, + _update: function() { + this._contentSection.removeAll(); - _addDrive: function(drive) { - if (!this._isDriveInteresting(drive)) - return; - - let item = new DriveMenuItem(drive); - this._drives.unshift(item); - this.menu.addMenuItem(item, 0); - }, - - _removeDrive: function(drive) { - if (!this._isDriveInteresting(drive)) - return; - - for (let i = 0; i < this._drives.length; i++) { - let item = this._drives[i]; - if (item.drive == drive) { - item.destroy(); - this._drives.splice(i, 1); - return; + let mounts = this._manager.getMounts(); + let any = false; + for (let i = 0; i < mounts.length; i++) { + if (mounts[i].isRemovable()) { + this._contentSection.addMenuItem(new DriveMenuItem(mounts[i])); + any = true; } } - log ('Removing a drive that was never added to the menu'); - }, - _updateMenuVisibility: function() { - if (this._drives.length > 0) - this.actor.show(); - else - this.actor.hide(); - } + this.actor.visible = any; + }, } // Put your extension initialization code here