%PDF- %PDF-
Direktori : /lib/calibre/calibre/gui2/actions/ |
Current File : //lib/calibre/calibre/gui2/actions/device.py |
#!/usr/bin/env python3 __license__ = 'GPL v3' __copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>' __docformat__ = 'restructuredtext en' from qt.core import QIcon, QMenu, QTimer, QToolButton, pyqtSignal, QUrl from calibre.gui2 import info_dialog, question_dialog, open_url from calibre.gui2.actions import InterfaceAction from calibre.gui2.dialogs.smartdevice import SmartdeviceDialog from calibre.utils.icu import primary_sort_key from calibre.utils.smtp import config as email_config def local_url_for_content_server(): from calibre.srv.opts import server_config opts = server_config() interface = opts.listen_on or '0.0.0.0' interface = {'0.0.0.0': '127.0.0.1', '::':'::1'}.get(interface) protocol = 'https' if opts.ssl_certfile and opts.ssl_keyfile else 'http' prefix = opts.url_prefix or '' port = opts.port return f'{protocol}://{interface}:{port}{prefix}' def open_in_browser(): open_url(QUrl(local_url_for_content_server())) class ShareConnMenu(QMenu): # {{{ connect_to_folder = pyqtSignal() config_email = pyqtSignal() toggle_server = pyqtSignal() control_smartdevice = pyqtSignal() server_state_changed_signal = pyqtSignal(object, object) dont_add_to = frozenset(('context-menu-device',)) DEVICE_MSGS = [_('Start wireless device connection'), _('Stop wireless device connection')] def __init__(self, parent=None): QMenu.__init__(self, parent) self.ip_text = '' mitem = self.addAction(QIcon(I('devices/folder.png')), _('Connect to folder')) mitem.setEnabled(True) connect_lambda(mitem.triggered, self, lambda self: self.connect_to_folder.emit()) self.connect_to_folder_action = mitem self.addSeparator() self.toggle_server_action = \ self.addAction(QIcon(I('network-server.png')), _('Start Content server')) connect_lambda(self.toggle_server_action.triggered, self, lambda self: self.toggle_server.emit()) self.open_server_in_browser_action = self.addAction( QIcon(I('forward.png')), _("Visit Content server in browser")) connect_lambda(self.open_server_in_browser_action.triggered, self, lambda self: open_in_browser()) self.open_server_in_browser_action.setVisible(False) self.control_smartdevice_action = \ self.addAction(QIcon(I('dot_red.png')), self.DEVICE_MSGS[0]) connect_lambda(self.control_smartdevice_action.triggered, self, lambda self: self.control_smartdevice.emit()) self.addSeparator() self.email_actions = [] if hasattr(parent, 'keyboard'): r = parent.keyboard.register_shortcut prefix = 'Share/Connect Menu ' gr = ConnectShareAction.action_spec[0] for attr in ('folder', ): ac = getattr(self, 'connect_to_%s_action'%attr) r(prefix + attr, str(ac.text()), action=ac, group=gr) r(prefix+' content server', _('Start/stop Content server'), action=self.toggle_server_action, group=gr) r(prefix + ' open server in browser', self.open_server_in_browser_action.text(), action=self.open_server_in_browser_action, group=gr) def server_state_changed(self, running): from calibre.utils.mdns import get_external_ip, verify_ipV4_address text = _('Start Content server') if running: from calibre.srv.opts import server_config opts = server_config() listen_on = verify_ipV4_address(opts.listen_on) or get_external_ip() protocol = 'HTTPS' if opts.ssl_certfile and opts.ssl_keyfile else 'HTTP' try: ip_text = ' ' + _('[{ip}, port {port}, {protocol}]').format( ip=listen_on, port=opts.port, protocol=protocol) except Exception: ip_text = f' [{listen_on} {protocol}]' self.ip_text = ip_text self.server_state_changed_signal.emit(running, ip_text) text = _('Stop Content server') + ip_text else: self.ip_text = '' self.toggle_server_action.setText(text) self.open_server_in_browser_action.setVisible(running) def hide_smartdevice_menus(self): self.control_smartdevice_action.setVisible(False) 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) ac = self.addMenu(self.email_to_menu) self.email_actions.append(ac) self.email_to_and_delete_menu = QMenu( _('Email to and delete from library')+'...', self) keys = sorted(opts.accounts.keys()) def sk(account): return primary_sort_key(opts.aliases.get(account) or account) for account in sorted(keys, key=sk): formats, auto, default = opts.accounts[account] subject = opts.subjects.get(account, '') alias = opts.aliases.get(account, '') dest = 'mail:'+account+';'+formats+';'+subject action1 = DeviceAction(dest, False, False, I('mail.png'), alias or account) action2 = DeviceAction(dest, True, False, I('mail.png'), (alias or account) + ' ' + _('(delete from library)')) self.email_to_menu.addAction(action1) self.email_to_and_delete_menu.addAction(action2) self.memory.append(action1) self.memory.append(action2) if default: ac = DeviceAction(dest, False, False, I('mail.png'), _('Email to') + ' ' +(alias or account)) self.addAction(ac) self.email_actions.append(ac) ac.a_s.connect(sync_menu.action_triggered) action1.a_s.connect(sync_menu.action_triggered) action2.a_s.connect(sync_menu.action_triggered) action1 = DeviceAction('choosemail:', False, False, I('mail.png'), _('Select recipients')) action2 = DeviceAction('choosemail:', True, False, I('mail.png'), _('Select recipients') + ' ' + _('(delete from library)')) self.email_to_menu.addAction(action1) self.email_to_and_delete_menu.addAction(action2) self.memory.append(action1) self.memory.append(action2) tac1 = DeviceAction('choosemail:', False, False, I('mail.png'), _('Email to selected recipients...')) self.addAction(tac1) tac1.a_s.connect(sync_menu.action_triggered) self.memory.append(tac1) self.email_actions.append(tac1) ac = self.addMenu(self.email_to_and_delete_menu) self.email_actions.append(ac) action1.a_s.connect(sync_menu.action_triggered) action2.a_s.connect(sync_menu.action_triggered) else: ac = self.addAction(QIcon.ic('mail.png'), _('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, device): self.connect_to_folder_action.setEnabled(not device_connected) # }}} class SendToDeviceAction(InterfaceAction): name = 'Send To Device' action_spec = (_('Send to device'), 'sync.png', None, _('D')) dont_add_to = frozenset(('menubar', 'toolbar', 'context-menu', 'toolbar-child')) 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) self.menuless_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.png', _('Share books using a web server or email. Connect to special devices, etc.'), None) popup_type = QToolButton.ToolButtonPopupMode.InstantPopup def genesis(self): self.content_server_is_running = False self.share_conn_menu = ShareConnMenu(self.gui) self.share_conn_menu.aboutToShow.connect(self.set_smartdevice_action_state) self.share_conn_menu.toggle_server.connect(self.toggle_content_server) self.share_conn_menu.control_smartdevice.connect(self.control_smartdevice) connect_lambda(self.share_conn_menu.config_email, self, lambda self: self.gui.iactions['Preferences'].do_config(initial_plugin=('Sharing', 'Email'), close_after_initial=True)) self.qaction.setMenu(self.share_conn_menu) self.share_conn_menu.connect_to_folder.connect(self.gui.connect_to_folder) def location_selected(self, loc): enabled = loc == 'library' self.qaction.setEnabled(enabled) self.menuless_qaction.setEnabled(enabled) def set_state(self, device_connected, device): self.share_conn_menu.set_state(device_connected, device) 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) if running: self.content_server_is_running = True self.qaction.setIcon(QIcon(I('connect_share_on.png'))) else: self.content_server_is_running = False self.qaction.setIcon(QIcon(I('connect_share.png'))) def toggle_content_server(self): if self.gui.content_server is None: self.gui.start_content_server() else: self.gui.content_server.stop() self.stopping_msg = info_dialog(self.gui, _('Stopping'), _('Stopping server, this could take up to a minute, please wait...'), show_copy_button=False) QTimer.singleShot(1000, self.check_exited) self.stopping_msg.exec() def check_exited(self): if getattr(self.gui.content_server, 'is_running', False): QTimer.singleShot(50, self.check_exited) return self.gui.content_server = None self.stopping_msg.accept() def control_smartdevice(self): dm = self.gui.device_manager running = dm.is_running('smartdevice') if running: dm.stop_plugin('smartdevice') if dm.get_option('smartdevice', 'autostart'): if not question_dialog(self.gui, _('Disable autostart'), _('Do you want wireless device connections to be' ' started automatically when calibre starts?')): dm.set_option('smartdevice', 'autostart', False) else: sd_dialog = SmartdeviceDialog(self.gui) sd_dialog.exec() self.set_smartdevice_action_state() def check_smartdevice_menus(self): if not self.gui.device_manager.is_enabled('smartdevice'): self.share_conn_menu.hide_smartdevice_menus() def set_smartdevice_action_state(self): from calibre.gui2.dialogs.smartdevice import get_all_ip_addresses dm = self.gui.device_manager forced_ip = dm.get_option('smartdevice', 'force_ip_address') if forced_ip: formatted_addresses = forced_ip show_port = True else: all_ips = get_all_ip_addresses() if len(all_ips) == 0: formatted_addresses = _('Still looking for IP addresses') show_port = False elif len(all_ips) > 3: formatted_addresses = _('Many IP addresses. See Start/Stop dialog.') show_port = False else: formatted_addresses = ' or '.join(get_all_ip_addresses()) show_port = True running = dm.is_running('smartdevice') if not running: text = self.share_conn_menu.DEVICE_MSGS[0] else: use_fixed_port = dm.get_option('smartdevice', 'use_fixed_port') port_number = dm.get_option('smartdevice', 'port_number') if show_port and use_fixed_port: text = self.share_conn_menu.DEVICE_MSGS[1] + ' [%s, port %s]'%( formatted_addresses, port_number) else: text = self.share_conn_menu.DEVICE_MSGS[1] + ' [' + formatted_addresses + ']' icon = 'green' if running else 'red' ac = self.share_conn_menu.control_smartdevice_action ac.setIcon(QIcon(I('dot_%s.png'%icon))) ac.setText(text)