Run debug device detection on the gui thread, with proper handling of startup() and shutdown(). Also refuse to run if a device is already detected.

This commit is contained in:
Kovid Goyal 2012-08-09 10:27:40 +05:30
parent 5904626f3c
commit dfed990a65
4 changed files with 65 additions and 13 deletions

View File

@ -55,7 +55,7 @@ def get_connected_device():
break break
return dev return dev
def debug(ioreg_to_tmp=False, buf=None): def debug(ioreg_to_tmp=False, buf=None, plugins=None):
import textwrap import textwrap
from calibre.customize.ui import device_plugins from calibre.customize.ui import device_plugins
from calibre.devices.scanner import DeviceScanner, win_pnp_drives from calibre.devices.scanner import DeviceScanner, win_pnp_drives
@ -66,9 +66,19 @@ def debug(ioreg_to_tmp=False, buf=None):
if buf is None: if buf is None:
buf = StringIO() buf = StringIO()
sys.stdout = sys.stderr = buf sys.stdout = sys.stderr = buf
out = partial(prints, file=buf)
devplugins = device_plugins() if plugins is None else plugins
devplugins = list(sorted(devplugins, cmp=lambda
x,y:cmp(x.__class__.__name__, y.__class__.__name__)))
if plugins is None:
for d in devplugins:
try:
d.startup()
except:
out('Startup failed for device plugin: %s'%d)
try: try:
out = partial(prints, file=buf)
out('Version:', __version__) out('Version:', __version__)
s = DeviceScanner() s = DeviceScanner()
s.scan() s.scan()
@ -96,8 +106,6 @@ def debug(ioreg_to_tmp=False, buf=None):
ioreg += 'Output from osx_get_usb_drives:\n'+drives+'\n\n' ioreg += 'Output from osx_get_usb_drives:\n'+drives+'\n\n'
ioreg += Device.run_ioreg() ioreg += Device.run_ioreg()
connected_devices = [] connected_devices = []
devplugins = list(sorted(device_plugins(), cmp=lambda
x,y:cmp(x.__class__.__name__, y.__class__.__name__)))
out('Available plugins:', textwrap.fill(' '.join([x.__class__.__name__ for x in out('Available plugins:', textwrap.fill(' '.join([x.__class__.__name__ for x in
devplugins]))) devplugins])))
out(' ') out(' ')
@ -155,6 +163,12 @@ def debug(ioreg_to_tmp=False, buf=None):
finally: finally:
sys.stdout = oldo sys.stdout = oldo
sys.stderr = olde sys.stderr = olde
if plugins is None:
for d in devplugins:
try:
d.shutdown()
except:
pass
def device_info(ioreg_to_tmp=False, buf=None): def device_info(ioreg_to_tmp=False, buf=None):
from calibre.devices.scanner import DeviceScanner, win_pnp_drives from calibre.devices.scanner import DeviceScanner, win_pnp_drives

View File

