Fixes #1901249 [Edit Metadata: Minor alignment issues with ellide tweak](https://bugs.launchpad.net/calibre/+bug/1901249)
Fixes #1901435 [Capitalized tags in the Category editor is not saved](https://bugs.launchpad.net/calibre/+bug/1901435)
Fixes #1901456 [Slight text error in Column Icon rules](https://bugs.launchpad.net/calibre/+bug/1901456)
This commit is contained in:
Kovid Goyal 2020-11-01 19:20:04 +05:30
commit a42fefed75
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
6 changed files with 59 additions and 30 deletions

View File

@ -12,7 +12,7 @@ from functools import partial
from PyQt5.Qt import (Qt, QComboBox, QLabel, QSpinBox, QDoubleSpinBox, from PyQt5.Qt import (Qt, QComboBox, QLabel, QSpinBox, QDoubleSpinBox,
QDateTime, QGroupBox, QVBoxLayout, QSizePolicy, QGridLayout, QUrl, QDateTime, QGroupBox, QVBoxLayout, QSizePolicy, QGridLayout, QUrl,
QSpacerItem, QIcon, QCheckBox, QWidget, QHBoxLayout, QLineEdit, QSpacerItem, QIcon, QCheckBox, QWidget, QHBoxLayout, QLineEdit,
QMessageBox, QToolButton, QPlainTextEdit) QMessageBox, QToolButton, QPlainTextEdit, QApplication, QStyle)
from calibre.utils.date import qt_to_dt, now, as_local_time, as_utc, internal_iso_format_string from calibre.utils.date import qt_to_dt, now, as_local_time, as_utc, internal_iso_format_string
from calibre.gui2.complete2 import EditWithComplete from calibre.gui2.complete2 import EditWithComplete
@ -756,6 +756,9 @@ def populate_metadata_page(layout, db, book_id, bulk=False, two_column=False, pa
do_elision = tweaks['metadata_edit_elide_labels'] do_elision = tweaks['metadata_edit_elide_labels']
elide_pos = tweaks['metadata_edit_elision_point'] elide_pos = tweaks['metadata_edit_elision_point']
elide_pos = elide_pos if elide_pos in {'left', 'middle', 'right'} else 'right' elide_pos = elide_pos if elide_pos in {'left', 'middle', 'right'} else 'right'
# make room on the right side for the scrollbar
sb_width = QApplication.instance().style().pixelMetric(QStyle.PM_ScrollBarExtent)
layout.setContentsMargins(0, 0, sb_width, 0)
for key in cols: for key in cols:
if not fm[key]['is_editable']: if not fm[key]['is_editable']:
continue # The job spy plugin can change is_editable continue # The job spy plugin can change is_editable
@ -820,7 +823,6 @@ def populate_metadata_page(layout, db, book_id, bulk=False, two_column=False, pa
l.addWidget(w.widgets[c+1], c, 1) l.addWidget(w.widgets[c+1], c, 1)
else: else:
l.addWidget(w.widgets[0], 0, 0, 1, 2) l.addWidget(w.widgets[0], 0, 0, 1, 2)
l.addItem(QSpacerItem(0, 0, vPolicy=QSizePolicy.Expanding), c, 0, 1, 1)
max_row = max(max_row, row) max_row = max(max_row, row)
if row >= turnover_point: if row >= turnover_point:
column = 1 column = 1

View File

@ -296,19 +296,20 @@ class TagListEditor(QDialog, Ui_TagListEditor):
ca.triggered.connect(partial(self.search_for_books, item)) ca.triggered.connect(partial(self.search_for_books, item))
if disable_copy_paste_search: if disable_copy_paste_search:
ca.setEnabled(False) ca.setEnabled(False)
m.addSeparator() if self.table.state() == self.table.EditingState:
case_menu = QMenu(_('Change case')) m.addSeparator()
action_upper_case = case_menu.addAction(_('Upper case')) case_menu = QMenu(_('Change case'))
action_lower_case = case_menu.addAction(_('Lower case')) action_upper_case = case_menu.addAction(_('Upper case'))
action_swap_case = case_menu.addAction(_('Swap case')) action_lower_case = case_menu.addAction(_('Lower case'))
action_title_case = case_menu.addAction(_('Title case')) action_swap_case = case_menu.addAction(_('Swap case'))
action_capitalize = case_menu.addAction(_('Capitalize')) action_title_case = case_menu.addAction(_('Title case'))
action_upper_case.triggered.connect(partial(self.do_case, icu_upper)) action_capitalize = case_menu.addAction(_('Capitalize'))
action_lower_case.triggered.connect(partial(self.do_case, icu_lower)) action_upper_case.triggered.connect(partial(self.do_case, icu_upper))
action_swap_case.triggered.connect(partial(self.do_case, self.swap_case)) action_lower_case.triggered.connect(partial(self.do_case, icu_lower))
action_title_case.triggered.connect(partial(self.do_case, titlecase)) action_swap_case.triggered.connect(partial(self.do_case, self.swap_case))
action_capitalize.triggered.connect(partial(self.do_case, capitalize)) action_title_case.triggered.connect(partial(self.do_case, titlecase))
m.addMenu(case_menu) action_capitalize.triggered.connect(partial(self.do_case, capitalize))
m.addMenu(case_menu)
m.exec_(self.table.mapToGlobal(point)) m.exec_(self.table.mapToGlobal(point))
def search_for_books(self, item): def search_for_books(self, item):

View File

@ -873,8 +873,9 @@ class RulesModel(QAbstractListModel): # {{{
_('<li>The condition using column <b>%(col)s</b> is <b>invalid</b>') _('<li>The condition using column <b>%(col)s</b> is <b>invalid</b>')
% dict(col=c)) % dict(col=c))
return ( return (
_('<li>If the <b>%(col)s</b> column <b>%(action)s</b> value: <b>%(val)s</b>') % dict( _('<li>If the <b>%(col)s</b> column <b>%(action)s</b> %(val_label)s<b>%(val)s</b>') % dict(
col=c, action=action_name, val=prepare_string_for_xml(v))) col=c, action=action_name, val=prepare_string_for_xml(v),
val_label=_('value: ') if v else ''))
# }}} # }}}

