class RemoveDialog(Dialog): def __init__(self, parent): from calibre_plugins.diaps_toolbag.span_div_config import plugin_prefs as prefs self.criteria = None self.prefs = prefs self.parent = parent self.help_file_name = '{0}_span_div_help.html'.format(PLUGIN_SAFE_NAME) self.taglist = TAGLIST Dialog.__init__(self, _('Edit Spans & Divs'), 'toolbag_spans_divs_dialog', parent) def setup_ui(self): DELETE_STR = _('Delete') MODIFY_STR = _('Modify') NO_ATTRIB_STR = _('No attributes ("naked" tag)') self.NO_CHANGE_STR = _('No change') layout = QVBoxLayout(self) self.setLayout(layout) help_layout = QHBoxLayout() layout.addLayout(help_layout) # Add hyperlink to a help file at the right. We will replace the correct name when it is clicked. help_label = QLabel('<a href="http://www.foo.com/">Plugin Help</a>', self) help_label.setTextInteractionFlags(Qt.LinksAccessibleByMouse | Qt.LinksAccessibleByKeyboard) help_label.setAlignment(Qt.AlignRight) help_label.linkActivated.connect(self.help_link_activated) help_layout.addWidget(help_label) action_layout = QHBoxLayout() layout.addLayout(action_layout) label = QLabel(_('Action type:'), self) action_layout.addWidget(label) self.action_combo = QComboBox() action_layout.addWidget(self.action_combo) self.action_combo.addItems([DELETE_STR, MODIFY_STR]) self.action_combo.currentIndexChanged.connect(self.update_gui) tag_layout = QHBoxLayout() layout.addLayout(tag_layout) label = QLabel(_('Tag name:'), self) tag_layout.addWidget(label) self.tag_combo = QComboBox() tag_layout.addWidget(self.tag_combo) self.tag_combo.addItems(self.taglist) self.tag_combo.currentIndexChanged.connect(self.update_gui) attr_layout = QHBoxLayout() layout.addLayout(attr_layout) label = QLabel(_('Having the attribute:'), self) attr_layout.addWidget(label) self.attr_combo = QComboBox() attr_layout.addWidget(self.attr_combo) self.attr_combo.addItems(self.prefs['attrs']) self.attr_combo.addItem(NO_ATTRIB_STR) self.attr_combo.currentIndexChanged.connect(self.update_gui) srch_layout = QHBoxLayout() layout.addLayout(srch_layout) label = QLabel(_("Whose value is (no quotes):"), self) srch_layout.addWidget(label) self.srch_txt = QLineEdit('', self) srch_layout.addWidget(self.srch_txt) self.srch_method = QCheckBox(_('Regex'), self) srch_layout.addWidget(self.srch_method) newtag_layout = QHBoxLayout() layout.addLayout(newtag_layout) label = QLabel(_('Change tag to:'), self) newtag_layout.addWidget(label) self.newtag_combo = QComboBox() newtag_layout.addWidget(self.newtag_combo) self.newtag_combo.addItem(self.NO_CHANGE_STR) self.newtag_combo.addItems(self.prefs['{}_changes'.format(unicode(self.tag_combo.currentText()))]) if self.action_combo.currentIndex() == 0: self.newtag_combo.setDisabled(True) newattr_layout = QVBoxLayout() layout.addLayout(newattr_layout) label = QLabel(_('New attribute string to insert (entire):'), self) newattr_layout.addWidget(label) self.newattr_txt = QLineEdit('', self) newattr_layout.addWidget(self.newattr_txt) self.copy_attr = QCheckBox(_('Copy existing attribute string'), self) self.copy_attr.stateChanged.connect(self.update_txt_box) newattr_layout.addWidget(self.copy_attr) if self.action_combo.currentIndex() == 0: self.copy_attr.setDisabled(True) self.newattr_txt.setDisabled(True) layout.addSpacing(10) button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) button_box.accepted.connect(self._ok_clicked) button_box.rejected.connect(self.reject) layout.addWidget(button_box) def update_gui(self): if self.attr_combo.currentIndex() == self.attr_combo.count()-1: self.srch_txt.clear() self.srch_txt.setDisabled(True) self.srch_method.setChecked(False) self.srch_method.setDisabled(True) else: self.srch_txt.setDisabled(False) self.srch_method.setDisabled(False) self.newtag_combo.clear() self.newtag_combo.addItem(self.NO_CHANGE_STR) self.newtag_combo.addItems(self.prefs['{}_changes'.format(unicode(self.tag_combo.currentText()))]) if self.action_combo.currentIndex() == 0: self.newtag_combo.setCurrentIndex(0) self.newtag_combo.setDisabled(True) self.newattr_txt.clear() self.newattr_txt.setDisabled(True) self.copy_attr.setChecked(False) self.copy_attr.setDisabled(True) else: self.newtag_combo.setDisabled(False) self.newattr_txt.setDisabled(False) self.copy_attr.setDisabled(False) def update_txt_box(self): if self.copy_attr.isChecked(): self.newattr_txt.clear() self.newattr_txt.setDisabled(True) else: self.newattr_txt.setDisabled(False) def _ok_clicked(self): if self.action_combo.currentIndex() == 0: action = 'delete' else: action = 'modify' if self.attr_combo.currentIndex() == self.attr_combo.count()-1: attribute = None else: attribute = unicode(self.attr_combo.currentText()) srch_str = unicode(self.srch_txt.displayText()) if not len(srch_str): srch_str = None if srch_str is None and attribute is not None: return error_dialog(self.parent, _('Error'), '<p>{0}'.format( _('Must enter a value for the attribute selected')), det_msg='', show=True) srch_method = 'normal' if self.srch_method.isChecked(): srch_method = 'regex' if self.newtag_combo.currentIndex() == 0: newtag = None else: newtag = unicode(self.newtag_combo.currentText()) if action == 'modify' and newtag is None and self.copy_attr.isChecked(): return error_dialog(self.parent, _('Error'), '<p>{0}'.format( _('What--exactly--would that achieve?')), det_msg='', show=True) new_str = unicode(self.newattr_txt.displayText()) copy_attr = False if self.copy_attr.isChecked(): copy_attr = True if not len(new_str): new_str = '' self.criteria = (srch_str, srch_method, unicode(self.tag_combo.currentText()), attribute, action, newtag, new_str, copy_attr) self.accept() def getCriteria(self): return self.criteria def help_link_activated(self, url): def get_help_file_resource(): # Copy the HTML helpfile to the plugin directory each time the # link is clicked in case the helpfile is updated in newer plugins. file_path = os.path.join(config_dir, 'plugins', self.help_file_name) with open(file_path,'w') as f: f.write(load_resource('resources/{}'.format(self.help_file_name))) return file_path url = 'file:///' + get_help_file_resource() open_url(QUrl(url))
class PunctDialog(Dialog): def __init__(self, parent): self.prefs = self.prefsPrep() self.criteria = None self.parent = parent self.help_file_name = '{0}_smarten_help.html'.format(PLUGIN_SAFE_NAME) Dialog.__init__(self, _('Smarten Punctuation (the sequel)'), 'toolbag_smarter_dialog', parent) def setup_ui(self,): layout = QVBoxLayout(self) self.setLayout(layout) help_layout = QHBoxLayout() layout.addLayout(help_layout) # Add hyperlink to a help file at the right. We will replace the correct name when it is clicked. help_label = QLabel('<a href="http://www.foo.com/">Plugin Help</a>', self) help_label.setTextInteractionFlags(Qt.LinksAccessibleByMouse | Qt.LinksAccessibleByKeyboard) help_label.setAlignment(Qt.AlignRight) help_label.linkActivated.connect(self.help_link_activated) help_layout.addWidget(help_label) self.edu_quotes = QCheckBox(_('Smarten Quotation marks'), self) layout.addWidget(self.edu_quotes) self.edu_quotes.setChecked(self.prefs['edu_quotes']) self.edu_quotes.stateChanged.connect(self.quotes_gui_changes) exceptions_group_box = QGroupBox('', self) layout.addWidget(exceptions_group_box) exceptions_group_box_layout = QVBoxLayout() exceptions_group_box.setLayout(exceptions_group_box_layout) self.use_file = QCheckBox(_('Use custom apostrophe exceptions file'), self) exceptions_group_box_layout.addWidget(self.use_file) if not self.edu_quotes.isChecked(): self.use_file.setDisabled(True) else: self.use_file.setChecked(self.prefs['use_file']) self.use_file.stateChanged.connect(self.use_file_gui_changes) path_layout = QHBoxLayout() exceptions_group_box_layout.addLayout(path_layout) self.file_path = QLineEdit('', self) if not self.edu_quotes.isChecked() and not self.use_file.isChecked(): self.file_path.setReadOnly(True) else: self.file_path.setText(self.prefs['file_path']) self.file_path.setReadOnly(True) path_layout.addWidget(self.file_path) self.file_button = QPushButton('...', self) self.file_button.clicked.connect(self.getFile) path_layout.addWidget(self.file_button) if not self.edu_quotes.isChecked() and not self.use_file.isChecked(): self.file_button.setDisabled(True) combo_layout = QVBoxLayout() layout.addLayout(combo_layout) label = QLabel(_('(em|en)-dash settings'), self) combo_layout.addWidget(label) self.dashes_combo = QComboBox() combo_layout.addWidget(self.dashes_combo) values = [_('Do not educate dashes'), _('-- = emdash (no endash support)'), _('-- = emdash | --- = endash'), _('--- = emdash | -- = endash')] self.dashes_combo.addItems(values) self.dashes_combo.setCurrentIndex(self.prefs['dashes']) # self.dashes_combo.currentIndexChanged.connect(self.update_gui) self.ellipses = QCheckBox(_('Smarten ellipses'), self) layout.addWidget(self.ellipses) self.ellipses.setChecked(self.prefs['ellipses']) self.unicode = QCheckBox(_('Educate with unicode characters (instead of entities)'), self) layout.addWidget(self.unicode) self.unicode.setChecked(self.prefs['unicode']) layout.addSpacing(10) button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) button_box.accepted.connect(self._ok_clicked) button_box.rejected.connect(self.reject) layout.addWidget(button_box) def getFile(self): unique_dlg_name = '{0}plugin:smarter_choose_dialog'.format(PLUGIN_SAFE_NAME) caption = _('Select custom apostrophe exceptions file') filters = [('Text files', ['txt'])] c = choose_files(self, unique_dlg_name, caption, filters, all_files=True) if c: self.file_path.setReadOnly(False) self.file_path.setText(c[0]) self.file_path.setReadOnly(True) def _ok_clicked(self): quotes_setting = 'q' if self.edu_quotes.isChecked() else '' if self.dashes_combo.currentIndex() == 0: dash_setting = '' elif self.dashes_combo.currentIndex() == 1: dash_setting = 'd' elif self.dashes_combo.currentIndex() == 2: dash_setting = 'i' elif self.dashes_combo.currentIndex() == 3: dash_setting = 'D' else: dash_setting = '' ellipses_setting = 'e' if self.ellipses.isChecked() else '' smarty_attr = quotes_setting + dash_setting + ellipses_setting if smarty_attr == '': smarty_attr = '0' self.file_path.setReadOnly(False) if self.use_file.isChecked() and not len(self.file_path.displayText()): self.file_path.setReadOnly(True) return error_dialog(self.parent, _('Error'), '<p>' + _('Must select a custom exception file'), det_msg='', show=True) if self.use_file.isChecked(): apos_exception_file = unicode(self.file_path.displayText()) if not os.path.exists(apos_exception_file): apos_exception_file = None else: apos_exception_file = None self.file_path.setReadOnly(True) apos_words_list = [] if apos_exception_file is not None: apos_words_list = self.parseExceptionsFile(os.path.normpath(apos_exception_file)) self.criteria = (smarty_attr, self.unicode.isChecked(), apos_words_list) self.savePrefs() self.accept() def getCriteria(self): return self.criteria def quotes_gui_changes(self): if self.edu_quotes.isChecked(): self.use_file.setDisabled(False) if self.use_file.isChecked(): self.file_button.setDisabled(False) else: self.use_file.setChecked(False) self.file_path.setReadOnly(False) self.file_path.clear() self.file_path.setReadOnly(True) self.use_file.setDisabled(True) self.file_button.setDisabled(True) def use_file_gui_changes(self): if self.use_file.isChecked(): self.file_button.setDisabled(False) else: self.file_path.setReadOnly(False) self.file_path.clear() self.file_path.setReadOnly(True) self.file_button.setDisabled(True) def prefsPrep(self): from calibre.utils.config import JSONConfig plugin_prefs = JSONConfig('plugins/{0}_SmarterPunct_settings'.format(PLUGIN_SAFE_NAME)) plugin_prefs.defaults['edu_quotes'] = True plugin_prefs.defaults['use_file'] = False plugin_prefs.defaults['file_path'] = '' plugin_prefs.defaults['dashes'] = 1 plugin_prefs.defaults['ellipses'] = True plugin_prefs.defaults['unicode'] = True return plugin_prefs def savePrefs(self): self.prefs['edu_quotes'] = self.edu_quotes.isChecked() self.prefs['use_file'] = self.use_file.isChecked() self.prefs['file_path'] = unicode(self.file_path.displayText()) if len(self.file_path.displayText()) else '' self.prefs['dashes'] = self.dashes_combo.currentIndex() self.prefs['ellipses'] = self.ellipses.isChecked() self.prefs['unicode'] = self.unicode.isChecked() def help_link_activated(self, url): def get_help_file_resource(): # Copy the HTML helpfile to the plugin directory each time the # link is clicked in case the helpfile is updated in newer plugins. file_path = os.path.join(config_dir, 'plugins', self.help_file_name) with open(file_path,'w') as f: f.write(load_resource('resources/{}'.format(self.help_file_name))) return file_path url = 'file:///' + get_help_file_resource() open_url(QUrl(url)) def parseExceptionsFile(self, filename): import os, codecs, chardet words_list = [] bytes = min(32, os.path.getsize(filename)) raw = open(filename, 'rb').read(bytes) if raw.startswith(codecs.BOM_UTF8): enc = 'utf-8-sig' else: result = chardet.detect(raw) enc = result['encoding'] try: with codecs.open(filename, encoding=enc, mode='r') as fd: words_list = [line.rstrip() for line in fd] words_list = filter(None, words_list) print('Exceptions list:', words_list) except: pass return words_list