Implement bulk metadata editing for half star rating fields

This commit is contained in:
Kovid Goyal 2016-09-04 18:39:27 +05:30
parent baddd6c298
commit 982d406121
5 changed files with 107 additions and 116 deletions

View File

@ -394,9 +394,9 @@ def check_doi(doi):
return doi_check.group() return doi_check.group()
return None 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)) r = max(0, min(int(value), 10))
if allow_half_star: if allow_half_stars:
ans = u'' * (r // 2) ans = u'' * (r // 2)
if r % 2: if r % 2:
ans += u'½' ans += u'½'

View File

@ -824,25 +824,16 @@ class BulkFloat(BulkInt):
class BulkRating(BulkBase): class BulkRating(BulkBase):
def setup_ui(self, parent): def setup_ui(self, parent):
self.make_widgets(parent, QSpinBox) allow_half_stars = self.col_metadata['display'].get('allow_half_stars', False)
self.main_widget.setRange(0, 5) self.make_widgets(parent, partial(RatingEditor, is_half_star=allow_half_stars))
self.main_widget.setSuffix(' '+_('star(s)'))
self.main_widget.setSpecialValueText(_('Not rated'))
self.main_widget.setSingleStep(1)
def setter(self, val): def setter(self, val):
if val is None: val = max(0, min(int(val or 0), 10))
val = 0 self.main_widget.rating_value = val
self.main_widget.setValue(int(round(val/2.)))
self.ignore_change_signals = False self.ignore_change_signals = False
def getter(self): def getter(self):
val = self.main_widget.value() return self.main_widget.rating_value or None
if val == 0:
val = None
else:
val *= 2
return val
class BulkDateTime(BulkBase): class BulkDateTime(BulkBase):

View File

@ -231,7 +231,7 @@ class MyBlockingBusy(QDialog): # {{{
# Various fields # Various fields
if args.rating != -1: 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: if args.clear_pub:
cache.set_field('publisher', {bid:'' for bid in self.ids}) 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.remove_format.setCurrentIndex(-1)
self.series.currentIndexChanged[int].connect(self.series_changed) 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.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) self.autonumber_series.stateChanged[int].connect(self.auto_number_changed)
@ -981,7 +982,9 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog):
au = unicode(self.authors.text()) au = unicode(self.authors.text())
aus = unicode(self.author_sort.text()) aus = unicode(self.author_sort.text())
do_aus = self.author_sort.isEnabled() 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()) pub = unicode(self.publisher.text())
do_series = self.write_series do_series = self.write_series
clear_series = self.clear_series.isChecked() clear_series = self.clear_series.isChecked()

View File

@ -61,6 +61,13 @@
<string>&amp;Basic metadata</string> <string>&amp;Basic metadata</string>
</attribute> </attribute>
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<item row="10" column="3">
<widget class="QCheckBox" name="apply_pubdate">
<property name="text">
<string>&amp;Apply date</string>
</property>
</widget>
</item>
<item row="0" column="0"> <item row="0" column="0">
<widget class="QLabel" name="label_2"> <widget class="QLabel" name="label_2">
<property name="text"> <property name="text">
@ -74,14 +81,14 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="1"> <item row="0" column="2">
<widget class="EditWithComplete" name="authors"> <widget class="EditWithComplete" name="authors">
<property name="editable"> <property name="editable">
<bool>true</bool> <bool>true</bool>
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="1"> <item row="1" column="2">
<layout class="QHBoxLayout" name="horizontalLayout_2"> <layout class="QHBoxLayout" name="horizontalLayout_2">
<item> <item>
<widget class="QCheckBox" name="auto_author_sort"> <widget class="QCheckBox" name="auto_author_sort">
@ -118,7 +125,7 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="1"> <item row="2" column="2">
<widget class="EnLineEdit" name="author_sort"> <widget class="EnLineEdit" name="author_sort">
<property name="toolTip"> <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> <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> </property>
</widget> </widget>
</item> </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"> <item row="4" column="0">
<widget class="QLabel" name="label_3"> <widget class="QLabel" name="label_3">
<property name="text"> <property name="text">
@ -179,14 +158,14 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="1"> <item row="4" column="2">
<widget class="EditWithComplete" name="publisher"> <widget class="EditWithComplete" name="publisher">
<property name="editable"> <property name="editable">
<bool>true</bool> <bool>true</bool>
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="2"> <item row="4" column="3">
<widget class="QCheckBox" name="clear_pub"> <widget class="QCheckBox" name="clear_pub">
<property name="toolTip"> <property name="toolTip">
<string>If checked, the publisher will be cleared</string> <string>If checked, the publisher will be cleared</string>
@ -209,14 +188,14 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="5" column="1"> <item row="5" column="2">
<widget class="EditWithComplete" name="tags"> <widget class="EditWithComplete" name="tags">
<property name="toolTip"> <property name="toolTip">
<string>Tags categorize the book. This is particularly useful while searching. &lt;br&gt;&lt;br&gt;They can be any words or phrases, separated by commas.</string> <string>Tags categorize the book. This is particularly useful while searching. &lt;br&gt;&lt;br&gt;They can be any words or phrases, separated by commas.</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="5" column="2"> <item row="5" column="3">
<widget class="QToolButton" name="tag_editor_button"> <widget class="QToolButton" name="tag_editor_button">
<property name="toolTip"> <property name="toolTip">
<string>Open Tag Editor</string> <string>Open Tag Editor</string>
@ -243,14 +222,14 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="6" column="1"> <item row="6" column="2">
<widget class="EditWithComplete" name="remove_tags"> <widget class="EditWithComplete" name="remove_tags">
<property name="toolTip"> <property name="toolTip">
<string>Comma separated list of tags to remove from the books. </string> <string>Comma separated list of tags to remove from the books. </string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="6" column="2"> <item row="6" column="3">
<widget class="QCheckBox" name="remove_all_tags"> <widget class="QCheckBox" name="remove_all_tags">
<property name="toolTip"> <property name="toolTip">
<string>Check this box to remove all tags from the books.</string> <string>Check this box to remove all tags from the books.</string>
@ -276,7 +255,7 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="7" column="1"> <item row="7" column="2">
<widget class="EditWithComplete" name="series"> <widget class="EditWithComplete" name="series">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed"> <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
@ -304,7 +283,7 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="7" column="2"> <item row="7" column="3">
<widget class="QCheckBox" name="clear_series"> <widget class="QCheckBox" name="clear_series">
<property name="toolTip"> <property name="toolTip">
<string>If checked, the series will be cleared</string> <string>If checked, the series will be cleared</string>
@ -314,7 +293,7 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="8" column="1"> <item row="8" column="2">
<layout class="QHBoxLayout" name="HLayout_3"> <layout class="QHBoxLayout" name="HLayout_3">
<item> <item>
<widget class="QCheckBox" name="autonumber_series"> <widget class="QCheckBox" name="autonumber_series">
@ -397,7 +376,47 @@ from the value in the box</string>
</property> </property>
</widget> </widget>
</item> </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&amp;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&amp;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"> <layout class="QHBoxLayout" name="horizontalLayout_5">
<item> <item>
<widget class="QDateTimeEdit" name="adddate"> <widget class="QDateTimeEdit" name="adddate">
@ -422,7 +441,7 @@ from the value in the box</string>
</item> </item>
</layout> </layout>
</item> </item>
<item row="9" column="2"> <item row="9" column="3">
<widget class="QCheckBox" name="apply_adddate"> <widget class="QCheckBox" name="apply_adddate">
<property name="text"> <property name="text">
<string>&amp;Apply date</string> <string>&amp;Apply date</string>
@ -442,7 +461,7 @@ from the value in the box</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="10" column="1"> <item row="10" column="2">
<layout class="QHBoxLayout" name="horizontalLayout_4"> <layout class="QHBoxLayout" name="horizontalLayout_4">
<item> <item>
<widget class="QDateTimeEdit" name="pubdate"> <widget class="QDateTimeEdit" name="pubdate">
@ -470,13 +489,6 @@ from the value in the box</string>
</item> </item>
</layout> </layout>
</item> </item>
<item row="10" column="2">
<widget class="QCheckBox" name="apply_pubdate">
<property name="text">
<string>&amp;Apply date</string>
</property>
</widget>
</item>
<item row="11" column="0"> <item row="11" column="0">
<widget class="QLabel" name="label_11"> <widget class="QLabel" name="label_11">
<property name="text"> <property name="text">
@ -490,10 +502,10 @@ from the value in the box</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="11" column="1"> <item row="11" column="2">
<widget class="LanguagesEdit" name="languages"/> <widget class="LanguagesEdit" name="languages"/>
</item> </item>
<item row="11" column="2"> <item row="11" column="3">
<widget class="QCheckBox" name="clear_languages"> <widget class="QCheckBox" name="clear_languages">
<property name="text"> <property name="text">
<string>Remove &amp;all</string> <string>Remove &amp;all</string>
@ -510,7 +522,7 @@ from the value in the box</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="12" column="1"> <item row="12" column="2">
<layout class="QHBoxLayout" name="horizontalLayout_7"> <layout class="QHBoxLayout" name="horizontalLayout_7">
<item> <item>
<widget class="QComboBox" name="remove_format"> <widget class="QComboBox" name="remove_format">
@ -567,7 +579,7 @@ for e.g., EPUB to EPUB, calibre saves the original EPUB
</property> </property>
</spacer> </spacer>
</item> </item>
<item row="14" column="0" colspan="2"> <item row="14" column="0" colspan="3">
<layout class="QHBoxLayout" name="horizontalLayout_3"> <layout class="QHBoxLayout" name="horizontalLayout_3">
<item> <item>
<widget class="QCheckBox" name="change_title_to_title_case"> <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> </item>
</layout> </layout>
</item> </item>
<item row="15" column="0" colspan="2"> <item row="15" column="0" colspan="3">
<widget class="QGroupBox" name="groupBox"> <widget class="QGroupBox" name="groupBox">
<property name="title"> <property name="title">
<string>Change &amp;cover</string> <string>Change &amp;cover</string>
@ -670,46 +682,6 @@ as that of the first selected book.</string>
</layout> </layout>
</widget> </widget>
</item> </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&amp;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&amp;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"> <item row="17" column="0">
<spacer name="verticalSpacer_2"> <spacer name="verticalSpacer_2">
<property name="orientation"> <property name="orientation">
@ -723,6 +695,16 @@ as that of the first selected book.</string>
</property> </property>
</spacer> </spacer>
</item> </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>&amp;Apply rating</string>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
<widget class="QWidget" name="tab"> <widget class="QWidget" name="tab">
@ -1209,8 +1191,8 @@ not multiple and the destination field is multiple</string>
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>922</width> <width>210</width>
<height>268</height> <height>66</height>
</rect> </rect>
</property> </property>
<layout class="QGridLayout" name="testgrid"> <layout class="QGridLayout" name="testgrid">
@ -1325,6 +1307,11 @@ is completed. This can be slow on large libraries.</string>
<extends>QComboBox</extends> <extends>QComboBox</extends>
<header>calibre/gui2/languages.h</header> <header>calibre/gui2/languages.h</header>
</customwidget> </customwidget>
<customwidget>
<class>RatingEditor</class>
<extends>QComboBox</extends>
<header>calibre/gui2/widgets2.h</header>
</customwidget>
</customwidgets> </customwidgets>
<tabstops> <tabstops>
<tabstop>authors</tabstop> <tabstop>authors</tabstop>

