Пример #1
0
def _run(args, notify=None):
    # Ensure we can continue to function if GUI is closed
    os.environ.pop('CALIBRE_WORKER_TEMP_DIR', None)
    reset_base_dir()

    # The following two lines are needed to prevent circular imports causing
    # errors during initialization of plugins that use the polish container
    # infrastructure.
    importlib.import_module('calibre.customize.ui')
    from calibre.gui2.tweak_book.ui import Main

    parser = option_parser()
    opts, args = parser.parse_args(args)
    if getattr(opts, 'detach', False):
        detach_gui()
    override = 'calibre-edit-book' if islinux else None
    app = Application(args, override_program_name=override)
    app.load_builtin_fonts()
    app.setWindowIcon(QIcon(I('tweak.png')))
    Application.setOrganizationName(ORG_NAME)
    Application.setApplicationName(APP_UID)
    main = Main(opts, notify=notify)
    sys.excepthook = main.unhandled_exception
    main.show()
    if len(args) > 1:
        main.boss.open_book(args[1], edit_file=opts.edit_file, clear_notify_data=False)
    app.exec_()
Пример #2
0
def main(args=sys.argv):
    # Ensure viewer can continue to function if GUI is closed
    os.environ.pop('CALIBRE_WORKER_TEMP_DIR', None)
    reset_base_dir()

    parser = option_parser()
    opts, args = parser.parse_args(args)
    if getattr(opts, 'detach', False):
        detach_gui()
    try:
        open_at = float(opts.open_at)
    except:
        open_at = None
    override = 'calibre-ebook-viewer' if islinux else None
    app = Application(args, override_program_name=override)
    app.load_builtin_fonts()
    app.setWindowIcon(QIcon(I('viewer.png')))
    QApplication.setOrganizationName(ORG_NAME)
    QApplication.setApplicationName(APP_UID)
    main = EbookViewer(args[1] if len(args) > 1 else None,
            debug_javascript=opts.debug_javascript, open_at=open_at,
                       start_in_fullscreen=opts.full_screen)
    # This is needed for paged mode. Without it, the first document that is
    # loaded will have extra blank space at the bottom, as
    # turn_off_internal_scrollbars does not take effect for the first
    # rendered document
    main.view.load_path(P('viewer/blank.html', allow_user_override=False))

    sys.excepthook = main.unhandled_exception
    main.show()
    if opts.raise_window:
        main.raise_()
    with main:
        return app.exec_()
    return 0
Пример #3
0
def main(args=sys.argv):
    # Ensure we can continue to function if GUI is closed
    os.environ.pop('CALIBRE_WORKER_TEMP_DIR', None)
    reset_base_dir()

    # The following two lines are needed to prevent circular imports causing
    # errors during initialization of plugins that use the polish container
    # infrastructure.
    importlib.import_module('calibre.customize.ui')
    from calibre.gui2.tweak_book.ui import Main

    parser = option_parser()
    opts, args = parser.parse_args(args)
    if getattr(opts, 'detach', False):
        detach_gui()
    override = 'calibre-tweak-book' if islinux else None
    app = Application(args, override_program_name=override)
    app.load_builtin_fonts()
    app.setWindowIcon(QIcon(I('tweak.png')))
    Application.setOrganizationName(ORG_NAME)
    Application.setApplicationName(APP_UID)
    main = Main(opts)
    sys.excepthook = main.unhandled_exception
    main.show()
    if len(args) > 1:
        main.boss.open_book(args[1])
    app.exec_()
