[kupfer: 29/67] thunar: Implement CopyTo, MoveTo, Update for Thunar 1.2



commit cb649cbed863aac1cef018ac043e73e542fe561b
Author: Ulrik Sverdrup <ulrik sverdrup gmail com>
Date:   Tue Mar 15 22:52:31 2011 +0100

    thunar: Implement CopyTo, MoveTo, Update for Thunar 1.2
    
    Implement Thunar actions CopyTo, MoveTo that are simple & nice
    commands for the user to copy and move files. When these actions are
    not available we show a runtime error "Thunar does not support this
    operation".
    
    The Empty Trash, Show Properties, Show in File Manager actions are all
    special-cased to try both the two-arg version for 1.2 as well as the
    one-argument version for Thunar 1.0

 kupfer/plugin/thunar.py |  142 +++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 138 insertions(+), 4 deletions(-)
---
diff --git a/kupfer/plugin/thunar.py b/kupfer/plugin/thunar.py
index 28a9780..35f900b 100644
--- a/kupfer/plugin/thunar.py
+++ b/kupfer/plugin/thunar.py
@@ -4,6 +4,8 @@ __kupfer_actions__ = (
 	"Reveal",
 	"GetInfo",
 	"SendTo",
+	"CopyTo",
+	"MoveTo",
 )
 __description__ = _("File manager Thunar actions")
 __version__ = ""
@@ -14,13 +16,17 @@ import os
 import dbus
 import gio
 
-from kupfer.objects import Leaf, Action, Source, InvalidDataError
+from kupfer.objects import Leaf, Action, Source
+from kupfer.objects import (InvalidDataError, OperationError, NotAvailableError,
+                            NoMultiError)
 from kupfer.objects import FileLeaf, RunnableLeaf, SourceLeaf, AppLeaf
 from kupfer.obj.apps import AppLeafContentMixin
 from kupfer import config
 from kupfer import plugin_support
 from kupfer import pretty
 from kupfer import utils
+from kupfer import launch
+from kupfer import commandexec
 
 plugin_support.check_dbus_connection()
 
@@ -74,7 +80,14 @@ class Reveal (Action):
 			return
 		uri = parent.get_uri()
 		bname = gfile.get_basename()
