Fetching the stylesheet of Maya

2,179 views
Skip to first unread message

Fredrik Averpil

unread,
Mar 10, 2015, 12:19:25 PM3/10/15
to python_in...@googlegroups.com
Anyone know how to fetch the stylesheet of Maya 2015?

I've tried this:

from PyQt4 import QtGui, QtCore
import sip
import maya.OpenMayaUI as mui

def get_maya_window():
    """Get the maya main window as a QMainWindow instance"""
    ptr = mui.MQtUtil.mainWindow()
    return sip.wrapinstance(long(ptr), QtCore.QObject)

maya_win = get_maya_window()
stylesheet = maya_win.styleSheet()


But there's no stylesheet to be found there...

Regards,
Fredrik

Marcus Ottosson

unread,
Mar 10, 2015, 12:29:17 PM3/10/15
to python_in...@googlegroups.com
Fetch the stylesheet? I don't think there is such a thing. The stylesheet you put into Qt is immediately parsed into native attributes and then discarded. 

Have you managed this in previous versions of Maya?

Fredrik Averpil

unread,
Mar 10, 2015, 12:35:52 PM3/10/15
to python_in...@googlegroups.com
No, I haven't.
To be honest, I'm trying to snatch the complete stylesheet from Maya (if at all possible) to use that look in one of my UIs which runs outside of Maya.

But it seems maybe this is not possible at all.

// Fredrik


On Tue, Mar 10, 2015 at 5:29 PM Marcus Ottosson <konstr...@gmail.com> wrote:
Fetch the stylesheet? I don't think there is such a thing. The stylesheet you put into Qt is immediately parsed into native attributes and then discarded. 

Have you managed this in previous versions of Maya?

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/CAFRtmOCrRyiYT_kAb_fJ1BjFDP2qkVjyZYbgbn%2BYQnajcMhLPA%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

Fredrik Averpil

unread,
Mar 10, 2015, 12:49:33 PM3/10/15
to python_in...@googlegroups.com
Getting closer ... (?)

from PySide.QtGui import QApplication
app = QApplication
print app.style().metaObject().className()
>> QadskDarkStyle

Hm, I wonder if I can somehow extract the CSS from this.

// Fredrik


On Tue, Mar 10, 2015 at 5:35 PM Fredrik Averpil <fredrik...@gmail.com> wrote:
No, I haven't.
To be honest, I'm trying to snatch the complete stylesheet from Maya (if at all possible) to use that look in one of my UIs which runs outside of Maya.

But it seems maybe this is not possible at all.

// Fredrik


On Tue, Mar 10, 2015 at 5:29 PM Marcus Ottosson <konstr...@gmail.com> wrote:
Fetch the stylesheet? I don't think there is such a thing. The stylesheet you put into Qt is immediately parsed into native attributes and then discarded. 

Have you managed this in previous versions of Maya?

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_maya+unsub...@googlegroups.com.

Tony Barbieri

unread,
Mar 10, 2015, 1:23:07 PM3/10/15
to python_in...@googlegroups.com

Hey Fredrik,

I believe Maya is actually using an Application wide QPalette and the QApplication is using the "Plastique" style.  The following code I took from elsewhere but hopefully you get the general idea.

base_palette = QtGui.QPalette()

HIGHLIGHT_COLOR = QtGui.QColor(103, 141, 178)
BRIGHTNESS_SPREAD = 2.5

BRIGHT_COLOR = QtGui.QColor(200, 200, 200)
LIGHT_COLOR = QtGui.QColor(100, 100, 100)
DARK_COLOR = QtGui.QColor(42, 42, 42)
MID_COLOR = QtGui.QColor(68, 68, 68)
MID_LIGHT_COLOR = QtGui.QColor(84, 84, 84)
SHADOW_COLOR = QtGui.QColor(21, 21, 21)

BASE_COLOR = MID_COLOR
TEXT_COLOR = BRIGHT_COLOR
DISABLED_BUTTON_COLOR = QtGui.QColor(78, 78, 78)
DISABLED_TEXT_COLOR = QtGui.QColor(128, 128, 128)
ALTERNATE_BASE_COLOR = QtGui.QColor(46, 46, 46)

if self.lightness(BASE_COLOR) > 0.5:
    SPREAD = 100 / BRIGHTNESS_SPREAD
