def save_annotations(self, in_book_file=True): if not self.current_book_data: return if self.annotations_saver is None: self.annotations_saver = AnnotationsSaveWorker() self.annotations_saver.start() self.annotations_saver.save_annotations( self.current_book_data, in_book_file and get_session_pref('save_annotations_in_ebook', default=True), get_session_pref('sync_annots_user', default=''))
def restore_state(self): state = vprefs['main_window_state'] geom = vprefs['main_window_geometry'] if geom and get_session_pref('remember_window_geometry', default=False): QApplication.instance().safe_restore_geometry(self, geom) else: QApplication.instance().ensure_window_on_screen(self) if state: self.restoreState(state, self.MAIN_WINDOW_STATE_VERSION) self.inspector_dock.setVisible(False) if not get_session_pref('restore_docks', True): for dock_def in self.dock_defs.values(): d = getattr(self, '{}_dock'.format(dock_def.name.partition('-')[0])) d.setVisible(False)
def calibre_book_data(self, book_id, fmt): from calibre.db.annotations import merge_annotations from calibre.gui2.viewer.config import get_session_pref, vprefs vprefs.refresh() sync_annots_user = get_session_pref('sync_annots_user', default='') db = self.gui.current_db.new_api annotations_map = db.annotations_map_for_book(book_id, fmt) if sync_annots_user: other_annotations_map = db.annotations_map_for_book( book_id, fmt, user_type='web', user=sync_annots_user) if other_annotations_map: merge_annotations(other_annotations_map, annotations_map, merge_last_read=False) return { 'book_id': book_id, 'uuid': db.field_for('uuid', book_id), 'fmt': fmt.upper(), 'annotations_map': annotations_map, 'library_id': getattr(self.gui.current_db.new_api, 'server_library_id', None) }
def load_book_annotations(self, calibre_book_data=None): amap = self.current_book_data['annotations_map'] path = os.path.join(self.current_book_data['base'], 'calibre-book-annotations.json') if os.path.exists(path): with open(path, 'rb') as f: raw = f.read() merge_annotations(parse_annotations(raw), amap) path = os.path.join(annotations_dir, self.current_book_data['annotations_path_key']) if os.path.exists(path): with open(path, 'rb') as f: raw = f.read() merge_annotations(parse_annotations(raw), amap) if calibre_book_data is None: bld = self.current_book_data['book_library_details'] if bld is not None: lib_amap = load_annotations_map_from_library(bld) sau = get_session_pref('sync_annots_user', default='') if sau: other_amap = load_annotations_map_from_library(bld, user_type='web', user=sau) if other_amap: merge_annotations(other_amap, lib_amap) if lib_amap: for annot_type, annots in iteritems(lib_amap): merge_annotations(annots, amap) else: for annot_type, annots in iteritems(calibre_book_data['annotations_map']): merge_annotations(annots, amap)
def populate_open_menu(self): m = self.open_menu m.clear() recent = get_session_pref('standalone_recently_opened', group=None, default=()) if recent: for entry in recent: try: path = os.path.abspath(entry['pathtoebook']) except Exception: continue if hasattr(set_book_path, 'pathtoebook') and path == os.path.abspath( set_book_path.pathtoebook): continue if os.path.exists(path): m.addAction('{}\t {}'.format( elided_text(entry['title'], pos='right', width=250), elided_text(os.path.basename(path), width=250))).triggered.connect( partial(self.open_book_at_path.emit, path)) else: self.web_view.remove_recently_opened(path)
def update_mode_action(self): mode = get_session_pref('read_mode', default='paged', group=None) a = self.mode_action if mode == 'paged': a.setChecked(False) a.setToolTip(_('Switch to flow mode -- where the text is not broken into pages')) else: a.setChecked(True) a.setToolTip(_('Switch to paged mode -- where the text is broken into pages'))
def populate_color_scheme_menu(self): m = self.color_scheme_menu m.clear() ccs = get_session_pref('current_color_scheme', group=None) or '' ucs = get_session_pref('user_color_schemes', group=None) or {} def add_action(key, defns): a = m.addAction(defns[key]['name']) a.setCheckable(True) a.setObjectName('color-switch-action:{}'.format(key)) a.triggered.connect(self.color_switch_triggerred) if key == ccs: a.setChecked(True) for key in sorted(ucs, key=lambda x: primary_sort_key(ucs[x]['name'])): add_action(key, ucs) m.addSeparator() for key in sorted(self.default_color_schemes, key=lambda x: primary_sort_key(self.default_color_schemes[x]['name'])): add_action(key, self.default_color_schemes)
def restore_state(self): state = vprefs['main_window_state'] geom = vprefs['main_window_geometry'] if geom and get_session_pref('remember_window_geometry', default=False): QApplication.instance().safe_restore_geometry(self, geom) else: QApplication.instance().ensure_window_on_screen(self) if state: self.restoreState(state, self.MAIN_WINDOW_STATE_VERSION) self.inspector_dock.setVisible(False)
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.Flag.SecureScheme) QWebEngineUrlScheme.registerScheme(scheme) override = 'calibre-ebook-viewer' if islinux else None processed_args = [] internal_book_data = internal_book_data_path = None for arg in args: if arg.startswith('--internal-book-data='): internal_book_data_path = arg.split('=', 1)[1] continue processed_args.append(arg) if internal_book_data_path: try: with lopen(internal_book_data_path, 'rb') as f: internal_book_data = json.load(f) finally: try: os.remove(internal_book_data_path) except OSError: pass args = processed_args 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) or oat.startswith('ref:')): raise SystemExit('Not a valid --open-at value: {}'.format(opts.open_at)) if get_session_pref('singleinstance', False): from calibre.utils.lock import SingleInstance from calibre.gui2.listener import Listener with SingleInstance(singleinstance_name) as si: if si: try: listener = Listener(address=viewer_socket_address(), parent=app) listener.start_listening() except Exception as err: error_dialog(None, _('Failed to start listener'), _( 'Could not start the listener used for single instance viewers. Try rebooting your computer.'), det_msg=str(err), show=True) else: with closing(listener): run_gui(app, opts, args, internal_book_data, listener=listener) else: send_message_to_viewer_instance(args, opts.open_at) else: run_gui(app, opts, args, internal_book_data)
def hide_cursor(self): if get_session_pref('auto_hide_mouse', True): self.cursor_hidden = True QApplication.instance().setOverrideCursor(Qt.CursorShape.BlankCursor)
def initial_cfi_for_current_book(self): lrp = self.current_book_data['annotations_map']['last-read'] if lrp and get_session_pref('remember_last_read', default=True): lrp = lrp[0] if lrp['pos_type'] == 'epubcfi': return lrp['pos']
def visible_in_fullscreen(self): return bool( get_session_pref('show_actions_toolbar_in_fullscreen', default=False))
def update_visibility(self): self.setVisible( bool(get_session_pref('show_actions_toolbar', default=False)))
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 processed_args = [] internal_book_data = internal_book_data_path = None for arg in args: if arg.startswith('--internal-book-data='): internal_book_data_path = arg.split('=', 1)[1] continue processed_args.append(arg) if internal_book_data_path: try: with lopen(internal_book_data_path, 'rb') as f: internal_book_data = json.load(f) finally: try: os.remove(internal_book_data_path) except EnvironmentError: pass args = processed_args 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) or oat.startswith('ref:')): 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, calibre_book_data=internal_book_data) 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()