-		_get_thunar().DisplayFolderAndSelect(uri, bname, _current_display(),
+		id_ = launch.make_startup_notification_id()
+		try:
+			# Thunar 1.2 Uses $DISPLAY and $STARTUP_ID args
+			_get_thunar().DisplayFolderAndSelect(uri, bname, _current_display(),
+				id_, reply_handler=_dummy, error_handler=_dummy)
+		except TypeError:
+			# Thunar 1.0 Uses $DISPLAY
+			_get_thunar().DisplayFolderAndSelect(uri, bname, _current_display(),
 				reply_handler=_dummy, error_handler=_dummy)
 
 	def item_types(self):
@@ -87,7 +100,14 @@ class GetInfo (Action):
 	def activate(self, leaf):
 		gfile = gio.File(leaf.object)
 		uri = gfile.get_uri()
-		_get_thunar().DisplayFileProperties(uri, _current_display(),
+		id_ = launch.make_startup_notification_id()
+		try:
+			# Thunar 1.2 Uses $DISPLAY and $STARTUP_ID args
+			_get_thunar().DisplayFileProperties(uri, _current_display(),
+				id_, reply_handler=_dummy, error_handler=_dummy)
+		except TypeError:
+			# Thunar 1.0 Uses $DISPLAY
+			_get_thunar().DisplayFileProperties(uri, _current_display(),
 				reply_handler=_dummy, error_handler=_dummy)
 
 	def item_types(self):
@@ -121,13 +141,127 @@ class SendTo (Action):
 	def object_source(self, for_item=None):
 		return _SendToAppsSource()
 
+def _good_destination(dpath, spath):
+	"""If directory path @dpath is a valid destination for file @spath
+	to be copied or moved to. 
+	"""
+	if not os.path.isdir(dpath):
+		return False
+	spath = os.path.normpath(spath)
+	dpath = os.path.normpath(dpath)
+	cpfx = os.path.commonprefix((spath, dpath))
+	if os.path.samefile(dpath, spath) or cpfx == spath:
+		return False
+	return True
+
+def path_to_uri(filepath):
+	return gio.File(filepath).get_uri()
+
+class CopyTo (Action, pretty.OutputMixin):
+	def __init__(self):
+		Action.__init__(self, _("Copy To..."))
+
+	def activate_multiple(self, leaves, iobjects):
+		# Unroll by looping over the destinations,
+		# copying everything into each destination
+		ctx = commandexec.DefaultActionExecutionContext()
+		token = ctx.get_async_token()
+
+		thunar = _get_thunar()
+		display = _current_display()
+		work_dir = os.path.expanduser("~/")
+		notify_id = launch.make_startup_notification_id()
+		sourcefiles = [path_to_uri(L.object) for L in leaves]
+
+		def _reply(*args):
+			self.output_debug("reply got for copying", *args)
+
+		def _reply_error(exc):
+			self.output_debug(exc)
+			ctx.register_late_error(token, NotAvailableError(_("Thunar")))
+
+		for dest_iobj in iobjects:
+			desturi = path_to_uri(dest_iobj.object)
+			thunar.CopyInto(work_dir, sourcefiles, desturi, display, notify_id,
+			                reply_handler=_reply,
+			                error_handler=_reply_error)
+
+	def activate(self, leaf, iobj):
+		return self.activate_multiple([leaf], [iobj])
+
+	def item_types(self):
+		yield FileLeaf
+	def valid_for_item(self, item):
+		return True
+	def requires_object(self):
+		return True
+	def object_types(self):
+		yield FileLeaf
+	def valid_object(self, obj, for_item):
+		return _good_destination(obj.object, for_item.object)
+	def get_description(self):
+		return _("Copy file to a chosen location")
+
+class MoveTo (Action, pretty.OutputMixin):
+	def __init__(self):
+		Action.__init__(self, _("Move To..."))
+
+	def activate_multiple(self, leaves, iobjects):
+		if len(iobjects) != 1:
+			raise NoMultiError()
+
+		ctx = commandexec.DefaultActionExecutionContext()
+		token = ctx.get_async_token()
+
+		def _reply():
+			self.output_debug("reply got for moving")
+
+		def _reply_error(exc):
+			self.output_debug(exc)
+			ctx.register_late_error(token, NotAvailableError(_("Thunar")))
+
+		(dest_iobj,) = iobjects
+		# Move everything into the destination
+		thunar = _get_thunar()
+		display = _current_display()
+		work_dir = os.path.expanduser("~/")
+		notify_id = launch.make_startup_notification_id()
+		sourcefiles = [path_to_uri(L.object) for L in leaves]
+		desturi = path_to_uri(dest_iobj.object)
+		thunar.MoveInto(work_dir, sourcefiles, desturi, display, notify_id,
+		                reply_handler=_reply,
+		                error_handler=_reply_error)
+
+	def activate(self, leaf, iobj):
+		return self.activate_multiple([leaf], [iobj])
+
+	def item_types(self):
+		yield FileLeaf
+	def valid_for_item(self, item):
+		return True
+	def requires_object(self):
+		return True
+	def object_types(self):
+		yield FileLeaf
+	def valid_object(self, obj, for_item):
+		return _good_destination(obj.object, for_item.object)
+	def get_description(self):
+		return _("Move file to new location")
 
 class EmptyTrash (RunnableLeaf):
 	def __init__(self):
 		RunnableLeaf.__init__(self, None, _("Empty Trash"))
 
 	def run(self):
-		_get_thunar_trash().EmptyTrash(_current_display(),
+		id_ = launch.make_startup_notification_id()
+		thunar = _get_thunar_trash()
+		try:
+			# Thunar 1.2 Uses $DISPLAY and $STARTUP_ID args
+			thunar.EmptyTrash(_current_display(), id_,
+				reply_handler=_dummy, error_handler=_dummy)
+		except TypeError:
+			# Thunar 1.0 uses only $DISPLAY arg
+			thunar.EmptyTrash(_current_display(),
 				reply_handler=_dummy, error_handler=_dummy)
 
 	def get_description(self):



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