From 8d3d28da09479e619ac428929159ab2734c75edc Mon Sep 17 00:00:00 2001 From: Charles Haley Date: Sun, 5 Jun 2022 17:40:51 +0100 Subject: [PATCH 1/2] Make the accelerator on &Show work. I am a bit concerned about why shift-tab works differently from tab. It clearly does, but perhaps because of a bug in Qt? In any event, without the code one gets stuck in the group box. --- .../gui2/preferences/create_custom_column.py | 30 +++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/src/calibre/gui2/preferences/create_custom_column.py b/src/calibre/gui2/preferences/create_custom_column.py index 3d5e3eab10..15b221dc0f 100644 --- a/src/calibre/gui2/preferences/create_custom_column.py +++ b/src/calibre/gui2/preferences/create_custom_column.py @@ -13,7 +13,7 @@ from functools import partial from qt.core import ( QDialog, Qt, QColor, QIcon, QVBoxLayout, QLabel, QGridLayout, QDialogButtonBox, QWidget, QLineEdit, QHBoxLayout, QComboBox, - QCheckBox, QSpinBox, QRadioButton, QGroupBox + QCheckBox, QSpinBox, QRadioButton, QGroupBox, pyqtSignal ) from calibre.gui2 import error_dialog @@ -22,6 +22,22 @@ from calibre.utils.date import parse_date, UNDEFINED_DATE from polyglot.builtins import iteritems +class GroupBox(QGroupBox): + # A group box for radio buttons that acts passes along focus events so the + # correct child button is given the focus + + got_focus = pyqtSignal() + + def focusInEvent(self, ev): + # We need this backtab focus stuff because a backtab from a radio button + # gives the focus back to the group box instead of the next widget in the + # focus chain. For some reason a tab doesn't do that. + if ev.reason() != Qt.FocusReason.BacktabFocusReason: + self.got_focus.emit() + else: + self.focusNextPrevChild(False) + + class CreateCustomColumn(QDialog): # Note: in this class, we are treating is_multiple as the boolean that @@ -332,7 +348,9 @@ class CreateCustomColumn(QDialog): h1.addWidget(self.bool_show_text_button) self.bool_show_both_button = QRadioButton(_('&Both')) h1.addWidget(self.bool_show_both_button) - self.bool_button_group = QGroupBox() + self.bool_button_group = GroupBox() + self.bool_button_group.setFocusPolicy(Qt.StrongFocus) + self.bool_button_group.got_focus.connect(self.bool_groupbox_focused) self.bool_button_group.setLayout(h1) h = QHBoxLayout() h.addWidget(self.bool_button_group) @@ -452,6 +470,14 @@ class CreateCustomColumn(QDialog): self.resize(self.sizeHint()) # }}} + def bool_groupbox_focused(self): + if self.bool_show_icon_button.isChecked(): + self.bool_show_icon_button.setFocus() + elif self.bool_show_text_button.isChecked(): + self.bool_show_text_button.setFocus() + else: + self.bool_show_both_button.setFocus() + def datatype_changed(self, *args): try: col_type = self.column_types[self.column_type_box.currentIndex()]['datatype'] From 9e5b656bd5f6233789a54d92421bc2eb97e50183 Mon Sep 17 00:00:00 2001 From: Charles Haley Date: Sun, 5 Jun 2022 21:37:47 +0100 Subject: [PATCH 2/2] This commit works the way I want, ensuring the checked button is focused while using 'vanilla' Qt. It doesn't work around the odd behavior of backtab. Apologies for the multiple commits. I don't know what happens if I remove commits in a pull request so I left them all. --- .../gui2/preferences/create_custom_column.py | 53 ++++++------------- 1 file changed, 17 insertions(+), 36 deletions(-) diff --git a/src/calibre/gui2/preferences/create_custom_column.py b/src/calibre/gui2/preferences/create_custom_column.py index 15b221dc0f..42de366f3e 100644 --- a/src/calibre/gui2/preferences/create_custom_column.py +++ b/src/calibre/gui2/preferences/create_custom_column.py @@ -13,7 +13,7 @@ from functools import partial from qt.core import ( QDialog, Qt, QColor, QIcon, QVBoxLayout, QLabel, QGridLayout, QDialogButtonBox, QWidget, QLineEdit, QHBoxLayout, QComboBox, - QCheckBox, QSpinBox, QRadioButton, QGroupBox, pyqtSignal + QCheckBox, QSpinBox, QRadioButton, QGroupBox ) from calibre.gui2 import error_dialog @@ -22,22 +22,6 @@ from calibre.utils.date import parse_date, UNDEFINED_DATE from polyglot.builtins import iteritems -class GroupBox(QGroupBox): - # A group box for radio buttons that acts passes along focus events so the - # correct child button is given the focus - - got_focus = pyqtSignal() - - def focusInEvent(self, ev): - # We need this backtab focus stuff because a backtab from a radio button - # gives the focus back to the group box instead of the next widget in the - # focus chain. For some reason a tab doesn't do that. - if ev.reason() != Qt.FocusReason.BacktabFocusReason: - self.got_focus.emit() - else: - self.focusNextPrevChild(False) - - class CreateCustomColumn(QDialog): # Note: in this class, we are treating is_multiple as the boolean that @@ -193,11 +177,11 @@ class CreateCustomColumn(QDialog): icon = bool(c['display'].get('bools_show_icons', True)) txt = bool(c['display'].get('bools_show_text', False)) if icon and txt: - self.bool_show_both_button.setChecked(True) + self.bool_show_both_button.click() elif icon: - self.bool_show_icon_button.setChecked(True) + self.bool_show_icon_button.click() else: - self.bool_show_text_button.setChecked(True) + self.bool_show_text_button.click() # Default values dv = c['display'].get('default_value', None) @@ -342,15 +326,16 @@ class CreateCustomColumn(QDialog): # bool formatting h1 = QHBoxLayout() - self.bool_show_icon_button = QRadioButton(_('&Icon')) - h1.addWidget(self.bool_show_icon_button) - self.bool_show_text_button = QRadioButton(_('&Text')) - h1.addWidget(self.bool_show_text_button) - self.bool_show_both_button = QRadioButton(_('&Both')) - h1.addWidget(self.bool_show_both_button) - self.bool_button_group = GroupBox() - self.bool_button_group.setFocusPolicy(Qt.StrongFocus) - self.bool_button_group.got_focus.connect(self.bool_groupbox_focused) + def add_bool_radio_button(txt): + b = QRadioButton(txt) + b.clicked.connect(partial(self.bool_radio_button_clicked, b)) + h1.addWidget(b) + return b + self.bool_show_icon_button = add_bool_radio_button(_('&Icon')) + self.bool_show_text_button = add_bool_radio_button(_('&Text')) + self.bool_show_both_button = add_bool_radio_button(_('&Both')) + self.bool_button_group = QGroupBox() + self.bool_button_group.setFocusPolicy(Qt.FocusPolicy.StrongFocus) self.bool_button_group.setLayout(h1) h = QHBoxLayout() h.addWidget(self.bool_button_group) @@ -470,13 +455,9 @@ class CreateCustomColumn(QDialog): self.resize(self.sizeHint()) # }}} - def bool_groupbox_focused(self): - if self.bool_show_icon_button.isChecked(): - self.bool_show_icon_button.setFocus() - elif self.bool_show_text_button.isChecked(): - self.bool_show_text_button.setFocus() - else: - self.bool_show_both_button.setFocus() + def bool_radio_button_clicked(self, button, clicked): + if clicked: + self.bool_button_group.setFocusProxy(button) def datatype_changed(self, *args): try: