mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Add entry to Connect/share menu to conveniently stop.start the Content Server
This commit is contained in:
parent
898b61a55e
commit
1834ae8a10
@ -329,6 +329,7 @@ class ShareConnMenu(QMenu): # {{{
|
|||||||
connect_to_folder = pyqtSignal()
|
connect_to_folder = pyqtSignal()
|
||||||
connect_to_itunes = pyqtSignal()
|
connect_to_itunes = pyqtSignal()
|
||||||
config_email = pyqtSignal()
|
config_email = pyqtSignal()
|
||||||
|
toggle_server = pyqtSignal()
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
QMenu.__init__(self, parent)
|
QMenu.__init__(self, parent)
|
||||||
@ -336,15 +337,27 @@ class ShareConnMenu(QMenu): # {{{
|
|||||||
mitem.setEnabled(True)
|
mitem.setEnabled(True)
|
||||||
mitem.triggered.connect(lambda x : self.connect_to_folder.emit())
|
mitem.triggered.connect(lambda x : self.connect_to_folder.emit())
|
||||||
self.connect_to_folder_action = mitem
|
self.connect_to_folder_action = mitem
|
||||||
|
|
||||||
mitem = self.addAction(QIcon(I('devices/itunes.png')),
|
mitem = self.addAction(QIcon(I('devices/itunes.png')),
|
||||||
_('Connect to iTunes'))
|
_('Connect to iTunes'))
|
||||||
mitem.setEnabled(True)
|
mitem.setEnabled(True)
|
||||||
mitem.triggered.connect(lambda x : self.connect_to_itunes.emit())
|
mitem.triggered.connect(lambda x : self.connect_to_itunes.emit())
|
||||||
self.connect_to_itunes_action = mitem
|
self.connect_to_itunes_action = mitem
|
||||||
self.addSeparator()
|
self.addSeparator()
|
||||||
|
self.toggle_server_action = \
|
||||||
|
self.addAction(QIcon(I('network-server.svg')),
|
||||||
|
_('Start Content Server'))
|
||||||
|
self.toggle_server_action.triggered.connect(lambda x:
|
||||||
|
self.toggle_server.emit())
|
||||||
|
self.addSeparator()
|
||||||
|
|
||||||
self.email_actions = []
|
self.email_actions = []
|
||||||
|
|
||||||
|
def server_state_changed(self, running):
|
||||||
|
text = _('Start Content Server')
|
||||||
|
if running:
|
||||||
|
text = _('Stop Content Server')
|
||||||
|
self.toggle_server_action.setText(text)
|
||||||
|
|
||||||
def build_email_entries(self, sync_menu):
|
def build_email_entries(self, sync_menu):
|
||||||
from calibre.gui2.device import DeviceAction
|
from calibre.gui2.device import DeviceAction
|
||||||
for ac in self.email_actions:
|
for ac in self.email_actions:
|
||||||
@ -478,6 +491,7 @@ class MainWindowMixin(object):
|
|||||||
self.action_news.triggered.connect(
|
self.action_news.triggered.connect(
|
||||||
self.scheduler.show_dialog)
|
self.scheduler.show_dialog)
|
||||||
self.share_conn_menu = ShareConnMenu(self)
|
self.share_conn_menu = ShareConnMenu(self)
|
||||||
|
self.share_conn_menu.toggle_server.connect(self.toggle_content_server)
|
||||||
self.share_conn_menu.config_email.connect(partial(self.do_config,
|
self.share_conn_menu.config_email.connect(partial(self.do_config,
|
||||||
initial_category='email'))
|
initial_category='email'))
|
||||||
self.action_conn_share.setMenu(self.share_conn_menu)
|
self.action_conn_share.setMenu(self.share_conn_menu)
|
||||||
@ -614,4 +628,12 @@ class MainWindowMixin(object):
|
|||||||
def show_help(self, *args):
|
def show_help(self, *args):
|
||||||
open_url(QUrl('http://calibre-ebook.com/user_manual'))
|
open_url(QUrl('http://calibre-ebook.com/user_manual'))
|
||||||
|
|
||||||
|
def content_server_state_changed(self, running):
|
||||||
|
self.share_conn_menu.server_state_changed(running)
|
||||||
|
|
||||||
|
def toggle_content_server(self):
|
||||||
|
if self.content_server is None:
|
||||||
|
self.start_content_server()
|
||||||
|
else:
|
||||||
|
self.content_server.exit()
|
||||||
|
self.content_server = None
|
||||||
|
@ -24,7 +24,7 @@ from calibre.ptempfile import PersistentTemporaryFile
|
|||||||
from calibre.utils.config import prefs, dynamic
|
from calibre.utils.config import prefs, dynamic
|
||||||
from calibre.utils.ipc.server import Server
|
from calibre.utils.ipc.server import Server
|
||||||
from calibre.gui2 import error_dialog, GetMetadata, open_local_file, \
|
from calibre.gui2 import error_dialog, GetMetadata, open_local_file, \
|
||||||
gprefs, max_available_height, config, info_dialog
|
gprefs, max_available_height, config, info_dialog, Dispatcher
|
||||||
from calibre.gui2.cover_flow import CoverFlowMixin
|
from calibre.gui2.cover_flow import CoverFlowMixin
|
||||||
from calibre.gui2.widgets import ProgressIndicator
|
from calibre.gui2.widgets import ProgressIndicator
|
||||||
from calibre.gui2.update import UpdateMixin
|
from calibre.gui2.update import UpdateMixin
|
||||||
@ -106,6 +106,7 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{
|
|||||||
opts = self.opts
|
opts = self.opts
|
||||||
self.preferences_action, self.quit_action = actions
|
self.preferences_action, self.quit_action = actions
|
||||||
self.library_path = library_path
|
self.library_path = library_path
|
||||||
|
self.content_server = None
|
||||||
self.spare_servers = []
|
self.spare_servers = []
|
||||||
self.must_restart_before_config = False
|
self.must_restart_before_config = False
|
||||||
# Initialize fontconfig in a separate thread as this can be a lengthy
|
# Initialize fontconfig in a separate thread as this can be a lengthy
|
||||||
@ -146,7 +147,6 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{
|
|||||||
self.default_thumbnail = None
|
self.default_thumbnail = None
|
||||||
self.tb_wrapper = textwrap.TextWrapper(width=40)
|
self.tb_wrapper = textwrap.TextWrapper(width=40)
|
||||||
self.viewers = collections.deque()
|
self.viewers = collections.deque()
|
||||||
self.content_server = None
|
|
||||||
self.system_tray_icon = SystemTrayIcon(QIcon(I('library.png')), self)
|
self.system_tray_icon = SystemTrayIcon(QIcon(I('library.png')), self)
|
||||||
self.system_tray_icon.setToolTip('calibre')
|
self.system_tray_icon.setToolTip('calibre')
|
||||||
self.system_tray_icon.tooltip_requested.connect(
|
self.system_tray_icon.tooltip_requested.connect(
|
||||||
@ -246,11 +246,7 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{
|
|||||||
|
|
||||||
|
|
||||||
if config['autolaunch_server']:
|
if config['autolaunch_server']:
|
||||||
from calibre.library.server.main import start_threaded_server
|
self.start_content_server()
|
||||||
from calibre.library.server import server_config
|
|
||||||
self.content_server = start_threaded_server(
|
|
||||||
db, server_config().parse())
|
|
||||||
self.test_server_timer = QTimer.singleShot(10000, self.test_server)
|
|
||||||
|
|
||||||
self.keyboard_interrupt.connect(self.quit, type=Qt.QueuedConnection)
|
self.keyboard_interrupt.connect(self.quit, type=Qt.QueuedConnection)
|
||||||
AddAction.__init__(self)
|
AddAction.__init__(self)
|
||||||
@ -263,6 +259,15 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{
|
|||||||
self.library_view.model().delete_books_by_id,
|
self.library_view.model().delete_books_by_id,
|
||||||
type=Qt.QueuedConnection)
|
type=Qt.QueuedConnection)
|
||||||
|
|
||||||
|
def start_content_server(self):
|
||||||
|
from calibre.library.server.main import start_threaded_server
|
||||||
|
from calibre.library.server import server_config
|
||||||
|
self.content_server = start_threaded_server(
|
||||||
|
self.library_view.model().db, server_config().parse())
|
||||||
|
self.content_server.state_callback = Dispatcher(self.content_server_state_changed)
|
||||||
|
self.content_server.state_callback(True)
|
||||||
|
self.test_server_timer = QTimer.singleShot(10000, self.test_server)
|
||||||
|
|
||||||
|
|
||||||
def resizeEvent(self, ev):
|
def resizeEvent(self, ev):
|
||||||
MainWindow.resizeEvent(self, ev)
|
MainWindow.resizeEvent(self, ev)
|
||||||
@ -308,7 +313,8 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{
|
|||||||
setattr(window, '__systray_minimized', False)
|
setattr(window, '__systray_minimized', False)
|
||||||
|
|
||||||
def test_server(self, *args):
|
def test_server(self, *args):
|
||||||
if self.content_server.exception is not None:
|
if self.content_server is not None and \
|
||||||
|
self.content_server.exception is not None:
|
||||||
error_dialog(self, _('Failed to start content server'),
|
error_dialog(self, _('Failed to start content server'),
|
||||||
unicode(self.content_server.exception)).exec_()
|
unicode(self.content_server.exception)).exec_()
|
||||||
|
|
||||||
@ -367,6 +373,10 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{
|
|||||||
|
|
||||||
d.exec_()
|
d.exec_()
|
||||||
self.content_server = d.server
|
self.content_server = d.server
|
||||||
|
self.content_server.state_callback = \
|
||||||
|
Dispatcher(self.content_server_state_changed)
|
||||||
|
self.content_server.state_callback(self.content_server.is_running)
|
||||||
|
|
||||||
if d.result() == d.Accepted:
|
if d.result() == d.Accepted:
|
||||||
self.read_toolbar_settings()
|
self.read_toolbar_settings()
|
||||||
self.search.search_as_you_type(config['search_as_you_type'])
|
self.search.search_as_you_type(config['search_as_you_type'])
|
||||||
@ -583,7 +593,9 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{
|
|||||||
try:
|
try:
|
||||||
try:
|
try:
|
||||||
if self.content_server is not None:
|
if self.content_server is not None:
|
||||||
self.content_server.exit()
|
s = self.content_server
|
||||||
|
self.content_server = None
|
||||||
|
s.exit()
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
|
@ -64,6 +64,7 @@ class LibraryServer(ContentServer, MobileServer, XMLServer, OPDSServer, Cache):
|
|||||||
break
|
break
|
||||||
self.opts = opts
|
self.opts = opts
|
||||||
self.embedded = embedded
|
self.embedded = embedded
|
||||||
|
self.state_callback = None
|
||||||
self.max_cover_width, self.max_cover_height = \
|
self.max_cover_width, self.max_cover_height = \
|
||||||
map(int, self.opts.max_cover.split('x'))
|
map(int, self.opts.max_cover.split('x'))
|
||||||
path = P('content_server')
|
path = P('content_server')
|
||||||
@ -159,11 +160,22 @@ class LibraryServer(ContentServer, MobileServer, XMLServer, OPDSServer, Cache):
|
|||||||
import traceback
|
import traceback
|
||||||
cherrypy.log.error('Failed to stop BonJour:')
|
cherrypy.log.error('Failed to stop BonJour:')
|
||||||
cherrypy.log.error(traceback.format_exc())
|
cherrypy.log.error(traceback.format_exc())
|
||||||
|
try:
|
||||||
|
if callable(self.state_callback):
|
||||||
|
self.state_callback(self.is_running)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
def exit(self):
|
def exit(self):
|
||||||
try:
|
try:
|
||||||
cherrypy.engine.exit()
|
cherrypy.engine.exit()
|
||||||
finally:
|
finally:
|
||||||
cherrypy.server.httpserver = None
|
cherrypy.server.httpserver = None
|
||||||
|
self.is_running = False
|
||||||
|
try:
|
||||||
|
if callable(self.state_callback):
|
||||||
|
self.state_callback(self.is_running)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user