public
Last active

An attempt at modifying the default volumes plugin for kupfer to allow it to be more modular (as in only using gio for the unmount checks, which the unmount command actually handles the unmount).

  • Download Gist
volumes_cc.py
Python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
__kupfer_name__ = _("Volumes and Disks (Custom Unmount)")
__kupfer_sources__ = ("VolumesSource", )
__description__ = _("Mounted volumes and disks")
__version__ = ""
__author__ = "Ulrik Sverdrup <ulrik.sverdrup@gmail.com>, Sapphira Armageddos <shadowkyogre.public@gmail.com>"
 
import gio
 
from kupfer.objects import Action, Source, FileLeaf
from kupfer.obj.fileactions import Open, OpenTerminal
from kupfer import utils
from kupfer import plugin_support
from kupfer import pretty
from kupfer.objects import OperationError
 
__kupfer_settings__ = plugin_support.PluginSettings(
{
"key": "command",
"label": _("Command"),
"type": str,
"value": "unmount",
"tooltip": ("The command used to unmount or eject a device.")
},
)
 
class Volume (FileLeaf):
"""
The Volume class actually represents one instance
of GIO's GMount (as long as it is mounted)
"""
# NOTE: marking as non-serializable
serializable = None
 
def __init__(self, volume):
self.volume = volume
fil = self.volume.get_root()
path = fil.get_path()
super(Volume, self).__init__(obj=path, name=volume.get_name())
self.kupfer_add_alias(fil.get_basename())
 
def get_actions(self):
yield Open()
yield OpenTerminal()
if self.volume.can_eject():
yield Eject()
elif self.volume.can_unmount():
yield Unmount()
 
def is_valid(self):
vm = gio.volume_monitor_get()
return any(self.volume == v for v in vm.get_mounts())
 
def get_description(self):
return _("Volume mounted at %s") % \
utils.get_display_path_for_bytestring(self.object)
def get_gicon(self):
return self.volume.get_icon()
def get_icon_name(self):
return "drive-removable-media"
 
class Unmount (Action):
def __init__(self, name=None):
super(Unmount, self).__init__(name or _("Unmount"))
 
def wants_context(self):
return True
def unmount_callback(self, acommand, stdout, stderr, ctx):
"""Show async error if @acommand returns error output & error status.
Else post async result if @post_result.
"""
max_error_msg=512
pretty.print_debug(__name__, "Exited:", acommand)
if acommand.exit_status != 0:
if stderr:
errstr = kupferstring.fromlocale(stderr)[:max_error_msg]
else:
errstr = kupferstring.fromlocale("An unknown error has occurred.")
ctx.register_late_error(OperationError(errstr))
 
def activate(self, leaf, ctx):
if not leaf.is_valid():
return
vol = leaf.volume
if vol.can_eject() or vol.can_unmount():
command = __kupfer_settings__["command"]
argv = utils.argv_for_commandline(command)
argv.append(vol.get_root().get_path())
def finish_callback(acommand, stdout, stderr):
self.unmount_callback(acommand, stdout, stderr, ctx)
utils.AsyncCommand(argv, finish_callback, 15)
 
def get_description(self):
return _("Unmount this volume")
 
def get_icon_name(self):
return "media-eject"
 
class Eject (Unmount):
def __init__(self):
super(Eject, self).__init__(_("Eject"))
 
def get_description(self):
return _("Unmount and eject this media")
 
class VolumesSource (Source):
def __init__(self, name=_("Volumes and Disks")):
super(VolumesSource, self).__init__(name)
def is_dynamic(self):
return True
def get_items(self):
vm = gio.volume_monitor_get()
# get_mounts gets all mounted removable media
return (Volume(v) for v in vm.get_mounts())
 
def get_description(self):
return _("Mounted volumes and disks")
def get_icon_name(self):
return "drive-removable-media"
def provides(self):
yield Volume

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.