else:
    SPREAD = 100 * BRIGHTNESS_SPREAD

if self.lightness(HIGHLIGHT_COLOR) > 0.6:
    HIGHLIGHTEDTEXT_COLOR= BASE_COLOR.darker(SPREAD*2)
else:
    HIGHLIGHTEDTEXT_COLOR= BASE_COLOR.lighter(SPREAD*2)

base_palette.setBrush(QtGui.QPalette.Window, QtGui.QBrush(MID_COLOR))
base_palette.setBrush(QtGui.QPalette.WindowText, QtGui.QBrush(TEXT_COLOR))
base_palette.setBrush(QtGui.QPalette.Foreground, QtGui.QBrush(BRIGHT_COLOR))
base_palette.setBrush(QtGui.QPalette.Base, QtGui.QBrush(DARK_COLOR))
base_palette.setBrush(QtGui.QPalette.AlternateBase, QtGui.QBrush(ALTERNATE_BASE_COLOR))
base_palette.setBrush(QtGui.QPalette.ToolTipBase, QtGui.QBrush(BASE_COLOR))
base_palette.setBrush(QtGui.QPalette.ToolTipText, QtGui.QBrush(TEXT_COLOR))

base_palette.setBrush(QtGui.QPalette.Text, QtGui.QBrush(TEXT_COLOR))
base_palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Text, QtGui.QBrush(DISABLED_TEXT_COLOR))

base_palette.setBrush(QtGui.QPalette.Button, QtGui.QBrush(LIGHT_COLOR))
base_palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Button, QtGui.QBrush(DISABLED_BUTTON_COLOR))
base_palette.setBrush(QtGui.QPalette.ButtonText, QtGui.QBrush(TEXT_COLOR))
base_palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.ButtonText, QtGui.QBrush(DISABLED_TEXT_COLOR))
base_palette.setBrush(QtGui.QPalette.BrightText, QtGui.QBrush(TEXT_COLOR))
base_palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.BrightText, QtGui.QBrush(DISABLED_TEXT_COLOR))

base_palette.setBrush(QtGui.QPalette.Light, QtGui.QBrush(LIGHT_COLOR))
base_palette.setBrush(QtGui.QPalette.Midlight, QtGui.QBrush(MID_LIGHT_COLOR))
base_palette.setBrush(QtGui.QPalette.Mid, QtGui.QBrush(MID_COLOR))
base_palette.setBrush(QtGui.QPalette.Dark, QtGui.QBrush(DARK_COLOR))
base_palette.setBrush(QtGui.QPalette.Shadow, QtGui.QBrush(SHADOW_COLOR))

base_palette.setBrush(QtGui.QPalette.Highlight, QtGui.QBrush(HIGHLIGHT_COLOR))
base_palette.setBrush(QtGui.QPalette.HighlightedText, QtGui.QBrush(HIGHLIGHTEDTEXT_COLOR))

# Setup additional palettes for QTabBar and QTabWidget to look more like
# maya.
tab_palette = QtGui.QPalette(base_palette)
tab_palette.setBrush(QtGui.QPalette.Window, QtGui.QBrush(LIGHT_COLOR))
tab_palette.setBrush(QtGui.QPalette.Button, QtGui.QBrush(MID_COLOR))

widget_palettes = {}
widget_palettes["QTabBar"] = tab_palette
widget_palettes["QTabWidget"] = tab_palette

QtGui.QApplication.setStyle("Plastique")
QtGui.QApplication.setPalette(base_palette)
for name, palette in widget_palettes.items():
    QtGui.QApplication.setPalette(palette, name)

To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/CAD%3DwhWPyozxHyjruv7_k8cx-EufpkuJyGVQ5LO1h0KkKbv548w%40mail.gmail.com.

For more options, visit https://groups.google.com/d/optout.



--
Tony

Fredrik Averpil

unread,
Mar 10, 2015, 1:36:59 PM3/10/15
to python_in...@googlegroups.com
That's awesome Tony, thanks!

I wonder how the person who came up with this extracted the data though.


Regards,
Fredrik



Marcus Ottosson

unread,
Mar 10, 2015, 1:57:03 PM3/10/15
to python_in...@googlegroups.com

To be honest, I’m trying to snatch the complete stylesheet from Maya (if at all possible) to use that look in one of my UIs which runs outside of Maya.​