Пример #4
0
def _run(args, notify=None):
    # Ensure we can continue to function if GUI is closed
    os.environ.pop('CALIBRE_WORKER_TEMP_DIR', None)
    reset_base_dir()

    if iswindows:
        # Ensure that all ebook editor instances are grouped together in the task
        # bar. This prevents them from being grouped with viewer process when
        # launched from within calibre, as both use calibre-parallel.exe
        import ctypes
        try:
            ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(
                'com.calibre-ebook.edit-book')
        except:
            pass  # Only available on windows 7 and newer

    # The following two lines are needed to prevent circular imports causing
    # errors during initialization of plugins that use the polish container
    # infrastructure.
    importlib.import_module('calibre.customize.ui')
    from calibre.gui2.tweak_book import tprefs
    from calibre.gui2.tweak_book.ui import Main

    parser = option_parser()
    opts, args = parser.parse_args(args)
    decouple('edit-book-'), set_gui_prefs(tprefs)
    override = 'calibre-edit-book' if islinux else None
    app = Application(args, override_program_name=override, color_prefs=tprefs)
    app.file_event_hook = EventAccumulator()
    app.load_builtin_fonts()
    app.setWindowIcon(QIcon(I('tweak.png')))
    Application.setOrganizationName(ORG_NAME)
    Application.setApplicationName(APP_UID)
    main = Main(opts, notify=notify)
    main.set_exception_handler()
    main.show()
    app.shutdown_signal_received.connect(main.boss.quit)
    if len(args) > 1:
        main.boss.open_book(args[1],
                            edit_file=args[2:],
                            clear_notify_data=False)
    else:
        for path in reversed(app.file_event_hook.events):
            main.boss.open_book(path)
            break
        app.file_event_hook = main.boss.open_book
    app.exec_()
    # Ensure that the parse worker has quit so that temp files can be deleted
    # on windows
    st = time.time()
    from calibre.gui2.tweak_book.preview import parse_worker
    while parse_worker.is_alive() and time.time() - st < 120:
        time.sleep(0.1)
Пример #5
0
def main(args=sys.argv):
    # Ensure viewer can continue to function if GUI is closed
    os.environ.pop('CALIBRE_WORKER_TEMP_DIR', None)
    reset_base_dir()
    scheme = QWebEngineUrlScheme(FAKE_PROTOCOL.encode('ascii'))
    scheme.setSyntax(QWebEngineUrlScheme.Syntax.Host)
    scheme.setFlags(QWebEngineUrlScheme.SecureScheme)
    QWebEngineUrlScheme.registerScheme(scheme)
    override = 'calibre-ebook-viewer' if islinux else None
    app = Application(args, override_program_name=override, windows_app_uid=VIEWER_APP_UID)

    parser = option_parser()
    opts, args = parser.parse_args(args)
    oat = opts.open_at
    if oat and not (
            oat.startswith('toc:') or oat.startswith('toc-href:') or oat.startswith('toc-href-contains:') or
            oat.startswith('epubcfi(/') or is_float(oat)):
        raise SystemExit('Not a valid --open-at value: {}'.format(opts.open_at))

    listener = None
    if get_session_pref('singleinstance', False):
        try:
            listener = ensure_single_instance(args, opts.open_at)
        except Exception as e:
            import traceback
            error_dialog(None, _('Failed to start viewer'), as_unicode(e), det_msg=traceback.format_exc(), show=True)
            raise SystemExit(1)

    acc = EventAccumulator(app)
    app.file_event_hook = acc
    app.load_builtin_fonts()
    app.setWindowIcon(QIcon(I('viewer.png')))
    migrate_previous_viewer_prefs()
    main = EbookViewer(open_at=opts.open_at, continue_reading=opts.continue_reading, force_reload=opts.force_reload)
    main.set_exception_handler()
    if len(args) > 1:
        acc.events.append(os.path.abspath(args[-1]))
    acc.got_file.connect(main.handle_commandline_arg)
    main.show()
    main.msg_from_anotherinstance.connect(main.another_instance_wants_to_talk, type=Qt.QueuedConnection)
    if listener is not None:
        t = Thread(name='ConnListener', target=listen, args=(listener, main.msg_from_anotherinstance))
        t.daemon = True
        t.start()
    QTimer.singleShot(0, acc.flush)
    if opts.raise_window:
        main.raise_()
    if opts.full_screen:
        main.set_full_screen(True)

    app.exec_()
    if listener is not None:
        listener.close()
