-
-
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
Resizable spinnies #1079
Resizable spinnies #1079
Conversation
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.
Yea, this is definitely tricky due to unfortunate problems with Qt's layout system. I'll have to play around with it -- it's been a while since I last tried to keep a widget square. I think it may require something ugly like wrapping WSpinny in a widget that has a custom QLayout that forces the spinny to stay square.
src/skin/legacyskinparser.cpp
Outdated
@@ -1112,6 +1112,8 @@ QWidget* LegacySkinParser::parseSpinny(const QDomElement& node) { | |||
return dummy; | |||
} | |||
commonWidgetSetup(node, spinny); | |||
// Pixmaps are rendered from SVGs upon resizing, so initialize the pixmaps | |||
spinny->resize(spinny->size()); |
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 can stall the skin parsing process since it triggers a bunch of QtGui code (like layout) before the skin is done being created. Instead, we could do this inside WSpinny with a helper method that generates the pixmaps, then call that in setup() and resizeEvent().
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 tried calling it in WSpinny::setup(), but that didn't work either. IIRC WSpinny's initial size was not set up at that point, but I'll try again.
src/skin/pixmapsource.cpp
Outdated
@@ -48,6 +50,31 @@ void PixmapSource::setSVG(const QByteArray& content) { | |||
m_eType = SVG; | |||
} | |||
|
|||
QPixmap PixmapSource::toPixmap(const QSize& size) { |
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 probably belongs on Paintable in src/widget/wpixmapstore.h/cpp. PixmapSource is a description of a pixmap/svg, not a means to render it. All the rendering code is currently kept in Paintable.
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 first looked into using Paintable's draw methods inside WSpinny::paintEvent(), but yeah moving the toPixmap() function to Paintable and calling that from WSpinny::resizeEvent() seems like a better idea than the current state.
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, I think I understand how to use Paintable::draw() for this. Create a QPainter in WSpinny::resizeEvent() that paints onto the QPixmap members of WSpinny instead of onto the widget like other parts of the skin code.
<< "old size:" << re->oldSize(); | ||
// Keep it square | ||
if (height() < width()) { | ||
resize(height(), height()); |
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 think even with this check it isn't safe. The parent widget's layout has the final say over our size, so it can modify the request in a way that would trigger an infinite loop.
@@ -60,6 +60,7 @@ class WSpinny : public QGLWidget, public WBaseWidget, public VinylSignalQualityL | |||
void showEvent(QShowEvent* event) override; | |||
void hideEvent(QHideEvent* event) override; | |||
bool event(QEvent* pEvent) override; | |||
QSize sizeHint() const override; |
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.
May also want to define heightForWidth.
https://doc.qt.io/qt-4.8/qwidget.html#heightForWidth
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 tried. It didn't do anything.
src/widget/wspinny.cpp
Outdated
m_ghostImageScaled = m_pGhostImage->scaled( | ||
size(), Qt::KeepAspectRatio, Qt::SmoothTransformation); | ||
} | ||
m_bgSource = context.getPixmapSource( |
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 should keep the legacy behavior (bg scalemode is FIXED, then setFixedSize, otherwise set MinimumExpanding) otherwise this can break old skins.
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 could we determine when to revert to legacy behavior?
src/widget/wspinny.cpp
Outdated
// specify deck color in QSS | ||
m_loadedCoverScaled = scaledCoverArt(m_loadedCover); | ||
|
||
m_bgPixmap = m_bgSource.toPixmap(size()); |
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 is going to reload the pixmap from file / parse the SVG every time (which will block the GUI thread every time the spinny gets resized). Instead, let's keep a Paintable in the WSpinny for each of the originals and use Paintable::draw to render the pixmap at the desired size (that way it's all CPU + some mallocs).
src/widget/wspinny.h
Outdated
QImage* m_pGhostImage; | ||
QImage m_ghostImageScaled; | ||
|
||
QPixmap m_bgPixmap; |
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 some history for why WSpinny uses QImage.
https://bugs.launchpad.net/mixxx/+bug/981210
a15c268
#440
@daschuer -- do you still have this netbook? I wonder if this bug in Qt 4.6.2 was fixed in a later version.
I'm afraid you may be right. :/ |
Yes it is still alive, running Trusty and QT 4.8.5. Mixxx is still usable. :-) |
This keeps the SVG/PNG in memory rather than reading from disk each rerender.
Hm, so as long as we're supporting Trusty, we can't make the switch here to QPixmap here without reviving the bug. When should we end Trusty support? |
trusty came out in 2014 and is an LTS so it's technically supported until 2019 |
Indeed -- that doesn't mean we have to support it through 2019 though. Mixxx 1.10 will work fine on Trusty through 2019 :). |
From what I can tell, what Daniel said in this bug comment still stands. Looks like it will be easy to change to using QImage. |
that seems sufficient |
I think the resizing looks slightly smoother for my system using QImage instead of QPixmap. I'm using a Core i5 2410M with Intel HD Graphics 3000 using the default Intel Linux graphic driver. Both issues mentioned at the top of this PR still remain. |
Are you suggesting to remove Windows XP support ? \o/ |
Yes, for Mixxx 2.2! Qt 5 dropped support for XP, so once we switch we have to. |
I tried that and the result is the same. I can get the QLayout's setGeometry() method to resize the inner widget, but I don't know how to get the outer widget to shrink to the size of the inner widget. Maybe a subclass of WidgetGroup with a custom layout is needed for the container holding the waveform and the spinny? |
src/widget/wspinny.cpp
Outdated
|
||
if (rect.height() > rect.width()) { | ||
m_pSpinnyItem->setGeometry(QRect(0, 0, rect.width(), rect.width())); | ||
QLayout::setGeometry(QRect(0, 0, rect.width(), rect.width())); |
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 haven't found any documentation on what calling QLayout::setGeometry() in a QLayout subclass' setGeometry method does, but I see it in all of Qt's examples.
2ac3a6f
to
38d605c
Compare
Shade does not specify a mask image
Working on PR #940, I realized spinnies were set to a fixed size in C++ and wouldn't scale. This PR rerenders SVGs to QPixmaps when spinnies are resized. I avoided rendering the SVGs in WSpinny::paintEvent() for efficiency.
This is not ready for merge. There are two big issues I could use help with, and their solutions might be related: