Add option to bulk metadata edit dialog to force series renumbering starting at a given number

This commit is contained in:
Kovid Goyal 2010-09-21 13:34:23 -06:00
commit 822a83b434
4 changed files with 89 additions and 25 deletions

View File

@ -31,7 +31,8 @@ class Worker(Thread):
def doit(self): def doit(self):
remove, add, au, aus, do_aus, rating, pub, do_series, \ remove, add, au, aus, do_aus, rating, pub, do_series, \
do_autonumber, do_remove_format, remove_format, do_swap_ta, \ do_autonumber, do_remove_format, remove_format, do_swap_ta, \
do_remove_conv, do_auto_author, series = self.args do_remove_conv, do_auto_author, series, do_series_restart, \
series_start_value = self.args
# first loop: do author and title. These will commit at the end of each # first loop: do author and title. These will commit at the end of each
# operation, because each operation modifies the file system. We want to # operation, because each operation modifies the file system. We want to
@ -69,6 +70,10 @@ class Worker(Thread):
self.db.set_publisher(id, pub, notify=False, commit=False) self.db.set_publisher(id, pub, notify=False, commit=False)
if do_series: if do_series:
if do_series_restart:
next = series_start_value
series_start_value += 1
else:
next = self.db.get_next_series_num_for(series) next = self.db.get_next_series_num_for(series)
self.db.set_series(id, series, notify=False, commit=False) self.db.set_series(id, series, notify=False, commit=False)
num = next if do_autonumber and series else 1.0 num = next if do_autonumber and series else 1.0
@ -163,6 +168,7 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog):
self.series.currentIndexChanged[int].connect(self.series_changed) self.series.currentIndexChanged[int].connect(self.series_changed)
self.series.editTextChanged.connect(self.series_changed) self.series.editTextChanged.connect(self.series_changed)
self.tag_editor_button.clicked.connect(self.tag_editor) self.tag_editor_button.clicked.connect(self.tag_editor)
self.autonumber_series.stateChanged[int].connect(self.auto_number_changed)
if len(db.custom_column_label_map) == 0: if len(db.custom_column_label_map) == 0:
self.central_widget.removeTab(1) self.central_widget.removeTab(1)
@ -478,6 +484,9 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog):
setter = self.db.set_comment setter = self.db.set_comment
else: else:
setter = getattr(self.db, 'set_'+dest) setter = getattr(self.db, 'set_'+dest)
if dest in ['title', 'authors']:
setter(id, val, notify=False)
else:
setter(id, val, notify=False, commit=False) setter(id, val, notify=False, commit=False)
self.db.commit() self.db.commit()
dynamic['s_r_search_mode'] = self.search_mode.currentIndex() dynamic['s_r_search_mode'] = self.search_mode.currentIndex()
@ -538,6 +547,16 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog):
self.tags.update_tags_cache(self.db.all_tags()) self.tags.update_tags_cache(self.db.all_tags())
self.remove_tags.update_tags_cache(self.db.all_tags()) self.remove_tags.update_tags_cache(self.db.all_tags())
def auto_number_changed(self, state):
if state:
self.series_numbering_restarts.setEnabled(True)
self.series_start_number.setEnabled(True)
else:
self.series_numbering_restarts.setEnabled(False)
self.series_numbering_restarts.setChecked(False)
self.series_start_number.setEnabled(False)
self.series_start_number.setValue(1)
def accept(self): def accept(self):
if len(self.ids) < 1: if len(self.ids) < 1:
return QDialog.accept(self) return QDialog.accept(self)
@ -566,6 +585,8 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog):
do_series = self.write_series do_series = self.write_series
series = unicode(self.series.currentText()).strip() series = unicode(self.series.currentText()).strip()
do_autonumber = self.autonumber_series.isChecked() do_autonumber = self.autonumber_series.isChecked()
do_series_restart = self.series_numbering_restarts.isChecked()
series_start_value = self.series_start_number.value()
do_remove_format = self.remove_format.currentIndex() > -1 do_remove_format = self.remove_format.currentIndex() > -1
remove_format = unicode(self.remove_format.currentText()) remove_format = unicode(self.remove_format.currentText())
do_swap_ta = self.swap_title_and_author.isChecked() do_swap_ta = self.swap_title_and_author.isChecked()
@ -574,7 +595,8 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog):
args = (remove, add, au, aus, do_aus, rating, pub, do_series, args = (remove, add, au, aus, do_aus, rating, pub, do_series,
do_autonumber, do_remove_format, remove_format, do_swap_ta, do_autonumber, do_remove_format, remove_format, do_swap_ta,
do_remove_conv, do_auto_author, series) do_remove_conv, do_auto_author, series, do_series_restart,
series_start_value)
bb = BlockingBusy(_('Applying changes to %d books. This may take a while.') bb = BlockingBusy(_('Applying changes to %d books. This may take a while.')
%len(self.ids), parent=self) %len(self.ids), parent=self)