Пример #6
0
def _run(args, notify=None):
    # Ensure we can continue to function if GUI is closed
    os.environ.pop("CALIBRE_WORKER_TEMP_DIR", None)
    reset_base_dir()

    if iswindows:
        # Ensure that all ebook editor instances are grouped together in the task
        # bar. This prevents them from being grouped with viewer process when
        # launched from within calibre, as both use calibre-parallel.exe
        import ctypes

        try:
            ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID("com.calibre-ebook.edit-book")
        except:
            pass  # Only available on windows 7 and newer

    # The following two lines are needed to prevent circular imports causing
    # errors during initialization of plugins that use the polish container
    # infrastructure.
    importlib.import_module("calibre.customize.ui")
    from calibre.gui2.tweak_book import tprefs
    from calibre.gui2.tweak_book.ui import Main

    parser = option_parser()
    opts, args = parser.parse_args(args)
    decouple("edit-book-"), set_gui_prefs(tprefs)
    override = "calibre-edit-book" if islinux else None
    app = Application(args, override_program_name=override, color_prefs=tprefs)
    app.file_event_hook = EventAccumulator()
    app.load_builtin_fonts()
    app.setWindowIcon(QIcon(I("tweak.png")))
    Application.setOrganizationName(ORG_NAME)
    Application.setApplicationName(APP_UID)
    main = Main(opts, notify=notify)
    main.set_exception_handler()
    main.show()
    app.shutdown_signal_received.connect(main.boss.quit)
    if len(args) > 1:
        main.boss.open_book(args[1], edit_file=args[2:], clear_notify_data=False)
    else:
        for path in reversed(app.file_event_hook.events):
            main.boss.open_book(path)
            break
        app.file_event_hook = main.boss.open_book
    app.exec_()
    # Ensure that the parse worker has quit so that temp files can be deleted
    # on windows
    st = time.time()
    from calibre.gui2.tweak_book.preview import parse_worker

    while parse_worker.is_alive() and time.time() - st < 120:
        time.sleep(0.1)
Пример #7
0
def _run(args, notify=None):
    # Ensure we can continue to function if GUI is closed
    os.environ.pop('CALIBRE_WORKER_TEMP_DIR', None)
    reset_base_dir()
    scheme = QWebEngineUrlScheme(FAKE_PROTOCOL.encode('ascii'))
    scheme.setSyntax(QWebEngineUrlScheme.Syntax.Host)
    scheme.setFlags(QWebEngineUrlScheme.Flag.SecureScheme)
    QWebEngineUrlScheme.registerScheme(scheme)

    # The following two lines are needed to prevent circular imports causing
    # errors during initialization of plugins that use the polish container
    # infrastructure.
    importlib.import_module('calibre.customize.ui')
    from calibre.gui2.tweak_book import tprefs
    from calibre.gui2.tweak_book.ui import Main

    parser = option_parser()
    opts, args = parser.parse_args(args)
    decouple('edit-book-'), set_gui_prefs(tprefs)
    override = 'calibre-edit-book' if islinux else None
    app = Application(args,
                      override_program_name=override,
                      color_prefs=tprefs,
                      windows_app_uid=EDITOR_APP_UID)
    app.file_event_hook = EventAccumulator()
    app.load_builtin_fonts()
    app.setWindowIcon(QIcon(I('tweak.png')))
    main = Main(opts, notify=notify)
    main.set_exception_handler()
    main.show()
    app.shutdown_signal_received.connect(main.boss.quit)
    if len(args) > 1:
        main.boss.open_book(args[1],
                            edit_file=args[2:],
                            clear_notify_data=False,
                            search_text=opts.select_text)
    else:
        for path in reversed(app.file_event_hook.events):
            main.boss.open_book(path)
            break
        app.file_event_hook = main.boss.open_book
    app.exec_()
    # Ensure that the parse worker has quit so that temp files can be deleted
    # on windows
    st = time.time()
    from calibre.gui2.tweak_book.preview import parse_worker
    while parse_worker.is_alive() and time.time() - st < 120:
        time.sleep(0.1)
