2016-03-03 22:21:15 +01:00
|
|
|
#ifndef DBQUERY_H
|
|
|
|
#define DBQUERY_H
|
|
|
|
|
|
|
|
#include <c++utilities/application/global.h>
|
|
|
|
|
|
|
|
#include <QAbstractTableModel>
|
2016-11-10 23:45:08 +01:00
|
|
|
#include <QNetworkReply>
|
2016-03-03 22:21:15 +01:00
|
|
|
|
2019-06-12 20:47:44 +02:00
|
|
|
#ifdef CPP_UTILITIES_DEBUG_BUILD
|
2018-03-07 01:18:01 +01:00
|
|
|
#include <iostream>
|
2016-10-09 22:41:34 +02:00
|
|
|
#endif
|
|
|
|
|
2016-03-06 17:52:33 +01:00
|
|
|
QT_FORWARD_DECLARE_CLASS(QNetworkReply)
|
|
|
|
|
2019-07-07 12:00:16 +02:00
|
|
|
#define TAGEDITOR_ENUM_CLASS enum class
|
2018-03-06 23:10:13 +01:00
|
|
|
namespace TagParser {
|
2016-03-03 22:21:15 +01:00
|
|
|
class TagValue;
|
2019-07-07 12:00:16 +02:00
|
|
|
TAGEDITOR_ENUM_CLASS KnownField : unsigned int;
|
2018-03-07 01:18:01 +01:00
|
|
|
} // namespace TagParser
|
2019-07-07 12:00:16 +02:00
|
|
|
#undef TAGEDITOR_ENUM_CLASS
|
2016-03-03 22:21:15 +01:00
|
|
|
|
|
|
|
namespace QtGui {
|
|
|
|
|
2018-03-07 01:18:01 +01:00
|
|
|
struct SongDescription {
|
2017-08-08 20:22:37 +02:00
|
|
|
SongDescription(const QString &songId = QString());
|
2016-03-03 22:21:15 +01:00
|
|
|
|
2017-08-08 20:22:37 +02:00
|
|
|
QString songId;
|
2016-03-03 22:21:15 +01:00
|
|
|
QString title;
|
|
|
|
QString album;
|
2016-03-06 17:52:33 +01:00
|
|
|
QString albumId;
|
2016-03-03 22:21:15 +01:00
|
|
|
QString artist;
|
2019-05-31 13:54:16 +02:00
|
|
|
QString artistId;
|
2016-03-03 22:21:15 +01:00
|
|
|
QString year;
|
|
|
|
QString genre;
|
2019-03-13 19:07:51 +01:00
|
|
|
std::int32_t track;
|
|
|
|
std::int32_t totalTracks;
|
|
|
|
std::int32_t disk;
|
2016-03-06 17:52:33 +01:00
|
|
|
QByteArray cover;
|
2016-10-09 22:41:34 +02:00
|
|
|
QString lyrics;
|
2017-07-30 20:30:50 +02:00
|
|
|
QString coverUrl;
|
2016-03-03 22:21:15 +01:00
|
|
|
};
|
|
|
|
|
2018-03-07 01:18:01 +01:00
|
|
|
class QueryResultsModel : public QAbstractTableModel {
|
2016-03-03 22:21:15 +01:00
|
|
|
Q_OBJECT
|
|
|
|
|
|
|
|
public:
|
|
|
|
enum Column {
|
|
|
|
TitleCol,
|
|
|
|
AlbumCol,
|
|
|
|
ArtistCol,
|
|
|
|
GenreCol,
|
|
|
|
YearCol,
|
|
|
|
TrackCol,
|
2017-08-08 20:22:37 +02:00
|
|
|
TotalTracksCol,
|
2019-06-01 12:50:09 +02:00
|
|
|
DiskCol,
|
|
|
|
EndCol,
|
2016-03-03 22:21:15 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
const QList<SongDescription> &results() const;
|
|
|
|
const QStringList &errorList() const;
|
|
|
|
bool areResultsAvailable() const;
|
2016-03-06 17:52:33 +01:00
|
|
|
bool isFetchingCover() const;
|
2018-03-06 23:10:13 +01:00
|
|
|
TagParser::TagValue fieldValue(int row, TagParser::KnownField knownField) const;
|
2016-03-03 22:21:15 +01:00
|
|
|
|
2019-06-01 12:45:12 +02:00
|
|
|
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
|
|
|
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
|
|
|
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
|
|
|
|
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
|
|
|
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
2016-03-06 17:52:33 +01:00
|
|
|
const QByteArray *cover(const QModelIndex &index) const;
|
|
|
|
virtual bool fetchCover(const QModelIndex &index);
|
2016-10-09 22:41:34 +02:00
|
|
|
const QString *lyrics(const QModelIndex &index) const;
|
|
|
|
virtual bool fetchLyrics(const QModelIndex &index);
|
2016-03-06 17:52:33 +01:00
|
|
|
virtual void abort();
|
2017-08-08 20:22:37 +02:00
|
|
|
virtual QUrl webUrl(const QModelIndex &index);
|
2016-03-03 22:21:15 +01:00
|
|
|
|
2020-03-09 18:46:08 +01:00
|
|
|
Q_SIGNALS:
|
2016-03-03 22:21:15 +01:00
|
|
|
void resultsAvailable();
|
2016-03-06 17:52:33 +01:00
|
|
|
void coverAvailable(const QModelIndex &index);
|
2016-10-09 22:41:34 +02:00
|
|
|
void lyricsAvailable(const QModelIndex &index);
|
2016-03-03 22:21:15 +01:00
|
|
|
|
|
|
|
protected:
|
|
|
|
QueryResultsModel(QObject *parent = nullptr);
|
|
|
|
void setResultsAvailable(bool resultsAvailable);
|
2016-03-06 17:52:33 +01:00
|
|
|
void setFetchingCover(bool fetchingCover);
|
2016-03-03 22:21:15 +01:00
|
|
|
|
|
|
|
QList<SongDescription> m_results;
|
|
|
|
QStringList m_errorList;
|
|
|
|
bool m_resultsAvailable;
|
2016-03-06 17:52:33 +01:00
|
|
|
bool m_fetchingCover;
|
2019-06-14 18:08:05 +02:00
|
|
|
static std::list<QString> s_coverNames;
|
|
|
|
static std::map<QString, QByteArray> s_coverData;
|
2016-03-03 22:21:15 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
inline const QList<SongDescription> &QueryResultsModel::results() const
|
|
|
|
{
|
|
|
|
return m_results;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline const QStringList &QueryResultsModel::errorList() const
|
|
|
|
{
|
|
|
|
return m_errorList;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool QueryResultsModel::areResultsAvailable() const
|
|
|
|
{
|
|
|
|
return m_resultsAvailable;
|
|
|
|
}
|
|
|
|
|
2016-03-06 17:52:33 +01:00
|
|
|
inline bool QueryResultsModel::isFetchingCover() const
|
|
|
|
{
|
|
|
|
return m_fetchingCover;
|
|
|
|
}
|
|
|
|
|
2018-03-07 01:18:01 +01:00
|
|
|
class HttpResultsModel : public QueryResultsModel {
|
2016-10-09 19:44:06 +02:00
|
|
|
Q_OBJECT
|
|
|
|
public:
|
2019-04-21 17:08:24 +02:00
|
|
|
~HttpResultsModel() override;
|
|
|
|
void abort() override;
|
2016-10-09 19:44:06 +02:00
|
|
|
|
|
|
|
protected:
|
|
|
|
HttpResultsModel(SongDescription &&initialSongDescription, QNetworkReply *reply);
|
2018-03-07 01:18:01 +01:00
|
|
|
template <class Object, class Function> void addReply(QNetworkReply *reply, Object object, Function handler);
|
|
|
|
template <class Function> void addReply(QNetworkReply *reply, Function handler);
|
2016-10-09 22:41:34 +02:00
|
|
|
virtual void parseInitialResults(const QByteArray &data) = 0;
|
|
|
|
QNetworkReply *evaluateReplyResults(QNetworkReply *reply, QByteArray &data, bool alwaysFollowRedirection = false);
|
2016-10-09 19:44:06 +02:00
|
|
|
|
2017-07-30 20:30:50 +02:00
|
|
|
void handleCoverReplyFinished(QNetworkReply *reply, const QString &albumId, int row);
|
|
|
|
void parseCoverResults(const QString &albumId, int row, const QByteArray &data);
|
|
|
|
|
2020-03-08 14:04:29 +01:00
|
|
|
private Q_SLOTS:
|
2016-10-09 22:41:34 +02:00
|
|
|
void handleInitialReplyFinished();
|
2016-10-09 19:44:06 +02:00
|
|
|
|
|
|
|
protected:
|
|
|
|
QList<QNetworkReply *> m_replies;
|
|
|
|
const SongDescription m_initialDescription;
|
|
|
|
};
|
|
|
|
|
2018-03-07 01:18:01 +01:00
|
|
|
template <class Object, class Function> inline void HttpResultsModel::addReply(QNetworkReply *reply, Object object, Function handler)
|
2016-10-09 22:41:34 +02:00
|
|
|
{
|
|
|
|
(m_replies << reply), connect(reply, &QNetworkReply::finished, object, handler);
|
2019-06-12 20:47:44 +02:00
|
|
|
#ifdef CPP_UTILITIES_DEBUG_BUILD
|
2016-12-19 23:53:12 +01:00
|
|
|
std::cerr << "HTTP query: " << reply->url().toString().toUtf8().data() << std::endl;
|
2016-10-09 22:41:34 +02:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Adds a reply.
|
|
|
|
* \remarks Called within c'tor and handleReplyFinished() in case of redirection. Might be called when subclassing to do further requests.
|
|
|
|
*/
|
2018-03-07 01:18:01 +01:00
|
|
|
template <class Function> inline void HttpResultsModel::addReply(QNetworkReply *reply, Function handler)
|
2016-10-09 22:41:34 +02:00
|
|
|
{
|
|
|
|
(m_replies << reply), connect(reply, &QNetworkReply::finished, handler);
|
2019-06-12 20:47:44 +02:00
|
|
|
#ifdef CPP_UTILITIES_DEBUG_BUILD
|
2016-12-19 23:53:12 +01:00
|
|
|
std::cerr << "HTTP query: " << reply->url().toString().toUtf8().data() << std::endl;
|
2016-10-09 22:41:34 +02:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2016-10-09 19:44:06 +02:00
|
|
|
QueryResultsModel *queryMusicBrainz(SongDescription &&songDescription);
|
|
|
|
QueryResultsModel *queryLyricsWikia(SongDescription &&songDescription);
|
2016-03-06 17:52:33 +01:00
|
|
|
QNetworkReply *queryCoverArtArchive(const QString &albumId);
|
2019-09-02 21:47:11 +02:00
|
|
|
QueryResultsModel *queryMakeItPersonal(SongDescription &&songDescription);
|
2016-03-03 22:21:15 +01:00
|
|
|
|
2018-03-07 01:18:01 +01:00
|
|
|
} // namespace QtGui
|
2016-03-03 22:21:15 +01:00
|
|
|
|
|
|
|
#endif // DBQUERY_H
|