diff options
-rw-r--r-- | src/dlgtrackinfo.cpp | 14 | ||||
-rw-r--r-- | src/dlgtrackinfo.h | 1 | ||||
-rw-r--r-- | src/library/coverartcache.cpp | 22 | ||||
-rw-r--r-- | src/library/coverartcache.h | 11 | ||||
-rw-r--r-- | src/widget/wcoverart.cpp | 11 | ||||
-rw-r--r-- | src/widget/wcoverart.h | 1 | ||||
-rw-r--r-- | src/widget/wcoverartlabel.cpp | 2 | ||||
-rw-r--r-- | src/widget/wcoverartlabel.h | 1 | ||||
-rw-r--r-- | src/widget/wcoverartmenu.cpp | 8 | ||||
-rw-r--r-- | src/widget/wcoverartmenu.h | 2 | ||||
-rw-r--r-- | src/widget/wtracktableview.cpp | 53 | ||||
-rw-r--r-- | src/widget/wtracktableview.h | 3 |
12 files changed, 112 insertions, 17 deletions
diff --git a/src/dlgtrackinfo.cpp b/src/dlgtrackinfo.cpp index abe9da6a92..24120ca4ba 100644 --- a/src/dlgtrackinfo.cpp +++ b/src/dlgtrackinfo.cpp @@ -7,6 +7,7 @@ #include "dlgtrackinfo.h" #include "trackinfoobject.h" #include "library/coverartcache.h" +#include "library/coverartutils.h" #include "library/dao/cue.h" const int kMinBPM = 30; @@ -80,6 +81,8 @@ void DlgTrackInfo::init(){ } connect(m_pWCoverArtLabel, SIGNAL(coverArtSelected(const CoverArt&)), this, SLOT(slotCoverArtSelected(const CoverArt&))); + connect(m_pWCoverArtLabel, SIGNAL(reloadCover()), + this, SLOT(slotReloadCoverArt())); } void DlgTrackInfo::OK() { @@ -205,6 +208,17 @@ void DlgTrackInfo::slotCoverFound(const QObject* pRequestor, } } +void DlgTrackInfo::slotReloadCoverArt() { + if (m_pLoadedTrack) { + // TODO(rryan) move this out of the main thread. The issue is that + // CoverArtCache::requestGuessCover mutates the provided track whereas + // in DlgTrackInfo we delay changing the track until the user hits apply + // (or cancels the edit). + CoverArt art = CoverArtUtils::guessCoverArt(m_pLoadedTrack); + slotCoverArtSelected(art); + } +} + void DlgTrackInfo::slotCoverArtSelected(const CoverArt& art) { qDebug() << "DlgTrackInfo::slotCoverArtSelected" << art; m_loadedCoverInfo = art.info; diff --git a/src/dlgtrackinfo.h b/src/dlgtrackinfo.h index ef88a5c27c..8d469c0d3f 100644 --- a/src/dlgtrackinfo.h +++ b/src/dlgtrackinfo.h @@ -58,6 +58,7 @@ class DlgTrackInfo : public QDialog, public Ui::DlgTrackInfo { void slotCoverFound(const QObject* pRequestor, int requestReference, const CoverInfo& info, QPixmap pixmap, bool fromCache); void slotCoverArtSelected(const CoverArt& art); + void slotReloadCoverArt(); private: void populateFields(TrackPointer pTrack); diff --git a/src/library/coverartcache.cpp b/src/library/coverartcache.cpp index 212045e727..3d1e30de5d 100644 --- a/src/library/coverartcache.cpp +++ b/src/library/coverartcache.cpp @@ -152,3 +152,25 @@ void CoverArtCache::coverLoaded() { res.cover.info, pixmap, false)); } } + +void CoverArtCache::requestGuessCovers(QList<TrackPointer> tracks) { + QtConcurrent::run(this, &CoverArtCache::guessCovers, tracks); +} + +void CoverArtCache::requestGuessCover(TrackPointer pTrack) { + QtConcurrent::run(this, &CoverArtCache::guessCover, pTrack); +} + +void CoverArtCache::guessCover(TrackPointer pTrack) { + if (pTrack) { + pTrack->setCoverArt(CoverArtUtils::guessCoverArt(pTrack)); + } +} + +void CoverArtCache::guessCovers(QList<TrackPointer> tracks) { + qDebug() << "CoverArtCache::guessCovers guessing covers for" + << tracks.size() << "tracks"; + foreach (TrackPointer pTrack, tracks) { + guessCover(pTrack); + } +} diff --git a/src/library/coverartcache.h b/src/library/coverartcache.h index 990c5140d6..0db4171122 100644 --- a/src/library/coverartcache.h +++ b/src/library/coverartcache.h @@ -6,6 +6,7 @@ #include "library/coverart.h" #include "util/singleton.h" +#include "trackinfoobject.h" class CoverArtCache : public QObject, public Singleton<CoverArtCache> { Q_OBJECT @@ -32,6 +33,12 @@ class CoverArtCache : public QObject, public Singleton<CoverArtCache> { const bool onlyCached = false, const bool signalWhenDone = true); + // Guesses the cover art for the provided tracks by searching the tracks' + // metadata and folders for image files. All I/O is done in a separate + // thread. + void requestGuessCovers(QList<TrackPointer> tracks); + void requestGuessCover(TrackPointer pTrack); + struct FutureResult { FutureResult() : pRequestor(NULL), requestReference(0), @@ -67,6 +74,10 @@ class CoverArtCache : public QObject, public Singleton<CoverArtCache> { const int desiredWidth, const bool emitSignals); + // Guesses the cover art for each track. + void guessCovers(QList<TrackPointer> tracks); + void guessCover(TrackPointer pTrack); + private: QSet<QPair<const QObject*, int> > m_runningRequests; }; diff --git a/src/widget/wcoverart.cpp b/src/widget/wcoverart.cpp index d7321f02f2..2c9b42a6fb 100644 --- a/src/widget/wcoverart.cpp +++ b/src/widget/wcoverart.cpp @@ -36,6 +36,8 @@ WCoverArt::WCoverArt(QWidget* parent, } connect(m_pMenu, SIGNAL(coverArtSelected(const CoverArt&)), this, SLOT(slotCoverArtSelected(const CoverArt&))); + connect(m_pMenu, SIGNAL(reloadCoverArt()), + this, SLOT(slotReloadCoverArt())); } WCoverArt::~WCoverArt() { @@ -78,6 +80,15 @@ void WCoverArt::setup(QDomNode node, const SkinContext& context) { m_defaultCoverScaled = scaledCoverArt(m_defaultCover); } +void WCoverArt::slotReloadCoverArt() { + if (m_loadedTrack) { + CoverArtCache* pCache = CoverArtCache::instance(); + if (pCache) { + pCache->requestGuessCover(m_loadedTrack); + } + } +} + void WCoverArt::slotCoverArtSelected(const CoverArt& art) { if (m_loadedTrack) { // Will trigger slotTrackCoverArtUpdated(). diff --git a/src/widget/wcoverart.h b/src/widget/wcoverart.h index 8ab44bfedd..aa0d7dd825 100644 --- a/src/widget/wcoverart.h +++ b/src/widget/wcoverart.h @@ -35,6 +35,7 @@ class WCoverArt : public QWidget, public WBaseWidget { void slotCoverFound(const QObject* pRequestor, int requestReference, const CoverInfo& info, QPixmap pixmap, bool fromCache); void slotCoverArtSelected(const CoverArt& art); + void slotReloadCoverArt(); void slotTrackCoverArtUpdated(); protected: diff --git a/src/widget/wcoverartlabel.cpp b/src/widget/wcoverartlabel.cpp index 3325cf7e25..bdd15f9959 100644 --- a/src/widget/wcoverartlabel.cpp +++ b/src/widget/wcoverartlabel.cpp @@ -19,6 +19,8 @@ WCoverArtLabel::WCoverArtLabel(QWidget* parent) this, SLOT(slotCoverMenu(QPoint))); connect(m_pCoverMenu, SIGNAL(coverArtSelected(const CoverArt&)), this, SIGNAL(coverArtSelected(const CoverArt&))); + connect(m_pCoverMenu, SIGNAL(reloadCoverArt()), + this, SIGNAL(reloadCoverArt())); m_defaultCover = m_defaultCover.scaled(s_labelDisplaySize, Qt::KeepAspectRatio, diff --git a/src/widget/wcoverartlabel.h b/src/widget/wcoverartlabel.h index ac1f062f2b..4b9452a973 100644 --- a/src/widget/wcoverartlabel.h +++ b/src/widget/wcoverartlabel.h @@ -19,6 +19,7 @@ class WCoverArtLabel : public QLabel { signals: void coverArtSelected(const CoverArt& art); + void reloadCoverArt(); protected: void leaveEvent(QEvent*); diff --git a/src/widget/wcoverartmenu.cpp b/src/widget/wcoverartmenu.cpp index 4be49bf464..ca5f790e4c 100644 --- a/src/widget/wcoverartmenu.cpp +++ b/src/widget/wcoverartmenu.cpp @@ -28,7 +28,7 @@ void WCoverArtMenu::createActions() { m_pReload = new QAction(tr("Reload from track/folder", "reload cover art from track metadata or folder"), this); - connect(m_pReload, SIGNAL(triggered()), this, SLOT(slotReload())); + connect(m_pReload, SIGNAL(triggered()), this, SIGNAL(reloadCoverArt())); addAction(m_pReload); } @@ -90,12 +90,6 @@ void WCoverArtMenu::slotChange() { emit(coverArtSelected(art)); } -void WCoverArtMenu::slotReload() { - CoverArt art = CoverArtUtils::guessCoverArt(m_pTrack); - qDebug() << "WCoverArtMenu::slotReload emit" << art; - emit(coverArtSelected(art)); -} - void WCoverArtMenu::slotUnset() { CoverArt art; art.info.type = CoverInfo::NONE; diff --git a/src/widget/wcoverartmenu.h b/src/widget/wcoverartmenu.h index 575aa073c2..798466d6e3 100644 --- a/src/widget/wcoverartmenu.h +++ b/src/widget/wcoverartmenu.h @@ -24,10 +24,10 @@ class WCoverArtMenu : public QMenu { signals: void coverArtSelected(const CoverArt& art); + void reloadCoverArt(); private slots: void slotChange(); - void slotReload(); void slotUnset(); private: diff --git a/src/widget/wtracktableview.cpp b/src/widget/wtracktableview.cpp index f6acf820e0..419003477f 100644 --- a/src/widget/wtracktableview.cpp +++ b/src/widget/wtracktableview.cpp @@ -83,6 +83,8 @@ WTrackTableView::WTrackTableView(QWidget * parent, m_pCoverMenu->setTitle(tr("Cover Art")); connect(m_pCoverMenu, SIGNAL(coverArtSelected(const CoverArt&)), this, SLOT(slotCoverArtSelected(const CoverArt&))); + connect(m_pCoverMenu, SIGNAL(reloadCoverArt()), + this, SLOT(slotReloadCoverArt())); // Disable editing @@ -863,12 +865,22 @@ void WTrackTableView::contextMenuEvent(QContextMenuEvent* event) { m_pMenu->addAction(m_pReloadMetadataFromMusicBrainzAct); } - m_contextTrack = trackModel->getTrack(indices.at(0)); - m_pCoverMenu->setCoverArt(m_contextTrack, m_contextTrack->getCoverInfo()); - // TODO(rryan): support multiple selection. disable for now to indicate we - // don't support it. - m_pCoverMenu->setEnabled(indices.size() == 1); + // We load a single track to get the necessary context for the cover (we use + // last to be consistent with selectionChanged above). + QModelIndex last = indices.last(); + CoverInfo info; + info.source = static_cast<CoverInfo::Source>( + last.sibling(last.row(), m_iCoverSourceColumn).data().toInt()); + info.type = static_cast<CoverInfo::Type>( + last.sibling(last.row(), m_iCoverTypeColumn).data().toInt()); + info.hash = last.sibling(last.row(), m_iCoverHashColumn).data().toUInt(); + info.trackLocation = last.sibling( + last.row(), m_iTrackLocationColumn).data().toString(); + info.coverLocation = last.sibling( + last.row(), m_iCoverLocationColumn).data().toString(); + m_pCoverMenu->setCoverArt(TrackPointer(), info); m_pMenu->addMenu(m_pCoverMenu); + // REMOVE and HIDE should not be at the first menu position to avoid accidental clicks m_pMenu->addSeparator(); if (modelHasCapabilities(TrackModel::TRACKMODELCAPS_REMOVE)) { @@ -1576,7 +1588,34 @@ void WTrackTableView::slotClearBeats() { } void WTrackTableView::slotCoverArtSelected(const CoverArt& art) { - if (m_contextTrack) { - m_contextTrack->setCoverArt(art); + TrackModel* trackModel = getTrackModel(); + if (trackModel == NULL) { + return; + } + QModelIndexList selection = selectionModel()->selectedRows(); + foreach (QModelIndex index, selection) { + TrackPointer pTrack = trackModel->getTrack(index); + if (pTrack) { + pTrack->setCoverArt(art); + } + } +} + +void WTrackTableView::slotReloadCoverArt() { + TrackModel* trackModel = getTrackModel(); + if (trackModel == NULL) { + return; + } + QList<TrackPointer> selectedTracks; + QModelIndexList selection = selectionModel()->selectedRows(); + foreach (QModelIndex index, selection) { + TrackPointer pTrack = trackModel->getTrack(index); + if (pTrack) { + selectedTracks.append(pTrack); + } + } + CoverArtCache* pCache = CoverArtCache::instance(); + if (pCache) { + pCache->requestGuessCovers(selectedTracks); } } diff --git a/src/widget/wtracktableview.h b/src/widget/wtracktableview.h index fc835575e7..5fd0ed1bc8 100644 --- a/src/widget/wtracktableview.h +++ b/src/widget/wtracktableview.h @@ -75,6 +75,7 @@ class WTrackTableView : public WLibraryTableView { void slotGuiTick50ms(double); void slotScrollValueChanged(int); void slotCoverArtSelected(const CoverArt& art); + void slotReloadCoverArt(); private: void sendToAutoDJ(bool bTop); @@ -163,8 +164,6 @@ class WTrackTableView : public WLibraryTableView { int m_iCoverColumn; // visible cover art int m_iTrackLocationColumn; - TrackPointer m_contextTrack; - // Control the delay to load a cover art. qint64 m_lastUserActionNanos; bool m_loadCachedOnly; |