Пример #8
0
def main(args=sys.argv):
    # Ensure viewer can continue to function if GUI is closed
    os.environ.pop("CALIBRE_WORKER_TEMP_DIR", None)
    reset_base_dir()

    parser = option_parser()
    opts, args = parser.parse_args(args)
    open_at = float(opts.open_at.replace(",", ".")) if opts.open_at else None
    listener = None
    override = "calibre-ebook-viewer" if islinux else None
    app = Application(args, override_program_name=override, color_prefs=vprefs)
    app.load_builtin_fonts()
    app.setWindowIcon(QIcon(I("viewer.png")))
    QApplication.setOrganizationName(ORG_NAME)
    QApplication.setApplicationName(APP_UID)

    if vprefs["singleinstance"]:
        try:
            listener = ensure_single_instance(args, open_at)
        except Exception as e:
            import traceback

            error_dialog(None, _("Failed to start viewer"), as_unicode(e), det_msg=traceback.format_exc(), show=True)
            raise SystemExit(1)

    main = EbookViewer(
        args[1] if len(args) > 1 else None,
        debug_javascript=opts.debug_javascript,
        open_at=open_at,
        continue_reading=opts.continue_reading,
        start_in_fullscreen=opts.full_screen,
        listener=listener,
    )
    app.installEventFilter(main)
    # This is needed for paged mode. Without it, the first document that is
    # loaded will have extra blank space at the bottom, as
    # turn_off_internal_scrollbars does not take effect for the first
    # rendered document
    main.view.load_path(P("viewer/blank.html", allow_user_override=False))

    sys.excepthook = main.unhandled_exception
    main.show()
    if opts.raise_window:
        main.raise_()
    with main:
        return app.exec_()
    return 0
Пример #9
0
def _run(args, notify=None):
    # Ensure we can continue to function if GUI is closed
    os.environ.pop('CALIBRE_WORKER_TEMP_DIR', None)
    reset_base_dir()

    if iswindows:
        # Ensure that all ebook editor instances are grouped together in the task
        # bar. This prevents them from being grouped with viewer process when
        # launched from within calibre, as both use calibre-parallel.exe
        import ctypes
        try:
            ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID('com.calibre-ebook.edit-book')
        except:
            pass  # Only available on windows 7 and newer

    # The following two lines are needed to prevent circular imports causing
    # errors during initialization of plugins that use the polish container
    # infrastructure.
    importlib.import_module('calibre.customize.ui')
    from calibre.gui2.tweak_book.ui import Main

    parser = option_parser()
    opts, args = parser.parse_args(args)
    if getattr(opts, 'detach', False):
        detach_gui()
    decouple('edit-book-')
    override = 'calibre-edit-book' if islinux else None
    app = Application(args, override_program_name=override)
    app.load_builtin_fonts()
    app.setWindowIcon(QIcon(I('tweak.png')))
    Application.setOrganizationName(ORG_NAME)
    Application.setApplicationName(APP_UID)
    main = Main(opts, notify=notify)
    sys.excepthook = main.unhandled_exception
    main.show()
    if len(args) > 1:
        main.boss.open_book(args[1], edit_file=opts.edit_file, clear_notify_data=False)
    app.exec_()
    # Ensure that the parse worker has quit so that temp files can be deleted
    # on windows
    st = time.time()
    from calibre.gui2.tweak_book.preview import parse_worker
    while parse_worker.is_alive() and time.time() - st < 120:
        time.sleep(0.1)
Пример #10
0
def main(args=sys.argv):
    # Ensure we can continue to function if GUI is closed
    os.environ.pop('CALIBRE_WORKER_TEMP_DIR', None)
    reset_base_dir()

    parser = option_parser()
    opts, args = parser.parse_args(args)
    override = 'calibre-tweak-book' if islinux else None
    app = Application(args, override_program_name=override)
    app.load_builtin_fonts()
    app.setWindowIcon(QIcon(I('tweak.png')))
    Application.setOrganizationName(ORG_NAME)
    Application.setApplicationName(APP_UID)
    main = Main(opts)
    sys.excepthook = main.unhandled_exception
    main.show()
    if len(args) > 1:
        main.boss.open_book(args[1])
    app.exec_()
Пример #11
0
def main(args=sys.argv):
    # Ensure viewer can continue to function if GUI is closed
    os.environ.pop('CALIBRE_WORKER_TEMP_DIR', None)
    reset_base_dir()

    parser = option_parser()
    opts, args = parser.parse_args(args)
    open_at = float(opts.open_at.replace(',', '.')) if opts.open_at else None
    listener = None
    override = 'calibre-ebook-viewer' if islinux else None
    app = Application(args, override_program_name=override, color_prefs=vprefs)
    app.load_builtin_fonts()
    app.setWindowIcon(QIcon(I('viewer.png')))
    QApplication.setOrganizationName(ORG_NAME)
    QApplication.setApplicationName(APP_UID)

    if vprefs['singleinstance']:
        try:
            listener = ensure_single_instance(args, open_at)
        except Exception as e:
            import traceback
            error_dialog(None, _('Failed to start viewer'), as_unicode(e), det_msg=traceback.format_exc(), show=True)
            raise SystemExit(1)

    main = EbookViewer(args[1] if len(args) > 1 else None,
            debug_javascript=opts.debug_javascript, open_at=open_at, continue_reading=opts.continue_reading,
                       start_in_fullscreen=opts.full_screen, listener=listener)
    app.installEventFilter(main)
    # This is needed for paged mode. Without it, the first document that is
    # loaded will have extra blank space at the bottom, as
    # turn_off_internal_scrollbars does not take effect for the first
    # rendered document
    main.view.load_path(P('viewer/blank.html', allow_user_override=False))

    sys.excepthook = main.unhandled_exception
    main.show()
    if opts.raise_window:
        main.raise_()
    with main:
        return app.exec_()
    return 0
