-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add WCollapsibleGroupBox, use for controller mapping info boxes and settings #14324
base: main
Are you sure you want to change the base?
Conversation
0166ab4
to
160c07b
Compare
160c07b
to
eb616c7
Compare
eb616c7
to
bbe7749
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM 👍 Just a few small comment-related nitpicks. No major objections.
const QString title = pBox->title(); | ||
pBox->setCheckable(true); | ||
if (m_settingsCollapsedStates.contains(title)) { | ||
pBox->setChecked(m_settingsCollapsedStates.value(title)); | ||
} | ||
|
||
connect(pBox, | ||
&WCollapsibleGroupBox::toggled, | ||
this, | ||
[this, title](bool checked) { | ||
m_settingsCollapsedStates.insert(title, checked); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will slightly misbehave when multiple groups have the same title. I think that's OK, but maybe we should add a comment similar to this:
// Note: If multiple groups happen to have the same name (which should
// not normally happen in well-behaved controller mappings, but is not
// strictly prohibited), the last one to be expanded/collapsed determines
// the state that will be restored.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
how about we just store whether the groupbox is collapsed in the groupbox itself?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIUC, the MIDI learning wizard can cause the mapping to be reloaded while the preferences dialog is open, and this is an attempt to restore the expansion state in that case (because reloading also means that the mapping-defined GUI widgets are destroyed and recreated).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that, too. The primary reason we need (want) to restore the state in the first place is that the settings widgets are rebuild every time the Preferences are shown. Same when pressing Cancel.
We may re-show the mapping only if it has been changed (I/O mapping, setting(s)). Eg. we could compare each setting's value with its saved value (when a setting is toggled on and of again) and somehow link that to mapping->setDirty().
But that seems a lot of work compared to the QHash implementation.
Thanks for your review! I pushed the fixup and will squash before merge. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
couple thoughts
const QString title = pBox->title(); | ||
pBox->setCheckable(true); | ||
if (m_settingsCollapsedStates.contains(title)) { | ||
pBox->setChecked(m_settingsCollapsedStates.value(title)); | ||
} | ||
|
||
connect(pBox, | ||
&WCollapsibleGroupBox::toggled, | ||
this, | ||
[this, title](bool checked) { | ||
m_settingsCollapsedStates.insert(title, checked); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
how about we just store whether the groupbox is collapsed in the groupbox itself?
auto pContainer = make_parented<QGroupBox>(m_label, pParent); | ||
auto pContainer = make_parented<WCollapsibleGroupBox>(m_label, pParent); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wdyt of making this configurable in the settings XML? Shouldn't be hard IMO.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mean with an extra xml node?
If yes, I 'd rather not put that work on mapping developers. I mean collapsing top-level groups is desirable, and on lower levels it only makes the GUI more complex.
But maybe we can check if the groupbox' parent is a WCollapsibleGroupBox, too, and auto-set checkable if it's not.
Will check..
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Naa, we already query the groups in DlgPrefController so that's the place to set the checkable IMO.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mean with an extra xml node?
Either that or add an attribute to the node
If yes, I 'd rather not put that work on mapping developers.
Right. On the flipside (and why I was suggesting to make it configurable), what if devs really want some settings to be easily visible and hide others (more advances ones for instance)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah okay, so you're proposing to allow setting the default collapsed
state in xml (not the collapsible feature in general).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, that works too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the idea of the collapsed
default state! I was looking at adding some kin d of depends
or condition
to help with the large amount of settings in #13653, but this looks like anm elegant solution to address this with a minimum effort.
c91d5d5
to
6d6e02a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for adding this, this is looking very good! Just some minor comments and feedbacks
auto pContainer = make_parented<QGroupBox>(m_label, pParent); | ||
auto pContainer = make_parented<WCollapsibleGroupBox>(m_label, pParent); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the idea of the collapsed
default state! I was looking at adding some kin d of depends
or condition
to help with the large amount of settings in #13653, but this looks like anm elegant solution to address this with a minimum effort.
WCollapsibleGroupBox::WCollapsibleGroupBox(QWidget* pParent) | ||
: QGroupBox(pParent), | ||
m_minH(-1), | ||
m_maxH(10000) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we use a constant here? Or maybe some std::numeric_limits
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried std::numeric_limits<int>::quiet_NaN()
earlier but it didn't work as expected, and I was lazy / it was late ; )
Will check again..
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, that's only available for floating-point types.
so std::numeric_limits<T>::min
seems to be the only applicable member?
} | ||
|
||
bool WCollapsibleGroupBox::event(QEvent* pEvent) { | ||
if (isCheckable()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you please refactor some of these nested condition to flatten it and use early return instead? It is a bit hard to follow at the moment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, I'll try.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Though early return isn't really applicable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (isCheckable()) { | |
if (!isCheckable()) { | |
// Only enable the special expand/collapse behaviors | |
// when the users has requested them via setCheckable(true). | |
// Otherwise, this should just behave like a normal QGroupBox. | |
QGroupBox::event(pEvent); | |
return; | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that's the only one.
class CollapsibleGroupBoxStyle : public QProxyStyle { | ||
Q_OBJECT | ||
public: | ||
explicit CollapsibleGroupBoxStyle(QStyle* pStyle = 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be nullptr
instead of 0
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Umm, right.
Seems I mixed up the original Qt implementation with that of ctkCollapsibleGroupBox
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
explicit CollapsibleGroupBoxStyle(QStyle* pStyle = 0) | |
explicit CollapsibleGroupBoxStyle(QStyle* pStyle = nullptr) |
int m_minH; | ||
int m_maxH; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does H
stands for "height" here? How do you feel about making it explicit?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, no prob: m_minHeight, m_maxHeight then
I already have an additional use case for Also, could you make sure/test that the
Footnotes
|
} else if (pEvent->type() == QEvent::LayoutRequest || | ||
pEvent->type() == QEvent::ContentsRectChange || | ||
pEvent->type() == QEvent::Resize) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might make sense to replace this if/else
blocks with a switch
.
This adds a QGroupBox-derived
![Screenshot_2025-02-12_18-16-08](https://private-user-images.githubusercontent.com/5934199/412538935-a121cecb-1419-4736-9dd4-dbd5b98c6acc.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk2ODM5ODUsIm5iZiI6MTczOTY4MzY4NSwicGF0aCI6Ii81OTM0MTk5LzQxMjUzODkzNS1hMTIxY2VjYi0xNDE5LTQ3MzYtOWRkNC1kYmQ1Yjk4YzZhY2MucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI1MDIxNiUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNTAyMTZUMDUyODA1WiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9MWNhMGMwMjY0MzBjYzNiNGFiMTZhZWQ3NjNlMzg0ZTA2ZjliNmYwMDczYTM5YjY1OGQ3ZDY0NWQyZjkyZTg3OCZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.HGkp7GyBvGa5po4kUxk6CiCJH6MIwYVzjcehEFYPNzw)
WCollapsibleGroupBox
that can be collapsed/expanded by clicking its title.IMHO this fixes the regression with the new tab'ed controller page where the device and mapping info would push the setting and I/O tabs down.
It also allows to focus on a certain settings group when adjusting the mapping.
(they are expanded every time the controller page is shown because the controller settings are rebuild each time)
WCollapsibleGroupBox
abusesQGroupBox::setChecked()
mechanism. Originally this is a checkbox in the title bar and toggling it enables/disables all children.Adopting this saves us from reimplementing the checked state tracking, signal etc.
This is not touched but also irrelevant since the content is now hidden anyway when it's collapsed.
Collapsing is achieved by simply setting the maximum height to height of the title row.
Inspired by ctkCollapsibleGroupBox, just without the complexity of hiding/showing child widgets (which requires some small, low-risk hacks to get the appearance right under all circumstances).
I imagine this groupbox can be helpful in other preferences pages, too.
(as quick fix for long pages, compared to restructuring into tab or otherwise splitting pages)