The problem is Maya doesn’t have a stylesheet.

Qt supports parsing of CSS-like* stylesheets that is then converted into commands similar to what Tony posted. But once they’re converted, the stylesheet you passed is out of the game. That’s why you can’t get the full stylesheet, because even if one were used to initially create the look - which may not be the case at all - it would never have been stored into the application to begin with.

You could potentially reverse-engineer part of it by querying the brushes and pens of each QWidget.

*CSS-like, as in, not all CSS-features are included. See here for more: http://qt-project.org/doc/qt-4.8/stylesheet.html

Tony Barbieri

unread,
Mar 10, 2015, 2:03:56 PM3/10/15
to python_in...@googlegroups.com
I ran across the QPalette concept via google awhile ago.  It was originally to mimic Nuke's look and feel.  As for the colors, I used screen captures and the color picker in Photoshop.


For more options, visit https://groups.google.com/d/optout.



--
Tony

Tony Barbieri

unread,
Mar 10, 2015, 2:10:32 PM3/10/15
to python_in...@googlegroups.com
Looks like it was from Thorsten Kaufmann's Github that I found the concept: https://github.com/instinct-vfx/QColorscheme/blob/master/src/QColorScheme/QColorScheme.py

Wanted to make sure he got the credit for it!  All I did was figure out the Maya colors to use.
--
Tony

Justin Israel

unread,
Mar 10, 2015, 2:21:31 PM3/10/15
to python_in...@googlegroups.com

I am not sure this information is accurate. Stylesheets and QPalette/QStyle are two different things. If you use a stylesheets it takes priority over a palette, and setting a stylesheet doesn't transform it into a QPalette that you can then access values of. That is actually a downside of stylesheets since you cannot introspect the colours and do lighter/darker variations. They are also supposedly a touch slower, albeit the are way more flexible to use.
Maya is most likely using a custom QStyle/palette and not stylesheets.

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.

To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/CAFRtmOCYpx6Z7diabhkosmvXR5NwbOB2bK555P_%3DXyC%3Dqp%2B2XA%40mail.gmail.com.

Marcus Ottosson

unread,
Mar 10, 2015, 3:09:25 PM3/10/15
to python_in...@googlegroups.com

and setting a stylesheet doesn’t transform it into a QPalette that you can then access values of.​

Sure it does. :)

Here’s an example of sampling the QPalette of a QWindow, setting a stylesheet, and then sampling again.
https://gist.github.com/mottosso/9f27229fa75815bf4969

The stylesheet is:

QWidget {
    background-color: "blue"
}

And the corresponding changes to the QPalette are:

Changed (Window) #444444 = #0000ff
Changed (Base) #2a2a2a = #0000ff
Changed (Background) #444444 = #0000ff
Changed (Button) #646464 = #0000ff

Basically, from various levels of gray (Maya default) to blue, where the parentheses name is the Role taken from QtGui.QPalette.

Justin Israel

unread,
Mar 10, 2015, 3:19:12 PM3/10/15
to python_in...@googlegroups.com

Apparently I can’t find an example off-hand of the limitations in wanting to query parent colors that were applied via a stylesheet, so I will have to dig through some of my code. I will also try to find the various posts I have found from others outlining the same limitations. It is related to situations where I have wanted to set a certain widgets colors to be lighter/darker than the parent, and the parent palette values did not reflect the actual stylesheet. 

But the part about the stylsheets being converted and not stored was definitely not right:

    app = QtGui.QApplication([])
    stylesheet = 'QWidget { background: #ff0000; }'
    app.setStyleSheet(stylesheet)
    assert(app.styleSheet() == stylesheet)

If the stylesheet value is set on the application, you should be able to ask for it back.

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.

Tony Barbieri

unread,
Mar 10, 2015, 3:20:17 PM3/10/15
to python_in...@googlegroups.com
Not adding much to the conversation with details but I have also hit the same limitation in the past.


For more options, visit https://groups.google.com/d/optout.



--
Tony

Marcus Ottosson

unread,
Mar 10, 2015, 5:07:33 PM3/10/15
to python_in...@googlegroups.com

But the part about the stylsheets being converted and not stored was definitely not right.

