Merge from trunk

This commit is contained in:
Charles Haley 2011-06-11 23:34:37 +01:00
commit a67be30f1c
3 changed files with 30 additions and 14 deletions

View File

@ -271,6 +271,9 @@ class Dispatcher(QObject):
Convenience class to use Qt signals with arbitrary python callables. Convenience class to use Qt signals with arbitrary python callables.
By default, ensures that a function call always happens in the By default, ensures that a function call always happens in the
thread this Dispatcher was created in. thread this Dispatcher was created in.
Note that if you create the Dispatcher in a thread without an event loop of
its own, the function call will happen in the GUI thread (I think).
''' '''
dispatch_signal = pyqtSignal(object, object) dispatch_signal = pyqtSignal(object, object)
@ -292,11 +295,20 @@ class FunctionDispatcher(QObject):
''' '''
Convenience class to use Qt signals with arbitrary python functions. Convenience class to use Qt signals with arbitrary python functions.
By default, ensures that a function call always happens in the By default, ensures that a function call always happens in the
thread this Dispatcher was created in. thread this FunctionDispatcher was created in.
Note that you must create FunctionDispatcher objects in the GUI thread.
''' '''
dispatch_signal = pyqtSignal(object, object, object) dispatch_signal = pyqtSignal(object, object, object)
def __init__(self, func, queued=True, parent=None): def __init__(self, func, queued=True, parent=None):
global gui_thread
if gui_thread is None:
gui_thread = QThread.currentThread()
if not is_gui_thread():
raise ValueError(
'You can only create a FunctionDispatcher in the GUI thread')
QObject.__init__(self, parent) QObject.__init__(self, parent)
self.func = func self.func = func
typ = Qt.QueuedConnection typ = Qt.QueuedConnection
@ -305,10 +317,9 @@ class FunctionDispatcher(QObject):
self.dispatch_signal.connect(self.dispatch, type=typ) self.dispatch_signal.connect(self.dispatch, type=typ)
self.q = Queue.Queue() self.q = Queue.Queue()
self.lock = threading.Lock() self.lock = threading.Lock()
self.calling_thread = QThread.currentThread()
def __call__(self, *args, **kwargs): def __call__(self, *args, **kwargs):
if self.calling_thread == QThread.currentThread(): if is_gui_thread():
return self.func(*args, **kwargs) return self.func(*args, **kwargs)
with self.lock: with self.lock:
self.dispatch_signal.emit(self.q, args, kwargs) self.dispatch_signal.emit(self.q, args, kwargs)

View File

@ -6,18 +6,18 @@ __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
import os, traceback, Queue, time, cStringIO, re, sys import os, traceback, Queue, time, cStringIO, re, sys
from threading import Thread from threading import Thread
from PyQt4.Qt import QMenu, QAction, QActionGroup, QIcon, SIGNAL, \ from PyQt4.Qt import (QMenu, QAction, QActionGroup, QIcon, SIGNAL,
Qt, pyqtSignal, QDialog, QObject Qt, pyqtSignal, QDialog, QObject)
from calibre.customize.ui import available_input_formats, available_output_formats, \ from calibre.customize.ui import (available_input_formats, available_output_formats,
device_plugins device_plugins)
from calibre.devices.interface import DevicePlugin from calibre.devices.interface import DevicePlugin
from calibre.devices.errors import UserFeedback, OpenFeedback from calibre.devices.errors import UserFeedback, OpenFeedback
from calibre.gui2.dialogs.choose_format_device import ChooseFormatDeviceDialog from calibre.gui2.dialogs.choose_format_device import ChooseFormatDeviceDialog
from calibre.utils.ipc.job import BaseJob from calibre.utils.ipc.job import BaseJob
from calibre.devices.scanner import DeviceScanner from calibre.devices.scanner import DeviceScanner
from calibre.gui2 import config, error_dialog, Dispatcher, dynamic, \ from calibre.gui2 import (config, error_dialog, Dispatcher, dynamic,
warning_dialog, info_dialog, choose_dir, FunctionDispatcher warning_dialog, info_dialog, choose_dir, FunctionDispatcher)
from calibre.ebooks.metadata import authors_to_string from calibre.ebooks.metadata import authors_to_string
from calibre import preferred_encoding, prints, force_unicode, as_unicode from calibre import preferred_encoding, prints, force_unicode, as_unicode
from calibre.utils.filenames import ascii_filename from calibre.utils.filenames import ascii_filename
@ -35,8 +35,9 @@ class DeviceJob(BaseJob): # {{{
def __init__(self, func, done, job_manager, args=[], kwargs={}, def __init__(self, func, done, job_manager, args=[], kwargs={},
description=''): description=''):
BaseJob.__init__(self, description, done=done) BaseJob.__init__(self, description)
self.func = func self.func = func
self.callback_on_done = done
self.args, self.kwargs = args, kwargs self.args, self.kwargs = args, kwargs
self.exception = None self.exception = None
self.job_manager = job_manager self.job_manager = job_manager
@ -50,6 +51,10 @@ class DeviceJob(BaseJob): # {{{
def job_done(self): def job_done(self):
self.duration = time.time() - self.start_time self.duration = time.time() - self.start_time
self.percent = 1 self.percent = 1
try:
self.callback_on_done(self)
except:
pass
self.job_manager.changed_queue.put(self) self.job_manager.changed_queue.put(self)
def report_progress(self, percent, msg=''): def report_progress(self, percent, msg=''):

View File

@ -11,8 +11,8 @@ from binascii import unhexlify
from functools import partial from functools import partial
from itertools import repeat from itertools import repeat
from calibre.utils.smtp import compose_mail, sendmail, extract_email_address, \ from calibre.utils.smtp import (compose_mail, sendmail, extract_email_address,
config as email_config config as email_config)
from calibre.utils.filenames import ascii_filename from calibre.utils.filenames import ascii_filename
from calibre.customize.ui import available_input_formats, available_output_formats from calibre.customize.ui import available_input_formats, available_output_formats
from calibre.ebooks.metadata import authors_to_string from calibre.ebooks.metadata import authors_to_string
@ -67,8 +67,8 @@ class Sendmail(object):
from_ = opts.from_ from_ = opts.from_
if not from_: if not from_:
from_ = 'calibre <calibre@'+socket.getfqdn()+'>' from_ = 'calibre <calibre@'+socket.getfqdn()+'>'
msg = compose_mail(from_, to, text, subject, open(attachment, 'rb'), with lopen(attachment, 'rb') as f:
aname) msg = compose_mail(from_, to, text, subject, f, aname)
efrom, eto = map(extract_email_address, (from_, to)) efrom, eto = map(extract_email_address, (from_, to))
eto = [eto] eto = [eto]
sendmail(msg, efrom, eto, localhost=None, sendmail(msg, efrom, eto, localhost=None,