class AddEmptyBookDialog(QDialog): def __init__(self, parent, db, author, series=None, title=None, dup_title=None): QDialog.__init__(self, parent) self.db = db self.setWindowTitle(_('How many empty books?')) self._layout = QGridLayout(self) self.setLayout(self._layout) self.qty_label = QLabel(_('How many empty books should be added?')) self._layout.addWidget(self.qty_label, 0, 0, 1, 2) self.qty_spinbox = QSpinBox(self) self.qty_spinbox.setRange(1, 10000) self.qty_spinbox.setValue(1) self._layout.addWidget(self.qty_spinbox, 1, 0, 1, 2) self.author_label = QLabel(_('Set the author of the new books to:')) self._layout.addWidget(self.author_label, 2, 0, 1, 2) self.authors_combo = EditWithComplete(self) self.authors_combo.setSizeAdjustPolicy( QComboBox.SizeAdjustPolicy.AdjustToMinimumContentsLengthWithIcon) self.authors_combo.setEditable(True) self._layout.addWidget(self.authors_combo, 3, 0, 1, 1) self.initialize_authors(db, author) self.clear_button = QToolButton(self) self.clear_button.setIcon(QIcon(I('trash.png'))) self.clear_button.setToolTip(_('Reset author to Unknown')) self.clear_button.clicked.connect(self.reset_author) self._layout.addWidget(self.clear_button, 3, 1, 1, 1) self.series_label = QLabel(_('Set the series of the new books to:')) self._layout.addWidget(self.series_label, 4, 0, 1, 2) self.series_combo = EditWithComplete(self) self.series_combo.setSizeAdjustPolicy( QComboBox.SizeAdjustPolicy.AdjustToMinimumContentsLengthWithIcon) self.series_combo.setEditable(True) self._layout.addWidget(self.series_combo, 5, 0, 1, 1) self.initialize_series(db, series) self.sclear_button = QToolButton(self) self.sclear_button.setIcon(QIcon(I('trash.png'))) self.sclear_button.setToolTip(_('Reset series')) self.sclear_button.clicked.connect(self.reset_series) self._layout.addWidget(self.sclear_button, 5, 1, 1, 1) self.title_label = QLabel(_('Set the title of the new books to:')) self._layout.addWidget(self.title_label, 6, 0, 1, 2) self.title_edit = QLineEdit(self) self.title_edit.setText(title or '') self._layout.addWidget(self.title_edit, 7, 0, 1, 1) self.tclear_button = QToolButton(self) self.tclear_button.setIcon(QIcon(I('trash.png'))) self.tclear_button.setToolTip(_('Reset title')) self.tclear_button.clicked.connect(self.title_edit.clear) self._layout.addWidget(self.tclear_button, 7, 1, 1, 1) self.format_label = QLabel(_('Also create an empty e-book in format:')) self._layout.addWidget(self.format_label, 8, 0, 1, 2) c = self.format_value = QComboBox(self) from calibre.ebooks.oeb.polish.create import valid_empty_formats possible_formats = [''] + sorted(x.upper() for x in valid_empty_formats) c.addItems(possible_formats) c.setToolTip( _('Also create an empty book format file that you can subsequently edit' )) if gprefs.get('create_empty_epub_file', False): # Migration of the check box gprefs.set('create_empty_format_file', 'epub') del gprefs['create_empty_epub_file'] use_format = gprefs.get('create_empty_format_file', '').upper() try: c.setCurrentIndex(possible_formats.index(use_format)) except Exception: pass self._layout.addWidget(c, 9, 0, 1, 1) self.copy_formats = cf = QCheckBox( _('Also copy book &formats when duplicating a book'), self) cf.setToolTip( _('Also copy all e-book files into the newly created duplicate' ' books.')) cf.setChecked(gprefs.get('create_empty_copy_dup_formats', False)) self._layout.addWidget(cf, 10, 0, 1, -1) button_box = self.bb = QDialogButtonBox( QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel) button_box.accepted.connect(self.accept) button_box.rejected.connect(self.reject) self._layout.addWidget(button_box, 11, 0, 1, -1) if dup_title: self.dup_button = b = button_box.addButton( _('&Duplicate current book'), QDialogButtonBox.ButtonRole.ActionRole) b.clicked.connect(self.do_duplicate_book) b.setIcon(QIcon(I('edit-copy.png'))) b.setToolTip( _('Make the new empty book records exact duplicates\n' 'of the current book "%s", with all metadata identical') % dup_title) self.resize(self.sizeHint()) self.duplicate_current_book = False def do_duplicate_book(self): self.duplicate_current_book = True self.accept() def accept(self): self.save_settings() return QDialog.accept(self) def save_settings(self): gprefs['create_empty_format_file'] = self.format_value.currentText( ).lower() gprefs['create_empty_copy_dup_formats'] = self.copy_formats.isChecked() def reject(self): self.save_settings() return QDialog.reject(self) def reset_author(self, *args): self.authors_combo.setEditText(_('Unknown')) def reset_series(self): self.series_combo.setEditText('') def initialize_authors(self, db, author): au = author if not au: au = _('Unknown') self.authors_combo.show_initial_value(au.replace('|', ',')) self.authors_combo.set_separator('&') self.authors_combo.set_space_before_sep(True) self.authors_combo.set_add_separator( tweaks['authors_completer_append_separator']) self.authors_combo.update_items_cache(db.all_author_names()) def initialize_series(self, db, series): self.series_combo.show_initial_value(series or '') self.series_combo.update_items_cache(db.all_series_names()) self.series_combo.set_separator(None) @property def qty_to_add(self): return self.qty_spinbox.value() @property def selected_authors(self): return string_to_authors(unicode_type(self.authors_combo.text())) @property def selected_series(self): return unicode_type(self.series_combo.text()) @property def selected_title(self): return self.title_edit.text().strip()
def __init__(self, mi=None, prefs=None, parent=None, for_global_prefs=False): QWidget.__init__(self, parent) self.ignore_changed = False self.for_global_prefs = for_global_prefs self.l = l = QHBoxLayout(self) l.setContentsMargins(0, 0, 0, 0) self.setLayout(l) self.settings_tabs = st = QTabWidget(self) l.addWidget(st) self.preview_label = la = Preview(self) l.addWidget(la) if prefs is None: prefs = cprefs self.original_prefs = prefs self.mi = mi or self.default_mi() self.colors_page = cp = QWidget(st) st.addTab(cp, _('&Colors')) cp.l = l = QGridLayout() cp.setLayout(l) if for_global_prefs: msg = _( 'When generating covers, a color scheme for the cover is chosen at random from the' ' color schemes below. You can prevent an individual scheme from being selected by' ' unchecking it. The preview on the right shows the currently selected color scheme.' ) else: msg = _( 'Choose a color scheme to be used for this generated cover.' ) + '<p>' + _( 'In normal cover generation, the color scheme is chosen at random from the list of color schemes below. You' ' can prevent an individual color scheme from being chosen by unchecking it here.' ) cp.la = la = QLabel('<p>' + msg) la.setWordWrap(True) l.addWidget(la, 0, 0, 1, -1) self.colors_list = cl = QListWidget(cp) l.addWidget(cl, 1, 0, 1, -1) self.colors_map = OrderedDict() self.ncs = ncs = QPushButton(QIcon(I('plus.png')), _('&New color scheme'), cp) ncs.clicked.connect(self.create_color_scheme) l.addWidget(ncs) self.ecs = ecs = QPushButton(QIcon(I('format-fill-color.png')), _('&Edit color scheme'), cp) ecs.clicked.connect(self.edit_color_scheme) l.addWidget(ecs, l.rowCount() - 1, 1) self.rcs = rcs = QPushButton(QIcon(I('minus.png')), _('&Remove color scheme'), cp) rcs.clicked.connect(self.remove_color_scheme) l.addWidget(rcs, l.rowCount() - 1, 2) self.styles_page = sp = QWidget(st) st.addTab(sp, _('&Styles')) sp.l = l = QVBoxLayout() sp.setLayout(l) if for_global_prefs: msg = _( 'When generating covers, a style for the cover is chosen at random from the' ' styles below. You can prevent an individual style from being selected by' ' unchecking it. The preview on the right shows the currently selected style.' ) else: msg = _( 'Choose a style to be used for this generated cover.' ) + '<p>' + _( 'In normal cover generation, the style is chosen at random from the list of styles below. You' ' can prevent an individual style from being chosen by unchecking it here.' ) sp.la = la = QLabel('<p>' + msg) la.setWordWrap(True) l.addWidget(la) self.styles_list = sl = QListWidget(sp) l.addWidget(sl) self.style_map = OrderedDict() self.font_page = fp = QWidget(st) st.addTab(fp, _('&Fonts and sizes')) fp.l = l = QFormLayout() fp.setLayout(l) fp.f = [] def add_hline(): f = QFrame() fp.f.append(f) f.setFrameShape(QFrame.Shape.HLine) l.addRow(f) for x, label, size_label in ( ('title', _('&Title font family:'), _('&Title font size:')), ('subtitle', _('&Subtitle font family:'), _('&Subtitle font size:')), ('footer', _('&Footer font family:'), _('&Footer font size:')), ): attr = '%s_font_family' % x ff = FontFamilyChooser(fp) setattr(self, attr, ff) l.addRow(label, ff) ff.family_changed.connect(self.emit_changed) attr = '%s_font_size' % x fs = QSpinBox(fp) setattr(self, attr, fs) fs.setMinimum(8), fs.setMaximum(200), fs.setSuffix(' px') fs.setValue(prefs[attr]) fs.valueChanged.connect(self.emit_changed) l.addRow(size_label, fs) add_hline() self.changed_timer = t = QTimer(self) t.setSingleShot(True), t.setInterval(500), t.timeout.connect( self.emit_changed) def create_sz(label): ans = QSpinBox(self) ans.setSuffix(' px'), ans.setMinimum(100), ans.setMaximum(10000) l.addRow(label, ans) ans.valueChanged.connect(self.changed_timer.start) return ans self.cover_width = create_sz(_('Cover &width:')) self.cover_height = create_sz(_('Cover &height:')) fp.cla = la = QLabel( _('Note that the preview to the side is of fixed aspect ratio, so changing the cover' ' width above will not have any effect. If you change the height, you should also change the width nevertheless' ' as it will be used in actual cover generation.')) la.setWordWrap(True) l.addRow(la) self.templates_page = tp = QWidget(st) st.addTab(tp, _('&Text')) tp.l = l = QVBoxLayout() tp.setLayout(l) tp.la = la = QLabel( _('The text on the generated cover is taken from the metadata of the book.' ' This is controlled via templates. You can use the <b>, <i> and <br> tags' ' in the templates for bold, italic and line breaks, respectively. The' ' default templates use the title, series and authors. You can change them to use' ' whatever metadata you like.')) la.setWordWrap(True), la.setTextFormat(Qt.TextFormat.PlainText) l.addWidget(la) def create_template_widget(title, which, button): attr = which + '_template' heading = QLabel('<h2>' + title) setattr(tp, attr + '_heading', heading) l.addWidget(heading) la = QLabel() setattr(self, attr, la) l.addWidget(la), la.setTextFormat( Qt.TextFormat.PlainText), la.setStyleSheet( 'QLabel {font-family: monospace}') la.setWordWrap(True) b = QPushButton(button) b.setSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed) connect_lambda(b.clicked, self, lambda self: self.change_template(which)) setattr(self, attr + '_button', b) l.addWidget(b) if which != 'footer': f = QFrame(tp) setattr(tp, attr + '_sep', f), f.setFrameShape(QFrame.Shape.HLine) l.addWidget(f) l.addSpacing(10) create_template_widget(_('The title template'), 'title', _('Change the &title template')) create_template_widget(_('The sub-title template'), 'subtitle', _('Change the &sub-title template')) create_template_widget(_('The footer template'), 'footer', _('Change the &footer template')) l.addStretch(2) self.apply_prefs(prefs) self.changed.connect(self.update_preview) self.styles_list.itemSelectionChanged.connect(self.update_preview) self.colors_list.itemSelectionChanged.connect(self.update_preview) self.update_preview()