View File

@ -270,12 +270,14 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="8" column="1"> <item row="8" column="1" colspan="2">
<layout class="QHBoxLayout" name="HLayout_3">
<item>
<widget class="QCheckBox" name="autonumber_series"> <widget class="QCheckBox" name="autonumber_series">
<property name="toolTip"> <property name="toolTip">
<string>Selected books will be automatically numbered, <string>If not checked, the series number for the books will be set to 1.
in the order you selected them. If checked, selected books will be automatically numbered, in the order
So if you selected Book A and then Book B, you selected them. So if you selected Book A and then Book B,
Book A will have series number 1 and Book B series number 2.</string> Book A will have series number 1 and Book B series number 2.</string>
</property> </property>
<property name="text"> <property name="text">
@ -283,6 +285,49 @@ Book A will have series number 1 and Book B series number 2.</string>
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QCheckBox" name="series_numbering_restarts">
<property name="enabled">
<bool>false</bool>
</property>
<property name="toolTip">
<string>Series will normally be renumbered from the highest number in the database
for that series. Checking this box will tell calibre to start numbering
from the value in the box</string>
</property>
<property name="text">
<string>Force numbers to start with </string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="series_start_number">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="value">
<number>1</number>
</property>
</widget>
</item>
<item>
<spacer name="HSpacer_34">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>10</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="10" column="0" colspan="2"> <item row="10" column="0" colspan="2">
<widget class="QCheckBox" name="remove_conversion_settings"> <widget class="QCheckBox" name="remove_conversion_settings">
<property name="toolTip"> <property name="toolTip">
@ -599,7 +644,7 @@ nothing should be put between the original text and the inserted text</string>
<property name="sizeHint" stdset="0"> <property name="sizeHint" stdset="0">
<size> <size>
<width>20</width> <width>20</width>
<height>40</height> <height>0</height>
</size> </size>
</property> </property>
</spacer> </spacer>

View File

@ -333,7 +333,7 @@ class ResultCache(SearchQueryParser):
if query and query.strip(): if query and query.strip():
# get metadata key associated with the search term. Eliminates # get metadata key associated with the search term. Eliminates
# dealing with plurals and other aliases # dealing with plurals and other aliases
location = self.field_metadata.search_term_to_key(location.lower().strip()) location = self.field_metadata.search_term_to_field_key(location.lower().strip())
if isinstance(location, list): if isinstance(location, list):
if allow_recursion: if allow_recursion:
for loc in location: for loc in location:
@ -609,12 +609,9 @@ class ResultCache(SearchQueryParser):
# Sorting functions {{{ # Sorting functions {{{
def sanitize_sort_field_name(self, field): def sanitize_sort_field_name(self, field):
field = field.lower().strip() field = self.field_metadata.search_term_to_field_key(field.lower().strip())
if field not in self.field_metadata.iterkeys(): # translate some fields to their hidden equivalent
if field in ('author', 'tag', 'comment'): if field == 'title': field = 'sort'
field += 's'
if field == 'date': field = 'timestamp'
elif field == 'title': field = 'sort'
elif field == 'authors': field = 'author_sort' elif field == 'authors': field = 'author_sort'
return field return field

View File

@ -501,12 +501,12 @@ class FieldMetadata(dict):
raise ValueError('Attempt to add duplicate search term "%s"'%t) raise ValueError('Attempt to add duplicate search term "%s"'%t)
self._search_term_map[t] = key self._search_term_map[t] = key
def search_term_to_key(self, term): def search_term_to_field_key(self, term):
if term in self._search_term_map: if term in self._search_term_map:
return self._search_term_map[term] return self._search_term_map[term]
return term return term
def searchable_field_keys(self): def searchable_fields(self):
return [k for k in self._tb_cats.keys() return [k for k in self._tb_cats.keys()
if self._tb_cats[k]['kind']=='field' and if self._tb_cats[k]['kind']=='field' and
len(self._tb_cats[k]['search_terms']) > 0] len(self._tb_cats[k]['search_terms']) > 0]