From af763a7a0c81178ef2e4284357887c3fd2288d50 Mon Sep 17 00:00:00 2001 From: Charles Haley Date: Mon, 3 Oct 2022 11:31:50 +0100 Subject: [PATCH] More accessibility changes related to the book list header context menu: 1) add a dialog to set the width without using the mouse. 2) Change the name from "Book list context menu" to "Book list header menu" to avoid confusion with the context menu on book list cells. --- .../gui2/actions/booklist_context_menu.py | 4 +- src/calibre/gui2/library/views.py | 97 ++++++++++++++++++- 2 files changed, 96 insertions(+), 5 deletions(-) diff --git a/src/calibre/gui2/actions/booklist_context_menu.py b/src/calibre/gui2/actions/booklist_context_menu.py index 014137d275..94bcefc49b 100644 --- a/src/calibre/gui2/actions/booklist_context_menu.py +++ b/src/calibre/gui2/actions/booklist_context_menu.py @@ -9,8 +9,8 @@ from calibre.gui2.actions import InterfaceAction class BooklistContextMenuAction(InterfaceAction): name = 'Booklist context menu' - action_spec = (_('Book list context menu'), 'context_menu.png', - _('Show the book list context menu'), '') + action_spec = (_('Book list header menu'), 'context_menu.png', + _('Show the book list header context menu'), '') action_type = 'current' action_add_menu = False dont_add_to = frozenset(['context-menu-device', 'menubar-device']) diff --git a/src/calibre/gui2/library/views.py b/src/calibre/gui2/library/views.py index 8703d18297..e5e723627d 100644 --- a/src/calibre/gui2/library/views.py +++ b/src/calibre/gui2/library/views.py @@ -12,7 +12,8 @@ from collections import OrderedDict from qt.core import ( QTableView, Qt, QAbstractItemView, QMenu, pyqtSignal, QFont, QModelIndex, QIcon, QItemSelection, QMimeData, QDrag, QStyle, QPoint, QUrl, QHeaderView, QEvent, - QStyleOptionHeader, QItemSelectionModel, QSize, QFontMetrics, QApplication) + QStyleOptionHeader, QItemSelectionModel, QSize, QFontMetrics, QApplication, + QDialog, QGridLayout, QPushButton, QDialogButtonBox, QLabel, QSpinBox) from calibre.constants import islinux from calibre.gui2.dialogs.enum_values_edit import EnumValuesEdit @@ -33,11 +34,15 @@ from calibre.utils.icu import primary_sort_key from polyglot.builtins import iteritems -def restrict_column_width(self, col, old_size, new_size): +def max_permitted_column_width(self, col): # arbitrary: scroll bar + header + some sw = self.verticalScrollBar().width() if self.verticalScrollBar().isVisible() else 0 hw = self.verticalHeader().width() if self.verticalHeader().isVisible() else 0 - max_width = max(200, self.width() - (sw + hw + 10)) + return max(200, self.width() - (sw + hw + 10)) + + +def restrict_column_width(self, col, old_size, new_size): + max_width = max_permitted_column_width(self, col) if new_size > max_width: self.column_header.blockSignals(True) self.setColumnWidth(col, max_width) @@ -203,6 +208,86 @@ class PreserveViewState: # {{{ # }}} +class AdjustColumnSize(QDialog): # {{{ + + def __init__(self, view, column, name): + QDialog.__init__(self) + self.setWindowTitle(_('Adjust column size of {0}').format(name)) + self.view = view + self.column = column + l = QGridLayout() + self.setLayout(l) + + original_size = self.original_size = view.horizontalHeader().sectionSize(column) + l.addWidget(QLabel(_('Original size:')), 0, 0) + l.addWidget(QLabel(_('{0} pixels').format(str(original_size))), 0, 1) + + self.minimum_size = self.view.horizontalHeader().minimumSectionSize() + l.addWidget(QLabel(_('Minimum size:')), 1, 0) + l.addWidget(QLabel(_('{0} pixels').format(str(self.minimum_size))), 1, 1) + + self.maximum_size = max_permitted_column_width(self.view, self.column) + l.addWidget(QLabel(_('Maximum size:')), 2, 0) + l.addWidget(QLabel(_('{0} pixels').format(str(self.maximum_size))), 2, 1) + + b = self.shrink_button = QPushButton('&Shrink 10%') + l.addWidget(b, 5, 0) + b = self.expand_button = QPushButton('&Expand 10%') + l.addWidget(b, 5, 1) + + b = self.set_minimum_button = QPushButton('Set to mi&nimum') + l.addWidget(b, 6, 0) + b = self.set_maximum_button = QPushButton('Set to ma&ximum') + l.addWidget(b, 6, 1) + + sb = self.spin_box = QSpinBox() + sb.setMinimum(self.view.horizontalHeader().minimumSectionSize()) + sb.setMaximum(self.maximum_size) + sb.setValue(original_size) + sb.setSuffix(' ' + _('pixels')) + l.addWidget(sb, 7, 1) + sb_label = QLabel('Set &to') + l.addWidget(sb_label, 7, 0) + sb_label.setBuddy(sb) + + bb = self.button_box = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok | + QDialogButtonBox.StandardButton.Cancel) + l.addWidget(bb, 10, 0, 1, 2) + + self.shrink_button.clicked.connect(self.shrink_button_clicked) + self.expand_button.clicked.connect(self.expand_button_clicked) + self.spin_box.valueChanged.connect(self.spin_box_changed) + self.set_minimum_button.clicked.connect(self.set_minimum_button_clicked) + self.set_maximum_button.clicked.connect(self.set_maximum_button_clicked) + bb.accepted.connect(self.accept) + bb.rejected.connect(self.reject) + + def reject(self): + self.view.setColumnWidth(self.column, self.original_size) + QDialog.reject(self) + + def set_maximum_button_clicked(self): + # Do this dance in case the current width exceeds the maximum, which can + # happen if the user is playing across multiple monitors + self.spin_box.setValue(self.maximum_size-1) + self.spin_box.setValue(self.maximum_size) + + def set_minimum_button_clicked(self): + self.spin_box.setValue(self.minimum_size) + + def shrink_button_clicked(self): + w = int(self.view.horizontalHeader().sectionSize(self.column) * 0.9) + self.spin_box.setValue(w) + + def expand_button_clicked(self): + w = int(self.view.horizontalHeader().sectionSize(self.column) * 1.1) + self.spin_box.setValue(w) + + def spin_box_changed(self, val): + self.view.setColumnWidth(self.column, val) +# }}} + + @setup_dnd_interface class BooksView(QTableView): # {{{ @@ -508,6 +593,8 @@ class BooksView(QTableView): # {{{ partial(self.resize_column_to_fit, view, col)) ans.addAction(_('Resize column to fit contents'), partial(self.fit_column_to_contents, view, col)) + ans.addAction(_('Manually adjust column size'), + partial(self.manually_adjust_column_size, view, col, name)) ans.addAction(_('Restore default layout'), partial(handler, action='defaults')) if self.can_add_columns: ans.addAction( @@ -940,6 +1027,10 @@ class BooksView(QTableView): # {{{ col = self.column_map.index(column) view.resizeColumnToContents(col) + def manually_adjust_column_size(self, view, column, name): + col = self.column_map.index(column) + AdjustColumnSize(view, col, name).exec_() + def column_resized(self, col, old_size, new_size): restrict_column_width(self, col, old_size, new_size)