-
-
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
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.
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.
Thanks for the feedback!
Though I'd love to merge the basic implementation first.
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.
I already have an additional use case for Also, could you make sure/test that the
Footnotes
|
src/widget/wcollapsiblegroupbox.cpp
Outdated
} 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
.
✔️ since we just hook up to the 'checked' state this is all handled correctly by QGroupBox
The same here: QGroupBox handles this. The original behavior of setChecked() is to enable/disable all children and we simply expect that to work. |
Btw I fixed soe other keyboard focus issue in the controller page (settings checkbox, more tabstops, don't focus hidden tabs ..) |
<widget class="QLabel" name="labelDataHandlingProtocolValue"> | ||
<layout class="QVBoxLayout" name="deviceInfoGroupLayout"> | ||
<item> | ||
<widget class="WCollapsibleGroupBox" name="groupBoxDeviceInfo"> |
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.
Please ensure that groupBoxDeviceInfo and groupBoxMappingInfoare always expanded, if no mapping is loaded to a device, as these boxes contain the information needed by the end user to select the correct mapping for the right device.
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.
By default these groups are expanded and remain so until the user explicitly collapses them.
And the most important info is the device name which is the big label in the top left corner.
What other info do you refer to?
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.
The text in the big label is not unique, this is why Device Info was implemented for 2.6. On my system I have 3 devices with exactly the same string:
This is normal because this string depends on assumptions that are only sometimes true. This was addressed by adding the device info box. If this information is hidden, the user has no chance to distinguish the devices.
There is no use case for collapsing these 2 boxes of valuable information needed for the mapping selection, until a mapping is loaded. This is because the tabs below are hidden at this time and enough space is available to show them.
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 understand. Still, the groups are expanded by default and the state is persistent per controller page. And the device order in the sidebar is also persistent. Collapsing is optional and done manually. So if you don't need it, don't use it.
In the case of multiple devices with the same display name, why would a user collapse the info if they need it to make sure it's the correct device?
I mean, sure we can somehow force-expand the device info when 'No mapping' is selected but which exact use case would that cover?
I'm not a fan of GUI elements being shifted / shown with for obvious reason.
m_minH(-1), | ||
m_maxH(10000) { | ||
m_minHeight(-1), | ||
m_maxHeight(QWIDGETSIZE_MAX) { |
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.
Nice 💯 ! I didn't know about this macro
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.
Code LGTM! Will take that for a spin in a bit
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.
There is a weird glitch when expending a collapsed group. tested on Fedora 41 (Wayland)
Screencast.From.2025-02-17.23-12-28.mp4
I'm seeing this, too, if I look for it. |
Hmm, I traced the layout / resize events and it seems there is no easy fix: Maybe sequential hiding/showing of the group children fixes it but I fear this also adds more complexity / more stuff to care about. Bit like it's done in ctkCollapsibleGroupBox which also resizes via |
No, it doesn't.
The weird thing is: it also happens when a group is collapsed.. so in that case the layout seems to shrink before the box is actually collapsed, squeezing the groups above. These are extemely hard to debug/trace and I wasted countless hours already fixing (or trying to) some Mixxx dialogs. |
Yeah, I'll stop working on this (fix). Btw when collapsing a group, the parent QScrollArea might toggle the vertical scrollbars which is another resize reason. I think we either have to live with this Qt glitch, or delay this PR until someone finds a fix. |
Tbh, I'm happy living with this bug. It's a small discomfort, but doesn't fundamentally prevent or break anything. Thanks for trying anyway! |
f06af1e
to
4beaa90
Compare
Alright then, thanks for your review! @JoergAtGithub Could I dispel your concerns re the Device/Mapping groups? |
This adds a QGroupBox-derived

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)