The 5.6 (and probably dev) branch of pyside-tools fails to preserve SVG icons as in-memory vector images. Instead, the Python logic generated by pyside2-uic unconditionally downgrades all SVG icons to in-memory raster pixmaps.
This is horrible for any number of obvious reasons, including:
- Pixellation. Rasterization of vector images inevitably introduces visual artifacting. Sadly, SVG icons are no exception.
- No upscaling. Qt wisely refuses to upscale raster pixmaps. However, Qt typically converts SVG icons to extremely small raster pixmaps. Together, these two observations imply that SVG icons are locked to extremely small sizes. On high-DPI displays (e.g., Retina), the resulting raster pixmaps are effectively invisible.
Examples or The Little Dog Gets It
Why did this horrible thing happen? A minimal-length example should hopefully clarify.
Given the attached mainwindow.ui and mainwindow.qrc files, pyside2-uic encapsulates the attached dashboard.svg icon with the following Python:
icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/dashboard.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
Note the rasterization of this SVG icon into an in-memory pixmap. Since the QIcon::addFile() method already implicitly supports SVG icons, however, this rasterization is needlessly destructive. Ideally, pyside2-uic should encapsulate this icon with a call to the QIcon::addFile() method instead: e.g.,
icon = QtGui.QIcon() icon.addFile(":/dashboard.svg", QtCore.QSize(), QtGui.QIcon.Normal, QtGui.QIcon.Off)
Note the need to pass an additional size parameter to the QIcon::addFile() method, which remains unconstrained due to the infinitely rescalable nature of vector images.
Note also that there appears to be no benefit to calling QIcon::addPixmap() at all – even for non-vector icons (e.g., jpg, png). QIcon::addFile() already supports all image filetypes and is thus probably always preferable to QIcon::addPixmap() here.
Or maybe I have no idea what I'm talking about. (A distinct possibility.)
Better Examples or The Little Dog Really Gets It
The attached qiconpixmap.py application embeds this SVG icon as a toolbar action of an otherwise empty main window. This application is runnable in the usual way. For example, at a Bash terminal:
pyside2-uic -omainwindow.py mainwindow.ui pyside2-rcc -o mainwindow_rc.py mainwindow.qrc python3 qiconpixmap.py
The SVG icon should appear rasterized to an extremely small size rather than stretching to vertically fill the height of its parent toolbar.
Hacky Workaround for Great Justice
Our downstream application currently hacks around this by forcibly performing a sed-style global search-and-replacement on the text emitted by the pyside2uic module before serializing this text to disk. Assuming this text to be assigned to local variable ui_code_str, the following string munging suffices:
import re ui_code_str = re.sub( ( r'^(\s*icon\d*\.add)' r'Pixmap\(QtGui\.QPixmap\(' r'("[^"]+\.svg")' r'\)(.*)$' ), r'\1File(\2, QtCore.QSize()\3', ui_code_str, flags=re.MULTILINE, )
Thanks to that black magic, this isn't necessarily a high-priority issue for us.
Everybody else might feel differently.
- relates to
PYSIDE-797 Rewrite pyside-uic