diff --git a/src/calibre/ebooks/conversion/plumber.py b/src/calibre/ebooks/conversion/plumber.py index 88e56c4633..f873b5485d 100644 --- a/src/calibre/ebooks/conversion/plumber.py +++ b/src/calibre/ebooks/conversion/plumber.py @@ -628,7 +628,17 @@ OptionRecommendation(name='sr3_replace', OptionRecommendation(name='search_replace', recommended_value='[]', level=OptionRecommendation.LOW, - help=_('Modify the document text and structure using user defined patterns.')), + help=_('Modify the document text and structure using user defined patterns.' + 'This option accepts parameters in two forms:\n' + '1.file:\n' + 'The file should contain alternating lines or search/replace strings:\n' + ' \n' + ' \n' + ' \n' + ' \n' + 'Files saved through the user interface dialog can be used with this option.\n' + '2.json:= 0: @@ -122,14 +119,40 @@ class SearchAndReplaceWidget(Widget, Ui_Form): self.sr_search.set_doc(doc) def pre_commit_check(self): - for row in xrange(0, self.search_replace.rowCount()): + + + definitions = self.get_definitions() + + # Verify the search/replace in the edit widgets has been + # included to the list of search/replace definitions + + edit_search = self.sr_search.regex + + if edit_search: + edit_replace = unicode(self.sr_replace.text()) + found = False + for search, replace in definitions: + if search == edit_search and replace == edit_replace: + found = True + break + if not found: + msgBox = QMessageBox(self) + msgBox.setText(_('The search / replace definition being edited has not been added to the list of definitions')) + msgBox.setInformativeText(_('Do you wish to continue with the conversion (the definition will not be used)?')) + msgBox.setStandardButtons(QMessageBox.Yes | QMessageBox.No) + msgBox.setDefaultButton(QMessageBox.No) + if msgBox.exec_() != QMessageBox.Yes: + return False + + # Verify all search expressions are valid + for search, replace in definitions: try: - pat = unicode(self.search_replace.item(row,0).text()) - re.compile(pat) + re.compile(search) except Exception as err: error_dialog(self, _('Invalid regular expression'), _('Invalid regular expression: %s')%err, show=True) return False + return True # Options @@ -171,14 +194,16 @@ class SearchAndReplaceWidget(Widget, Ui_Form): def get_value_handler(self, g): if g != self.opt_search_replace: return None - + return search_replace_option.encodeJson(self.get_definitions()) + + def get_definitions(self): ans = [] for row in xrange(0, self.search_replace.rowCount()): colItems = [] for col in xrange(0, self.search_replace.columnCount()): colItems.append(unicode(self.search_replace.item(row, col).text())) ans.append(colItems) - return json.dumps(ans) + return ans def set_value_handler(self, g, val): if g != self.opt_search_replace: @@ -186,7 +211,7 @@ class SearchAndReplaceWidget(Widget, Ui_Form): return True try: - rowItems = json.loads(val) + rowItems = search_replace_option.decode(val) if not isinstance(rowItems, list): rowItems = [] except: diff --git a/src/calibre/gui2/convert/search_and_replace.ui b/src/calibre/gui2/convert/search_and_replace.ui index 47180ed702..41063a7eb3 100644 --- a/src/calibre/gui2/convert/search_and_replace.ui +++ b/src/calibre/gui2/convert/search_and_replace.ui @@ -32,7 +32,7 @@ - First expression + Search/Replace Definition Edit @@ -147,7 +147,7 @@ - <p>Search and replace uses <i>regular expressions</i>. See the <a href="http://manual.calibre-ebook.com/regexp.html">regular expressions tutorial</a> to get started with regular expressions. Also clicking the wizard buttons below will allow you to test your regular expression against the current input document. + <p>Search and replace uses <i>regular expressions</i>. See the <a href="http://manual.calibre-ebook.com/regexp.html">regular expressions tutorial</a> to get started with regular expressions. Also clicking the wizard button below will allow you to test your regular expression against the current input document. true