slackbuilds/audio/mixxx/debc5051ddf02c4274cfe21eba3...

386 lines
15 KiB
Diff

From debc5051ddf02c4274cfe21eba3779a14a0fc55c Mon Sep 17 00:00:00 2001
From: ronso0 <ronso0@mixxx.org>
Date: Thu, 27 Feb 2025 13:45:15 +0100
Subject: [PATCH] Track info: fix size of cover art label
* max height is now height of the three top rows
* max width is now width of the two rightmost columns
This prevents
* flickering of single-track dialog when switching tracks
* unintentional vertical stretching grid rows
---
src/library/dlgtagfetcher.cpp | 8 ++--
src/library/dlgtrackinfo.cpp | 36 ++++++++++++++-
src/library/dlgtrackinfo.h | 4 ++
src/library/dlgtrackinfomulti.cpp | 31 +++++++++++--
src/library/dlgtrackinfomulti.h | 4 +-
src/widget/wcoverartlabel.cpp | 77 +++++++++++++++++++++++--------
src/widget/wcoverartlabel.h | 13 ++++--
7 files changed, 139 insertions(+), 34 deletions(-)
diff --git a/src/library/dlgtagfetcher.cpp b/src/library/dlgtagfetcher.cpp
index 59361de64b87..b460db7d62ad 100644
--- a/src/library/dlgtagfetcher.cpp
+++ b/src/library/dlgtagfetcher.cpp
@@ -255,7 +255,7 @@ void DlgTagFetcher::loadTrack(const TrackPointer& pTrack) {
&DlgTagFetcher::slotTrackChanged);
}
- m_pWFetchedCoverArtLabel->setCoverArt(CoverInfo{}, QPixmap{});
+ m_pWFetchedCoverArtLabel->setCoverInfoAndPixmap(CoverInfo{}, QPixmap{});
m_coverCache.clear();
@@ -580,7 +580,7 @@ void DlgTagFetcher::tagSelected() {
m_data.m_selectedTag = tagIndex;
m_fetchedCoverArtByteArrays.clear();
- m_pWFetchedCoverArtLabel->setCoverArt(CoverInfo{},
+ m_pWFetchedCoverArtLabel->setCoverInfoAndPixmap(CoverInfo{},
QPixmap(CoverArtUtils::defaultCoverLocation()));
const mixxx::musicbrainz::TrackRelease& trackRelease = m_data.m_tags[tagIndex];
@@ -612,7 +612,7 @@ void DlgTagFetcher::slotCoverFound(
m_pTrack &&
m_pTrack->getLocation() == coverInfo.trackLocation) {
m_trackRecord.setCoverInfo(coverInfo);
- m_pWCurrentCoverArtLabel->setCoverArt(coverInfo, pixmap);
+ m_pWCurrentCoverArtLabel->setCoverInfoAndPixmap(coverInfo, pixmap);
}
}
@@ -673,7 +673,7 @@ void DlgTagFetcher::loadPixmapToLabel(const QPixmap& pixmap) {
statusMessage->clear();
statusMessage->setVisible(true);
- m_pWFetchedCoverArtLabel->setCoverArt(coverInfo, pixmap);
+ m_pWFetchedCoverArtLabel->setCoverInfoAndPixmap(coverInfo, pixmap);
checkBoxCover->setEnabled(!pixmap.isNull());
}
diff --git a/src/library/dlgtrackinfo.cpp b/src/library/dlgtrackinfo.cpp
index 070658721c91..97dbf200d8b1 100644
--- a/src/library/dlgtrackinfo.cpp
+++ b/src/library/dlgtrackinfo.cpp
@@ -382,7 +382,7 @@ void DlgTrackInfo::replaceTrackRecord(
const auto coverInfo = CoverInfo(
m_trackRecord.getCoverInfo(),
trackLocation);
- m_pWCoverArtLabel->setCoverArt(coverInfo, QPixmap());
+ m_pWCoverArtLabel->setCoverInfoAndPixmap(coverInfo, QPixmap());
// Executed concurrently
CoverArtCache::requestCover(this, coverInfo);
@@ -508,6 +508,9 @@ void DlgTrackInfo::loadTrack(const QModelIndex& index) {
return;
}
TrackPointer pTrack = m_pTrackModel->getTrack(index);
+ VERIFY_OR_DEBUG_ASSERT(pTrack) {
+ return;
+ }
m_currentTrackIndex = index;
loadTrackInternal(pTrack);
if (m_pDlgTagFetcher && m_pDlgTagFetcher->isVisible()) {
@@ -537,7 +540,7 @@ void DlgTrackInfo::slotCoverFound(
m_pLoadedTrack &&
m_pLoadedTrack->getLocation() == coverInfo.trackLocation) {
m_trackRecord.setCoverInfo(coverInfo);
- m_pWCoverArtLabel->setCoverArt(coverInfo, pixmap);
+ m_pWCoverArtLabel->setCoverInfoAndPixmap(coverInfo, pixmap);
}
}
@@ -863,3 +866,32 @@ void DlgTrackInfo::slotImportMetadataFromMusicBrainz() {
}
m_pDlgTagFetcher->show();
}
+
+void DlgTrackInfo::resizeEvent(QResizeEvent* pEvent) {
+ QDialog::resizeEvent(pEvent);
+
+ if (!isVisible()) {
+ // Likely one of the resize events before show().
+ // Widgets don't have their final size, yet, so it
+ // makes no sense to resize the cover label.
+ return;
+ }
+
+ // Set a maximum size on the cover label so it can use the available space
+ // but doesn't force-expand the dialog.
+ // The cover label spans across three tag rows and the two rightmost columns.
+ // Unfortunately we can't read row/column sizes directly, so we use the widgets.
+ int contHeight = txtTitle->height() + txtArtist->height() + txtAlbum->height();
+ int vSpacing = tags_layout->verticalSpacing();
+ int totalHeight = vSpacing * 2 + contHeight;
+
+ int contWidth = lblYear->width() + txtYear->width();
+ int hSpacing = tags_layout->horizontalSpacing();
+ int totalWidth = contWidth + hSpacing;
+
+ m_pWCoverArtLabel->setMaxSize(QSize(totalWidth, totalHeight));
+
+ // Also clamp height of the cover's parent widget. Keeping its height minimal
+ // can't be accomplished with QSizePolicies alone unfortunately.
+ coverWidget->setFixedHeight(totalHeight);
+}
diff --git a/src/library/dlgtrackinfo.h b/src/library/dlgtrackinfo.h
index 8949c530eb47..525042b5ed13 100644
--- a/src/library/dlgtrackinfo.h
+++ b/src/library/dlgtrackinfo.h
@@ -45,6 +45,10 @@ class DlgTrackInfo : public QDialog, public Ui::DlgTrackInfo {
void next();
void previous();
+ protected:
+ // used to set the maximum size of the cover label
+ void resizeEvent(QResizeEvent* pEvent) override;
+
private slots:
void slotNextButton();
void slotPrevButton();
diff --git a/src/library/dlgtrackinfomulti.cpp b/src/library/dlgtrackinfomulti.cpp
index bbcd07a46ca0..7977dd55bc71 100644
--- a/src/library/dlgtrackinfomulti.cpp
+++ b/src/library/dlgtrackinfomulti.cpp
@@ -613,10 +613,35 @@ void DlgTrackInfoMulti::addValuesToCommentBox(QSet<QString>& comments) {
void DlgTrackInfoMulti::resizeEvent(QResizeEvent* pEvent) {
Q_UNUSED(pEvent);
+ if (!isVisible()) {
+ // Likely one of the resize events before show().
+ // Dialog & widgets don't have their final size, yet,
+ // so it makes no sense to resize the cover label.
+ return;
+ }
+
// Limit comment popup to dialog width. This may introduce some linebreaks
// but is still much better than letting the popup expand to screen width,
// which it would do regrardless if it's actually necessary.
txtCommentBox->view()->parentWidget()->setMaximumWidth(width());
+
+ // Set a maximum size on the cover label so it can use the available space
+ // but doesn't force-expand the dialog.
+ // The cover label spans across three tag rows and the two rightmost columns.
+ // Unfortunately we can't read row/column sizes directly, so we use the widgets.
+ int contHeight = txtTitle->height() + txtArtist->height() + txtAlbum->height();
+ int vSpacing = tags_layout->verticalSpacing();
+ int totalHeight = vSpacing * 2 + contHeight;
+
+ int contWidth = lblYear->width() + txtYear->width();
+ int hSpacing = tags_layout->horizontalSpacing();
+ int totalWidth = contWidth + hSpacing;
+
+ m_pWCoverArtLabel->setMaxSize(QSize(totalWidth, totalHeight));
+
+ // Also clamp height of the cover's parent widget. Keeping its height minimal
+ // can't be accomplished with QSizePolicies alone unfortunately.
+ coverWidget->setFixedHeight(totalHeight);
}
void DlgTrackInfoMulti::saveTracks() {
@@ -1043,12 +1068,12 @@ void DlgTrackInfoMulti::updateCoverArtFromTracks() {
// Just make sure the same track is used in slotCoverFound(): the track
// location has to match in order to load the cover image to the label.
auto trCover = pRefTrack->getCoverInfoWithLocation();
- m_pWCoverArtLabel->setCoverArt(trCover, QPixmap());
+ m_pWCoverArtLabel->setCoverInfoAndPixmap(trCover, QPixmap());
CoverArtCache::requestCover(this, trCover);
} else {
// Set empty cover + track location
auto trCover = CoverInfo(CoverInfoRelative(), pRefTrack->getLocation());
- m_pWCoverArtLabel->setCoverArt(trCover, QPixmap());
+ m_pWCoverArtLabel->setCoverInfoAndPixmap(trCover, QPixmap());
}
}
@@ -1061,7 +1086,7 @@ void DlgTrackInfoMulti::slotCoverFound(
m_pLoadedTracks.cbegin().value()->getLocation() == coverInfo.trackLocation) {
// Track records have already been updated in slotCoverInfoSelected,
// now load the image to the label.
- m_pWCoverArtLabel->setCoverArt(coverInfo, pixmap);
+ m_pWCoverArtLabel->setCoverInfoAndPixmap(coverInfo, pixmap);
}
}
diff --git a/src/library/dlgtrackinfomulti.h b/src/library/dlgtrackinfomulti.h
index d733bda4788f..4c069f549d95 100644
--- a/src/library/dlgtrackinfomulti.h
+++ b/src/library/dlgtrackinfomulti.h
@@ -31,11 +31,11 @@ class DlgTrackInfoMulti : public QDialog, public Ui::DlgTrackInfoMulti {
void loadTracks(const QList<TrackPointer>& pTracks);
void focusField(const QString& property);
+ protected:
/// We need this to set the max width of the comment QComboBox which has
/// issues with long lines / multi-line content. See init() for details.
+ /// Also used to set the maximum size of the cover label
void resizeEvent(QResizeEvent* event) override;
-
- protected:
bool eventFilter(QObject* pObj, QEvent* pEvent) override;
private slots:
diff --git a/src/widget/wcoverartlabel.cpp b/src/widget/wcoverartlabel.cpp
index 519c65b5de6f..fa08bc55767a 100644
--- a/src/widget/wcoverartlabel.cpp
+++ b/src/widget/wcoverartlabel.cpp
@@ -9,61 +9,100 @@
namespace {
-constexpr QSize kDeviceIndependentCoverLabelSize = QSize(100, 100);
+// Device-independent size for the label
+constexpr QSize kDefaultSize = QSize(100, 100);
+
+// Size for the pixmap. Assumes frame width is 1px.
+constexpr QSize kDefaultPixmapSize = kDefaultSize - QSize(2, 2);
inline QPixmap scaleCoverLabel(
- QWidget* parent,
- QPixmap pixmap) {
- const auto devicePixelRatioF = parent->devicePixelRatioF();
+ QLabel* pLabel,
+ QPixmap pixmap,
+ QSize size) {
+ VERIFY_OR_DEBUG_ASSERT(size.isValid()) {
+ size = kDefaultPixmapSize;
+ }
+ const auto devicePixelRatioF = pLabel->devicePixelRatioF();
pixmap.setDevicePixelRatio(devicePixelRatioF);
return pixmap.scaled(
- kDeviceIndependentCoverLabelSize * devicePixelRatioF,
+ size * devicePixelRatioF,
Qt::KeepAspectRatio,
Qt::SmoothTransformation);
}
-QPixmap createDefaultCover(QWidget* parent) {
+QPixmap createDefaultCover(QLabel* pLabel, QSize size) {
auto defaultCover = QPixmap(CoverArtUtils::defaultCoverLocation());
- return scaleCoverLabel(parent, defaultCover);
+ return scaleCoverLabel(pLabel, defaultCover, size);
}
} // anonymous namespace
-WCoverArtLabel::WCoverArtLabel(QWidget* parent, WCoverArtMenu* pCoverMenu)
- : QLabel(parent),
+WCoverArtLabel::WCoverArtLabel(QWidget* pParent, WCoverArtMenu* pCoverMenu)
+ : QLabel(pParent),
m_pCoverMenu(pCoverMenu),
m_pDlgFullSize(make_parented<DlgCoverArtFullSize>(this, nullptr, pCoverMenu)),
- m_defaultCover(createDefaultCover(this)) {
- setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
+ m_maxSize(kDefaultSize),
+ m_pixmapSizeMax(kDefaultPixmapSize),
+ m_defaultCover(createDefaultCover(this, m_pixmapSizeMax)) {
+ setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
setFrameShape(QFrame::Box);
setAlignment(Qt::AlignCenter);
- setPixmap(m_defaultCover);
+ setPixmapAndResize(m_defaultCover);
}
WCoverArtLabel::~WCoverArtLabel() = default;
-void WCoverArtLabel::setCoverArt(const CoverInfo& coverInfo,
+void WCoverArtLabel::setCoverInfoAndPixmap(const CoverInfo& coverInfo,
const QPixmap& px) {
if (m_pCoverMenu != nullptr) {
m_pCoverMenu->setCoverArt(coverInfo);
}
+ setPixmapAndResize(px);
+}
+
+void WCoverArtLabel::setPixmapAndResize(const QPixmap& px) {
if (px.isNull()) {
m_loadedCover = px;
m_fullSizeCover = px;
setPixmap(m_defaultCover);
} else {
- m_loadedCover = scaleCoverLabel(this, px);
+ m_loadedCover = scaleCoverLabel(this, px, m_pixmapSizeMax);
m_fullSizeCover = px;
setPixmap(m_loadedCover);
}
#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
- QSize frameSize = pixmap(Qt::ReturnByValue).size() / devicePixelRatioF();
+ QSize newSize = pixmap().size() / devicePixelRatioF();
#else
- QSize frameSize = pixmap()->size() / devicePixelRatioF();
+ QSize newSize = pixmap()->size() / devicePixelRatioF();
#endif
- frameSize += QSize(2, 2); // margin
- setMinimumSize(frameSize);
- setMaximumSize(frameSize);
+ // add the frame so the entire pixmap is visible
+ newSize += QSize(frameWidth() * 2, frameWidth() * 2);
+ if (size() != newSize) {
+ setFixedSize(newSize);
+ }
+}
+
+void WCoverArtLabel::setMaxSize(const QSize newSize) {
+ if (newSize == m_maxSize) {
+ return;
+ }
+
+ m_maxSize = newSize;
+ m_pixmapSizeMax = newSize - QSize(frameWidth() * 2, frameWidth() * 2);
+ // Skip resizing the pixmap and label if the pixmap already fits.
+ // Check if we got more space in one dimension and don't need it
+ // for the other.
+ const QSize pixmapSize = pixmap().size() / devicePixelRatioF();
+ if (m_pixmapSizeMax == pixmapSize ||
+ (m_pixmapSizeMax.height() == pixmapSize.height() &&
+ m_pixmapSizeMax.width() > pixmapSize.width()) ||
+ (m_pixmapSizeMax.width() == pixmapSize.width() &&
+ m_pixmapSizeMax.height() > pixmapSize.height())) {
+ return;
+ }
+
+ m_defaultCover = createDefaultCover(this, m_pixmapSizeMax);
+ setPixmapAndResize(m_fullSizeCover);
}
void WCoverArtLabel::slotCoverMenu(const QPoint& pos) {
diff --git a/src/widget/wcoverartlabel.h b/src/widget/wcoverartlabel.h
index 9b5421d26868..2611c7a140f4 100644
--- a/src/widget/wcoverartlabel.h
+++ b/src/widget/wcoverartlabel.h
@@ -19,24 +19,29 @@ class WCoverArtLabel : public QLabel {
~WCoverArtLabel() override; // Verifies that the base destructor is virtual
- void setCoverArt(const CoverInfo& coverInfo, const QPixmap& px);
+ void setCoverInfoAndPixmap(const CoverInfo& coverInfo, const QPixmap& px);
void loadTrack(TrackPointer pTrack);
+ void setMaxSize(const QSize size);
protected:
- void mousePressEvent(QMouseEvent* event) override;
- void contextMenuEvent(QContextMenuEvent* event) override;
+ void mousePressEvent(QMouseEvent* pEvent) override;
+ void contextMenuEvent(QContextMenuEvent* pEvent) override;
private slots:
void slotCoverMenu(const QPoint& pos);
private:
+ void setPixmapAndResize(const QPixmap& px);
+
WCoverArtMenu* m_pCoverMenu;
const parented_ptr<DlgCoverArtFullSize> m_pDlgFullSize;
TrackPointer m_pLoadedTrack;
- const QPixmap m_defaultCover;
+ QSize m_maxSize;
+ QSize m_pixmapSizeMax;
+ QPixmap m_defaultCover;
QPixmap m_loadedCover;
QPixmap m_fullSizeCover;
};