def __init__(self, parent): self.restrict_to_book_ids = frozenset() QWidget.__init__(self, parent) v = QVBoxLayout(self) v.setContentsMargins(0, 0, 0, 0) h = QHBoxLayout() h.setContentsMargins(0, 0, 0, 0) v.addLayout(h) self.rla = QLabel(_('Restrict to') + ': ') h.addWidget(self.rla) la = QLabel(_('Types:')) h.addWidget(la) self.types_box = tb = QComboBox(self) tb.la = la tb.currentIndexChanged.connect(self.restrictions_changed) connect_lambda(tb.currentIndexChanged, tb, lambda tb: gprefs.set('browse_annots_restrict_to_type', tb.currentData())) la.setBuddy(tb) tb.setToolTip(_('Show only annotations of the specified type')) h.addWidget(tb) la = QLabel(_('User:'******'browse_annots_restrict_to_user', ub.currentData())) la.setBuddy(ub) ub.setToolTip(_('Show only annotations created by the specified user')) h.addWidget(ub) h.addStretch(10) h = QHBoxLayout() self.restrict_to_books_cb = cb = QCheckBox('') self.update_book_restrictions_text() cb.setToolTip(_('Only show annotations from books that have been selected in the calibre library')) cb.setChecked(bool(gprefs.get('show_annots_from_selected_books_only', False))) cb.stateChanged.connect(self.show_only_selected_changed) h.addWidget(cb) v.addLayout(h)
def setupUi(self, *a): Ui_Form.setupUi(self, *a) v = self.page_margins_box.v = QVBoxLayout(self.page_margins_box) self.opt_pdf_use_document_margins = c = QCheckBox(_('Use page margins from the &document being converted')) v.addWidget(c) h = self.page_margins_box.h = QHBoxLayout() l = self.page_margins_box.l = QFormLayout() r = self.page_margins_box.r = QFormLayout() h.addLayout(l), h.addLayout(r) v.addLayout(h) def margin(which): w = QDoubleSpinBox(self) w.setRange(-100, 500), w.setSuffix(' pt'), w.setDecimals(1) setattr(self, 'opt_pdf_page_margin_' + which, w) return w l.addRow(_('&Left:'), margin('left')) l.addRow(_('&Right:'), margin('right')) r.addRow(_('&Top:'), margin('top')) r.addRow(_('&Bottom:'), margin('bottom')) self.opt_use_profile_size.toggled.connect(self.profile_size_toggled)
def setup_ui(self): self.l = l = QVBoxLayout(self) self.plist = pl = QListWidget(self) pl.setIconSize(QSize(48, 48)), pl.setSpacing(5) l.addWidget(pl) self.bb.clear(), self.bb.setStandardButtons( QDialogButtonBox.StandardButton.Close) self.rb = b = self.bb.addButton(_('&Remove'), QDialogButtonBox.ButtonRole.ActionRole) b.clicked.connect(self.remove), b.setIcon(QIcon(I('list_remove.png'))) self.cb = b = self.bb.addButton(_('Change &icon'), QDialogButtonBox.ButtonRole.ActionRole) b.clicked.connect(self.change_icon), b.setIcon( QIcon(I('icon_choose.png'))) self.cb = b = self.bb.addButton(_('Change &name'), QDialogButtonBox.ButtonRole.ActionRole) b.clicked.connect(self.change_name), b.setIcon(QIcon( I('modified.png'))) l.addWidget(self.bb) self.populate()
def __init__(self, gui, error): QDialog.__init__(self, gui) self.l = l = QVBoxLayout() self.setLayout(l) self.la = la = QLabel('<p>'+ _('You are trying to send books into the <b>%s</b> folder. This ' 'folder is currently ignored by calibre when scanning the ' 'device. You have to tell calibre you want this folder scanned ' 'in order to be able to send books to it. Click the ' '<b>Configure</b> button below to send books to it.')%error.folder) la.setWordWrap(True) la.setMinimumWidth(500) l.addWidget(la) self.bb = bb = QDialogButtonBox(QDialogButtonBox.StandardButton.Close) self.b = bb.addButton(_('Configure'), QDialogButtonBox.ButtonRole.AcceptRole) bb.accepted.connect(self.accept) bb.rejected.connect(self.reject) l.addWidget(bb) self.setWindowTitle(_('Cannot send to %s')%error.folder) self.setWindowIcon(QIcon(I('dialog_error.png'))) self.resize(self.sizeHint())
def change_builtin(self): d = QDialog(self) lw = QListWidget(d) for (trigger, syntaxes), snip in iteritems(builtin_snippets): snip = copy.deepcopy(snip) snip['trigger'], snip['syntaxes'] = trigger, syntaxes i = QListWidgetItem(self.snip_to_text(snip), lw) i.setData(Qt.ItemDataRole.UserRole, snip) d.l = l = QVBoxLayout(d) l.addWidget(QLabel(_('Choose the built-in snippet to modify:'))) l.addWidget(lw) lw.itemDoubleClicked.connect(d.accept) d.bb = bb = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel) l.addWidget(bb) bb.accepted.connect(d.accept), bb.rejected.connect(d.reject) if d.exec_() == QDialog.DialogCode.Accepted and lw.currentItem( ) is not None: self.stack.setCurrentIndex(1) self.edit_snip.apply_snip(lw.currentItem().data( Qt.ItemDataRole.UserRole), creating_snippet=True)
def setup_ui(self): from calibre.gui2.tweak_book.editor.text import TextEdit self.l = l = QVBoxLayout(self) self.bb.setStandardButtons(QDialogButtonBox.StandardButton.Close) self.la = la = QLabel(self.LABEL) l.addWidget(la) self.css = t = TextEdit(self) t.load_text('', self.SYNTAX) la.setBuddy(t) c = t.textCursor() c.movePosition(QTextCursor.MoveOperation.End) t.setTextCursor(c) self.h = h = QHBoxLayout() l.addLayout(h) h.addWidget(t) self.test_button = b = QPushButton(_('&Test'), self) b.clicked.connect(self.do_test) h.addWidget(b) self.result = la = TextEdit(self) la.setReadOnly(True) l.addWidget(la) l.addWidget(self.bb)
def __init__(self, parent=None): QWidget.__init__(self, parent) self.l = l = QVBoxLayout(self) self.h = h = QHBoxLayout() self.la = la = QLabel(self.MSG) la.setWordWrap(True) l.addWidget(la) l.addLayout(h) english_sentence = '{preamble} {match_type}' sentence = _('{preamble} {match_type}') if set(sentence.split()) != set(english_sentence.split()): sentence = english_sentence parts = sentence.split() for clause in parts: if clause == '{preamble}': self.preamble = w = QLabel(_('If the tag')) elif clause == '{match_type}': self.match_type = w = QComboBox(self) for action, m in MATCH_TYPE_MAP.items(): w.addItem(m.text, action) w.currentIndexChanged.connect(self.update_state) h.addWidget(w) if clause is not parts[-1]: h.addWidget(QLabel('\xa0')) h.addStretch(1) self.generic_query = gq = GenericEdit(self) self.css_query = cq = CSSEdit(self) self.xpath_query = xq = XPathEdit(self, object_name='html_transform_rules_xpath', show_msg=False) l.addWidget(gq), l.addWidget(cq), l.addWidget(xq) self.thenl = QLabel(_('Then:')) l.addWidget(self.thenl) self.actions = a = ActionsContainer(self) l.addWidget(a) self.add_button = b = QPushButton(QIcon(I('plus.png')), _('Add another action')) b.clicked.connect(self.actions.new_action) l.addWidget(b) self.update_state()
def setup_ui(self): from calibre.gui2.tweak_book.templates import DEFAULT_TEMPLATES from calibre.gui2.tweak_book.editor.text import TextEdit # Cannot use QFormLayout as it does not play nice with TextEdit on windows self.l = l = QVBoxLayout(self) self.syntaxes = s = QComboBox(self) s.addItems(sorted(DEFAULT_TEMPLATES)) s.setCurrentIndex(s.findText('html')) h = QHBoxLayout() l.addLayout(h) la = QLabel(_('Choose the &type of template to edit:')) la.setBuddy(s) h.addWidget(la), h.addWidget(s), h.addStretch(10) s.currentIndexChanged.connect(self.show_template) self.helpl = la = QLabel(_( 'The variables {0} and {1} will be replaced with the title and author of the book. {2}' ' is where the cursor will be positioned. If you want to include braces in your template,' ' for example for CSS rules, you have to escape them, like this: {3}').format(*['<code>%s</code>'%x for x in ['{TITLE}', '{AUTHOR}', '%CURSOR%', 'body {{ color: red }}']])) la.setWordWrap(True) l.addWidget(la) self.save_timer = t = QTimer(self) t.setSingleShot(True), t.setInterval(100) t.timeout.connect(self._save_syntax) self.editor = e = TextEdit(self) l.addWidget(e) e.textChanged.connect(self.save_syntax) self.show_template() self.bb.clear() self.bb.addButton(QDialogButtonBox.StandardButton.Close) self.rd = b = self.bb.addButton(QDialogButtonBox.StandardButton.RestoreDefaults) b.clicked.connect(self.restore_defaults) l.addWidget(self.bb)
class Tab2Config(DeviceConfigTab): # {{{ def __init__(self, parent, device): super().__init__(parent) self.l = QVBoxLayout(self) self.setLayout(self.l) self.metadata_options = MetadataGroupBox(self, device) self.l.addWidget(self.metadata_options) self.addDeviceWidget(self.metadata_options) self.device_list_options = DeviceListGroupBox(self, device) self.l.addWidget(self.device_list_options) self.addDeviceWidget(self.device_list_options) self.advanced_options = AdvancedGroupBox(self, device) self.l.addWidget(self.advanced_options) self.addDeviceWidget(self.advanced_options) self.l.addStretch() def validate(self): return self.metadata_options.validate()
def show_devtools(self): if not hasattr(self, '_devtools_page'): self._devtools_page = QWebEnginePage() self._devtools_view = QWebEngineView(self) self._devtools_view.setPage(self._devtools_page) self._page.setDevToolsPage(self._devtools_page) self._devtools_dialog = d = QDialog(self) d.setWindowTitle('Inspect Lookup page') v = QVBoxLayout(d) v.addWidget(self._devtools_view) d.bb = QDialogButtonBox(QDialogButtonBox.StandardButton.Close) d.bb.rejected.connect(d.reject) v.addWidget(d.bb) d.resize(QSize(800, 600)) d.setAttribute(Qt.WidgetAttribute.WA_DeleteOnClose, False) self._devtools_dialog.show() self._page.triggerAction(QWebEnginePage.WebAction.InspectElement)
def __init__(self, log, parent=None): QWidget.__init__(self, parent) self.log = log self.abort = Event() self.caches = {} self.l = l = QVBoxLayout(self) names = ['<b>'+p.name+'</b>' for p in metadata_plugins(['identify']) if p.is_configured()] self.top = QLabel('<p>'+_('calibre is downloading metadata from: ') + ', '.join(names)) self.top.setWordWrap(True) l.addWidget(self.top) self.splitter = s = QSplitter(self) s.setChildrenCollapsible(False) l.addWidget(s, 100) self.results_view = ResultsView(self) self.results_view.book_selected.connect(self.emit_book_selected) self.get_result = self.results_view.get_result s.addWidget(self.results_view) self.comments_view = Comments(self) s.addWidget(self.comments_view) s.setStretchFactor(0, 2) s.setStretchFactor(1, 1) self.results_view.show_details_signal.connect(self.comments_view.show_data) self.query = QLabel('download starting...') self.query.setWordWrap(True) l.addWidget(self.query) self.comments_view.show_wait() state = gprefs.get('metadata-download-identify-widget-splitter-state') if state is not None: s.restoreState(state)
def __init__(self, names, txt, parent=None): QDialog.__init__(self, parent) self.l = l = QVBoxLayout(self) self.setLayout(l) self.la = la = QLabel(_('Create a Virtual library based on %s') % txt) l.addWidget(la) self.filter = f = QLineEdit(self) f.setPlaceholderText(_('Filter {}').format(txt)) f.setClearButtonEnabled(True) l.addWidget(f) self.model = QStringListModel(sorted(names, key=sort_key)) self.pmodel = QSortFilterProxyModel(self) self.pmodel.setFilterCaseSensitivity( Qt.CaseSensitivity.CaseInsensitive) f.textChanged.connect(self.pmodel.setFilterFixedString) self.pmodel.setSourceModel(self.model) self._names = QListView(self) self._names.setModel(self.pmodel) self._names.setSelectionMode( QAbstractItemView.SelectionMode.MultiSelection) l.addWidget(self._names) self._or = QRadioButton(_('Match any of the selected %s') % txt) self._and = QRadioButton(_('Match all of the selected %s') % txt) self._or.setChecked(True) l.addWidget(self._or) l.addWidget(self._and) self.bb = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel) self.bb.accepted.connect(self.accept) self.bb.rejected.connect(self.reject) l.addWidget(self.bb) self.resize(self.sizeHint())
def genesis(self, gui): self.gui = gui r = self.register r('read_file_metadata', prefs) r('swap_author_names', prefs) r('add_formats_to_existing', prefs) r('check_for_dupes_on_ctl', prefs) r('preserve_date_on_ctl', gprefs) r('manual_add_auto_convert', gprefs) choices = [ (_('Ignore duplicate incoming formats'), 'ignore'), (_('Overwrite existing duplicate formats'), 'overwrite'), (_('Create new record for each duplicate format'), 'new record')] r('automerge', gprefs, choices=choices) r('new_book_tags', prefs, setting=CommaSeparatedList) r('mark_new_books', prefs) r('auto_add_path', gprefs, restart_required=True) r('auto_add_everything', gprefs, restart_required=True) r('auto_add_check_for_duplicates', gprefs) r('auto_add_auto_convert', gprefs) r('auto_convert_same_fmt', gprefs) self.filename_pattern = FilenamePattern(self) self.metadata_box.l = QVBoxLayout(self.metadata_box) self.metadata_box.layout().insertWidget(0, self.filename_pattern) self.filename_pattern.changed_signal.connect(self.changed_signal.emit) self.auto_add_browse_button.clicked.connect(self.choose_aa_path) for signal in ('Activated', 'Changed', 'DoubleClicked', 'Clicked'): signal = getattr(self.opt_blocked_auto_formats, 'item'+signal) signal.connect(self.blocked_auto_formats_changed) self.tag_map_rules = self.add_filter_rules = self.author_map_rules = None self.tag_map_rules_button.clicked.connect(self.change_tag_map_rules) self.author_map_rules_button.clicked.connect(self.change_author_map_rules) self.add_filter_rules_button.clicked.connect(self.change_add_filter_rules) self.tabWidget.setCurrentIndex(0) self.actions_tab.layout().setFieldGrowthPolicy(QFormLayout.FieldGrowthPolicy.AllNonFixedFieldsGrow)
def __init__(self, parent=None): super().__init__(parent) self.l = l = QVBoxLayout(self) self.h = h = QHBoxLayout() l.addLayout(h) english_sentence = '{action_type} {action_data}' sentence = _('{action_type} {action_data}') if set(sentence.split()) != set(english_sentence.split()): sentence = english_sentence parts = sentence.split() for clause in parts: if clause == '{action_data}': self.action_data = w = QLineEdit(self) w.setClearButtonEnabled(True) elif clause == '{action_type}': self.action_type = w = QComboBox(self) for action, ac in ACTION_MAP.items(): w.addItem(ac.short_text, action) w.currentIndexChanged.connect(self.update_state) h.addWidget(w) if clause is not parts[-1]: h.addWidget(QLabel('\xa0')) self.h2 = h = QHBoxLayout() l.addLayout(h) self.remove_button = b = QToolButton(self) b.setToolTip(_('Remove this action')), b.setIcon(QIcon(I('minus.png'))) b.clicked.connect(self.request_remove) h.addWidget(b) self.action_desc = la = QLabel('') la.setWordWrap(True) la.setTextFormat(Qt.TextFormat.RichText) h.addWidget(la) self.sep = sep = QFrame(self) sep.setFrameShape(QFrame.Shape.HLine) l.addWidget(sep) self.update_state()
def genesis(self, gui): self.gui = gui self.l = l = QVBoxLayout() self.setLayout(l) self.confirms_reset = False self.la = la = QLabel( _('The list of devices that you have asked calibre to ignore. ' 'Uncheck a device to have calibre stop ignoring it.')) la.setWordWrap(True) l.addWidget(la) self.devices = f = QListWidget(self) l.addWidget(f) f.itemChanged.connect(self.changed_signal) f.itemDoubleClicked.connect(self.toggle_item) self.la2 = la = QLabel( _('The list of device plugins you have disabled. Uncheck an entry ' 'to enable the plugin. calibre cannot detect devices that are ' 'managed by disabled plugins.')) la.setWordWrap(True) l.addWidget(la) self.device_plugins = f = QListWidget(f) l.addWidget(f) f.itemChanged.connect(self.changed_signal) f.itemDoubleClicked.connect(self.toggle_item) self.reset_confirmations_button = b = QPushButton( _('Reset allowed devices')) b.setToolTip( textwrap.fill( _('This will erase the list of devices that calibre knows about' ' causing it to ask you for permission to manage them again,' ' the next time they connect'))) b.clicked.connect(self.reset_confirmations) l.addWidget(b)
def __init__(self, title=None, parent=None): QDialog.__init__(self, parent) self.last_reject_at = self.last_accept_at = -1000 t = title or current_container().mi.title self.book_title = t self.setWindowTitle(_('Edit the ToC in %s') % t) self.setWindowIcon(QIcon(I('toc.png'))) l = self.l = QVBoxLayout() self.setLayout(l) self.stacks = s = QStackedWidget(self) l.addWidget(s) self.toc_view = TOCView(self, tprefs) self.toc_view.add_new_item.connect(self.add_new_item) s.addWidget(self.toc_view) self.item_edit = ItemEdit(self, tprefs) s.addWidget(self.item_edit) bb = self.bb = QDialogButtonBox( QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel) l.addWidget(bb) bb.accepted.connect(self.accept) bb.rejected.connect(self.reject) self.undo_button = b = bb.addButton( _('&Undo'), QDialogButtonBox.ButtonRole.ActionRole) b.setToolTip(_('Undo the last action, if any')) b.setIcon(QIcon(I('edit-undo.png'))) b.clicked.connect(self.toc_view.undo) self.read_toc() self.resize(950, 630) geom = tprefs.get('toc_editor_window_geom', None) if geom is not None: QApplication.instance().safe_restore_geometry(self, bytes(geom))
def link_stylesheets(self, names): s = self.categories['styles'] sheets = [str(s.child(i).data(0, NAME_ROLE) or '') for i in range(s.childCount())] if not sheets: return error_dialog(self, _('No stylesheets'), _( 'This book currently has no stylesheets. You must first create a stylesheet' ' before linking it.'), show=True) d = QDialog(self) d.l = l = QVBoxLayout(d) d.setLayout(l) d.setWindowTitle(_('Choose stylesheets')) d.la = la = QLabel(_('Choose the stylesheets to link. Drag and drop to re-arrange')) la.setWordWrap(True) l.addWidget(la) d.s = s = QListWidget(d) l.addWidget(s) s.setDragEnabled(True) s.setDropIndicatorShown(True) s.setDragDropMode(QAbstractItemView.DragDropMode.InternalMove) s.setAutoScroll(True) s.setDefaultDropAction(Qt.DropAction.MoveAction) for name in sheets: i = QListWidgetItem(name, s) flags = Qt.ItemFlag.ItemIsEnabled | Qt.ItemFlag.ItemIsUserCheckable | Qt.ItemFlag.ItemIsDragEnabled | Qt.ItemFlag.ItemIsSelectable i.setFlags(flags) i.setCheckState(Qt.CheckState.Checked) d.r = r = QCheckBox(_('Remove existing links to stylesheets')) r.setChecked(tprefs['remove_existing_links_when_linking_sheets']) l.addWidget(r) d.bb = bb = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel) bb.accepted.connect(d.accept), bb.rejected.connect(d.reject) l.addWidget(bb) if d.exec() == QDialog.DialogCode.Accepted: tprefs['remove_existing_links_when_linking_sheets'] = r.isChecked() sheets = [str(s.item(il).text()) for il in range(s.count()) if s.item(il).checkState() == Qt.CheckState.Checked] if sheets: self.link_stylesheets_requested.emit(names, sheets, r.isChecked())
def setup_ui(self): self.use_stemmer = us = QCheckBox(_('Match on related English words')) us.setChecked(gprefs['browse_annots_use_stemmer']) us.setToolTip('<p>' + _( 'With this option searching for words will also match on any related English words. For' ' example: <i>correction</i> matches <i>correcting</i> and <i>corrected</i> as well' )) us.stateChanged.connect(lambda state: gprefs.set( 'browse_annots_use_stemmer', state != Qt.CheckState.Unchecked)) l = QVBoxLayout(self) self.splitter = s = QSplitter(self) l.addWidget(s) s.setChildrenCollapsible(False) self.browse_panel = bp = BrowsePanel(self) bp.open_annotation.connect(self.do_open_annotation) bp.show_book.connect(self.show_book) bp.delete_requested.connect(self.delete_selected) bp.export_requested.connect(self.export_selected) bp.edit_annotation.connect(self.edit_annotation) s.addWidget(bp) self.details_panel = dp = DetailsPanel(self) s.addWidget(dp) dp.open_annotation.connect(self.do_open_annotation) dp.show_book.connect(self.show_book) dp.delete_annotation.connect(self.delete_annotation) dp.edit_annotation.connect(self.edit_annotation) bp.current_result_changed.connect(dp.show_result) h = QHBoxLayout() l.addLayout(h) h.addWidget(us), h.addStretch(10), h.addWidget(self.bb) self.delete_button = b = self.bb.addButton( _('Delete all selected'), QDialogButtonBox.ButtonRole.ActionRole) b.setToolTip(_('Delete the selected annotations')) b.setIcon(QIcon(I('trash.png'))) b.clicked.connect(self.delete_selected) self.export_button = b = self.bb.addButton( _('Export all selected'), QDialogButtonBox.ButtonRole.ActionRole) b.setToolTip(_('Export the selected annotations')) b.setIcon(QIcon(I('save.png'))) b.clicked.connect(self.export_selected)
def setup_ui(self): from calibre.gui2.ui import get_gui db = get_gui().current_db self.l = l = QVBoxLayout(self) b = self.bb.addButton(_('&Add search'), QDialogButtonBox.ButtonRole.ActionRole) b.setIcon(QIcon(I('plus.png'))) b.clicked.connect(self.add_search) b = self.bb.addButton(_('&Remove search'), QDialogButtonBox.ButtonRole.ActionRole) b.setIcon(QIcon(I('minus.png'))) b.clicked.connect(self.del_search) b = self.bb.addButton(_('&Edit search'), QDialogButtonBox.ButtonRole.ActionRole) b.setIcon(QIcon(I('modified.png'))) b.clicked.connect(self.edit_search) self.slist = QListWidget(self) self.slist.setStyleSheet('QListView::item { padding: 3px }') self.slist.activated.connect(self.edit_search) self.slist.setAlternatingRowColors(True) self.searches = {name: db.saved_search_lookup(name) for name in db.saved_search_names()} self.populate_search_list() if self.initial_search is not None and self.initial_search in self.searches: self.select_search(self.initial_search) elif self.searches: self.slist.setCurrentRow(0) self.slist.currentItemChanged.connect(self.current_index_changed) l.addWidget(self.slist) self.desc = la = QLabel('\xa0') la.setWordWrap(True) l.addWidget(la) l.addWidget(self.bb) self.current_index_changed(self.slist.currentItem()) self.setMinimumHeight(500) self.setMinimumWidth(600)
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.StandardButton.Close) d.show_changes = False if changed: b = d.b = d.bb.addButton(_('See what &changed'), QDialogButtonBox.ButtonRole.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'), QDialogButtonBox.ButtonRole.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(QDialogButtonBox.StandardButton.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)
class Category(QWidget): # {{{ plugin_activated = pyqtSignal(object) def __init__(self, name, plugins, gui_name, parent=None): QWidget.__init__(self, parent) self._layout = QVBoxLayout() self.setLayout(self._layout) self.label = QLabel(gui_name) self.sep = QFrame(self) self.bf = QFont() self.bf.setBold(True) self.label.setFont(self.bf) self.sep.setFrameShape(QFrame.Shape.HLine) self._layout.addWidget(self.label) self._layout.addWidget(self.sep) self.plugins = plugins self.bar = QToolBar(self) self.bar.setStyleSheet('QToolBar { border: none; background: none }') lh = QApplication.instance().line_height self.bar.setIconSize(QSize(2 * lh, 2 * lh)) self.bar.setMovable(False) self.bar.setFloatable(False) self.bar.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonTextUnderIcon) self._layout.addWidget(self.bar) self.actions = [] for p in plugins: target = partial(self.triggered, p) ac = self.bar.addAction(QIcon(p.icon), p.gui_name.replace('&', '&&'), target) ac.setToolTip(textwrap.fill(p.description)) ac.setWhatsThis(textwrap.fill(p.description)) ac.setStatusTip(p.description) self.actions.append(ac) w = self.bar.widgetForAction(ac) w.setCursor(Qt.CursorShape.PointingHandCursor) if hasattr(w, 'setAutoRaise'): w.setAutoRaise(True) w.setMinimumWidth(100) def triggered(self, plugin, *args): self.plugin_activated.emit(plugin)
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, devs, blacklist): QWidget.__init__(self) self.l = l = QVBoxLayout() self.setLayout(l) self.la = la = QLabel('<p>' + _( '''Select the devices to be <b>ignored</b>. calibre <b>will not</b> connect to devices with a checkmark next to their names.''')) la.setWordWrap(True) l.addWidget(la) self.f = f = QListWidget(self) l.addWidget(f) devs = [(snum, (x[0], parse_date(x[1]))) for snum, x in iteritems(devs)] for dev, x in sorted(devs, key=lambda x: x[1][1], reverse=True): name = x[0] name = '%s [%s]' % (name, dev) item = QListWidgetItem(name, f) item.setData(Qt.ItemDataRole.UserRole, dev) item.setFlags(Qt.ItemFlag.ItemIsEnabled | Qt.ItemFlag.ItemIsUserCheckable | Qt.ItemFlag.ItemIsSelectable) item.setCheckState(Qt.CheckState.Checked if dev in blacklist else Qt.CheckState.Unchecked)
def setup_ui(self): self.l = l = QVBoxLayout(self) self.edit_widget = w = self.RulesClass(self) l.addWidget(w) ebw = self.extra_bottom_widget() if ebw is None: l.addWidget(self.bb) else: self.h = h = QHBoxLayout() l.addLayout(h) h.addWidget(ebw), h.addStretch(10), h.addWidget(self.bb) self.save_button = b = self.bb.addButton( _('&Save'), QDialogButtonBox.ButtonRole.ActionRole) b.setToolTip(_('Save this ruleset for later re-use')) b.clicked.connect(self.save_ruleset) self.load_button = b = self.bb.addButton( _('&Load'), QDialogButtonBox.ButtonRole.ActionRole) b.setToolTip(_('Load a previously saved ruleset')) self.load_menu = QMenu(self) b.setMenu(self.load_menu) self.build_load_menu() self.test_button = b = self.bb.addButton( _('&Test rules'), QDialogButtonBox.ButtonRole.ActionRole) b.clicked.connect(self.test_rules)
def setup_ui(self): self.l = l = QVBoxLayout(self) self.stack = s = QStackedWidget(self) l.addWidget(s) self.recipe_list = rl = RecipeList(self, self.recipe_model) rl.edit_recipe.connect(self.edit_recipe) s.addWidget(rl) self.basic_recipe = br = BasicRecipe(self) s.addWidget(br) self.advanced_recipe = ar = AdvancedRecipe(self) s.addWidget(ar) l.addWidget(self.bb) self.list_actions = [] la = lambda *args: self.list_actions.append(args) la('plus.png', _('&New recipe'), _('Create a new recipe from scratch'), self.add_recipe) la('news.png', _('Customize &builtin recipe'), _('Customize a builtin news download source'), self.customize_recipe) la('document_open.png', _('Load recipe from &file'), _('Load a recipe from a file'), self.load_recipe) la('mimetypes/dir.png', _('&Show recipe files'), _('Show the folder containing all recipe files'), self.show_recipe_files) la( 'mimetypes/opml.png', _('Import &OPML'), _("Import a collection of RSS feeds in OPML format\n" "Many RSS readers can export their subscribed RSS feeds\n" "in OPML format"), self.import_opml) s.currentChanged.connect(self.update_button_box) self.update_button_box()
class PluginTweaks(QDialog): # {{{ def __init__(self, raw, parent=None): QDialog.__init__(self, parent) self.setWindowTitle(_('Plugin tweaks')) self.edit = QPlainTextEdit(self) self.highlighter = PythonHighlighter(self.edit.document()) self.l = QVBoxLayout() self.setLayout(self.l) self.msg = QLabel( _('Add/edit tweaks for any custom plugins you have installed. ' 'Documentation for these tweaks should be available ' 'on the website from where you downloaded the plugins.')) self.msg.setWordWrap(True) self.l.addWidget(self.msg) self.l.addWidget(self.edit) self.edit.setPlainText(raw) self.bb = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok|QDialogButtonBox.StandardButton.Cancel, Qt.Orientation.Horizontal, self) self.bb.accepted.connect(self.accept) self.bb.rejected.connect(self.reject) self.l.addWidget(self.bb) self.resize(550, 300)
def show_config_widget(category, name, gui=None, show_restart_msg=False, parent=None, never_shutdown=False): ''' Show the preferences plugin identified by category and name :param gui: gui instance, if None a hidden gui is created :param show_restart_msg: If True and the preferences plugin indicates a restart is required, show a message box telling the user to restart :param parent: The parent of the displayed dialog :return: True iff a restart is required for the changes made by the user to take effect ''' from calibre.gui2 import gprefs pl = get_plugin(category, name) d = ConfigDialog(parent) d.resize(750, 550) conf_name = 'config_widget_dialog_geometry_%s_%s'%(category, name) geom = gprefs.get(conf_name, None) d.setWindowTitle(_('Configure ') + pl.gui_name) d.setWindowIcon(QIcon(I('config.png'))) bb = QDialogButtonBox(d) bb.setStandardButtons(QDialogButtonBox.StandardButton.Apply|QDialogButtonBox.StandardButton.Cancel|QDialogButtonBox.StandardButton.RestoreDefaults) bb.accepted.connect(d.accept) bb.rejected.connect(d.reject) w = pl.create_widget(d) d.set_widget(w) bb.button(QDialogButtonBox.StandardButton.RestoreDefaults).clicked.connect(w.restore_defaults) bb.button(QDialogButtonBox.StandardButton.RestoreDefaults).setEnabled(w.supports_restoring_to_defaults) bb.button(QDialogButtonBox.StandardButton.Apply).setEnabled(False) bb.button(QDialogButtonBox.StandardButton.Apply).clicked.connect(d.accept) def onchange(): b = bb.button(QDialogButtonBox.StandardButton.Apply) b.setEnabled(True) b.setDefault(True) b.setAutoDefault(True) w.changed_signal.connect(onchange) bb.button(QDialogButtonBox.StandardButton.Cancel).setFocus(True) l = QVBoxLayout() d.setLayout(l) l.addWidget(w) l.addWidget(bb) mygui = gui is None if gui is None: gui = init_gui() mygui = True w.genesis(gui) w.initialize() if geom is not None: QApplication.instance().safe_restore_geometry(d, geom) d.exec_() geom = bytearray(d.saveGeometry()) gprefs[conf_name] = geom rr = getattr(d, 'restart_required', False) if show_restart_msg and rr: from calibre.gui2 import warning_dialog warning_dialog(gui, 'Restart required', 'Restart required', show=True) if mygui and not never_shutdown: gui.shutdown() return rr
def __init__(self, parent): QFrame.__init__(self, parent) self.setFrameStyle(QFrame.Shape.NoFrame if gprefs['tag_browser_old_look'] else QFrame.Shape.StyledPanel) self._parent = parent self._layout = QVBoxLayout(self) self._layout.setContentsMargins(0,0,0,0) # Set up the find box & button self.tb_bar = tbb = TagBrowserBar(self) tbb.clear_find.connect(self.reset_find) self.alter_tb, self.item_search, self.search_button = tbb.alter_tb, tbb.item_search, tbb.search_button self.toggle_search_button = tbb.toggle_search_button self._layout.addWidget(tbb) self.current_find_position = None self.search_button.clicked.connect(self.find) self.item_search.lineEdit().textEdited.connect(self.find_text_changed) self.item_search.activated[str].connect(self.do_find) # The tags view parent.tags_view = TagsView(parent) self.tags_view = parent.tags_view self._layout.insertWidget(0, parent.tags_view) # Now the floating 'not found' box l = QLabel(self.tags_view) self.not_found_label = l l.setFrameStyle(QFrame.Shape.StyledPanel) l.setAutoFillBackground(True) l.setText('<p><b>'+_('No more matches.</b><p> Click Find again to go to first match')) l.setAlignment(Qt.AlignmentFlag.AlignVCenter) l.setWordWrap(True) l.resize(l.sizeHint()) l.move(10,20) l.setVisible(False) self.not_found_label_timer = QTimer() self.not_found_label_timer.setSingleShot(True) self.not_found_label_timer.timeout.connect(self.not_found_label_timer_event, type=Qt.ConnectionType.QueuedConnection) self.collapse_all_action = ac = QAction(parent) parent.addAction(ac) parent.keyboard.register_shortcut('tag browser collapse all', _('Collapse all'), default_keys=(), action=ac, group=_('Tag browser')) connect_lambda(ac.triggered, self, lambda self: self.tags_view.collapseAll()) # The Configure Tag Browser button l = self.alter_tb ac = QAction(parent) parent.addAction(ac) parent.keyboard.register_shortcut('tag browser alter', _('Configure Tag browser'), default_keys=(), action=ac, group=_('Tag browser')) ac.triggered.connect(l.showMenu) l.m.aboutToShow.connect(self.about_to_show_configure_menu) l.m.show_counts_action = ac = l.m.addAction('counts') ac.triggered.connect(self.toggle_counts) l.m.show_avg_rating_action = ac = l.m.addAction('avg rating') ac.triggered.connect(self.toggle_avg_rating) sb = l.m.addAction(_('Sort by')) sb.m = l.sort_menu = QMenu(l.m) sb.setMenu(sb.m) sb.bg = QActionGroup(sb) # Must be in the same order as db2.CATEGORY_SORTS for i, x in enumerate((_('Name'), _('Number of books'), _('Average rating'))): a = sb.m.addAction(x) sb.bg.addAction(a) a.setCheckable(True) if i == 0: a.setChecked(True) sb.setToolTip( _('Set the sort order for entries in the Tag browser')) sb.setStatusTip(sb.toolTip()) ma = l.m.addAction(_('Search type when selecting multiple items')) ma.m = l.match_menu = QMenu(l.m) ma.setMenu(ma.m) ma.ag = QActionGroup(ma) # Must be in the same order as db2.MATCH_TYPE for i, x in enumerate((_('Match any of the items'), _('Match all of the items'))): a = ma.m.addAction(x) ma.ag.addAction(a) a.setCheckable(True) if i == 0: a.setChecked(True) ma.setToolTip( _('When selecting multiple entries in the Tag browser ' 'match any or all of them')) ma.setStatusTip(ma.toolTip()) mt = l.m.addAction(_('Manage authors, tags, etc.')) mt.setToolTip(_('All of these category_managers are available by right-clicking ' 'on items in the Tag browser above')) mt.m = l.manage_menu = QMenu(l.m) mt.setMenu(mt.m) ac = QAction(parent) parent.addAction(ac) parent.keyboard.register_shortcut('tag browser toggle item', _("'Click' found item"), default_keys=(), action=ac, group=_('Tag browser')) ac.triggered.connect(self.toggle_item) ac = QAction(parent) parent.addAction(ac) parent.keyboard.register_shortcut('tag browser set focus', _("Give the Tag browser keyboard focus"), default_keys=(), action=ac, group=_('Tag browser')) ac.triggered.connect(self.give_tb_focus)
def __init__(self, parent=None): QWidget.__init__(self, parent) self.setVisible(False) self.l = QVBoxLayout(self) self.items = {}
def __init__(self, gui, initial_plugin=None, close_after_initial=False): QDialog.__init__(self, gui) self.gui = gui self.must_restart = False self.do_restart = False self.committed = False self.close_after_initial = close_after_initial self.resize(930, 720) nh, nw = min_available_height() - 25, available_width() - 10 if nh < 0: nh = 800 if nw < 0: nw = 600 nh = min(self.height(), nh) nw = min(self.width(), nw) self.resize(nw, nh) geom = gprefs.get('preferences dialog geometry', None) if geom is not None: QApplication.instance().safe_restore_geometry(self, geom) # Center if islinux: self.move(gui.rect().center() - self.rect().center()) self.setWindowModality(Qt.WindowModality.ApplicationModal) self.setWindowTitle(__appname__ + ' — ' + _('Preferences')) self.setWindowIcon(QIcon(I('config.png'))) self.l = l = QVBoxLayout(self) self.stack = QStackedWidget(self) self.bb = QDialogButtonBox( QDialogButtonBox.StandardButton.Close | QDialogButtonBox.StandardButton.Apply | QDialogButtonBox.StandardButton.Cancel | QDialogButtonBox.StandardButton.RestoreDefaults) self.bb.button(QDialogButtonBox.StandardButton.Apply).clicked.connect( self.accept) self.bb.button( QDialogButtonBox.StandardButton.RestoreDefaults).setIcon( QIcon(I('clear_left.png'))) self.bb.button( QDialogButtonBox.StandardButton.RestoreDefaults).clicked.connect( self.restore_defaults) self.wizard_button = self.bb.addButton( _('Run Welcome &wizard'), QDialogButtonBox.ButtonRole.ActionRole) self.wizard_button.setIcon(QIcon(I('wizard.png'))) self.wizard_button.clicked.connect( self.run_wizard, type=Qt.ConnectionType.QueuedConnection) self.wizard_button.setAutoDefault(False) self.bb.rejected.connect(self.reject) self.browser = Browser(self) self.browser.show_plugin.connect(self.show_plugin) self.stack.addWidget(self.browser) self.scroll_area = QScrollArea(self) self.stack.addWidget(self.scroll_area) self.scroll_area.setWidgetResizable(True) self.setContextMenuPolicy(Qt.ContextMenuPolicy.NoContextMenu) self.title_bar = TitleBar(self) for ac, tt in [(QDialogButtonBox.StandardButton.Apply, _('Save changes')), (QDialogButtonBox.StandardButton.Cancel, _('Cancel and return to overview'))]: self.bb.button(ac).setToolTip(tt) l.addWidget(self.title_bar), l.addWidget(self.stack), l.addWidget( self.bb) if initial_plugin is not None: category, name = initial_plugin[:2] plugin = get_plugin(category, name) if plugin is not None: self.show_plugin(plugin) if len(initial_plugin) > 2: w = self.findChild(QWidget, initial_plugin[2]) if w is not None: for c in self.showing_widget.children(): if isinstance(c, QTabWidget): idx = c.indexOf(w) if idx > -1: c.setCurrentIndex(idx) break else: self.hide_plugin()