def __init__(self, *args): QFrame.__init__(self, *args) self.setFrameStyle(QFrame.StyledPanel | QFrame.Sunken) self.edit = QTextBrowser() self.edit.setFrameStyle(QFrame.NoFrame) self.number_bar = self.NumberBar() self.number_bar.setTextEdit(self.edit) hbox = QHBoxLayout(self) hbox.setSpacing(0) margins = QMargins(0, 0, 0, 0) hbox.setContentsMargins(margins) hbox.addWidget(self.number_bar) hbox.addWidget(self.edit) self.edit.installEventFilter(self) self.edit.viewport().installEventFilter(self) config = Config() style_str = config.array_config_str('log_line_number_style') self.setStyleSheet(style_str)
def __init__(self, parent): QWidget.__init__(self, parent) self._text_edit = CodeTextEdit(self) self._output_pane = QTextBrowser(self) self._output_pane.document().setDefaultFont(QFont('Courier', pointSize=7)) self._output_pane.setWordWrapMode(QTextOption.NoWrap) self._output_pane_container = QWidget(self) self._output_pane_layout = QGridLayout(self._output_pane_container) self._output_pane_layout.setContentsMargins(0, 16, 0, 0) self._output_pane_layout.addWidget(QLabel(self.tr('Script Output')), 0, 0) self._output_pane_layout.addWidget(self._output_pane) self._splitter = QSplitter(Qt.Vertical, self) self._splitter.addWidget(self._text_edit) self._splitter.addWidget(self._output_pane_container) self._splitter.setStretchFactor(0, 3) self._splitter.setStretchFactor(1, 1) self._layout = QGridLayout(self) self._layout.setContentsMargins(0, 0, 0, 0) self._layout.addWidget(self._splitter, 0, 0) self._text_edit.editComplete.connect(self.editComplete)
def setup_ui(self): self.pb = pb = QProgressBar(self) pb.setTextVisible(True) pb.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) pb.setRange(0, 0) self.w = w = QWidget(self) self.w.l = l = QVBoxLayout(w) l.addStretch(), l.addWidget(pb) self.w.la = la = QLabel(_('Checking external links, please wait...')) la.setStyleSheet('QLabel { font-size: 20px; font-weight: bold }') l.addWidget(la, 0, Qt.AlignCenter), l.addStretch() self.l = l = QVBoxLayout(self) self.results = QTextBrowser(self) self.results.setOpenLinks(False) self.results.anchorClicked.connect(self.anchor_clicked) self.stack = s = QStackedWidget(self) s.addWidget(w), s.addWidget(self.results) l.addWidget(s) self.bh = h = QHBoxLayout() self.check_anchors = ca = QCheckBox(_('Check &anchors')) ca.setToolTip( _('Check HTML anchors in links (the part after the #).\n' ' This can be a little slow, since it requires downloading and parsing all the HTML pages.' )) ca.setChecked(tprefs.get('check_external_link_anchors', True)) ca.stateChanged.connect(self.anchors_changed) h.addWidget(ca), h.addStretch(100), h.addWidget(self.bb) l.addLayout(h) self.bb.setStandardButtons(self.bb.Close) self.rb = b = self.bb.addButton(_('&Refresh'), self.bb.ActionRole) b.setIcon(QIcon(I('view-refresh.png'))) b.clicked.connect(self.refresh)
def __init__(self, title, html, parent=None, unique_name=None): QDialog.__init__(self, parent) self.l = l = QVBoxLayout() self.setLayout(l) self.tb = QTextBrowser(self) self.tb.setHtml('<pre style="font-family: monospace">%s</pre>' % html) l.addWidget(self.tb) self.bb = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok) self.bb.accepted.connect(self.accept) self.bb.rejected.connect(self.reject) self.copy_button = self.bb.addButton(_('Copy to clipboard'), self.bb.ActionRole) self.copy_button.setIcon(QIcon(I('edit-copy.png'))) self.copy_button.clicked.connect(self.copy_to_clipboard) l.addWidget(self.bb) self.unique_name = unique_name or 'view-log-dialog' self.finished.connect(self.dialog_closing) self.resize(QSize(700, 500)) geom = gprefs.get(self.unique_name, None) if geom is not None: QApplication.instance().safe_restore_geometry(self, geom) self.setModal(False) self.setWindowTitle(title) self.setWindowIcon(QIcon(I('debug.png'))) self.show()
def __init__(self, mi, parent=None): QTextBrowser.__init__(self, parent) series = '' fm = field_metadata if mi.series: series = _('{num} of {series}').format( num=mi.format_series_index(), series='<i>%s</i>' % mi.series) self.setHtml(''' <h3 style="text-align:center">{mb}</h3> <p><b>{title}</b> - <i>{authors}</i><br></p> <table> <tr><td>{fm[timestamp][name]}:</td><td>{date}</td></tr> <tr><td>{fm[pubdate][name]}:</td><td>{published}</td></tr> <tr><td>{fm[formats][name]}:</td><td>{formats}</td></tr> <tr><td>{fm[series][name]}:</td><td>{series}</td></tr> </table> '''.format(mb=_('Target book'), title=mi.title, authors=authors_to_string(mi.authors), date=format_date(mi.timestamp, tweaks['gui_timestamp_display_format']), fm=fm, published=(format_date(mi.pubdate, tweaks['gui_pubdate_display_format']) if mi.pubdate else ''), formats=', '.join(mi.formats or ()), series=series))
class ViewLog(QDialog): # {{{ def __init__(self, title, html, parent=None): QDialog.__init__(self, parent) self.l = l = QVBoxLayout() self.setLayout(l) self.tb = QTextBrowser(self) self.tb.setHtml('<pre style="font-family: monospace">%s</pre>' % html) l.addWidget(self.tb) self.bb = QDialogButtonBox(QDialogButtonBox.Ok) self.bb.accepted.connect(self.accept) self.bb.rejected.connect(self.reject) self.copy_button = self.bb.addButton(_('Copy to clipboard'), self.bb.ActionRole) self.copy_button.setIcon(QIcon(I('edit-copy.png'))) self.copy_button.clicked.connect(self.copy_to_clipboard) l.addWidget(self.bb) self.setModal(False) self.resize(QSize(700, 500)) self.setWindowTitle(title) self.setWindowIcon(QIcon(I('debug.png'))) self.show() def copy_to_clipboard(self): txt = self.tb.toPlainText() QApplication.clipboard().setText(txt)
def __init__(self, title, html, parent=None): QDialog.__init__(self, parent) self.l = l = QVBoxLayout() self.setLayout(l) self.tb = QTextBrowser(self) QApplication.setOverrideCursor(Qt.WaitCursor) # Rather than formatting the text in <pre> blocks like the calibre # ViewLog does, instead just format it inside divs to keep style formatting html = html.replace('\t', ' ') html = html.replace('> ', '> ') self.tb.setHtml('<div>{0}</div>'.format(html)) QApplication.restoreOverrideCursor() l.addWidget(self.tb) self.bb = QDialogButtonBox(QDialogButtonBox.Ok) self.bb.accepted.connect(self.accept) self.bb.rejected.connect(self.reject) self.copy_button = self.bb.addButton(_('Copy to clipboard'), self.bb.ActionRole) self.copy_button.setIcon(QIcon(I('edit-copy.png'))) self.copy_button.clicked.connect(self.copy_to_clipboard) l.addWidget(self.bb) self.setModal(False) self.resize(QSize(700, 500)) self.setWindowTitle(title) self.setWindowIcon(QIcon(I('debug.png'))) self.show()
class ViewLog(QDialog): def __init__(self, title, html, parent=None): QDialog.__init__(self, parent) self.l = l = QVBoxLayout() self.setLayout(l) self.tb = QTextBrowser(self) QApplication.setOverrideCursor(Qt.WaitCursor) # Rather than formatting the text in <pre> blocks like the calibre # ViewLog does, instead just format it inside divs to keep style formatting html = html.replace('\t',' ') html = html.replace('> ','> ') self.tb.setHtml('<div>{0}</div>'.format(html)) QApplication.restoreOverrideCursor() l.addWidget(self.tb) self.bb = QDialogButtonBox(QDialogButtonBox.Ok) self.bb.accepted.connect(self.accept) self.bb.rejected.connect(self.reject) self.copy_button = self.bb.addButton(_('Copy to clipboard'), self.bb.ActionRole) self.copy_button.setIcon(QIcon(I('edit-copy.png'))) self.copy_button.clicked.connect(self.copy_to_clipboard) l.addWidget(self.bb) self.setModal(False) self.resize(QSize(700, 500)) self.setWindowTitle(title) self.setWindowIcon(QIcon(I('debug.png'))) self.show() def copy_to_clipboard(self): txt = self.tb.toPlainText() QApplication.clipboard().setText(txt)
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, *args): QTextBrowser.__init__(self, *args) self.setStyleSheet("background:white;color:black;") try: self.setText(codecs.open(self.loadFile(), "r", "UTF-8").read()) except Exception, msg: ctx.logger.error(_(msg))
def __init__(self, parent): QTextBrowser.__init__(self, parent) self.setFrameShape(self.NoFrame) self.setOpenLinks(False) self.setAttribute(Qt.WA_OpaquePaintEvent, False) palette = self.palette() palette.setBrush(QPalette.Base, Qt.transparent) self.setPalette(palette) self.setAcceptDrops(False)
def __init__(self, parent=None): QTextBrowser.__init__(self, parent) self.setAcceptDrops(False) self.setMaximumWidth(300) self.setMinimumWidth(300) self.wait_timer = QTimer(self) self.wait_timer.timeout.connect(self.update_wait) self.wait_timer.setInterval(800) self.dots_count = 0 palette = self.palette() palette.setBrush(QPalette.Base, Qt.transparent) self.setPalette(palette) self.setAttribute(Qt.WA_OpaquePaintEvent, False) self.anchorClicked.connect(self.link_clicked)
def __init__(self, parent=None): QSplitter.__init__(self, parent) self.setChildrenCollapsible(False) self.items = i = QListWidget(self) i.setContextMenuPolicy(Qt.CustomContextMenu) i.customContextMenuRequested.connect(self.context_menu) self.items.setSpacing(3) self.items.itemDoubleClicked.connect(self.current_item_activated) self.items.currentItemChanged.connect(self.current_item_changed) self.items.setSelectionMode(self.items.NoSelection) self.delegate = Delegate(self.items) self.items.setItemDelegate(self.delegate) self.addWidget(i) self.help = h = QTextBrowser(self) h.anchorClicked.connect(self.link_clicked) h.setOpenLinks(False) self.addWidget(h) self.setStretchFactor(0, 100) self.setStretchFactor(1, 50) self.clear_at_startup() state = tprefs.get('check-book-splitter-state', None) if state is not None: self.restoreState(state)
def setup_ui(self): self.pb = pb = QProgressBar(self) pb.setTextVisible(True) pb.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) pb.setRange(0, 0) self.w = w = QWidget(self) self.w.l = l = QVBoxLayout(w) l.addStretch(), l.addWidget(pb) self.w.la = la = QLabel(_('Checking external links, please wait...')) la.setStyleSheet('QLabel { font-size: 20px; font-weight: bold }') l.addWidget(la, 0, Qt.AlignCenter), l.addStretch() self.l = l = QVBoxLayout(self) self.results = QTextBrowser(self) self.results.setOpenLinks(False) self.results.anchorClicked.connect(self.anchor_clicked) self.stack = s = QStackedWidget(self) s.addWidget(w), s.addWidget(self.results) l.addWidget(s) self.bh = h = QHBoxLayout() self.check_anchors = ca = QCheckBox(_('Check &anchors')) ca.setToolTip(_('Check HTML anchors in links (the part after the #).\n' ' This can be a little slow, since it requires downloading and parsing all the HTML pages.')) ca.setChecked(tprefs.get('check_external_link_anchors', True)) ca.stateChanged.connect(self.anchors_changed) h.addWidget(ca), h.addStretch(100), h.addWidget(self.bb) l.addLayout(h) self.bb.setStandardButtons(self.bb.Close) self.rb = b = self.bb.addButton(_('&Refresh'), self.bb.ActionRole) b.setIcon(QIcon(I('view-refresh.png'))) b.clicked.connect(self.refresh)
def __init__(self, parent=None): QTextBrowser.__init__(self, parent) font = self.font() f = QFontInfo(font) delta = tweaks['change_book_details_font_size_by'] + 1 if delta: font.setPixelSize(f.pixelSize() + delta) self.setFont(font) self.setFrameShape(self.NoFrame) self.setOpenLinks(False) self.setAttribute(Qt.WA_OpaquePaintEvent, False) palette = self.palette() palette.setBrush(QPalette.Base, Qt.transparent) self.setPalette(palette) self.setAcceptDrops(False) self.anchorClicked.connect(self.on_anchor_clicked)
def show_report(changed, title, report, parent, show_current_diff): report = format_report(title, report) d = QDialog(parent) d.setWindowTitle(_('Action report')) d.l = QVBoxLayout() d.setLayout(d.l) d.e = QTextBrowser(d) d.l.addWidget(d.e) d.e.setHtml(report) d.bb = QDialogButtonBox(QDialogButtonBox.Close) d.show_changes = False if changed: b = d.b = d.bb.addButton(_('See what &changed'), d.bb.AcceptRole) b.setIcon(QIcon(I('diff.png'))), b.setAutoDefault(False) connect_lambda(b.clicked, d, lambda d: setattr(d, 'show_changes', True)) b = d.bb.addButton(_('&Copy to clipboard'), d.bb.ActionRole) b.setIcon(QIcon(I('edit-copy.png'))), b.setAutoDefault(False) def copy_report(): text = re.sub(r'</.+?>', '\n', report) text = re.sub(r'<.+?>', '', text) cp = QApplication.instance().clipboard() cp.setText(text) b.clicked.connect(copy_report) d.bb.button(d.bb.Close).setDefault(True) d.l.addWidget(d.bb) d.bb.rejected.connect(d.reject) d.bb.accepted.connect(d.accept) d.resize(600, 400) d.exec_() b.clicked.disconnect() if d.show_changes: show_current_diff(allow_revert=True)
def __init__(self, title, html, parent=None, unique_name=None): QDialog.__init__(self, parent) self.l = l = QVBoxLayout() self.setLayout(l) self.tb = QTextBrowser(self) self.tb.setHtml('<pre style="font-family: monospace">%s</pre>' % html) l.addWidget(self.tb) self.bb = QDialogButtonBox(QDialogButtonBox.Ok) self.bb.accepted.connect(self.accept) self.bb.rejected.connect(self.reject) self.copy_button = self.bb.addButton(_('Copy to clipboard'), self.bb.ActionRole) self.copy_button.setIcon(QIcon(I('edit-copy.png'))) self.copy_button.clicked.connect(self.copy_to_clipboard) l.addWidget(self.bb) self.unique_name = unique_name or 'view-log-dialog' self.finished.connect(self.dialog_closing) self.resize(QSize(700, 500)) geom = gprefs.get(self.unique_name, None) if geom is not None: self.restoreGeometry(geom) self.setModal(False) self.setWindowTitle(title) self.setWindowIcon(QIcon(I('debug.png'))) self.show()
class LogViewer(QDialog): # {{{ 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 copy_to_clipboard(self): QApplication.clipboard().setText(''.join(self.log.plain_text)) def stop(self, *args): self.keep_updating = False 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)
class LogViewer(QDialog): # {{{ 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 copy_to_clipboard(self): QApplication.clipboard().setText(''.join(self.log.plain_text)) def stop(self, *args): self.keep_updating = False 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, title, html, parent=None): SizePersistedDialog.__init__(self, parent, 'epubsplit:view sample') self.l = l = QVBoxLayout() self.setLayout(l) self.tb = QTextBrowser(self) self.tb.setHtml(html) l.addWidget(self.tb) self.bb = QDialogButtonBox(QDialogButtonBox.Ok) self.bb.accepted.connect(self.accept) self.bb.rejected.connect(self.reject) l.addWidget(self.bb) self.setModal(False) self.setWindowTitle(title) self.setWindowIcon(get_icon('format-justify-fill.png')) # Cause our dialog size to be restored from prefs or created on first usage self.resize_dialog() self.show()
class ViewLog(QDialog): ''' Show a detailed summary of results as html. ''' def __init__(self, title, html, parent=None): ''' :param title: Caption for window title :param html: HTML string log/report ''' QDialog.__init__(self, parent) self.l = l = QVBoxLayout() self.setLayout(l) self.tb = QTextBrowser(self) QApplication.setOverrideCursor(Qt.WaitCursor) # Rather than formatting the text in <pre> blocks like the calibre # ViewLog does, instead just format it inside divs to keep style formatting html = html.replace( '\t', ' ') #.replace('\n', '<br/>') html = html.replace('> ', '> ') self.tb.setHtml('<div>{0}</div>'.format(html)) QApplication.restoreOverrideCursor() l.addWidget(self.tb) self.bb = QDialogButtonBox(QDialogButtonBox.Ok) self.bb.accepted.connect(self.accept) self.bb.rejected.connect(self.reject) self.copy_button = self.bb.addButton(_('Copy to clipboard'), self.bb.ActionRole) self.copy_button.setIcon(QIcon(I('edit-copy.png'))) self.copy_button.clicked.connect(self.copy_to_clipboard) l.addWidget(self.bb) self.setModal(False) self.resize(QSize(700, 500)) self.setWindowTitle(title) self.setWindowIcon(QIcon(I('dialog_information.png'))) self.show() def copy_to_clipboard(self): txt = self.tb.toPlainText() QApplication.clipboard().setText(txt)
def __init__(self, parent=None): QTextBrowser.__init__(self, parent) self.last_set_html = '' self.default_css = self.external_css = '' app = QApplication.instance() app.palette_changed.connect(self.palette_changed) self.palette_changed() font = self.font() f = QFontInfo(font) delta = tweaks['change_book_details_font_size_by'] + 1 if delta: font.setPixelSize(f.pixelSize() + delta) self.setFont(font) self.setFrameShape(self.NoFrame) self.setOpenLinks(False) self.setAttribute(Qt.WidgetAttribute.WA_OpaquePaintEvent, False) palette = self.palette() palette.setBrush(QPalette.ColorRole.Base, Qt.GlobalColor.transparent) self.setPalette(palette) self.setAcceptDrops(False) self.anchorClicked.connect(self.on_anchor_clicked)
class ViewSample(SizePersistedDialog): def __init__(self, title, html, parent=None): SizePersistedDialog.__init__(self, parent, 'epubsplit:view sample') self.l = l = QVBoxLayout() self.setLayout(l) self.tb = QTextBrowser(self) self.tb.setHtml(html) l.addWidget(self.tb) self.bb = QDialogButtonBox(QDialogButtonBox.Ok) self.bb.accepted.connect(self.accept) self.bb.rejected.connect(self.reject) l.addWidget(self.bb) self.setModal(False) self.setWindowTitle(title) self.setWindowIcon(get_icon('format-justify-fill.png')) # Cause our dialog size to be restored from prefs or created on first usage self.resize_dialog() self.show()
class ViewLog(QDialog): # {{{ def __init__(self, title, html, parent=None, unique_name=None): QDialog.__init__(self, parent) self.l = l = QVBoxLayout() self.setLayout(l) self.tb = QTextBrowser(self) self.tb.setHtml('<pre style="font-family: monospace">%s</pre>' % html) l.addWidget(self.tb) self.bb = QDialogButtonBox(QDialogButtonBox.Ok) self.bb.accepted.connect(self.accept) self.bb.rejected.connect(self.reject) self.copy_button = self.bb.addButton(_('Copy to clipboard'), self.bb.ActionRole) self.copy_button.setIcon(QIcon(I('edit-copy.png'))) self.copy_button.clicked.connect(self.copy_to_clipboard) l.addWidget(self.bb) self.unique_name = unique_name or 'view-log-dialog' self.finished.connect(self.dialog_closing) self.resize(QSize(700, 500)) geom = gprefs.get(self.unique_name, None) if geom is not None: self.restoreGeometry(geom) self.setModal(False) self.setWindowTitle(title) self.setWindowIcon(QIcon(I('debug.png'))) self.show() def copy_to_clipboard(self): txt = self.tb.toPlainText() QApplication.clipboard().setText(txt) def dialog_closing(self, result): gprefs[self.unique_name] = bytearray(self.saveGeometry())
def __init__(self, mi, parent=None): QTextBrowser.__init__(self, parent) series = '' fm = field_metadata if mi.series: series = _('{num} of {series}').format(num=mi.format_series_index(), series='<i>%s</i>' % mi.series) self.setHtml(''' <h3 style="text-align:center">{mb}</h3> <p><b>{title}</b> - <i>{authors}</i><br></p> <table> <tr><td>{fm[timestamp][name]}:</td><td>{date}</td></tr> <tr><td>{fm[pubdate][name]}:</td><td>{published}</td></tr> <tr><td>{fm[formats][name]}:</td><td>{formats}</td></tr> <tr><td>{fm[series][name]}:</td><td>{series}</td></tr> </table> '''.format( mb=_('Target book'), title=mi.title, authors=authors_to_string(mi.authors), date=format_date(mi.timestamp, tweaks['gui_timestamp_display_format']), fm=fm, published=(format_date(mi.pubdate, tweaks['gui_pubdate_display_format']) if mi.pubdate else ''), formats=', '.join(mi.formats or ()), series=series ))
def setup_ui(self): self.pb = pb = QProgressBar(self) pb.setTextVisible(True) pb.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) pb.setRange(0, 0) self.w = w = QWidget(self) self.w.l = l = QVBoxLayout(w) l.addStretch(), l.addWidget(pb) self.w.la = la = QLabel(_('Checking external links, please wait...')) la.setStyleSheet('QLabel { font-size: 20px; font-weight: bold }') l.addWidget(la, 0, Qt.AlignCenter), l.addStretch() self.l = l = QVBoxLayout(self) self.results = QTextBrowser(self) self.results.setOpenLinks(False) self.results.anchorClicked.connect(self.anchor_clicked) self.stack = s = QStackedWidget(self) s.addWidget(w), s.addWidget(self.results) l.addWidget(s) l.addWidget(self.bb) self.bb.setStandardButtons(self.bb.Close) self.rb = b = self.bb.addButton(_('&Refresh'), self.bb.ActionRole) b.setIcon(QIcon(I('view-refresh.png'))) b.clicked.connect(self.refresh)
def setup_ui(self): self.l = l = QVBoxLayout(self) self.splitter = s = QSplitter(self) s.setChildrenCollapsible(False) l.addWidget(s), l.addWidget(self.bb) self.bb.setStandardButtons(self.bb.Yes | self.bb.No) self.left = w = QWidget(self) s.addWidget(w) w.l = l = QVBoxLayout(w) l.setContentsMargins(0, 0, 0, 0) self.la = la = QLabel(self.msg) la.setWordWrap(True) l.addWidget(la) self.confirm = c = QCheckBox(_('Show this confirmation again'), self) c.setChecked(True) c.stateChanged.connect(self.toggle) l.addWidget(c) self.right = r = QTextBrowser(self) series = '' mi, fm = self.mi, field_metadata if mi.series: series = _('{num} of {series}').format( num=mi.format_series_index(), series='<i>%s</i>' % mi.series) r.setHtml(''' <h3 style="text-align:center">{mb}</h3> <p><b>{title}</b> - <i>{authors}</i><br></p> <table> <tr><td>{fm[timestamp][name]}:</td><td>{date}</td></tr> <tr><td>{fm[pubdate][name]}:</td><td>{published}</td></tr> <tr><td>{fm[formats][name]}:</td><td>{formats}</td></tr> <tr><td>{fm[series][name]}:</td><td>{series}</td></tr> </table> '''.format(mb=_('Target book'), title=mi.title, authors=authors_to_string(mi.authors), date=format_date(mi.timestamp, tweaks['gui_timestamp_display_format']), fm=fm, published=(format_date(mi.pubdate, tweaks['gui_pubdate_display_format']) if mi.pubdate else ''), formats=', '.join(mi.formats or ()), series=series)) s.addWidget(r)
def loadResource(self, rtype, qurl): if qurl.isLocalFile(): path = qurl.toLocalFile() try: with lopen(path, 'rb') as f: data = f.read() except EnvironmentError: if path.rpartition('.')[-1].lower() in {'jpg', 'jpeg', 'gif', 'png', 'bmp', 'webp'}: return QByteArray(bytearray.fromhex( '89504e470d0a1a0a0000000d49484452' '000000010000000108060000001f15c4' '890000000a49444154789c6300010000' '0500010d0a2db40000000049454e44ae' '426082')) else: return QByteArray(data) else: return QTextBrowser.loadResource(self, rtype, qurl)
def setup_ui(self): self.l = l = QVBoxLayout(self) if self.html_view: self.tb = w = QTextBrowser(self) else: self.log = w = QPlainTextEdit(self) w.setReadOnly(True), w.setLineWrapMode(w.NoWrap) l.addWidget(w) l.addWidget(self.bb) self.bb.clear(), self.bb.setStandardButtons(self.bb.Close) self.next_pos = 0 self.update() self.timer = QTimer(self) self.timer.timeout.connect(self.update) self.timer.start(1000) if not self.html_view: v = self.log.verticalScrollBar() v.setValue(v.maximum())
def show_report(changed, title, report, parent, show_current_diff): report = format_report(title, report) d = QDialog(parent) d.l = QVBoxLayout() d.setLayout(d.l) d.e = QTextBrowser(d) d.l.addWidget(d.e) d.e.setHtml(report) d.bb = QDialogButtonBox(QDialogButtonBox.Close) if changed: b = d.b = d.bb.addButton(_('See what &changed'), d.bb.AcceptRole) b.setIcon(QIcon(I('diff.png'))), b.setAutoDefault(False) b.clicked.connect(partial(show_current_diff, allow_revert=True)) d.bb.button(d.bb.Close).setDefault(True) d.l.addWidget(d.bb) d.bb.rejected.connect(d.reject) d.bb.accepted.connect(d.accept) d.resize(600, 400) d.exec_()
def setup_ui(self): self.l = l = QVBoxLayout(self) if self.html_view: self.tb = w = QTextBrowser(self) else: self.log = w = QPlainTextEdit(self) w.setReadOnly(True), w.setLineWrapMode(QPlainTextEdit.LineWrapMode.NoWrap) l.addWidget(w) l.addWidget(self.bb) self.bb.clear(), self.bb.setStandardButtons(QDialogButtonBox.StandardButton.Close) self.copy_button = b = self.bb.addButton(_('&Copy to clipboard'), QDialogButtonBox.ButtonRole.ActionRole) b.setIcon(QIcon(I('edit-copy.png'))) b.clicked.connect(self.copy_to_clipboard) self.next_pos = 0 self.update() self.timer = QTimer(self) self.timer.timeout.connect(self.update) self.timer.start(1000) if not self.html_view: v = self.log.verticalScrollBar() v.setValue(v.maximum())
def __init__(self, parent=None): QWidget.__init__(self, parent) self.setFocusPolicy(Qt.NoFocus) self.l = l = QVBoxLayout(self) l.setContentsMargins(0, 0, 0, 0) self.search_input = si = SearchInput(self, 'highlights-search') si.do_search.connect(self.search_requested) l.addWidget(si) la = QLabel(_('Double click to jump to an entry')) la.setWordWrap(True) l.addWidget(la) self.highlights = h = Highlights(self) l.addWidget(h) h.jump_to_highlight.connect(self.jump_to_highlight) h.current_highlight_changed.connect(self.current_highlight_changed) self.load = h.load self.refresh = h.refresh self.h = h = QHBoxLayout() l.addLayout(h) def button(icon, text, tt, target): b = QPushButton(QIcon(I(icon)), text, self) b.setToolTip(tt) b.setFocusPolicy(Qt.NoFocus) b.clicked.connect(target) return b self.add_button = button('plus.png', _('Add'), _('Create a new highlight'), self.add_highlight) self.edit_button = button('edit_input.png', _('Edit'), _('Edit the selected highlight'), self.edit_highlight) self.remove_button = button('trash.png', _('Remove'), _('Remove the selected highlight'), self.remove_highlight) h.addWidget(self.add_button), h.addWidget(self.edit_button), h.addWidget(self.remove_button) self.notes_display = nd = QTextBrowser(self) l.addWidget(nd) nd.setVisible(False)
def setHtml(self, html): self.last_set_html = html QTextBrowser.setHtml(self, html)
class NumberedTextBrowser(QFrame): class NumberBar(QWidget): def __init__(self, *args): QWidget.__init__(self, *args) self.edit = None # This is used to update the width of the control. # It is the highest line that is currently visibile. self.highest_line = '0' self.orig_line_number = [] def reset_data(self): self.orig_line_number.clear() self.highest_line = '0' self.edit.clear() def setOriginalLineNum(self, line_number): self.orig_line_number.append(str(line_number)) def setLineNumberList(self, line_numbers): self.orig_line_number = line_numbers def setTextEdit(self, edit): self.edit = edit def update(self, *args): ''' Updates the number bar to display the current set of numbers. Also, adjusts the width of the number bar if necessary. ''' # The + 4 is used to compensate for the current line being bold. width = self.fontMetrics().width(self.highest_line) + 4 if self.width() != width: self.setFixedWidth(width) QWidget.update(self, *args) def paintEvent(self, event): contents_y = self.edit.verticalScrollBar().value() page_bottom = contents_y + self.edit.viewport().height() font_metrics = self.fontMetrics() current_block = self.edit.document().findBlock( self.edit.textCursor().position()) painter = QPainter(self) line_count = 0 line_count_str = '' # Iterate over all text blocks in the document. block = self.edit.document().begin() while block.isValid(): orig_number = '' line_count += 1 if len(self.orig_line_number) >= line_count: orig_number = self.orig_line_number[line_count - 1] # The top left position of the block in the document position = self.edit.document().documentLayout( ).blockBoundingRect(block).topLeft() # Check if the position of the block is out side of the visible # area. if position.y() > page_bottom: break # We want the line number for the selected line to be bold. bold = False if block == current_block: bold = True font = painter.font() font.setBold(True) painter.setFont(font) if orig_number: line_count_str = str(line_count) + ' | ' + str(orig_number) else: line_count_str = str(line_count) # Draw the line number right justified at the y position of the # line. 3 is a magic padding number. drawText(x, y, text). painter.drawText( self.width() - font_metrics.width(line_count_str) - 3, round(position.y()) - contents_y + font_metrics.ascent(), line_count_str) # Remove the bold style if it was set previously. if bold: font = painter.font() font.setBold(False) painter.setFont(font) block = block.next() self.highest_line = line_count_str painter.end() QWidget.paintEvent(self, event) def __init__(self, *args): QFrame.__init__(self, *args) self.setFrameStyle(QFrame.StyledPanel | QFrame.Sunken) self.edit = QTextBrowser() self.edit.setFrameStyle(QFrame.NoFrame) self.number_bar = self.NumberBar() self.number_bar.setTextEdit(self.edit) hbox = QHBoxLayout(self) hbox.setSpacing(0) margins = QMargins(0, 0, 0, 0) hbox.setContentsMargins(margins) hbox.addWidget(self.number_bar) hbox.addWidget(self.edit) self.edit.installEventFilter(self) self.edit.viewport().installEventFilter(self) config = Config() style_str = config.array_config_str('log_line_number_style') self.setStyleSheet(style_str) def refresh_data(self, new_data): self.number_bar.reset_data() line_number_list = new_data['line_number'].tolist() self.number_bar.setLineNumberList(line_number_list) lines = new_data['log_line'].tolist() for line in lines: self.edit.append(line) def reset_data(self): self.number_bar.reset_data() def setOriginalLineNum(self, line_number): self.number_bar.setOriginalLineNum(line_number) def eventFilter(self, object, event): # Update the line numbers for all events on the text edit and the viewport. # This is easier than connecting all necessary singals. if object in (self.edit, self.edit.viewport()): self.number_bar.update() return False return QFrame.eventFilter(object, event) def getTextEdit(self): return self.edit
class CheckExternalLinks(Dialog): progress_made = pyqtSignal(object, object) def __init__(self, parent=None): Dialog.__init__(self, _('Check external links'), 'check-external-links-dialog', parent) self.progress_made.connect(self.on_progress_made, type=Qt.QueuedConnection) def show(self): if self.rb.isEnabled(): self.refresh() return Dialog.show(self) def refresh(self): self.stack.setCurrentIndex(0) self.rb.setEnabled(False) t = Thread(name='CheckLinksMaster', target=self.run) t.daemon = True t.start() def setup_ui(self): self.pb = pb = QProgressBar(self) pb.setTextVisible(True) pb.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) pb.setRange(0, 0) self.w = w = QWidget(self) self.w.l = l = QVBoxLayout(w) l.addStretch(), l.addWidget(pb) self.w.la = la = QLabel(_('Checking external links, please wait...')) la.setStyleSheet('QLabel { font-size: 20px; font-weight: bold }') l.addWidget(la, 0, Qt.AlignCenter), l.addStretch() self.l = l = QVBoxLayout(self) self.results = QTextBrowser(self) self.results.setOpenLinks(False) self.results.anchorClicked.connect(self.anchor_clicked) self.stack = s = QStackedWidget(self) s.addWidget(w), s.addWidget(self.results) l.addWidget(s) self.bh = h = QHBoxLayout() self.check_anchors = ca = QCheckBox(_('Check &anchors')) ca.setToolTip(_('Check HTML anchors in links (the part after the #).\n' ' This can be a little slow, since it requires downloading and parsing all the HTML pages.')) ca.setChecked(tprefs.get('check_external_link_anchors', True)) ca.stateChanged.connect(self.anchors_changed) h.addWidget(ca), h.addStretch(100), h.addWidget(self.bb) l.addLayout(h) self.bb.setStandardButtons(self.bb.Close) self.rb = b = self.bb.addButton(_('&Refresh'), self.bb.ActionRole) b.setIcon(QIcon(I('view-refresh.png'))) b.clicked.connect(self.refresh) def anchors_changed(self): tprefs.set('check_external_link_anchors', self.check_anchors.isChecked()) def sizeHint(self): ans = Dialog.sizeHint(self) ans.setHeight(600) ans.setWidth(max(ans.width(), 800)) return ans def run(self): from calibre.ebooks.oeb.polish.check.links import check_external_links self.tb = None self.errors = [] try: self.errors = check_external_links(current_container(), self.progress_made.emit, check_anchors=self.check_anchors.isChecked()) except Exception: import traceback self.tb = traceback.format_exc() self.progress_made.emit(None, None) def on_progress_made(self, curr, total): if curr is None: self.results.setText('') self.stack.setCurrentIndex(1) self.fixed_errors = set() self.rb.setEnabled(True) if self.tb is not None: return error_dialog(self, _('Checking failed'), _( 'There was an error while checking links, click "Show details" for more information'), det_msg=self.tb, show=True) if not self.errors: self.results.setText(_('No broken links found')) else: self.populate_results() else: self.pb.setMaximum(total), self.pb.setValue(curr) def populate_results(self, preserve_pos=False): num = len(self.errors) - len(self.fixed_errors) text = '<h3>%s</h3><ol>' % (ngettext( 'Found a broken link', 'Found {} broken links', num).format(num)) for i, (locations, err, url) in enumerate(self.errors): if i in self.fixed_errors: continue text += '<li><b>%s</b> \xa0<a href="err:%d">[%s]</a><br>%s<br><ul>' % (url, i, _('Fix this link'), err) for name, href, lnum, col in locations: text += '<li>{name} \xa0<a href="loc:{lnum},{name}">[{line}: {lnum}]</a></li>'.format( name=name, lnum=lnum, line=_('line number')) text += '</ul></li><hr>' self.results.setHtml(text) def anchor_clicked(self, qurl): url = qurl.toString() if url.startswith('err:'): errnum = int(url[4:]) err = self.errors[errnum] newurl, ok = QInputDialog.getText(self, _('Fix URL'), _('Enter the corrected URL:') + '\xa0'*40, text=err[2]) if not ok: return nmap = defaultdict(set) for name, href in {(l[0], l[1]) for l in err[0]}: nmap[name].add(href) for name, hrefs in nmap.iteritems(): raw = oraw = get_data(name) for href in hrefs: raw = raw.replace(href, newurl) if raw != oraw: set_data(name, raw) self.fixed_errors.add(errnum) self.populate_results() elif url.startswith('loc:'): lnum, name = url[4:].partition(',')[::2] lnum = int(lnum or 1) editor = get_boss().edit_file(name) if lnum and editor is not None and editor.has_line_numbers: editor.current_line = lnum
class CheckExternalLinks(Dialog): progress_made = pyqtSignal(object, object) def __init__(self, parent=None): Dialog.__init__(self, _('Check external links'), 'check-external-links-dialog', parent) self.progress_made.connect(self.on_progress_made, type=Qt.QueuedConnection) def show(self): if self.rb.isEnabled(): self.refresh() return Dialog.show(self) def refresh(self): self.stack.setCurrentIndex(0) self.rb.setEnabled(False) t = Thread(name='CheckLinksMaster', target=self.run) t.daemon = True t.start() def setup_ui(self): self.pb = pb = QProgressBar(self) pb.setTextVisible(True) pb.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) pb.setRange(0, 0) self.w = w = QWidget(self) self.w.l = l = QVBoxLayout(w) l.addStretch(), l.addWidget(pb) self.w.la = la = QLabel(_('Checking external links, please wait...')) la.setStyleSheet('QLabel { font-size: 20px; font-weight: bold }') l.addWidget(la, 0, Qt.AlignCenter), l.addStretch() self.l = l = QVBoxLayout(self) self.results = QTextBrowser(self) self.results.setOpenLinks(False) self.results.anchorClicked.connect(self.anchor_clicked) self.stack = s = QStackedWidget(self) s.addWidget(w), s.addWidget(self.results) l.addWidget(s) self.bh = h = QHBoxLayout() self.check_anchors = ca = QCheckBox(_('Check &anchors')) ca.setToolTip( _('Check HTML anchors in links (the part after the #).\n' ' This can be a little slow, since it requires downloading and parsing all the HTML pages.' )) ca.setChecked(tprefs.get('check_external_link_anchors', True)) ca.stateChanged.connect(self.anchors_changed) h.addWidget(ca), h.addStretch(100), h.addWidget(self.bb) l.addLayout(h) self.bb.setStandardButtons(self.bb.Close) self.rb = b = self.bb.addButton(_('&Refresh'), self.bb.ActionRole) b.setIcon(QIcon(I('view-refresh.png'))) b.clicked.connect(self.refresh) def anchors_changed(self): tprefs.set('check_external_link_anchors', self.check_anchors.isChecked()) def sizeHint(self): ans = Dialog.sizeHint(self) ans.setHeight(600) ans.setWidth(max(ans.width(), 800)) return ans def run(self): from calibre.ebooks.oeb.polish.check.links import check_external_links self.tb = None self.errors = [] try: self.errors = check_external_links( current_container(), self.progress_made.emit, check_anchors=self.check_anchors.isChecked()) except Exception: import traceback self.tb = traceback.format_exc() self.progress_made.emit(None, None) def on_progress_made(self, curr, total): if curr is None: self.results.setText('') self.stack.setCurrentIndex(1) self.fixed_errors = set() self.rb.setEnabled(True) if self.tb is not None: return error_dialog( self, _('Checking failed'), _('There was an error while checking links, click "Show details" for more information' ), det_msg=self.tb, show=True) if not self.errors: self.results.setText(_('No broken links found')) else: self.populate_results() else: self.pb.setMaximum(total), self.pb.setValue(curr) def populate_results(self, preserve_pos=False): num = len(self.errors) - len(self.fixed_errors) text = '<h3>%s</h3><ol>' % (ngettext( 'Found a broken link', 'Found {} broken links', num).format(num)) for i, (locations, err, url) in enumerate(self.errors): if i in self.fixed_errors: continue text += '<li><b>%s</b> \xa0<a href="err:%d">[%s]</a><br>%s<br><ul>' % ( url, i, _('Fix this link'), err) for name, href, lnum, col in locations: text += '<li>{name} \xa0<a href="loc:{lnum},{name}">[{line}: {lnum}]</a></li>'.format( name=name, lnum=lnum, line=_('line number')) text += '</ul></li><hr>' self.results.setHtml(text) def anchor_clicked(self, qurl): url = qurl.toString() if url.startswith('err:'): errnum = int(url[4:]) err = self.errors[errnum] newurl, ok = QInputDialog.getText(self, _('Fix URL'), _('Enter the corrected URL:') + '\xa0' * 40, text=err[2]) if not ok: return nmap = defaultdict(set) for name, href in {(l[0], l[1]) for l in err[0]}: nmap[name].add(href) for name, hrefs in nmap.iteritems(): raw = oraw = get_data(name) for href in hrefs: raw = raw.replace(href, newurl) if raw != oraw: set_data(name, raw) self.fixed_errors.add(errnum) self.populate_results() elif url.startswith('loc:'): lnum, name = url[4:].partition(',')[::2] lnum = int(lnum or 1) editor = get_boss().edit_file(name) if lnum and editor is not None and editor.has_line_numbers: editor.current_line = lnum
def __init__(self, gui, existing_names, editing=None): QDialog.__init__(self, gui) self.gui = gui self.existing_names = existing_names if editing: self.setWindowTitle(_('Edit virtual library')) else: self.setWindowTitle(_('Create virtual library')) self.setWindowIcon(QIcon(I('lt.png'))) gl = QGridLayout() self.setLayout(gl) self.la1 = la1 = QLabel(_('Virtual library &name:')) gl.addWidget(la1, 0, 0) self.vl_name = QComboBox() self.vl_name.setEditable(True) self.vl_name.lineEdit().setMaxLength(MAX_VIRTUAL_LIBRARY_NAME_LENGTH) la1.setBuddy(self.vl_name) gl.addWidget(self.vl_name, 0, 1) self.editing = editing self.saved_searches_label = sl = QTextBrowser(self) sl.viewport().setAutoFillBackground(False) gl.addWidget(sl, 2, 0, 1, 2) self.la2 = la2 = QLabel(_('&Search expression:')) gl.addWidget(la2, 1, 0) self.vl_text = QLineEdit() self.vl_text.textChanged.connect(self.search_text_changed) la2.setBuddy(self.vl_text) gl.addWidget(self.vl_text, 1, 1) self.vl_text.setText(_build_full_search_string(self.gui)) self.sl = sl = QLabel( '<p>' + _('Create a virtual library based on: ') + ('<a href="author.{0}">{0}</a>, ' '<a href="tag.{1}">{1}</a>, ' '<a href="publisher.{2}">{2}</a>, ' '<a href="series.{3}">{3}</a>, ' '<a href="search.{4}">{4}</a>.').format(_('Authors'), _( 'Tags'), _('Publishers'), _('Series'), _('Saved searches'))) sl.setWordWrap(True) sl.setTextInteractionFlags(Qt.LinksAccessibleByMouse) sl.linkActivated.connect(self.link_activated) gl.addWidget(sl, 3, 0, 1, 2) gl.setRowStretch(3, 10) self.hl = hl = QLabel( _(''' <h2>Virtual libraries</h2> <p>Using <i>virtual libraries</i> you can restrict calibre to only show you books that match a search. When a virtual library is in effect, calibre behaves as though the library contains only the matched books. The Tag browser display only the tags/authors/series/etc. that belong to the matched books and any searches you do will only search within the books in the virtual library. This is a good way to partition your large library into smaller and easier to work with subsets.</p> <p>For example you can use a Virtual library to only show you books with the Tag <i>"Unread"</i> or only books by <i>"My favorite author"</i> or only books in a particular series.</p> <p>More information and examples are available in the <a href="%s">User Manual</a>.</p> ''') % localize_user_manual_link( 'https://manual.calibre-ebook.com/virtual_libraries.html')) hl.setWordWrap(True) hl.setOpenExternalLinks(True) hl.setFrameStyle(hl.StyledPanel) gl.addWidget(hl, 0, 3, 4, 1) bb = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) bb.accepted.connect(self.accept) bb.rejected.connect(self.reject) gl.addWidget(bb, 4, 0, 1, 0) if editing: db = self.gui.current_db virt_libs = db.prefs.get('virtual_libraries', {}) for dex, vl in enumerate(sorted(virt_libs.keys(), key=sort_key)): self.vl_name.addItem(vl, virt_libs.get(vl, '')) if vl == editing: self.vl_name.setCurrentIndex(dex) self.original_index = dex self.original_search = virt_libs.get(editing, '') self.vl_text.setText(self.original_search) self.new_name = editing self.vl_name.currentIndexChanged[int].connect( self.name_index_changed) self.vl_name.lineEdit().textEdited.connect(self.name_text_edited) self.resize(self.sizeHint() + QSize(150, 25))