Пример #12
0
    def palette_changed(self):
        app = QApplication.instance()
        if app.is_dark_theme:
            pal = app.palette()
            col = pal.color(pal.Link)
            self.default_css = 'a { color: %s }\n\n' % col.name(col.HexRgb)
        else:
            self.default_css = ''
        self.document().setDefaultStyleSheet(self.default_css +
                                             self.external_css)
        self.setHtml(self.last_set_html)

    def on_anchor_clicked(self, qurl):
        if not qurl.scheme() and qurl.hasFragment() and qurl.toString(
        ).startswith('#'):
            frag = qurl.fragment(qurl.FullyDecoded)
            if frag:
                self.scrollToAnchor(frag)
                return
        self.anchor_clicked.emit(qurl)


if __name__ == '__main__':
    from calibre.gui2 import Application
    app = Application([])
    app.load_builtin_fonts()
    w = FlowLayout.test()
    w.show()
    app.exec_()
Пример #13
0
        if not self.is_half_star:
            val //= 2
        self.setCurrentIndex(val)

    def keyPressEvent(self, ev):
        if ev == QKeySequence.Undo:
            self.undo()
            return ev.accept()
        if ev == QKeySequence.Redo:
            self.redo()
            return ev.accept()
        k = ev.key()
        num = {getattr(Qt, "Key_%d" % i): i for i in range(6)}.get(k)
        if num is None:
            return QComboBox.keyPressEvent(self, ev)
        ev.accept()
        if self.is_half_star:
            num *= 2
        self.setCurrentIndex(num)


if __name__ == "__main__":
    from calibre.gui2 import Application

    app = Application([])
    app.load_builtin_fonts()
    q = RatingEditor(is_half_star=True)
    q.rating_value = 7
    q.show()
    app.exec_()
