Reduce memory usage, by storing album covers in a cache - and using this for display.
This commit is contained in:
committed by
craig.p.drummond
parent
374e055ed2
commit
7716ed9962
@@ -46,6 +46,8 @@
|
||||
after album name.
|
||||
28. Only show album year in non-icon view.
|
||||
29. Only show album year in browsers.
|
||||
30. Reduce memory usage, by storing album covers in a cache - and using this
|
||||
for display.
|
||||
|
||||
1.3.3
|
||||
-----
|
||||
|
||||
1
TODO
1
TODO
@@ -75,7 +75,6 @@
|
||||
- mixramp MPD settings
|
||||
- Does MPD need to be restarted to change settings?
|
||||
- Create a base 'Page' class?
|
||||
- Reduce memory usage - use QCache for artists and albums models?
|
||||
|
||||
- Bugs
|
||||
- Jamendo search sometimes causes crash (not seen for a while)
|
||||
|
||||
@@ -254,7 +254,6 @@ void DevicesPage::addSelectionToPlaylist(const QString &name, bool replace, quin
|
||||
void DevicesPage::refresh()
|
||||
{
|
||||
view->setLevel(0);
|
||||
DevicesModel::self()->clearImages();
|
||||
if (ItemView::Mode_SimpleTree==view->viewMode() || ItemView::Mode_DetailedTree==view->viewMode()) {
|
||||
for (int i=0; i<DevicesModel::self()->rowCount(QModelIndex()); ++i) {
|
||||
view->setExpanded(proxy.mapFromSource(DevicesModel::self()->index(i, 0, QModelIndex())));
|
||||
|
||||
108
gui/covers.cpp
108
gui/covers.cpp
@@ -54,6 +54,7 @@
|
||||
#include <QFont>
|
||||
#include <QXmlStreamReader>
|
||||
#include <QTimer>
|
||||
#include <QCache>
|
||||
|
||||
#ifdef ENABLE_KDE_SUPPORT
|
||||
#include <KDE/KStandardDirs>
|
||||
@@ -88,6 +89,9 @@ static bool saveInMpdDir=true;
|
||||
static bool fetchCovers=true;
|
||||
static QString constCoverInTagPrefix=QLatin1String("{tag}");
|
||||
|
||||
static QSet<int> cacheSizes;
|
||||
static QCache<QString, QPixmap> cache(4*1024*1024);
|
||||
|
||||
static bool canSaveTo(const QString &dir)
|
||||
{
|
||||
QString mpdDir=MPDConnection::self()->getDetails().dir;
|
||||
@@ -140,14 +144,35 @@ static QString save(const QString &mimeType, const QString &extension, const QSt
|
||||
return QString();
|
||||
}
|
||||
|
||||
static inline QString albumKey(const QString &artist, const QString &album)
|
||||
{
|
||||
return "{"+artist+"}{"+album+"}";
|
||||
}
|
||||
|
||||
static inline QString albumKey(const Song &s)
|
||||
{
|
||||
return "{"+s.albumArtist()+"}{"+s.album+"}";
|
||||
return albumKey(s.albumArtist(), s.album);
|
||||
}
|
||||
|
||||
static inline QString artistKey(const QString &artist)
|
||||
{
|
||||
return "{"+artist+"}";
|
||||
}
|
||||
|
||||
static inline QString artistKey(const Song &s)
|
||||
{
|
||||
return "{"+s.albumArtist()+"}";
|
||||
return artistKey(s);
|
||||
}
|
||||
|
||||
static inline QString cacheKey(const Song &song, int size)
|
||||
{
|
||||
return (song.isArtistImageRequest() ? artistKey(song) : albumKey(song))+QString::number(size);
|
||||
}
|
||||
|
||||
|
||||
static inline QString cacheKey(const QString &artist, const QString &album, int size)
|
||||
{
|
||||
return (album.isEmpty() ? artistKey(artist) : albumKey(artist, album))+QString::number(size);
|
||||
}
|
||||
|
||||
static const QLatin1String constScaledFormat(".jpg");
|
||||
@@ -201,32 +226,41 @@ static void clearScaledCache(const Song &song)
|
||||
|
||||
QPixmap * Covers::getScaledCover(const QString &artist, const QString &album, int size)
|
||||
{
|
||||
if (!cacheScaledCovers) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
DBUG_CLASS("Covers") << artist << album << size;
|
||||
QString cache=getScaledCoverName(artist, album, size, true);
|
||||
if (!cache.isEmpty() && QFile::exists(cache)) {
|
||||
QImage img(cache);
|
||||
if (!img.isNull() && (img.width()==size || img.height()==size)) {
|
||||
DBUG_CLASS("Covers") << artist << album << size << "scaled cover found";
|
||||
return new QPixmap(QPixmap::fromImage(img));
|
||||
// DBUG_CLASS("Covers") << artist << album << size;
|
||||
QString key=cacheKey(artist, album, size);
|
||||
QPixmap *pix(cache.object(key));
|
||||
if (!pix && cacheScaledCovers) {
|
||||
QString fileName=getScaledCoverName(artist, album, size, false);
|
||||
if (!fileName.isEmpty() && QFile::exists(fileName)) {
|
||||
QImage img(fileName);
|
||||
if (!img.isNull() && (img.width()==size || img.height()==size)) {
|
||||
DBUG_CLASS("Covers") << artist << album << size << "scaled cover found" << fileName;
|
||||
pix=new QPixmap(QPixmap::fromImage(img));
|
||||
cache.insert(key, pix, pix->width()*pix->height()*(pix->depth()/8));
|
||||
}
|
||||
}
|
||||
|
||||
if (!pix) {
|
||||
// Create a dummy pixmap so that we dont keep on stating files that do not exist!
|
||||
pix=new QPixmap(1, 1);
|
||||
cache.insert(key, pix, 4);
|
||||
}
|
||||
cacheSizes.insert(size);
|
||||
}
|
||||
return 0;
|
||||
return pix && pix->width()>1 ? pix : 0;
|
||||
}
|
||||
|
||||
bool Covers::saveScaledCover(const QImage &img, const QString &artist, const QString &album, int size)
|
||||
QPixmap * Covers::saveScaledCover(const QImage &img, const QString &artist, const QString &album, int size)
|
||||
{
|
||||
if (!cacheScaledCovers) {
|
||||
return false;
|
||||
if (cacheScaledCovers) {
|
||||
QString fileName=getScaledCoverName(artist, album, size, true);
|
||||
bool status=img.save(fileName);
|
||||
DBUG_CLASS("Covers") << artist << album << size << fileName << status;
|
||||
}
|
||||
|
||||
QString fileName=getScaledCoverName(artist, album, size, true);
|
||||
bool status=img.save(fileName);
|
||||
DBUG_CLASS("Covers") << artist << album << size << fileName << status;
|
||||
return status;
|
||||
QPixmap *pix=new QPixmap(QPixmap::fromImage(img));
|
||||
cache.insert(cacheKey(artist, album, size), pix, pix->width()*pix->height()*(pix->depth()/8));
|
||||
cacheSizes.insert(size);
|
||||
return pix;
|
||||
}
|
||||
|
||||
bool Covers::isJpg(const QByteArray &data)
|
||||
@@ -874,7 +908,6 @@ void CoverLocator::locate()
|
||||
|
||||
Covers::Covers()
|
||||
: retrieved(0)
|
||||
, cache(300000)
|
||||
, downloader(0)
|
||||
, locator(0)
|
||||
, countResetTimer(0)
|
||||
@@ -908,28 +941,13 @@ void Covers::stop()
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline QString cacheKey(const Song &song, int size)
|
||||
{
|
||||
return (song.isArtistImageRequest() ? artistKey(song) : albumKey(song))+QString::number(size);
|
||||
}
|
||||
|
||||
QPixmap * Covers::get(const Song &song, int size)
|
||||
{
|
||||
if (song.isUnknown()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
QString key=cacheKey(song, size);
|
||||
QPixmap *pix(cache.object(key));
|
||||
|
||||
if (!pix) {
|
||||
pix=getScaledCover(song.albumArtist(), song.album, size);
|
||||
if (pix) {
|
||||
cacheSizes.insert(size);
|
||||
cache.insert(key, pix, size);
|
||||
return pix;
|
||||
}
|
||||
}
|
||||
QPixmap *pix=getScaledCover(song.albumArtist(), song.album, size);
|
||||
|
||||
if (!pix) {
|
||||
QImage img;
|
||||
@@ -947,23 +965,19 @@ QPixmap * Covers::get(const Song &song, int size)
|
||||
img=findImage(song, false).img;
|
||||
}
|
||||
|
||||
cacheSizes.insert(size);
|
||||
if (!img.isNull()) {
|
||||
QImage scaled=img.scaled(size, size, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
saveScaledCover(scaled, song.albumArtist(), song.album, size);
|
||||
pix=new QPixmap(QPixmap::fromImage(scaled));
|
||||
pix=saveScaledCover(img.scaled(size, size, Qt::KeepAspectRatio, Qt::SmoothTransformation), song.albumArtist(), song.album, size);
|
||||
}
|
||||
|
||||
if (pix) {
|
||||
cache.insert(key, pix, pix->width()*pix->height()*(pix->depth()/8));
|
||||
} else {
|
||||
if (!pix) {
|
||||
// Attempt to download cover...
|
||||
if (Song::OnlineSvrTrack!=song.type) {
|
||||
tryToDownload(song);
|
||||
}
|
||||
// Create a dummy pixmap so that we dont keep on stating files that do not exist!
|
||||
pix=new QPixmap(1, 1);
|
||||
cache.insert(key, pix, 4);
|
||||
cache.insert(cacheKey(song, size), pix, 4);
|
||||
cacheSizes.insert(size);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
#include <QHash>
|
||||
#include <QSet>
|
||||
#include <QMap>
|
||||
#include <QCache>
|
||||
#include <QImage>
|
||||
#include <QPixmap>
|
||||
#include <QMutex>
|
||||
@@ -173,7 +172,7 @@ public:
|
||||
static QString artistFileName(const Song &song);
|
||||
static QString fixArtist(const QString &artist);
|
||||
static QPixmap * getScaledCover(const QString &artist, const QString &album, int size);
|
||||
static bool saveScaledCover(const QImage &img, const QString &artist, const QString &album, int size);
|
||||
static QPixmap *saveScaledCover(const QImage &img, const QString &artist, const QString &album, int size);
|
||||
static bool isJpg(const QByteArray &data);
|
||||
static bool isPng(const QByteArray &data);
|
||||
static const char * imageFormat(const QByteArray &data);
|
||||
@@ -228,8 +227,6 @@ private:
|
||||
int retrieved;
|
||||
QSet<QString> currentImageRequests;
|
||||
QList<Song> queue;
|
||||
QSet<int> cacheSizes;
|
||||
QCache<QString, QPixmap> cache;
|
||||
QMap<QString, QString> filenames;
|
||||
CoverDownloader *downloader;
|
||||
CoverLocator *locator;
|
||||
|
||||
@@ -209,11 +209,12 @@ QVariant AlbumsModel::data(const QModelIndex &index, int role) const
|
||||
return ActionModel::data(index, role);
|
||||
case ItemView::Role_Image:
|
||||
case Qt::DecorationRole: {
|
||||
if (al->cover) {
|
||||
return *(al->cover);
|
||||
QPixmap *pix=al->cover();
|
||||
if (pix) {
|
||||
return *pix;
|
||||
}
|
||||
int iSize=iconSize();
|
||||
|
||||
int iSize=iconSize();
|
||||
if (Qt::DecorationRole==role && 0==iSize) {
|
||||
return Icons::self()->albumIcon;
|
||||
}
|
||||
@@ -227,13 +228,6 @@ QVariant AlbumsModel::data(const QModelIndex &index, int role) const
|
||||
theDefaultIcon = new QPixmap(Icons::self()->albumIcon.pixmap(stdSize, stdSize)
|
||||
.scaled(QSize(cSize, cSize), Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
|
||||
}
|
||||
if (!al->coverRequested && iSize && Song::SingleTracks!=al->type) {
|
||||
al->coverRequested=true;
|
||||
al->getCover();
|
||||
if (al->cover) {
|
||||
return *(al->cover);
|
||||
}
|
||||
}
|
||||
return *theDefaultIcon;
|
||||
}
|
||||
case Qt::ToolTipRole:
|
||||
@@ -377,7 +371,6 @@ void AlbumsModel::update(const MusicLibraryItemRoot *root)
|
||||
|
||||
for (; it!=end; ++it) {
|
||||
(*it)->updated=false;
|
||||
//(*it)->coverRequested=false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < root->childCount(); i++) {
|
||||
@@ -467,7 +460,7 @@ void AlbumsModel::setCover(const Song &song, const QImage &img, const QString &f
|
||||
|
||||
for (int row=0; it!=end; ++it, ++row) {
|
||||
if ((*it)->artist==artist && (*it)->album==album) {
|
||||
if (!(*it)->cover || update) {
|
||||
if ((*it)->coverRequested || update) {
|
||||
(*it)->setCover(img);
|
||||
QModelIndex idx=index(row, 0, QModelIndex());
|
||||
emit dataChanged(idx, idx);
|
||||
@@ -488,7 +481,6 @@ void AlbumsModel::clear()
|
||||
qDeleteAll(items);
|
||||
items.clear();
|
||||
endResetModel();
|
||||
// coversRequested=false;
|
||||
}
|
||||
|
||||
void AlbumsModel::setEnabled(bool e)
|
||||
@@ -533,7 +525,6 @@ AlbumsModel::AlbumItem::AlbumItem(const QString &ar, const QString &al, quint16
|
||||
: artist(ar)
|
||||
, album(al)
|
||||
, year(y)
|
||||
, cover(0)
|
||||
, updated(false)
|
||||
, coverRequested(false)
|
||||
, numTracks(0)
|
||||
@@ -544,7 +535,6 @@ AlbumsModel::AlbumItem::AlbumItem(const QString &ar, const QString &al, quint16
|
||||
AlbumsModel::AlbumItem::~AlbumItem()
|
||||
{
|
||||
clearSongs();
|
||||
delete cover;
|
||||
}
|
||||
|
||||
bool AlbumsModel::AlbumItem::operator<(const AlbumItem &o) const
|
||||
@@ -605,51 +595,49 @@ void AlbumsModel::AlbumItem::updateStats()
|
||||
}
|
||||
}
|
||||
|
||||
void AlbumsModel::AlbumItem::getCover()
|
||||
QPixmap * AlbumsModel::AlbumItem::cover()
|
||||
{
|
||||
if (Song::SingleTracks!=type && songs.count()) {
|
||||
cover=Covers::getScaledCover(artist, album, iconSize());
|
||||
if (cover) {
|
||||
return;
|
||||
QPixmap *pix=Covers::getScaledCover(artist, album, iconSize());
|
||||
if (pix) {
|
||||
return pix;
|
||||
}
|
||||
|
||||
SongItem *firstSong=songs.first();
|
||||
Song s;
|
||||
if (Song::MultipleArtists==type) { // Then Cantata has placed this album under 'Various Artists' but the actual album as a different AlbumArtist tag
|
||||
s.artist=firstSong->albumArtist();
|
||||
} else {
|
||||
s.artist=firstSong->artist;
|
||||
s.albumartist=Song::useComposer() && !firstSong->composer.isEmpty()
|
||||
? firstSong->albumArtist() : artist;
|
||||
}
|
||||
s.album=album;
|
||||
s.year=year;
|
||||
s.file=firstSong->file;
|
||||
s.type=type;
|
||||
s.composer=firstSong->composer;
|
||||
Covers::Image img=Covers::self()->requestImage(s);
|
||||
if (!img.img.isNull()) {
|
||||
setCover(img.img);
|
||||
if (!coverRequested) {
|
||||
SongItem *firstSong=songs.first();
|
||||
Song s;
|
||||
if (Song::MultipleArtists==type) { // Then Cantata has placed this album under 'Various Artists' but the actual album as a different AlbumArtist tag
|
||||
s.artist=firstSong->albumArtist();
|
||||
} else {
|
||||
s.artist=firstSong->artist;
|
||||
s.albumartist=Song::useComposer() && !firstSong->composer.isEmpty()
|
||||
? firstSong->albumArtist() : artist;
|
||||
}
|
||||
s.album=album;
|
||||
s.year=year;
|
||||
s.file=firstSong->file;
|
||||
s.type=type;
|
||||
s.composer=firstSong->composer;
|
||||
Covers::Image img=Covers::self()->requestImage(s);
|
||||
if (img.img.isNull()) {
|
||||
coverRequested=true;
|
||||
} else {
|
||||
return setCover(img.img);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void AlbumsModel::AlbumItem::setCover(const QImage &img)
|
||||
QPixmap * AlbumsModel::AlbumItem::setCover(const QImage &img)
|
||||
{
|
||||
if (cover) {
|
||||
delete cover;
|
||||
}
|
||||
|
||||
coverRequested=false;
|
||||
if (Song::SingleTracks!=type && songs.count() && !img.isNull()) {
|
||||
int size=iconSize();
|
||||
QImage scaled=img.scaled(QSize(size, size), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
|
||||
Covers::saveScaledCover(scaled, artist, album, size);
|
||||
cover=new QPixmap(QPixmap::fromImage(scaled));
|
||||
return;
|
||||
return Covers::saveScaledCover(img.scaled(QSize(size, size), Qt::IgnoreAspectRatio, Qt::SmoothTransformation), artist, album, size);
|
||||
}
|
||||
|
||||
int size=iconSize();
|
||||
cover=new QPixmap(QPixmap::fromImage(img.scaled(QSize(size, size), Qt::IgnoreAspectRatio, Qt::SmoothTransformation)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
const AlbumsModel::SongItem *AlbumsModel::AlbumItem::getCueFile() const
|
||||
|
||||
@@ -84,8 +84,8 @@ public:
|
||||
quint32 trackCount();
|
||||
quint32 totalTime();
|
||||
void updateStats();
|
||||
void getCover();
|
||||
void setCover(const QImage &img);
|
||||
QPixmap *cover();
|
||||
QPixmap *setCover(const QImage &img);
|
||||
bool isSingleTracks() const { return Song::SingleTracks==type; }
|
||||
const SongItem *getCueFile() const;
|
||||
QString albumDisplay() const { return Song::displayAlbum(album, year); }
|
||||
@@ -94,7 +94,6 @@ public:
|
||||
quint16 year;
|
||||
QList<SongItem *> songs;
|
||||
QSet<QString> genres;
|
||||
QPixmap *cover;
|
||||
bool updated;
|
||||
bool coverRequested;
|
||||
Song::Type type;
|
||||
|
||||
@@ -251,12 +251,3 @@ QStringList MultiMusicModel::filenames(const QModelIndexList &indexes, bool play
|
||||
}
|
||||
return fnames;
|
||||
}
|
||||
|
||||
void MultiMusicModel::clearImages()
|
||||
{
|
||||
beginResetModel();
|
||||
foreach (MusicLibraryItemRoot *c, collections) {
|
||||
c->clearImages();
|
||||
}
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
@@ -47,7 +47,6 @@ public:
|
||||
QStringList filenames(const QModelIndexList &indexes, bool playableOnly=false, bool fullPath=false) const;
|
||||
const QSet<QString> & genres() { return colGenres; }
|
||||
int row(void *i) const { return collections.indexOf(static_cast<MusicLibraryItemRoot *>(i)); }
|
||||
void clearImages();
|
||||
|
||||
Q_SIGNALS:
|
||||
void updateGenres(const QSet<QString> &genres);
|
||||
|
||||
@@ -45,7 +45,6 @@
|
||||
|
||||
static MusicLibraryItemAlbum::CoverSize coverSize=MusicLibraryItemAlbum::CoverNone;
|
||||
static QPixmap *theDefaultIcon=0;
|
||||
static QPixmap *theDefaultLargeIcon=0;
|
||||
static bool dateSort=false;
|
||||
static QSize iconItemSize;
|
||||
|
||||
@@ -118,10 +117,6 @@ void MusicLibraryItemAlbum::setCoverSize(MusicLibraryItemAlbum::CoverSize size)
|
||||
delete theDefaultIcon;
|
||||
theDefaultIcon=0;
|
||||
}
|
||||
if (theDefaultLargeIcon) {
|
||||
delete theDefaultLargeIcon;
|
||||
theDefaultLargeIcon=0;
|
||||
}
|
||||
MusicLibraryItemArtist::clearDefaultCover();
|
||||
coverSize=size;
|
||||
}
|
||||
@@ -160,27 +155,21 @@ MusicLibraryItemAlbum::MusicLibraryItemAlbum(const QString &data, QString origin
|
||||
, m_totalTime(0)
|
||||
, m_numTracks(0)
|
||||
, m_originalName(original!=data ? original : QString())
|
||||
, m_coverIsDefault(false)
|
||||
, m_cover(0)
|
||||
, m_coverRequested(false)
|
||||
, m_type(Song::Standard)
|
||||
{
|
||||
}
|
||||
|
||||
MusicLibraryItemAlbum::~MusicLibraryItemAlbum()
|
||||
{
|
||||
delete m_cover;
|
||||
}
|
||||
|
||||
void MusicLibraryItemAlbum::setCoverImage(const QImage &img) const
|
||||
QPixmap * MusicLibraryItemAlbum::setCoverImage(const QImage &img) const
|
||||
{
|
||||
if (m_cover) {
|
||||
delete m_cover;
|
||||
}
|
||||
int size=iconSize(largeImages());
|
||||
QImage scaled=img.scaled(QSize(size, size), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
|
||||
m_cover = new QPixmap(QPixmap::fromImage(scaled));
|
||||
m_coverIsDefault=false;
|
||||
Covers::saveScaledCover(scaled, parentItem()->data(), data(), size);
|
||||
m_coverRequested=false;
|
||||
return Covers::saveScaledCover(scaled, parentItem()->data(), data(), size);
|
||||
}
|
||||
|
||||
QString MusicLibraryItemAlbum::displayData(bool full) const
|
||||
@@ -190,51 +179,23 @@ QString MusicLibraryItemAlbum::displayData(bool full) const
|
||||
|
||||
bool MusicLibraryItemAlbum::setCover(const QImage &img, bool update) const
|
||||
{
|
||||
if ((update || m_coverIsDefault) && !img.isNull()) {
|
||||
if ((update || m_coverRequested) && !img.isNull()) {
|
||||
setCoverImage(img);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const QPixmap & MusicLibraryItemAlbum::cover() const
|
||||
{
|
||||
if (m_coverIsDefault) {
|
||||
if (largeImages()) {
|
||||
if (theDefaultLargeIcon) {
|
||||
return *theDefaultLargeIcon;
|
||||
}
|
||||
} else if (theDefaultIcon) {
|
||||
return *theDefaultIcon;
|
||||
int iSize=iconSize(largeImages());
|
||||
if (Song::SingleTracks!=m_type && parentItem() && iSize && childCount()) {
|
||||
QPixmap *pix=Covers::getScaledCover(parentItem()->data(), data(), iSize);
|
||||
if (pix) {
|
||||
return *pix;
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_cover) {
|
||||
bool useLarge=largeImages();
|
||||
int iSize=iconSize(useLarge);
|
||||
|
||||
if ((useLarge && !theDefaultLargeIcon) || (!useLarge && !theDefaultIcon)) {
|
||||
int cSize=iSize;
|
||||
if (0==cSize) {
|
||||
cSize=22;
|
||||
}
|
||||
if (useLarge) {
|
||||
theDefaultLargeIcon = new QPixmap(Icons::self()->albumIcon.pixmap(cSize, cSize)
|
||||
.scaled(QSize(cSize, cSize), Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
|
||||
} else {
|
||||
theDefaultIcon = new QPixmap(Icons::self()->albumIcon.pixmap(cSize, cSize)
|
||||
.scaled(QSize(cSize, cSize), Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
|
||||
}
|
||||
}
|
||||
m_coverIsDefault = true;
|
||||
if (Song::SingleTracks!=m_type && parentItem() && iSize && childCount()) {
|
||||
m_cover=Covers::getScaledCover(parentItem()->data(), data(), iSize);
|
||||
if (m_cover) {
|
||||
m_coverIsDefault=false;
|
||||
return *m_cover;
|
||||
}
|
||||
|
||||
if (!m_coverRequested) {
|
||||
MusicLibraryItemSong *firstSong=static_cast<MusicLibraryItemSong*>(childItem(0));
|
||||
Song song;
|
||||
if (Song::MultipleArtists==m_type) { // Then Cantata has placed this album under 'Various Artists' but the actual album as a different AlbumArtist tag
|
||||
@@ -242,7 +203,7 @@ const QPixmap & MusicLibraryItemAlbum::cover() const
|
||||
} else {
|
||||
song.artist=firstSong->song().artist;
|
||||
song.albumartist=Song::useComposer() && !firstSong->song().composer.isEmpty()
|
||||
? firstSong->song().albumArtist() : parentItem()->data();
|
||||
? firstSong->song().albumArtist() : parentItem()->data();
|
||||
}
|
||||
song.album=Song::useComposer() ? firstSong->song().album : m_itemData;
|
||||
song.year=m_year;
|
||||
@@ -251,7 +212,8 @@ const QPixmap & MusicLibraryItemAlbum::cover() const
|
||||
song.composer=firstSong->song().composer;
|
||||
Covers::Image img;
|
||||
MusicLibraryItemRoot *root=parentItem() && parentItem()->parentItem() && MusicLibraryItem::Type_Root==parentItem()->parentItem()->itemType()
|
||||
? static_cast<MusicLibraryItemRoot *>(parentItem()->parentItem()) : 0;
|
||||
? static_cast<MusicLibraryItemRoot *>(parentItem()->parentItem()) : 0;
|
||||
m_coverRequested=true;
|
||||
if (root && !root->useAlbumImages()) {
|
||||
// Not showing album images in this model, so dont request any!
|
||||
}
|
||||
@@ -266,12 +228,12 @@ const QPixmap & MusicLibraryItemAlbum::cover() const
|
||||
else if (root && root->isOnlineService()) {
|
||||
img.img=OnlineServicesModel::self()->requestImage(static_cast<OnlineService *>(root)->id(), parentItem()->data(), data(), m_imageUrl);
|
||||
// ONLINE: Image URL is encoded in song.name...
|
||||
// if (!m_imageUrl.isEmpty()) {
|
||||
// song.name=m_imageUrl;
|
||||
// song.title=parentItem()->parentItem()->data().toLower();
|
||||
// song.type=Song::OnlineSvrTrack;
|
||||
// }
|
||||
// img=Covers::self()->requestImage(song);
|
||||
// if (!m_imageUrl.isEmpty()) {
|
||||
// song.name=m_imageUrl;
|
||||
// song.title=parentItem()->parentItem()->data().toLower();
|
||||
// song.type=Song::OnlineSvrTrack;
|
||||
// }
|
||||
// img=Covers::self()->requestImage(song);
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
@@ -279,14 +241,27 @@ const QPixmap & MusicLibraryItemAlbum::cover() const
|
||||
}
|
||||
|
||||
if (!img.img.isNull()) {
|
||||
setCoverImage(img.img);
|
||||
return *m_cover;
|
||||
pix=setCoverImage(img.img);
|
||||
if (pix) {
|
||||
return *pix;
|
||||
}
|
||||
}
|
||||
}
|
||||
return useLarge ? *theDefaultLargeIcon : *theDefaultIcon;
|
||||
}
|
||||
|
||||
return *m_cover;
|
||||
int cSize=iSize;
|
||||
if (0==cSize) {
|
||||
cSize=22;
|
||||
}
|
||||
|
||||
if (!theDefaultIcon || theDefaultIcon->width()!=cSize) {
|
||||
if (theDefaultIcon) {
|
||||
delete theDefaultIcon;
|
||||
}
|
||||
theDefaultIcon = new QPixmap(Icons::self()->albumIcon.pixmap(cSize, cSize)
|
||||
.scaled(QSize(cSize, cSize), Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
|
||||
}
|
||||
return *theDefaultIcon;
|
||||
}
|
||||
|
||||
quint32 MusicLibraryItemAlbum::totalTime()
|
||||
@@ -475,18 +450,6 @@ bool MusicLibraryItemAlbum::containsArtist(const QString &a)
|
||||
return m_artists.contains(a);
|
||||
}
|
||||
|
||||
void MusicLibraryItemAlbum::clearImage() const
|
||||
{
|
||||
if (!m_coverIsDefault) {
|
||||
m_coverIsDefault=true;
|
||||
delete m_cover;
|
||||
m_cover=0;
|
||||
if (theDefaultIcon) {
|
||||
m_cover=theDefaultIcon;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MusicLibraryItemAlbum::setYear(const MusicLibraryItemSong *song)
|
||||
{
|
||||
if (m_childItems.isEmpty() || (m_yearOfDisc>song->disc() || (m_yearOfDisc==song->disc() && m_yearOfTrack>song->track()))) {
|
||||
|
||||
@@ -67,7 +67,7 @@ public:
|
||||
QString displayData(bool full=false) const;
|
||||
bool setCover(const QImage &img, bool update=false) const;
|
||||
const QPixmap & cover() const;
|
||||
bool hasRealCover() const { return !m_coverIsDefault; }
|
||||
bool hasRealCover() const { return !m_coverRequested; }
|
||||
quint32 year() const { return m_year; }
|
||||
quint32 totalTime();
|
||||
quint32 trackCount();
|
||||
@@ -90,12 +90,11 @@ public:
|
||||
void setImageUrl(const QString &u) { m_imageUrl=u; }
|
||||
bool updateYear();
|
||||
bool containsArtist(const QString &a);
|
||||
void clearImage() const;
|
||||
// Return orignal album name. If we are grouping by composer, then album will appear as "Album (Artist)"
|
||||
const QString & originalName() const { return m_originalName; }
|
||||
|
||||
private:
|
||||
void setCoverImage(const QImage &img) const;
|
||||
QPixmap *setCoverImage(const QImage &img) const;
|
||||
void setYear(const MusicLibraryItemSong *song);
|
||||
bool largeImages() const;
|
||||
void updateStats();
|
||||
@@ -107,8 +106,7 @@ private:
|
||||
quint32 m_totalTime;
|
||||
quint32 m_numTracks;
|
||||
QString m_originalName;
|
||||
mutable bool m_coverIsDefault;
|
||||
mutable QPixmap *m_cover;
|
||||
mutable bool m_coverRequested;
|
||||
Song::Type m_type;
|
||||
QSet<QString> m_singleTrackFiles;
|
||||
QString m_imageUrl;
|
||||
|
||||
@@ -55,7 +55,7 @@ bool MusicLibraryItemArtist::lessThan(const MusicLibraryItem *a, const MusicLibr
|
||||
}
|
||||
|
||||
static QPixmap *theDefaultIcon=0;
|
||||
static QPixmap *theDefaultLargeIcon=0;
|
||||
static QPixmap *theVariousArtistsIcon=0;
|
||||
|
||||
void MusicLibraryItemArtist::clearDefaultCover()
|
||||
{
|
||||
@@ -63,16 +63,15 @@ void MusicLibraryItemArtist::clearDefaultCover()
|
||||
delete theDefaultIcon;
|
||||
theDefaultIcon=0;
|
||||
}
|
||||
if (theDefaultLargeIcon) {
|
||||
delete theDefaultLargeIcon;
|
||||
theDefaultLargeIcon=0;
|
||||
if (theVariousArtistsIcon) {
|
||||
delete theVariousArtistsIcon;
|
||||
theVariousArtistsIcon=0;
|
||||
}
|
||||
}
|
||||
|
||||
MusicLibraryItemArtist::MusicLibraryItemArtist(const QString &data, const QString &artistName, MusicLibraryItemContainer *parent)
|
||||
: MusicLibraryItemContainer(data, parent)
|
||||
, m_coverIsDefault(false)
|
||||
, m_cover(0)
|
||||
, m_coverRequested(false)
|
||||
, m_various(false)
|
||||
, m_actualArtist(artistName==data ? QString() : artistName)
|
||||
{
|
||||
@@ -85,17 +84,13 @@ MusicLibraryItemArtist::MusicLibraryItemArtist(const QString &data, const QStrin
|
||||
|
||||
bool MusicLibraryItemArtist::setCover(const QImage &img, bool update) const
|
||||
{
|
||||
if ((m_coverIsDefault || update) && !img.isNull()) {
|
||||
if ((m_coverRequested || update) && !img.isNull()) {
|
||||
int size=MusicLibraryItemAlbum::iconSize(largeImages());
|
||||
QImage scaled=img.scaled(QSize(size, size), Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation);
|
||||
if (scaled.width()>size || scaled.height()>size) {
|
||||
scaled=scaled.copy((scaled.width()-size)/2, 0, size, size);
|
||||
}
|
||||
if (m_cover) {
|
||||
delete m_cover;
|
||||
}
|
||||
m_cover = new QPixmap(QPixmap::fromImage(scaled));
|
||||
m_coverIsDefault=false;
|
||||
m_coverRequested=false;
|
||||
Covers::saveScaledCover(scaled, data(), QString(), size);
|
||||
return true;
|
||||
}
|
||||
@@ -105,104 +100,82 @@ bool MusicLibraryItemArtist::setCover(const QImage &img, bool update) const
|
||||
|
||||
const QPixmap & MusicLibraryItemArtist::cover() const
|
||||
{
|
||||
if (m_coverIsDefault) {
|
||||
if (largeImages()) {
|
||||
if (theDefaultLargeIcon) {
|
||||
return *theDefaultLargeIcon;
|
||||
int iSize=MusicLibraryItemAlbum::iconSize(largeImages());
|
||||
int cSize=iSize;
|
||||
if (0==cSize) {
|
||||
cSize=22;
|
||||
}
|
||||
if (m_various) {
|
||||
if (!theVariousArtistsIcon || theVariousArtistsIcon->width()!=cSize) {
|
||||
if (theVariousArtistsIcon) {
|
||||
delete theVariousArtistsIcon;
|
||||
}
|
||||
theVariousArtistsIcon = new QPixmap(Icons::self()->variousArtistsIcon.pixmap(cSize, cSize)
|
||||
.scaled(QSize(cSize, cSize), Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
|
||||
}
|
||||
return *theVariousArtistsIcon;
|
||||
}
|
||||
|
||||
QPixmap *pix=Covers::getScaledCover(data(), QString(), iSize);
|
||||
if (pix) {
|
||||
return *pix;
|
||||
}
|
||||
|
||||
if (!m_coverRequested) {
|
||||
Covers::Image img;
|
||||
Song song;
|
||||
song.albumartist=m_itemData;
|
||||
|
||||
MusicLibraryItemAlbum *firstAlbum=static_cast<MusicLibraryItemAlbum *>(childItem(0));
|
||||
MusicLibraryItemSong *firstSong=firstAlbum ? static_cast<MusicLibraryItemSong *>(firstAlbum->childItem(0)) : 0;
|
||||
|
||||
if (firstSong) {
|
||||
song.file=firstSong->file();
|
||||
if (Song::useComposer() && !firstSong->song().composer.isEmpty()) {
|
||||
song.albumartist=firstSong->song().albumArtist();
|
||||
}
|
||||
}
|
||||
MusicLibraryItemRoot *root=parentItem() && MusicLibraryItem::Type_Root==parentItem()->itemType()
|
||||
? static_cast<MusicLibraryItemRoot *>(parentItem()) : 0;
|
||||
// NO ARTIST IMAGES FOR DEVICES!
|
||||
//#ifdef ENABLE_DEVICES_SUPPORT
|
||||
//if (root && root->isDevice()) {
|
||||
// // This item is in the devices model, so get cover from device...
|
||||
// song.id=firstSong->song().id;
|
||||
// static_cast<Device *>(root)->requestArtistImage(song);
|
||||
//} else
|
||||
//#endif
|
||||
m_coverRequested=true;
|
||||
if (root && !root->useArtistImages()) {
|
||||
// Not showing artist images in this model, so dont request any!
|
||||
}
|
||||
#ifdef ENABLE_ONLINE_SERVICES
|
||||
else if (root && root->isOnlineService()) {
|
||||
img.img=OnlineServicesModel::self()->requestImage(static_cast<OnlineService *>(parentItem())->id(), data(), QString(), m_imageUrl);
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
img=Covers::self()->requestImage(song);
|
||||
}
|
||||
|
||||
if (!img.img.isNull()) {
|
||||
setCover(img.img);
|
||||
m_coverRequested=false;
|
||||
pix=Covers::getScaledCover(data(), QString(), iSize);
|
||||
if (pix) {
|
||||
return *pix;
|
||||
}
|
||||
} else if (theDefaultIcon) {
|
||||
return *theDefaultIcon;
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_cover) {
|
||||
bool useLarge=largeImages();
|
||||
int iSize=MusicLibraryItemAlbum::iconSize(useLarge);
|
||||
int cSize=iSize;
|
||||
if (0==cSize) {
|
||||
cSize=22;
|
||||
}
|
||||
|
||||
if (m_various) {
|
||||
m_cover = new QPixmap(Icons::self()->variousArtistsIcon.pixmap(cSize, cSize).scaled(QSize(cSize, cSize), Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
|
||||
m_coverIsDefault=false;
|
||||
} else {
|
||||
m_cover=Covers::getScaledCover(data(), QString(), iSize);
|
||||
if (m_cover) {
|
||||
m_coverIsDefault=false;
|
||||
return *m_cover;
|
||||
}
|
||||
|
||||
if (useLarge) {
|
||||
theDefaultLargeIcon = new QPixmap(Icons::self()->artistIcon.pixmap(cSize, cSize)
|
||||
.scaled(QSize(cSize, cSize), Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
|
||||
} else {
|
||||
theDefaultIcon = new QPixmap(Icons::self()->artistIcon.pixmap(cSize, cSize)
|
||||
.scaled(QSize(cSize, cSize), Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
|
||||
}
|
||||
m_coverIsDefault = true;
|
||||
Covers::Image img;
|
||||
Song song;
|
||||
song.albumartist=m_itemData;
|
||||
|
||||
MusicLibraryItemAlbum *firstAlbum=static_cast<MusicLibraryItemAlbum *>(childItem(0));
|
||||
MusicLibraryItemSong *firstSong=firstAlbum ? static_cast<MusicLibraryItemSong *>(firstAlbum->childItem(0)) : 0;
|
||||
|
||||
if (firstSong) {
|
||||
song.file=firstSong->file();
|
||||
if (Song::useComposer() && !firstSong->song().composer.isEmpty()) {
|
||||
song.albumartist=firstSong->song().albumArtist();
|
||||
}
|
||||
}
|
||||
MusicLibraryItemRoot *root=parentItem() && MusicLibraryItem::Type_Root==parentItem()->itemType()
|
||||
? static_cast<MusicLibraryItemRoot *>(parentItem()) : 0;
|
||||
// NO ARTIST IMAGES FOR DEVICES!
|
||||
//#ifdef ENABLE_DEVICES_SUPPORT
|
||||
//if (root && root->isDevice()) {
|
||||
// // This item is in the devices model, so get cover from device...
|
||||
// song.id=firstSong->song().id;
|
||||
// static_cast<Device *>(root)->requestArtistImage(song);
|
||||
//} else
|
||||
//#endif
|
||||
if (root && !root->useArtistImages()) {
|
||||
// Not showing artist images in this model, so dont request any!
|
||||
}
|
||||
#ifdef ENABLE_ONLINE_SERVICES
|
||||
else if (root && root->isOnlineService()) {
|
||||
img.img=OnlineServicesModel::self()->requestImage(static_cast<OnlineService *>(parentItem())->id(), data(), QString(), m_imageUrl);
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
img=Covers::self()->requestImage(song);
|
||||
}
|
||||
|
||||
if (!img.img.isNull()) {
|
||||
setCover(img.img);
|
||||
m_coverIsDefault=false;
|
||||
return *m_cover;
|
||||
}
|
||||
return useLarge ? *theDefaultLargeIcon : *theDefaultIcon;
|
||||
}
|
||||
}
|
||||
|
||||
return *m_cover;
|
||||
}
|
||||
|
||||
void MusicLibraryItemArtist::clearImages() const
|
||||
{
|
||||
if (!m_coverIsDefault) {
|
||||
m_coverIsDefault=true;
|
||||
delete m_cover;
|
||||
m_cover=0;
|
||||
if (!theDefaultIcon || theDefaultIcon->width()!=cSize) {
|
||||
if (theDefaultIcon) {
|
||||
m_cover=theDefaultIcon;
|
||||
}
|
||||
}
|
||||
foreach (MusicLibraryItem *i, m_childItems) {
|
||||
if (MusicLibraryItem::Type_Album==i->itemType()) {
|
||||
static_cast<MusicLibraryItemAlbum *>(i)->clearImage();
|
||||
delete theDefaultIcon;
|
||||
}
|
||||
theDefaultIcon = new QPixmap(Icons::self()->albumIcon.pixmap(cSize, cSize)
|
||||
.scaled(QSize(cSize, cSize), Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
|
||||
}
|
||||
return *theDefaultIcon;
|
||||
}
|
||||
|
||||
MusicLibraryItemAlbum * MusicLibraryItemArtist::album(const Song &s, bool create)
|
||||
|
||||
@@ -59,10 +59,9 @@ public:
|
||||
static void clearDefaultCover();
|
||||
bool setCover(const QImage &img, bool update=false) const;
|
||||
const QPixmap & cover() const;
|
||||
bool hasRealCover() const { return !m_coverIsDefault; }
|
||||
bool hasRealCover() const { return !m_coverRequested; }
|
||||
const QString & imageUrl() const { return m_imageUrl; }
|
||||
void setImageUrl(const QString &u) { m_imageUrl=u; }
|
||||
void clearImages() const;
|
||||
// 'data' could be 'Composer' if we are set to use that, but need to save real artist...
|
||||
const QString & actualArtist() const { return m_actualArtist; }
|
||||
|
||||
@@ -70,8 +69,7 @@ private:
|
||||
bool largeImages() const;
|
||||
|
||||
private:
|
||||
mutable bool m_coverIsDefault;
|
||||
mutable QPixmap *m_cover;
|
||||
mutable bool m_coverRequested;
|
||||
bool m_various;
|
||||
QString m_nonTheArtist;
|
||||
QString m_actualArtist;
|
||||
|
||||
@@ -1001,15 +1001,6 @@ void MusicLibraryItemRoot::removeSongFromList(const Song &s)
|
||||
}
|
||||
}
|
||||
|
||||
void MusicLibraryItemRoot::clearImages()
|
||||
{
|
||||
foreach (MusicLibraryItem *i, m_childItems) {
|
||||
if (MusicLibraryItem::Type_Artist==i->itemType()) {
|
||||
static_cast<MusicLibraryItemArtist *>(i)->clearImages();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QString MusicLibraryItemRoot::artistName(const Song &s)
|
||||
{
|
||||
if (Song::Standard==s.type || (Song::Playlist==s.type && !s.albumArtist().isEmpty())) {
|
||||
|
||||
@@ -111,7 +111,6 @@ public:
|
||||
bool updateSong(const Song &orig, const Song &edit);
|
||||
void addSongToList(const Song &s);
|
||||
void removeSongFromList(const Song &s);
|
||||
void clearImages();
|
||||
static QString artistName(const Song &s);
|
||||
|
||||
protected:
|
||||
|
||||
@@ -233,7 +233,6 @@ void OnlineServicesPage::addSelectionToPlaylist(const QString &name, bool replac
|
||||
void OnlineServicesPage::refresh()
|
||||
{
|
||||
view->setLevel(0);
|
||||
OnlineServicesModel::self()->clearImages();
|
||||
}
|
||||
|
||||
void OnlineServicesPage::itemDoubleClicked(const QModelIndex &)
|
||||
|
||||
Reference in New Issue
Block a user