What you’re seeing there is merely the last command put into setStyleSheet, it doesn’t actually represent the sum of each individual command. Technically, the string is cached internally, into a private member of QApplication and discarded each time it is set.

You can prove that by setting it twice.

app.setStyleSheet("QWidget { background-color: 'blue' }")
app.setStyleSheet("QWidget { font: 'verdana' }")
assert app.styleSheet() == "QWidget { font: 'verdana' }"

What’s more, it also doesn’t take into account stylesheets applied to children within widgets or the application.

You can prove that by applying it to a widget first, and then application. As the widget is affected by the stylesheet, one might think it should be able to reproduce it.

widget = QtWidgets.QWidget()
app.setStyleSheet("QWidget { font: 'verdana' }")
assert widget.styleSheet() == ""

Which means that unless you’re certain that the setStyleSheet command was used only once, on only one object - either the QApplication, or a QWidget, which are the only objects that carry this method - then it’s quite difficult to be certain that what you get is what’s actually being drawn.

If you use a stylesheets it takes priority over a palette

I think it’s more a matter of which gets set last.

They are also supposedly a touch slower

Then what? In the above example, four QPalette roles are being set with only one CSS directive. Some may argue that this would be faster than setting each role manually; at least when it’s done from Python.

Maya is most likely using a custom QStyle/palette and not stylesheets.

They not necessarily mutually exclusive. Some things may be more easily set using stylesheets, whereas others are easier/only possible via QPalette.

It’s all in the source, folks.
https://qt.gitorious.org/qt

Marcus Ottosson

unread,
Mar 10, 2015, 5:18:17 PM3/10/15
to python_in...@googlegroups.com

They are also supposedly a touch slower

Actually, disregard my reply to that, that’s beside the point of the original question (and quite frankly, just plain bait, Justin! :))​

Justin Israel

unread,
Mar 10, 2015, 5:33:23 PM3/10/15
to python_in...@googlegroups.com
On Wed, Mar 11, 2015 at 10:07 AM Marcus Ottosson <konstr...@gmail.com> wrote:

But the part about the stylsheets being converted and not stored was definitely not right.

What you’re seeing there is merely the last command put into setStyleSheet, it doesn’t actually represent the sum of each individual command. Technically, the string is cached internally, into a private member of QApplication and discarded each time it is set.

You can prove that by setting it twice.

app.setStyleSheet("QWidget { background-color: 'blue' }")
app.setStyleSheet("QWidget { font: 'verdana' }")
assert app.styleSheet() == "QWidget { font: 'verdana' }"

What’s more, it also doesn’t take into account stylesheets applied to children within widgets or the application.

Maybe this is just about expectations... because I had never had the expectation that multiple calls to setStyleSheet would be incremental changes to the previous stylesheet. I have always assume you are setting the whole stylesheet. In which case, it is storing the stylesheet for that object and using it as part of the cascading effect. "set" to me generally means to replace the previous value with a new value.
 

You can prove that by applying it to a widget first, and then application. As the widget is affected by the stylesheet, one might think it should be able to reproduce it.

widget = QtWidgets.QWidget()
app.setStyleSheet("QWidget { font: 'verdana' }")
assert widget.styleSheet() == ""

Which means that unless you’re certain that the setStyleSheet command was used only once, on only one object - either the QApplication, or a QWidget, which are the only objects that carry this method - then it’s quite difficult to be certain that what you get is what’s actually being drawn.


Again, expectations I suppose. It is a cascading system, so if a specific object never had a stylesheet value applied, then it only inherits from the parent and has no additional modifications.  
 

If you use a stylesheets it takes priority over a palette

I think it’s more a matter of which gets set last.


Well, the documentation does suggest that stylesheets should not be mixed with custom palettes: 

So I presume that to mean non-deterministic behaviour. You either try to fully go the stylesheet route, or custom palettes, is what I take away from that. And based on my past experience of having some reference issues to palette values in combination with stylesheets (as Tony had also confirmed), I tend to believe the non-deterministic behaviour is real. 
 

They are also supposedly a touch slower

Then what? In the above example, four QPalette roles are being set with only one CSS directive. Some may argue that this would be faster than setting each role manually; at least when it’s done from Python.

Maya is most likely using a custom QStyle/palette and not stylesheets.

They not necessarily mutually exclusive. Some things may be more easily set using stylesheets, whereas others are easier/only possible via QPalette.

