mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Migrate device actions and other minor actions
This commit is contained in:
parent
886db1b6a8
commit
72c2d636b0
@ -613,6 +613,29 @@ class ActionSaveToDisk(InterfaceActionBase):
|
|||||||
name = 'Save To Disk'
|
name = 'Save To Disk'
|
||||||
actual_plugin = 'calibre.gui2.actions.save_to_disk:SaveToDiskAction'
|
actual_plugin = 'calibre.gui2.actions.save_to_disk:SaveToDiskAction'
|
||||||
|
|
||||||
|
class ActionShowBookDetails(InterfaceActionBase):
|
||||||
|
name = 'Show Book Details'
|
||||||
|
actual_plugin = 'calibre.gui2.actions.show_book_details:ShowBookDetailsAction'
|
||||||
|
|
||||||
|
class ActionRestart(InterfaceActionBase):
|
||||||
|
name = 'Restart'
|
||||||
|
actual_plugin = 'calibre.gui2.actions.restart:RestartAction'
|
||||||
|
|
||||||
|
class ActionOpenFolder(InterfaceActionBase):
|
||||||
|
name = 'OpenFolder'
|
||||||
|
actual_plugin = 'calibre.gui2.actions.open:OpenFolderAction'
|
||||||
|
|
||||||
|
class ActionSendToDevice(InterfaceActionBase):
|
||||||
|
name = 'Send To Device'
|
||||||
|
actual_plugin = 'calibre.gui2.actions.device:SendToDeviceAction'
|
||||||
|
|
||||||
|
class ActionConnectShare(InterfaceActionBase):
|
||||||
|
name = 'Connect Share'
|
||||||
|
actual_plugin = 'calibre.gui2.actions.device:ConnectShareAction'
|
||||||
|
|
||||||
|
|
||||||
plugins += [ActionAdd, ActionFetchAnnotations, ActionGenerateCatalog,
|
plugins += [ActionAdd, ActionFetchAnnotations, ActionGenerateCatalog,
|
||||||
ActionConvert, ActionDelete, ActionEditMetadata, ActionView,
|
ActionConvert, ActionDelete, ActionEditMetadata, ActionView,
|
||||||
ActionFetchNews, ActionSaveToDisk]
|
ActionFetchNews, ActionSaveToDisk, ActionShowBookDetails,
|
||||||
|
ActionRestart, ActionOpenFolder, ActionConnectShare,
|
||||||
|
ActionSendToDevice, ]
|
||||||
|
@ -32,6 +32,7 @@ class InterfaceAction(QObject):
|
|||||||
def do_genesis(self):
|
def do_genesis(self):
|
||||||
self.Dispatcher = partial(Dispatcher, parent=self)
|
self.Dispatcher = partial(Dispatcher, parent=self)
|
||||||
self.create_action()
|
self.create_action()
|
||||||
|
self.gui.addAction(self.qaction)
|
||||||
self.genesis()
|
self.genesis()
|
||||||
|
|
||||||
def create_action(self, spec=None, attr='qaction'):
|
def create_action(self, spec=None, attr='qaction'):
|
||||||
|
143
src/calibre/gui2/actions/device.py
Normal file
143
src/calibre/gui2/actions/device.py
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
|
||||||
|
|
||||||
|
__license__ = 'GPL v3'
|
||||||
|
__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||||
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
|
from functools import partial
|
||||||
|
|
||||||
|
from PyQt4.Qt import QToolButton, QMenu, pyqtSignal, QIcon
|
||||||
|
|
||||||
|
from calibre.gui2.actions import InterfaceAction
|
||||||
|
from calibre.utils.smtp import config as email_config
|
||||||
|
|
||||||
|
class ShareConnMenu(QMenu): # {{{
|
||||||
|
|
||||||
|
connect_to_folder = pyqtSignal()
|
||||||
|
connect_to_itunes = pyqtSignal()
|
||||||
|
config_email = pyqtSignal()
|
||||||
|
toggle_server = pyqtSignal()
|
||||||
|
|
||||||
|
def __init__(self, parent=None):
|
||||||
|
QMenu.__init__(self, parent)
|
||||||
|
mitem = self.addAction(QIcon(I('devices/folder.svg')), _('Connect to folder'))
|
||||||
|
mitem.setEnabled(True)
|
||||||
|
mitem.triggered.connect(lambda x : self.connect_to_folder.emit())
|
||||||
|
self.connect_to_folder_action = mitem
|
||||||
|
mitem = self.addAction(QIcon(I('devices/itunes.png')),
|
||||||
|
_('Connect to iTunes'))
|
||||||
|
mitem.setEnabled(True)
|
||||||
|
mitem.triggered.connect(lambda x : self.connect_to_itunes.emit())
|
||||||
|
self.connect_to_itunes_action = mitem
|
||||||
|
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 = []
|
||||||
|
|
||||||
|
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):
|
||||||
|
from calibre.gui2.device import DeviceAction
|
||||||
|
for ac in self.email_actions:
|
||||||
|
self.removeAction(ac)
|
||||||
|
self.email_actions = []
|
||||||
|
self.memory = []
|
||||||
|
opts = email_config().parse()
|
||||||
|
if opts.accounts:
|
||||||
|
self.email_to_menu = QMenu(_('Email to')+'...', self)
|
||||||
|
keys = sorted(opts.accounts.keys())
|
||||||
|
for account in keys:
|
||||||
|
formats, auto, default = opts.accounts[account]
|
||||||
|
dest = 'mail:'+account+';'+formats
|
||||||
|
action1 = DeviceAction(dest, False, False, I('mail.svg'),
|
||||||
|
_('Email to')+' '+account)
|
||||||
|
action2 = DeviceAction(dest, True, False, I('mail.svg'),
|
||||||
|
_('Email to')+' '+account+ _(' and delete from library'))
|
||||||
|
map(self.email_to_menu.addAction, (action1, action2))
|
||||||
|
map(self.memory.append, (action1, action2))
|
||||||
|
if default:
|
||||||
|
map(self.addAction, (action1, action2))
|
||||||
|
map(self.email_actions.append, (action1, action2))
|
||||||
|
self.email_to_menu.addSeparator()
|
||||||
|
action1.a_s.connect(sync_menu.action_triggered)
|
||||||
|
action2.a_s.connect(sync_menu.action_triggered)
|
||||||
|
ac = self.addMenu(self.email_to_menu)
|
||||||
|
self.email_actions.append(ac)
|
||||||
|
else:
|
||||||
|
ac = self.addAction(_('Setup email based sharing of books'))
|
||||||
|
self.email_actions.append(ac)
|
||||||
|
ac.triggered.connect(self.setup_email)
|
||||||
|
|
||||||
|
def setup_email(self, *args):
|
||||||
|
self.config_email.emit()
|
||||||
|
|
||||||
|
def set_state(self, device_connected):
|
||||||
|
self.connect_to_folder_action.setEnabled(not device_connected)
|
||||||
|
self.connect_to_itunes_action.setEnabled(not device_connected)
|
||||||
|
|
||||||
|
|
||||||
|
# }}}
|
||||||
|
|
||||||
|
class SendToDeviceAction(InterfaceAction):
|
||||||
|
|
||||||
|
name = 'Send To Device'
|
||||||
|
action_spec = (_('Send to device'), 'sync.svg', None, _('D'))
|
||||||
|
|
||||||
|
def genesis(self):
|
||||||
|
self.qaction.triggered.connect(self.do_sync)
|
||||||
|
self.gui.create_device_menu()
|
||||||
|
|
||||||
|
def location_selected(self, loc):
|
||||||
|
enabled = loc == 'library'
|
||||||
|
self.qaction.setEnabled(enabled)
|
||||||
|
|
||||||
|
def do_sync(self, *args):
|
||||||
|
self.gui._sync_action_triggered()
|
||||||
|
|
||||||
|
|
||||||
|
class ConnectShareAction(InterfaceAction):
|
||||||
|
|
||||||
|
name = 'Connect Share'
|
||||||
|
action_spec = (_('Connect/share'), 'connect_share.svg', None, None)
|
||||||
|
popup_type = QToolButton.InstantPopup
|
||||||
|
|
||||||
|
def genesis(self):
|
||||||
|
self.share_conn_menu = ShareConnMenu(self.gui)
|
||||||
|
self.share_conn_menu.toggle_server.connect(self.toggle_content_server)
|
||||||
|
self.share_conn_menu.config_email.connect(partial(
|
||||||
|
self.gui.iactions['Preferences'].do_config,
|
||||||
|
initial_category='email'))
|
||||||
|
self.qaction.setMenu(self.share_conn_menu)
|
||||||
|
self.share_conn_menu.connect_to_folder.connect(self.gui.connect_to_folder)
|
||||||
|
self.share_conn_menu.connect_to_itunes.connect(self.gui.connect_to_itunes)
|
||||||
|
|
||||||
|
def location_selected(self, loc):
|
||||||
|
enabled = loc == 'library'
|
||||||
|
self.qaction.setEnabled(enabled)
|
||||||
|
|
||||||
|
def set_state(self, device_connected):
|
||||||
|
self.share_conn_menu.set_state(device_connected)
|
||||||
|
|
||||||
|
def build_email_entries(self):
|
||||||
|
m = self.gui.iactions['Send To Device'].qaction.menu()
|
||||||
|
self.share_conn_menu.build_email_entries(m)
|
||||||
|
|
||||||
|
def content_server_state_changed(self, running):
|
||||||
|
self.share_conn_menu.server_state_changed(running)
|
||||||
|
|
||||||
|
def toggle_content_server(self):
|
||||||
|
if self.gui.content_server is None:
|
||||||
|
self.gui.start_content_server()
|
||||||
|
else:
|
||||||
|
self.gui.content_server.exit()
|
||||||
|
self.gui.content_server = None
|
24
src/calibre/gui2/actions/open.py
Normal file
24
src/calibre/gui2/actions/open.py
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
|
||||||
|
|
||||||
|
__license__ = 'GPL v3'
|
||||||
|
__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||||
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
|
|
||||||
|
from calibre.gui2.actions import InterfaceAction
|
||||||
|
|
||||||
|
class OpenFolderAction(InterfaceAction):
|
||||||
|
|
||||||
|
name = 'Open Folder'
|
||||||
|
action_spec = (_('Open containing folder'), 'document_open.svg', None,
|
||||||
|
_('O'))
|
||||||
|
|
||||||
|
def genesis(self):
|
||||||
|
self.action_open_containing_folder.triggered.connect(self.iactions['View'].view_folder)
|
||||||
|
|
||||||
|
def location_selected(self, loc):
|
||||||
|
enabled = loc == 'library'
|
||||||
|
self.qaction.setEnabled(enabled)
|
||||||
|
|
||||||
|
|
22
src/calibre/gui2/actions/restart.py
Normal file
22
src/calibre/gui2/actions/restart.py
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
|
||||||
|
|
||||||
|
__license__ = 'GPL v3'
|
||||||
|
__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||||
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
|
|
||||||
|
from calibre.gui2.actions import InterfaceAction
|
||||||
|
|
||||||
|
class RestartAction(InterfaceAction):
|
||||||
|
|
||||||
|
name = 'Restart'
|
||||||
|
action_spec = (_('&Restart'), None, None, _('Ctrl+R'))
|
||||||
|
|
||||||
|
def genesis(self):
|
||||||
|
self.qaction.triggered.connect(self.restart)
|
||||||
|
|
||||||
|
def restart(self, *args):
|
||||||
|
self.gui.quit(restart=True)
|
||||||
|
|
||||||
|
|
31
src/calibre/gui2/actions/show_book_details.py
Normal file
31
src/calibre/gui2/actions/show_book_details.py
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
|
||||||
|
|
||||||
|
__license__ = 'GPL v3'
|
||||||
|
__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||||
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
|
|
||||||
|
from calibre.gui2.actions import InterfaceAction
|
||||||
|
from calibre.gui2.dialogs.book_info import BookInfo
|
||||||
|
from calibre.gui2 import error_dialog
|
||||||
|
|
||||||
|
class ShowBookDetailsAction(InterfaceAction):
|
||||||
|
|
||||||
|
name = 'Show Book Details'
|
||||||
|
action_spec = (_('Show book details'), 'dialog_information.svg', None,
|
||||||
|
_('I'))
|
||||||
|
|
||||||
|
def genesis(self):
|
||||||
|
self.qaction.triggered.connect(self.show_book_info)
|
||||||
|
|
||||||
|
def show_book_info(self, *args):
|
||||||
|
if self.gui.current_view() is not self.gui.library_view:
|
||||||
|
error_dialog(self.gui, _('No detailed info available'),
|
||||||
|
_('No detailed information is available for books '
|
||||||
|
'on the device.')).exec_()
|
||||||
|
return
|
||||||
|
index = self.gui.library_view.currentIndex()
|
||||||
|
if index.isValid():
|
||||||
|
BookInfo(self.gui, self.gui.library_view, index).show()
|
||||||
|
|
@ -608,8 +608,6 @@ class DeviceMixin(object): # {{{
|
|||||||
self.device_error_dialog = error_dialog(self, _('Error'),
|
self.device_error_dialog = error_dialog(self, _('Error'),
|
||||||
_('Error communicating with device'), ' ')
|
_('Error communicating with device'), ' ')
|
||||||
self.device_error_dialog.setModal(Qt.NonModal)
|
self.device_error_dialog.setModal(Qt.NonModal)
|
||||||
self.share_conn_menu.connect_to_folder.connect(self.connect_to_folder)
|
|
||||||
self.share_conn_menu.connect_to_itunes.connect(self.connect_to_itunes)
|
|
||||||
self.emailer = Emailer()
|
self.emailer = Emailer()
|
||||||
self.emailer.start()
|
self.emailer.start()
|
||||||
self.device_manager = DeviceManager(Dispatcher(self.device_detected),
|
self.device_manager = DeviceManager(Dispatcher(self.device_detected),
|
||||||
@ -647,21 +645,18 @@ class DeviceMixin(object): # {{{
|
|||||||
|
|
||||||
def create_device_menu(self):
|
def create_device_menu(self):
|
||||||
self._sync_menu = DeviceMenu(self)
|
self._sync_menu = DeviceMenu(self)
|
||||||
self.share_conn_menu.build_email_entries(self._sync_menu)
|
self.iactions['Send To Device'].qaction.setMenu(self._sync_menu)
|
||||||
self.action_sync.setMenu(self._sync_menu)
|
self.iactions['Connect Share'].build_email_entries()
|
||||||
self.connect(self._sync_menu,
|
self.connect(self._sync_menu,
|
||||||
SIGNAL('sync(PyQt_PyObject, PyQt_PyObject, PyQt_PyObject)'),
|
SIGNAL('sync(PyQt_PyObject, PyQt_PyObject, PyQt_PyObject)'),
|
||||||
self.dispatch_sync_event)
|
self.dispatch_sync_event)
|
||||||
self._sync_menu.fetch_annotations.connect(
|
self._sync_menu.fetch_annotations.connect(
|
||||||
self.iactions['Fetch Annotations'].fetch_annotations)
|
self.iactions['Fetch Annotations'].fetch_annotations)
|
||||||
self._sync_menu.disconnect_mounted_device.connect(self.disconnect_mounted_device)
|
self._sync_menu.disconnect_mounted_device.connect(self.disconnect_mounted_device)
|
||||||
|
self.iactions['Connect Share'].set_state(self.device_connected)
|
||||||
if self.device_connected:
|
if self.device_connected:
|
||||||
self.share_conn_menu.connect_to_folder_action.setEnabled(False)
|
|
||||||
self.share_conn_menu.connect_to_itunes_action.setEnabled(False)
|
|
||||||
self._sync_menu.disconnect_mounted_device_action.setEnabled(True)
|
self._sync_menu.disconnect_mounted_device_action.setEnabled(True)
|
||||||
else:
|
else:
|
||||||
self.share_conn_menu.connect_to_folder_action.setEnabled(True)
|
|
||||||
self.share_conn_menu.connect_to_itunes_action.setEnabled(True)
|
|
||||||
self._sync_menu.disconnect_mounted_device_action.setEnabled(False)
|
self._sync_menu.disconnect_mounted_device_action.setEnabled(False)
|
||||||
|
|
||||||
def device_job_exception(self, job):
|
def device_job_exception(self, job):
|
||||||
@ -697,17 +692,14 @@ class DeviceMixin(object): # {{{
|
|||||||
# Device connected {{{
|
# Device connected {{{
|
||||||
|
|
||||||
def set_device_menu_items_state(self, connected):
|
def set_device_menu_items_state(self, connected):
|
||||||
|
self.iactions['Connect Share'].set_state(connected)
|
||||||
if connected:
|
if connected:
|
||||||
self.share_conn_menu.connect_to_folder_action.setEnabled(False)
|
|
||||||
self.share_conn_menu.connect_to_itunes_action.setEnabled(False)
|
|
||||||
self._sync_menu.disconnect_mounted_device_action.setEnabled(True)
|
self._sync_menu.disconnect_mounted_device_action.setEnabled(True)
|
||||||
self._sync_menu.enable_device_actions(True,
|
self._sync_menu.enable_device_actions(True,
|
||||||
self.device_manager.device.card_prefix(),
|
self.device_manager.device.card_prefix(),
|
||||||
self.device_manager.device)
|
self.device_manager.device)
|
||||||
self.eject_action.setEnabled(True)
|
self.eject_action.setEnabled(True)
|
||||||
else:
|
else:
|
||||||
self.share_conn_menu.connect_to_folder_action.setEnabled(True)
|
|
||||||
self.share_conn_menu.connect_to_itunes_action.setEnabled(True)
|
|
||||||
self._sync_menu.disconnect_mounted_device_action.setEnabled(False)
|
self._sync_menu.disconnect_mounted_device_action.setEnabled(False)
|
||||||
self._sync_menu.enable_device_actions(False)
|
self._sync_menu.enable_device_actions(False)
|
||||||
self.eject_action.setEnabled(False)
|
self.eject_action.setEnabled(False)
|
||||||
|
@ -306,7 +306,7 @@ class LayoutMixin(object): # {{{
|
|||||||
|
|
||||||
def finalize_layout(self):
|
def finalize_layout(self):
|
||||||
self.status_bar.initialize(self.system_tray_icon)
|
self.status_bar.initialize(self.system_tray_icon)
|
||||||
self.book_details.show_book_info.connect(self.show_book_info)
|
self.book_details.show_book_info.connect(self.iactions['Show Book Details'].show_book_info)
|
||||||
self.book_details.files_dropped.connect(self.iactions['Add Books'].files_dropped_on_book)
|
self.book_details.files_dropped.connect(self.iactions['Add Books'].files_dropped_on_book)
|
||||||
self.book_details.open_containing_folder.connect(self.iactions['View'].view_folder_for_id)
|
self.book_details.open_containing_folder.connect(self.iactions['View'].view_folder_for_id)
|
||||||
self.book_details.view_specific_format.connect(self.iactions['View'].view_format_by_id)
|
self.book_details.view_specific_format.connect(self.iactions['View'].view_format_by_id)
|
||||||
|
@ -20,7 +20,6 @@ from calibre.gui2 import config, open_url, gprefs
|
|||||||
from calibre.gui2.widgets import ComboBoxWithHelp
|
from calibre.gui2.widgets import ComboBoxWithHelp
|
||||||
from calibre import human_readable
|
from calibre import human_readable
|
||||||
from calibre.gui2.dialogs.scheduler import Scheduler
|
from calibre.gui2.dialogs.scheduler import Scheduler
|
||||||
from calibre.utils.smtp import config as email_config
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -306,77 +305,6 @@ class ToolBar(QToolBar): # {{{
|
|||||||
class Action(QAction):
|
class Action(QAction):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class ShareConnMenu(QMenu): # {{{
|
|
||||||
|
|
||||||
connect_to_folder = pyqtSignal()
|
|
||||||
connect_to_itunes = pyqtSignal()
|
|
||||||
config_email = pyqtSignal()
|
|
||||||
toggle_server = pyqtSignal()
|
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
|
||||||
QMenu.__init__(self, parent)
|
|
||||||
mitem = self.addAction(QIcon(I('devices/folder.svg')), _('Connect to folder'))
|
|
||||||
mitem.setEnabled(True)
|
|
||||||
mitem.triggered.connect(lambda x : self.connect_to_folder.emit())
|
|
||||||
self.connect_to_folder_action = mitem
|
|
||||||
mitem = self.addAction(QIcon(I('devices/itunes.png')),
|
|
||||||
_('Connect to iTunes'))
|
|
||||||
mitem.setEnabled(True)
|
|
||||||
mitem.triggered.connect(lambda x : self.connect_to_itunes.emit())
|
|
||||||
self.connect_to_itunes_action = mitem
|
|
||||||
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 = []
|
|
||||||
|
|
||||||
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):
|
|
||||||
from calibre.gui2.device import DeviceAction
|
|
||||||
for ac in self.email_actions:
|
|
||||||
self.removeAction(ac)
|
|
||||||
self.email_actions = []
|
|
||||||
self.memory = []
|
|
||||||
opts = email_config().parse()
|
|
||||||
if opts.accounts:
|
|
||||||
self.email_to_menu = QMenu(_('Email to')+'...', self)
|
|
||||||
keys = sorted(opts.accounts.keys())
|
|
||||||
for account in keys:
|
|
||||||
formats, auto, default = opts.accounts[account]
|
|
||||||
dest = 'mail:'+account+';'+formats
|
|
||||||
action1 = DeviceAction(dest, False, False, I('mail.svg'),
|
|
||||||
_('Email to')+' '+account)
|
|
||||||
action2 = DeviceAction(dest, True, False, I('mail.svg'),
|
|
||||||
_('Email to')+' '+account+ _(' and delete from library'))
|
|
||||||
map(self.email_to_menu.addAction, (action1, action2))
|
|
||||||
map(self.memory.append, (action1, action2))
|
|
||||||
if default:
|
|
||||||
map(self.addAction, (action1, action2))
|
|
||||||
map(self.email_actions.append, (action1, action2))
|
|
||||||
self.email_to_menu.addSeparator()
|
|
||||||
action1.a_s.connect(sync_menu.action_triggered)
|
|
||||||
action2.a_s.connect(sync_menu.action_triggered)
|
|
||||||
ac = self.addMenu(self.email_to_menu)
|
|
||||||
self.email_actions.append(ac)
|
|
||||||
else:
|
|
||||||
ac = self.addAction(_('Setup email based sharing of books'))
|
|
||||||
self.email_actions.append(ac)
|
|
||||||
ac.triggered.connect(self.setup_email)
|
|
||||||
|
|
||||||
def setup_email(self, *args):
|
|
||||||
self.config_email.emit()
|
|
||||||
|
|
||||||
# }}}
|
|
||||||
|
|
||||||
class MainWindowMixin(object):
|
class MainWindowMixin(object):
|
||||||
|
|
||||||
def __init__(self, db):
|
def __init__(self, db):
|
||||||
@ -442,17 +370,11 @@ class MainWindowMixin(object):
|
|||||||
setattr(self, 'action_'+name, action)
|
setattr(self, 'action_'+name, action)
|
||||||
all_actions.append(action)
|
all_actions.append(action)
|
||||||
|
|
||||||
ac(-1, 4, 0, 'sync', _('Send to device'), 'sync.svg')
|
|
||||||
ac(5, 5, 3, 'choose_library', _('%d books')%0, 'lt.png',
|
ac(5, 5, 3, 'choose_library', _('%d books')%0, 'lt.png',
|
||||||
tooltip=_('Choose calibre library to work with'))
|
tooltip=_('Choose calibre library to work with'))
|
||||||
ac(8, 8, 0, 'conn_share', _('Connect/share'), 'connect_share.svg')
|
|
||||||
ac(10, 10, 3, 'help', _('Help'), 'help.svg', _('F1'), _("Browse the calibre User Manual"))
|
ac(10, 10, 3, 'help', _('Help'), 'help.svg', _('F1'), _("Browse the calibre User Manual"))
|
||||||
ac(11, 11, 0, 'preferences', _('Preferences'), 'config.svg', _('Ctrl+P'))
|
ac(11, 11, 0, 'preferences', _('Preferences'), 'config.svg', _('Ctrl+P'))
|
||||||
|
|
||||||
ac(-1, -1, 0, 'open_containing_folder', _('Open containing folder'),
|
|
||||||
'document_open.svg')
|
|
||||||
ac(-1, -1, 0, 'show_book_details', _('Show book details'),
|
|
||||||
'dialog_information.svg')
|
|
||||||
ac(-1, -1, 0, 'books_by_same_author', _('Books by same author'),
|
ac(-1, -1, 0, 'books_by_same_author', _('Books by same author'),
|
||||||
'user_profile.svg')
|
'user_profile.svg')
|
||||||
ac(-1, -1, 0, 'books_in_this_series', _('Books in this series'),
|
ac(-1, -1, 0, 'books_in_this_series', _('Books in this series'),
|
||||||
@ -462,24 +384,10 @@ class MainWindowMixin(object):
|
|||||||
ac(-1, -1, 0, 'books_with_the_same_tags', _('Books with the same tags'),
|
ac(-1, -1, 0, 'books_with_the_same_tags', _('Books with the same tags'),
|
||||||
'tags.svg')
|
'tags.svg')
|
||||||
|
|
||||||
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,
|
|
||||||
initial_category='email'))
|
|
||||||
self.action_conn_share.setMenu(self.share_conn_menu)
|
|
||||||
|
|
||||||
self.action_help.triggered.connect(self.show_help)
|
self.action_help.triggered.connect(self.show_help)
|
||||||
|
|
||||||
|
|
||||||
self.action_open_containing_folder.setShortcut(Qt.Key_O)
|
|
||||||
self.addAction(self.action_open_containing_folder)
|
|
||||||
self.action_open_containing_folder.triggered.connect(self.iactions['View'].view_folder)
|
|
||||||
self.action_sync.setShortcut(Qt.Key_D)
|
|
||||||
self.action_sync.setEnabled(True)
|
|
||||||
self.create_device_menu()
|
|
||||||
self.action_sync.triggered.connect(
|
|
||||||
self._sync_action_triggered)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
pm = QMenu()
|
pm = QMenu()
|
||||||
@ -498,12 +406,5 @@ 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
|
|
||||||
|
@ -15,7 +15,7 @@ from threading import Thread
|
|||||||
from PyQt4.Qt import Qt, SIGNAL, QTimer, \
|
from PyQt4.Qt import Qt, SIGNAL, QTimer, \
|
||||||
QPixmap, QMenu, QIcon, pyqtSignal, \
|
QPixmap, QMenu, QIcon, pyqtSignal, \
|
||||||
QDialog, \
|
QDialog, \
|
||||||
QSystemTrayIcon, QApplication, QKeySequence, QAction, \
|
QSystemTrayIcon, QApplication, QKeySequence, \
|
||||||
QMessageBox, QHelpEvent
|
QMessageBox, QHelpEvent
|
||||||
|
|
||||||
from calibre import prints
|
from calibre import prints
|
||||||
@ -35,7 +35,6 @@ from calibre.gui2.layout import MainWindowMixin
|
|||||||
from calibre.gui2.device import DeviceMixin
|
from calibre.gui2.device import DeviceMixin
|
||||||
from calibre.gui2.jobs import JobManager, JobsDialog, JobsButton
|
from calibre.gui2.jobs import JobManager, JobsDialog, JobsButton
|
||||||
from calibre.gui2.dialogs.config import ConfigDialog
|
from calibre.gui2.dialogs.config import ConfigDialog
|
||||||
from calibre.gui2.dialogs.book_info import BookInfo
|
|
||||||
from calibre.gui2.init import LibraryViewMixin, LayoutMixin
|
from calibre.gui2.init import LibraryViewMixin, LayoutMixin
|
||||||
from calibre.gui2.search_box import SearchBoxMixin, SavedSearchBoxMixin
|
from calibre.gui2.search_box import SearchBoxMixin, SavedSearchBoxMixin
|
||||||
from calibre.gui2.search_restriction_mixin import SearchRestrictionMixin
|
from calibre.gui2.search_restriction_mixin import SearchRestrictionMixin
|
||||||
@ -172,22 +171,13 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{
|
|||||||
QIcon(I('eject.svg')), _('&Eject connected device'))
|
QIcon(I('eject.svg')), _('&Eject connected device'))
|
||||||
self.eject_action.setEnabled(False)
|
self.eject_action.setEnabled(False)
|
||||||
self.addAction(self.quit_action)
|
self.addAction(self.quit_action)
|
||||||
self.action_restart = QAction(_('&Restart'), self)
|
|
||||||
self.addAction(self.action_restart)
|
|
||||||
self.system_tray_menu.addAction(self.quit_action)
|
self.system_tray_menu.addAction(self.quit_action)
|
||||||
self.quit_action.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_Q))
|
self.quit_action.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_Q))
|
||||||
self.action_restart.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_R))
|
|
||||||
self.action_show_book_details.setShortcut(QKeySequence(Qt.Key_I))
|
|
||||||
self.addAction(self.action_show_book_details)
|
|
||||||
self.system_tray_icon.setContextMenu(self.system_tray_menu)
|
self.system_tray_icon.setContextMenu(self.system_tray_menu)
|
||||||
self.connect(self.quit_action, SIGNAL('triggered(bool)'), self.quit)
|
self.connect(self.quit_action, SIGNAL('triggered(bool)'), self.quit)
|
||||||
self.connect(self.donate_action, SIGNAL('triggered(bool)'), self.donate)
|
self.connect(self.donate_action, SIGNAL('triggered(bool)'), self.donate)
|
||||||
self.connect(self.restore_action, SIGNAL('triggered()'),
|
self.connect(self.restore_action, SIGNAL('triggered()'),
|
||||||
self.show_windows)
|
self.show_windows)
|
||||||
self.connect(self.action_show_book_details,
|
|
||||||
SIGNAL('triggered(bool)'), self.show_book_info)
|
|
||||||
self.connect(self.action_restart, SIGNAL('triggered()'),
|
|
||||||
self.restart)
|
|
||||||
self.connect(self.system_tray_icon,
|
self.connect(self.system_tray_icon,
|
||||||
SIGNAL('activated(QSystemTrayIcon::ActivationReason)'),
|
SIGNAL('activated(QSystemTrayIcon::ActivationReason)'),
|
||||||
self.system_tray_icon_activated)
|
self.system_tray_icon_activated)
|
||||||
@ -270,7 +260,8 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{
|
|||||||
from calibre.library.server import server_config
|
from calibre.library.server import server_config
|
||||||
self.content_server = start_threaded_server(
|
self.content_server = start_threaded_server(
|
||||||
self.library_view.model().db, server_config().parse())
|
self.library_view.model().db, server_config().parse())
|
||||||
self.content_server.state_callback = Dispatcher(self.content_server_state_changed)
|
self.content_server.state_callback = Dispatcher(
|
||||||
|
self.iactions['Connect Share'].content_server_state_changed)
|
||||||
self.content_server.state_callback(True)
|
self.content_server.state_callback(True)
|
||||||
self.test_server_timer = QTimer.singleShot(10000, self.test_server)
|
self.test_server_timer = QTimer.singleShot(10000, self.test_server)
|
||||||
|
|
||||||
@ -381,7 +372,7 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{
|
|||||||
self.content_server = d.server
|
self.content_server = d.server
|
||||||
if self.content_server is not None:
|
if self.content_server is not None:
|
||||||
self.content_server.state_callback = \
|
self.content_server.state_callback = \
|
||||||
Dispatcher(self.content_server_state_changed)
|
Dispatcher(self.iactions['Connect Share'].content_server_state_changed)
|
||||||
self.content_server.state_callback(self.content_server.is_running)
|
self.content_server.state_callback(self.content_server.is_running)
|
||||||
|
|
||||||
if d.result() == d.Accepted:
|
if d.result() == d.Accepted:
|
||||||
@ -411,15 +402,6 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{
|
|||||||
self.scheduler.database_changed(db)
|
self.scheduler.database_changed(db)
|
||||||
prefs['library_path'] = self.library_path
|
prefs['library_path'] = self.library_path
|
||||||
|
|
||||||
def show_book_info(self, *args):
|
|
||||||
if self.current_view() is not self.library_view:
|
|
||||||
error_dialog(self, _('No detailed info available'),
|
|
||||||
_('No detailed information is available for books '
|
|
||||||
'on the device.')).exec_()
|
|
||||||
return
|
|
||||||
index = self.library_view.currentIndex()
|
|
||||||
if index.isValid():
|
|
||||||
BookInfo(self, self.library_view, index).show()
|
|
||||||
|
|
||||||
def location_selected(self, location):
|
def location_selected(self, location):
|
||||||
'''
|
'''
|
||||||
@ -434,12 +416,8 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{
|
|||||||
for action in self.iactions.values():
|
for action in self.iactions.values():
|
||||||
action.location_selected(location)
|
action.location_selected(location)
|
||||||
if location == 'library':
|
if location == 'library':
|
||||||
self.action_open_containing_folder.setEnabled(True)
|
|
||||||
self.action_sync.setEnabled(True)
|
|
||||||
self.search_restriction.setEnabled(True)
|
self.search_restriction.setEnabled(True)
|
||||||
else:
|
else:
|
||||||
self.action_open_containing_folder.setEnabled(False)
|
|
||||||
self.action_sync.setEnabled(False)
|
|
||||||
self.search_restriction.setEnabled(False)
|
self.search_restriction.setEnabled(False)
|
||||||
# Reset the view in case something changed while it was invisible
|
# Reset the view in case something changed while it was invisible
|
||||||
self.current_view().reset()
|
self.current_view().reset()
|
||||||
@ -503,9 +481,6 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{
|
|||||||
dynamic.set('sort_history', self.library_view.model().sort_history)
|
dynamic.set('sort_history', self.library_view.model().sort_history)
|
||||||
self.save_layout_state()
|
self.save_layout_state()
|
||||||
|
|
||||||
def restart(self):
|
|
||||||
self.quit(restart=True)
|
|
||||||
|
|
||||||
def quit(self, checked=True, restart=False):
|
def quit(self, checked=True, restart=False):
|
||||||
if not self.confirm_quit():
|
if not self.confirm_quit():
|
||||||
return
|
return
|
||||||
|
Loading…
x
Reference in New Issue
Block a user