222 lines
6.5 KiB
C++
222 lines
6.5 KiB
C++
/*
|
|
* Cantata
|
|
*
|
|
* Copyright (c) 2011-2022 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 "onlinedbservice.h"
|
|
#include "gui/covers.h"
|
|
#include "models/roles.h"
|
|
#include "network/networkaccessmanager.h"
|
|
#include "qtiocompressor/qtiocompressor.h"
|
|
#include "db/onlinedb.h"
|
|
#include <QXmlStreamReader>
|
|
|
|
OnlineXmlParser::OnlineXmlParser()
|
|
{
|
|
thread=new Thread(metaObject()->className());
|
|
moveToThread(thread);
|
|
thread->start();
|
|
connect(this, SIGNAL(startParsing(NetworkJob*)), this, SLOT(doParsing(NetworkJob*)));
|
|
}
|
|
|
|
OnlineXmlParser::~OnlineXmlParser()
|
|
{
|
|
}
|
|
|
|
void OnlineXmlParser::start(NetworkJob *job)
|
|
{
|
|
emit startParsing(job);
|
|
}
|
|
|
|
void OnlineXmlParser::doParsing(NetworkJob *job)
|
|
{
|
|
QtIOCompressor comp(job->actualJob());
|
|
comp.setStreamFormat(QtIOCompressor::GzipFormat);
|
|
if (comp.open(QIODevice::ReadOnly)) {
|
|
QXmlStreamReader reader;
|
|
reader.setDevice(&comp);
|
|
emit startUpdate();
|
|
int artistCount=parse(reader);
|
|
if (artistCount>0) {
|
|
emit endUpdate();
|
|
emit stats(artistCount);
|
|
} else {
|
|
emit error(tr("Failed to parse"));
|
|
emit abortUpdate();
|
|
}
|
|
} else {
|
|
emit error(tr("Failed to parse"));
|
|
}
|
|
emit complete();
|
|
}
|
|
|
|
OnlineDbService::OnlineDbService(LibraryDb *d, QObject *p)
|
|
: SqlLibraryModel(d, p, T_Genre)
|
|
, lastPc(-1)
|
|
, job(nullptr)
|
|
{
|
|
connect(Covers::self(), SIGNAL(cover(Song,QImage,QString)), this, SLOT(cover(Song,QImage,QString)));
|
|
}
|
|
|
|
QVariant OnlineDbService::data(const QModelIndex &index, int role) const
|
|
{
|
|
if (!index.isValid()) {
|
|
switch (role) {
|
|
case Cantata::Role_TitleText:
|
|
return title();
|
|
case Cantata::Role_SubText:
|
|
if (!status.isEmpty()) {
|
|
return status;
|
|
}
|
|
if (!stats.isEmpty()) {
|
|
return stats;
|
|
}
|
|
return descr();
|
|
case Qt::DecorationRole:
|
|
return icon();
|
|
}
|
|
}
|
|
return SqlLibraryModel::data(index, role);
|
|
}
|
|
|
|
bool OnlineDbService::previouslyDownloaded() const
|
|
{
|
|
// Create DB, if it does not already exist
|
|
static_cast<OnlineDb *>(db)->create();
|
|
return 0!=db->getCurrentVersion();
|
|
}
|
|
|
|
void OnlineDbService::open()
|
|
{
|
|
if (0==rowCount(QModelIndex())) {
|
|
// Create DB, if it does not already exist
|
|
static_cast<OnlineDb *>(db)->create();
|
|
libraryUpdated();
|
|
updateStats();
|
|
}
|
|
}
|
|
|
|
void OnlineDbService::download(bool redownload)
|
|
{
|
|
if (job) {
|
|
return;
|
|
}
|
|
if (redownload || !previouslyDownloaded()) {
|
|
job=NetworkAccessManager::self()->get(QUrl(listingUrl()));
|
|
connect(job, SIGNAL(downloadPercent(int)), this, SLOT(downloadPercent(int)));
|
|
connect(job, SIGNAL(finished()), this, SLOT(downloadFinished()));
|
|
lastPc=-1;
|
|
downloadPercent(0);
|
|
}
|
|
}
|
|
|
|
void OnlineDbService::abort()
|
|
{
|
|
if (job) {
|
|
job->cancelAndDelete();
|
|
job=nullptr;
|
|
}
|
|
db->abortUpdate();
|
|
}
|
|
|
|
void OnlineDbService::cover(const Song &song, const QImage &img, const QString &file)
|
|
{
|
|
if (file.isEmpty() || img.isNull() || !song.isFromOnlineService() || song.onlineService()!=name()) {
|
|
return;
|
|
}
|
|
|
|
const Item *genre=root ? root->getChild(song.genres[0]) : nullptr;
|
|
if (genre) {
|
|
const Item *artist=static_cast<const CollectionItem *>(genre)->getChild(song.albumArtistOrComposer());
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void OnlineDbService::updateStatus(const QString &msg)
|
|
{
|
|
status=msg;
|
|
emit dataChanged(QModelIndex(), QModelIndex());
|
|
}
|
|
|
|
void OnlineDbService::downloadPercent(int pc)
|
|
{
|
|
if (lastPc!=pc) {
|
|
lastPc=pc;
|
|
updateStatus(tr("Downloading...%1%").arg(pc));
|
|
}
|
|
}
|
|
|
|
void OnlineDbService::downloadFinished()
|
|
{
|
|
NetworkJob *reply=qobject_cast<NetworkJob *>(sender());
|
|
if (!reply) {
|
|
return;
|
|
}
|
|
|
|
if (reply!=job) {
|
|
reply->deleteLater();
|
|
return;
|
|
}
|
|
|
|
if (reply->ok()) {
|
|
// Ensure DB is created
|
|
static_cast<OnlineDb *>(db)->create();
|
|
updateStatus(tr("Parsing music list...."));
|
|
OnlineXmlParser *parser=createParser();
|
|
db->clear();
|
|
connect(parser, SIGNAL(startUpdate()), static_cast<OnlineDb *>(db), SLOT(startUpdate()));
|
|
connect(parser, SIGNAL(endUpdate()), static_cast<OnlineDb *>(db), SLOT(endUpdate()));
|
|
connect(parser, SIGNAL(abortUpdate()), static_cast<OnlineDb *>(db), SLOT(abortUpdate()));
|
|
connect(parser, SIGNAL(stats(int)), static_cast<OnlineDb *>(db), SLOT(insertStats(int)));
|
|
connect(parser, SIGNAL(coverUrl(QString,QString,QString)), static_cast<OnlineDb *>(db), SLOT(storeCoverUrl(QString,QString,QString)));
|
|
connect(parser, SIGNAL(songs(QList<Song>*)), static_cast<OnlineDb *>(db), SLOT(insertSongs(QList<Song>*)));
|
|
connect(parser, SIGNAL(complete()), job, SLOT(deleteLater()));
|
|
connect(parser, SIGNAL(complete()), this, SLOT(updateStats()));
|
|
connect(parser, SIGNAL(error(QString)), this, SIGNAL(error(QString)));
|
|
connect(parser, SIGNAL(complete()), parser, SLOT(deleteLater()));
|
|
parser->start(reply);
|
|
} else {
|
|
reply->deleteLater();
|
|
updateStatus(QString());
|
|
emit error(tr("Failed to download"));
|
|
}
|
|
job=nullptr;
|
|
}
|
|
|
|
void OnlineDbService::updateStats()
|
|
{
|
|
int numArtists=static_cast<OnlineDb *>(db)->getStats();
|
|
if (numArtists>0) {
|
|
stats=tr("%n Artist(s)", "", numArtists);
|
|
} else {
|
|
stats=QString();
|
|
}
|
|
updateStatus(QString());
|
|
}
|
|
|
|
#include "moc_onlinedbservice.cpp"
|