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)
def test(): app = QApplication([]) app d = QDialog() d.setLayout(QVBoxLayout()) d.layout().addWidget(FontFamilyChooser(d)) d.layout().addWidget(QFontComboBox(d)) d.exec_()
def customize_remove_unused_css(name, parent, ans): d = QDialog(parent) d.l = l = QVBoxLayout() d.setLayout(d.l) d.setWindowTitle(_('Remove unused CSS')) def label(text): la = QLabel(text) la.setWordWrap(True), l.addWidget(la), la.setMinimumWidth(450) l.addWidget(la) return la d.la = label( _('This will remove all CSS rules that do not match any actual content.' ' There are a couple of additional cleanups you can enable, below:')) d.c = c = QCheckBox(_('Remove unused &class attributes')) c.setChecked(tprefs['remove_unused_classes']) l.addWidget(c) d.la2 = label('<span style="font-size:small; font-style: italic">' + _( 'Remove all class attributes from the HTML that do not match any existing CSS rules' )) d.m = m = QCheckBox(_('Merge CSS rules with identical &selectors')) m.setChecked(tprefs['merge_identical_selectors']) l.addWidget(m) d.la3 = label('<span style="font-size:small; font-style: italic">' + _( 'Merge CSS rules in the same stylesheet that have identical selectors.' ' Note that in rare cases merging can result in a change to the effective styling' ' of the book, so use with care.')) d.p = p = QCheckBox(_('Merge CSS rules with identical &properties')) p.setChecked(tprefs['merge_rules_with_identical_properties']) l.addWidget(p) d.la4 = label('<span style="font-size:small; font-style: italic">' + _( 'Merge CSS rules in the same stylesheet that have identical properties.' ' Note that in rare cases merging can result in a change to the effective styling' ' of the book, so use with care.')) d.u = u = QCheckBox(_('Remove &unreferenced style sheets')) u.setChecked(tprefs['remove_unreferenced_sheets']) l.addWidget(u) d.la5 = label( '<span style="font-size:small; font-style: italic">' + _('Remove stylesheets that are not referenced by any content.')) d.bb = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel) d.l.addWidget(d.bb) d.bb.rejected.connect(d.reject) d.bb.accepted.connect(d.accept) ret = d.exec() ans['remove_unused_classes'] = tprefs[ 'remove_unused_classes'] = c.isChecked() ans['merge_identical_selectors'] = tprefs[ 'merge_identical_selectors'] = m.isChecked() ans['merge_rules_with_identical_properties'] = tprefs[ 'merge_rules_with_identical_properties'] = p.isChecked() ans['remove_unreferenced_sheets'] = tprefs[ 'remove_unreferenced_sheets'] = u.isChecked() if ret != QDialog.DialogCode.Accepted: raise Abort()
def test(): from calibre.gui2 import Application app = Application([]) app d = QDialog() d.setLayout(QVBoxLayout()) d.layout().addWidget(FontFamilyChooser(d)) d.layout().addWidget(QFontComboBox(d)) d.exec()
def view_server_logs(self): from calibre.srv.embedded import log_paths log_error_file, log_access_file = log_paths() d = QDialog(self) d.resize(QSize(800, 600)) layout = QVBoxLayout() d.setLayout(layout) layout.addWidget(QLabel(_('Error log:'))) el = QPlainTextEdit(d) layout.addWidget(el) try: el.setPlainText( share_open(log_error_file, 'rb').read().decode('utf8', 'replace') ) except EnvironmentError: el.setPlainText(_('No error log found')) layout.addWidget(QLabel(_('Access log:'))) al = QPlainTextEdit(d) layout.addWidget(al) try: al.setPlainText( share_open(log_access_file, 'rb').read().decode('utf8', 'replace') ) except EnvironmentError: al.setPlainText(_('No access log found')) loc = QLabel(_('The server log files are in: {}').format(os.path.dirname(log_error_file))) loc.setWordWrap(True) layout.addWidget(loc) bx = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok) layout.addWidget(bx) bx.accepted.connect(d.accept) b = bx.addButton(_('&Clear logs'), QDialogButtonBox.ButtonRole.ActionRole) def clear_logs(): if getattr(self.server, 'is_running', False): return error_dialog(d, _('Server running'), _( 'Cannot clear logs while the server is running. First stop the server.'), show=True) if self.server: self.server.access_log.clear() self.server.log.clear() else: for x in (log_error_file, log_access_file): try: os.remove(x) except EnvironmentError as err: if err.errno != errno.ENOENT: raise el.setPlainText(''), al.setPlainText('') b.clicked.connect(clear_logs) d.show()
def get_bulk_rename_settings(parent, number, msg=None, sanitize=sanitize_file_name, leading_zeros=True, prefix=None, category='text', allow_spine_order=False): # {{{ d = QDialog(parent) d.setWindowTitle(_('Bulk rename items')) d.l = l = QFormLayout(d) d.setLayout(l) d.prefix = p = QLineEdit(d) default_prefix = {k:v for k, __, v in CATEGORIES}.get(category, _('Chapter-')) previous = tprefs.get('file-list-bulk-rename-prefix', {}) prefix = prefix or previous.get(category, default_prefix) p.setText(prefix) p.selectAll() d.la = la = QLabel(msg or _( 'All selected files will be renamed to the form prefix-number')) l.addRow(la) l.addRow(_('&Prefix:'), p) d.num = num = QSpinBox(d) num.setMinimum(0), num.setValue(1), num.setMaximum(1000) l.addRow(_('Starting &number:'), num) if allow_spine_order: d.spine_order = QCheckBox(_('Rename files according to their book order')) d.spine_order.setToolTip(textwrap.fill(_( 'Rename the selected files according to the order they appear in the book, instead of the order they were selected in.'))) l.addRow(d.spine_order) d.bb = bb = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel) bb.accepted.connect(d.accept), bb.rejected.connect(d.reject) l.addRow(bb) ans = {'prefix': None, 'start': None} if d.exec() == QDialog.DialogCode.Accepted: prefix = sanitize(str(d.prefix.text())) previous[category] = prefix tprefs.set('file-list-bulk-rename-prefix', previous) num = d.num.value() fmt = '%d' if leading_zeros: largest = num + number - 1 fmt = f'%0{len(str(largest))}d' ans['prefix'] = prefix + fmt ans['start'] = num if allow_spine_order: ans['spine_order'] = d.spine_order.isChecked() return ans
def show_debug_info(self): info = self.device.device_debug_info() d = QDialog(self) d.l = l = QVBoxLayout() d.setLayout(l) d.v = v = QPlainTextEdit() d.setWindowTitle(self.device.get_gui_name()) v.setPlainText(info) v.setMinimumWidth(400) v.setMinimumHeight(350) l.addWidget(v) bb = d.bb = QDialogButtonBox(QDialogButtonBox.StandardButton.Close) bb.accepted.connect(d.accept) bb.rejected.connect(d.reject) l.addWidget(bb) bb.addButton(_('Copy to clipboard'), QDialogButtonBox.ButtonRole.ActionRole) bb.clicked.connect(lambda : QApplication.clipboard().setText(v.toPlainText())) d.exec_()
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())
'<br>'+str(err), show=True) return False # }}} if __name__ == '__main__': from calibre.gui2 import Application from calibre.devices.kobo.driver import KOBOTOUCH from calibre.devices.scanner import DeviceScanner s = DeviceScanner() s.scan() app = Application([]) debug_print("KOBOTOUCH:", KOBOTOUCH) dev = KOBOTOUCH(None) # dev.startup() # cd = dev.detect_managed_devices(s.devices) # dev.open(cd, 'test') cw = dev.config_widget() d = QDialog() d.l = QVBoxLayout() d.setLayout(d.l) d.l.addWidget(cw) bb = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok|QDialogButtonBox.StandardButton.Cancel) d.l.addWidget(bb) bb.accepted.connect(d.accept) bb.rejected.connect(d.reject) if d.exec() == QDialog.DialogCode.Accepted: cw.commit() dev.shutdown()
EnComboBox.clear(self) def eventFilter(self, obj, e): try: c = self.lineEdit().mcompleter except AttributeError: return False etype = e.type() if self.eat_focus_out and self is obj and etype == QEvent.Type.FocusOut: if c.isVisible(): return True return EnComboBox.eventFilter(self, obj, e) if __name__ == '__main__': from qt.core import QDialog, QVBoxLayout from calibre.gui2 import Application app = Application([]) d = QDialog() d.setLayout(QVBoxLayout()) le = EditWithComplete(d) d.layout().addWidget(le) items = [ 'oane\n line2\n line3', 'otwo', 'othree', 'ooone', 'ootwo', 'other', 'odd', 'over', 'orc', 'oven', 'owe', 'oothree', 'a1', 'a2', 'Edgas', 'Èdgar', 'Édgaq', 'Edgar', 'Édgar' ] le.update_items_cache(items) le.show_initial_value('') d.exec()
def ask_about_cc_mismatch(gui, db, newdb, missing_cols, incompatible_cols): # {{{ source_metadata = db.field_metadata.custom_field_metadata( include_composites=True) dest_library_path = newdb.library_path ndbname = os.path.basename(dest_library_path) d = QDialog(gui) d.setWindowTitle(_('Different custom columns')) l = QFormLayout() tl = QVBoxLayout() d.setLayout(tl) d.s = QScrollArea(d) tl.addWidget(d.s) d.w = QWidget(d) d.s.setWidget(d.w) d.s.setWidgetResizable(True) d.w.setLayout(l) d.setMinimumWidth(600) d.setMinimumHeight(500) d.bb = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel) msg = _( 'The custom columns in the <i>{0}</i> library are different from the ' 'custom columns in the <i>{1}</i> library. As a result, some metadata might not be copied.' ).format(os.path.basename(db.library_path), ndbname) d.la = la = QLabel(msg) la.setWordWrap(True) la.setStyleSheet('QLabel { margin-bottom: 1.5ex }') l.addRow(la) if incompatible_cols: la = d.la2 = QLabel( _('The following columns are incompatible - they have the same name' ' but different data types. They will be ignored: ') + ', '.join(sorted(incompatible_cols, key=sort_key))) la.setWordWrap(True) la.setStyleSheet('QLabel { margin-bottom: 1.5ex }') l.addRow(la) missing_widgets = [] if missing_cols: la = d.la3 = QLabel( _('The following columns are missing in the <i>{0}</i> library.' ' You can choose to add them automatically below.').format( ndbname)) la.setWordWrap(True) l.addRow(la) for k in missing_cols: widgets = (k, QCheckBox(_('Add to the %s library') % ndbname)) l.addRow(QLabel(k), widgets[1]) missing_widgets.append(widgets) d.la4 = la = QLabel( _('This warning is only shown once per library, per session')) la.setWordWrap(True) tl.addWidget(la) tl.addWidget(d.bb) d.bb.accepted.connect(d.accept) d.bb.rejected.connect(d.reject) d.resize(d.sizeHint()) if d.exec_() == QDialog.DialogCode.Accepted: changes_made = False for k, cb in missing_widgets: if cb.isChecked(): col_meta = source_metadata[k] newdb.create_custom_column(col_meta['label'], col_meta['name'], col_meta['datatype'], len(col_meta['is_multiple']) > 0, col_meta['is_editable'], col_meta['display']) changes_made = True if changes_made: # Unload the db so that the changes are available # when it is next accessed from calibre.gui2.ui import get_gui library_broker = get_gui().library_broker library_broker.unload_library(dest_library_path) return True return False