-
-
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
Highlight feature for WidgetGroup #1068
Conversation
} | ||
|
||
QWidget* LegacySkinParser::parseWidgetGroup(const QDomElement& node) { | ||
WWidgetGroup* pGroup = new WWidgetGroup(m_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.
Why don't you use unique_ptr
? It's generally considered bad practice to use naked new
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.
We must not mix smart pointers with the Qt object tree, which manages the widget lifetime just right.
This widget is added to the object tree here:
https://github.com/mixxxdj/mixxx/pull/1068/files/9b7ac9a01c34812922b73f48ec328eba820b0433#diff-c2c84548a4801a7ca8649f1095e0bf36L601
Some time ago we have tested the object tree performance versus smart pointer solutions.
The object tree has won.
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 I didn't know about that
<Size>170,90</Size> | ||
<Layout>vertical</Layout> | ||
<HighlightingGroup> | ||
<Id>1</Id> |
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.
tabs and spaces are mixed, throwing off alignment on GitHub's web view
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 implementing this. It generally looks good, although I am doubtful that changing a background image is how this should generally be used. What I had in mind was changing a border to indicate highlighting. It looks like this should be possible by using QSS with this.
Q_PROPERTY(int highlight READ getHighlight WRITE setHighlight NOTIFY highlightChanged) | ||
|
||
// The highlightedId property is used to select the highlighted widget | ||
// group by it's Id, which can be set from skin by <Id>4</Id> |
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.
typo in comment: "its"
WWidgetGroup::setup(node, context); | ||
|
||
// Set background pixmap for the highlighted state | ||
QDomElement backPathNodehighlighted = |
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.
capitalize "H" (backPathNodeHighlighted rather than backPathNodehighlighted)
Yes, changing the background in Shade is just the proof of concept that this works, even if color schemes are used. Using #MyGroup[highlight="1"] { } you can change any style-able property. |
<Pos>9,5</Pos> | ||
<Size>170,90</Size> | ||
<Layout>vertical</Layout> | ||
<HighlightingGroup> |
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 find it confusing that HighlightingGroups are children of ordinary WidgetGroups. I think there should be a different name for the parent, maybe HighlightingGroupContainer?
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.
Also, HighlightingGroup
isn't a great name considering any QSS property could be changed. How about SelectionGroup
and SelectionGroupContainer
?
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 case here is somehow random. A HighlightingGroup Group is just a Widget that can be highlighted. It can be placed at any place where you can place a WidgetGroup as well. It is just a WidgetGroup with highlighting features.
There is also no need to place other HighlightingGroup as siblings into a WidgetGroup. You can spread them all over the skin.
The word "selected" has already a Qt css meaning. I did not fell in love with the word "highlight", but I picked it, because it is not used in any default Qt style pseudo states, so it should be less confusing. We can pick any other name if you know a better unused one.
|
||
// The highlightedId property is used to select the highlighted widget | ||
// group by its Id, which can be set from skin by <Id>4</Id> | ||
Q_PROPERTY(int highlightedId READ getHighlight WRITE setHighlightedId NOTIFY highlightChanged) |
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.
highlightedId
should be a property of the parent of the groups that could be highlighted. The groups that can be highlighted should have their own binary highlighted
property.
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.
Currently widgets, which are controlled by the same CO, are grouped by the same connection to its highlightedId property, not by its parent widget. This allows much more flexibility for the skinner since he can place highligted widget wherever he likes it.
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 provides more flexibility, but to me it does not really fit the idea of selecting one member of a group. What do we really want to provide with this? A general way for skins to apply different styles in response to changes in COs? I like that idea, but I don't think the concept of a highlightedId
makes much sense with it. An ID implies that it is one member of a group. Perhaps we should have a general way for a QSS-accessible property to mirror the state of a CO. For example:
in skin XML:
<WidgetGroup>
<ObjectName>ExampleWidgetGroup</ObjectName>
<Children>
whatever widgets here
</Children>
</WidgetGroup>
<Connection>
<Connection>[Channel1],play</Connection>
<BindProperty>connection</BindProperty>
</Connection>
in skin QSS:
#ExampleWidgetGroup[connection="1"] {
style to apply when [Channel1],play is 1
}
This will allow different styles to be applied for each state of a CO, not just 0 and 1.
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 it was possible to change whether WidgetGroups are visible as well as their sizeHint and SizePolicy through QSS, that would be great.
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.
Your example is already possible with this PR. Except that the property is not "connection" but "highlightedId"
I can easily think of examples where the HighligtingGroup can be used and the the cannot be in a common parent widget. Think of highlighting an Deck switch indicator or something .. or a solution where you can hide effect 3 + 4 or have a splitter between effect 1 + 2 and 3 + 4 or ...
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.
Is there a confusion due to the ID member? Maybe the name is wrong. It is the common ID of all widgets that are highlighted if the connected CO has the ID value.
If you have two HighligtingGroups with ID=4 both are highlighted if the connected control has the value 4.
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, the choice of the name <Id>
was confusing. I think that element is unnecessary and limiting. The way it is, the QSS can only react to a binary condition of whether the CO is at a specified value. The value of the bound CO should be accessible through QSS so the QSS can easily handle COs with more than 2 states. I think it would make more sense to make this a general capability of <WidgetGroup>
rather than create a new element type.
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.
Since is optional, you can use the ID, as shown in this PR or not like you describe.
The use-case for the ID value works like that:
Creat n HighligtingGroups and name them EffectBackground. Set the ID of the first HighligtingGroup to 1 and up to the n'th HighligtingGroup to n. Bind the highlightedId property of each to the same CO, wich can have the values 0 ... n
Now you can style all these groups with a single style like that:
#EffectBackground {
/*default style*/
}
#EffectBackground[highlight="1"] {
/*higlighted style*/
}
Without that ID feature, each of the EffectBackgrounds need an individual name and an individual style. The color schema changing background will similar hard to use since you have to define a background for each of the N states.
I have made this feature separate, because it is more attracting for the user and a bit resource saving RAM/CPU. Remember that the majority of groups are happy with the default QT states.
But If you think it is a benefit to merge HighligtingGroups and WidgetGroups I can do it.
Should I?
// <Connection> | ||
// <ConfigKey>[EffectRack1_EffectUnit1],single_effect_focus</ConfigKey> | ||
// <BindProperty>highlightedId</BindProperty> | ||
// </Connection> |
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 Connection
should be on the parent, not the children.
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.
Since each HighlightingGroup is independent, it needs its own connection.
I would prefer that we not introduce a dedicated widget for this -- I think we can already make it work without introducing new concepts. What about doing this with Transform and BindProperty? Set the highlight property with a BindProperty / Transform to massage the CO value into a boolean (e.g. matching against the selected effect) and then use QSS attribute selectors for the rest. WDYT? |
That would also work, but we need a new transformer type.
|
I think that's a good way to accomplish what we're seeking here. We're treading close to pseudo-scripting-with-XML territory here. It seems there was a branch for QML skins years ago that was never merged. Are there any intentions to move to QML in the future? |
Sounds good to me -- they aren't invertible so maybe we could record in the transform when it's not invertible and then print a skin warning if you use it in a bidirectional situation? Would also be nice to have some more comparison operators e.g. Greater[Equal]/Less[Equal] |
From my perspective, definitely -- I have code that depends on #941 that introduces QML skins (and I've even gotten a very stripped down Mixxx running on Android). All the features we added to the skin system in the past year or so (templates, resizing, etc.) were mostly to allow us to keep limping along and get the features we needed for 2.0 done. I'd like to ditch the qt-widgets skin system at the first opportunity :). |
Cool, I've been thinking QML would be helpful for controller mappings to control how off screen rendering for controller screens could work. FWIW, that is what Traktor does. |
The transformer based solution is done. A GreaterThan transformer and friend is not required, since we have the Add transformer, and the x > 0.0 boolean conversion schema which should be sufficient for these potential use-cases. |
VERSION THREE POINT ZERO :) |
Nice, thanks for the changes! code looks good to me |
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.
To clarify, the transform is not necessary, correct? If I understand correctly, without that, the new highlight
property will be set to whatever the value of the bound <ConfigKey>
is.
Please document this on the wiki and note it is new in 2.1
@rryan : there's a TODO for you on the wiki to document <Connection>
VERSION THREE POINT ZERO :)
+3!
@@ -35,17 +35,44 @@ class WWidgetGroup : public QFrame, public WBaseWidget { | |||
Q_PROPERTY(QRect layoutContentsMargins READ layoutContentsMargins WRITE setLayoutContentsMargins DESIGNABLE true); | |||
Q_PROPERTY(Qt::Alignment layoutAlignment READ layoutAlignment WRITE setLayoutAlignment DESIGNABLE true); | |||
|
|||
// A WWidgetGroup can be also used to highlight a group of widgets by |
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.
nit: word order should be "can also be used"
Correct! |
Thank you for review! |
@@ -60,7 +59,6 @@ | |||
</Template> | |||
</Children> | |||
<Connection> | |||
<ConfigKey>[Microphone],show_microphone</ConfigKey> | |||
<BindProperty>highlight</BindProperty> |
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.
Remove the whole <Connection>
element if it isn't doing anything.
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 is prepared to take the new CO once your work is merged.
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.
Oh, okay. LGTM then as long as it's documented on the wiki. 👍
Wiki is updated |
I added support for this to my branch for new Deere effects units in #1063 but it is not working. The highlight="1" style is only applied for the effect that has its focused CO set to 1 when the skin is loaded. Changing the focused CO after loading the skin does not update the styles. You can test by building my personal branch that has #1063 and #1062 merged into it. |
Oh Sorry, I see there is
missing in WWidgetGroup::setHighlight() |
This PR introduce a new WidgetGroup, that allows to change the style according to a binary ControlObject, or by comparing an Index value.
The Shade skin demonstrates this behavior by using the [Microphone],show_microphone CO to change the effect background.
This should help to finish #1062
Usage details you find in src/widget/whighlightinggroup.h