From 0c9dbec71f9da7095b387f06af9cebcb8444d4f8 Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Thu, 3 Feb 2011 10:33:40 +0000 Subject: [PATCH] Ticket #8732: Search and replace title sort --- src/calibre/gui2/dialogs/metadata_bulk.py | 65 ++++++++++++++++------- src/calibre/gui2/dialogs/metadata_bulk.ui | 11 ++++ src/calibre/library/database2.py | 4 -- 3 files changed, 56 insertions(+), 24 deletions(-) diff --git a/src/calibre/gui2/dialogs/metadata_bulk.py b/src/calibre/gui2/dialogs/metadata_bulk.py index 12f49baaca..8e098ef17b 100644 --- a/src/calibre/gui2/dialogs/metadata_bulk.py +++ b/src/calibre/gui2/dialogs/metadata_bulk.py @@ -11,7 +11,7 @@ from PyQt4.Qt import Qt, QDialog, QGridLayout, QVBoxLayout, QFont, QLabel, \ from calibre.gui2.dialogs.metadata_bulk_ui import Ui_MetadataBulkDialog from calibre.gui2.dialogs.tag_editor import TagEditor -from calibre.ebooks.metadata import string_to_authors, authors_to_string +from calibre.ebooks.metadata import string_to_authors, authors_to_string, title_sort from calibre.ebooks.metadata.book.base import composite_formatter from calibre.ebooks.metadata.meta import get_metadata from calibre.gui2.custom_column_widgets import populate_metadata_page @@ -134,7 +134,7 @@ class MyBlockingBusy(QDialog): # {{{ do_autonumber, do_remove_format, remove_format, do_swap_ta, \ do_remove_conv, do_auto_author, series, do_series_restart, \ series_start_value, do_title_case, cover_action, clear_series, \ - pubdate, adddate = self.args + pubdate, adddate, do_title_sort = self.args # first loop: do author and title. These will commit at the end of each @@ -159,6 +159,9 @@ class MyBlockingBusy(QDialog): # {{{ if do_title_case and not title_set: title = self.db.title(id, index_is_id=True) self.db.set_title(id, titlecase(title), notify=False) + if do_title_sort: + title = self.db.title(id, index_is_id=True) + self.db.set_title_sort(id, title_sort(title), notify=False) if au: self.db.set_authors(id, string_to_authors(au), notify=False) if cover_action == 'remove': @@ -360,11 +363,11 @@ class MetadataBulkDialog(ResizableDialog, Ui_MetadataBulkDialog): if (f in ['author_sort'] or (fm[f]['datatype'] in ['text', 'series', 'enumeration'] and fm[f].get('search_terms', None) - and f not in ['formats', 'ondevice', 'sort']) or + and f not in ['formats', 'ondevice']) or fm[f]['datatype'] in ['int', 'float', 'bool'] ): self.all_fields.append(f) self.writable_fields.append(f) - if f in ['sort'] or fm[f]['datatype'] == 'composite': + if fm[f]['datatype'] == 'composite': self.all_fields.append(f) self.all_fields.sort() self.all_fields.insert(1, '{template}') @@ -437,7 +440,7 @@ class MetadataBulkDialog(ResizableDialog, Ui_MetadataBulkDialog): self.replace_func.addItems(sorted(self.s_r_functions.keys())) self.search_mode.currentIndexChanged[int].connect(self.s_r_search_mode_changed) self.search_field.currentIndexChanged[int].connect(self.s_r_search_field_changed) - self.destination_field.currentIndexChanged[str].connect(self.s_r_destination_field_changed) + self.destination_field.currentIndexChanged[int].connect(self.s_r_destination_field_changed) self.replace_mode.currentIndexChanged[int].connect(self.s_r_paint_results) self.replace_func.currentIndexChanged[str].connect(self.s_r_paint_results) @@ -469,6 +472,16 @@ class MetadataBulkDialog(ResizableDialog, Ui_MetadataBulkDialog): self.query_field.currentIndexChanged[str].connect(self.s_r_query_change) self.query_field.setCurrentIndex(0) + def s_r_sf_itemdata(self, idx): + if idx is None: + idx = self.search_field.currentIndex() + return unicode(self.search_field.itemData(idx).toString()) + + def s_r_df_itemdata(self, idx): + if idx is None: + idx = self.destination_field.currentIndex() + return unicode(self.destination_field.itemData(idx).toString()) + def s_r_get_field(self, mi, field): if field: if field == '{template}': @@ -508,7 +521,7 @@ class MetadataBulkDialog(ResizableDialog, Ui_MetadataBulkDialog): for i in range(0, self.s_r_number_of_books): w = getattr(self, 'book_%d_text'%(i+1)) mi = self.db.get_metadata(self.ids[i], index_is_id=True) - src = unicode(self.search_field.currentText()) + src = self.s_r_sf_itemdata(idx) t = self.s_r_get_field(mi, src) if len(t) > 1: t = t[self.starting_from.value()-1: @@ -518,13 +531,13 @@ class MetadataBulkDialog(ResizableDialog, Ui_MetadataBulkDialog): if self.search_mode.currentIndex() == 0: self.destination_field.setCurrentIndex(idx) else: - self.s_r_destination_field_changed(self.destination_field.currentText()) + self.s_r_destination_field_changed(self.destination_field.currentIndex()) self.s_r_paint_results(None) - def s_r_destination_field_changed(self, txt): - txt = unicode(txt) + def s_r_destination_field_changed(self, idx): + txt = self.s_r_df_itemdata(idx) if not txt: - txt = unicode(self.search_field.currentText()) + txt = self.s_r_sf_itemdata(None) if txt and txt in self.writable_fields: self.destination_field_fm = self.db.metadata_for_field(txt) self.s_r_paint_results(None) @@ -533,8 +546,9 @@ class MetadataBulkDialog(ResizableDialog, Ui_MetadataBulkDialog): self.search_field.clear() self.destination_field.clear() if val == 0: - self.search_field.addItems(self.writable_fields) - self.destination_field.addItems(self.writable_fields) + for f in self.writable_fields: + self.search_field.addItem(f if f != 'sort' else 'title_sort', f) + self.destination_field.addItem(f if f != 'sort' else 'title_sort', f) self.destination_field.setCurrentIndex(0) self.destination_field.setVisible(False) self.destination_field_label.setVisible(False) @@ -544,8 +558,16 @@ class MetadataBulkDialog(ResizableDialog, Ui_MetadataBulkDialog): self.comma_separated.setVisible(False) self.s_r_heading.setText('

'+self.main_heading + self.character_heading) else: - self.search_field.addItems(self.all_fields) - self.destination_field.addItems(self.writable_fields) + self.search_field.blockSignals(True) + self.destination_field.blockSignals(True) + for f in self.all_fields: + self.search_field.addItem(f if f != 'sort' else 'title_sort', f) + for f in self.writable_fields: + self.destination_field.addItem(f if f != 'sort' else 'title_sort', f) + self.search_field.blockSignals(False) + self.destination_field.blockSignals(False) + for i in range(0, len(self.all_fields)): + print unicode(self.search_field.itemData(i).toString()) self.destination_field.setVisible(True) self.destination_field_label.setVisible(True) self.replace_mode.setVisible(True) @@ -575,7 +597,7 @@ class MetadataBulkDialog(ResizableDialog, Ui_MetadataBulkDialog): return rfunc(rtext) def s_r_do_regexp(self, mi): - src_field = unicode(self.search_field.currentText()) + src_field = self.s_r_sf_itemdata(None) src = self.s_r_get_field(mi, src_field) result = [] rfunc = self.s_r_functions[unicode(self.replace_func.currentText())] @@ -587,10 +609,10 @@ class MetadataBulkDialog(ResizableDialog, Ui_MetadataBulkDialog): return result def s_r_do_destination(self, mi, val): - src = unicode(self.search_field.currentText()) + src = self.s_r_sf_itemdata(None) if src == '': return '' - dest = unicode(self.destination_field.currentText()) + dest = self.s_r_df_itemdata(None) if dest == '': if self.db.metadata_for_field(src)['datatype'] == 'composite': raise Exception(_('You must specify a destination when source is a composite field')) @@ -680,10 +702,10 @@ class MetadataBulkDialog(ResizableDialog, Ui_MetadataBulkDialog): break def do_search_replace(self, id): - source = unicode(self.search_field.currentText()) + source = self.s_r_sf_itemdata(None) if not source or not self.s_r_obj: return - dest = unicode(self.destination_field.currentText()) + dest = self.s_r_df_itemdata(None) if not dest: dest = source dfm = self.db.field_metadata[dest] @@ -717,6 +739,8 @@ class MetadataBulkDialog(ResizableDialog, Ui_MetadataBulkDialog): else: if dest == 'comments': setter = self.db.set_comment + elif dest == 'sort': + setter = self.db.set_title_sort else: setter = getattr(self.db, 'set_'+dest) if dest in ['title', 'authors']: @@ -844,6 +868,7 @@ class MetadataBulkDialog(ResizableDialog, Ui_MetadataBulkDialog): do_remove_conv = self.remove_conversion_settings.isChecked() do_auto_author = self.auto_author_sort.isChecked() do_title_case = self.change_title_to_title_case.isChecked() + do_title_sort = self.update_title_sort.isChecked() pubdate = adddate = None if self.apply_pubdate.isChecked(): pubdate = qt_to_dt(self.pubdate.date()) @@ -862,7 +887,7 @@ class MetadataBulkDialog(ResizableDialog, Ui_MetadataBulkDialog): do_autonumber, do_remove_format, remove_format, do_swap_ta, do_remove_conv, do_auto_author, series, do_series_restart, series_start_value, do_title_case, cover_action, clear_series, - pubdate, adddate) + pubdate, adddate, do_title_sort) bb = MyBlockingBusy(_('Applying changes to %d books.\nPhase {0} {1}%%.') %len(self.ids), args, self.db, self.ids, diff --git a/src/calibre/gui2/dialogs/metadata_bulk.ui b/src/calibre/gui2/dialogs/metadata_bulk.ui index ecdb396662..576c6b060f 100644 --- a/src/calibre/gui2/dialogs/metadata_bulk.ui +++ b/src/calibre/gui2/dialogs/metadata_bulk.ui @@ -489,6 +489,17 @@ title and author are swapped before the title case is set + + + + Recompute the title sort value and store it in title sort. +This will happen after any title case changes + + + Update &title sort + + + diff --git a/src/calibre/library/database2.py b/src/calibre/library/database2.py index 95e568bdbe..c147773f1f 100644 --- a/src/calibre/library/database2.py +++ b/src/calibre/library/database2.py @@ -1718,10 +1718,6 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns): title = title.decode(preferred_encoding, 'replace') self.conn.execute('UPDATE books SET title=? WHERE id=?', (title, id)) self.data.set(id, self.FIELD_MAP['title'], title, row_is_id=True) - if tweaks['title_series_sorting'] == 'library_order': - self.data.set(id, self.FIELD_MAP['sort'], title_sort(title), row_is_id=True) - else: - self.data.set(id, self.FIELD_MAP['sort'], title, row_is_id=True) return True def set_title(self, id, title, notify=True, commit=True):