1 /* This file is part of Clementine.
2    Copyright 2012, David Sansome <me@davidsansome.com>
3 
4    Clementine is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation, either version 3 of the License, or
7    (at your option) any later version.
8 
9    Clementine is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13 
14    You should have received a copy of the GNU General Public License
15    along with Clementine.  If not, see <http://www.gnu.org/licenses/>.
16 */
17 
18 #include "standarditemiconloader.h"
19 #include "covers/albumcoverloader.h"
20 
21 #include <QAbstractItemModel>
22 #include <QSet>
23 #include <QStandardItem>
24 
StandardItemIconLoader(AlbumCoverLoader * cover_loader,QObject * parent)25 StandardItemIconLoader::StandardItemIconLoader(AlbumCoverLoader* cover_loader,
26                                                QObject* parent)
27     : QObject(parent), cover_loader_(cover_loader), model_(nullptr) {
28   cover_options_.desired_height_ = 16;
29 
30   connect(cover_loader_, SIGNAL(ImageLoaded(quint64, QImage)),
31           SLOT(ImageLoaded(quint64, QImage)));
32 }
33 
SetModel(QAbstractItemModel * model)34 void StandardItemIconLoader::SetModel(QAbstractItemModel* model) {
35   if (model_) {
36     disconnect(model_, SIGNAL(rowsAboutToBeRemoved(QModelIndex, int, int)),
37                this, SLOT(RowsAboutToBeRemoved(QModelIndex, int, int)));
38   }
39 
40   model_ = model;
41 
42   connect(model_, SIGNAL(rowsAboutToBeRemoved(QModelIndex, int, int)),
43           SLOT(RowsAboutToBeRemoved(QModelIndex, int, int)));
44   connect(model_, SIGNAL(modelAboutToBeReset()), SLOT(ModelReset()));
45 }
46 
LoadIcon(const QString & art_automatic,const QString & art_manual,QStandardItem * for_item)47 void StandardItemIconLoader::LoadIcon(const QString& art_automatic,
48                                       const QString& art_manual,
49                                       QStandardItem* for_item) {
50   const quint64 id =
51       cover_loader_->LoadImageAsync(cover_options_, art_automatic, art_manual);
52   pending_covers_[id] = for_item;
53 }
54 
LoadIcon(const Song & song,QStandardItem * for_item)55 void StandardItemIconLoader::LoadIcon(const Song& song,
56                                       QStandardItem* for_item) {
57   const quint64 id = cover_loader_->LoadImageAsync(cover_options_, song);
58   pending_covers_[id] = for_item;
59 }
60 
RowsAboutToBeRemoved(const QModelIndex & parent,int begin,int end)61 void StandardItemIconLoader::RowsAboutToBeRemoved(const QModelIndex& parent,
62                                                   int begin, int end) {
63   for (QMap<quint64, QStandardItem*>::iterator it = pending_covers_.begin();
64        it != pending_covers_.end();) {
65     const QStandardItem* item = it.value();
66     const QStandardItem* item_parent = item->parent();
67 
68     if (item_parent && item_parent->index() == parent &&
69         item->index().row() >= begin && item->index().row() <= end) {
70       cover_loader_->CancelTask(it.key());
71       it = pending_covers_.erase(it);
72     } else {
73       ++it;
74     }
75   }
76 }
77 
ModelReset()78 void StandardItemIconLoader::ModelReset() {
79   cover_loader_->CancelTasks(QSet<quint64>::fromList(pending_covers_.keys()));
80   pending_covers_.clear();
81 }
82 
ImageLoaded(quint64 id,const QImage & image)83 void StandardItemIconLoader::ImageLoaded(quint64 id, const QImage& image) {
84   QStandardItem* item = pending_covers_.take(id);
85   if (!item) return;
86 
87   if (!image.isNull()) {
88     item->setIcon(QIcon(QPixmap::fromImage(image)));
89   }
90 }
91