View File

@ -192,6 +192,7 @@ class RatingModel(QAbstractListModel):
QAbstractListModel.__init__(self, parent) QAbstractListModel.__init__(self, parent)
self.is_half_star = is_half_star self.is_half_star = is_half_star
self.rating_font = QFont(rating_font()) self.rating_font = QFont(rating_font())
self.null_text = _('Not rated')
def rowCount(self, parent=QModelIndex()): def rowCount(self, parent=QModelIndex()):
return 11 if self.is_half_star else 6 return 11 if self.is_half_star else 6
@ -199,7 +200,7 @@ class RatingModel(QAbstractListModel):
def data(self, index, role=Qt.DisplayRole): def data(self, index, role=Qt.DisplayRole):
if role == Qt.DisplayRole: if role == Qt.DisplayRole:
val = index.row() * (1 if self.is_half_star else 2) 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: if role == Qt.FontRole:
return QApplication.instance().font() if index.row() == 0 else self.rating_font return QApplication.instance().font() if index.row() == 0 else self.rating_font
@ -235,6 +236,15 @@ class RatingEditor(QComboBox):
self.setMaxVisibleItems(self.count()) self.setMaxVisibleItems(self.count())
self.currentIndexChanged.connect(self.update_font) 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): def update_font(self):
if self.currentIndex() == 0: if self.currentIndex() == 0:
self.setFont(QApplication.instance().font()) self.setFont(QApplication.instance().font())