Skip to content
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

Merged
merged 11 commits into from
Dec 17, 2016

Conversation

daschuer
Copy link
Member

@daschuer daschuer commented Dec 9, 2016

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

}

QWidget* LegacySkinParser::parseWidgetGroup(const QDomElement& node) {
WWidgetGroup* pGroup = new WWidgetGroup(m_pParent);
Copy link
Contributor

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

Copy link
Member Author

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.

Copy link
Contributor

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>
Copy link
Contributor

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

Copy link
Contributor

@Be-ing Be-ing left a 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>
Copy link
Contributor

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 =
Copy link
Contributor

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)

@daschuer
Copy link
Member Author

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.

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.

This was referenced Dec 11, 2016
<Pos>9,5</Pos>
<Size>170,90</Size>
<Layout>vertical</Layout>
<HighlightingGroup>
Copy link
Contributor

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?

Copy link
Contributor

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?

Copy link
Member Author

@daschuer daschuer Dec 15, 2016

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)
Copy link
Contributor

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.

Copy link
Member Author

@daschuer daschuer Dec 15, 2016

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.

Copy link
Contributor

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.

Copy link
Contributor

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.

Copy link
Member Author

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 ...

Copy link
Member Author

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.

Copy link
Contributor

@Be-ing Be-ing Dec 16, 2016

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.

Copy link
Member Author

@daschuer daschuer Dec 16, 2016

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>
Copy link
Contributor

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.

Copy link
Member Author

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.

@rryan
Copy link
Member

rryan commented Dec 16, 2016

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?

@daschuer
Copy link
Member Author

That would also work, but we need a new transformer type.
How about this:

<Transform>
    <Is>5</Is>
</Transform> 

@Be-ing
Copy link
Contributor

Be-ing commented Dec 16, 2016

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?

@rryan
Copy link
Member

rryan commented Dec 16, 2016

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]

@rryan
Copy link
Member

rryan commented Dec 16, 2016

Are there any intentions to move to QML in the future?

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 :).

@Be-ing
Copy link
Contributor

Be-ing commented Dec 16, 2016

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.

@daschuer daschuer changed the title HighlightingGroup for effects Highlight feature for WidgetGroup Dec 17, 2016
@daschuer
Copy link
Member Author

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.

@ywwg
Copy link
Member

ywwg commented Dec 17, 2016

QML skins

VERSION THREE POINT ZERO :)

@rryan
Copy link
Member

rryan commented Dec 17, 2016

Nice, thanks for the changes! code looks good to me

Copy link
Contributor

@Be-ing Be-ing left a 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
Copy link
Contributor

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"

@daschuer
Copy link
Member Author

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 is.

Correct!

@daschuer
Copy link
Member Author

Thank you for review!

@@ -60,7 +59,6 @@
</Template>
</Children>
<Connection>
<ConfigKey>[Microphone],show_microphone</ConfigKey>
<BindProperty>highlight</BindProperty>
Copy link
Contributor

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.

Copy link
Member Author

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.

Copy link
Contributor

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. 👍

@daschuer daschuer merged commit 2ba33ad into mixxxdj:master Dec 17, 2016
@daschuer
Copy link
Member Author

Wiki is updated

@Be-ing
Copy link
Contributor

Be-ing commented Dec 19, 2016

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.

@daschuer
Copy link
Member Author

Oh Sorry, I see there is

    style()->polish(this);

missing in WWidgetGroup::setHighlight()

@daschuer daschuer deleted the single_effect_focused branch September 7, 2021 21:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants