diff --git a/src/calibre/devices/kobo/driver.py b/src/calibre/devices/kobo/driver.py index 9d398c0c44..95266ecb89 100644 --- a/src/calibre/devices/kobo/driver.py +++ b/src/calibre/devices/kobo/driver.py @@ -3253,7 +3253,9 @@ class KOBOTOUCH(KOBO): # debug_print('KoboTouch:set_core_metadata book="%s"' % book.title) show_debug = self.is_debugging_title(book.title) if show_debug: - debug_print(f'KoboTouch:set_core_metadata book="{book}", \nseries_only="{series_only}"') + debug_print(f'KoboTouch:set_core_metadata book="{book}"\n' + f'series_only="{series_only}"\n' + f'force_series_id="{self.force_series_id}"') def generate_update_from_template(book, update_values, set_clause, column_name, new_value=None, template=None, current_value=None): if template is None or template == '': @@ -3327,7 +3329,12 @@ class KOBOTOUCH(KOBO): set_clause.append('Series') update_values.append(new_series_number) set_clause.append('SeriesNumber') - if self.supports_series_list and book.is_sideloaded: + if self.force_series_id: + update_values.append(new_series) + set_clause.append('SeriesID') + update_values.append(newmi.series_index) + set_clause.append('SeriesNumberFloat') + elif self.supports_series_list and book.is_sideloaded: series_id = self.kobo_series_dict.get(new_series, new_series) try: kobo_series_id = book.kobo_series_id @@ -3337,8 +3344,8 @@ class KOBOTOUCH(KOBO): kobo_series_number_float = None if series_changed or series_number_changed \ - or not kobo_series_id == series_id \ - or not kobo_series_number_float == newmi.series_index: + or kobo_series_id != series_id \ + or kobo_series_number_float != newmi.series_index: update_values.append(series_id) set_clause.append('SeriesID') update_values.append(newmi.series_index) @@ -3530,6 +3537,7 @@ class KOBOTOUCH(KOBO): c.add_opt('show_recommendations', default=False) c.add_opt('update_series', default=True) + c.add_opt('force_series_id', default=False) c.add_opt('update_core_metadata', default=False) c.add_opt('update_purchased_kepubs', default=False) c.add_opt('update_device_metadata', default=True) @@ -3843,6 +3851,10 @@ class KOBOTOUCH(KOBO): def update_series_details(self): return self.update_device_metadata and self.get_pref('update_series') and self.supports_series() + @property + def force_series_id(self): + return self.update_device_metadata and self.get_pref('force_series_id') and self.supports_series() + @property def update_subtitle(self): # Subtitle was added to the database at the same time as the series support. diff --git a/src/calibre/devices/kobo/kobotouch_config.py b/src/calibre/devices/kobo/kobotouch_config.py index b0bd335b2a..a639ebb98c 100644 --- a/src/calibre/devices/kobo/kobotouch_config.py +++ b/src/calibre/devices/kobo/kobotouch_config.py @@ -6,10 +6,12 @@ __docformat__ = 'restructuredtext en' import textwrap -from qt.core import QCheckBox, QDialog, QDialogButtonBox, QGridLayout, QLabel, QLineEdit, QPushButton, QVBoxLayout, QWidget +from qt.core import (QCheckBox, QDialog, QDialogButtonBox, QGridLayout, QHBoxLayout, + QLabel, QLineEdit, QPushButton, QVBoxLayout, QWidget) from calibre.gui2 import error_dialog -from calibre.gui2.device_drivers.tabbed_device_config import DeviceConfigTab, DeviceOptionsGroupBox, TabbedDeviceConfig +from calibre.gui2.device_drivers.tabbed_device_config import (DeviceConfigTab, + DeviceOptionsGroupBox, TabbedDeviceConfig) from calibre.gui2.dialogs.template_dialog import TemplateDialog from calibre.gui2.dialogs.template_line_editor import TemplateLineEditor from calibre.gui2.widgets2 import ColorButton @@ -118,6 +120,7 @@ class KOBOTOUCHConfig(TabbedDeviceConfig): p['update_device_metadata'] = self.update_device_metadata p['update_series'] = self.update_series + p['force_series_id'] = self.force_series_id p['update_core_metadata'] = self.update_core_metadata p['update_purchased_kepubs'] = self.update_purchased_kepubs p['subtitle_template'] = self.subtitle_template @@ -578,10 +581,21 @@ class MetadataGroupBox(DeviceOptionsGroupBox): _("Set series information"), _('The book lists on the Kobo devices can display series information. ' 'This is not read by the device from the sideloaded books. ' - 'Series information can only be added to the device after the book has been processed by the device. ' + 'Series information can only be added to the device after the ' + 'book has been processed by the device. ' 'Enable if you wish to set series information.'), device.get_pref('update_series') ) + self.force_series_id_checkbox = create_checkbox( + _("Force series ID"), + _('Kobo devices use a SeriesID to distinguish between different series. ' + 'Purchased books have a SeriesID assigned by Kobo. Sideloaded books ' + 'have a SeriesID assigned by calibre, which is usually different. ' + 'This causes a series to be shown twice on the Kobo device. ' + 'Enable if you wish to force all the SeriesID for books ' + 'in a series to the same value.'), + device.get_pref('force_series_id') + ) self.update_core_metadata_checkbox = create_checkbox( _("Update metadata on Book Details pages"), _('This will update the metadata in the device database when the device is connected. ' @@ -648,7 +662,12 @@ class MetadataGroupBox(DeviceOptionsGroupBox): ) line = 0 - self.options_layout.addWidget(self.update_series_checkbox, line, 0, 1, 4) + hbl = QHBoxLayout() + hbl.setContentsMargins(0, 0, 0, 0) + hbl.addWidget(self.update_series_checkbox) + hbl.addWidget(self.force_series_id_checkbox) + hbl.addStretch(1) + self.options_layout.addLayout(hbl, line, 0, 1, 4) line += 1 self.options_layout.addWidget(self.update_core_metadata_checkbox, line, 0, 1, 4) line += 1 @@ -665,15 +684,23 @@ class MetadataGroupBox(DeviceOptionsGroupBox): line += 1 self.options_layout.addWidget(self.update_purchased_kepubs_checkbox, line, 0, 1, 4) + self.force_series_id_checkbox.setEnabled(self.update_series) self.update_core_metadata_checkbox.clicked.connect(self.update_core_metadata_checkbox_clicked) + self.update_series_checkbox.clicked.connect(self.update_series_checkbox_clicked) self.update_subtitle_checkbox.clicked.connect(self.update_subtitle_checkbox_clicked) self.update_bookstats_checkbox.clicked.connect(self.update_bookstats_checkbox_clicked) self.update_core_metadata_checkbox_clicked(device.get_pref('update_core_metadata')) self.update_subtitle_checkbox_clicked(device.get_pref('update_subtitle')) self.update_bookstats_checkbox_clicked(device.get_pref('update_bookstats')) + def update_series_checkbox_clicked(self, checked): + self.force_series_id_checkbox.setEnabled(checked) + if not checked: + self.force_series_id_checkbox.setChecked(False) + def update_core_metadata_checkbox_clicked(self, checked): self.update_series_checkbox.setEnabled(not checked) + self.force_series_id_checkbox.setEnabled(self.update_series) self.subtitle_template_edit.setEnabled(checked) self.update_subtitle_checkbox.setEnabled(checked) self.update_bookstats_checkbox.setEnabled(checked) @@ -714,6 +741,10 @@ class MetadataGroupBox(DeviceOptionsGroupBox): def update_series(self): return self.update_series_checkbox.isChecked() + @property + def force_series_id(self): + return self.update_series and self.force_series_id_checkbox.isChecked() + @property def update_core_metadata(self): return self.update_core_metadata_checkbox.isChecked()