It’s all in the source, folks.
https://qt.gitorious.org/qt

See above
 

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.

Marcus Ottosson

unread,
Mar 10, 2015, 5:48:45 PM3/10/15
to python_in...@googlegroups.com

If you use a stylesheets it takes priority over a palette

I think you’re right about that; this should otherwise have produced a yellow background, but it ends up blue.

window = QtWidgets.QWidget()
window.setFixedSize(800, 600)
window.show()

yellow = QtGui.QColor("yellow")
brush = QtGui.QBrush(yellow)
palette = app.palette()
palette.setBrush(QtGui.QPalette.Window, brush)

app.setStyleSheet("QWidget { background-color: 'blue' }")
app.setPalette(palette)

It looks like the reason is that stylesheets are parsed into an undocumented QStyleSheetStyle which then becomes a parent of the application style itself; via a call to setParent on the QStyle of the application.

I couldn’t find a search function in gitorious, but it’s on line 1087 of qapplication.cpp.

because I had never had the expectation that multiple calls to setStyleSheet would be incremental changes to the previous stylesheet.

No, you’re right, it doesn’t work the way I meant. The last call wipes out the call before it.

window = QtWidgets.QWidget()
window.setFixedSize(800, 600)
window.show()

app.setStyleSheet("QWidget { background-color: 'blue' }")
app.setStyleSheet("QWidget { border: 5px solid red }")

I was thinking of applying stylesheets incrementally to individual widgets. This will on the other hand apply the border to the window, whilst keeping it blue via cascading.

window = QtWidgets.QWidget()
window.setFixedSize(800, 600)
window.show()

app.setStyleSheet("QWidget { background-color: 'blue' }")
window.setStyleSheet("QWidget { border: 5px solid red }")

In any case, grabbing the stylesheet from QApplication in this latter case will not yield the stylesheet applied to the QWidget window.



For more options, visit https://groups.google.com/d/optout.



--
Marcus Ottosson
konstr...@gmail.com

Justin Israel

unread,
Mar 10, 2015, 5:54:48 PM3/10/15
to python_in...@googlegroups.com
Correct. There isn't any way to retrieve a fully baked stylesheet from anything, in either direction. 
 

Fredrik Averpil

unread,
Mar 11, 2015, 4:53:09 AM3/11/15
to python_in...@googlegroups.com
Hey guys,

I see you've been busy with this while I've been asleep ;)

So, it seems you are totally right I cannot fetch the stylesheet, as the UI needs to have been created using the qApp.setStylesheet(), which Autodesk seems not to have done (?). Thanks to Tony's post about QPalette, I started searching and so I found an old post on this list and added a few QPalette roles to the code in that email, and I'm very close to matching the Maya UI now -- by fetching the QPalette groups/roles values, writing those to file, and then setting that data along with the "plastique" style in my own PySide UI.


I'm going to try to list all groups and roles as well as the style instead of defining them in the code.

Also, I'm noticing that tab widgets don't look the same in Maya as in my app which is now using the Maya palette data. Perhaps Autodesk did an override of some sort on that widget type.

// Fredrik

Panupat Chongstitwattana

unread,
Mar 11, 2015, 5:57:36 AM3/11/15
to python_in...@googlegroups.com
I based my own style on QDarkStyle. I think it's a very decent and nice looking one with color very similar to VFX software like Clarisse. Buttons are a bit too round and some tree widget and tree view elements still have none-matching colors but over all still great.

https://github.com/ColinDuquesnoy/QDarkStyleSheet

Marcus Ottosson

unread,
Mar 11, 2015, 6:16:44 AM3/11/15
to python_in...@googlegroups.com
There's also this which might provide some more inspiration.

Tony Barbieri

unread,
Mar 11, 2015, 8:40:11 AM3/11/15
to python_in...@googlegroups.com
They most likely did customize further than just the QPalette.  The QPalette should give you a good base to start from.

Best,

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.



--
Tony

Fredrik Averpil

unread,
Mar 11, 2015, 10:23:57 AM3/11/15
to python_in...@googlegroups.com
Thanks everyone, I've reached a satisfactory result by pickling down the Maya QPalette and using that together with some of Tony's code (or Thorsten Kaufmann's code).

Cheers!


Reply all
Reply to author
Forward
0 new messages