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)