def __init__(self, *args, **kw): ConfigWidgetBase.__init__(self, *args, **kw) self.l = l = QVBoxLayout(self) l.setContentsMargins(0, 0, 0, 0) self.tabs_widget = t = QTabWidget(self) l.addWidget(t) self.main_tab = m = MainTab(self) t.addTab(m, _('&Main')) m.start_server.connect(self.start_server) m.stop_server.connect(self.stop_server) m.test_server.connect(self.test_server) m.show_logs.connect(self.view_server_logs) self.opt_autolaunch_server = m.opt_autolaunch_server self.users_tab = ua = Users(self) t.addTab(ua, _('&User accounts')) self.advanced_tab = a = AdvancedTab(self) sa = QScrollArea(self) sa.setWidget(a), sa.setWidgetResizable(True) t.addTab(sa, _('&Advanced')) self.custom_list_tab = clt = CustomList(self) sa = QScrollArea(self) sa.setWidget(clt), sa.setWidgetResizable(True) t.addTab(sa, _('Book &list template')) self.search_net_tab = SearchTheInternet(self) t.addTab(self.search_net_tab, _('&Search the internet')) for tab in self.tabs: if hasattr(tab, 'changed_signal'): tab.changed_signal.connect(self.changed_signal.emit)
def __init__(self, parent=None): QStackedWidget.__init__(self, parent) self.welcome = w = QLabel('<p>'+_( 'Double click a file in the left panel to start editing' ' it.')) self.addWidget(w) w.setWordWrap(True) w.setAlignment(Qt.AlignmentFlag.AlignTop | Qt.AlignmentFlag.AlignHCenter) self.container = c = QWidget(self) self.addWidget(c) l = c.l = QVBoxLayout(c) c.setLayout(l) l.setContentsMargins(0, 0, 0, 0) self.editor_tabs = t = QTabWidget(c) l.addWidget(t) t.setDocumentMode(True) t.setTabsClosable(True) t.setMovable(True) pal = self.palette() if pal.color(QPalette.ColorRole.WindowText).lightness() > 128: i = QImage(I('modified.png')) i.invertPixels() self.modified_icon = QIcon(QPixmap.fromImage(i)) else: self.modified_icon = QIcon(I('modified.png')) self.editor_tabs.currentChanged.connect(self.current_editor_changed) self.editor_tabs.tabCloseRequested.connect(self._close_requested) self.search_panel = SearchPanel(self) l.addWidget(self.search_panel) self.restore_state() self.editor_tabs.tabBar().installEventFilter(self)
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, dev, ignored_folders=None, parent=None): QDialog.__init__(self, parent) self.l = l = QVBoxLayout() self.setLayout(l) self.la = la = QLabel('<p>' + _('<b>Scanned folders:</b>') + ' ' + _('You can select which folders calibre will ' 'scan when searching this device for books.')) la.setWordWrap(True) l.addWidget(la) self.tabs = QTabWidget(self) l.addWidget(self.tabs) self.widgets = [] for storage in dev.filesystem_cache.entries: self.dev = dev w = Storage(storage, item_func=self.create_item) del self.dev self.tabs.addTab(w, storage.name) self.widgets.append(w) w.itemChanged.connect(self.item_changed) self.la2 = la = QLabel( _('If you a select a previously unselected folder, any sub-folders' ' will not be visible until you restart calibre.')) l.addWidget(la) la.setWordWrap(True) self.bb = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel) self.bb.accepted.connect(self.accept) self.bb.rejected.connect(self.reject) self.sab = self.bb.addButton(_('Select &all'), QDialogButtonBox.ButtonRole.ActionRole) self.sab.clicked.connect(self.select_all) self.snb = self.bb.addButton(_('Select &none'), QDialogButtonBox.ButtonRole.ActionRole) self.snb.clicked.connect(self.select_none) l.addWidget(self.bb) self.setWindowTitle(_('Choose folders to scan')) self.setWindowIcon(QIcon(I('devices/tablet.png'))) self.resize(600, 500)
def __init__(self, parent=None, one_line_toolbar=False, toolbar_prefs_name=None): QWidget.__init__(self, parent) self.toolbar_prefs_name = toolbar_prefs_name or self.toolbar_prefs_name self.toolbar1 = QToolBar(self) self.toolbar2 = QToolBar(self) self.toolbar3 = QToolBar(self) for i in range(1, 4): t = getattr(self, 'toolbar%d'%i) t.setIconSize(QSize(18, 18)) self.editor = EditorWidget(self) self.editor.data_changed.connect(self.data_changed) self.set_base_url = self.editor.set_base_url self.set_html = self.editor.set_html self.tabs = QTabWidget(self) self.tabs.setTabPosition(QTabWidget.TabPosition.South) self.wyswyg = QWidget(self.tabs) self.code_edit = QPlainTextEdit(self.tabs) self.source_dirty = False self.wyswyg_dirty = True self._layout = QVBoxLayout(self) self.wyswyg.layout = l = QVBoxLayout(self.wyswyg) self.setLayout(self._layout) l.setContentsMargins(0, 0, 0, 0) if one_line_toolbar: tb = QHBoxLayout() l.addLayout(tb) else: tb = l tb.addWidget(self.toolbar1) tb.addWidget(self.toolbar2) tb.addWidget(self.toolbar3) l.addWidget(self.editor) self._layout.addWidget(self.tabs) self.tabs.addTab(self.wyswyg, _('&Normal view')) self.tabs.addTab(self.code_edit, _('&HTML source')) self.tabs.currentChanged[int].connect(self.change_tab) self.highlighter = Highlighter(self.code_edit.document()) self.layout().setContentsMargins(0, 0, 0, 0) if self.toolbar_prefs_name is not None: hidden = gprefs.get(self.toolbar_prefs_name) if hidden: self.hide_toolbars() # toolbar1 {{{ self.toolbar1.addAction(self.editor.action_undo) self.toolbar1.addAction(self.editor.action_redo) self.toolbar1.addAction(self.editor.action_select_all) self.toolbar1.addAction(self.editor.action_remove_format) self.toolbar1.addAction(self.editor.action_clear) self.toolbar1.addSeparator() for x in ('copy', 'cut', 'paste'): ac = getattr(self.editor, 'action_'+x) self.toolbar1.addAction(ac) self.toolbar1.addSeparator() self.toolbar1.addAction(self.editor.action_background) # }}} # toolbar2 {{{ for x in ('', 'un'): ac = getattr(self.editor, 'action_%sordered_list'%x) self.toolbar2.addAction(ac) self.toolbar2.addSeparator() for x in ('superscript', 'subscript', 'indent', 'outdent'): self.toolbar2.addAction(getattr(self.editor, 'action_' + x)) if x in ('subscript', 'outdent'): self.toolbar2.addSeparator() self.toolbar2.addAction(self.editor.action_block_style) w = self.toolbar2.widgetForAction(self.editor.action_block_style) if hasattr(w, 'setPopupMode'): w.setPopupMode(QToolButton.ToolButtonPopupMode.InstantPopup) self.toolbar2.addAction(self.editor.action_insert_link) self.toolbar2.addAction(self.editor.action_insert_hr) # }}} # toolbar3 {{{ for x in ('bold', 'italic', 'underline', 'strikethrough'): ac = getattr(self.editor, 'action_'+x) self.toolbar3.addAction(ac) self.addAction(ac) self.toolbar3.addSeparator() for x in ('left', 'center', 'right', 'justified'): ac = getattr(self.editor, 'action_align_'+x) self.toolbar3.addAction(ac) self.toolbar3.addSeparator() self.toolbar3.addAction(self.editor.action_color) # }}} self.code_edit.textChanged.connect(self.code_dirtied) self.editor.data_changed.connect(self.wyswyg_dirtied)
def __init__(self, parent=None, one_line_toolbar=False, toolbar_prefs_name=None): QWidget.__init__(self, parent) self.toolbar_prefs_name = toolbar_prefs_name or self.toolbar_prefs_name self.toolbar = create_flow_toolbar( self, restrict_to_single_line=one_line_toolbar, icon_size=18) self.editor = EditorWidget(self) self.editor.data_changed.connect(self.data_changed) self.set_base_url = self.editor.set_base_url self.set_html = self.editor.set_html self.tabs = QTabWidget(self) self.tabs.setTabPosition(QTabWidget.TabPosition.South) self.wyswyg = QWidget(self.tabs) self.code_edit = QPlainTextEdit(self.tabs) self.source_dirty = False self.wyswyg_dirty = True self._layout = QVBoxLayout(self) self.wyswyg.layout = l = QVBoxLayout(self.wyswyg) self.setLayout(self._layout) l.setContentsMargins(0, 0, 0, 0) l.addWidget(self.toolbar) l.addWidget(self.editor) self._layout.addWidget(self.tabs) self.tabs.addTab(self.wyswyg, _('&Normal view')) self.tabs.addTab(self.code_edit, _('&HTML source')) self.tabs.currentChanged[int].connect(self.change_tab) self.highlighter = Highlighter(self.code_edit.document()) self.layout().setContentsMargins(0, 0, 0, 0) if self.toolbar_prefs_name is not None: hidden = gprefs.get(self.toolbar_prefs_name) if hidden: self.hide_toolbars() self.toolbar.add_action(self.editor.action_undo) self.toolbar.add_action(self.editor.action_redo) self.toolbar.add_action(self.editor.action_select_all) self.toolbar.add_action(self.editor.action_remove_format) self.toolbar.add_action(self.editor.action_clear) self.toolbar.add_separator() for x in ('copy', 'cut', 'paste'): ac = getattr(self.editor, 'action_' + x) self.toolbar.add_action(ac) self.toolbar.add_separator() self.toolbar.add_action(self.editor.action_background) self.toolbar.add_action(self.editor.action_color) self.toolbar.add_separator() for x in ('', 'un'): ac = getattr(self.editor, 'action_%sordered_list' % x) self.toolbar.add_action(ac) self.toolbar.add_separator() for x in ('superscript', 'subscript', 'indent', 'outdent'): self.toolbar.add_action(getattr(self.editor, 'action_' + x)) if x in ('subscript', 'outdent'): self.toolbar.add_separator() self.toolbar.add_action( self.editor.action_block_style, popup_mode=QToolButton.ToolButtonPopupMode.InstantPopup) self.toolbar.add_action(self.editor.action_insert_link) self.toolbar.add_action(self.editor.action_insert_hr) self.toolbar.add_separator() for x in ('bold', 'italic', 'underline', 'strikethrough'): ac = getattr(self.editor, 'action_' + x) self.toolbar.add_action(ac) self.addAction(ac) self.toolbar.add_separator() for x in ('left', 'center', 'right', 'justified'): ac = getattr(self.editor, 'action_align_' + x) self.toolbar.add_action(ac) self.toolbar.add_separator() QTimer.singleShot(0, self.toolbar.updateGeometry) self.code_edit.textChanged.connect(self.code_dirtied) self.editor.data_changed.connect(self.wyswyg_dirtied)
def __init__(self, recipe_model, parent=None): QDialog.__init__(self, parent) self.commit_on_change = True self.previous_urn = None self.setWindowIcon(QIcon(I('scheduler.png'))) self.l = l = QGridLayout(self) # Left panel self.h = h = QHBoxLayout() l.addLayout(h, 0, 0, 1, 1) self.search = s = SearchBox2(self) self.search.initialize('scheduler_search_history') self.search.setMinimumContentsLength(15) self.go_button = b = QToolButton(self) b.setText(_("Go")) b.clicked.connect(self.search.do_search) h.addWidget(s), h.addWidget(b) self.recipes = RecipesView(self) l.addWidget(self.recipes, 1, 0, 2, 1) self.recipe_model = recipe_model self.recipe_model.do_refresh() self.recipes.setModel(self.recipe_model) self.recipes.setFocus(Qt.FocusReason.OtherFocusReason) self.recipes.item_activated.connect(self.download_clicked) self.setWindowTitle( _("Schedule news download [{} sources]").format( self.recipe_model.showing_count)) self.search.search.connect(self.recipe_model.search) self.recipe_model.searched.connect( self.search.search_done, type=Qt.ConnectionType.QueuedConnection) self.recipe_model.searched.connect(self.search_done) # Right Panel self.scroll_area_contents = sac = QWidget(self) self.l.addWidget(sac, 0, 1, 2, 1) sac.v = v = QVBoxLayout(sac) v.setContentsMargins(0, 0, 0, 0) self.detail_box = QTabWidget(self) self.detail_box.setVisible(False) self.detail_box.setCurrentIndex(0) v.addWidget(self.detail_box) v.addItem( QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding)) # First Tab (scheduling) self.tab = QWidget() self.detail_box.addTab(self.tab, _("&Schedule")) self.tab.v = vt = QVBoxLayout(self.tab) vt.setContentsMargins(0, 0, 0, 0) self.blurb = la = QLabel('blurb') la.setWordWrap(True), la.setOpenExternalLinks(True) vt.addWidget(la) self.frame = f = QFrame(self.tab) vt.addWidget(f) f.setFrameShape(QFrame.Shape.StyledPanel) f.setFrameShadow(QFrame.Shadow.Raised) f.v = vf = QVBoxLayout(f) self.schedule = s = QCheckBox(_("&Schedule for download:"), f) self.schedule.stateChanged[int].connect(self.toggle_schedule_info) vf.addWidget(s) f.h = h = QHBoxLayout() vf.addLayout(h) self.days_of_week = QRadioButton(_("&Days of week"), f) self.days_of_month = QRadioButton(_("Da&ys of month"), f) self.every_x_days = QRadioButton(_("Every &x days"), f) self.days_of_week.setChecked(True) h.addWidget(self.days_of_week), h.addWidget( self.days_of_month), h.addWidget(self.every_x_days) self.schedule_stack = ss = QStackedWidget(f) self.schedule_widgets = [] for key in reversed(self.SCHEDULE_TYPES): self.schedule_widgets.insert(0, self.SCHEDULE_TYPES[key](self)) self.schedule_stack.insertWidget(0, self.schedule_widgets[0]) vf.addWidget(ss) self.last_downloaded = la = QLabel(f) la.setWordWrap(True) vf.addWidget(la) self.account = acc = QGroupBox(self.tab) acc.setTitle(_("&Account")) vt.addWidget(acc) acc.g = g = QGridLayout(acc) acc.unla = la = QLabel(_("&Username:"******"&Password:"******"&Show password"), self.account) spw.stateChanged[int].connect(self.set_pw_echo_mode) g.addWidget(spw, 2, 0, 1, 2) self.rla = la = QLabel( _("For the scheduling to work, you must leave calibre running.")) vt.addWidget(la) for b, c in iteritems(self.SCHEDULE_TYPES): b = getattr(self, b) b.toggled.connect(self.schedule_type_selected) b.setToolTip(textwrap.dedent(c.HELP)) # Second tab (advanced settings) self.tab2 = t2 = QWidget() self.detail_box.addTab(self.tab2, _("&Advanced")) self.tab2.g = g = QGridLayout(t2) g.setContentsMargins(0, 0, 0, 0) self.add_title_tag = tt = QCheckBox(_("Add &title as tag"), t2) g.addWidget(tt, 0, 0, 1, 2) t2.la = la = QLabel(_("&Extra tags:")) self.custom_tags = ct = QLineEdit(self) la.setBuddy(ct) g.addWidget(la), g.addWidget(ct, 1, 1) t2.la2 = la = QLabel(_("&Keep at most:")) la.setToolTip( _("Maximum number of copies (issues) of this recipe to keep. Set to 0 to keep all (disable)." )) self.keep_issues = ki = QSpinBox(t2) tt.toggled['bool'].connect(self.keep_issues.setEnabled) ki.setMaximum(100000), la.setBuddy(ki) ki.setToolTip( _("<p>When set, this option will cause calibre to keep, at most, the specified number of issues" " of this periodical. Every time a new issue is downloaded, the oldest one is deleted, if the" " total is larger than this number.\n<p>Note that this feature only works if you have the" " option to add the title as tag checked, above.\n<p>Also, the setting for deleting periodicals" " older than a number of days, below, takes priority over this setting." )) ki.setSpecialValueText(_("all issues")), ki.setSuffix(_(" issues")) g.addWidget(la), g.addWidget(ki, 2, 1) si = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding) g.addItem(si, 3, 1, 1, 1) # Bottom area self.hb = h = QHBoxLayout() self.l.addLayout(h, 2, 1, 1, 1) self.labt = la = QLabel(_("Delete downloaded &news older than:")) self.old_news = on = QSpinBox(self) on.setToolTip( _("<p>Delete downloaded news older than the specified number of days. Set to zero to disable.\n" "<p>You can also control the maximum number of issues of a specific periodical that are kept" " by clicking the Advanced tab for that periodical above.")) on.setSpecialValueText(_("never delete")), on.setSuffix(_(" days")) on.setMaximum(1000), la.setBuddy(on) on.setValue(gconf['oldest_news']) h.addWidget(la), h.addWidget(on) self.download_all_button = b = QPushButton( QIcon(I('news.png')), _("Download &all scheduled"), self) b.setToolTip(_("Download all scheduled news sources at once")) b.clicked.connect(self.download_all_clicked) self.l.addWidget(b, 3, 0, 1, 1) self.bb = bb = QDialogButtonBox( QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel, self) bb.accepted.connect(self.accept), bb.rejected.connect(self.reject) self.download_button = b = bb.addButton( _('&Download now'), QDialogButtonBox.ButtonRole.ActionRole) b.setIcon(QIcon(I('arrow-down.png'))), b.setVisible(False) b.clicked.connect(self.download_clicked) self.l.addWidget(bb, 3, 1, 1, 1) geom = gprefs.get('scheduler_dialog_geometry') if geom is not None: QApplication.instance().safe_restore_geometry(self, geom)
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()