Files
cantata/models/mpdlibrarymodel.cpp
Craig Drummond 0a73215867 Update (c) year
2017-04-02 18:45:30 +01:00

259 lines
8.4 KiB
C++

/*
* Cantata
*
* Copyright (c) 2017 Craig Drummond <craig.p.drummond@gmail.com>
*
* ----
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "mpdlibrarymodel.h"
#include "support/globalstatic.h"
#include "support/configuration.h"
#include "db/mpdlibrarydb.h"
#include "gui/settings.h"
#include "gui/covers.h"
#include "roles.h"
#include <QTimer>
#include <QDebug>
GLOBAL_STATIC(MpdLibraryModel, instance)
MpdLibraryModel::MpdLibraryModel()
: SqlLibraryModel(new MpdLibraryDb(0), 0)
, showArtistImages(false)
{
connect(Covers::self(), SIGNAL(cover(Song,QImage,QString)), this, SLOT(cover(Song,QImage,QString)));
connect(Covers::self(), SIGNAL(coverUpdated(Song,QImage,QString)), this, SLOT(coverUpdated(Song,QImage,QString)));
connect(Covers::self(), SIGNAL(artistImage(Song,QImage,QString)), this, SLOT(artistImage(Song,QImage,QString)));
connect(Covers::self(), SIGNAL(composerImage(Song,QImage,QString)), this, SLOT(artistImage(Song,QImage,QString)));
if (MPDConnection::self()->isConnected()) {
static_cast<MpdLibraryDb *>(db)->connectionChanged(MPDConnection::self()->getDetails());
}
}
QVariant MpdLibraryModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid()) {
return QVariant();
}
switch (role) {
case Cantata::Role_ListImage: {
Item *item = static_cast<Item *>(index.internalPointer());
return T_Album==item->getType() || (T_Artist==item->getType() && useArtistImages());
}
case Cantata::Role_GridCoverSong:
case Cantata::Role_CoverSong: {
QVariant v;
Item *item = static_cast<Item *>(index.internalPointer());
switch (item->getType()) {
case T_Album:
if (item->getSong().isEmpty()) {
Song song=static_cast<MpdLibraryDb *>(db)->getCoverSong(T_Album==topLevel() ? static_cast<AlbumItem *>(item)->getArtistId() : item->getParent()->getId(), item->getId());
item->setSong(song);
if (T_Genre==topLevel()) {
song.addGenre(item->getParent()->getParent()->getId());
}
}
v.setValue<Song>(item->getSong());
break;
case T_Artist:
if (!showArtistImages && Cantata::Role_CoverSong==role) {
return QVariant();
}
if (item->getSong().isEmpty()) {
Song song=static_cast<MpdLibraryDb *>(db)->getCoverSong(item->getId());
if (song.useComposer()) {
song.setComposerImageRequest();
} else {
song.setArtistImageRequest();
}
if (T_Genre==topLevel()) {
song.addGenre(item->getParent()->getId());
}
item->setSong(song);
}
v.setValue<Song>(item->getSong());
break;
default:
break;
}
return v;
}
}
return SqlLibraryModel::data(index, role);
}
void MpdLibraryModel::setUseArtistImages(bool u)
{
if (u!=showArtistImages) {
showArtistImages=u;
switch(topLevel()) {
case T_Genre: {
foreach (const Item *g, root->getChildren()) {
const CollectionItem *genre=static_cast<const CollectionItem *>(g);
if (genre->getChildCount()) {
QModelIndex idx=index(genre->getRow(), 0, QModelIndex());
emit dataChanged(index(0, 0, idx), index(genre->getChildCount()-1, 0, idx));
}
}
break;
}
case T_Artist:
if (root->getChildCount()) {
emit dataChanged(index(0, 0, QModelIndex()), index(root->getChildCount()-1, 0, QModelIndex()));
}
break;
default:
break;
}
}
}
static QLatin1String constUseArtistImagesKey("artistImages");
void MpdLibraryModel::load(Configuration &config)
{
showArtistImages=config.get(constUseArtistImagesKey, showArtistImages);
SqlLibraryModel::load(config);
}
void MpdLibraryModel::save(Configuration &config)
{
config.set(constUseArtistImagesKey, showArtistImages);
SqlLibraryModel::save(config);
}
void MpdLibraryModel::listSongs()
{
listingTotal=db->trackCount();
listingCurrent=0;
if (listingTotal>0) {
QTimer::singleShot(0, this, SLOT(listNextChunk()));
} else {
emit songListing(QList<Song>(), 100.0);
}
}
void MpdLibraryModel::cancelListing()
{
listingTotal=0;
}
static const int constMaxSongsInList=1000;
void MpdLibraryModel::listNextChunk()
{
if (listingTotal<=0) {
return;
}
QList<Song> songs=db->getTracks(listingCurrent, constMaxSongsInList);
listingCurrent+=songs.count();
emit songListing(songs, (listingCurrent*100.0)/(listingTotal*1.0));
if (songs.count()>0) {
if (listingCurrent==listingTotal) {
emit songListing(QList<Song>(), 100.0);
} else {
QTimer::singleShot(0, this, SLOT(listNextChunk()));
}
}
}
void MpdLibraryModel::cover(const Song &song, const QImage &img, const QString &file)
{
if (file.isEmpty() || img.isNull() || song.isFromOnlineService()) {
return;
}
switch(topLevel()) {
case T_Genre: {
const Item *genre=root ? root->getChild(song.genres[0]) : 0;
if (genre) {
const Item *artist=static_cast<const CollectionItem *>(genre)->getChild(song.artistOrComposer());
if (artist) {
const Item *album=static_cast<const CollectionItem *>(artist)->getChild(song.albumId());
if (album) {
QModelIndex idx=index(album->getRow(), 0, index(artist->getRow(), 0, index(genre->getRow(), 0, QModelIndex())));
emit dataChanged(idx, idx);
}
}
}
break;
}
case T_Artist: {
const Item *artist=root ? root->getChild(song.artistOrComposer()) : 0;
if (artist) {
const Item *album=static_cast<const CollectionItem *>(artist)->getChild(song.albumId());
if (album) {
QModelIndex idx=index(album->getRow(), 0, index(artist->getRow(), 0, QModelIndex()));
emit dataChanged(idx, idx);
}
}
break;
}
case T_Album: {
const Item *album=root ? root->getChild(song.artistOrComposer()+song.albumId()) : 0;
if (album) {
QModelIndex idx=index(album->getRow(), 0, QModelIndex());
emit dataChanged(idx, idx);
}
break;
}
default:
break;
}
}
void MpdLibraryModel::coverUpdated(const Song &song, const QImage &img, const QString &file)
{
if (file.isEmpty() || img.isNull() || (T_Album==topLevel() && (song.isArtistImageRequest() || song.isComposerImageRequest()))) {
return;
}
cover(song, img, file);
}
void MpdLibraryModel::artistImage(const Song &song, const QImage &img, const QString &file)
{
if (file.isEmpty() || img.isNull() || T_Album==topLevel()) {
return;
}
switch(topLevel()) {
case T_Genre: {
const Item *genre=root ? root->getChild(song.genres[0]) : 0;
if (genre) {
const Item *artist=static_cast<const CollectionItem *>(genre)->getChild(song.artistOrComposer());
if (artist) {
QModelIndex idx=index(artist->getRow(), 0, index(genre->getRow(), 0, QModelIndex()));
emit dataChanged(idx, idx);
}
}
break;
}
case T_Artist: {
const Item *artist=root ? root->getChild(song.artistOrComposer()) : 0;
if (artist) {
QModelIndex idx=index(artist->getRow(), 0, QModelIndex());
emit dataChanged(idx, idx);
}
break;
}
default:
break;
}
}