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()
예제 #2
0
    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()