mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Add option to bulk metadata edit dialog to force series renumbering starting at a given number
This commit is contained in:
commit
822a83b434
@ -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)
|
||||||
|
@ -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>
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user