Reduce memory usage, by storing album covers in a cache - and using this for display.

This commit is contained in:
craig.p.drummond
2014-03-12 17:20:29 +00:00
committed by craig.p.drummond
parent 374e055ed2
commit 7716ed9962
16 changed files with 220 additions and 311 deletions

View File

@@ -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
View File

@@ -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)

View File

@@ -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())));

View File

@@ -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);
}
}

View File

@@ -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;

View File

@@ -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

View File

@@ -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;

View File

@@ -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();
}

View File

@@ -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);

View File

@@ -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()))) {

View File

@@ -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;

View File

@@ -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)

View File

@@ -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;

View File

@@ -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())) {

View File

@@ -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:

View File

@@ -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 &)