class BlockingBusy(QDialog): def __init__(self, msg, parent=None, window_title=_('Working')): QDialog.__init__(self, parent) self._layout = QVBoxLayout() self.setLayout(self._layout) self.msg = QLabel(msg) # self.msg.setWordWrap(True) self.font = QFont() self.font.setPointSize(self.font.pointSize() + 8) self.msg.setFont(self.font) self.pi = ProgressIndicator(self) self.pi.setDisplaySize(QSize(100, 100)) self._layout.addWidget(self.pi, 0, Qt.AlignmentFlag.AlignHCenter) self._layout.addSpacing(15) self._layout.addWidget(self.msg, 0, Qt.AlignmentFlag.AlignHCenter) self.start() self.setWindowTitle(window_title) self.resize(self.sizeHint()) def start(self): self.pi.startAnimation() def stop(self): self.pi.stopAnimation() def accept(self): self.stop() return QDialog.accept(self) def reject(self): pass # Cannot cancel this dialog
def __init__(self, parent=None): self.loaded_ruleset = None QWidget.__init__(self, parent) self.PREFS_OBJECT = JSONConfig('style-transform-rules') l = QVBoxLayout(self) self.rules_widget = w = Rules(self) w.changed.connect(self.changed.emit) l.addWidget(w) self.h = h = QHBoxLayout() l.addLayout(h) self.export_button = b = QPushButton(_('E&xport'), self) b.setToolTip(_('Export these rules to a file')) b.clicked.connect(self.export_rules) h.addWidget(b) self.import_button = b = QPushButton(_('&Import'), self) b.setToolTip(_('Import previously exported rules')) b.clicked.connect(self.import_rules) h.addWidget(b) self.test_button = b = QPushButton(_('&Test rules'), self) b.clicked.connect(self.test_rules) h.addWidget(b) h.addStretch(10) self.save_button = b = QPushButton(_('&Save'), self) b.setToolTip(_('Save this ruleset for later re-use')) b.clicked.connect(self.save_ruleset) h.addWidget(b) self.export_button = b = QPushButton(_('&Load'), self) self.load_menu = QMenu(self) b.setMenu(self.load_menu) b.setToolTip(_('Load a previously saved ruleset')) b.clicked.connect(self.load_ruleset) h.addWidget(b) self.build_load_menu()
def develop(): from qt.core import QPainter, QPalette from calibre.gui2 import Application from calibre_extensions.progress_indicator import SpinAnimator class Widget(QWidget): def __init__(self): QWidget.__init__(self) self.a = SpinAnimator(self) self.a.updated.connect(self.update) def paintEvent(self, ev): p = QPainter(self) pal = self.palette() self.a.draw(p, self.rect(), pal.color(QPalette.ColorRole.WindowText)) p.end() app = Application([]) d = QDialog() d.resize(64, 64) l = QVBoxLayout(d) w = Widget() l.addWidget(w) w.a.start() d.exec() del d del app
def __init__(self, parent): QWidget.__init__(self, parent) l = QVBoxLayout(parent) l.addWidget(self) l.setContentsMargins(0, 0, 0, 0) l = QFormLayout(self) l.setContentsMargins(0, 0, 0, 0) l.setFieldGrowthPolicy(QFormLayout.FieldGrowthPolicy.AllNonFixedFieldsGrow) self.choices = c = QComboBox() c.setMinimumContentsLength(30) for text, data in [ (_('Search for the author on Goodreads'), 'search-goodreads'), (_('Search for the author on Amazon'), 'search-amzn'), (_('Search for the author in your calibre library'), 'search-calibre'), (_('Search for the author on Wikipedia'), 'search-wikipedia'), (_('Search for the author on Google Books'), 'search-google'), (_('Search for the book on Goodreads'), 'search-goodreads-book'), (_('Search for the book on Amazon'), 'search-amzn-book'), (_('Search for the book on Google Books'), 'search-google-book'), (_('Use a custom search URL'), 'url'), ]: c.addItem(text, data) l.addRow(_('Clicking on &author names should:'), c) self.custom_url = u = QLineEdit(self) u.setToolTip(_( 'Enter the URL to search. It should contain the string {0}' '\nwhich will be replaced by the author name. For example,' '\n{1}').format('{author}', 'https://en.wikipedia.org/w/index.php?search={author}')) u.textChanged.connect(self.changed_signal) u.setPlaceholderText(_('Enter the URL')) c.currentIndexChanged.connect(self.current_changed) l.addRow(u) self.current_changed() c.currentIndexChanged.connect(self.changed_signal)
class DownloadProgress(QWidget): def __init__(self, parent=None): QWidget.__init__(self, parent) self.setVisible(False) self.l = QVBoxLayout(self) self.items = {} def add_item(self, download_id, filename): self.setVisible(True) item = DownloadItem(download_id, filename, self) self.l.addWidget(item) self.items[download_id] = item def update_item(self, download_id, done, total): item = self.items.get(download_id) if item is not None: item(done, total) def remove_item(self, download_id): item = self.items.pop(download_id, None) if item is not None: self.l.removeWidget(item) item.setVisible(False) item.setParent(None) item.deleteLater() if not self.items: self.setVisible(False)
def __init__(self, parent): QWidget.__init__(self, parent) self.current_result = None l = QVBoxLayout(self) self.text_browser = tb = Details(self) tb.anchorClicked.connect(self.link_clicked) l.addWidget(tb) self.show_result(None)
def setup_ui(self): self.use_stemmer = us = QCheckBox(_('&Match on related words')) us.setChecked(gprefs['browse_annots_use_stemmer']) us.setToolTip('<p>' + _( 'With this option searching for words will also match on any related words (supported in several languages). For' ' example, in the English language: <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) self.refresh_button = b = RightClickButton(self.bb) self.bb.addButton(b, QDialogButtonBox.ButtonRole.ActionRole) b.setText(_('&Refresh')) b.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonTextBesideIcon) self.refresh_menu = m = QMenu(self) m.addAction(_('Rebuild search index')).triggered.connect(self.rebuild) b.setMenu(m) b.setToolTip( _('Refresh annotations in case they have been changed since this window was opened' )) b.setIcon(QIcon(I('restart.png'))) b.setPopupMode(QToolButton.ToolButtonPopupMode.DelayedPopup) b.clicked.connect(self.refresh)
def setup_ui(self): l = QVBoxLayout(self) self.qte = qte = QTextEdit(self) qte.setMinimumHeight(400) qte.setMinimumWidth(600) if self.initial_notes: qte.setPlainText(self.initial_notes) l.addWidget(qte) l.addWidget(self.bb)
def setup_ui(self): self.notes_edit = QPlainTextEdit(self) if self.initial_notes: self.notes_edit.setPlainText(self.initial_notes) self.notes_edit.setMinimumWidth(400) self.notes_edit.setMinimumHeight(300) l = QVBoxLayout(self) l.addWidget(self.notes_edit) l.addWidget(self.bb)
class DebugDevice(QDialog): def __init__(self, gui, parent=None): QDialog.__init__(self, parent) self.gui = gui self._layout = QVBoxLayout(self) self.setLayout(self._layout) self.log = QPlainTextEdit(self) self._layout.addWidget(self.log) self.log.setPlainText( _('Getting debug information, please wait') + '...') self.copy = QPushButton(_('Copy to &clipboard')) self.copy.setDefault(True) self.setWindowTitle(_('Debug device detection')) self.setWindowIcon(QIcon(I('debug.png'))) self.copy.clicked.connect(self.copy_to_clipboard) self.ok = QPushButton('&OK') self.ok.setAutoDefault(False) self.ok.clicked.connect(self.accept) self.bbox = QDialogButtonBox(self) self.bbox.addButton(self.copy, QDialogButtonBox.ButtonRole.ActionRole) self.bbox.addButton(self.ok, QDialogButtonBox.ButtonRole.AcceptRole) self._layout.addWidget(self.bbox) self.resize(750, 500) self.bbox.setEnabled(False) QTimer.singleShot(1000, self.debug) def debug(self): if self.gui.device_manager.is_device_connected: error_dialog( self, _('Device already detected'), _('A device (%s) is already detected by calibre.' ' If you wish to debug the detection of another device' ', first disconnect this device.') % self.gui.device_manager.connected_device.get_gui_name(), show=True) self.bbox.setEnabled(True) return self.gui.debug_detection(self) def __call__(self, job): if not self.isVisible(): return self.bbox.setEnabled(True) if job.failed: return error_dialog( self, _('Debugging failed'), _('Running debug device detection failed. Click Show ' 'Details for more information.'), det_msg=job.details, show=True) self.log.setPlainText(job.result) def copy_to_clipboard(self): QApplication.clipboard().setText(self.log.toPlainText())
def setup_ui(self): l = QVBoxLayout(self) self.qte = qte = QTextEdit(self) qte.setMinimumHeight(400) qte.setMinimumWidth(600) if self.initial_notes: qte.setPlainText(self.initial_notes) qte.moveCursor(QTextCursor.MoveOperation.End) l.addWidget(qte) l.addWidget(self.bb)
def __init__(self, parent): QWidget.__init__(self, parent) l = QVBoxLayout() self.setLayout(l) l.addStretch(10) self.pi = ProgressIndicator(self, 128) l.addWidget(self.pi, alignment=Qt.AlignmentFlag.AlignHCenter) self.dummy = QLabel('<h2>\xa0') l.addSpacing(10) l.addWidget(self.dummy, alignment=Qt.AlignmentFlag.AlignHCenter) l.addStretch(10) self.text = _('Calculating differences, please wait...')
class DBCheck(QDialog): # {{{ update_msg = pyqtSignal(object) def __init__(self, parent, db): QDialog.__init__(self, parent) self.l = QVBoxLayout() self.setLayout(self.l) self.l1 = QLabel( _('Vacuuming database to improve performance.') + ' ' + _('This will take a while, please wait...')) self.setWindowTitle(_('Vacuuming...')) self.l1.setWordWrap(True) self.l.addWidget(self.l1) self.msg = QLabel('') self.update_msg.connect(self.msg.setText, type=Qt.ConnectionType.QueuedConnection) self.l.addWidget(self.msg) self.msg.setWordWrap(True) self.resize(self.sizeHint() + QSize(100, 50)) self.error = None self.db = db.new_api self.rejected = False def start(self): t = self.thread = Thread(target=self.vacuum) t.daemon = True t.start() QTimer.singleShot(100, self.check) self.exec_() def vacuum(self): try: self.db.vacuum() except Exception as e: import traceback self.error = (as_unicode(e), traceback.format_exc()) def reject(self): self.rejected = True return QDialog.reject(self) def check(self): if self.rejected: return if self.thread.is_alive(): QTimer.singleShot(100, self.check) else: self.accept() def break_cycles(self): self.db = self.thread = None
def __init__(self, parent): QDialog.__init__(self, parent) self.setWindowTitle(_('Choose stores')) button_box = QDialogButtonBox(QDialogButtonBox.StandardButton.Close) button_box.accepted.connect(self.accept) button_box.rejected.connect(self.reject) v = QVBoxLayout(self) self.config_widget = StoreChooserWidget() v.addWidget(self.config_widget) v.addWidget(button_box) self.resize(800, 600)
def __init__(self, pa, parent): QDialog.__init__(self, parent) self.test_func = parent.test_email_settings self.setWindowTitle(_("Test email settings")) self.setWindowIcon(QIcon(I('config.ui'))) l = QVBoxLayout(self) opts = smtp_prefs().parse() self.from_ = la = QLabel(_("Send test mail from %s to:") % opts.from_) l.addWidget(la) self.to = le = QLineEdit(self) if pa: self.to.setText(pa) self.test_button = b = QPushButton(_('&Test'), self) b.clicked.connect(self.start_test) self.test_done.connect(self.on_test_done, type=Qt.ConnectionType.QueuedConnection) self.h = h = QHBoxLayout() h.addWidget(le), h.addWidget(b) l.addLayout(h) if opts.relay_host: self.la = la = QLabel( _('Using: %(un)s:%(pw)s@%(host)s:%(port)s and %(enc)s encryption' ) % dict(un=opts.relay_username, pw=from_hex_unicode(opts.relay_password), host=opts.relay_host, port=opts.relay_port, enc=opts.encryption)) l.addWidget(la) self.log = QPlainTextEdit(self) l.addWidget(self.log) self.bb = bb = QDialogButtonBox(QDialogButtonBox.StandardButton.Close) bb.rejected.connect(self.reject), bb.accepted.connect(self.accept) l.addWidget(bb)
def __init__(self, parent): QWidget.__init__(self, parent) l = QVBoxLayout() self.setLayout(l) l.addStretch(10) self.pi = ProgressIndicator(self, 128) l.addWidget(self.pi, alignment=Qt.AlignmentFlag.AlignHCenter) self.dummy = QLabel('<h2>\xa0') l.addSpacing(10) l.addWidget(self.dummy, alignment=Qt.AlignmentFlag.AlignHCenter) l.addStretch(10) self.setVisible(False) self.text = '' self.setFocusPolicy(Qt.FocusPolicy.NoFocus)
def setup_ui(self): from calibre.gui2.preferences.look_feel import (DisplayedFields, move_field_down, move_field_up) self.l = QVBoxLayout(self) self.field_display_order = fdo = QListView(self) self.model = DisplayedFields(self.db, fdo, pref_name='popup_book_display_fields') self.model.initialize() fdo.setModel(self.model) fdo.setAlternatingRowColors(True) del self.db self.l.addWidget(QLabel(_('Select displayed metadata'))) h = QHBoxLayout() h.addWidget(fdo) v = QVBoxLayout() self.mub = b = QToolButton(self) connect_lambda(b.clicked, self, lambda self: move_field_up(fdo, self.model)) b.setIcon(QIcon(I('arrow-up.png'))) b.setToolTip(_('Move the selected field up')) v.addWidget(b), v.addStretch(10) self.mud = b = QToolButton(self) b.setIcon(QIcon(I('arrow-down.png'))) b.setToolTip(_('Move the selected field down')) connect_lambda(b.clicked, self, lambda self: move_field_down(fdo, self.model)) v.addWidget(b) h.addLayout(v) self.l.addLayout(h) self.l.addWidget( QLabel('<p>' + _( 'Note that <b>comments</b> will always be displayed at the end, regardless of the order you assign here' ))) b = self.bb.addButton(_('Restore &defaults'), QDialogButtonBox.ButtonRole.ActionRole) b.clicked.connect(self.restore_defaults) b = self.bb.addButton(_('Select &all'), QDialogButtonBox.ButtonRole.ActionRole) b.clicked.connect(self.select_all) b = self.bb.addButton(_('Select &none'), QDialogButtonBox.ButtonRole.ActionRole) b.clicked.connect(self.select_none) self.l.addWidget(self.bb) self.setMinimumHeight(500)
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)
class Browser(QScrollArea): # {{{ show_plugin = pyqtSignal(object) def __init__(self, parent=None): QScrollArea.__init__(self, parent) self.setWidgetResizable(True) category_map, category_names = {}, {} for plugin in preferences_plugins(): if plugin.category not in category_map: category_map[plugin.category] = plugin.category_order if category_map[plugin.category] < plugin.category_order: category_map[plugin.category] = plugin.category_order if plugin.category not in category_names: category_names[plugin.category] = (plugin.gui_category if plugin.gui_category else plugin.category) self.category_names = category_names categories = list(category_map.keys()) categories.sort(key=lambda x: category_map[x]) self.category_map = OrderedDict() for c in categories: self.category_map[c] = [] for plugin in preferences_plugins(): self.category_map[plugin.category].append(plugin) for plugins in self.category_map.values(): plugins.sort(key=lambda x: x.name_order) self.widgets = [] self._layout = QVBoxLayout() self.container = QWidget(self) self.container.setLayout(self._layout) self.setWidget(self.container) for name, plugins in self.category_map.items(): w = Category(name, plugins, self.category_names[name], parent=self) self.widgets.append(w) self._layout.addWidget(w) w.plugin_activated.connect(self.show_plugin.emit) self._layout.addStretch(1)
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 do_config(self): # Save values that need to be synced between the dialog and the # search widget. self.config['open_external'] = self.open_external.isChecked() # Create the config dialog. It's going to put two config widgets # into a QTabWidget for displaying all of the settings. d = QDialog(self) button_box = QDialogButtonBox(QDialogButtonBox.StandardButton.Close) v = QVBoxLayout(d) button_box.accepted.connect(d.accept) button_box.rejected.connect(d.reject) d.setWindowTitle(_('Customize Get books search')) tab_widget = QTabWidget(d) v.addWidget(tab_widget) v.addWidget(button_box) chooser_config_widget = StoreChooserWidget() search_config_widget = StoreConfigWidget(self.config) tab_widget.addTab(chooser_config_widget, _('Choose s&tores')) tab_widget.addTab(search_config_widget, _('Configure s&earch')) # Restore dialog state. geometry = self.config.get('config_dialog_geometry', None) if geometry: QApplication.instance().safe_restore_geometry(d, geometry) else: d.resize(800, 600) tab_index = self.config.get('config_dialog_tab_index', 0) tab_index = min(tab_index, tab_widget.count() - 1) tab_widget.setCurrentIndex(tab_index) d.exec() # Save dialog state. self.config['config_dialog_geometry'] = bytearray(d.saveGeometry()) self.config['config_dialog_tab_index'] = tab_widget.currentIndex() search_config_widget.save_settings() self.config_changed() self.gui.load_store_plugins() self.setup_store_checks()
def __init__(self, parent): QWidget.__init__(self, parent) self.use_stemmer = parent.use_stemmer self.current_query = None l = QVBoxLayout(self) h = QHBoxLayout() l.addLayout(h) self.search_box = sb = SearchBox(self) sb.initialize('library-annotations-browser-search-box') sb.cleared.connect(self.cleared, type=Qt.ConnectionType.QueuedConnection) sb.lineEdit().returnPressed.connect(self.show_next) sb.lineEdit().setPlaceholderText(_('Enter words to search for')) h.addWidget(sb) self.next_button = nb = QToolButton(self) h.addWidget(nb) nb.setFocusPolicy(Qt.FocusPolicy.NoFocus) nb.setIcon(QIcon(I('arrow-down.png'))) nb.clicked.connect(self.show_next) nb.setToolTip(_('Find next match')) self.prev_button = nb = QToolButton(self) h.addWidget(nb) nb.setFocusPolicy(Qt.FocusPolicy.NoFocus) nb.setIcon(QIcon(I('arrow-up.png'))) nb.clicked.connect(self.show_previous) nb.setToolTip(_('Find previous match')) self.restrictions = rs = Restrictions(self) rs.restrictions_changed.connect(self.effective_query_changed) self.use_stemmer.stateChanged.connect(self.effective_query_changed) l.addWidget(rs) self.results_list = rl = ResultsList(self) rl.current_result_changed.connect(self.current_result_changed) rl.open_annotation.connect(self.open_annotation) rl.show_book.connect(self.show_book) rl.edit_annotation.connect(self.edit_annotation) rl.delete_requested.connect(self.delete_requested) rl.export_requested.connect(self.export_requested) l.addWidget(rl)
class Wizard(QDialog): def __init__(self, parent=None): QDialog.__init__(self, parent) self.resize(440, 480) self.verticalLayout = QVBoxLayout(self) self.widget = WizardWidget(self) self.verticalLayout.addWidget(self.widget) self.buttonBox = QDialogButtonBox(self) self.buttonBox.setOrientation(Qt.Orientation.Horizontal) self.buttonBox.setStandardButtons(QDialogButtonBox.StandardButton.Cancel|QDialogButtonBox.StandardButton.Ok) self.verticalLayout.addWidget(self.buttonBox) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) self.setModal(Qt.WindowModality.WindowModal) @property def xpath(self): return self.widget.xpath
class ChoosePluginToolbarsDialog(QDialog): def __init__(self, parent, plugin, locations): QDialog.__init__(self, parent) self.locations = locations self.setWindowTitle(_('Add "%s" to toolbars or menus') % plugin.name) self._layout = QVBoxLayout(self) self.setLayout(self._layout) self._header_label = QLabel( _('Select the toolbars and/or menus to add <b>%s</b> to:') % plugin.name) self._layout.addWidget(self._header_label) self._locations_list = QListWidget(self) self._locations_list.setSelectionMode( QAbstractItemView.SelectionMode.MultiSelection) sizePolicy = QSizePolicy(QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Minimum) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) self._locations_list.setSizePolicy(sizePolicy) for key, text in locations: self._locations_list.addItem(text) if key in {'toolbar', 'toolbar-device'}: self._locations_list.item(self._locations_list.count() - 1).setSelected(True) self._layout.addWidget(self._locations_list) self._footer_label = QLabel( _('You can also customise the plugin locations ' 'using <b>Preferences -> Interface -> Toolbars</b>')) self._layout.addWidget(self._footer_label) button_box = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel) button_box.accepted.connect(self.accept) button_box.rejected.connect(self.reject) self._layout.addWidget(button_box) self.resize(self.sizeHint()) def selected_locations(self): selected = [] for row in self._locations_list.selectionModel().selectedRows(): selected.append(self.locations[row.row()]) return selected
def do_user_config(self, parent=None): ''' This method shows a configuration dialog for this plugin. It returns True if the user clicks OK, False otherwise. The changes are automatically applied. ''' from qt.core import (QDialog, QDialogButtonBox, QVBoxLayout, QLabel, Qt, QLineEdit, QCheckBox) config_dialog = QDialog(parent) button_box = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel) v = QVBoxLayout(config_dialog) def size_dialog(): config_dialog.resize(config_dialog.sizeHint()) button_box.accepted.connect(config_dialog.accept) button_box.rejected.connect(config_dialog.reject) config_dialog.setWindowTitle(_('Customize') + ' ' + self.name) from calibre.customize.ui import (plugin_customization, customize_plugin) help_text = self.customization_help(gui=True) help_text = QLabel(help_text, config_dialog) help_text.setWordWrap(True) help_text.setTextInteractionFlags( Qt.TextInteractionFlag.LinksAccessibleByMouse | Qt.TextInteractionFlag.LinksAccessibleByKeyboard) help_text.setOpenExternalLinks(True) v.addWidget(help_text) bf = QCheckBox(_('Add linked files in breadth first order')) bf.setToolTip( _('Normally, when following links in HTML files' ' calibre does it depth first, i.e. if file A links to B and ' ' C, but B links to D, the files are added in the order A, B, D, C. ' ' With this option, they will instead be added as A, B, C, D')) sc = plugin_customization(self) if not sc: sc = '' sc = sc.strip() enc = sc.partition('|')[0] bfs = sc.partition('|')[-1] bf.setChecked(bfs == 'bf') sc = QLineEdit(enc, config_dialog) v.addWidget(sc) v.addWidget(bf) v.addWidget(button_box) size_dialog() config_dialog.exec() if config_dialog.result() == QDialog.DialogCode.Accepted: sc = str(sc.text()).strip() if bf.isChecked(): sc += '|bf' customize_plugin(self, sc) return config_dialog.result()
class SelectFormats(QDialog): def __init__(self, fmt_count, msg, single=False, parent=None, exclude=False): QDialog.__init__(self, parent) self._l = QVBoxLayout(self) self.single_fmt = single self.setLayout(self._l) self.setWindowTitle(_('Choose formats')) self._m = QLabel(msg) self._m.setWordWrap(True) self._l.addWidget(self._m) self.formats = Formats(fmt_count) self.fview = QListView(self) self.fview.doubleClicked.connect( self.double_clicked, type=Qt.ConnectionType.QueuedConnection) if exclude: if QApplication.instance().is_dark_theme: sheet = 'background-color: #DAA520; color: black' else: sheet = 'background-color: #fae7b5' self.fview.setStyleSheet('QListView { %s }' % sheet) self._l.addWidget(self.fview) self.fview.setModel(self.formats) self.fview.setSelectionMode( QAbstractItemView.SelectionMode.SingleSelection if single else QAbstractItemView.SelectionMode.MultiSelection) self.bbox = \ QDialogButtonBox(QDialogButtonBox.StandardButton.Ok|QDialogButtonBox.StandardButton.Cancel, Qt.Orientation.Horizontal, self) self._l.addWidget(self.bbox) self.bbox.accepted.connect(self.accept) self.bbox.rejected.connect(self.reject) self.fview.setIconSize(QSize(48, 48)) self.fview.setSpacing(2) self.resize(350, 500) self.selected_formats = set() def accept(self, *args): for idx in self.fview.selectedIndexes(): self.selected_formats.add(self.formats.fmt(idx)) QDialog.accept(self, *args) def double_clicked(self, index): if self.single_fmt: self.accept()
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)
class Tab1Config(DeviceConfigTab): # {{{ def __init__(self, parent, device): super().__init__(parent) self.l = QVBoxLayout(self) self.setLayout(self.l) self.collections_options = CollectionsGroupBox(self, device) self.l.addWidget(self.collections_options) self.addDeviceWidget(self.collections_options) self.covers_options = CoversGroupBox(self, device) self.l.addWidget(self.covers_options) self.addDeviceWidget(self.covers_options) self.book_uploads_options = BookUploadsGroupBox(self, device) self.l.addWidget(self.book_uploads_options) self.addDeviceWidget(self.book_uploads_options) self.l.addStretch()
def __init__(self, parent, duplicates, loc): QDialog.__init__(self, parent) l = QVBoxLayout() self.setLayout(l) self.la = la = QLabel( _('Books with the same, title, author and language as the following already exist in the library %s.' ' Select which books you want copied anyway.') % os.path.basename(loc)) la.setWordWrap(True) l.addWidget(la) self.setWindowTitle(_('Duplicate books')) self.books = QListWidget(self) self.items = [] for book_id, (title, authors) in iteritems(duplicates): i = QListWidgetItem( _('{0} by {1}').format(title, ' & '.join(authors[:3])), self.books) i.setData(Qt.ItemDataRole.UserRole, book_id) i.setFlags(Qt.ItemFlag.ItemIsUserCheckable | Qt.ItemFlag.ItemIsEnabled) i.setCheckState(Qt.CheckState.Checked) self.items.append(i) l.addWidget(self.books) self.bb = bb = QDialogButtonBox( QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel) bb.accepted.connect(self.accept) bb.rejected.connect(self.reject) self.a = b = bb.addButton(_('Select &all'), QDialogButtonBox.ButtonRole.ActionRole) b.clicked.connect(self.select_all), b.setIcon(QIcon(I('plus.png'))) self.n = b = bb.addButton(_('Select &none'), QDialogButtonBox.ButtonRole.ActionRole) b.clicked.connect(self.select_none), b.setIcon(QIcon(I('minus.png'))) self.ctc = b = bb.addButton(_('&Copy to clipboard'), QDialogButtonBox.ButtonRole.ActionRole) b.clicked.connect(self.copy_to_clipboard), b.setIcon( QIcon(I('edit-copy.png'))) l.addWidget(bb) self.resize(600, 400)
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()