diff --git a/src/calibre/gui2/custom_column_widgets.py b/src/calibre/gui2/custom_column_widgets.py index 9fde49eb87..bcf7c798f9 100644 --- a/src/calibre/gui2/custom_column_widgets.py +++ b/src/calibre/gui2/custom_column_widgets.py @@ -12,7 +12,7 @@ from functools import partial from PyQt5.Qt import (Qt, QComboBox, QLabel, QSpinBox, QDoubleSpinBox, QDateTime, QGroupBox, QVBoxLayout, QSizePolicy, QGridLayout, QUrl, 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.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'] elide_pos = tweaks['metadata_edit_elision_point'] 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: if not fm[key]['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) else: 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) if row >= turnover_point: column = 1 diff --git a/src/calibre/gui2/dialogs/tag_list_editor.py b/src/calibre/gui2/dialogs/tag_list_editor.py index 0e56510a42..c6b8ab7641 100644 --- a/src/calibre/gui2/dialogs/tag_list_editor.py +++ b/src/calibre/gui2/dialogs/tag_list_editor.py @@ -296,19 +296,20 @@ class TagListEditor(QDialog, Ui_TagListEditor): ca.triggered.connect(partial(self.search_for_books, item)) if disable_copy_paste_search: ca.setEnabled(False) - m.addSeparator() - case_menu = QMenu(_('Change case')) - action_upper_case = case_menu.addAction(_('Upper case')) - action_lower_case = case_menu.addAction(_('Lower case')) - action_swap_case = case_menu.addAction(_('Swap case')) - action_title_case = case_menu.addAction(_('Title case')) - action_capitalize = case_menu.addAction(_('Capitalize')) - action_upper_case.triggered.connect(partial(self.do_case, icu_upper)) - action_lower_case.triggered.connect(partial(self.do_case, icu_lower)) - action_swap_case.triggered.connect(partial(self.do_case, self.swap_case)) - action_title_case.triggered.connect(partial(self.do_case, titlecase)) - action_capitalize.triggered.connect(partial(self.do_case, capitalize)) - m.addMenu(case_menu) + if self.table.state() == self.table.EditingState: + m.addSeparator() + case_menu = QMenu(_('Change case')) + action_upper_case = case_menu.addAction(_('Upper case')) + action_lower_case = case_menu.addAction(_('Lower case')) + action_swap_case = case_menu.addAction(_('Swap case')) + action_title_case = case_menu.addAction(_('Title case')) + action_capitalize = case_menu.addAction(_('Capitalize')) + action_upper_case.triggered.connect(partial(self.do_case, icu_upper)) + action_lower_case.triggered.connect(partial(self.do_case, icu_lower)) + action_swap_case.triggered.connect(partial(self.do_case, self.swap_case)) + action_title_case.triggered.connect(partial(self.do_case, titlecase)) + action_capitalize.triggered.connect(partial(self.do_case, capitalize)) + m.addMenu(case_menu) m.exec_(self.table.mapToGlobal(point)) def search_for_books(self, item): diff --git a/src/calibre/gui2/preferences/coloring.py b/src/calibre/gui2/preferences/coloring.py index fed09e0b63..ad91f916b8 100644 --- a/src/calibre/gui2/preferences/coloring.py +++ b/src/calibre/gui2/preferences/coloring.py @@ -873,8 +873,9 @@ class RulesModel(QAbstractListModel): # {{{ _('
  • The condition using column %(col)s is invalid') % dict(col=c)) return ( - _('
  • If the %(col)s column %(action)s value: %(val)s') % dict( - col=c, action=action_name, val=prepare_string_for_xml(v))) + _('
  • If the %(col)s column %(action)s %(val_label)s%(val)s') % dict( + col=c, action=action_name, val=prepare_string_for_xml(v), + val_label=_('value: ') if v else '')) # }}} diff --git a/src/calibre/gui2/preferences/look_feel.ui b/src/calibre/gui2/preferences/look_feel.ui index e11a68cb81..8b52d5bda3 100644 --- a/src/calibre/gui2/preferences/look_feel.ui +++ b/src/calibre/gui2/preferences/look_feel.ui @@ -1122,6 +1122,17 @@ using the mouse.</p> + + + + margin-left: 1.5em + + + <p>If you check this box then you probably want to define the +keyboard shortcut 'Tag browser / Give the tag browser keyboard focus'</p> + + + diff --git a/src/calibre/gui2/tag_browser/ui.py b/src/calibre/gui2/tag_browser/ui.py index a8c4127f4d..b07af28a02 100644 --- a/src/calibre/gui2/tag_browser/ui.py +++ b/src/calibre/gui2/tag_browser/ui.py @@ -688,22 +688,27 @@ class TagBrowserWidget(QFrame): # {{{ def give_tb_focus(self, *args): if gprefs['tag_browser_allow_keyboard_focus']: tb = self.tags_view - idx = tb.currentIndex() - if not idx.isValid: - idx = tb.model().createIndex(0, 0) - tb.setCurrentIndex(idx) - tb.setFocus(Qt.OtherFocusReason) + if tb.hasFocus(): + self._parent.shift_esc() + elif self._parent.current_view() == self._parent.library_view: + tb.setFocus() + idx = tb.currentIndex() + if not idx.isValid(): + idx = tb.model().createIndex(0, 0) + tb.setCurrentIndex(idx) def set_pane_is_visible(self, 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 def set_focus_to_find_box(self): 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.find() diff --git a/src/calibre/gui2/tag_browser/view.py b/src/calibre/gui2/tag_browser/view.py index 2639b8c01e..30e74ef600 100644 --- a/src/calibre/gui2/tag_browser/view.py +++ b/src/calibre/gui2/tag_browser/view.py @@ -12,7 +12,7 @@ from functools import partial from PyQt5.Qt import ( QStyledItemDelegate, Qt, QTreeView, pyqtSignal, QSize, QIcon, QApplication, 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 @@ -22,7 +22,8 @@ from calibre.gui2.complete2 import EditWithComplete from calibre.gui2.tag_browser.model import (TagTreeItem, TAG_SEARCH_STATES, TagsModel, DRAG_IMAGE_ROLE, COUNT_ROLE) 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.serialize import json_loads from polyglot.builtins import unicode_type, range, zip @@ -198,6 +199,10 @@ class TagsView(QTreeView): # {{{ self.set_look_and_feel() if not gprefs['tag_browser_allow_keyboard_focus']: 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) def set_style_sheet(self): @@ -294,10 +299,14 @@ class TagsView(QTreeView): # {{{ self.collapsed.connect(self.collapse_node_and_children) def keyPressEvent(self, event): - if event.key() == Qt.Key_Return and self.state() != self.EditingState: - # I don't see how it can ever not be valid, but ... - if self.currentIndex().isValid(): - self.toggle_current_index() + if (gprefs['tag_browser_allow_keyboard_focus'] and event.key() == Qt.Key_Return + and self.state() != self.EditingState + # I don't see how current_index can ever be not valid, but ... + 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 QTreeView.keyPressEvent(self, event)