@ -3,7 +3,7 @@ __license__ = 'GPL v3'
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>' __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
# Imports {{{ # Imports {{{
import os, traceback, Queue, time, cStringIO, re, sys import os, traceback, Queue, time, cStringIO, re, sys, weakref
from threading import Thread, Event from threading import Thread, Event
from PyQt4.Qt import (QMenu, QAction, QActionGroup, QIcon, SIGNAL, from PyQt4.Qt import (QMenu, QAction, QActionGroup, QIcon, SIGNAL,
@ -369,6 +369,18 @@ class DeviceManager(Thread): # {{{
except: except:
return False return False
def _debug_detection(self):
from calibre.devices import debug
raw = debug(plugins=self.devices)
return raw
def debug_detection(self, done):
if self.is_device_connected:
raise ValueError('Device is currently detected in calibre, cannot'
' debug device detection')
self.create_job(self._debug_detection, done,
_('Debug device detection'))
def _get_device_information(self): def _get_device_information(self):
info = self.device.get_device_information(end_session=False) info = self.device.get_device_information(end_session=False)
if len(info) < 5: if len(info) < 5:
@ -771,6 +783,15 @@ class DeviceMixin(object): # {{{
if tweaks['auto_connect_to_folder']: if tweaks['auto_connect_to_folder']:
self.connect_to_folder_named(tweaks['auto_connect_to_folder']) self.connect_to_folder_named(tweaks['auto_connect_to_folder'])
def debug_detection(self, done):
self.debug_detection_callback = weakref.ref(done)
self.device_manager.debug_detection(FunctionDispatcher(self.debug_detection_done))
def debug_detection_done(self, job):
d = self.debug_detection_callback()
if d is not None:
d(job)
def show_open_feedback(self, devname, e): def show_open_feedback(self, devname, e):
try: try:
self.__of_dev_mem__ = d = e.custom_dialog(self) self.__of_dev_mem__ = d = e.custom_dialog(self)

View File

@ -10,15 +10,18 @@ __docformat__ = 'restructuredtext en'
from PyQt4.Qt import QDialog, QVBoxLayout, QPlainTextEdit, QTimer, \ from PyQt4.Qt import QDialog, QVBoxLayout, QPlainTextEdit, QTimer, \
QDialogButtonBox, QPushButton, QApplication, QIcon QDialogButtonBox, QPushButton, QApplication, QIcon
from calibre.gui2 import error_dialog
class DebugDevice(QDialog): class DebugDevice(QDialog):
def __init__(self, parent=None): def __init__(self, gui, parent=None):
QDialog.__init__(self, parent) QDialog.__init__(self, parent)
self.gui = gui
self._layout = QVBoxLayout(self) self._layout = QVBoxLayout(self)
self.setLayout(self._layout) self.setLayout(self._layout)
self.log = QPlainTextEdit(self) self.log = QPlainTextEdit(self)
self._layout.addWidget(self.log) self._layout.addWidget(self.log)
self.log.setPlainText(_('Getting debug information')+'...') self.log.setPlainText(_('Getting debug information, please wait')+'...')
self.copy = QPushButton(_('Copy to &clipboard')) self.copy = QPushButton(_('Copy to &clipboard'))
self.copy.setDefault(True) self.copy.setDefault(True)
self.setWindowTitle(_('Debug device detection')) self.setWindowTitle(_('Debug device detection'))
@ -36,12 +39,26 @@ class DebugDevice(QDialog):
QTimer.singleShot(1000, self.debug) QTimer.singleShot(1000, self.debug)
def debug(self): def debug(self):
try: if self.gui.device_manager.is_device_connected:
from calibre.devices import debug error_dialog(self, _('Device already detected'),
raw = debug() _('A device (%s) is already detected by calibre.'
self.log.setPlainText(raw) ' If you wish to debug the detection of another device'
finally: ', first disconnect this device.')%
self.gui.device_manager.connected_device.get_gui_name(),
show=True)
self.bbox.setEnabled(True) self.bbox.setEnabled(True)
return
self.gui.debug_detection(self)
def __call__(self, job):
if not self.isVisible(): return
self.bbox.setEnabled(True)
if job.failed:
return error_dialog(self, _('Debugging failed'),
_('Running debug device detection failed. Click Show '
'Details for more information.'), det_msg=job.details,
show=True)
self.log.setPlainText(job.result)
def copy_to_clipboard(self): def copy_to_clipboard(self):
QApplication.clipboard().setText(self.log.toPlainText()) QApplication.clipboard().setText(self.log.toPlainText())

View File

@ -52,7 +52,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
def debug_device_detection(self, *args): def debug_device_detection(self, *args):
from calibre.gui2.preferences.device_debug import DebugDevice from calibre.gui2.preferences.device_debug import DebugDevice
d = DebugDevice(self) d = DebugDevice(self.gui, self)
d.exec_() d.exec_()
def user_defined_device(self, *args): def user_defined_device(self, *args):