def onTextCtrlZoom(self, direction, announce=True): self._has_text_zoom = True last_pos = self.contentTextCtrl.GetLastPosition() existing_style = wx.TextAttr() self.contentTextCtrl.GetStyle(0, existing_style) new_style = wx.TextAttr(existing_style) font = new_style.Font size = font.GetPointSize() if direction == 1: if size > 64: return wx.Bell() new_style.Font = font.MakeLarger() # Translators: a message telling the user that the font size has been increased msg = _("The font size has been Increased") elif direction == -1: if size < 8: return wx.Bell() new_style.Font = font.MakeSmaller() # Translators: a message telling the user that the font size has been decreased msg = _("The font size has been decreased") else: new_style = self.contentTextCtrl.GetDefaultStyle() # Translators: a message telling the user that the font size has been reset msg = _("The font size has been reset") self._has_text_zoom = False self.contentTextCtrl.SetStyle(0, last_pos, new_style) if announce: speech.announce(msg)
def go_to_position(self, start_pos, end_pos=None): if end_pos is None: start, end = self.get_containing_line(start_pos) else: start, end = start_pos, end_pos line_text = self.contentTextCtrl.GetRange(start, end) self.set_insertion_point(start) sounds.navigation.play() speech.announce(line_text)
def onPinDocument(self, event): if self.IsChecked(event.GetId()): recents_manager.pin(self.reader.document) sounds.pinning.play() speech.announce("Pinned") else: recents_manager.unpin(self.reader.document) sounds.pinning.play() speech.announce("Unpinned") self.populate_pinned_documents_list()
def onAutoScanPages(self, event): event.Skip() if self.service.stored_options is None: self._get_ocr_options(force_save=True) if self.auto_scan_item.IsChecked(): speech.announce(_("Automatic OCR is enabled")) else: speech.announce(_("Automatic OCR is disabled")) if not self.view.contentTextCtrl.GetValue(): self.onScanCurrentPage(event)
def zoom_factor(self, value): if (value < 1.0) or (value > 10.0): return self._zoom_factor = value self.setDialogImage() self.scroll.SetupScrolling(rate_x=self.scroll_rate, rate_y=self.scroll_rate) # Translators: a message announced to the user when the zoom factor changes speech.announce( _("Zoom is at {factor} percent").format(factor=int(value * 100)) )
def onStructuredNavigation(self, event): if not self.reader.ready: wx.Bell() return elif not self.reader.document.supports_structural_navigation(): # Translators: spoken message when the current document does not # support structural navigation speech.announce("Not supported in this document.") return self.view.navigate_to_structural_element( element_type=event.SemanticElementType, forward=event.Forward)
def onPauseToggle(self, event): if self.reader.tts.is_ready: if self.reader.tts.engine.state is SynthState.busy: self.reader.tts.engine.pause() # Translators: a message that is announced when the speech is paused return speech.announce(_("Paused")) elif self.reader.tts.engine.state is SynthState.paused: self.reader.tts.engine.resume() # Translators: a message that is announced when the speech is resumed return speech.announce(_("Resumed")) wx.Bell()
def set_state_on_section_change(self, current): self.tocTreeSetSelection(current) is_single_page_doc = self.reader.document.is_single_page_document() if (is_single_page_doc and current is not self.reader.document.get_section_at_position( self.get_insertion_point())): target_pos = self.get_containing_line(current.text_range.start + 1)[0] self.set_insertion_point(target_pos) if not is_single_page_doc and config.conf["general"][ "speak_section_title"]: speech.announce(current.title)
def active_section(self, value): if (value is None) or (value is self.active_section): return elif self.active_section is not None: self.active_section.pager.reset() _prev_page = None if self.active_section is None else self.current_page self.__state["active_section"] = value self.view.tocTreeSetSelection(value) page_number = value.pager.current if page_number != _prev_page: self.current_page = page_number speech.announce(value.title) reader_section_changed.send(self, active=value)
def onItemActivated(self, event): selected_result = self.result_list.get_selected() page = selected_result.page_index position = Page.get_text_start_position( selected_result.page_id, selected_result.snippet ) uri = selected_result.document.uri.create_copy( openner_args=dict(page=page, position=position) ) # Translators: spoken message speech.announce("Openning document...") sounds.navigation.play() EBookReader.open_document_in_a_new_instance(uri)
def filter_document_list(self, filter_query): matching_items = fuzzy_search( filter_query, self._all_items, string_converter=operator.attrgetter("title")) self.document_list.DeleteAllItems() self.items = matching_items self.render_items( matching_items, self.create_image_list_from_items(matching_items), set_focus_to_first_item=False, ) if not matching_items: # Translators: spoken message when no matching documents upon filtering the document list speech.announce(_("No matching documents"))
def onScanCurrentPage(self, event): self._ocr_cancelled.clear() ocr_opts = self._get_ocr_options() if ocr_opts is None: return speech.announce(_("Canceled"), True) reader = self.service.reader if reader.current_page in self.service.saved_scanned_pages: self.view.set_content( self.service.saved_scanned_pages[reader.current_page]) return image = reader.document.get_page_image( reader.current_page, ocr_opts.zoom_factor, ) def _ocr_callback(ocr_result): page_number = ocr_result.cookie content = ocr_result.recognized_text self.service.saved_scanned_pages[page_number] = content if page_number == self.view.reader.current_page: self.view.set_content(content) self.view.set_text_direction(ocr_opts.language.is_rtl) ocr_request = OcrRequest( language=ocr_opts.language, image=image, image_processing_pipelines=ocr_opts.image_processing_pipelines, cookie=reader.current_page, ) self._run_ocr(ocr_request, _ocr_callback)
def onStop(self, event): if (self.service.is_engine_ready and self.service.engine.state is not SynthState.ready): self.service.stop_speech(user_requested=True) # Translators: a message that is announced when the speech is stopped return speech.announce(_("Stopped")) wx.Bell()
def onStop(self, event): if (self.reader.tts.is_ready and self.reader.tts.engine.state is not SynthState.ready): self.reader.tts.engine.stop() setattr(self.reader.tts, "_requested_play", False) # Translators: a message that is announced when the speech is stopped return speech.announce(_("Stopped")) wx.Bell()
def navigate_to_structural_element(self, element_type, forward): if not self.reader.ready: wx.Bell() return current_insertion_point = self.get_insertion_point() pos = self.reader.get_semantic_element( element_type, forward, current_insertion_point, ) if pos is not None: ((start, stop), actual_element_type) = pos pos_info = (current_insertion_point, pos) if self.__latest_structured_navigation_position == pos_info: self.set_insertion_point(stop) return self.navigate_to_structural_element( element_type, forward) self.__latest_structured_navigation_position = pos_info ( element_label, should_speak_whole_text, move_to_start_of_line, ) = SEMANTIC_ELEMENT_OUTPUT_OPTIONS[actual_element_type] text_start, text_stop = (self.get_containing_line(start + 1) if should_speak_whole_text else (start, stop)) text = self.contentTextCtrl.GetRange(text_start, text_stop) msg = _("{text}: {item_type}").format(text=text, item_type=_(element_label)) target_position = (start if not move_to_start_of_line else self.get_containing_line(stop - 1)[0]) self.set_insertion_point(target_position) speech.announce(msg, True) sounds.structured_navigation.play() reading_position_change.send( self, position=start, tts_speech_prefix=_(element_label), ) else: element_label = SEMANTIC_ELEMENT_OUTPUT_OPTIONS[element_type][0] if forward: msg = _("No next {item}") else: msg = _("No previous {item}") speech.announce(msg.format(item=_(element_label)), True)
def _process_ocr_result(self, callback, task): if self._ocr_cancelled.is_set(): ocr_ended.send(sender=self.view, isfaulted=True) self._ocr_cancelled.clear() return try: ocr_result = task.result() except Exception as e: log.exception(f"Error getting OCR recognition results.", exc_info=True) ocr_ended.send(sender=self.view, isfaulted=True) return callback(ocr_result) sounds.ocr_end.play() speech.announce(_("Scan finished."), urgent=True) self.view.contentTextCtrl.SetFocusFromKbd() ocr_ended.send(sender=self.view, isfaulted=False)
def set_state_on_page_change(self, page): self.set_content(page.get_text()) if config.conf["general"]["play_pagination_sound"]: sounds.pagination.play() status_text = self.get_statusbar_text() self.set_status(status_text) if self.reader.document.is_single_page_document(): # Translators: label of content text control when the currently opened # document is a single page document self.contentTextCtrlLabel.SetLabel(_("Document content")) if config.conf["general"]["speak_page_number"]: # Translators: a message that is announced after navigating to a page spoken_msg = _("Page {page} of {total}").format( page=page.number, total=len(self.reader.document)) speech.announce(spoken_msg) if config.conf["general"]["show_reading_progress_percentage"]: self.update_reading_progress()
def _add_search_results(self, request, dlg): search_func = self.reader.document.search results = [] for (i, resultset) in enumerate(search_func(request)): results.extend(resultset) if dlg.IsShown(): dlg.addResultSet(resultset) # Translators: message to announce the number of search results # also used as the final title of the search results dialog msg = _("Results | {total}").format(total=len(results)) with self.search_lock: if self._last_search_request != request: return speech.announce(msg, True) sounds.ready.play() if dlg.IsShown(): dlg.SetTitle(msg) self._latest_search_results = tuple(results) self.maintain_state(True)
def current_page(self, value): assert self.active_section is not None, "No active section." if value is None: return elif value not in self.active_section.pager: raise ValueError(f"Page {value} is out of range for this section.") _prev = self.active_section.pager.current self.active_section.pager.set_current(value) self.view.set_content(self.get_page_content(value)) if config.conf["general"]["play_pagination_sound"]: sounds.pagination.play_after() # Translators: the label of the page content text area cmsg = _("Page {page} | {chapter}").format( page=value + 1, chapter=self.active_section.title) # Translators: a message that is announced after navigating to a page smsg = _("Page {page} of {total}").format(page=value + 1, total=len(self.document)) self.view.SetStatusText(cmsg) speech.announce(smsg) reader_page_changed.send(self, current=value, prev=_prev)
def onTextCtrlZoom(self, direction): font = self.contentTextCtrl.GetFont() size = font.GetPointSize() if direction == 1: if size >= 64: return wx.Bell() self.contentTextCtrl.SetFont(font.MakeLarger()) # Translators: a message telling the user that the font size has been increased msg = _("The font size has been Increased") elif direction == -1: if size <= 6: return wx.Bell() self.contentTextCtrl.SetFont(font.MakeSmaller()) # Translators: a message telling the user that the font size has been decreased msg = _("The font size has been decreased") else: self.contentTextCtrl.SetFont(wx.NullFont) # Translators: a message telling the user that the font size has been reset msg = _("The font size has been reset") speech.announce(msg)
def _add_bookmark(self, name=""): bookmarker = Bookmarker(self.reader) insertionPoint = self.view.contentTextCtrl.GetInsertionPoint() __, __, current_lino = self.view.contentTextCtrl.PositionToXY( insertionPoint) count = 0 for bkm in bookmarker.get_for_page(self.reader.current_page): __, __, lino = self.view.contentTextCtrl.PositionToXY(bkm.position) if lino == current_lino: count += 1 bookmarker.delete(bkm.id) self.service.style_bookmark(self.view, bkm.position, enable=False) if count and not name: return speech.announce(_("Bookmark removed")) Bookmarker(self.reader).create(title=name, position=insertionPoint) # Translators: spoken message speech.announce(_("Bookmark Added")) self.service.style_bookmark(self.view, insertionPoint)
def _add_search_results(self, request, dlg): search_func = self.reader.document.search doc_path = self.reader.document.filename total = 0 for page, snip, section, pos in search_func(doc_path, request): if pos is None: wx.CallAfter( dlg.progressbar.SetValue, round((page / request.to_page) * 100) ) continue if not dlg.IsShown(): break wx.CallAfter(dlg.addResult, page, snip, section, pos) self._latest_search_results.append((page, snip, section, pos)) total += 1 if dlg.IsShown(): # Translators: the final title of the search results dialog # shown after the search is finished msg = _("Results | {total}").format(total=total) dlg.SetTitle(msg) speech.announce(msg, True)
def onQuoteSelection(self, event): _with_tags = wx.GetKeyState(wx.WXK_SHIFT) quoter = Quoter(self.reader) selected_text = self.view.contentTextCtrl.GetStringSelection() if not selected_text: return speech.announce(_("No selection")) x, y = self.view.get_selection_range() for q in quoter.get_for_page(): q_range = TextRange(q.start_pos, q.end_pos) if (q_range.start == x) and (q_range.stop == y): quoter.delete(q.id) self.service.style_highlight(self.view, x, y, enable=False) # Translators: spoken message return speech.announce(_("Highlight removed")) elif (q.start_pos < x) and (q.end_pos > y): # Translators: spoken message speech.announce(_("Already highlighted")) return wx.Bell() if (x in q_range) or (y in q_range): if x not in q_range: q.start_pos = x q.session.commit() self.service.style_highlight(self.view, x, q_range.stop) return speech.announce(_("Highlight extended")) elif y not in q_range: q.end_pos = y q.session.commit() self.service.style_highlight(self.view, q_range.start, y) # Translators: spoken message return speech.announce(_("Highlight extended")) quote = quoter.create(title="", content=selected_text, start_pos=x, end_pos=y) # Translators: spoken message speech.announce(_("Selection highlighted")) self.service.style_highlight(self.view, x, y) if _with_tags: # add tags tags_text = self.view.get_text_from_user( # Translators: title of a dialog _("Tag Highlight"), # Translators: label of a text entry _("Tags:"), ) if tags_text: for tag in tags_text.split(): quote.tags.append(tag.strip()) Quoter.model.session.commit()
def _do_open_document_in_system_viewer(self, document_info): uri = self.source.resolve_item_uri(document_info) wx.LaunchDefaultApplication(str(uri.path)) sounds.navigation.play() # Translators: spoken message when activating a document speech.announce("Openning document...")
def _do_open_document(self, document_info): sounds.navigation.play() # Translators: spoken message when activating a document speech.announce("Openning document...") uri = self.source.resolve_item_uri(document_info) EBookReader.open_document_in_a_new_instance(uri)
def go_to_webpage(self, url): speech.announce(_("Opening page: {url}").format(url=url)) webbrowser.open_new_tab(url)
def _on_ocr_cancelled(self): self._ocr_cancelled.set() speech.announce(_("OCR canceled"), True) sounds.ocr_end.play() return True