diff --git a/src/calibre/gui2/actions/device.py b/src/calibre/gui2/actions/device.py index 429bc641d0..0b0492228e 100644 --- a/src/calibre/gui2/actions/device.py +++ b/src/calibre/gui2/actions/device.py @@ -7,13 +7,14 @@ __docformat__ = 'restructuredtext en' from functools import partial -from PyQt4.Qt import QToolButton, QMenu, pyqtSignal, QIcon +from PyQt4.Qt import QToolButton, QMenu, pyqtSignal, QIcon, QTimer from calibre.gui2.actions import InterfaceAction from calibre.utils.smtp import config as email_config from calibre.constants import iswindows, isosx from calibre.customize.ui import is_disabled from calibre.devices.bambook.driver import BAMBOOK +from calibre.gui2 import info_dialog class ShareConnMenu(QMenu): # {{{ @@ -169,5 +170,20 @@ class ConnectShareAction(InterfaceAction): if self.gui.content_server is None: self.gui.start_content_server() else: - self.gui.content_server.exit() - self.gui.content_server = None + self.gui.content_server.threaded_exit() + self.stopping_msg = info_dialog(self.gui, _('Stopping'), + _('Stopping server, this could take upto a minute, please wait...'), + show_copy_button=False) + QTimer.singleShot(1000, self.check_exited) + + def check_exited(self): + if self.gui.content_server.is_running: + QTimer.singleShot(20, self.check_exited) + if not self.stopping_msg.isVisible(): + self.stopping_msg.exec_() + return + + + self.gui.content_server = None + self.stopping_msg.accept() + diff --git a/src/calibre/gui2/preferences/server.py b/src/calibre/gui2/preferences/server.py index 4db1244d75..82519f17cd 100644 --- a/src/calibre/gui2/preferences/server.py +++ b/src/calibre/gui2/preferences/server.py @@ -8,7 +8,7 @@ __docformat__ = 'restructuredtext en' import time from PyQt4.Qt import Qt, QUrl, QDialog, QSize, QVBoxLayout, QLabel, \ - QPlainTextEdit, QDialogButtonBox + QPlainTextEdit, QDialogButtonBox, QTimer from calibre.gui2.preferences import ConfigWidgetBase, test_widget from calibre.gui2.preferences.server_ui import Ui_Form @@ -16,7 +16,8 @@ from calibre.utils.search_query_parser import saved_searches from calibre.library.server import server_config from calibre.utils.config import ConfigProxy from calibre.gui2 import error_dialog, config, open_url, warning_dialog, \ - Dispatcher + Dispatcher, info_dialog +from calibre import as_unicode class ConfigWidget(ConfigWidgetBase, Ui_Form): @@ -67,25 +68,36 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): def start_server(self): self.set_server_options() - from calibre.library.server.main import start_threaded_server - self.server = start_threaded_server(self.db, server_config().parse()) - while not self.server.is_running and self.server.exception is None: + self.gui.start_content_server(check_started=False) + while not self.gui.content_server.is_running and self.gui.content_server.exception is None: time.sleep(1) - if self.server.exception is not None: + if self.gui.content_server.exception is not None: error_dialog(self, _('Failed to start content server'), - unicode(self.server.exception)).exec_() + as_unicode(self.gui.content_server.exception)).exec_() return self.start_button.setEnabled(False) self.test_button.setEnabled(True) self.stop_button.setEnabled(True) def stop_server(self): - from calibre.library.server.main import stop_threaded_server - stop_threaded_server(self.server) - self.server = None + self.gui.content_server.threaded_exit() + self.stopping_msg = info_dialog(self, _('Stopping'), + _('Stopping server, this could take upto a minute, please wait...'), + show_copy_button=False) + QTimer.singleShot(500, self.check_exited) + + def check_exited(self): + if self.gui.content_server.is_running: + QTimer.singleShot(20, self.check_exited) + if not self.stopping_msg.isVisible(): + self.stopping_msg.exec_() + return + + self.gui.content_server = None self.start_button.setEnabled(True) self.test_button.setEnabled(False) self.stop_button.setEnabled(False) + self.stopping_msg.accept() def test_server(self): open_url(QUrl('http://127.0.0.1:'+str(self.opt_port.value()))) diff --git a/src/calibre/gui2/ui.py b/src/calibre/gui2/ui.py index 5ac7e6a45d..4ac92e7806 100644 --- a/src/calibre/gui2/ui.py +++ b/src/calibre/gui2/ui.py @@ -311,7 +311,7 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{ def esc(self, *args): self.search.clear() - def start_content_server(self): + def start_content_server(self, check_started=True): from calibre.library.server.main import start_threaded_server from calibre.library.server import server_config self.content_server = start_threaded_server( @@ -319,7 +319,8 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{ self.content_server.state_callback = Dispatcher( self.iactions['Connect Share'].content_server_state_changed) self.content_server.state_callback(True) - self.test_server_timer = QTimer.singleShot(10000, self.test_server) + if check_started: + QTimer.singleShot(10000, self.test_server) def resizeEvent(self, ev): MainWindow.resizeEvent(self, ev) diff --git a/src/calibre/library/server/base.py b/src/calibre/library/server/base.py index b4f2b663a5..83d395dec5 100644 --- a/src/calibre/library/server/base.py +++ b/src/calibre/library/server/base.py @@ -120,6 +120,8 @@ class LibraryServer(ContentServer, MobileServer, XMLServer, OPDSServer, Cache, self.set_database(db) + st = 0.1 if opts.develop else 1 + cherrypy.config.update({ 'log.screen' : opts.develop, 'engine.autoreload_on' : getattr(opts, @@ -131,6 +133,7 @@ class LibraryServer(ContentServer, MobileServer, XMLServer, OPDSServer, Cache, 'server.socket_port' : opts.port, 'server.socket_timeout' : opts.timeout, #seconds 'server.thread_pool' : opts.thread_pool, # number of threads + 'server.shutdown_timeout': st, # minutes }) if embedded or wsgi: cherrypy.config.update({'engine.SIGHUP' : None, @@ -241,4 +244,9 @@ class LibraryServer(ContentServer, MobileServer, XMLServer, OPDSServer, Cache, except: pass + def threaded_exit(self): + from threading import Thread + t = Thread(target=self.exit) + t.daemon = True + t.start()