Пример #14
0
    def initialize(self, library_path, db, listener, actions, show_gui=True):
        from calibre.gui2 import Application
        app = Application([])
        app.load_builtin_fonts()
        w = QtWidgets.QWidget()
        w.show()
        app.exec_()
        #time.sleep(1000)
        opts = self.opts
        self.preferences_action, self.quit_action = actions
        self.library_path = library_path
        self.library_broker = GuiLibraryBroker(db)
        self.content_server = None
        self.server_change_notification_timer = t = QTimer(self)
        self.server_changes = Queue()
        t.setInterval(1000), t.timeout.connect(
            self.handle_changes_from_server_debounced), t.setSingleShot(True)
        self._spare_pool = None
        self.must_restart_before_config = False
        self.listener = Listener(listener)
        self.check_messages_timer = QTimer()
        self.check_messages_timer.timeout.connect(
            self.another_instance_wants_to_talk)
        self.check_messages_timer.start(1000)

        for ac in self.iactions.values():
            try:
                ac.do_genesis()
            except Exception:
                # Ignore errors in third party plugins
                import traceback
                traceback.print_exc()
                if getattr(ac, 'plugin_path', None) is None:
                    raise
        self.donate_action = QAction(QIcon(I('donate.png')),
                                     _('&Donate to support calibre'), self)
        for st in self.istores.values():
            st.do_genesis()
        MainWindowMixin.init_main_window_mixin(self, db)

        # Jobs Button {{{
        self.job_manager = JobManager()
        self.jobs_dialog = JobsDialog(self, self.job_manager)
        self.jobs_button = JobsButton(parent=self)
        self.jobs_button.initialize(self.jobs_dialog, self.job_manager)
        # }}}

        LayoutMixin.init_layout_mixin(self)
        DeviceMixin.init_device_mixin(self)

        self.progress_indicator = ProgressIndicator(self)
        self.progress_indicator.pos = (0, 20)
        self.verbose = opts.verbose
        self.get_metadata = GetMetadata()
        self.upload_memory = {}
        self.metadata_dialogs = []
        self.default_thumbnail = None
        self.tb_wrapper = textwrap.TextWrapper(width=40)
        self.viewers = collections.deque()
        self.system_tray_icon = None
        do_systray = config['systray_icon'] or opts.start_in_tray
        if do_systray:
            self.system_tray_icon = factory(
                app_id='com.calibre-ebook.gui').create_system_tray_icon(
                    parent=self, title='calibre')
        if self.system_tray_icon is not None:
            self.system_tray_icon.setIcon(
                QIcon(I('lt.png', allow_user_override=False)))
            if not (iswindows or isosx):
                self.system_tray_icon.setIcon(
                    QIcon.fromTheme('calibre-tray',
                                    self.system_tray_icon.icon()))
            self.system_tray_icon.setToolTip(self.jobs_button.tray_tooltip())
            self.system_tray_icon.setVisible(True)
            self.jobs_button.tray_tooltip_updated.connect(
                self.system_tray_icon.setToolTip)
        elif do_systray:
            prints(
                'Failed to create system tray icon, your desktop environment probably'
                ' does not support the StatusNotifier spec https://www.freedesktop.org/wiki/Specifications/StatusNotifierItem/'
            )
        self.system_tray_menu = QMenu(self)
        self.toggle_to_tray_action = self.system_tray_menu.addAction(
            QIcon(I('page.png')), '')
        self.toggle_to_tray_action.triggered.connect(
            self.system_tray_icon_activated)
        self.system_tray_menu.addAction(self.donate_action)
        self.eject_action = self.system_tray_menu.addAction(
            QIcon(I('eject.png')), _('&Eject connected device'))
        self.eject_action.setEnabled(False)
        self.addAction(self.quit_action)
        self.system_tray_menu.addAction(self.quit_action)
        self.keyboard.register_shortcut('quit calibre',
                                        _('Quit calibre'),
                                        default_keys=('Ctrl+Q', ),
                                        action=self.quit_action)
        if self.system_tray_icon is not None:
            self.system_tray_icon.setContextMenu(self.system_tray_menu)
            self.system_tray_icon.activated.connect(
                self.system_tray_icon_activated)
        self.quit_action.triggered[bool].connect(self.quit)
        self.donate_action.triggered[bool].connect(self.donate)
        self.minimize_action = QAction(_('Minimize the calibre window'), self)
        self.addAction(self.minimize_action)
        self.keyboard.register_shortcut('minimize calibre',
                                        self.minimize_action.text(),
                                        default_keys=(),
                                        action=self.minimize_action)
        self.minimize_action.triggered.connect(self.showMinimized)

        self.esc_action = QAction(self)
        self.addAction(self.esc_action)
        self.keyboard.register_shortcut('clear current search',
                                        _('Clear the current search'),
                                        default_keys=('Esc', ),
                                        action=self.esc_action)
        self.esc_action.triggered.connect(self.esc)

        self.shift_esc_action = QAction(self)
        self.addAction(self.shift_esc_action)
        self.keyboard.register_shortcut('focus book list',
                                        _('Focus the book list'),
                                        default_keys=('Shift+Esc', ),
                                        action=self.shift_esc_action)
        self.shift_esc_action.triggered.connect(self.shift_esc)

        self.ctrl_esc_action = QAction(self)
        self.addAction(self.ctrl_esc_action)
        self.keyboard.register_shortcut('clear virtual library',
                                        _('Clear the virtual library'),
                                        default_keys=('Ctrl+Esc', ),
                                        action=self.ctrl_esc_action)
        self.ctrl_esc_action.triggered.connect(self.ctrl_esc)

        self.alt_esc_action = QAction(self)
        self.addAction(self.alt_esc_action)
        self.keyboard.register_shortcut('clear additional restriction',
                                        _('Clear the additional restriction'),
                                        default_keys=('Alt+Esc', ),
                                        action=self.alt_esc_action)
        self.alt_esc_action.triggered.connect(
            self.clear_additional_restriction)

        # ###################### Start spare job server ########################
        QTimer.singleShot(1000, self.create_spare_pool)

        # ###################### Location Manager ########################
        self.location_manager.location_selected.connect(self.location_selected)
        self.location_manager.unmount_device.connect(
            self.device_manager.umount_device)
        self.location_manager.configure_device.connect(
            self.configure_connected_device)
        self.location_manager.update_device_metadata.connect(
            self.update_metadata_on_device)
        self.eject_action.triggered.connect(self.device_manager.umount_device)

        # ################### Update notification ###################
        UpdateMixin.init_update_mixin(self, opts)

        # ###################### Search boxes ########################
        SearchRestrictionMixin.init_search_restriction_mixin(self)
        SavedSearchBoxMixin.init_saved_seach_box_mixin(self)

        # ###################### Library view ########################
        LibraryViewMixin.init_library_view_mixin(self, db)
        SearchBoxMixin.init_search_box_mixin(self)  # Requires current_db

        self.library_view.model().count_changed_signal.connect(
            self.iactions['Choose Library'].count_changed)
        if not gprefs.get('quick_start_guide_added', False):
            try:
                add_quick_start_guide(self.library_view)
            except:
                import traceback
                traceback.print_exc()
        for view in ('library', 'memory', 'card_a', 'card_b'):
            v = getattr(self, '%s_view' % view)
            v.selectionModel().selectionChanged.connect(self.update_status_bar)
            v.model().count_changed_signal.connect(self.update_status_bar)

        self.library_view.model().count_changed()
        self.bars_manager.database_changed(self.library_view.model().db)
        self.library_view.model().database_changed.connect(
            self.bars_manager.database_changed, type=Qt.QueuedConnection)

        # ########################## Tags Browser ##############################
        TagBrowserMixin.init_tag_browser_mixin(self, db)
        self.library_view.model().database_changed.connect(
            self.populate_tb_manage_menu, type=Qt.QueuedConnection)

        # ######################## Search Restriction ##########################
        if db.prefs['virtual_lib_on_startup']:
            self.apply_virtual_library(db.prefs['virtual_lib_on_startup'])
        self.rebuild_vl_tabs()

        # ########################## Cover Flow ################################

        CoverFlowMixin.init_cover_flow_mixin(self)

        self._calculated_available_height = min(max_available_height() - 15,
                                                self.height())
        self.resize(self.width(), self._calculated_available_height)

        self.build_context_menus()

        for ac in self.iactions.values():
            try:
                ac.gui_layout_complete()
            except:
                import traceback
                traceback.print_exc()
                if ac.plugin_path is None:
                    raise

        if config['autolaunch_server']:
            self.start_content_server()

        self.read_settings()

        self.finalize_layout()
        self.bars_manager.start_animation()
        self.set_window_title()

        for ac in self.iactions.values():
            try:
                ac.initialization_complete()
            except:
                import traceback
                traceback.print_exc()
                if ac.plugin_path is None:
                    raise
        self.set_current_library_information(current_library_name(),
                                             db.library_id, db.field_metadata)

        register_keyboard_shortcuts()
        self.keyboard.finalize()
        if show_gui:
            # Note this has to come after restoreGeometry() because of
            # https://bugreports.qt.io/browse/QTBUG-56831
            self.show()
        if self.system_tray_icon is not None and self.system_tray_icon.isVisible(
        ) and opts.start_in_tray:
            self.hide_windows()
        self.auto_adder = AutoAdder(gprefs['auto_add_path'], self)

        # Now that the gui is initialized we can restore the quickview state
        # The same thing will be true for any action-based operation with a
        # layout button
        from calibre.gui2.actions.show_quickview import get_quickview_action_plugin
        qv = get_quickview_action_plugin()
        if qv:
            qv.qv_button.restore_state()
        self.save_layout_state()

        # Collect cycles now
        gc.collect()

        QApplication.instance().shutdown_signal_received.connect(self.quit)
        if show_gui and self.gui_debug is not None:
            QTimer.singleShot(10, self.show_gui_debug_msg)

        self.iactions['Connect Share'].check_smartdevice_menus()
        QTimer.singleShot(1, self.start_smartdevice)
        QTimer.singleShot(100, self.update_toggle_to_tray_action)