diff --git a/src/calibre/devices/interface.py b/src/calibre/devices/interface.py index ff9d71f370..f4ade8d02e 100644 --- a/src/calibre/devices/interface.py +++ b/src/calibre/devices/interface.py @@ -67,11 +67,19 @@ class DevicePlugin(Plugin): For example: For devices that present themselves as USB Mass storage devices, this method would be responsible for mounting the device or if the device has been automounted, for finding out where it has been - mounted. The driver for the PRS505 has a implementation of this function - that should serve as a good example for USB Mass storage devices. + mounted. The base class within USBMS device.py has a implementation of + this function that should serve as a good example for USB Mass storage + devices. ''' raise NotImplementedError() + def eject(self): + ''' + Un-mount / eject the device from the OS. This does not check if there + are pending GUI jobs that need to communicate with the device. + ''' + raise NotImplementedError() + def set_progress_reporter(self, report_progress): ''' @param report_progress: Function that is called with a % progress diff --git a/src/calibre/devices/prs500/driver.py b/src/calibre/devices/prs500/driver.py index c6cd120283..cb7cd715fd 100644 --- a/src/calibre/devices/prs500/driver.py +++ b/src/calibre/devices/prs500/driver.py @@ -279,6 +279,9 @@ class PRS500(DeviceConfig, DevicePlugin): if res.code != 0: raise ProtocolError("Could not set time on device") + def eject(self): + pass + def close(self): """ Release device interface """ try: diff --git a/src/calibre/devices/usbms/device.py b/src/calibre/devices/usbms/device.py index a48d71edd2..7ad93b1d6e 100644 --- a/src/calibre/devices/usbms/device.py +++ b/src/calibre/devices/usbms/device.py @@ -491,3 +491,39 @@ class Device(DeviceConfig, DevicePlugin): time.sleep(3) self.open_osx() + def eject_windows(self): + pass + + def eject_osx(self): + pass + + def eject_linux(self): + drives = self.find_device_nodes() + for drive in drives: + if drive: + cmd = ['pumount'] + try: + p = subprocess.Popen(cmd + [drive]) + except: + pass + while p.poll() is None: + time.sleep(0.1) + + def eject(self): + if islinux: + try: + self.eject_linux() + except: + pass + if iswindows: + try: + self.eject_windows() + except: + pass + if isosx: + try: + self.eject_osx() + except: + pass + self._main_prefix = self._card_a_prefix = self._card_b_prefix = None + diff --git a/src/calibre/gui2/device.py b/src/calibre/gui2/device.py index 4c13effe15..1205aabf66 100644 --- a/src/calibre/gui2/device.py +++ b/src/calibre/gui2/device.py @@ -123,6 +123,10 @@ class DeviceManager(Thread): self.connected_slot(False) device[1] ^= True + def umount_device(self): + self.device.eject() + self.device = None + def next(self): if not self.jobs.empty(): try: @@ -852,5 +856,3 @@ class DeviceGUI(object): getattr(f, 'close', lambda : True)() if memory and memory[1]: self.library_view.model().delete_books_by_id(memory[1]) - - diff --git a/src/calibre/gui2/images/eject.svg b/src/calibre/gui2/images/eject.svg new file mode 100644 index 0000000000..6cffae670b --- /dev/null +++ b/src/calibre/gui2/images/eject.svg @@ -0,0 +1,281 @@ + + + diff --git a/src/calibre/gui2/main.py b/src/calibre/gui2/main.py index b2648409f2..e82c613da3 100644 --- a/src/calibre/gui2/main.py +++ b/src/calibre/gui2/main.py @@ -176,10 +176,23 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI): SIGNAL('activated(QSystemTrayIcon::ActivationReason)'), self.system_tray_icon_activated) self.tool_bar.contextMenuEvent = self.no_op + + ####################### Start spare job server ######################## + QTimer.singleShot(1000, self.add_spare_server) + + ####################### Setup device detection ######################## + self.device_manager = DeviceManager(Dispatcher(self.device_detected), + self.job_manager) + self.device_manager.start() + + ####################### Location View ######################## QObject.connect(self.location_view, SIGNAL('location_selected(PyQt_PyObject)'), self.location_selected) + QObject.connect(self.location_view, + SIGNAL('umount_device()'), + self.device_manager.umount_device) ####################### Vanity ######################## self.vanity_template = _('