def __InitData(self, sizeX, sizeY): self.__size = QSize(sizeX, sizeY) self.__board = QPixmap( self.__size) # Make a new QPixmap as paint board,350px * 250px self.__board.fill(Qt.white) #Fill the paint board with white self.__IsEmpty = True #board is empty by default self.EraserMode = False #eraser mode is disabled by default self.__lastPos = None self.__currentPos = QPoint(0, 0) self.__painter = QPainter() self.__thickness = 1 #default pen thickness is 1 self.__penColor = QColor("black") #default color is black self.__colorList = QColor.colorNames() #get the list of colors
def __init__(self, parent, text, mi=None, fm=None, color_field=None): QDialog.__init__(self, parent) Ui_TemplateDialog.__init__(self) self.setupUi(self) self.coloring = color_field is not None if self.coloring: cols = sorted([k for k in displayable_columns(fm)]) self.colored_field.addItems(cols) self.colored_field.setCurrentIndex(self.colored_field.findText(color_field)) colors = QColor.colorNames() colors.sort() self.color_name.addItems(colors) else: self.colored_field.setVisible(False) self.colored_field_label.setVisible(False) self.color_chooser_label.setVisible(False) self.color_name.setVisible(False) self.color_copy_button.setVisible(False) if mi: self.mi = mi else: self.mi = Metadata(None, None) # Remove help icon on title bar icon = self.windowIcon() self.setWindowFlags(self.windowFlags()&(~Qt.WindowContextHelpButtonHint)) self.setWindowIcon(icon) self.last_text = '' self.highlighter = TemplateHighlighter(self.textbox.document()) self.textbox.cursorPositionChanged.connect(self.text_cursor_changed) self.textbox.textChanged.connect(self.textbox_changed) self.textbox.setTabStopWidth(10) self.source_code.setTabStopWidth(10) self.documentation.setReadOnly(True) self.source_code.setReadOnly(True) if text is not None: self.textbox.setPlainText(text) self.buttonBox.button(QDialogButtonBox.Ok).setText(_('&OK')) self.buttonBox.button(QDialogButtonBox.Cancel).setText(_('&Cancel')) self.color_copy_button.clicked.connect(self.color_to_clipboard) try: with open(P('template-functions.json'), 'rb') as f: self.builtin_source_dict = json.load(f, encoding='utf-8') except: self.builtin_source_dict = {} self.funcs = formatter_functions().get_functions() self.builtins = formatter_functions().get_builtins() func_names = sorted(self.funcs) self.function.clear() self.function.addItem('') self.function.addItems(func_names) self.function.setCurrentIndex(0) self.function.currentIndexChanged[str].connect(self.function_changed) self.textbox_changed() self.rule = (None, '') tt = _('Template language tutorial') self.template_tutorial.setText( '<a href="http://manual.calibre-ebook.com/template_lang.html">' '%s</a>'%tt) tt = _('Template function reference') self.template_func_reference.setText( '<a href="http://manual.calibre-ebook.com/template_ref.html">' '%s</a>'%tt)
def __init__(self, parent, text, mi=None, fm=None, color_field=None, icon_field_key=None, icon_rule_kind=None): QDialog.__init__(self, parent) Ui_TemplateDialog.__init__(self) self.setupUi(self) self.coloring = color_field is not None self.iconing = icon_field_key is not None cols = [] if fm is not None: for key in sorted(displayable_columns(fm), key=lambda(k): sort_key(fm[k]['name']) if k != color_row_key else 0): if key == color_row_key and not self.coloring: continue from calibre.gui2.preferences.coloring import all_columns_string name = all_columns_string if key == color_row_key else fm[key]['name'] if name: cols.append((name, key)) self.color_layout.setVisible(False) self.icon_layout.setVisible(False) if self.coloring: self.color_layout.setVisible(True) for n1, k1 in cols: self.colored_field.addItem(n1, k1) self.colored_field.setCurrentIndex(self.colored_field.findData(color_field)) colors = QColor.colorNames() colors.sort() self.color_name.addItems(colors) elif self.iconing: self.icon_layout.setVisible(True) for n1, k1 in cols: self.icon_field.addItem(n1, k1) self.icon_file_names = [] d = os.path.join(config_dir, 'cc_icons') if os.path.exists(d): for icon_file in os.listdir(d): icon_file = icu_lower(icon_file) if os.path.exists(os.path.join(d, icon_file)): if icon_file.endswith('.png'): self.icon_file_names.append(icon_file) self.icon_file_names.sort(key=sort_key) self.update_filename_box() self.icon_with_text.setChecked(True) if icon_rule_kind == 'icon_only': self.icon_without_text.setChecked(True) self.icon_field.setCurrentIndex(self.icon_field.findData(icon_field_key)) if mi: self.mi = mi else: self.mi = Metadata(_('Title'), [_('Author')]) self.mi.author_sort = _('Author Sort') self.mi.series = _('Series') self.mi.series_index = 3 self.mi.rating = 4.0 self.mi.tags = [_('Tag 1'), _('Tag 2')] self.mi.languages = ['eng'] if fm is not None: self.mi.set_all_user_metadata(fm.custom_field_metadata()) # Remove help icon on title bar icon = self.windowIcon() self.setWindowFlags(self.windowFlags()&(~Qt.WindowContextHelpButtonHint)) self.setWindowIcon(icon) self.last_text = '' self.highlighter = TemplateHighlighter(self.textbox.document()) self.textbox.cursorPositionChanged.connect(self.text_cursor_changed) self.textbox.textChanged.connect(self.textbox_changed) self.textbox.setTabStopWidth(10) self.source_code.setTabStopWidth(10) self.documentation.setReadOnly(True) self.source_code.setReadOnly(True) if text is not None: self.textbox.setPlainText(text) self.buttonBox.button(QDialogButtonBox.Ok).setText(_('&OK')) self.buttonBox.button(QDialogButtonBox.Cancel).setText(_('&Cancel')) self.color_copy_button.clicked.connect(self.color_to_clipboard) self.filename_button.clicked.connect(self.filename_button_clicked) self.icon_copy_button.clicked.connect(self.icon_to_clipboard) try: with open(P('template-functions.json'), 'rb') as f: self.builtin_source_dict = json.load(f, encoding='utf-8') except: self.builtin_source_dict = {} self.funcs = formatter_functions().get_functions() self.builtins = formatter_functions().get_builtins() func_names = sorted(self.funcs) self.function.clear() self.function.addItem('') self.function.addItems(func_names) self.function.setCurrentIndex(0) self.function.currentIndexChanged[str].connect(self.function_changed) self.textbox_changed() self.rule = (None, '') tt = _('Template language tutorial') self.template_tutorial.setText( '<a href="http://manual.calibre-ebook.com/template_lang.html">' '%s</a>'%tt) tt = _('Template function reference') self.template_func_reference.setText( '<a href="http://manual.calibre-ebook.com/template_ref.html">' '%s</a>'%tt)
def __init__(self, fm, parent=None): QDialog.__init__(self, parent) self.fm = fm self.setWindowIcon(QIcon(I('format-fill-color.png'))) self.setWindowTitle(_('Create/edit a column coloring rule')) self.l = l = QGridLayout(self) self.setLayout(l) self.l1 = l1 = QLabel(_('Create a coloring rule by' ' filling in the boxes below')) l.addWidget(l1, 0, 0, 1, 5) self.f1 = QFrame(self) self.f1.setFrameShape(QFrame.HLine) l.addWidget(self.f1, 1, 0, 1, 5) self.l2 = l2 = QLabel(_('Set the color of the column:')) l.addWidget(l2, 2, 0) self.column_box = QComboBox(self) l.addWidget(self.column_box, 2, 1) self.l3 = l3 = QLabel(_('to')) l.addWidget(l3, 2, 2) self.color_box = QComboBox(self) self.color_label = QLabel('Sample text Sample text') self.color_label.setTextFormat(Qt.RichText) l.addWidget(self.color_box, 2, 3) l.addWidget(self.color_label, 2, 4) l.addItem(QSpacerItem(10, 10, QSizePolicy.Expanding), 2, 5) self.l4 = l4 = QLabel( _('Only if the following conditions are all satisfied:')) l.addWidget(l4, 3, 0, 1, 6) self.scroll_area = sa = QScrollArea(self) sa.setMinimumHeight(300) sa.setMinimumWidth(950) sa.setWidgetResizable(True) l.addWidget(sa, 4, 0, 1, 6) self.add_button = b = QPushButton(QIcon(I('plus.png')), _('Add another condition')) l.addWidget(b, 5, 0, 1, 6) b.clicked.connect(self.add_blank_condition) self.l5 = l5 = QLabel(_('You can disable a condition by' ' blanking all of its boxes')) l.addWidget(l5, 6, 0, 1, 6) self.bb = bb = QDialogButtonBox( QDialogButtonBox.Ok|QDialogButtonBox.Cancel) bb.accepted.connect(self.accept) bb.rejected.connect(self.reject) l.addWidget(bb, 7, 0, 1, 6) self.conditions_widget = QWidget(self) sa.setWidget(self.conditions_widget) self.conditions_widget.setLayout(QVBoxLayout()) self.conditions_widget.layout().setAlignment(Qt.AlignTop) self.conditions = [] for b in (self.column_box, self.color_box): b.setSizeAdjustPolicy(b.AdjustToMinimumContentsLengthWithIcon) b.setMinimumContentsLength(15) for key in sorted( displayable_columns(fm), key=sort_key): name = fm[key]['name'] if name: self.column_box.addItem(key, key) self.column_box.setCurrentIndex(0) self.color_box.addItems(QColor.colorNames()) self.color_box.setCurrentIndex(0) self.update_color_label() self.color_box.currentIndexChanged.connect(self.update_color_label) self.resize(self.sizeHint())
def __init__(self, parent, editing, standard_colheads, standard_colnames): QDialog.__init__(self, parent) Ui_QCreateCustomColumn.__init__(self) self.setupUi(self) self.setWindowTitle(_('Create a custom column')) self.heading_label.setText(_('Create a custom column')) # Remove help icon on title bar icon = self.windowIcon() self.setWindowFlags(self.windowFlags() & (~Qt.WindowContextHelpButtonHint)) self.setWindowIcon(icon) self.simple_error = partial(error_dialog, self, show=True, show_copy_button=False) self.button_box.accepted.connect(self.accept) self.button_box.rejected.connect(self.reject) self.shortcuts.linkActivated.connect(self.shortcut_activated) text = '<p>' + _('Quick create:') for col, name in [('isbn', _('ISBN')), ('formats', _('Formats')), ('yesno', _('Yes/No')), ('tags', _('Tags')), ('series', _('Series')), ('rating', _('Rating')), ('people', _("People's names"))]: text += ' <a href="col:%s">%s</a>,' % (col, name) text = text[:-1] self.shortcuts.setText(text) for sort_by in [_('Text'), _('Number'), _('Date'), _('Yes/No')]: self.composite_sort_by.addItem(sort_by) self.parent = parent self.editing_col = editing self.standard_colheads = standard_colheads self.standard_colnames = standard_colnames self.column_type_box.setMaxVisibleItems(len(self.column_types)) for t in self.column_types: self.column_type_box.addItem(self.column_types[t]['text']) self.column_type_box.currentIndexChanged.connect(self.datatype_changed) if not self.editing_col: self.datatype_changed() self.exec_() return self.setWindowTitle(_('Edit a custom column')) self.heading_label.setText(_('Edit a custom column')) self.shortcuts.setVisible(False) idx = parent.opt_columns.currentRow() if idx < 0: self.simple_error(_('No column selected'), _('No column has been selected')) return col = unicode( parent.opt_columns.item(idx).data(Qt.UserRole).toString()) if col not in parent.custcols: self.simple_error( '', _('Selected column is not a user-defined column')) return c = parent.custcols[col] self.column_name_box.setText(c['label']) self.column_heading_box.setText(c['name']) ct = c['datatype'] if c['is_multiple']: ct = '*' + ct self.orig_column_number = c['colnum'] self.orig_column_name = col column_numbers = dict( map(lambda x: (self.column_types[x]['datatype'], x), self.column_types)) self.column_type_box.setCurrentIndex(column_numbers[ct]) self.column_type_box.setEnabled(False) if ct == 'datetime': if c['display'].get('date_format', None): self.date_format_box.setText(c['display'].get( 'date_format', '')) elif ct in ['composite', '*composite']: self.composite_box.setText(c['display'].get( 'composite_template', '')) sb = c['display'].get('composite_sort', 'text') vals = ['text', 'number', 'date', 'bool'] if sb in vals: sb = vals.index(sb) else: sb = 0 self.composite_sort_by.setCurrentIndex(sb) self.composite_make_category.setChecked(c['display'].get( 'make_category', False)) self.composite_contains_html.setChecked(c['display'].get( 'contains_html', False)) elif ct == 'enumeration': self.enum_box.setText(','.join(c['display'].get('enum_values', []))) self.enum_colors.setText(','.join(c['display'].get( 'enum_colors', []))) elif ct in ['int', 'float']: if c['display'].get('number_format', None): self.number_format_box.setText(c['display'].get( 'number_format', '')) self.datatype_changed() if ct in ['text', 'composite', 'enumeration']: self.use_decorations.setChecked(c['display'].get( 'use_decorations', False)) elif ct == '*text': self.is_names.setChecked(c['display'].get('is_names', False)) all_colors = [unicode(s) for s in list(QColor.colorNames())] self.enum_colors_label.setToolTip('<p>' + ', '.join(all_colors) + '</p>') self.composite_contains_html.setToolTip( '<p>' + _('If checked, this column will be displayed as HTML in ' 'book details and the content server. This can be used to ' 'construct links with the template language. For example, ' 'the template ' '<pre><big><b>{title}</b></big>' '{series:| [|}{series_index:| [|]]}</pre>' 'will create a field displaying the title in bold large ' 'characters, along with the series, for example <br>"<big><b>' 'An Oblique Approach</b></big> [Belisarius [1]]". The template ' '<pre><a href="http://www.beam-ebooks.de/ebook/{identifiers' ':select(beam)}">Beam book</a></pre> ' 'will generate a link to the book on the Beam ebooks site.') + '</p>') self.exec_()
def accept(self): col = unicode(self.column_name_box.text()).strip() if not col: return self.simple_error('', _('No lookup name was provided')) if col.startswith('#'): col = col[1:] if re.match('^\w*$', col) is None or not col[0].isalpha() or col.lower() != col: return self.simple_error( '', _('The lookup name must contain only ' 'lower case letters, digits and underscores, and start with a letter' )) if col.endswith('_index'): return self.simple_error( '', _('Lookup names cannot end with _index, ' 'because these names are reserved for the index of a series column.' )) col_heading = unicode(self.column_heading_box.text()).strip() col_type = self.column_types[ self.column_type_box.currentIndex()]['datatype'] if col_type[0] == '*': col_type = col_type[1:] is_multiple = True else: is_multiple = False if not col_heading: return self.simple_error('', _('No column heading was provided')) db = self.parent.gui.library_view.model().db key = db.field_metadata.custom_field_prefix + col bad_col = False if key in self.parent.custcols: if not self.editing_col or \ self.parent.custcols[key]['colnum'] != self.orig_column_number: bad_col = True if bad_col: return self.simple_error( '', _('The lookup name %s is already used') % col) bad_head = False for t in self.parent.custcols: if self.parent.custcols[t]['name'] == col_heading: if not self.editing_col or \ self.parent.custcols[t]['colnum'] != self.orig_column_number: bad_head = True for t in self.standard_colheads: if self.standard_colheads[t] == col_heading: bad_head = True if bad_head: return self.simple_error( '', _('The heading %s is already used') % col_heading) display_dict = {} if col_type == 'datetime': if unicode(self.date_format_box.text()).strip(): display_dict = { 'date_format': unicode(self.date_format_box.text()).strip() } else: display_dict = {'date_format': None} elif col_type == 'composite': if not unicode(self.composite_box.text()).strip(): return self.simple_error( '', _('You must enter a template for' ' composite columns')) display_dict = { 'composite_template': unicode(self.composite_box.text()).strip(), 'composite_sort': ['text', 'number', 'date', 'bool'][self.composite_sort_by.currentIndex()], 'make_category': self.composite_make_category.isChecked(), 'contains_html': self.composite_contains_html.isChecked(), } elif col_type == 'enumeration': if not unicode(self.enum_box.text()).strip(): return self.simple_error( '', _('You must enter at least one' ' value for enumeration columns')) l = [ v.strip() for v in unicode(self.enum_box.text()).split(',') if v.strip() ] l_lower = [v.lower() for v in l] for i, v in enumerate(l_lower): if v in l_lower[i + 1:]: return self.simple_error( '', _('The value "{0}" is in the ' 'list more than once, perhaps with different case'). format(l[i])) c = unicode(self.enum_colors.text()) if c: c = [ v.strip() for v in unicode(self.enum_colors.text()).split(',') ] else: c = [] if len(c) != 0 and len(c) != len(l): return self.simple_error( '', _('The colors box must be empty or ' 'contain the same number of items as the value box')) for tc in c: if tc not in QColor.colorNames(): return self.simple_error( '', _('The color {0} is unknown').format(tc)) display_dict = {'enum_values': l, 'enum_colors': c} elif col_type == 'text' and is_multiple: display_dict = {'is_names': self.is_names.isChecked()} elif col_type in ['int', 'float']: if unicode(self.number_format_box.text()).strip(): display_dict = { 'number_format': unicode(self.number_format_box.text()).strip() } else: display_dict = {'number_format': None} if col_type in ['text', 'composite', 'enumeration' ] and not is_multiple: display_dict['use_decorations'] = self.use_decorations.checkState() if not self.editing_col: self.parent.custcols[key] = { 'label': col, 'name': col_heading, 'datatype': col_type, 'display': display_dict, 'normalized': None, 'colnum': None, 'is_multiple': is_multiple, } item = QListWidgetItem(col_heading, self.parent.opt_columns) item.setData(Qt.UserRole, QVariant(key)) item.setData(Qt.DecorationRole, QVariant(QIcon(I('column.png')))) item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsUserCheckable | Qt.ItemIsSelectable) item.setCheckState(Qt.Checked) else: idx = self.parent.opt_columns.currentRow() item = self.parent.opt_columns.item(idx) item.setText(col_heading) self.parent.custcols[self.orig_column_name]['label'] = col self.parent.custcols[self.orig_column_name]['name'] = col_heading self.parent.custcols[self.orig_column_name]['display'].update( display_dict) self.parent.custcols[self.orig_column_name]['*edited'] = True self.parent.custcols[self.orig_column_name]['*must_restart'] = True QDialog.accept(self)
def __init__(self, fm, pref_name, parent=None): QDialog.__init__(self, parent) self.fm = fm if pref_name == 'column_color_rules': self.rule_kind = 'color' rule_text = _('coloring') else: self.rule_kind = 'icon' rule_text = _('icon') self.setWindowIcon(QIcon(I('format-fill-color.png'))) self.setWindowTitle( _('Create/edit a column {0} rule').format(rule_text)) self.l = l = QGridLayout(self) self.setLayout(l) self.l1 = l1 = QLabel( _('Create a column {0} rule by' ' filling in the boxes below'.format(rule_text))) l.addWidget(l1, 0, 0, 1, 8) self.f1 = QFrame(self) self.f1.setFrameShape(QFrame.HLine) l.addWidget(self.f1, 1, 0, 1, 8) self.l2 = l2 = QLabel(_('Set the')) l.addWidget(l2, 2, 0) if self.rule_kind == 'color': l.addWidget(QLabel(_('color'))) else: self.kind_box = QComboBox(self) for tt, t in icon_rule_kinds: self.kind_box.addItem(tt, t) l.addWidget(self.kind_box, 2, 1) self.l3 = l3 = QLabel(_('of the column:')) l.addWidget(l3, 2, 2) self.column_box = QComboBox(self) l.addWidget(self.column_box, 2, 3) self.l4 = l4 = QLabel(_('to')) l.addWidget(l4, 2, 4) if self.rule_kind == 'color': self.color_box = QComboBox(self) self.color_label = QLabel('Sample text Sample text') self.color_label.setTextFormat(Qt.RichText) l.addWidget(self.color_box, 2, 5) l.addWidget(self.color_label, 2, 6) l.addItem(QSpacerItem(10, 10, QSizePolicy.Expanding), 2, 7) else: self.filename_box = QComboBox() self.filename_box.setInsertPolicy( self.filename_box.InsertAlphabetically) d = os.path.join(config_dir, 'cc_icons') self.icon_file_names = [] if os.path.exists(d): for icon_file in os.listdir(d): icon_file = lower(icon_file) if os.path.exists(os.path.join(d, icon_file)): if icon_file.endswith('.png'): self.icon_file_names.append(icon_file) self.icon_file_names.sort(key=sort_key) self.update_filename_box() l.addWidget(self.filename_box, 2, 5) self.filename_button = QPushButton(QIcon(I('document_open.png')), _('&Add icon')) l.addWidget(self.filename_button, 2, 6) l.addWidget(QLabel(_('Icons should be square or landscape')), 2, 7) l.setColumnStretch(7, 10) self.l5 = l5 = QLabel( _('Only if the following conditions are all satisfied:')) l.addWidget(l5, 3, 0, 1, 7) self.scroll_area = sa = QScrollArea(self) sa.setMinimumHeight(300) sa.setMinimumWidth(950) sa.setWidgetResizable(True) l.addWidget(sa, 4, 0, 1, 8) self.add_button = b = QPushButton(QIcon(I('plus.png')), _('Add another condition')) l.addWidget(b, 5, 0, 1, 8) b.clicked.connect(self.add_blank_condition) self.l6 = l6 = QLabel( _('You can disable a condition by' ' blanking all of its boxes')) l.addWidget(l6, 6, 0, 1, 8) self.bb = bb = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) bb.accepted.connect(self.accept) bb.rejected.connect(self.reject) l.addWidget(bb, 7, 0, 1, 8) self.conditions_widget = QWidget(self) sa.setWidget(self.conditions_widget) self.conditions_widget.setLayout(QVBoxLayout()) self.conditions_widget.layout().setAlignment(Qt.AlignTop) self.conditions = [] if self.rule_kind == 'color': for b in (self.column_box, self.color_box): b.setSizeAdjustPolicy(b.AdjustToMinimumContentsLengthWithIcon) b.setMinimumContentsLength(15) for key in sorted(displayable_columns(fm), key=lambda (k): sort_key(fm[k]['name']) if k != color_row_key else 0): if key == color_row_key and self.rule_kind != 'color': continue name = all_columns_string if key == color_row_key else fm[key][ 'name'] if name: self.column_box.addItem(name, key) self.column_box.setCurrentIndex(0) if self.rule_kind == 'color': self.color_box.addItems(QColor.colorNames()) self.color_box.setCurrentIndex(0) self.update_color_label() self.color_box.currentIndexChanged.connect(self.update_color_label) else: self.filename_button.clicked.connect(self.filename_button_clicked) self.resize(self.sizeHint())
def __init__(self, parent, editing, standard_colheads, standard_colnames): QDialog.__init__(self, parent) Ui_QCreateCustomColumn.__init__(self) self.setupUi(self) self.setWindowTitle(_('Create a custom column')) self.heading_label.setText(_('Create a custom column')) # Remove help icon on title bar icon = self.windowIcon() self.setWindowFlags(self.windowFlags()&(~Qt.WindowContextHelpButtonHint)) self.setWindowIcon(icon) self.simple_error = partial(error_dialog, self, show=True, show_copy_button=False) self.button_box.accepted.connect(self.accept) self.button_box.rejected.connect(self.reject) self.shortcuts.linkActivated.connect(self.shortcut_activated) text = '<p>'+_('Quick create:') for col, name in [('isbn', _('ISBN')), ('formats', _('Formats')), ('yesno', _('Yes/No')), ('tags', _('Tags')), ('series', _('Series')), ('rating', _('Rating')), ('people', _("People's names"))]: text += ' <a href="col:%s">%s</a>,'%(col, name) text = text[:-1] self.shortcuts.setText(text) for sort_by in [_('Text'), _('Number'), _('Date'), _('Yes/No')]: self.composite_sort_by.addItem(sort_by) self.parent = parent self.editing_col = editing self.standard_colheads = standard_colheads self.standard_colnames = standard_colnames self.column_type_box.setMaxVisibleItems(len(self.column_types)) for t in self.column_types: self.column_type_box.addItem(self.column_types[t]['text']) self.column_type_box.currentIndexChanged.connect(self.datatype_changed) if not self.editing_col: self.datatype_changed() self.exec_() return self.setWindowTitle(_('Edit a custom column')) self.heading_label.setText(_('Edit a custom column')) self.shortcuts.setVisible(False) idx = parent.opt_columns.currentRow() if idx < 0: self.simple_error(_('No column selected'), _('No column has been selected')) return col = unicode(parent.opt_columns.item(idx).data(Qt.UserRole).toString()) if col not in parent.custcols: self.simple_error('', _('Selected column is not a user-defined column')) return c = parent.custcols[col] self.column_name_box.setText(c['label']) self.column_heading_box.setText(c['name']) ct = c['datatype'] if c['is_multiple']: ct = '*' + ct self.orig_column_number = c['colnum'] self.orig_column_name = col column_numbers = dict(map(lambda x:(self.column_types[x]['datatype'], x), self.column_types)) self.column_type_box.setCurrentIndex(column_numbers[ct]) self.column_type_box.setEnabled(False) if ct == 'datetime': if c['display'].get('date_format', None): self.date_format_box.setText(c['display'].get('date_format', '')) elif ct in ['composite', '*composite']: self.composite_box.setText(c['display'].get('composite_template', '')) sb = c['display'].get('composite_sort', 'text') vals = ['text', 'number', 'date', 'bool'] if sb in vals: sb = vals.index(sb) else: sb = 0 self.composite_sort_by.setCurrentIndex(sb) self.composite_make_category.setChecked( c['display'].get('make_category', False)) self.composite_contains_html.setChecked( c['display'].get('contains_html', False)) elif ct == 'enumeration': self.enum_box.setText(','.join(c['display'].get('enum_values', []))) self.enum_colors.setText(','.join(c['display'].get('enum_colors', []))) elif ct in ['int', 'float']: if c['display'].get('number_format', None): self.number_format_box.setText(c['display'].get('number_format', '')) self.datatype_changed() if ct in ['text', 'composite', 'enumeration']: self.use_decorations.setChecked(c['display'].get('use_decorations', False)) elif ct == '*text': self.is_names.setChecked(c['display'].get('is_names', False)) all_colors = [unicode(s) for s in list(QColor.colorNames())] self.enum_colors_label.setToolTip('<p>' + ', '.join(all_colors) + '</p>') self.composite_contains_html.setToolTip('<p>' + _('If checked, this column will be displayed as HTML in ' 'book details and the content server. This can be used to ' 'construct links with the template language. For example, ' 'the template ' '<pre><big><b>{title}</b></big>' '{series:| [|}{series_index:| [|]]}</pre>' 'will create a field displaying the title in bold large ' 'characters, along with the series, for example <br>"<big><b>' 'An Oblique Approach</b></big> [Belisarius [1]]". The template ' '<pre><a href="http://www.beam-ebooks.de/ebook/{identifiers' ':select(beam)}">Beam book</a></pre> ' 'will generate a link to the book on the Beam ebooks site.') + '</p>') self.exec_()
def accept(self): col = unicode(self.column_name_box.text()).strip() if not col: return self.simple_error('', _('No lookup name was provided')) if col.startswith('#'): col = col[1:] if re.match('^\w*$', col) is None or not col[0].isalpha() or col.lower() != col: return self.simple_error('', _('The lookup name must contain only ' 'lower case letters, digits and underscores, and start with a letter')) if col.endswith('_index'): return self.simple_error('', _('Lookup names cannot end with _index, ' 'because these names are reserved for the index of a series column.')) col_heading = unicode(self.column_heading_box.text()).strip() col_type = self.column_types[self.column_type_box.currentIndex()]['datatype'] if col_type[0] == '*': col_type = col_type[1:] is_multiple = True else: is_multiple = False if not col_heading: return self.simple_error('', _('No column heading was provided')) db = self.parent.gui.library_view.model().db key = db.field_metadata.custom_field_prefix+col bad_col = False if key in self.parent.custcols: if not self.editing_col or \ self.parent.custcols[key]['colnum'] != self.orig_column_number: bad_col = True if bad_col: return self.simple_error('', _('The lookup name %s is already used')%col) bad_head = False for t in self.parent.custcols: if self.parent.custcols[t]['name'] == col_heading: if not self.editing_col or \ self.parent.custcols[t]['colnum'] != self.orig_column_number: bad_head = True for t in self.standard_colheads: if self.standard_colheads[t] == col_heading: bad_head = True if bad_head: return self.simple_error('', _('The heading %s is already used')%col_heading) display_dict = {} if col_type == 'datetime': if unicode(self.date_format_box.text()).strip(): display_dict = {'date_format':unicode(self.date_format_box.text()).strip()} else: display_dict = {'date_format': None} elif col_type == 'composite': if not unicode(self.composite_box.text()).strip(): return self.simple_error('', _('You must enter a template for' ' composite columns')) display_dict = {'composite_template':unicode(self.composite_box.text()).strip(), 'composite_sort': ['text', 'number', 'date', 'bool'] [self.composite_sort_by.currentIndex()], 'make_category': self.composite_make_category.isChecked(), 'contains_html': self.composite_contains_html.isChecked(), } elif col_type == 'enumeration': if not unicode(self.enum_box.text()).strip(): return self.simple_error('', _('You must enter at least one' ' value for enumeration columns')) l = [v.strip() for v in unicode(self.enum_box.text()).split(',') if v.strip()] l_lower = [v.lower() for v in l] for i,v in enumerate(l_lower): if v in l_lower[i+1:]: return self.simple_error('', _('The value "{0}" is in the ' 'list more than once, perhaps with different case').format(l[i])) c = unicode(self.enum_colors.text()) if c: c = [v.strip() for v in unicode(self.enum_colors.text()).split(',')] else: c = [] if len(c) != 0 and len(c) != len(l): return self.simple_error('', _('The colors box must be empty or ' 'contain the same number of items as the value box')) for tc in c: if tc not in QColor.colorNames(): return self.simple_error('', _('The color {0} is unknown').format(tc)) display_dict = {'enum_values': l, 'enum_colors': c} elif col_type == 'text' and is_multiple: display_dict = {'is_names': self.is_names.isChecked()} elif col_type in ['int', 'float']: if unicode(self.number_format_box.text()).strip(): display_dict = {'number_format':unicode(self.number_format_box.text()).strip()} else: display_dict = {'number_format': None} if col_type in ['text', 'composite', 'enumeration'] and not is_multiple: display_dict['use_decorations'] = self.use_decorations.checkState() if not self.editing_col: self.parent.custcols[key] = { 'label':col, 'name':col_heading, 'datatype':col_type, 'display':display_dict, 'normalized':None, 'colnum':None, 'is_multiple':is_multiple, } item = QListWidgetItem(col_heading, self.parent.opt_columns) item.setData(Qt.UserRole, QVariant(key)) item.setFlags(Qt.ItemIsEnabled|Qt.ItemIsUserCheckable|Qt.ItemIsSelectable) item.setCheckState(Qt.Checked) else: idx = self.parent.opt_columns.currentRow() item = self.parent.opt_columns.item(idx) item.setText(col_heading) self.parent.custcols[self.orig_column_name]['label'] = col self.parent.custcols[self.orig_column_name]['name'] = col_heading self.parent.custcols[self.orig_column_name]['display'].update(display_dict) self.parent.custcols[self.orig_column_name]['*edited'] = True self.parent.custcols[self.orig_column_name]['*must_restart'] = True QDialog.accept(self)
def __init__(self, parent, editing, standard_colheads, standard_colnames): QDialog.__init__(self, parent) Ui_QCreateCustomColumn.__init__(self) self.setupUi(self) self.setWindowTitle(_("Create a custom column")) self.heading_label.setText(_("Create a custom column")) # Remove help icon on title bar icon = self.windowIcon() self.setWindowFlags(self.windowFlags() & (~Qt.WindowContextHelpButtonHint)) self.setWindowIcon(icon) self.simple_error = partial(error_dialog, self, show=True, show_copy_button=False) self.button_box.accepted.connect(self.accept) self.button_box.rejected.connect(self.reject) self.shortcuts.linkActivated.connect(self.shortcut_activated) text = "<p>" + _("Quick create:") for col, name in [ ("isbn", _("ISBN")), ("formats", _("Formats")), ("yesno", _("Yes/No")), ("tags", _("Tags")), ("series", _("Series")), ("rating", _("Rating")), ("people", _("People's names")), ]: text += ' <a href="col:%s">%s</a>,' % (col, name) text = text[:-1] self.shortcuts.setText(text) for sort_by in [_("Text"), _("Number"), _("Date"), _("Yes/No")]: self.composite_sort_by.addItem(sort_by) self.parent = parent self.editing_col = editing self.standard_colheads = standard_colheads self.standard_colnames = standard_colnames self.column_type_box.setMaxVisibleItems(len(self.column_types)) for t in self.column_types: self.column_type_box.addItem(self.column_types[t]["text"]) self.column_type_box.currentIndexChanged.connect(self.datatype_changed) if not self.editing_col: self.datatype_changed() self.exec_() return self.setWindowTitle(_("Edit a custom column")) self.heading_label.setText(_("Edit a custom column")) self.shortcuts.setVisible(False) idx = parent.opt_columns.currentRow() if idx < 0: self.simple_error(_("No column selected"), _("No column has been selected")) return col = unicode(parent.opt_columns.item(idx).data(Qt.UserRole).toString()) if col not in parent.custcols: self.simple_error("", _("Selected column is not a user-defined column")) return c = parent.custcols[col] self.column_name_box.setText(c["label"]) self.column_heading_box.setText(c["name"]) ct = c["datatype"] if c["is_multiple"]: ct = "*" + ct self.orig_column_number = c["colnum"] self.orig_column_name = col column_numbers = dict(map(lambda x: (self.column_types[x]["datatype"], x), self.column_types)) self.column_type_box.setCurrentIndex(column_numbers[ct]) self.column_type_box.setEnabled(False) if ct == "datetime": if c["display"].get("date_format", None): self.date_format_box.setText(c["display"].get("date_format", "")) elif ct in ["composite", "*composite"]: self.composite_box.setText(c["display"].get("composite_template", "")) sb = c["display"].get("composite_sort", "text") vals = ["text", "number", "date", "bool"] if sb in vals: sb = vals.index(sb) else: sb = 0 self.composite_sort_by.setCurrentIndex(sb) self.composite_make_category.setChecked(c["display"].get("make_category", False)) self.composite_contains_html.setChecked(c["display"].get("contains_html", False)) elif ct == "enumeration": self.enum_box.setText(",".join(c["display"].get("enum_values", []))) self.enum_colors.setText(",".join(c["display"].get("enum_colors", []))) elif ct in ["int", "float"]: if c["display"].get("number_format", None): self.number_format_box.setText(c["display"].get("number_format", "")) self.datatype_changed() if ct in ["text", "composite", "enumeration"]: self.use_decorations.setChecked(c["display"].get("use_decorations", False)) elif ct == "*text": self.is_names.setChecked(c["display"].get("is_names", False)) all_colors = [unicode(s) for s in list(QColor.colorNames())] self.enum_colors_label.setToolTip("<p>" + ", ".join(all_colors) + "</p>") self.composite_contains_html.setToolTip( "<p>" + _( "If checked, this column will be displayed as HTML in " "book details and the content server. This can be used to " "construct links with the template language. For example, " "the template " "<pre><big><b>{title}</b></big>" "{series:| [|}{series_index:| [|]]}</pre>" "will create a field displaying the title in bold large " 'characters, along with the series, for example <br>"<big><b>' 'An Oblique Approach</b></big> [Belisarius [1]]". The template ' '<pre><a href="http://www.beam-ebooks.de/ebook/{identifiers' ':select(beam)}">Beam book</a></pre> ' "will generate a link to the book on the Beam ebooks site." ) + "</p>" ) self.exec_()
def accept(self): col = unicode(self.column_name_box.text()).strip() if not col: return self.simple_error("", _("No lookup name was provided")) if col.startswith("#"): col = col[1:] if re.match("^\w*$", col) is None or not col[0].isalpha() or col.lower() != col: return self.simple_error( "", _( "The lookup name must contain only " "lower case letters, digits and underscores, and start with a letter" ), ) if col.endswith("_index"): return self.simple_error( "", _( "Lookup names cannot end with _index, " "because these names are reserved for the index of a series column." ), ) col_heading = unicode(self.column_heading_box.text()).strip() col_type = self.column_types[self.column_type_box.currentIndex()]["datatype"] if col_type[0] == "*": col_type = col_type[1:] is_multiple = True else: is_multiple = False if not col_heading: return self.simple_error("", _("No column heading was provided")) db = self.parent.gui.library_view.model().db key = db.field_metadata.custom_field_prefix + col bad_col = False if key in self.parent.custcols: if not self.editing_col or self.parent.custcols[key]["colnum"] != self.orig_column_number: bad_col = True if bad_col: return self.simple_error("", _("The lookup name %s is already used") % col) bad_head = False for t in self.parent.custcols: if self.parent.custcols[t]["name"] == col_heading: if not self.editing_col or self.parent.custcols[t]["colnum"] != self.orig_column_number: bad_head = True for t in self.standard_colheads: if self.standard_colheads[t] == col_heading: bad_head = True if bad_head: return self.simple_error("", _("The heading %s is already used") % col_heading) display_dict = {} if col_type == "datetime": if unicode(self.date_format_box.text()).strip(): display_dict = {"date_format": unicode(self.date_format_box.text()).strip()} else: display_dict = {"date_format": None} elif col_type == "composite": if not unicode(self.composite_box.text()).strip(): return self.simple_error("", _("You must enter a template for" " composite columns")) display_dict = { "composite_template": unicode(self.composite_box.text()).strip(), "composite_sort": ["text", "number", "date", "bool"][self.composite_sort_by.currentIndex()], "make_category": self.composite_make_category.isChecked(), "contains_html": self.composite_contains_html.isChecked(), } elif col_type == "enumeration": if not unicode(self.enum_box.text()).strip(): return self.simple_error("", _("You must enter at least one" " value for enumeration columns")) l = [v.strip() for v in unicode(self.enum_box.text()).split(",") if v.strip()] l_lower = [v.lower() for v in l] for i, v in enumerate(l_lower): if v in l_lower[i + 1 :]: return self.simple_error( "", _('The value "{0}" is in the ' "list more than once, perhaps with different case").format(l[i]), ) c = unicode(self.enum_colors.text()) if c: c = [v.strip() for v in unicode(self.enum_colors.text()).split(",")] else: c = [] if len(c) != 0 and len(c) != len(l): return self.simple_error( "", _("The colors box must be empty or " "contain the same number of items as the value box") ) for tc in c: if tc not in QColor.colorNames(): return self.simple_error("", _("The color {0} is unknown").format(tc)) display_dict = {"enum_values": l, "enum_colors": c} elif col_type == "text" and is_multiple: display_dict = {"is_names": self.is_names.isChecked()} elif col_type in ["int", "float"]: if unicode(self.number_format_box.text()).strip(): display_dict = {"number_format": unicode(self.number_format_box.text()).strip()} else: display_dict = {"number_format": None} if col_type in ["text", "composite", "enumeration"] and not is_multiple: display_dict["use_decorations"] = self.use_decorations.checkState() if not self.editing_col: self.parent.custcols[key] = { "label": col, "name": col_heading, "datatype": col_type, "display": display_dict, "normalized": None, "colnum": None, "is_multiple": is_multiple, } item = QListWidgetItem(col_heading, self.parent.opt_columns) item.setData(Qt.UserRole, QVariant(key)) item.setData(Qt.DecorationRole, QVariant(QIcon(I("column.png")))) item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsUserCheckable | Qt.ItemIsSelectable) item.setCheckState(Qt.Checked) else: idx = self.parent.opt_columns.currentRow() item = self.parent.opt_columns.item(idx) item.setText(col_heading) self.parent.custcols[self.orig_column_name]["label"] = col self.parent.custcols[self.orig_column_name]["name"] = col_heading self.parent.custcols[self.orig_column_name]["display"].update(display_dict) self.parent.custcols[self.orig_column_name]["*edited"] = True self.parent.custcols[self.orig_column_name]["*must_restart"] = True QDialog.accept(self)
def __init__(self, fm, pref_name, parent=None): QDialog.__init__(self, parent) self.fm = fm if pref_name == 'column_color_rules': self.rule_kind = 'color' rule_text = _('coloring') else: self.rule_kind = 'icon' rule_text = _('icon') self.setWindowIcon(QIcon(I('format-fill-color.png'))) self.setWindowTitle(_('Create/edit a column {0} rule').format(rule_text)) self.l = l = QGridLayout(self) self.setLayout(l) self.l1 = l1 = QLabel(_('Create a column {0} rule by' ' filling in the boxes below'.format(rule_text))) l.addWidget(l1, 0, 0, 1, 8) self.f1 = QFrame(self) self.f1.setFrameShape(QFrame.HLine) l.addWidget(self.f1, 1, 0, 1, 8) self.l2 = l2 = QLabel(_('Set the')) l.addWidget(l2, 2, 0) if self.rule_kind == 'color': l.addWidget(QLabel(_('color'))) else: self.kind_box = QComboBox(self) for tt, t in icon_rule_kinds: self.kind_box.addItem(tt, t) l.addWidget(self.kind_box, 2, 1) self.l3 = l3 = QLabel(_('of the column:')) l.addWidget(l3, 2, 2) self.column_box = QComboBox(self) l.addWidget(self.column_box, 2, 3) self.l4 = l4 = QLabel(_('to')) l.addWidget(l4, 2, 4) if self.rule_kind == 'color': self.color_box = QComboBox(self) self.color_label = QLabel('Sample text Sample text') self.color_label.setTextFormat(Qt.RichText) l.addWidget(self.color_box, 2, 5) l.addWidget(self.color_label, 2, 6) l.addItem(QSpacerItem(10, 10, QSizePolicy.Expanding), 2, 7) else: self.filename_box = QComboBox() self.filename_box.setInsertPolicy(self.filename_box.InsertAlphabetically) d = os.path.join(config_dir, 'cc_icons') self.icon_file_names = [] if os.path.exists(d): for icon_file in os.listdir(d): icon_file = lower(icon_file) if os.path.exists(os.path.join(d, icon_file)): if icon_file.endswith('.png'): self.icon_file_names.append(icon_file) self.icon_file_names.sort(key=sort_key) self.update_filename_box() l.addWidget(self.filename_box, 2, 5) self.filename_button = QPushButton(QIcon(I('document_open.png')), _('&Add icon')) l.addWidget(self.filename_button, 2, 6) l.addWidget(QLabel(_('Icons should be square or landscape')), 2, 7) l.setColumnStretch(7, 10) self.l5 = l5 = QLabel( _('Only if the following conditions are all satisfied:')) l.addWidget(l5, 3, 0, 1, 7) self.scroll_area = sa = QScrollArea(self) sa.setMinimumHeight(300) sa.setMinimumWidth(950) sa.setWidgetResizable(True) l.addWidget(sa, 4, 0, 1, 8) self.add_button = b = QPushButton(QIcon(I('plus.png')), _('Add another condition')) l.addWidget(b, 5, 0, 1, 8) b.clicked.connect(self.add_blank_condition) self.l6 = l6 = QLabel(_('You can disable a condition by' ' blanking all of its boxes')) l.addWidget(l6, 6, 0, 1, 8) self.bb = bb = QDialogButtonBox( QDialogButtonBox.Ok|QDialogButtonBox.Cancel) bb.accepted.connect(self.accept) bb.rejected.connect(self.reject) l.addWidget(bb, 7, 0, 1, 8) self.conditions_widget = QWidget(self) sa.setWidget(self.conditions_widget) self.conditions_widget.setLayout(QVBoxLayout()) self.conditions_widget.layout().setAlignment(Qt.AlignTop) self.conditions = [] if self.rule_kind == 'color': for b in (self.column_box, self.color_box): b.setSizeAdjustPolicy(b.AdjustToMinimumContentsLengthWithIcon) b.setMinimumContentsLength(15) for key in sorted(displayable_columns(fm), key=lambda(k): sort_key(fm[k]['name']) if k != color_row_key else 0): if key == color_row_key and self.rule_kind != 'color': continue name = all_columns_string if key == color_row_key else fm[key]['name'] if name: self.column_box.addItem(name, key) self.column_box.setCurrentIndex(0) if self.rule_kind == 'color': self.color_box.addItems(QColor.colorNames()) self.color_box.setCurrentIndex(0) self.update_color_label() self.color_box.currentIndexChanged.connect(self.update_color_label) else: self.filename_button.clicked.connect(self.filename_button_clicked) self.resize(self.sizeHint())
def __init__(self, parent, text, mi=None, fm=None, color_field=None): QDialog.__init__(self, parent) Ui_TemplateDialog.__init__(self) self.setupUi(self) self.coloring = color_field is not None if self.coloring: cols = sorted([k for k in displayable_columns(fm)]) self.colored_field.addItems(cols) self.colored_field.setCurrentIndex( self.colored_field.findText(color_field)) colors = QColor.colorNames() colors.sort() self.color_name.addItems(colors) else: self.colored_field.setVisible(False) self.colored_field_label.setVisible(False) self.color_chooser_label.setVisible(False) self.color_name.setVisible(False) self.color_copy_button.setVisible(False) if mi: self.mi = mi else: self.mi = Metadata(None, None) # Remove help icon on title bar icon = self.windowIcon() self.setWindowFlags(self.windowFlags() & (~Qt.WindowContextHelpButtonHint)) self.setWindowIcon(icon) self.last_text = '' self.highlighter = TemplateHighlighter(self.textbox.document()) self.textbox.cursorPositionChanged.connect(self.text_cursor_changed) self.textbox.textChanged.connect(self.textbox_changed) self.textbox.setTabStopWidth(10) self.source_code.setTabStopWidth(10) self.documentation.setReadOnly(True) self.source_code.setReadOnly(True) if text is not None: self.textbox.setPlainText(text) self.buttonBox.button(QDialogButtonBox.Ok).setText(_('&OK')) self.buttonBox.button(QDialogButtonBox.Cancel).setText(_('&Cancel')) self.color_copy_button.clicked.connect(self.color_to_clipboard) try: with open(P('template-functions.json'), 'rb') as f: self.builtin_source_dict = json.load(f, encoding='utf-8') except: self.builtin_source_dict = {} self.funcs = formatter_functions().get_functions() self.builtins = formatter_functions().get_builtins() func_names = sorted(self.funcs) self.function.clear() self.function.addItem('') self.function.addItems(func_names) self.function.setCurrentIndex(0) self.function.currentIndexChanged[str].connect(self.function_changed) self.textbox_changed() self.rule = (None, '') tt = _('Template language tutorial') self.template_tutorial.setText( '<a href="http://manual.calibre-ebook.com/template_lang.html">' '%s</a>' % tt) tt = _('Template function reference') self.template_func_reference.setText( '<a href="http://manual.calibre-ebook.com/template_ref.html">' '%s</a>' % tt)
def __init__(self, parent, text, mi=None, fm=None, color_field=None, icon_field_key=None, icon_rule_kind=None): QDialog.__init__(self, parent) Ui_TemplateDialog.__init__(self) self.setupUi(self) self.coloring = color_field is not None self.iconing = icon_field_key is not None cols = [] if fm is not None: for key in sorted(displayable_columns(fm), key=lambda (k): sort_key(fm[k]['name']) if k != color_row_key else 0): if key == color_row_key and not self.coloring: continue from calibre.gui2.preferences.coloring import all_columns_string name = all_columns_string if key == color_row_key else fm[key][ 'name'] if name: cols.append((name, key)) self.color_layout.setVisible(False) self.icon_layout.setVisible(False) if self.coloring: self.color_layout.setVisible(True) for n1, k1 in cols: self.colored_field.addItem(n1, k1) self.colored_field.setCurrentIndex( self.colored_field.findData(color_field)) colors = QColor.colorNames() colors.sort() self.color_name.addItems(colors) elif self.iconing: self.icon_layout.setVisible(True) for n1, k1 in cols: self.icon_field.addItem(n1, k1) self.icon_file_names = [] d = os.path.join(config_dir, 'cc_icons') if os.path.exists(d): for icon_file in os.listdir(d): icon_file = icu_lower(icon_file) if os.path.exists(os.path.join(d, icon_file)): if icon_file.endswith('.png'): self.icon_file_names.append(icon_file) self.icon_file_names.sort(key=sort_key) self.update_filename_box() self.icon_with_text.setChecked(True) if icon_rule_kind == 'icon_only': self.icon_without_text.setChecked(True) self.icon_field.setCurrentIndex( self.icon_field.findData(icon_field_key)) if mi: self.mi = mi else: self.mi = Metadata(_('Title'), [_('Author')]) self.mi.author_sort = _('Author Sort') self.mi.series = _('Series') self.mi.series_index = 3 self.mi.rating = 4.0 self.mi.tags = [_('Tag 1'), _('Tag 2')] self.mi.languages = ['eng'] # Remove help icon on title bar icon = self.windowIcon() self.setWindowFlags(self.windowFlags() & (~Qt.WindowContextHelpButtonHint)) self.setWindowIcon(icon) self.last_text = '' self.highlighter = TemplateHighlighter(self.textbox.document()) self.textbox.cursorPositionChanged.connect(self.text_cursor_changed) self.textbox.textChanged.connect(self.textbox_changed) self.textbox.setTabStopWidth(10) self.source_code.setTabStopWidth(10) self.documentation.setReadOnly(True) self.source_code.setReadOnly(True) if text is not None: self.textbox.setPlainText(text) self.buttonBox.button(QDialogButtonBox.Ok).setText(_('&OK')) self.buttonBox.button(QDialogButtonBox.Cancel).setText(_('&Cancel')) self.color_copy_button.clicked.connect(self.color_to_clipboard) self.filename_button.clicked.connect(self.filename_button_clicked) self.icon_copy_button.clicked.connect(self.icon_to_clipboard) try: with open(P('template-functions.json'), 'rb') as f: self.builtin_source_dict = json.load(f, encoding='utf-8') except: self.builtin_source_dict = {} self.funcs = formatter_functions().get_functions() self.builtins = formatter_functions().get_builtins() func_names = sorted(self.funcs) self.function.clear() self.function.addItem('') self.function.addItems(func_names) self.function.setCurrentIndex(0) self.function.currentIndexChanged[str].connect(self.function_changed) self.textbox_changed() self.rule = (None, '') tt = _('Template language tutorial') self.template_tutorial.setText( '<a href="http://manual.calibre-ebook.com/template_lang.html">' '%s</a>' % tt) tt = _('Template function reference') self.template_func_reference.setText( '<a href="http://manual.calibre-ebook.com/template_ref.html">' '%s</a>' % tt)