Skip to content

Commit

Permalink
Merge pull request #13990 from ronso0/controller-sett-scrollSafeGuard
Browse files Browse the repository at this point in the history
(fix/UX) set scrollSafeGuard also for controller settings widgets
  • Loading branch information
Swiftb0y authored Dec 7, 2024
2 parents 80fd83d + aad2abc commit d3a3c87
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 45 deletions.
7 changes: 6 additions & 1 deletion src/controllers/dlgprefcontroller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -861,7 +861,12 @@ void DlgPrefController::slotShowMapping(std::shared_ptr<LegacyControllerMapping>
}
}

m_ui.groupBoxSettings->setVisible(!settings.isEmpty());
if (settings.isEmpty()) {
m_ui.groupBoxSettings->setVisible(false);
} else {
m_ui.groupBoxSettings->setVisible(true);
setScrollSafeGuardForAllInputWidgets(m_ui.groupBoxSettings);
}
}

// If there is still settings that may be saved and no new mapping selected
Expand Down
72 changes: 30 additions & 42 deletions src/preferences/dialog/dlgpreferencepage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,62 +21,50 @@ QUrl DlgPreferencePage::helpUrl() const {
return QUrl();
}

void DlgPreferencePage::setScrollSafeGuardForAllInputWidgets(QObject* obj) {
void DlgPreferencePage::setScrollSafeGuardForAllInputWidgets(QObject* pObj) {
// Set the focus policy to for scrollable input widgets and connect them
// to the custom event filter
for (auto* ch : obj->children()) {
// children() does not descend into QGroupBox,
// so we need to do it manually
QGroupBox* gBox = qobject_cast<QGroupBox*>(ch);
if (gBox) {
setScrollSafeGuardForAllInputWidgets(gBox);
continue;
}

QComboBox* combo = qobject_cast<QComboBox*>(ch);
if (combo) {
setScrollSafeGuard(combo);
continue;
}
QSpinBox* spin = qobject_cast<QSpinBox*>(ch);
if (spin) {
setScrollSafeGuard(spin);
continue;
}
QDoubleSpinBox* spinDouble = qobject_cast<QDoubleSpinBox*>(ch);
if (spinDouble) {
setScrollSafeGuard(spinDouble);
continue;
}
QSlider* slider = qobject_cast<QSlider*>(ch);
if (slider) {
setScrollSafeGuard(slider);
continue;
}
}
// to the custom event filter.
// Note: finding all relevant widgets with pObj->findchildren<Type*>
// is much faster than with
// for (auto* ch : pObj->children()) { qobject_cast<Type*>(ch); }
setScrollSafeGuardForChildrenOfType<QComboBox>(pObj);
setScrollSafeGuardForChildrenOfType<QSpinBox>(pObj);
setScrollSafeGuardForChildrenOfType<QDoubleSpinBox>(pObj);
setScrollSafeGuardForChildrenOfType<QSlider>(pObj);
}

void DlgPreferencePage::setScrollSafeGuard(QWidget* pWidget) {
pWidget->setFocusPolicy(Qt::StrongFocus);
pWidget->installEventFilter(this);
}

bool DlgPreferencePage::eventFilter(QObject* obj, QEvent* e) {
if (e->type() == QEvent::Wheel) {
// Reject scrolling only if widget is unfocused.
template<typename T>
void DlgPreferencePage::setScrollSafeGuardForChildrenOfType(QObject* pObj) {
QList<T*> children = pObj->findChildren<T*>();
for (T* pChild : children) {
setScrollSafeGuard(pChild);
}
}

bool DlgPreferencePage::eventFilter(QObject* pObj, QEvent* pEvent) {
if (pEvent->type() == QEvent::Wheel) {
// Reject scrolling if widget is not focused.
// Object to widget cast is needed to check the focus state.
QComboBox* combo = qobject_cast<QComboBox*>(obj);
QSpinBox* spin = qobject_cast<QSpinBox*>(obj);
QDoubleSpinBox* spinDbl = qobject_cast<QDoubleSpinBox*>(obj);
QSlider* slider = qobject_cast<QSlider*>(obj);
QComboBox* combo = qobject_cast<QComboBox*>(pObj);
QSpinBox* spin = qobject_cast<QSpinBox*>(pObj);
QDoubleSpinBox* spinDbl = qobject_cast<QDoubleSpinBox*>(pObj);
QSlider* slider = qobject_cast<QSlider*>(pObj);
if ((combo && !combo->hasFocus()) ||
(spin && !spin->hasFocus()) ||
(spinDbl && !spinDbl->hasFocus()) ||
(slider && !slider->hasFocus())) {
QApplication::sendEvent(qobject_cast<QObject*>(layout()), e);
// QApplication::sendEvent(layout()->parent(), e); ??
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
QApplication::sendEvent(layout()->parent(), pEvent);
#else
QApplication::sendEvent(qobject_cast<QObject*>(layout()), pEvent);
#endif
return true;
}
}
return QObject::eventFilter(obj, e);
return QObject::eventFilter(pObj, pEvent);
}
8 changes: 6 additions & 2 deletions src/preferences/dialog/dlgpreferencepage.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@ class DlgPreferencePage : public QWidget {
"</html> ")
.arg(kWarningIconPath);

void setScrollSafeGuardForAllInputWidgets(QObject* obj);
void setScrollSafeGuardForAllInputWidgets(QObject* pObj);
/// Avoid undesired value changes when scrolling a preferences page while
/// the pointer is above an input widget (QSpinBox, QComboBox, QSlider):
/// * set the focus policy to Qt::StrongFocus (focusable by click & tab key)
/// * forward wheel events to the top-level layout
void setScrollSafeGuard(QWidget* pWidget);
bool eventFilter(QObject* obj, QEvent* e);
bool eventFilter(QObject* pObj, QEvent* pEvent);

QColor m_pLinkColor;

Expand Down Expand Up @@ -77,4 +77,8 @@ class DlgPreferencePage : public QWidget {
palette().text().color())
.name();
}

private:
template<typename T>
void setScrollSafeGuardForChildrenOfType(QObject* pObj);
};

0 comments on commit d3a3c87

Please sign in to comment.