def __call__(self, item, where): self.current_item, self.current_where = item, where self.current_name = None self.current_frag = None self.name.setText(_('(Untitled)')) dest_index, frag = 0, None if item is not None: if where is None: self.name.setText(item.data(0, Qt.DisplayRole) or '') self.name.setCursorPosition(0) toc = item.data(0, Qt.UserRole) if toc.dest: for i in xrange(self.dest_list.count()): litem = self.dest_list.item(i) if unicode(litem.data(Qt.DisplayRole) or '') == toc.dest: dest_index = i frag = toc.frag break self.dest_list.blockSignals(True) self.dest_list.setCurrentRow(dest_index) self.dest_list.blockSignals(False) item = self.dest_list.item(dest_index) self.current_changed(item) if frag: self.current_frag = frag QTimer.singleShot(1, self.show_frag)
def do_one_isbn_add(self): try: db = self.gui.library_view.model().db try: x = self.isbn_books.pop(0) except IndexError: self.gui.library_view.model().books_added(self.isbn_add_dialog.value) self.isbn_add_dialog.accept() self.gui.iactions['Edit Metadata'].download_metadata( ids=self.add_by_isbn_ids, ensure_fields=frozenset(['title', 'authors'])) return mi = MetaInformation(None) mi.isbn = x['isbn'] if self.isbn_add_tags: mi.tags = list(self.isbn_add_tags) fmts = [] if x['path'] is None else [x['path']] self.add_by_isbn_ids.add(db.import_book(mi, fmts)) self.isbn_add_dialog.value += 1 QTimer.singleShot(10, self.do_one_isbn_add) except: self.isbn_add_dialog.accept() raise
def execute(self): if not self.timer.isActive() or self.is_date_changed: QTimer.singleShot(500, self.setTime) self.timer.stop() index = self.ui.countryList.currentIndex() ctx.installData.timezone = self.ui.countryList.itemData(index) ctx.logger.debug("Time zone selected as %s " % ctx.installData.timezone) if ctx.flags.install_type == ctx.STEP_BASE: #FIXME:Refactor hacky code ctx.installData.rootPassword = ctx.consts.default_password ctx.installData.hostName = yali.util.product_release() if ctx.storageInitialized: disks = filter(lambda d: not d.format.hidden, ctx.storage.disks) if len(disks) == 1: ctx.storage.clearPartDisks = [disks[0].name] ctx.mainScreen.step_increment = 2 else: ctx.mainScreen.step_increment = 1 return True else: self.pds_messagebox.setMessage(_("Storage Devices initialising...")) self.pds_messagebox.animate(start=MIDCENTER, stop=MIDCENTER) ctx.mainScreen.step_increment = 0 self.pthread.start() QTimer.singleShot(2, self.startStorageInitialize) return False return True
def do_one_block(self): try: start_cursor, end_cursor = self.requests[0] except IndexError: return self.ignore_requests = True try: block = start_cursor.block() if not block.isValid(): self.requests.popleft() return formats, force_next_highlight = self.parse_single_block(block) self.apply_format_changes(block, formats) try: self.doc.markContentsDirty(block.position(), block.length()) except AttributeError: self.requests.clear() return ok = start_cursor.movePosition(start_cursor.NextBlock) if not ok: self.requests.popleft() return next_block = start_cursor.block() if next_block.position() > end_cursor.position(): if force_next_highlight: end_cursor.setPosition(next_block.position() + 1) else: self.requests.popleft() return finally: self.ignore_requests = False QTimer.singleShot(0, self.do_one_block)
def finalize_layout(self): self.status_bar.initialize(self.system_tray_icon) 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.cover_changed.connect(self.bd_cover_changed, type=Qt.QueuedConnection) self.book_details.cover_removed.connect(self.bd_cover_removed, type=Qt.QueuedConnection) self.book_details.remote_file_dropped.connect( self.iactions['Add Books'].remote_file_dropped_on_book, type=Qt.QueuedConnection) 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.search_requested.connect(self.search.set_search_string) self.book_details.remove_specific_format.connect( self.iactions['Remove Books'].remove_format_by_id) self.book_details.save_specific_format.connect( self.iactions['Save To Disk'].save_library_format_by_ids) self.book_details.restore_specific_format.connect( self.iactions['Remove Books'].restore_format) self.book_details.copy_link.connect(self.bd_copy_link, type=Qt.QueuedConnection) self.book_details.view_device_book.connect( self.iactions['View'].view_device_book) self.book_details.manage_author.connect(lambda author:self.do_author_sort_edit(self, author, select_sort=False, select_link=False)) self.book_details.compare_specific_format.connect(self.compare_format) m = self.library_view.model() if m.rowCount(None) > 0: QTimer.singleShot(0, self.library_view.set_current_row) m.current_changed(self.library_view.currentIndex(), self.library_view.currentIndex()) self.library_view.setFocus(Qt.OtherFocusReason)
def __init__(self, log, parent=None): QDialog.__init__(self, parent) self.log = log self.l = l = QVBoxLayout() self.setLayout(l) self.tb = QTextBrowser(self) l.addWidget(self.tb) self.bb = QDialogButtonBox(QDialogButtonBox.Close) l.addWidget(self.bb) self.copy_button = self.bb.addButton(_('Copy to clipboard'), self.bb.ActionRole) self.copy_button.clicked.connect(self.copy_to_clipboard) self.copy_button.setIcon(QIcon(I('edit-copy.png'))) self.bb.rejected.connect(self.reject) self.bb.accepted.connect(self.accept) self.setWindowTitle(_('Download log')) self.setWindowIcon(QIcon(I('debug.png'))) self.resize(QSize(800, 400)) self.keep_updating = True self.last_html = None self.finished.connect(self.stop) QTimer.singleShot(100, self.update_log) self.show()
def __init__(self, parent, library_path, wait_time=2): QDialog.__init__(self, parent) self.l = QVBoxLayout() self.setLayout(self.l) self.l1 = QLabel('<b>'+_('Restoring database from backups, do not' ' interrupt, this will happen in three stages')+'...') self.setWindowTitle(_('Restoring database')) self.l.addWidget(self.l1) self.pb = QProgressBar(self) self.l.addWidget(self.pb) self.pb.setMaximum(0) self.pb.setMinimum(0) self.msg = QLabel('') self.l.addWidget(self.msg) self.msg.setWordWrap(True) self.bb = QDialogButtonBox(QDialogButtonBox.Cancel) self.l.addWidget(self.bb) self.bb.rejected.connect(self.reject) self.resize(self.sizeHint() + QSize(100, 50)) self.error = None self.rejected = False self.library_path = library_path self.update_signal.connect(self.do_update, type=Qt.QueuedConnection) from calibre.db.restore import Restore self.restorer = Restore(library_path, self) self.restorer.daemon = True # Give the metadata backup thread time to stop QTimer.singleShot(wait_time * 1000, self.start)
def __init__(self, parent, db): QObject.__init__(self, parent) self.internet_connection_failed = False self._parent = parent self.no_internet_msg = _('Cannot download news as no internet connection ' 'is active') self.no_internet_dialog = d = error_dialog(self._parent, self.no_internet_msg, _('No internet connection'), show_copy_button=False) d.setModal(False) self.recipe_model = RecipeModel() self.db = db self.lock = QMutex(QMutex.Recursive) self.download_queue = set([]) self.news_menu = QMenu() self.news_icon = QIcon(I('news.png')) self.scheduler_action = QAction(QIcon(I('scheduler.png')), _('Schedule news download'), self) self.news_menu.addAction(self.scheduler_action) self.scheduler_action.triggered[bool].connect(self.show_dialog) self.cac = QAction(QIcon(I('user_profile.png')), _('Add a custom news source'), self) self.cac.triggered[bool].connect(self.customize_feeds) self.news_menu.addAction(self.cac) self.news_menu.addSeparator() self.all_action = self.news_menu.addAction( _('Download all scheduled news sources'), self.download_all_scheduled) self.timer = QTimer(self) self.timer.start(int(self.INTERVAL * 60 * 1000)) self.timer.timeout.connect(self.check) self.oldest = gconf['oldest_news'] QTimer.singleShot(5 * 1000, self.oldest_check)
def perform_action(self, ac, loc): if ac in ('new', 'existing'): self.callback(loc, copy_structure=self.copy_structure.isChecked()) else: # move library self.db.prefs.disable_setting = True abort_move = Event() pd = ProgressDialog(_('Moving library, please wait...'), _('Scanning...'), max=0, min=0, icon='lt.png', parent=self) pd.canceled_signal.connect(abort_move.set) self.parent().library_view.model().stop_metadata_backup() move_error = [] def do_move(): try: self.db.new_api.move_library_to(loc, abort=abort_move, progress=pd.show_new_progress) except Exception: import traceback move_error.append(traceback.format_exc()) finally: pd.finished_moving.emit() t = Thread(name='MoveLibrary', target=do_move) QTimer.singleShot(0, t.start) pd.exec_() if abort_move.is_set(): self.callback(self.db.library_path) return if move_error: error_dialog(self.parent(), _('Failed to move library'), _( 'There was an error while moving the library. The operation has been aborted. Click' ' "Show details" for details.'), det_msg=move_error[0], show=True) self.callback(self.db.library_path) return self.callback(loc, library_renamed=True)
def confirm_delete(self, spine_items, other_names): spine_names = {name for name, remove in spine_items if remove} if not question_dialog(self, _('Are you sure?'), _( 'Are you sure you want to delete the selected files?'), det_msg='\n'.join(spine_names | other_names)): return self.delete_requested.emit(spine_items, other_names) QTimer.singleShot(10, self.refresh)
def dump(self, items, out_stream, pdf_metadata): self.metadata = pdf_metadata self._delete_tmpdir() self.outline = Outline(self.toc, items) self.render_queue = items self.combine_queue = [] self.out_stream = out_stream self.insert_cover() self.render_succeeded = False self.current_page_num = self.doc.page_count() self.combine_queue.append(os.path.join(self.tmp_path, 'qprinter_out.pdf')) self.first_page = True self.setup_printer(self.combine_queue[-1]) QTimer.singleShot(0, self._render_book) self.loop.exec_() if self.painter is not None: self.painter.end() if self.printer is not None: self.printer.abort() if not self.render_succeeded: raise Exception('Rendering HTML to PDF failed')
def link_clicked(self, url): path = os.path.abspath(unicode(url.toLocalFile())) frag = None if path in self.iterator.spine: self.update_page_number() # Ensure page number is accurate as it is used for history self.history.add(self.pos.value()) path = self.iterator.spine[self.iterator.spine.index(path)] if url.hasFragment(): frag = unicode(url.fragment()) if path != self.current_page: self.pending_anchor = frag self.load_path(path) else: oldpos = self.view.document.ypos if frag: self.view.scroll_to(frag) else: # Scroll to top self.view.scroll_to(0) if self.view.document.ypos == oldpos: # If we are coming from goto_next_section() call this will # cause another goto next section call with the next toc # entry, since this one did not cause any scrolling at all. QTimer.singleShot(10, self.update_indexing_state) else: open_url(url)
def do_book_action(self): if self.wasCanceled(): return self.do_close() if self.i >= self.total_count: return self.do_close() epub_format = self.entries[self.i] self.i += 1 # assign the elements of the 3-tuple details to legible variables book_id, mi, path = epub_format[0], epub_format[1], epub_format[2] # Get the title and build the caption and label text from the string parameters provided dtitle = mi.title self.setWindowTitle('{0} {1} {2} ({3} {4} failures)...'.format(self.action_type[0], self.total_count, self.status_msg_type, len(self.failures), self.action_type[1])) self.setLabelText('{0}: {1}'.format(self.action_type[0], dtitle)) # Send the necessary elements to the process_epub_formats callback function (action.py) # and record the results if self.callback_fn(book_id, mi, path): self.successes.append((book_id, mi, path)) else: self.failures.append((book_id, mi, path)) self.setValue(self.i) # Lather, rinse, repeat QTimer.singleShot(0, self.do_book_action)
def __init__(self, container, do_embed=False): self.container = container self.log = self.logger = container.log self.do_embed = do_embed must_use_qt() self.parser = CSSParser(loglevel=logging.CRITICAL, log=logging.getLogger('calibre.css')) self.first_letter_pat = regex.compile(r'^[\p{Ps}\p{Ps}\p{Pe}\p{Pi}\p{Pf}\p{Po}]+', regex.VERSION1 | regex.UNICODE) self.loop = QEventLoop() self.view = QWebView() self.page = Page(self.log) self.view.setPage(self.page) self.page.setViewportSize(QSize(1200, 1600)) self.view.loadFinished.connect(self.collect, type=Qt.QueuedConnection) self.render_queue = list(container.spine_items) self.font_stats = {} self.font_usage_map = {} self.font_spec_map = {} self.font_rule_map = {} self.all_font_rules = {} QTimer.singleShot(0, self.render_book) if self.loop.exec_() == 1: raise Exception('Failed to gather statistics from book, see log for details')
def load_finished(self, ok): self.close_progress_indicator() path = self.view.path() try: index = self.iterator.spine.index(path) except (ValueError, AttributeError): return -1 self.current_page = self.iterator.spine[index] self.current_index = index self.set_page_number(self.view.scroll_fraction) QTimer.singleShot(100, self.update_indexing_state) if self.pending_search is not None: self.do_search(self.pending_search, self.pending_search_dir=='backwards') self.pending_search = None self.pending_search_dir = None if self.pending_anchor is not None: self.view.scroll_to(self.pending_anchor) self.pending_anchor = None if self.pending_reference is not None: self.view.goto(self.pending_reference) self.pending_reference = None if self.pending_bookmark is not None: self.goto_bookmark(self.pending_bookmark) self.pending_bookmark = None if self.pending_restore: self.view.document.page_position.restore() return self.current_index
def check(self): if self.rejected: return if self.thread.is_alive(): QTimer.singleShot(100, self.check) else: self.accept()
def close_tab(self, tab=None): tab = tab or self.current_tab if tab is not None: self.delete_removed_tabs(self.tab_tree.remove_tab(tab)) if not self.tabs: self.open_url(WELCOME_URL, switch_to_tab=True) QTimer.singleShot(0, self.current_tab_changed)
def drop_event(self, event, mime_data): mime = 'application/calibre+from_library' if mime_data.hasFormat(mime): self.dropped_ids = tuple(map(int, str(mime_data.data(mime)).split())) QTimer.singleShot(1, self.do_drop) return True return False
def main(): from calibre.gui2 import Application from PyQt5.Qt import QMainWindow, QStatusBar, QTimer app = Application([]) w = QMainWindow() s = QStatusBar(w) w.setStatusBar(s) s.showMessage("Testing ProceedQuestion") w.show() p = ProceedQuestion(w) def doit(): p.dummy_question() p.dummy_question(action_label="A very long button for testing relayout (indeed)") p( lambda p: None, None, "ass2", "ass2", "testing2", "testing2", det_msg="details shown first, with a long line to test wrapping of text and width layout", show_det=True, show_ok=True, ) QTimer.singleShot(10, doit) app.exec_()
def do_book_action(self): if self.wasCanceled(): return self.do_close() if self.i >= self.total_count: return self.do_close() book = self.indices[self.i] self.i += 1 # Get the title and build the caption and label text from the string parameters provided if self.db_type == 'calibre': dtitle = book[0].title elif self.db_type == 'kobo': dtitle = book.title self.setWindowTitle('{0} {1} {2} ({3} {4} failures)...'.format(self.action_type[0], self.total_count, self.status_msg_type, len(self.failures), self.action_type[1])) self.setLabelText('{0}: {1}'.format(self.action_type[0], dtitle)) # If a calibre db, feed the calibre bookmap to action.py's add_new_books method if self.db_type == 'calibre': if self.callback_fn([book]): self.successes.append(book) else: self.failures.append(book) # If a kobo db, feed the index to the kobo book to action.py's get_decrypted_kobo_books method elif self.db_type == 'kobo': if self.callback_fn(book): debug_print("DecryptAddProgressDialog::do_book_action - decrypted book: '%s'" % dtitle) self.successes.append(book) else: debug_print("DecryptAddProgressDialog::do_book_action - book decryption failed: '%s'" % dtitle) self.failures.append(book) self.setValue(self.i) # Lather, rinse, repeat. QTimer.singleShot(0, self.do_book_action)
def add_event(self, event_type, msg, timer=False, host=None): """ Add event to events list :param event_type: the type of event: OK, DOWN, ACK, ... :type event_type: str :param msg: message of event :type msg: str :param timer: timer to hide event at end of time :type timer: bool :param host: data of a host to set ``Qt.UserRole`` :type host: None | str """ if not self.event_exist(msg): logger.debug( 'Add Event: msg: %s, timer: %s, host: %s', msg, timer, host ) event = EventItem() event.initialize(event_type, msg, timer=timer, host=host) self.events_list.insertItem(0, event) if timer: event_duration = int( settings.get_config('Alignak-app', 'notification_duration') ) * 1000 QTimer.singleShot( event_duration, lambda: self.remove_timer_event(event) ) else: logger.debug( 'Event with msg: %s already exist.', msg )
def stop_server(self): self.gui.content_server.threaded_exit() self.stopping_msg = info_dialog(self, _('Stopping'), _('Stopping server, this could take upto a minute, please wait...'), show_copy_button=False) QTimer.singleShot(500, self.check_exited) self.stopping_msg.exec_()
def check_exited(self): if getattr(self.server, 'is_running', False): QTimer.singleShot(20, self.check_exited) return self.gui.content_server = None self.main_tab.update_button_state() self.stopping_msg.accept()
def __init__(self, parent, request): QNetworkReply.__init__(self, parent) self.setOpenMode(QNetworkReply.ReadOnly | QNetworkReply.Unbuffered) self.setHeader(QNetworkRequest.ContentTypeHeader, 'application/octet-stream') self.setHeader(QNetworkRequest.ContentLengthHeader, 0) self.setRequest(request) self.setUrl(request.url()) QTimer.singleShot(0, self.finalize_reply)
def check_exited(self): if self.gui.content_server.is_running: QTimer.singleShot(20, self.check_exited) if not self.stopping_msg.isVisible(): self.stopping_msg.exec_() return self.gui.content_server = None self.stopping_msg.accept()
def update_log(self): if not self.keep_updating: return html = self.log.html if html != self.last_html: self.last_html = html self.tb.setHtml('<pre style="font-family:monospace">%s</pre>'%html) QTimer.singleShot(1000, self.update_log)
def __init__(self, parent=None, initial=None): QDialog.__init__(self, parent) self.setWindowTitle(_('Choose a texture')) self.l = l = QVBoxLayout() self.setLayout(l) self.tdir = texture_dir() self.images = il = QListWidget(self) il.itemDoubleClicked.connect(self.accept, type=Qt.QueuedConnection) il.setIconSize(QSize(256, 256)) il.setViewMode(il.IconMode) il.setFlow(il.LeftToRight) il.setSpacing(20) il.setSelectionMode(il.SingleSelection) il.itemSelectionChanged.connect(self.update_remove_state) l.addWidget(il) self.ad = ad = QLabel(_('The builtin textures come from <a href="https://subtlepatterns.com">subtlepatterns.com</a>.')) ad.setOpenExternalLinks(True) ad.setWordWrap(True) l.addWidget(ad) self.bb = bb = QDialogButtonBox(QDialogButtonBox.Ok|QDialogButtonBox.Cancel) bb.accepted.connect(self.accept) bb.rejected.connect(self.reject) b = self.add_button = bb.addButton(_('Add texture'), bb.ActionRole) b.setIcon(QIcon(I('plus.png'))) b.clicked.connect(self.add_texture) b = self.remove_button = bb.addButton(_('Remove texture'), bb.ActionRole) b.setIcon(QIcon(I('minus.png'))) b.clicked.connect(self.remove_texture) l.addWidget(bb) images = [{ 'fname': ':'+os.path.basename(x), 'path': x, 'name': ' '.join(map(lambda s: s.capitalize(), os.path.splitext(os.path.basename(x))[0].split('_'))) } for x in glob.glob(I('textures/*.png'))] + [{ 'fname': os.path.basename(x), 'path': x, 'name': os.path.splitext(os.path.basename(x))[0], } for x in glob.glob(os.path.join(self.tdir, '*')) if x.rpartition('.')[-1].lower() in {'jpeg', 'png', 'jpg'}] images.sort(key=lambda x:sort_key(x['name'])) for i in images: self.create_item(i) self.update_remove_state() if initial: existing = {unicode_type(i.data(Qt.UserRole) or ''):i for i in (self.images.item(c) for c in range(self.images.count()))} item = existing.get(initial, None) if item is not None: item.setSelected(True) QTimer.singleShot(100, partial(il.scrollToItem, item)) self.resize(QSize(950, 650))
def start_download(self): self.worker.start() QTimer.singleShot(50, self.update) self.exec_() if self.worker.err is not None: error_dialog(self.parent(), _('Download failed'), _('Failed to download from %(url)r with error: %(err)s')%dict( url=self.worker.url, err=self.worker.err), det_msg=self.worker.tb, show=True)
def cover_browser_shown(self): self.cover_flow.setFocus(Qt.OtherFocusReason) if CoverFlow is not None: self.cover_flow.setCurrentSlide(self.library_view.currentIndex().row()) self.cover_flow_syncing_enabled = True QTimer.singleShot(500, self.cover_flow_do_sync) self.library_view.setCurrentIndex( self.library_view.currentIndex()) self.library_view.scroll_to_row(self.library_view.currentIndex().row())
def add_isbns(self, books, add_tags=[]): self.isbn_books = list(books) self.add_by_isbn_ids = set() self.isbn_add_tags = add_tags QTimer.singleShot(10, self.do_one_isbn_add) self.isbn_add_dialog = ProgressDialog(_('Adding'), _('Creating book records from ISBNs'), max=len(books), cancelable=False, parent=self.gui) self.isbn_add_dialog.exec_()
def initialize(self, library_path, db, listener, actions, show_gui=True): opts = self.opts self.preferences_action, self.quit_action = actions self.library_path = library_path self.content_server = None 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(horizontal=True, 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 if config['systray_icon']: 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'))) if not (iswindows or isosx): self.system_tray_icon.setIcon( QIcon.fromTheme('calibre-gui', QIcon(I('lt.png')))) 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 config['systray_icon']: prints( 'Failed to create system tray icon, your desktop environment probably does not support the StatusNotifier spec' ) 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.donate_button.clicked.connect(self.donate_action.trigger) self.donate_button.setToolTip(self.donate_action.text().replace( '&', '')) self.donate_button.setIcon(self.donate_action.icon()) self.donate_button.setStatusTip(self.donate_button.toolTip()) 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.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_restirction_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 if show_gui: 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.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) # ######################## 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.keyboard_interrupt.connect(self.quit, type=Qt.QueuedConnection) self.read_settings() self.finalize_layout() if self.bars_manager.showing_donate: self.donate_button.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() self.auto_adder = AutoAdder(gprefs['auto_add_path'], self) self.save_layout_state() # Collect cycles now gc.collect() 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)
def __init__(self, pathtoebook=None, debug_javascript=False, open_at=None, start_in_fullscreen=False, continue_reading=False): MainWindow.__init__(self, debug_javascript) self.view.magnification_changed.connect(self.magnification_changed) self.closed = False self.show_toc_on_open = False self.current_book_has_toc = False self.iterator = None self.current_page = None self.pending_search = None self.pending_search_dir = None self.pending_anchor = None self.pending_reference = None self.pending_bookmark = None self.pending_restore = False self.pending_goto_page = None self.cursor_hidden = False self.existing_bookmarks = [] self.selected_text = None self.was_maximized = False self.page_position_on_footnote_toggle = [] self.read_settings() self.autosave_timer = t = QTimer(self) t.setInterval(self.AUTOSAVE_INTERVAL * 1000), t.setSingleShot(True) t.timeout.connect(self.autosave) self.pos.value_changed.connect(self.update_pos_label) self.pos.value_changed.connect(self.autosave_timer.start) self.pos.setMinimumWidth(150) self.setFocusPolicy(Qt.StrongFocus) self.view.set_manager(self) self.pi = ProgressIndicator(self) self.action_quit = QAction(_('&Quit'), self) self.addAction(self.action_quit) self.view_resized_timer = QTimer(self) self.view_resized_timer.timeout.connect(self.viewport_resize_finished) self.view_resized_timer.setSingleShot(True) self.resize_in_progress = False self.action_reload = QAction(_('&Reload book'), self) self.action_reload.triggered.connect(self.reload_book) self.action_quit.triggered.connect(self.quit) self.action_reference_mode.triggered[bool].connect( self.view.reference_mode) self.action_metadata.triggered[bool].connect(self.metadata.setVisible) self.action_table_of_contents.toggled[bool].connect( self.set_toc_visible) self.action_copy.triggered[bool].connect(self.copy) self.action_font_size_larger.triggered.connect(self.font_size_larger) self.action_font_size_smaller.triggered.connect(self.font_size_smaller) self.action_open_ebook.triggered[bool].connect(self.open_ebook) self.action_next_page.triggered.connect(self.view.next_page) self.action_previous_page.triggered.connect(self.view.previous_page) self.action_find_next.triggered.connect(self.find_next) self.action_find_previous.triggered.connect(self.find_previous) self.action_full_screen.triggered[bool].connect(self.toggle_fullscreen) self.action_back.triggered[bool].connect(self.back) self.action_forward.triggered[bool].connect(self.forward) self.action_preferences.triggered.connect(self.do_config) self.pos.editingFinished.connect(self.goto_page_num) self.vertical_scrollbar.valueChanged[int].connect( lambda x: self.goto_page(x / 100.)) self.search.search.connect(self.find) self.search.focus_to_library.connect( lambda: self.view.setFocus(Qt.OtherFocusReason)) self.toc.pressed[QModelIndex].connect(self.toc_clicked) self.toc.searched.connect(partial(self.toc_clicked, force=True)) def toggle_toc(ev): try: key = self.view.shortcuts.get_match(ev) except AttributeError: pass if key == 'Table of Contents': ev.accept() self.action_table_of_contents.trigger() return True return False self.toc.handle_shortcuts = toggle_toc self.reference.goto.connect(self.goto) self.bookmarks.edited.connect(self.bookmarks_edited) self.bookmarks.activated.connect(self.goto_bookmark) self.bookmarks.create_requested.connect(self.bookmark) self.set_bookmarks([]) self.load_theme_menu() if pathtoebook is not None: f = functools.partial(self.load_ebook, pathtoebook, open_at=open_at) QTimer.singleShot(50, f) elif continue_reading: QTimer.singleShot(50, self.continue_reading) self.window_mode_changed = None self.toggle_toolbar_action = QAction(_('Show/hide controls'), self) self.toggle_toolbar_action.setCheckable(True) self.toggle_toolbar_action.triggered.connect(self.toggle_toolbars) self.toolbar_hidden = None self.addAction(self.toggle_toolbar_action) self.full_screen_label_anim = QPropertyAnimation( self.full_screen_label, b'size') self.clock_timer = QTimer(self) self.clock_timer.timeout.connect(self.update_clock) self.action_print.triggered.connect(self.print_book) self.clear_recent_history_action = QAction( _('Clear list of recently opened books'), self) self.clear_recent_history_action.triggered.connect( self.clear_recent_history) self.build_recent_menu() self.open_history_menu.triggered.connect(self.open_recent) for x in ('tool_bar', 'tool_bar2'): x = getattr(self, x) for action in x.actions(): # So that the keyboard shortcuts for these actions will # continue to function even when the toolbars are hidden self.addAction(action) for plugin in self.view.document.all_viewer_plugins: plugin.customize_ui(self) self.view.document.settings_changed.connect(self.settings_changed) self.restore_state() self.settings_changed() self.action_toggle_paged_mode.toggled[bool].connect( self.toggle_paged_mode) if (start_in_fullscreen or self.view.document.start_in_fullscreen): self.action_full_screen.trigger() self.hide_cursor_timer = t = QTimer(self) t.setSingleShot(True), t.setInterval(3000) t.timeout.connect(self.hide_cursor) t.start()
def do_multiple_book_action(self): if self.wasCanceled(): return self.do_close() if self.i >= self.total_count: return self.do_close() book_info = self.books[self.i] self.i += 1 book_id, dtitle, format_dict = book_info[0], book_info[1], book_info[2] all_formats = self.db.formats(book_id, index_is_id=True, verify_formats=True) if all_formats is not None: all_formats = all_formats.split(',') else: all_formats = [] self.setWindowTitle( _('{0} {1} {2} ({3} issues)...').format(self.action_type, self.total_count, self.status_msg_type, len(self.failures))) self.setLabelText(_('{0}: {1}').format(self.action_type, dtitle)) if self.target_format in format_dict.keys(): format = format_dict[self.target_format].get_format_details() kindle_obj = format['kindle_obj'] if not kindle_obj.isEncrypted: if getattr(kindle_obj, self.attr): if format['goal_format'] not in all_formats: target_format = self.target_format if format['goal_format'] == 'ZIP': target_format = 'ZIP' success, error = self.callback_fn( kindle_obj, book_id, target_format, True) if success: self.successes.append((book_id, dtitle)) elif error is None: self.failures.append(( 5, dtitle, _('{0} already has a {1} format. Won\'t overwrite.' ).format(dtitle, format['goal_format']))) else: self.failures.append( (4, dtitle, _('Unknown error processing {0}\'s {1} format' ).format(dtitle, self.target_format))) else: self.failures.append(( 5, dtitle, _('{0} already has a {1} format. Won\'t overwrite.' ).format(dtitle, format['goal_format']))) else: self.failures.append( (3, dtitle, _('{0}\'s {1} format is not a {2} book.').format( dtitle, self.target_format, self.kindle_type))) else: self.failures.append( (2, dtitle, _('{0} is encrypted.').format(dtitle))) else: self.failures.append( (1, dtitle, _('{0} has no {1} format to work with.').format( dtitle, self.target_format))) self.setValue(self.i) QTimer.singleShot(0, self.do_multiple_book_action)
def setEditorData(self, editor, index): name = unicode(index.data(NAME_ROLE) or '') # We do this because Qt calls selectAll() unconditionally on the # editor, and we want only a part of the file name to be selected QTimer.singleShot(0, partial(self.set_editor_data, name, editor))
def title_changed(self, title): if self.wait_for_title and title == self.wait_for_title and self.load_complete: QTimer.singleShot(self.settle_time, self.print_to_pdf)
def display(self): if not self.isVisible(): self.show() self.raise_() QTimer.singleShot(0, self.model.build)
def add_url(self): self.items.append(URLItem(None, self)) self.l.addWidget(self.items[-1]) QTimer.singleShot(100, self.scroll_to_bottom)
def spare_pool(self): ans, self._spare_pool = self._spare_pool, None QTimer.singleShot(1000, self.create_spare_pool) return ans
def eventFilter(self, obj, event): # noqa C901 ''' @param: obj QObject @param: event QEvent ''' evtype = event.type() # Keyboard events are sent to parent widget if obj == self and evtype == QEvent.ParentChange and self.parentWidget(): self.parentWidget().installEventFilter(self) # Hack to find widget that receives input events if obj == self and evtype == QEvent.ChildAdded: if const.QTWEBENGINEWIDGETS_VERSION >= const.QT_VERSION_CHECK(5, 12, 0): # NOTE: qobject_cast<QWidget*>(static_cast<QChildEvent*>(event)->child()); assert(isinstance(event, QChildEvent)) child = event.child() #assert(isinstance(child, QWidget)) def xxx(): if not sip.isdeleted(child) and \ child.inherits('QtWebEngineCore::RenderWidgetHostViewQtDelegateWidget'): self._rwhvqt = child self._rwhvqt.installEventFilter(self) w = self._rwhvqt if isinstance(w, QQuickWidget): w.setClearColor(self.palette().color(QPalette.Window)) QTimer.singleShot(0, xxx) else: def yyy(): focusProxy = self.focusProxy() if focusProxy and self._rwhvqt != focusProxy: self._rwhvqt = focusProxy self._rwhvqt.installEventFilter(self) w = self._rwhvqt if isinstance(w, QQuickWidget): w.setClearColor(self.palette().color(QPalette.Window)) QTimer.singleShot(0, yyy) def _HANDLE_EVENT(f, t): wasAccepted = event.isAccepted() event.setAccepted(False) f(event) ret = event.isAccepted() event.setAccepted(wasAccepted) return ret # Forward events to WebView if obj == self._rwhvqt: if evtype == QEvent.MouseButtonPress: return _HANDLE_EVENT(self._mousePressEvent, QMouseEvent) elif evtype == QEvent.MouseButtonRelease: return _HANDLE_EVENT(self.mouseReleaseEvent, QMouseEvent) elif evtype == QEvent.MouseMove: return _HANDLE_EVENT(self.mouseMoveEvent, QMouseEvent) elif evtype == QEvent.Wheel: return _HANDLE_EVENT(self._wheelEvent, QWheelEvent) if obj == self.parentWidget(): if evtype == QEvent.KeyPress: return _HANDLE_EVENT(self._keyPressEvent, QKeyEvent) if evtype == QEvent.KeyRelease: return _HANDLE_EVENT(self._keyReleaseEvent, QKeyEvent) # Block already handled events if obj == self: if evtype in (QEvent.KeyPress, QEvent.KeyRelease, QEvent.MouseButtonPress, QEvent.MouseButtonRelease, QEvent.MouseMove, QEvent.Wheel): return True if evtype == QEvent.Hide: if self.isFullScreen(): self.triggerPageAction(QWebEnginePage.ExitFullScreen) res = super().eventFilter(obj, event) if obj == self._rwhvqt: if evtype in (QEvent.FocusIn, QEvent.FocusOut): self.focusChanged.emit(self.hasFocus()) return res
def __init__(self, parent=None, initial=None): QDialog.__init__(self, parent) self.setWindowTitle(_('Choose a texture')) self.l = l = QVBoxLayout() self.setLayout(l) self.tdir = texture_dir() self.images = il = QListWidget(self) il.itemDoubleClicked.connect(self.accept, type=Qt.QueuedConnection) il.setIconSize(QSize(256, 256)) il.setViewMode(il.IconMode) il.setFlow(il.LeftToRight) il.setSpacing(20) il.setSelectionMode(il.SingleSelection) il.itemSelectionChanged.connect(self.update_remove_state) l.addWidget(il) self.ad = ad = QLabel( _('The builtin textures come from <a href="http://subtlepatterns.com">subtlepatterns.com</a>.' )) ad.setOpenExternalLinks(True) ad.setWordWrap(True) l.addWidget(ad) self.bb = bb = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) bb.accepted.connect(self.accept) bb.rejected.connect(self.reject) b = self.add_button = bb.addButton(_('Add texture'), bb.ActionRole) b.setIcon(QIcon(I('plus.png'))) b.clicked.connect(self.add_texture) b = self.remove_button = bb.addButton(_('Remove texture'), bb.ActionRole) b.setIcon(QIcon(I('minus.png'))) b.clicked.connect(self.remove_texture) l.addWidget(bb) images = [{ 'fname': ':' + os.path.basename(x), 'path': x, 'name': ' '.join( map(string.capitalize, os.path.splitext(os.path.basename(x))[0].split('_'))) } for x in glob.glob(I('textures/*.png'))] + [ { 'fname': os.path.basename(x), 'path': x, 'name': os.path.splitext(os.path.basename(x))[0], } for x in glob.glob(os.path.join(self.tdir, '*')) if x.rpartition('.')[-1].lower() in {'jpeg', 'png', 'jpg'} ] images.sort(key=lambda x: sort_key(x['name'])) map(self.create_item, images) self.update_remove_state() if initial: existing = { unicode(i.data(Qt.UserRole) or ''): i for i in (self.images.item(c) for c in xrange(self.images.count())) } item = existing.get(initial, None) if item is not None: item.setSelected(True) QTimer.singleShot(100, partial(il.scrollToItem, item)) self.resize(QSize(950, 650))
def sync_to_editor(self, name, sourceline_address): self.current_sync_request = (name, sourceline_address) QTimer.singleShot(100, self._sync_to_editor)
def create_docks(self): def create(name, oname): oname += '-dock' d = QDockWidget(name, self) d.setObjectName(oname) # Needed for saveState ac = d.toggleViewAction() desc = _('Toggle %s') % name.replace('&', '') self.keyboard.register_shortcut(oname, desc, description=desc, action=ac, group=_('Windows')) actions[oname] = ac setattr(self, oname.replace('-', '_'), d) return d d = create(_('File browser'), 'files-browser') d.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) self.file_list = FileListWidget(d) d.setWidget(self.file_list) self.addDockWidget(Qt.LeftDockWidgetArea, d) d = create(_('File preview'), 'preview') d.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) self.preview = Preview(d) d.setWidget(self.preview) self.addDockWidget(Qt.RightDockWidgetArea, d) d = create(_('Live CSS'), 'live-css') d.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea | Qt.BottomDockWidgetArea | Qt.TopDockWidgetArea) self.live_css = LiveCSS(self.preview, parent=d) d.setWidget(self.live_css) self.addDockWidget(Qt.RightDockWidgetArea, d) d.close() # Hidden by default d = create(_('Check book'), 'check-book') d.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea | Qt.BottomDockWidgetArea | Qt.TopDockWidgetArea) d.setWidget(self.check_book) self.addDockWidget(Qt.TopDockWidgetArea, d) d.close() # By default the check window is closed d = create(_('Inspector'), 'inspector') d.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea | Qt.BottomDockWidgetArea | Qt.TopDockWidgetArea) d.setWidget(self.preview.inspector) self.preview.inspector.setParent(d) self.addDockWidget(Qt.BottomDockWidgetArea, d) d.close() # By default the inspector window is closed QTimer.singleShot(10, self.preview.inspector.connect_to_dock) d = create(_('Table of Contents'), 'toc-viewer') d.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea | Qt.BottomDockWidgetArea | Qt.TopDockWidgetArea) d.setWidget(self.toc_view) self.addDockWidget(Qt.LeftDockWidgetArea, d) d.close() # Hidden by default d = create(_('Text search'), 'text-search') d.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea | Qt.BottomDockWidgetArea | Qt.TopDockWidgetArea) d.setWidget(self.text_search) self.addDockWidget(Qt.LeftDockWidgetArea, d) d.close() # Hidden by default d = create(_('Checkpoints'), 'checkpoints') d.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea | Qt.BottomDockWidgetArea | Qt.TopDockWidgetArea) self.checkpoints = CheckpointView(self.boss.global_undo, parent=d) d.setWidget(self.checkpoints) self.addDockWidget(Qt.LeftDockWidgetArea, d) d.close() # Hidden by default d = create(_('Saved searches'), 'saved-searches') d.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea | Qt.BottomDockWidgetArea | Qt.TopDockWidgetArea) d.setWidget(self.saved_searches) self.addDockWidget(Qt.LeftDockWidgetArea, d) d.close() # Hidden by default
def __init__(self, parent=None): super().__init__(parent) self._completer = None # LocationCompleter self._domainCompleterModel = None # QStringListModel self._bookmarkIcon = None # BookmarksIcon self._goIcon = None # GoIcon self._siteIcon = None # SiteIcon self._autofillIcon = None # AutoFillIcon self._window = None # BrowserWindow self._webView = None # TabbedWebView self._holdingAlt = False self._oldTextLength = 0 self._currentTextLength = 0 self._loadProgress = 0 self._progressVisible = True self._progressStyle = 0 # ProgressStyle self._progressColor = QColor() self._progressTimer = None # QTimer self.setObjectName('locationbar') self.setDragEnabled(True) # Disable KDE QLineEdit transitions, it breaks with setText() && home() self._bookmarkIcon = BookmarksIcon(self) self._goIcon = GoIcon(self) self._siteIcon = SiteIcon(self) self._autofillIcon = AutoFillIcon(self) down = DownIcon(self) self.addWidget(self._siteIcon, LineEdit.LeftSide) self.addWidget(self._autofillIcon, LineEdit.RightSide) self.addWidget(self._bookmarkIcon, LineEdit.RightSide) self.addWidget(self._goIcon, LineEdit.RightSide) self.addWidget(down, LineEdit.RightSide) self._completer = LocationCompleter(self) self._completer.setLocationBar(self) self._completer.showCompletion.connect(self._showCompletion) self._completer.showDomainCompletion.connect( self._showDomainCompletion) self._completer.clearCompletion.connect(self._clearCompletion) self._completer.loadRequested.connect(self.loadRequest) self._completer.popupClosed.connect(self._updateSiteIcon) self._domainCompleterModel = QStringListModel(self) domainCompleter = QCompleter(self) domainCompleter.setCompletionMode(QCompleter.InlineCompletion) domainCompleter.setModel(self._domainCompleterModel) self.setCompleter(domainCompleter) self._progressTimer = QTimer(self) self._progressTimer.setInterval(700) self._progressTimer.setSingleShot(True) self._progressTimer.timeout.connect(self._hideProgress) self.editAction(self.PasteAndGo).setText(_('Paste And &Go')) self.editAction(self.PasteAndGo).setIcon(QIcon.fromTheme('edit-paste')) self.editAction(self.PasteAndGo).triggered.connect(self._pasteAndGo) self.textEdited.connect(self._textEdited) self._goIcon.clicked.connect(self._requestLoadUrl) down.clicked.connect(self._completer.showMostVisited) # TODO: #gVar.app.searchEnginesManager().activeEngineChanged.connect(self._updatePlaceHolderText) #gVar.app.searchEnginesManager().defaultEngineChanged.connect(self._updatePlaceHolderText) self._loadSettings() self._updateSiteIcon() # Hide icons by default self._goIcon.setVisible(gVar.appSettings.alwaysShowGoIcon) self._autofillIcon.hide() QTimer.singleShot(0, self._updatePlaceHolderText)
def show_frag(self): self.view.show_frag(self.current_frag) QTimer.singleShot(1, self.check_frag)
def eventFilter(self, obj, e): 'Redirect key presses from the popup to the widget' widget = self.completer_widget() if widget is None or sip.isdeleted(widget): return False etype = e.type() if obj is not self: return QObject.eventFilter(self, obj, e) # self.debug_event(e) if etype == e.KeyPress: try: key = e.key() except AttributeError: return QObject.eventFilter(self, obj, e) if key == Qt.Key_Escape: self.hide() e.accept() return True if key == Qt.Key_F4 and e.modifiers() & Qt.AltModifier: self.hide() e.accept() return True if key in (Qt.Key_Enter, Qt.Key_Return): # We handle this explicitly because on OS X activated() is # not emitted on pressing Enter. idx = self.currentIndex() if idx.isValid(): self.item_chosen(idx) self.hide() e.accept() return True if key == Qt.Key_Tab: idx = self.currentIndex() if idx.isValid(): self.item_chosen(idx) self.hide() elif self.model().rowCount() > 0: self.next_match() e.accept() return True if key in (Qt.Key_PageUp, Qt.Key_PageDown): # Let the list view handle these keys return False if key in (Qt.Key_Up, Qt.Key_Down): self.next_match(previous=key == Qt.Key_Up) e.accept() return True # Send to widget widget.eat_focus_out = False widget.keyPressEvent(e) widget.eat_focus_out = True if not widget.hasFocus(): # Widget lost focus hide the popup self.hide() if e.isAccepted(): return True elif isosx and etype == e.InputMethodQuery and e.queries() == ( Qt.ImHints | Qt.ImEnabled) and self.isVisible(): # In Qt 5 the Esc key causes this event and the line edit does not # handle it, which causes the parent dialog to be closed # See https://bugreports.qt-project.org/browse/QTBUG-41806 e.accept() return True elif etype == e.MouseButtonPress and hasattr( e, 'globalPos') and not self.rect().contains( self.mapFromGlobal(e.globalPos())): # A click outside the popup, close it if isinstance(widget, QComboBox): # This workaround is needed to ensure clicking on the drop down # arrow of the combobox closes the popup opt = QStyleOptionComboBox() widget.initStyleOption(opt) sc = widget.style().hitTestComplexControl( QStyle.CC_ComboBox, opt, widget.mapFromGlobal(e.globalPos()), widget) if sc == QStyle.SC_ComboBoxArrow: QTimer.singleShot(0, self.hide) e.accept() return True self.hide() e.accept() return True elif etype in (e.InputMethod, e.ShortcutOverride): QApplication.sendEvent(widget, e) return False
def start(self): t = self.thread = Thread(target=self.vacuum) t.daemon = True t.start() QTimer.singleShot(100, self.check) self.exec_()
def __init__(self, opts): self.matched_ids = set() self.opts = opts self.prefs = opts.prefs super(FindAnnotationsDialog, self).__init__(self.opts.gui, 'find_annotations_dialog') self.setWindowTitle(_('Find Annotations')) self.setWindowIcon(self.opts.icon) self.l = QVBoxLayout(self) self.setLayout(self.l) self.search_criteria_gb = QGroupBox(self) self.search_criteria_gb.setTitle(_("Search criteria")) self.scgl = QGridLayout(self.search_criteria_gb) self.l.addWidget(self.search_criteria_gb) # addWidget(widget, row, col, rowspan, colspan) row = 0 # ~~~~~~~~ Create the Readers comboBox ~~~~~~~~ self.reader_label = QLabel(_('Reader')) self.reader_label.setAlignment(Qt.AlignRight | Qt.AlignVCenter) self.scgl.addWidget(self.reader_label, row, 0, 1, 1) self.find_annotations_reader_comboBox = QComboBox() self.find_annotations_reader_comboBox.setObjectName( 'find_annotations_reader_comboBox') self.find_annotations_reader_comboBox.setToolTip( _('Reader annotations to search for')) self.find_annotations_reader_comboBox.addItem(self.GENERIC_READER) racs = ReaderApp.get_reader_app_classes() for ra in sorted(list(racs.keys())): self.find_annotations_reader_comboBox.addItem(ra) self.scgl.addWidget(self.find_annotations_reader_comboBox, row, 1, 1, 4) row += 1 # ~~~~~~~~ Create the Styles comboBox ~~~~~~~~ self.style_label = QLabel(_('Style')) self.style_label.setAlignment(Qt.AlignRight | Qt.AlignVCenter) self.scgl.addWidget(self.style_label, row, 0, 1, 1) self.find_annotations_color_comboBox = QComboBox() self.find_annotations_color_comboBox.setObjectName( 'find_annotations_color_comboBox') self.find_annotations_color_comboBox.setToolTip( _('Annotation style to search for')) self.find_annotations_color_comboBox.addItem(self.GENERIC_STYLE) all_colors = list(COLOR_MAP.keys()) all_colors.remove('Default') for color in sorted(all_colors): self.find_annotations_color_comboBox.addItem(color) self.scgl.addWidget(self.find_annotations_color_comboBox, row, 1, 1, 4) row += 1 # ~~~~~~~~ Create the Text LineEdit control ~~~~~~~~ self.text_label = QLabel(_('Text')) self.text_label.setAlignment(Qt.AlignRight | Qt.AlignVCenter) self.scgl.addWidget(self.text_label, row, 0, 1, 1) self.find_annotations_text_lineEdit = MyLineEdit() self.find_annotations_text_lineEdit.setObjectName( 'find_annotations_text_lineEdit') self.scgl.addWidget(self.find_annotations_text_lineEdit, row, 1, 1, 3) self.reset_text_tb = QToolButton() self.reset_text_tb.setObjectName('reset_text_tb') self.reset_text_tb.setToolTip(_('Clear search criteria')) self.reset_text_tb.setIcon(QIcon(I('trash.png'))) self.reset_text_tb.clicked.connect(self.clear_text_field) self.scgl.addWidget(self.reset_text_tb, row, 4, 1, 1) row += 1 # ~~~~~~~~ Create the Note LineEdit control ~~~~~~~~ self.note_label = QLabel(_('Note')) self.note_label.setAlignment(Qt.AlignRight | Qt.AlignVCenter) self.scgl.addWidget(self.note_label, row, 0, 1, 1) self.find_annotations_note_lineEdit = MyLineEdit() self.find_annotations_note_lineEdit.setObjectName( 'find_annotations_note_lineEdit') self.scgl.addWidget(self.find_annotations_note_lineEdit, row, 1, 1, 3) self.reset_note_tb = QToolButton() self.reset_note_tb.setObjectName('reset_note_tb') self.reset_note_tb.setToolTip(_('Clear search criteria')) self.reset_note_tb.setIcon(QIcon(I('trash.png'))) self.reset_note_tb.clicked.connect(self.clear_note_field) self.scgl.addWidget(self.reset_note_tb, row, 4, 1, 1) row += 1 # ~~~~~~~~ Create the Date range controls ~~~~~~~~ self.date_range_label = QLabel(_('Date range')) self.date_range_label.setAlignment(Qt.AlignRight | Qt.AlignVCenter) self.scgl.addWidget(self.date_range_label, row, 0, 1, 1) # Date 'From' self.find_annotations_date_from_dateEdit = MyDateEdit( self, datetime(1970, 1, 1)) self.find_annotations_date_from_dateEdit.setObjectName( 'find_annotations_date_from_dateEdit') #self.find_annotations_date_from_dateEdit.current_val = datetime(1970,1,1) self.find_annotations_date_from_dateEdit.clear_button.clicked.connect( self.find_annotations_date_from_dateEdit.reset_from_date) self.scgl.addWidget(self.find_annotations_date_from_dateEdit, row, 1, 1, 1) self.scgl.addWidget( self.find_annotations_date_from_dateEdit.clear_button, row, 2, 1, 1) # Date 'To' self.find_annotations_date_to_dateEdit = MyDateEdit( self, datetime.today()) self.find_annotations_date_to_dateEdit.setObjectName( 'find_annotations_date_to_dateEdit') #self.find_annotations_date_to_dateEdit.current_val = datetime.today() self.find_annotations_date_to_dateEdit.clear_button.clicked.connect( self.find_annotations_date_to_dateEdit.reset_to_date) self.scgl.addWidget(self.find_annotations_date_to_dateEdit, row, 3, 1, 1) self.scgl.addWidget( self.find_annotations_date_to_dateEdit.clear_button, row, 4, 1, 1) row += 1 # ~~~~~~~~ Create a horizontal line ~~~~~~~~ self.hl = QFrame(self) self.hl.setGeometry(QRect(0, 0, 1, 3)) self.hl.setFrameShape(QFrame.HLine) self.hl.setFrameShadow(QFrame.Raised) self.scgl.addWidget(self.hl, row, 0, 1, 5) row += 1 # ~~~~~~~~ Create the results label field ~~~~~~~~ self.result_label = QLabel('<p style="color:red">{0}</p>'.format( _('scanning…'))) self.result_label.setAlignment(Qt.AlignCenter) self.result_label.setWordWrap(False) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Maximum) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.result_label.sizePolicy().hasHeightForWidth()) self.result_label.setSizePolicy(sizePolicy) self.result_label.setMinimumSize(QtCore.QSize(250, 0)) self.scgl.addWidget(self.result_label, row, 0, 1, 5) row += 1 # ~~~~~~~~ Create the ButtonBox ~~~~~~~~ self.dialogButtonBox = QDialogButtonBox(self) self.dialogButtonBox.setOrientation(Qt.Horizontal) if False: self.update_button = QPushButton(_('Update results')) self.update_button.setDefault(True) self.update_button.setVisible(False) self.dialogButtonBox.addButton(self.update_button, QDialogButtonBox.ActionRole) self.cancel_button = self.dialogButtonBox.addButton( self.dialogButtonBox.Cancel) self.find_button = self.dialogButtonBox.addButton( self.dialogButtonBox.Ok) self.find_button.setText(_('Find Matching Books')) self.l.addWidget(self.dialogButtonBox) self.dialogButtonBox.clicked.connect( self.find_annotations_dialog_clicked) # ~~~~~~~~ Add a spacer ~~~~~~~~ self.spacerItem = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) self.l.addItem(self.spacerItem) # ~~~~~~~~ Restore previously saved settings ~~~~~~~~ self.restore_settings() # ~~~~~~~~ Declare sizing ~~~~~~~~ sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.sizePolicy().hasHeightForWidth()) self.setSizePolicy(sizePolicy) self.resize_dialog() # ~~~~~~~~ Connect all signals ~~~~~~~~ self.find_annotations_reader_comboBox.currentIndexChanged.connect( partial(self.update_results, 'reader')) self.find_annotations_color_comboBox.currentIndexChanged.connect( partial(self.update_results, 'color')) self.find_annotations_text_lineEdit.editingFinished.connect( partial(self.update_results, 'text')) self.find_annotations_note_lineEdit.editingFinished.connect( partial(self.update_results, 'note')) # self.connect(self.find_annotations_text_lineEdit, pyqtSignal("return_pressed"), self.return_pressed) self.find_annotations_text_lineEdit.return_pressed.connect( self.return_pressed) # self.connect(self.find_annotations_note_lineEdit, pyqtSignal("return_pressed"), self.return_pressed) self.find_annotations_note_lineEdit.return_pressed.connect( self.return_pressed) # Date range signals connected in inventory_available() # ~~~~~~~~ Allow dialog to render before doing inventory ~~~~~~~~ #field = self.prefs.get('cfg_annotations_destination_field', None) field = get_cc_mapping('annotations', 'field', None) self.annotated_books_scanner = InventoryAnnotatedBooks( self.opts.gui, field, get_date_range=True) self.annotated_books_scanner.signal.connect(self.inventory_available) QTimer.singleShot(1, self.start_inventory_scan)
def setup_ui(self): self.l = l = QVBoxLayout(self) self.setLayout(l) self.h = h = QHBoxLayout() self.filter_text = ft = QLineEdit(self) ft.textChanged.connect(self.do_filter) ft.setPlaceholderText(_('Filter displayed searches')) h.addWidget(ft) self.cft = cft = QToolButton(self) cft.setToolTip(_('Clear filter')), cft.setIcon(QIcon(I('clear_left.png'))) cft.clicked.connect(ft.clear) h.addWidget(cft) l.addLayout(h) self.h2 = h = QHBoxLayout() self.searches = searches = QListView(self) self.stack = stack = QStackedLayout() self.main_widget = mw = QWidget(self) stack.addWidget(mw) self.edit_search_widget = es = EditSearch(mw) stack.addWidget(es) es.done.connect(self.search_editing_done) mw.v = QVBoxLayout(mw) mw.v.setContentsMargins(0, 0, 0, 0) mw.v.addWidget(searches) searches.doubleClicked.connect(self.edit_search) self.model = SearchesModel(self.searches) self.model.dataChanged.connect(self.show_details) searches.setModel(self.model) searches.selectionModel().currentChanged.connect(self.show_details) searches.setSelectionMode(searches.ExtendedSelection) self.delegate = SearchDelegate(searches) searches.setItemDelegate(self.delegate) searches.setAlternatingRowColors(True) h.addLayout(stack, stretch=10) self.v = v = QVBoxLayout() h.addLayout(v) l.addLayout(h) stack.currentChanged.connect(self.stack_current_changed) def pb(text, tooltip=None): b = AnimatablePushButton(text, self) b.setToolTip(tooltip or '') b.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed) return b mulmsg = '\n\n' + _('The entries are tried in order until the first one matches.') self.action_button_map = {} for text, action, tooltip in [ (_('&Find'), 'find', _('Run the search using the selected entries.') + mulmsg), (_('&Replace'), 'replace', _('Run replace using the selected entries.') + mulmsg), (_('Replace a&nd Find'), 'replace-find', _('Run replace and then find using the selected entries.') + mulmsg), (_('Replace &all'), 'replace-all', _('Run Replace All for all selected entries in the order selected')), (_('&Count all'), 'count', _('Run Count All for all selected entries')), ]: self.action_button_map[action] = b = pb(text, tooltip) v.addWidget(b) b.clicked.connect(partial(self.run_search, action)) self.d1 = d = QFrame(self) d.setFrameStyle(QFrame.HLine) v.addWidget(d) self.h3 = h = QHBoxLayout() self.upb = b = QToolButton(self) b.setIcon(QIcon(I('arrow-up.png'))), b.setToolTip(_('Move selected entries up')) b.clicked.connect(partial(self.move_entry, -1)) self.dnb = b = QToolButton(self) b.setIcon(QIcon(I('arrow-down.png'))), b.setToolTip(_('Move selected entries down')) b.clicked.connect(partial(self.move_entry, 1)) h.addWidget(self.upb), h.addWidget(self.dnb) v.addLayout(h) self.eb = b = pb(_('&Edit search'), _('Edit the currently selected search')) b.clicked.connect(self.edit_search) v.addWidget(b) self.rb = b = pb(_('Re&move search'), _('Remove the currently selected searches')) b.clicked.connect(self.remove_search) v.addWidget(b) self.ab = b = pb(_('&Add search'), _('Add a new saved search')) b.clicked.connect(self.add_search) v.addWidget(b) self.d2 = d = QFrame(self) d.setFrameStyle(QFrame.HLine) v.addWidget(d) self.where_box = wb = WhereBox(self, emphasize=True) self.where = SearchWidget.DEFAULT_STATE['where'] v.addWidget(wb) self.direction_box = db = DirectionBox(self) self.direction = SearchWidget.DEFAULT_STATE['direction'] v.addWidget(db) self.wr = wr = QCheckBox(_('&Wrap')) wr.setToolTip('<p>'+_('When searching reaches the end, wrap around to the beginning and continue the search')) self.wr.setChecked(SearchWidget.DEFAULT_STATE['wrap']) v.addWidget(wr) self.d3 = d = QFrame(self) d.setFrameStyle(QFrame.HLine) v.addWidget(d) self.description = d = QLabel(' \n \n ') d.setTextFormat(Qt.PlainText) d.setWordWrap(True) mw.v.addWidget(d) self.ib = b = pb(_('&Import'), _('Import saved searches')) b.clicked.connect(self.import_searches) v.addWidget(b) self.eb2 = b = pb(_('E&xport'), _('Export saved searches')) v.addWidget(b) self.em = m = QMenu(_('Export')) m.addAction(_('Export All'), lambda : QTimer.singleShot(0, partial(self.export_searches, all=True))) m.addAction(_('Export Selected'), lambda : QTimer.singleShot(0, partial(self.export_searches, all=False))) b.setMenu(m) self.searches.setFocus(Qt.OtherFocusReason)
def update(self): if self.restorer.is_alive(): QTimer.singleShot(10, self.update) else: self.restorer.progress_callback = lambda x, y: x self.accept()
def __init__(self, type_, startUrl=QUrl()): super().__init__(None) self._startUrl = startUrl self._homepage = QUrl() self._windowType = type_ self._startTab = None # WebTab self._startPage = None # WebPage self._mainLayout = None # QVBoxLayout self._mainSplitter = None # QSplitter self._tabWidget = None # TabWidget self._sideBar = None # QPointer<SideBar> self._sideBarManager = SideBarManager(self) self._statusBar = None self._navigationContainer = None # NavigationContainer self._navigationToolbar = None # NavigationBar self._bookmarksToolbar = None # BookmarksToolbar self._progressBar = None # ProgressBar self._ipLabel = None # QLabel self._superMenu = None # QMenu self._mainMenu = None # MainMenu self._tabModel = None # TabModel self._tabMruModel = None # TabMruModel self._sideBarWidth = 0 self._webViewWidth = 0 # Shortcuts self._useTabNumberShortcuts = False self._useSpeedDialNumberShortcuts = False self._useSingleKeyShortcuts = False # Remember visibility of menubar and statusbar after entering Fullscreen self._menuBarVisible = False self._statusBarVisible = False self._htmlFullScreenView = None # TabbedWebView self._hideNavigationTimer = None # QTimer self._deleteOnCloseWidgets = [] # QList<QPointer<QWidget>> self.setAttribute(Qt.WA_DeleteOnClose) self.setAttribute(Qt.WA_DontCreateNativeAncestors) self.setObjectName('mainwindow') self.setWindowTitle(const.APPNAME) self.setProperty('private', gVar.app.isPrivate()) self._setupUi() self._setupMenu() self._hideNavigationTimer = QTimer(self) self._hideNavigationTimer.setInterval(1000) self._hideNavigationTimer.setSingleShot(True) self._hideNavigationTimer.timeout.connect(self._hideNavigationSlot) gVar.app.settingsReloaded.connect(self._loadSettings) QTimer.singleShot(0, self._postLaunch) if gVar.app.isPrivate(): gVar.appTools.setWmClass( '%s Browser (Private Window)' % const.APPNAME, self) else: gVar.appTools.setWmClass('%s Browser' % const.APPNAME, self)
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()
widget.move(pos) if __name__ == '__main__': app = QApplication(sys.argv) lifetime_ms = 3000 if len(sys.argv) == 2: lifetime_ms = int(sys.argv[1]) pix = QPixmap(FILE_NAME) mw = QLabel() mw.setWindowFlag(Qt.WindowStaysOnTopHint) mw.setWindowFlag(Qt.FramelessWindowHint) mw.setPixmap(pix) mw.setMask(pix.mask()) mw.show() move_window_to_cursor(mw) timer = QTimer() timer.timeout.connect(lambda: move_window_to_cursor(mw)) timer.start(33) QTimer.singleShot(lifetime_ms, app.quit) app.exec()
def start(self): self.restorer.start() QTimer.singleShot(10, self.update)
def do_add(self, data): from calibre.ebooks.metadata.opf2 import OPF gui = self.parent() if gui is None: return m = gui.library_view.model() count = 0 needs_rescan = False duplicates = [] added_ids = set() for fname, tdir in data: paths = [os.path.join(self.worker.path, fname)] sz = os.path.join(tdir, 'size.txt') try: with open(sz, 'rb') as f: sz = int(f.read()) if sz != os.stat(paths[0]).st_size: raise Exception('Looks like the file was written to after' ' we tried to read metadata') except: needs_rescan = True try: self.worker.staging.remove(fname) except KeyError: pass continue mi = os.path.join(tdir, 'metadata.opf') if not os.access(mi, os.R_OK): continue mi = OPF(open(mi, 'rb'), tdir, populate_spine=False).to_book_metadata() if gprefs.get('tag_map_on_add_rules'): from calibre.ebooks.metadata.tag_mapper import map_tags mi.tags = map_tags(mi.tags, gprefs['tag_map_on_add_rules']) mi = [mi] dups, ids = m.add_books( paths, [os.path.splitext(fname)[1][1:].upper()], mi, add_duplicates=not gprefs['auto_add_check_for_duplicates'], return_ids=True) added_ids |= set(ids) num = len(ids) if dups: path = dups[0][0] with open( os.path.join(tdir, 'dup_cache.' + dups[1][0].lower()), 'wb') as dest, open(path, 'rb') as src: shutil.copyfileobj(src, dest) dups[0][0] = dest.name duplicates.append(dups) try: os.remove(paths[0]) self.worker.staging.remove(fname) except: import traceback traceback.print_exc() count += num if duplicates: paths, formats, metadata = [], [], [] for p, f, mis in duplicates: paths.extend(p) formats.extend(f) metadata.extend(mis) dups = [(mic, mic.cover, [p]) for mic, p in zip(metadata, paths)] d = DuplicatesQuestion(m.db, dups, parent=gui) dups = tuple(d.duplicates) if dups: paths, formats, metadata = [], [], [] for mi, cover, book_paths in dups: paths.extend(book_paths) formats.extend([p.rpartition('.')[-1] for p in book_paths]) metadata.extend([mi for i in book_paths]) ids = m.add_books(paths, formats, metadata, add_duplicates=True, return_ids=True)[1] added_ids |= set(ids) num = len(ids) count += num for fname, tdir in data: try: shutil.rmtree(tdir) except: pass if added_ids and gprefs['auto_add_auto_convert']: self.auto_convert.emit(added_ids) if count > 0: m.books_added(count) gui.status_bar.show_message( ngettext('Added a book automatically from {src}', 'Added {num} books automatically from {src}', count).format(num=count, src=self.worker.path), 2000) gui.refresh_cover_browser() if needs_rescan: QTimer.singleShot(2000, self.dir_changed)
def _on_spacings_combo_changed(self): if self.is_use_available: self._set_forwards_combo_to_available() QTimer.singleShot(0, self._check_if_valid)
def update(self): if self.worker.is_alive(): QTimer.singleShot(50, self.update) else: self.process_results()
def dump(self, items, out_stream, pdf_metadata): opts = self.opts page_size = get_page_size(self.opts) xdpi, ydpi = self.view.logicalDpiX(), self.view.logicalDpiY() def margin(which): val = getattr(opts, 'pdf_page_margin_' + which) if val == 0.0: val = getattr(opts, 'margin_' + which) return val ml, mr, mt, mb = map(margin, 'left right top bottom'.split()) # We cannot set the side margins in the webview as there is no right # margin for the last page (the margins are implemented with # -webkit-column-gap) self.doc = PdfDevice(out_stream, page_size=page_size, left_margin=ml, top_margin=0, right_margin=mr, bottom_margin=0, xdpi=xdpi, ydpi=ydpi, errors=self.log.error, debug=self.log.debug, compress=not opts.uncompressed_pdf, opts=opts, mark_links=opts.pdf_mark_links) self.footer = opts.pdf_footer_template if self.footer: self.footer = self.footer.strip() if not self.footer and opts.pdf_page_numbers: self.footer = '<p style="text-align:center; text-indent: 0">_PAGENUM_</p>' self.header = opts.pdf_header_template if self.header: self.header = self.header.strip() min_margin = 1.5 * opts._final_base_font_size if self.footer and mb < min_margin: self.log.warn( 'Bottom margin is too small for footer, increasing it to %.1fpts' % min_margin) mb = min_margin if self.header and mt < min_margin: self.log.warn( 'Top margin is too small for header, increasing it to %.1fpts' % min_margin) mt = min_margin self.page.setViewportSize(QSize(self.doc.width(), self.doc.height())) self.render_queue = items self.total_items = len(items) mt, mb = map(self.doc.to_px, (mt, mb)) self.margin_top, self.margin_bottom = map(lambda x: int(floor(x)), (mt, mb)) self.painter = QPainter(self.doc) self.doc.set_metadata(title=pdf_metadata.title, author=pdf_metadata.author, tags=pdf_metadata.tags, mi=pdf_metadata.mi) self.doc_title = pdf_metadata.title self.doc_author = pdf_metadata.author self.painter.save() try: if self.cover_data is not None: p = QPixmap() try: p.loadFromData(self.cover_data) except TypeError: self.log.warn( 'This ebook does not have a raster cover, cannot generate cover for PDF' '. Cover type: %s' % type(self.cover_data)) if not p.isNull(): self.doc.init_page() draw_image_page(QRect(*self.doc.full_page_rect), self.painter, p, preserve_aspect_ratio=self.opts. preserve_cover_aspect_ratio) self.doc.end_page() finally: self.painter.restore() QTimer.singleShot(0, self.render_book) if self.loop.exec_() == 1: raise Exception('PDF Output failed, see log for details') if self.toc is not None and len(self.toc) > 0: self.doc.add_outline(self.toc) self.painter.end() if self.doc.errors_occurred: raise Exception('PDF Output failed, see log for details')
def cover_view_resized(self, event): QTimer.singleShot(1, self.resize_cover)
def test(editor): c = editor.__c = CompletionPopup(editor.editor, max_height=100) items = 'a ab abc abcd abcde abcdef abcdefg abcdefgh'.split() m = Matcher(items) c.set_items(m('a'), descriptions={x: x for x in items}) QTimer.singleShot(100, c.show)
def do_book(self): if self.i >= len(self.book_ids): return self.do_queue() book_id = self.book_ids[self.i] self.i += 1 temp_files = [] try: input_format = get_input_format_for_book(self.db, book_id, None)[0] input_fmt = self.db.original_fmt(book_id, input_format).lower() same_fmt = input_fmt == self.output_format.lower() mi, opf_file = create_opf_file(self.db, book_id) in_file = PersistentTemporaryFile('.' + input_format) with in_file: self.db.copy_format_to(book_id, input_fmt, in_file, index_is_id=True) out_file = PersistentTemporaryFile('.' + self.output_format) out_file.write(as_bytes(self.output_format)) out_file.close() temp_files = [in_file] combined_recs = GuiRecommendations() default_recs = bulk_defaults_for_input_format(input_format) for key in default_recs: combined_recs[key] = default_recs[key] if self.use_saved_single_settings: specific_recs = load_specifics(self.db, book_id) for key in specific_recs: combined_recs[key] = specific_recs[key] for item in self.user_recs: combined_recs[item[0]] = item[1] save_specifics(self.db, book_id, combined_recs) lrecs = list(combined_recs.to_recommendations()) from calibre.customize.ui import plugin_for_output_format op = plugin_for_output_format(self.output_format) if op and op.recommendations: prec = {x[0] for x in op.recommendations} for i, r in enumerate(list(lrecs)): if r[0] in prec: lrecs[i] = (r[0], r[1], OptionRecommendation.HIGH) cover_file = create_cover_file(self.db, book_id) if opf_file is not None: lrecs.append(('read_metadata_from_opf', opf_file.name, OptionRecommendation.HIGH)) temp_files.append(opf_file) if cover_file is not None: lrecs.append( ('cover', cover_file.name, OptionRecommendation.HIGH)) temp_files.append(cover_file) for x in list(lrecs): if x[0] == 'debug_pipeline': lrecs.remove(x) try: dtitle = unicode_type(mi.title) except: dtitle = repr(mi.title) if len(dtitle) > 50: dtitle = dtitle[:50].rpartition(' ')[0] + '...' self.setLabelText(_('Queueing ') + dtitle) desc = _('Convert book %(num)d of %(tot)d (%(title)s)') % dict( num=self.i, tot=len(self.book_ids), title=dtitle) args = [in_file.name, out_file.name, lrecs] temp_files.append(out_file) func = 'gui_convert_override' if same_fmt: func += ':same_fmt' self.jobs.append((func, args, desc, self.output_format.upper(), book_id, temp_files)) self.changed = True self.setValue(self.i) except NoSupportedInputFormats: self.bad.append(book_id) QTimer.singleShot(0, self.do_book)