View File

@ -1122,6 +1122,17 @@ using the mouse.&lt;/p&gt;</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="15" column="0" colspan="2">
<widget class="QLabel">
<property name="styleSheet">
<string notr="true">margin-left: 1.5em</string>
</property>
<property name="text">
<string>&lt;p&gt;If you check this box then you probably want to define the
keyboard shortcut 'Tag browser / Give the tag browser keyboard focus'&lt;/p&gt;</string>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
<widget class="QWidget" name="cover_browser_tab"> <widget class="QWidget" name="cover_browser_tab">

View File

@ -688,22 +688,27 @@ class TagBrowserWidget(QFrame): # {{{
def give_tb_focus(self, *args): def give_tb_focus(self, *args):
if gprefs['tag_browser_allow_keyboard_focus']: if gprefs['tag_browser_allow_keyboard_focus']:
tb = self.tags_view tb = self.tags_view
idx = tb.currentIndex() if tb.hasFocus():
if not idx.isValid: self._parent.shift_esc()
idx = tb.model().createIndex(0, 0) elif self._parent.current_view() == self._parent.library_view:
tb.setCurrentIndex(idx) tb.setFocus()
tb.setFocus(Qt.OtherFocusReason) idx = tb.currentIndex()
if not idx.isValid():
idx = tb.model().createIndex(0, 0)
tb.setCurrentIndex(idx)
def set_pane_is_visible(self, to_what): def set_pane_is_visible(self, to_what):
self.tags_view.set_pane_is_visible(to_what) self.tags_view.set_pane_is_visible(to_what)
if not to_what:
self._parent.shift_esc()
def find_text_changed(self, str): def find_text_changed(self, str_):
self.current_find_position = None self.current_find_position = None
def set_focus_to_find_box(self): def set_focus_to_find_box(self):
self.tb_bar.set_focus_to_find_box() self.tb_bar.set_focus_to_find_box()
def do_find(self, str=None): def do_find(self, str_=None):
self.current_find_position = None self.current_find_position = None
self.find() self.find()

