mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-08 18:54:09 -04:00
Implement bulk metadata editing for half star rating fields
This commit is contained in:
parent
baddd6c298
commit
982d406121
@ -394,9 +394,9 @@ def check_doi(doi):
|
||||
return doi_check.group()
|
||||
return None
|
||||
|
||||
def rating_to_stars(value, allow_half_star=False, star=u'★', half=u'½'):
|
||||
def rating_to_stars(value, allow_half_stars=False, star=u'★', half=u'½'):
|
||||
r = max(0, min(int(value), 10))
|
||||
if allow_half_star:
|
||||
if allow_half_stars:
|
||||
ans = u'★' * (r // 2)
|
||||
if r % 2:
|
||||
ans += u'½'
|
||||
|
@ -824,25 +824,16 @@ class BulkFloat(BulkInt):
|
||||
class BulkRating(BulkBase):
|
||||
|
||||
def setup_ui(self, parent):
|
||||
self.make_widgets(parent, QSpinBox)
|
||||
self.main_widget.setRange(0, 5)
|
||||
self.main_widget.setSuffix(' '+_('star(s)'))
|
||||
self.main_widget.setSpecialValueText(_('Not rated'))
|
||||
self.main_widget.setSingleStep(1)
|
||||
allow_half_stars = self.col_metadata['display'].get('allow_half_stars', False)
|
||||
self.make_widgets(parent, partial(RatingEditor, is_half_star=allow_half_stars))
|
||||
|
||||
def setter(self, val):
|
||||
if val is None:
|
||||
val = 0
|
||||
self.main_widget.setValue(int(round(val/2.)))
|
||||
val = max(0, min(int(val or 0), 10))
|
||||
self.main_widget.rating_value = val
|
||||
self.ignore_change_signals = False
|
||||
|
||||
def getter(self):
|
||||
val = self.main_widget.value()
|
||||
if val == 0:
|
||||
val = None
|
||||
else:
|
||||
val *= 2
|
||||
return val
|
||||
return self.main_widget.rating_value or None
|
||||
|
||||
class BulkDateTime(BulkBase):
|
||||
|
||||
|
@ -231,7 +231,7 @@ class MyBlockingBusy(QDialog): # {{{
|
||||
|
||||
# Various fields
|
||||
if args.rating != -1:
|
||||
cache.set_field('rating', {bid:args.rating*2 for bid in self.ids})
|
||||
cache.set_field('rating', {bid:args.rating for bid in self.ids})
|
||||
|
||||
if args.clear_pub:
|
||||
cache.set_field('publisher', {bid:'' for bid in self.ids})
|
||||
@ -341,6 +341,7 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog):
|
||||
self.remove_format.setCurrentIndex(-1)
|
||||
|
||||
self.series.currentIndexChanged[int].connect(self.series_changed)
|
||||
self.rating.currentIndexChanged.connect(lambda:self.apply_rating.setChecked(True))
|
||||
self.series.editTextChanged.connect(self.series_changed)
|
||||
self.tag_editor_button.clicked.connect(self.tag_editor)
|
||||
self.autonumber_series.stateChanged[int].connect(self.auto_number_changed)
|
||||
@ -981,7 +982,9 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog):
|
||||
au = unicode(self.authors.text())
|
||||
aus = unicode(self.author_sort.text())
|
||||
do_aus = self.author_sort.isEnabled()
|
||||
rating = self.rating.value()
|
||||
rating = self.rating.rating_value
|
||||
if not self.apply_rating.isChecked():
|
||||
rating = -1
|
||||
pub = unicode(self.publisher.text())
|
||||
do_series = self.write_series
|
||||
clear_series = self.clear_series.isChecked()
|
||||
|
@ -61,6 +61,13 @@
|
||||
<string>&Basic metadata</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="10" column="3">
|
||||
<widget class="QCheckBox" name="apply_pubdate">
|
||||
<property name="text">
|
||||
<string>&Apply date</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
@ -74,14 +81,14 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<item row="0" column="2">
|
||||
<widget class="EditWithComplete" name="authors">
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<item row="1" column="2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="auto_author_sort">
|
||||
@ -118,7 +125,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<item row="2" column="2">
|
||||
<widget class="EnLineEdit" name="author_sort">
|
||||
<property name="toolTip">
|
||||
<string>Specify how the author(s) of this book should be sorted. For example Charles Dickens should be sorted as Dickens, Charles.</string>
|
||||
@ -138,34 +145,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QSpinBox" name="rating">
|
||||
<property name="toolTip">
|
||||
<string>Rating of this book. 0-5 stars</string>
|
||||
</property>
|
||||
<property name="whatsThis">
|
||||
<string>Rating of this book. 0-5 stars</string>
|
||||
</property>
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::PlusMinus</enum>
|
||||
</property>
|
||||
<property name="specialValueText">
|
||||
<string>No change</string>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string> stars</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>-1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>-1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
@ -179,14 +158,14 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<item row="4" column="2">
|
||||
<widget class="EditWithComplete" name="publisher">
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2">
|
||||
<item row="4" column="3">
|
||||
<widget class="QCheckBox" name="clear_pub">
|
||||
<property name="toolTip">
|
||||
<string>If checked, the publisher will be cleared</string>
|
||||
@ -209,14 +188,14 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<item row="5" column="2">
|
||||
<widget class="EditWithComplete" name="tags">
|
||||
<property name="toolTip">
|
||||
<string>Tags categorize the book. This is particularly useful while searching. <br><br>They can be any words or phrases, separated by commas.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="2">
|
||||
<item row="5" column="3">
|
||||
<widget class="QToolButton" name="tag_editor_button">
|
||||
<property name="toolTip">
|
||||
<string>Open Tag Editor</string>
|
||||
@ -243,14 +222,14 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<item row="6" column="2">
|
||||
<widget class="EditWithComplete" name="remove_tags">
|
||||
<property name="toolTip">
|
||||
<string>Comma separated list of tags to remove from the books. </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="2">
|
||||
<item row="6" column="3">
|
||||
<widget class="QCheckBox" name="remove_all_tags">
|
||||
<property name="toolTip">
|
||||
<string>Check this box to remove all tags from the books.</string>
|
||||
@ -276,7 +255,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<item row="7" column="2">
|
||||
<widget class="EditWithComplete" name="series">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
@ -304,7 +283,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="2">
|
||||
<item row="7" column="3">
|
||||
<widget class="QCheckBox" name="clear_series">
|
||||
<property name="toolTip">
|
||||
<string>If checked, the series will be cleared</string>
|
||||
@ -314,7 +293,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<item row="8" column="2">
|
||||
<layout class="QHBoxLayout" name="HLayout_3">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="autonumber_series">
|
||||
@ -397,7 +376,47 @@ from the value in the box</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="1">
|
||||
<item row="16" column="0" colspan="3">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="button_config_cover_gen">
|
||||
<property name="toolTip">
|
||||
<string>Control how the default generated covers are created</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Configure co&ver generation</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="comments_button">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Set the co&mments for all selected books</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="9" column="2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<item>
|
||||
<widget class="QDateTimeEdit" name="adddate">
|
||||
@ -422,7 +441,7 @@ from the value in the box</string>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="9" column="2">
|
||||
<item row="9" column="3">
|
||||
<widget class="QCheckBox" name="apply_adddate">
|
||||
<property name="text">
|
||||
<string>&Apply date</string>
|
||||
@ -442,7 +461,7 @@ from the value in the box</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="1">
|
||||
<item row="10" column="2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<widget class="QDateTimeEdit" name="pubdate">
|
||||
@ -470,13 +489,6 @@ from the value in the box</string>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="10" column="2">
|
||||
<widget class="QCheckBox" name="apply_pubdate">
|
||||
<property name="text">
|
||||
<string>&Apply date</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="0">
|
||||
<widget class="QLabel" name="label_11">
|
||||
<property name="text">
|
||||
@ -490,10 +502,10 @@ from the value in the box</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="1">
|
||||
<item row="11" column="2">
|
||||
<widget class="LanguagesEdit" name="languages"/>
|
||||
</item>
|
||||
<item row="11" column="2">
|
||||
<item row="11" column="3">
|
||||
<widget class="QCheckBox" name="clear_languages">
|
||||
<property name="text">
|
||||
<string>Remove &all</string>
|
||||
@ -510,7 +522,7 @@ from the value in the box</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="1">
|
||||
<item row="12" column="2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_7">
|
||||
<item>
|
||||
<widget class="QComboBox" name="remove_format">
|
||||
@ -567,7 +579,7 @@ for e.g., EPUB to EPUB, calibre saves the original EPUB
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="14" column="0" colspan="2">
|
||||
<item row="14" column="0" colspan="3">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="change_title_to_title_case">
|
||||
@ -617,7 +629,7 @@ Future conversion of these books will use the default settings.</string>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="15" column="0" colspan="2">
|
||||
<item row="15" column="0" colspan="3">
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Change &cover</string>
|
||||
@ -670,46 +682,6 @@ as that of the first selected book.</string>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="16" column="0" colspan="2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="button_config_cover_gen">
|
||||
<property name="toolTip">
|
||||
<string>Control how the default generated covers are created</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Configure co&ver generation</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="comments_button">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Set the co&mments for all selected books</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="17" column="0">
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
@ -723,6 +695,16 @@ as that of the first selected book.</string>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="RatingEditor" name="rating"/>
|
||||
</item>
|
||||
<item row="3" column="3">
|
||||
<widget class="QCheckBox" name="apply_rating">
|
||||
<property name="text">
|
||||
<string>&Apply rating</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab">
|
||||
@ -1209,8 +1191,8 @@ not multiple and the destination field is multiple</string>
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>922</width>
|
||||
<height>268</height>
|
||||
<width>210</width>
|
||||
<height>66</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="testgrid">
|
||||
@ -1325,6 +1307,11 @@ is completed. This can be slow on large libraries.</string>
|
||||
<extends>QComboBox</extends>
|
||||
<header>calibre/gui2/languages.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>RatingEditor</class>
|
||||
<extends>QComboBox</extends>
|
||||
<header>calibre/gui2/widgets2.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>authors</tabstop>
|
||||
|
@ -192,6 +192,7 @@ class RatingModel(QAbstractListModel):
|
||||
QAbstractListModel.__init__(self, parent)
|
||||
self.is_half_star = is_half_star
|
||||
self.rating_font = QFont(rating_font())
|
||||
self.null_text = _('Not rated')
|
||||
|
||||
def rowCount(self, parent=QModelIndex()):
|
||||
return 11 if self.is_half_star else 6
|
||||
@ -199,7 +200,7 @@ class RatingModel(QAbstractListModel):
|
||||
def data(self, index, role=Qt.DisplayRole):
|
||||
if role == Qt.DisplayRole:
|
||||
val = index.row() * (1 if self.is_half_star else 2)
|
||||
return rating_to_stars(val, self.is_half_star) or _('Not rated')
|
||||
return rating_to_stars(val, self.is_half_star) or self.null_text
|
||||
if role == Qt.FontRole:
|
||||
return QApplication.instance().font() if index.row() == 0 else self.rating_font
|
||||
|
||||
@ -235,6 +236,15 @@ class RatingEditor(QComboBox):
|
||||
self.setMaxVisibleItems(self.count())
|
||||
self.currentIndexChanged.connect(self.update_font)
|
||||
|
||||
@property
|
||||
def null_text(self):
|
||||
return self._model.null_text
|
||||
|
||||
@null_text.setter
|
||||
def null_text(self, val):
|
||||
self._model.null_text = val
|
||||
self._model.dataChanged.emit(self._model.index(0, 0), self._model.index(0, 0))
|
||||
|
||||
def update_font(self):
|
||||
if self.currentIndex() == 0:
|
||||
self.setFont(QApplication.instance().font())
|
||||
|
Loading…
x
Reference in New Issue
Block a user