From 7ea167eec1915428a6960f1f3caddb20de75e68e Mon Sep 17 00:00:00 2001 From: Eli Algranti Date: Thu, 12 Apr 2012 13:18:43 +1000 Subject: [PATCH] Returned all the original options sr?_search and sr?_replace and added backward compatibility to search_and_replace.py --- src/calibre/ebooks/conversion/cli.py | 5 +- src/calibre/ebooks/conversion/plumber.py | 26 +++ .../gui2/convert/search_and_replace.py | 150 +++++++++++++----- .../gui2/convert/search_and_replace.ui | 2 +- 4 files changed, 145 insertions(+), 38 deletions(-) diff --git a/src/calibre/ebooks/conversion/cli.py b/src/calibre/ebooks/conversion/cli.py index a80ddfb839..92f161bb33 100644 --- a/src/calibre/ebooks/conversion/cli.py +++ b/src/calibre/ebooks/conversion/cli.py @@ -156,7 +156,10 @@ def add_pipeline_options(parser, plumber): 'SEARCH AND REPLACE' : ( _('Modify the document text and structure using user defined patterns.'), [ - 'search_replace', + 'sr1_search', 'sr1_replace', + 'sr2_search', 'sr2_replace', + 'sr3_search', 'sr3_replace', + 'search_replace', ] ), diff --git a/src/calibre/ebooks/conversion/plumber.py b/src/calibre/ebooks/conversion/plumber.py index 62abc30fbd..88e56c4633 100644 --- a/src/calibre/ebooks/conversion/plumber.py +++ b/src/calibre/ebooks/conversion/plumber.py @@ -599,6 +599,32 @@ OptionRecommendation(name='renumber_headings', help=_('Looks for occurrences of sequential

or

tags. ' 'The tags are renumbered to prevent splitting in the middle ' 'of chapter headings.')), +OptionRecommendation(name='sr1_search', + recommended_value='', level=OptionRecommendation.LOW, + help=_('Search pattern (regular expression) to be replaced with ' + 'sr1-replace.')), + +OptionRecommendation(name='sr1_replace', + recommended_value='', level=OptionRecommendation.LOW, + help=_('Replacement to replace the text found with sr1-search.')), + +OptionRecommendation(name='sr2_search', + recommended_value='', level=OptionRecommendation.LOW, + help=_('Search pattern (regular expression) to be replaced with ' + 'sr2-replace.')), + +OptionRecommendation(name='sr2_replace', + recommended_value='', level=OptionRecommendation.LOW, + help=_('Replacement to replace the text found with sr2-search.')), + +OptionRecommendation(name='sr3_search', + recommended_value='', level=OptionRecommendation.LOW, + help=_('Search pattern (regular expression) to be replaced with ' + 'sr3-replace.')), + +OptionRecommendation(name='sr3_replace', + recommended_value='', level=OptionRecommendation.LOW, + help=_('Replacement to replace the text found with sr3-search.')), OptionRecommendation(name='search_replace', recommended_value='[]', level=OptionRecommendation.LOW, diff --git a/src/calibre/gui2/convert/search_and_replace.py b/src/calibre/gui2/convert/search_and_replace.py index d0ad43e1b4..7389482450 100644 --- a/src/calibre/gui2/convert/search_and_replace.py +++ b/src/calibre/gui2/convert/search_and_replace.py @@ -22,7 +22,10 @@ class SearchAndReplaceWidget(Widget, Ui_Form): def __init__(self, parent, get_option, get_help, db=None, book_id=None): Widget.__init__(self, parent, - ['search_replace'] + ['search_replace', + 'sr1_search', 'sr1_replace', + 'sr2_search', 'sr2_replace', + 'sr3_search', 'sr3_replace'] ) self.db, self.book_id = db, book_id @@ -34,65 +37,70 @@ class SearchAndReplaceWidget(Widget, Ui_Form): proto = QTableWidgetItem() proto.setFlags(Qt.ItemFlags(Qt.ItemIsSelectable + Qt.ItemIsEnabled)) - self.opt_search_replace.setItemPrototype(proto) - self.opt_search_replace.setColumnCount(2) - self.opt_search_replace.setColumnWidth(0, 300) - self.opt_search_replace.setColumnWidth(1, 300) - self.opt_search_replace.setHorizontalHeaderLabels(['Search Expression', 'Replacement']) + self.search_replace.setItemPrototype(proto) + self.search_replace.setColumnCount(2) + self.search_replace.setColumnWidth(0, 300) + self.search_replace.setColumnWidth(1, 300) + self.search_replace.setHorizontalHeaderLabels(['Search Expression', 'Replacement']) self.connect(self.sr_add, SIGNAL('clicked()'), self.sr_add_clicked) self.connect(self.sr_change, SIGNAL('clicked()'), self.sr_change_clicked) self.connect(self.sr_remove, SIGNAL('clicked()'), self.sr_remove_clicked) self.connect(self.sr_load, SIGNAL('clicked()'), self.sr_load_clicked) self.connect(self.sr_save, SIGNAL('clicked()'), self.sr_save_clicked) - self.connect(self.opt_search_replace, SIGNAL('currentCellChanged(int, int, int, int)'), self.sr_currentCellChanged) + self.connect(self.search_replace, SIGNAL('currentCellChanged(int, int, int, int)'), self.sr_currentCellChanged) self.initialize_options(get_option, get_help, db, book_id) def sr_add_clicked(self): if self.sr_search.regex: - self.opt_search_replace.insertRow(0) - newItem = self.opt_search_replace.itemPrototype().clone() - newItem.setText(self.sr_search.regex) - self.opt_search_replace.setItem(0,0, newItem) - newItem = self.opt_search_replace.itemPrototype().clone() - newItem.setText(self.sr_replace.text()) - self.opt_search_replace.setItem(0,1, newItem) - self.opt_search_replace.setCurrentCell(0, 0) + row = self.sr_add_row(self.sr_search.regex, self.sr_replace.text()) + self.search_replace.setCurrentCell(row, 0) + + def sr_add_row(self, search, replace): + row = self.search_replace.rowCount() + self.search_replace.setRowCount(row + 1) + newItem = self.search_replace.itemPrototype().clone() + newItem.setText(search) + self.search_replace.setItem(row,0, newItem) + newItem = self.search_replace.itemPrototype().clone() + newItem.setText(replace) + self.search_replace.setItem(row,1, newItem) + return row def sr_change_clicked(self): - row = self.opt_search_replace.currentRow() + row = self.search_replace.currentRow() if row >= 0: - self.opt_search_replace.item(row, 0).setText(self.sr_search.regex) - self.opt_search_replace.item(row, 1).setText(self.sr_replace.text()) - self.opt_search_replace.setCurrentCell(row, 0) + self.search_replace.item(row, 0).setText(self.sr_search.regex) + self.search_replace.item(row, 1).setText(self.sr_replace.text()) + self.search_replace.setCurrentCell(row, 0) def sr_remove_clicked(self): - row = self.opt_search_replace.currentRow() + row = self.search_replace.currentRow() if row >= 0: - self.opt_search_replace.removeRow(row) - self.opt_search_replace.setCurrentCell(row-1, 0) + self.search_replace.removeRow(row) + self.search_replace.setCurrentCell(row-1, 0) def sr_load_clicked(self): filename = QFileDialog.getOpenFileName(self, 'Load Calibre Search-Replace definitions file', '.', 'Calibre Search-Replace definitions file (*.csr)') if filename: with open(filename, 'r') as f: val = f.read() - self.set_value(self.opt_search_replace, val) + self.set_value(self.search_replace, val) def sr_save_clicked(self): filename = QFileDialog.getSaveFileName(self, 'Save Calibre Search-Replace definitions file', '.', 'Calibre Search-Replace definitions file (*.csr)') if filename: with open(filename, 'w') as f: - val = self.get_value(self.opt_search_replace) + val = self.get_value(self.search_replace) f.write(val) def sr_currentCellChanged(self, row, column, previousRow, previousColumn) : if row >= 0: self.sr_change.setEnabled(True) self.sr_remove.setEnabled(True) - self.sr_search.set_regex(self.opt_search_replace.item(row, 0).text()) - self.sr_replace.setText(self.opt_search_replace.item(row, 1).text()) + self.sr_search.set_regex(self.search_replace.item(row, 0).text()) + self.sr_replace.setText(self.search_replace.item(row, 1).text()) else: self.sr_change.setEnabled(False) self.sr_remove.setEnabled(False) @@ -114,9 +122,9 @@ class SearchAndReplaceWidget(Widget, Ui_Form): self.sr_search.set_doc(doc) def pre_commit_check(self): - for row in xrange(0, self.opt_search_replace.rowCount()): + for row in xrange(0, self.search_replace.rowCount()): try: - pat = unicode(self.opt_search_replace.item(row,0).text()) + pat = unicode(self.search_replace.item(row,0).text()) re.compile(pat) except Exception as err: error_dialog(self, _('Invalid regular expression'), @@ -124,23 +132,59 @@ class SearchAndReplaceWidget(Widget, Ui_Form): return False return True + # Options + @property + def opt_search_replace(self): + return 'search_replace' + + @property + def opt_sr1_search(self): + return 'sr1_search' + + @property + def opt_sr1_replace(self): + return 'sr1_replace' + + @property + def opt_sr2_search(self): + return 'sr2_search' + + @property + def opt_sr2_replace(self): + return 'sr2_replace' + + @property + def opt_sr3_search(self): + return 'sr3_search' + + @property + def opt_sr3_replace(self): + return 'sr3_replace' + # Options handling def connect_gui_obj_handler(self, g, slot): - if isinstance(g, QTableWidget): - g.cellChanged.connect(slot) + if g == self.opt_search_replace: + self.search_replace.cellChanged.connect(slot) def get_value_handler(self, g): + if g != self.opt_search_replace: + return None + ans = [] - for row in xrange(0, g.rowCount()): + for row in xrange(0, self.search_replace.rowCount()): colItems = [] - for col in xrange(0, g.columnCount()): - colItems.append(unicode(g.item(row, col).text())) + 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) def set_value_handler(self, g, val): + if g != self.opt_search_replace: + self.handle_legacy(g, val) + return True + try: rowItems = json.loads(val) if not isinstance(rowItems, list): @@ -148,11 +192,45 @@ class SearchAndReplaceWidget(Widget, Ui_Form): except: rowItems = [] - g.setRowCount(len(rowItems)) + if len(rowItems) == 0: + return True + + self.search_replace.setRowCount(len(rowItems)) for row, colItems in enumerate(rowItems): for col, cellValue in enumerate(colItems): - newItem = g.itemPrototype().clone() + newItem = self.search_replace.itemPrototype().clone() newItem.setText(cellValue) - g.setItem(row,col, newItem) + self.search_replace.setItem(row,col, newItem) return True + + def handle_legacy(self, g, val): + ''' + Handles legacy search/replace options sr1_search, sr1_replace, + sr2_search, sr2_replace, sr3_search, sr3_replace. + Before introducing the search_replace option only three search/replace + definitions could be made. These where stored in the options named above. + This function is for backward compatibility with saved options and for + compatibility with setting sr* options in the CLI. + ''' + + if not val: return + + row = int(g[2]) - 1 # the row to set in the search_replace table is 0 for sr1_*, 1 for sr2_*, etc + col = (0 if g[4] == 's' else 1) # the fourth character in g is 's' for search options and 'r' for replace options + + # add any missing rows + while self.search_replace.rowCount() < row+1: + self.sr_add_row('', '') + + # set the value + self.search_replace.item(row, col).setText(val) + + def setup_help_handler(self, g, help): + if g != self.opt_search_replace: + return True + + self.search_replace._help = help + self.setup_widget_help(self.search_replace) + return True + diff --git a/src/calibre/gui2/convert/search_and_replace.ui b/src/calibre/gui2/convert/search_and_replace.ui index af276d7992..47180ed702 100644 --- a/src/calibre/gui2/convert/search_and_replace.ui +++ b/src/calibre/gui2/convert/search_and_replace.ui @@ -129,7 +129,7 @@ - + 0