View File

@ -12,7 +12,7 @@ from functools import partial
from PyQt5.Qt import ( from PyQt5.Qt import (
QStyledItemDelegate, Qt, QTreeView, pyqtSignal, QSize, QIcon, QApplication, QStyledItemDelegate, Qt, QTreeView, pyqtSignal, QSize, QIcon, QApplication,
QMenu, QPoint, QToolTip, QCursor, QDrag, QRect, QModelIndex, QMenu, QPoint, QToolTip, QCursor, QDrag, QRect, QModelIndex,
QLinearGradient, QPalette, QColor, QPen, QBrush, QFont QLinearGradient, QPalette, QColor, QPen, QBrush, QFont, QTimer
) )
from calibre import sanitize_file_name from calibre import sanitize_file_name
@ -22,7 +22,8 @@ from calibre.gui2.complete2 import EditWithComplete
from calibre.gui2.tag_browser.model import (TagTreeItem, TAG_SEARCH_STATES, from calibre.gui2.tag_browser.model import (TagTreeItem, TAG_SEARCH_STATES,
TagsModel, DRAG_IMAGE_ROLE, COUNT_ROLE) TagsModel, DRAG_IMAGE_ROLE, COUNT_ROLE)
from calibre.gui2.widgets import EnLineEdit from calibre.gui2.widgets import EnLineEdit
from calibre.gui2 import config, gprefs, choose_files, pixmap_to_data, rating_font, empty_index from calibre.gui2 import (config, gprefs, choose_files, pixmap_to_data,
rating_font, empty_index)
from calibre.utils.icu import sort_key from calibre.utils.icu import sort_key
from calibre.utils.serialize import json_loads from calibre.utils.serialize import json_loads
from polyglot.builtins import unicode_type, range, zip from polyglot.builtins import unicode_type, range, zip
@ -198,6 +199,10 @@ class TagsView(QTreeView): # {{{
self.set_look_and_feel() self.set_look_and_feel()
if not gprefs['tag_browser_allow_keyboard_focus']: if not gprefs['tag_browser_allow_keyboard_focus']:
self.setFocusPolicy(Qt.NoFocus) self.setFocusPolicy(Qt.NoFocus)
else:
# This is necessary because the context menu sets things up. F2
# and company don't.
self.setEditTriggers(QTreeView.NoEditTriggers)
QApplication.instance().palette_changed.connect(self.set_style_sheet, type=Qt.QueuedConnection) QApplication.instance().palette_changed.connect(self.set_style_sheet, type=Qt.QueuedConnection)
def set_style_sheet(self): def set_style_sheet(self):
@ -294,10 +299,14 @@ class TagsView(QTreeView): # {{{
self.collapsed.connect(self.collapse_node_and_children) self.collapsed.connect(self.collapse_node_and_children)
def keyPressEvent(self, event): def keyPressEvent(self, event):
if event.key() == Qt.Key_Return and self.state() != self.EditingState: if (gprefs['tag_browser_allow_keyboard_focus'] and event.key() == Qt.Key_Return
# I don't see how it can ever not be valid, but ... and self.state() != self.EditingState
if self.currentIndex().isValid(): # I don't see how current_index can ever be not valid, but ...
self.toggle_current_index() and self.currentIndex().isValid()):
self.toggle_current_index()
# Reset the focus to the TB. Use the singleshot in case
# some of of searching is done using queued signals.
QTimer.singleShot(0, lambda: self.setFocus())
return return
QTreeView.keyPressEvent(self, event) QTreeView.keyPressEvent(self, event)