diff options
author | Kurt Jaeger <pi@FreeBSD.org> | 2019-09-21 18:45:22 +0000 |
---|---|---|
committer | Kurt Jaeger <pi@FreeBSD.org> | 2019-09-21 18:45:22 +0000 |
commit | afc03086202ce696e54c801d26c215310f4e2e31 (patch) | |
tree | 499d2ee3d97c9fc488cdeeaf3faf719b839a252f /graphics | |
parent | e6fb62b39052db178d65bec4b03ea125f203774f (diff) |
Notes
Diffstat (limited to 'graphics')
-rw-r--r-- | graphics/Makefile | 1 | ||||
-rw-r--r-- | graphics/rapid-photo-downloader/Makefile | 52 | ||||
-rw-r--r-- | graphics/rapid-photo-downloader/distinfo | 3 | ||||
-rw-r--r-- | graphics/rapid-photo-downloader/files/patch-raphodo_cache.py | 11 | ||||
-rw-r--r-- | graphics/rapid-photo-downloader/files/patch-raphodo_rapid.py | 140 | ||||
-rw-r--r-- | graphics/rapid-photo-downloader/files/patch-raphodo_storage.py | 319 | ||||
-rw-r--r-- | graphics/rapid-photo-downloader/files/patch-raphodo_utilities.py | 62 | ||||
-rw-r--r-- | graphics/rapid-photo-downloader/pkg-descr | 7 |
8 files changed, 595 insertions, 0 deletions
diff --git a/graphics/Makefile b/graphics/Makefile index 3225269eb007..012a0489fa78 100644 --- a/graphics/Makefile +++ b/graphics/Makefile @@ -928,6 +928,7 @@ SUBDIR += quesoglc SUBDIR += radiance SUBDIR += radius-engine + SUBDIR += rapid-photo-downloader SUBDIR += raster3d SUBDIR += rawtherapee SUBDIR += rayshade diff --git a/graphics/rapid-photo-downloader/Makefile b/graphics/rapid-photo-downloader/Makefile new file mode 100644 index 000000000000..660ea37c27db --- /dev/null +++ b/graphics/rapid-photo-downloader/Makefile @@ -0,0 +1,52 @@ +# $FreeBSD$ + +PORTNAME= rapid-photo-downloader +DISTVERSION= 0.9.17 +CATEGORIES= graphics +MASTER_SITES= https://launchpad.net/rapid/pyqt/${PORTVERSION}/+download/ + +MAINTAINER= m.ne@gmx.net +COMMENT= Import photos and videos efficiently and reliably + +LICENSE= GPLv3 + +BUILD_DEPENDS= intltool-update:textproc/intltool +LIB_DEPENDS= libgexiv2.so:graphics/gexiv2 \ + libgudev-1.0.so:devel/libgudev +RUN_DEPENDS= ${PYTHON_PKGNAMEPREFIX}arrow>0:devel/py-arrow@${PY_FLAVOR} \ + ${PYTHON_PKGNAMEPREFIX}colour>0:graphics/py-colour@${PY_FLAVOR} \ + ${PYTHON_PKGNAMEPREFIX}dateutil>2.2:devel/py-dateutil@${PY_FLAVOR} \ + ${PYTHON_PKGNAMEPREFIX}easygui>=0:x11-toolkits/py-easygui@${PY_FLAVOR} \ + ${PYTHON_PKGNAMEPREFIX}gobject3>0:devel/py-gobject3@${PY_FLAVOR} \ + ${PYTHON_PKGNAMEPREFIX}gphoto2>=1.4.0:graphics/py-gphoto2@${PY_FLAVOR} \ + ${PYTHON_PKGNAMEPREFIX}gstreamer1>=1.0:multimedia/py-gstreamer1@${PY_FLAVOR} \ + ${PYTHON_PKGNAMEPREFIX}notify2>0:devel/py-notify2@${PY_FLAVOR} \ + ${PYTHON_PKGNAMEPREFIX}psutil>=3.4.2:sysutils/py-psutil@${PY_FLAVOR} \ + ${PYTHON_PKGNAMEPREFIX}pymediainfo>=1.0:multimedia/py-pymediainfo@${PY_FLAVOR} \ + ${PYTHON_PKGNAMEPREFIX}pyzmq>0:net/py-pyzmq@${PY_FLAVOR} \ + ${PYTHON_PKGNAMEPREFIX}rawkit>0:graphics/py-rawkit@${PY_FLAVOR} \ + ${PYTHON_PKGNAMEPREFIX}requests>=0:www/py-requests@${PY_FLAVOR} \ + ${PYTHON_PKGNAMEPREFIX}sortedcontainers>0:devel/py-sortedcontainers@${PY_FLAVOR} \ + ${PYTHON_PKGNAMEPREFIX}tenacity>0:devel/py-tenacity@${PY_FLAVOR} \ + ${PYTHON_PKGNAMEPREFIX}tornado>=4.1:www/py-tornado@${PY_FLAVOR} \ + ${PYTHON_PKGNAMEPREFIX}xdg>0:devel/py-xdg@${PY_FLAVOR} \ + exiftool:graphics/p5-Image-ExifTool + +USES= desktop-file-utils gettext pyqt:5 python:3.4+ qt:5 +USE_PYTHON= autoplist distutils +USE_QT= imageformats_run +USE_PYQT= core gui network sip widgets + +BINARY_ALIAS= python3=${PYTHON_VERSION} +NO_ARCH= yes + +OPTIONS_DEFINE= COLOUR PROGRESS +OPTIONS_DEFAULT= COLOUR PROGRESS + +COLOUR_DESC= generates coloured program output +PROGRESS_DESC= shows a progress bar on the command line + +COLOUR_RUN_DEPENDS= ${PYTHON_PKGNAMEPREFIX}colorlog>0:devel/py-colorlog@${PY_FLAVOR} +PROGRESS_RUN_DEPENDS= ${PYTHON_PKGNAMEPREFIX}pyprind>=1.4.0:misc/py-pyprind@${PY_FLAVOR} + +.include <bsd.port.mk> diff --git a/graphics/rapid-photo-downloader/distinfo b/graphics/rapid-photo-downloader/distinfo new file mode 100644 index 000000000000..6258f9cb7a78 --- /dev/null +++ b/graphics/rapid-photo-downloader/distinfo @@ -0,0 +1,3 @@ +TIMESTAMP = 1568565754 +SHA256 (rapid-photo-downloader-0.9.17.tar.gz) = 26dbce5d2e775af39ce8f17224a862ed71a86a47768a7ebb04193d96535c7883 +SIZE (rapid-photo-downloader-0.9.17.tar.gz) = 6877573 diff --git a/graphics/rapid-photo-downloader/files/patch-raphodo_cache.py b/graphics/rapid-photo-downloader/files/patch-raphodo_cache.py new file mode 100644 index 000000000000..ee5116b0934e --- /dev/null +++ b/graphics/rapid-photo-downloader/files/patch-raphodo_cache.py @@ -0,0 +1,11 @@ +--- raphodo/cache.py.orig 2019-07-31 17:16:30 UTC ++++ raphodo/cache.py +@@ -131,7 +131,7 @@ class Cache: + not be generated) + """ + +- assert sys.platform.startswith('linux') ++ assert sys.platform.startswith('linux') or sys.platform.startswith('freebsd') + self.cache_dir = cache_dir + self.failure_dir = failure_dir + assert self.cache_dir diff --git a/graphics/rapid-photo-downloader/files/patch-raphodo_rapid.py b/graphics/rapid-photo-downloader/files/patch-raphodo_rapid.py new file mode 100644 index 000000000000..26fc07391c24 --- /dev/null +++ b/graphics/rapid-photo-downloader/files/patch-raphodo_rapid.py @@ -0,0 +1,140 @@ +--- raphodo/rapid.py.orig 2019-08-18 03:58:11 UTC ++++ raphodo/rapid.py +@@ -98,7 +98,7 @@ from PyQt5.QtNetwork import QLocalSocket, QLocalServer + import sip + + from raphodo.storage import ( +- ValidMounts, CameraHotplug, UDisks2Monitor, GVolumeMonitor, have_gio, ++ ValidMounts, CameraHotplug, GVolumeMonitor, have_gio, + has_one_or_more_folders, mountPaths, get_desktop_environment, get_desktop, + gvfs_controls_mounts, get_default_file_manager, validate_download_folder, + validate_source_folder, get_fdo_cache_thumb_base_directory, WatchDownloadDirs, get_media_dir, +@@ -584,12 +584,12 @@ class RapidWindow(QMainWindow): + self.prefs.backup_files = backup + else: + logging.info("Backing up files: %s", self.prefs.backup_files) +- ++ + if backup_auto_detect is not None: + self.prefs.backup_device_autodetection = backup_auto_detect + elif self.prefs.backup_files: + logging.info("Backup device auto detection: %s", self.prefs.backup_device_autodetection) +- ++ + if photo_backup_identifier is not None: + self.prefs.photo_backup_identifier = photo_backup_identifier + elif self.prefs.backup_files and self.prefs.backup_device_autodetection: +@@ -599,7 +599,7 @@ class RapidWindow(QMainWindow): + self.prefs.video_backup_identifier = video_backup_identifier + elif self.prefs.backup_files and self.prefs.backup_device_autodetection: + logging.info("video backup identifier: %s", self.prefs.video_backup_identifier) +- ++ + if photo_backup_location is not None: + self.prefs.backup_photo_location = photo_backup_location + elif self.prefs.backup_files and not self.prefs.backup_device_autodetection: +@@ -934,18 +934,6 @@ class RapidWindow(QMainWindow): + logging.debug("Starting camera hotplug monitor...") + QTimer.singleShot(0, self.cameraHotplugThread.start) + +- # Monitor when the user adds or removes a partition +- self.udisks2Monitor = UDisks2Monitor(self.validMounts) +- self.udisks2MonitorThread = QThread() +- self.udisks2MonitorThread.started.connect(self.udisks2Monitor.startMonitor) +- self.udisks2Unmount.connect(self.udisks2Monitor.unmount_volume) +- self.udisks2Monitor.moveToThread(self.udisks2MonitorThread) +- self.udisks2Monitor.partitionMounted.connect(self.partitionMounted) +- self.udisks2Monitor.partitionUnmounted.connect(self.partitionUmounted) +- # Start the monitor only on the thread it will be running on +- logging.debug("Starting UDisks2 monitor...") +- QTimer.singleShot(0, self.udisks2MonitorThread.start) +- + if self.gvfsControlsMounts: + # Gio.VolumeMonitor must be in the main thread, according to + # Gnome documentation +@@ -2119,7 +2107,7 @@ class RapidWindow(QMainWindow): + select_text=_('Select a destination folder') + ) + self.photoDestination.addWidget(self.photoDestinationWidget) +- ++ + self.videoDestinationDisplay = DestinationDisplay( + menu=True, file_type=FileType.video, parent=self + ) +@@ -2582,11 +2570,11 @@ class RapidWindow(QMainWindow): + + body = _( + r"""Please report the problem at <a href="{website}">{website}</a>.<br><br> +- Include in your bug report the program's log files. The bug report must include +- <i>{log_file}</i>, but attaching the other log files is often helpful.<br><br> ++ Include in your bug report the program's log files. The bug report must include ++ <i>{log_file}</i>, but attaching the other log files is often helpful.<br><br> + If possible, please also include the program's configuration file +- <i>{config_file}</i>.<br><br> +- Click <a href="{log_path}">here</a> to open the log directory, and ++ <i>{config_file}</i>.<br><br> ++ Click <a href="{log_path}">here</a> to open the log directory, and + <a href="{config_path}">here</a> to open the configuration directory. + """ + ).format( +@@ -2622,7 +2610,7 @@ class RapidWindow(QMainWindow): + + :param message: the text to display + :param rich_text: whether it text to display is in HTML format +- :param title: optional title for message box, else defaults to ++ :param title: optional title for message box, else defaults to + localized 'Rapid Photo Downloader' + :return: the message box + """ +@@ -4652,8 +4640,6 @@ Do you want to proceed with the download? + self.sendTerminateToThread(self.backup_controller) + + if not self.gvfsControlsMounts: +- self.udisks2MonitorThread.quit() +- self.udisks2MonitorThread.wait() + self.cameraHotplugThread.quit() + self.cameraHotplugThread.wait() + else: +@@ -5254,7 +5240,7 @@ Do you want to proceed with the download? + After a preference change, rescan already scanned devices + :param ignore_cameras: if True, don't rescan cameras + :param rescan_path: if True, include manually specified paths +- (i.e. This Computer) ++ (i.e. This Computer) + """ + + if rescan_path: +@@ -6243,7 +6229,7 @@ def main(): + logger = iplogging.setup_main_process_logging(logging_level=logging_level) + + logging.info("Rapid Photo Downloader is starting") +- ++ + if args.photo_renaming: + photo_rename = args.photo_renaming == 'on' + if photo_rename: +@@ -6252,7 +6238,7 @@ def main(): + logging.info("Photo renaming turned off from command line") + else: + photo_rename = None +- ++ + if args.video_renaming: + video_rename = args.video_renaming == 'on' + if video_rename: +@@ -6313,13 +6299,13 @@ def main(): + logging.info("This Computer path set from command line: %s", this_computer_location) + else: + this_computer_location=None +- ++ + if args.photo_location: + photo_location = os.path.abspath(args.photo_location) + logging.info("Photo location set from command line: %s", photo_location) + else: + photo_location=None +- ++ + if args.video_location: + video_location = os.path.abspath(args.video_location) + logging.info("video location set from command line: %s", video_location) diff --git a/graphics/rapid-photo-downloader/files/patch-raphodo_storage.py b/graphics/rapid-photo-downloader/files/patch-raphodo_storage.py new file mode 100644 index 000000000000..095d0263348c --- /dev/null +++ b/graphics/rapid-photo-downloader/files/patch-raphodo_storage.py @@ -0,0 +1,319 @@ +--- raphodo/storage.py.orig 2019-07-09 21:12:19 UTC ++++ raphodo/storage.py +@@ -68,10 +68,9 @@ import xdg + import gi + + gi.require_version('GUdev', '1.0') +-gi.require_version('UDisks', '2.0') + gi.require_version('GExiv2', '0.10') + gi.require_version('GLib', '2.0') +-from gi.repository import GUdev, UDisks, GLib ++from gi.repository import GUdev, GLib + + from gettext import gettext as _ + +@@ -170,7 +169,7 @@ def get_media_dir() -> str: + + """ + +- if sys.platform.startswith('linux'): ++ if sys.platform.startswith('linux') or sys.platform.startswith('freebsd'): + media_dir = '/media/{}'.format(get_user_name()) + run_media_dir = '/run{}'.format(media_dir) + distro = get_distro() +@@ -278,7 +277,7 @@ class ValidMounts(): + self.validMountFolders, e.g. /media/<USER>, etc. + """ + +- if not sys.platform.startswith('linux'): ++ if not sys.platform.startswith('linux') and not sys.platform.startswith('freebsd'): + raise ("Mounts.setValidMountPoints() not implemented on %s", sys.platform()) + else: + try: +@@ -646,7 +645,7 @@ def get_default_file_manager() -> Tuple[Optional[str], + + _default_file_manager_probed = True + +- assert sys.platform.startswith('linux') ++ assert sys.platform.startswith('linux') or sys.platform.startswith('freebsd') + cmd = shlex.split('xdg-mime query default inode/directory') + try: + desktop_file = subprocess.check_output(cmd, universal_newlines=True) # type: str +@@ -791,7 +790,7 @@ def validate_download_folder(path: Optional[str], + + :param path: path to analyze + :param write_on_waccesss_failure: if os.access reports path is not writable, test +- nonetheless to see if it's writable by writing and deleting a test file ++ nonetheless to see if it's writable by writing and deleting a test file + :return: Tuple indicating validity and path made absolute + + >>> validate_download_folder('/some/bogus/and/ridiculous/path') +@@ -1008,259 +1007,6 @@ class CameraHotplug(QObject): + self.cameraRemoved.emit() + + +-class UDisks2Monitor(QObject): +- # Most of this class is Copyright 2008-2015 Canonical +- +- partitionMounted = pyqtSignal(str, list, bool) +- partitionUnmounted = pyqtSignal(str) +- +- loop_prefix = '/org/freedesktop/UDisks2/block_devices/loop' +- not_interesting = ( +- '/org/freedesktop/UDisks2/block_devices/dm_', +- '/org/freedesktop/UDisks2/block_devices/ram', +- '/org/freedesktop/UDisks2/block_devices/zram', +- ) +- +- def __init__(self, validMounts: ValidMounts) -> None: +- super().__init__() +- self.validMounts = validMounts +- +- @pyqtSlot() +- def startMonitor(self) -> None: +- self.udisks = UDisks.Client.new_sync(None) +- self.manager = self.udisks.get_object_manager() +- self.manager.connect('object-added', +- lambda man, obj: self._udisks_obj_added(obj)) +- self.manager.connect('object-removed', +- lambda man, obj: self._device_removed(obj)) +- +- # Track the paths of the mount points, which is useful when unmounting +- # objects. +- self.known_mounts = {} # type: Dict[str, str] +- for obj in self.manager.get_objects(): +- path = obj.get_object_path() +- fs = obj.get_filesystem() +- if fs: +- mount_points = fs.get_cached_property('MountPoints').get_bytestring_array() +- if mount_points: +- self.known_mounts[path] = mount_points[0] +- logging.debug("... UDisks2 monitor started") +- +- def _udisks_obj_added(self, obj) -> None: +- path = obj.get_object_path() +- for boring in self.not_interesting: +- if path.startswith(boring): +- return +- block = obj.get_block() +- if not block: +- return +- +- drive = self._get_drive(block) +- +- part = obj.get_partition() +- is_system = block.get_cached_property('HintSystem').get_boolean() +- is_loop = path.startswith(self.loop_prefix) and not \ +- block.get_cached_property('ReadOnly').get_boolean() +- if not is_system or is_loop: +- if part: +- self._udisks_partition_added(obj, block, drive, path) +- +- def _get_drive(self, block) -> Optional[UDisks.Drive]: +- drive_name = block.get_cached_property('Drive').get_string() +- if drive_name != '/': +- return self.udisks.get_object(drive_name).get_drive() +- else: +- return None +- +- def _udisks_partition_added(self, obj, block, drive, path) -> None: +- logging.debug('UDisks: partition added: %s' % path) +- fstype = block.get_cached_property('IdType').get_string() +- logging.debug('Udisks: id-type: %s' % fstype) +- +- fs = obj.get_filesystem() +- +- if fs: +- icon_names = self.get_icon_names(obj) +- +- if drive is not None: +- ejectable = drive.get_property('ejectable') +- else: +- ejectable = False +- mount_point = '' +- mount_points = fs.get_cached_property('MountPoints').get_bytestring_array() +- if len(mount_points) == 0: +- try: +- logging.debug("UDisks: attempting to mount %s", path) +- mount_point = self.retry_mount(fs, fstype) +- if not mount_point: +- raise Exception +- else: +- logging.debug("UDisks: successfully mounted at %s", mount_point) +- except Exception: +- logging.error('UDisks: could not mount the device: %s', path) +- return +- else: +- mount_point = mount_points[0] +- logging.debug("UDisks: already mounted at %s", mount_point) +- +- self.known_mounts[path] = mount_point +- if self.validMounts.pathIsValidMountPoint(mount_point): +- self.partitionMounted.emit(mount_point, icon_names, ejectable) +- +- else: +- logging.debug("Udisks: partition has no file system %s", path) +- +- def retry_mount(self, fs, fstype) -> str: +- # Variant parameter construction Copyright Bernard Baeyens, and is +- # licensed under GNU General Public License Version 2 or higher. +- # https://github.com/berbae/udisksvm +- list_options = '' +- if fstype == 'vfat': +- list_options = 'flush' +- elif fstype == 'ext2': +- list_options = 'sync' +- G_VARIANT_TYPE_VARDICT = GLib.VariantType.new('a{sv}') +- param_builder = GLib.VariantBuilder.new(G_VARIANT_TYPE_VARDICT) +- optname = GLib.Variant.new_string('fstype') # s +- value = GLib.Variant.new_string(fstype) +- vvalue = GLib.Variant.new_variant(value) # v +- newsv = GLib.Variant.new_dict_entry(optname, vvalue) # {sv} +- param_builder.add_value(newsv) +- optname = GLib.Variant.new_string('options') +- value = GLib.Variant.new_string(list_options) +- vvalue = GLib.Variant.new_variant(value) +- newsv = GLib.Variant.new_dict_entry(optname, vvalue) +- param_builder.add_value(newsv) +- vparam = param_builder.end() # a{sv} +- +- # Try to mount until it does not fail with "Busy" +- timeout = 10 +- while timeout >= 0: +- try: +- return fs.call_mount_sync(vparam, None) +- except GLib.GError as e: +- if not 'UDisks2.Error.DeviceBusy' in e.message: +- raise +- logging.debug('Udisks: Device busy.') +- time.sleep(0.3) +- timeout -= 1 +- return '' +- +- def get_icon_names(self, obj: UDisks.Object) -> List[str]: +- # Get icon information, if possible +- icon_names = [] +- if have_gio: +- info = self.udisks.get_object_info(obj) +- icon = info.get_icon() +- if isinstance(icon, Gio.ThemedIcon): +- icon_names = icon.get_names() +- return icon_names +- +- # Next four class member functions from Damon Lynch, not Canonical +- def _device_removed(self, obj: UDisks.Object) -> None: +- # path here refers to the udev / udisks path, not the mount point +- path = obj.get_object_path() +- if path in self.known_mounts: +- mount_point = self.known_mounts[path] +- del self.known_mounts[path] +- self.partitionUnmounted.emit(mount_point) +- +- def get_can_eject(self, obj: UDisks.Object) -> bool: +- block = obj.get_block() +- drive = self._get_drive(block) +- if drive is not None: +- return drive.get_property('ejectable') +- return False +- +- def get_device_props(self, device_path: str) -> Tuple[List[str], bool]: +- """ +- Given a device, get the icon names suggested by udev, and +- determine whether the mount is ejectable or not. +- :param device_path: system path of the device to check, +- e.g. /dev/sdc1 +- :return: icon names and eject boolean +- """ +- +- object_path = '/org/freedesktop/UDisks2/block_devices/{}'.format( +- os.path.split(device_path)[1]) +- obj = self.udisks.get_object(object_path) +- icon_names = self.get_icon_names(obj) +- can_eject = self.get_can_eject(obj) +- return (icon_names, can_eject) +- +- @pyqtSlot(str) +- def unmount_volume(self, mount_point: str) -> None: +- +- G_VARIANT_TYPE_VARDICT = GLib.VariantType.new('a{sv}') +- param_builder = GLib.VariantBuilder.new(G_VARIANT_TYPE_VARDICT) +- +- # Variant parameter construction Copyright Bernard Baeyens, and is +- # licensed under GNU General Public License Version 2 or higher. +- # https://github.com/berbae/udisksvm +- +- optname = GLib.Variant.new_string('force') +- value = GLib.Variant.new_boolean(False) +- vvalue = GLib.Variant.new_variant(value) +- newsv = GLib.Variant.new_dict_entry(optname, vvalue) +- param_builder.add_value(newsv) +- +- vparam = param_builder.end() # a{sv} +- +- path = None +- # Get the path from the dict we keep of known mounts +- for key, value in self.known_mounts.items(): +- if value == mount_point: +- path = key +- break +- if path is None: +- logging.error("Could not find UDisks2 path used to be able to unmount %s", mount_point) +- +- fs = None +- for obj in self.manager.get_objects(): +- opath = obj.get_object_path() +- if path == opath: +- fs = obj.get_filesystem() +- if fs is None: +- logging.error("Could not find UDisks2 filesystem used to be able to unmount %s", +- mount_point) +- +- logging.debug("Unmounting %s...", mount_point) +- try: +- fs.call_unmount(vparam, None, self.umount_volume_callback, (mount_point, fs)) +- except GLib.GError: +- value = sys.exc_info()[1] +- logging.error('Unmounting failed with error:') +- logging.error("%s", value) +- +- def umount_volume_callback(self, source_object: UDisks.FilesystemProxy, +- result: Gio.AsyncResult, +- user_data: Tuple[str, UDisks.Filesystem]) -> None: +- """ +- Callback for asynchronous unmount operation. +- +- :param source_object: the FilesystemProxy object +- :param result: result of the unmount +- :param user_data: mount_point and the file system +- """ +- +- mount_point, fs = user_data +- +- try: +- if fs.call_unmount_finish(result): +- logging.debug("...successfully unmounted %s", mount_point) +- else: +- # this is the result even when the unmount was unsuccessful +- logging.debug("...possibly failed to unmount %s", mount_point) +- except GLib.GError as e: +- logging.error('Exception occurred unmounting %s', mount_point) +- logging.exception('Traceback:') +- except: +- logging.error('Exception occurred unmounting %s', mount_point) +- logging.exception('Traceback:') +- +- self.partitionUnmounted.emit(mount_point) +- +- + if have_gio: + class GVolumeMonitor(QObject): + r""" +@@ -1577,7 +1323,7 @@ def get_mount_size(mount: QStorageInfo) -> Tuple[int, + """ + Uses GIO to get bytes total and bytes free (available) for the mount that a + path is in. +- ++ + :param path: path located anywhere in the mount + :return: bytes_total, bytes_free + """ diff --git a/graphics/rapid-photo-downloader/files/patch-raphodo_utilities.py b/graphics/rapid-photo-downloader/files/patch-raphodo_utilities.py new file mode 100644 index 000000000000..7d46505e0be9 --- /dev/null +++ b/graphics/rapid-photo-downloader/files/patch-raphodo_utilities.py @@ -0,0 +1,62 @@ +--- raphodo/utilities.py.orig 2019-08-18 03:58:11 UTC ++++ raphodo/utilities.py +@@ -76,10 +76,11 @@ if arrow_version >= parse_version('0.14.3') and arrow_ + # Linux specific code to ensure child processes exit when parent dies + # See http://stackoverflow.com/questions/19447603/ + # how-to-kill-a-python-child-process-created-with-subprocess-check-output-when-t/ +-libc = ctypes.CDLL("libc.so.6") ++libc = ctypes.CDLL("libc.so.7") + def set_pdeathsig(sig = signal.SIGTERM): + def callable(): +- return libc.prctl(1, sig) ++ return 0 ++ #return libc.procctl(0, 0, 11, sig) + return callable + + +@@ -195,8 +196,8 @@ def show_errors(): + # kilobytes, etc. + suffixes = [_('B'), _('KB'), _('MB'), _('GB'), _('TB'), _('PB'), _('EB'), _('ZB'), _('YB')] + +-def format_size_for_user(size_in_bytes: int, +- zero_string: str='', ++def format_size_for_user(size_in_bytes: int, ++ zero_string: str='', + no_decimals: int=2) -> str: + r""" + Humanize display of bytes. +@@ -382,12 +383,12 @@ def find_mount_point(path: str) -> str: + Find the mount point of a path + See: + http://stackoverflow.com/questions/4453602/how-to-find-the-mountpoint-a-file-resides-on +- ++ + >>> print(find_mount_point('/crazy/path')) + / +- +- :param path: +- :return: ++ ++ :param path: ++ :return: + """ + path = os.path.realpath(path) + while not os.path.ismount(path): +@@ -724,13 +725,13 @@ def _collect_duplicates(basenames, paths): + + def make_path_end_snippets_unique(*paths) -> List[str]: + r""" +- Make list of path ends unique given possible common path endings. +- +- A snippet starts from the end of the path, in extreme cases possibly up the path start. ++ Make list of path ends unique given possible common path endings. + ++ A snippet starts from the end of the path, in extreme cases possibly up the path start. ++ + :param paths: sequence of paths to generate unique end snippets for + :return: list of unique snippets +- ++ + >>> p0 = '/home/damon/photos' + >>> p1 = '/media/damon/backup1/photos' + >>> p2 = '/media/damon/backup2/photos' diff --git a/graphics/rapid-photo-downloader/pkg-descr b/graphics/rapid-photo-downloader/pkg-descr new file mode 100644 index 000000000000..30d4ac6563a0 --- /dev/null +++ b/graphics/rapid-photo-downloader/pkg-descr @@ -0,0 +1,7 @@ +Rapid Photo Downloader imports photos and videos from cameras, phones, +memory cards and other devices at high speed. It can be configured to +rename photos and videos with meaningful filenames you specify. It can +also back up photos and videos as they are downloaded. It downloads +from and backs up to multiple devices simultaneously. + +WWW: http://www.damonlynch.net/rapid/ |