Cache added a lot of unecessarity complexity, in particular. It made no sense to add it to a class which handles network responses.
369 lines
8 KiB
C++
369 lines
8 KiB
C++
/*
|
|
* Copyright 2015 Luca Beltrame <lbeltrame@kde.org>
|
|
*
|
|
* This file is part of Danbooru Client.
|
|
*
|
|
* Danbooru Client 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 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* Danbooru Client 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 Danbooru Client. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "servicebase.h"
|
|
#include "libdanbooru_debug.h"
|
|
#include "utils.h"
|
|
|
|
#include <KIO/Job>
|
|
#include <KIO/Scheduler>
|
|
|
|
using KIO::StoredTransferJob;
|
|
|
|
|
|
namespace Danbooru {
|
|
|
|
DanbooruServiceBase::DanbooruServiceBase(QUrl boardUrl, QObject* parent):
|
|
QObject(parent),
|
|
m_url(boardUrl),
|
|
m_username(QString()),
|
|
m_password(QString()),
|
|
m_maxRating(Danbooru::Safe),
|
|
m_maxPosts(10),
|
|
m_currentPage(1),
|
|
m_minimumWidth(-1),
|
|
m_minimumHeight(-1),
|
|
m_tags(QStringList()),
|
|
m_postsToFetch(0)
|
|
{
|
|
}
|
|
|
|
const QStringList DanbooruServiceBase::allowedRatings() const {
|
|
|
|
QStringList ratings;
|
|
|
|
if (m_maxRating.testFlag(Danbooru::Safe)) {
|
|
ratings.append("Safe");
|
|
}
|
|
|
|
if (m_maxRating.testFlag(Danbooru::Questionable)) {
|
|
ratings.append("Questionable");
|
|
}
|
|
|
|
if (m_maxRating.testFlag(Danbooru::Explicit)) {
|
|
ratings.append("Explicit");
|
|
}
|
|
|
|
return ratings;
|
|
|
|
}
|
|
|
|
Danbooru::ApiType DanbooruServiceBase::apiType() const {
|
|
return Danbooru::ApiType::Unknown;
|
|
}
|
|
|
|
const QSet< QString > DanbooruServiceBase::blacklist() const
|
|
{
|
|
return m_blacklist;
|
|
}
|
|
|
|
int DanbooruServiceBase::currentPage() const
|
|
{
|
|
return m_currentPage;
|
|
}
|
|
|
|
const Danbooru::Ratings DanbooruServiceBase::maximumAllowedRating() const
|
|
{
|
|
return m_maxRating;
|
|
}
|
|
|
|
int DanbooruServiceBase::maxPosts() const
|
|
{
|
|
return m_maxPosts;
|
|
}
|
|
|
|
int DanbooruServiceBase::minimumHeight() const
|
|
{
|
|
return m_minimumHeight;
|
|
}
|
|
|
|
int DanbooruServiceBase::minimumWidth() const
|
|
{
|
|
return m_minimumWidth;
|
|
}
|
|
|
|
void DanbooruServiceBase::nextPostPage()
|
|
{
|
|
m_currentPage++;
|
|
getPostList();
|
|
}
|
|
|
|
void DanbooruServiceBase::nextPoolPage()
|
|
{
|
|
m_currentPage++;
|
|
getPoolList();
|
|
}
|
|
|
|
QStringList DanbooruServiceBase::postTags() const
|
|
{
|
|
return m_tags;
|
|
}
|
|
|
|
void DanbooruServiceBase::reset()
|
|
{
|
|
m_currentPage = 1;
|
|
m_minimumHeight = -1;
|
|
m_minimumWidth = -1;
|
|
m_maxRating = Danbooru::Safe;
|
|
m_tags = QStringList();
|
|
|
|
}
|
|
|
|
//////////
|
|
// Setters
|
|
//////////
|
|
|
|
void DanbooruServiceBase::setBlacklist(const QSet< QString > &blacklist)
|
|
{
|
|
|
|
if (!blacklist.isEmpty()) {
|
|
m_blacklist = blacklist;
|
|
}
|
|
|
|
}
|
|
|
|
void DanbooruServiceBase::setBlacklist(const QStringList &blacklist)
|
|
{
|
|
|
|
if (blacklist.isEmpty()) {
|
|
return;
|
|
}
|
|
|
|
m_blacklist.clear();
|
|
|
|
for (const auto &element : blacklist) {
|
|
m_blacklist.insert(element);
|
|
}
|
|
|
|
}
|
|
|
|
void DanbooruServiceBase::setBoardUrl(const QUrl &url)
|
|
{
|
|
m_url = url;
|
|
}
|
|
|
|
void DanbooruServiceBase::setCurrentPage(int page)
|
|
{
|
|
m_currentPage = page;
|
|
}
|
|
|
|
|
|
|
|
void DanbooruServiceBase::setMaximumAllowedRating(Danbooru::Rating rating)
|
|
{
|
|
Danbooru::Ratings flags;
|
|
|
|
switch (rating) {
|
|
case Danbooru::Safe:
|
|
flags = Danbooru::Safe;
|
|
break;
|
|
case Danbooru::Questionable:
|
|
flags = Danbooru::Safe | Danbooru::Questionable;
|
|
break;
|
|
case Danbooru::Explicit:
|
|
flags = Danbooru::Safe | Danbooru::Questionable | Danbooru::Explicit;
|
|
break;
|
|
}
|
|
|
|
m_maxRating = flags;
|
|
|
|
}
|
|
|
|
void DanbooruServiceBase::setMaxPosts(int number)
|
|
{
|
|
m_maxPosts = number < 100 ? number : 100;
|
|
}
|
|
|
|
void DanbooruServiceBase::setPassword(const QString &password)
|
|
{
|
|
if (password.isEmpty()) {
|
|
return;
|
|
}
|
|
|
|
m_password = password;
|
|
}
|
|
|
|
void DanbooruServiceBase::setPostTags(const QStringList &tags)
|
|
{
|
|
if (!tags.isEmpty()) {
|
|
m_tags = tags;
|
|
}
|
|
}
|
|
|
|
void DanbooruServiceBase::setUserName(const QString &username)
|
|
{
|
|
if (username.isEmpty()) {
|
|
return;
|
|
}
|
|
m_username = username;
|
|
}
|
|
|
|
void DanbooruServiceBase::processPixmap(KJob* job) {
|
|
|
|
if (job->error())
|
|
{
|
|
Q_EMIT(downloadError(job->errorString()));
|
|
return;
|
|
}
|
|
|
|
StoredTransferJob *jobResult = qobject_cast<StoredTransferJob *>(job);
|
|
|
|
if (jobResult == 0) {
|
|
Q_EMIT(downloadError(QString("Internal error")));
|
|
return;
|
|
|
|
}
|
|
|
|
QByteArray data = jobResult->data();
|
|
Danbooru::DanbooruPost* post = job->property("post").value<DanbooruPost*>();
|
|
auto pix = job->property("pixmap").value<QPixmap>();
|
|
|
|
if (!pix.loadFromData(jobResult->data()))
|
|
{
|
|
Q_EMIT(downloadError(QString("Pixmap data could not be loaded")));
|
|
return;
|
|
}
|
|
|
|
post->setPixmap(pix);
|
|
|
|
|
|
m_postsToFetch--; // One less post to do
|
|
|
|
qCDebug(LIBDANBOORU) << "Current posts remaining: " << m_postsToFetch;
|
|
Q_EMIT(postDownloaded(post));
|
|
|
|
if (m_postsToFetch == 0)
|
|
{
|
|
qCDebug(LIBDANBOORU) << "Post download finished";
|
|
Q_EMIT(postDownloadFinished());
|
|
}
|
|
|
|
}
|
|
|
|
void DanbooruServiceBase::processPostList(KJob *job)
|
|
{
|
|
|
|
qCDebug(LIBDANBOORU) << "Got post data OK";
|
|
|
|
if (job->error()) {
|
|
Q_EMIT(downloadError(job->errorString()));
|
|
}
|
|
|
|
StoredTransferJob *jobResult = qobject_cast<StoredTransferJob *>(job);
|
|
|
|
if (jobResult == 0) {
|
|
Q_EMIT(downloadError(QString("Internal error")));
|
|
return;
|
|
|
|
}
|
|
|
|
QByteArray data = jobResult->data();
|
|
|
|
bool ok;
|
|
bool is_pool = job->property("is_pool").toBool();
|
|
|
|
QList<QVariantMap> postList;
|
|
|
|
if (is_pool) {
|
|
// Special cases for pools
|
|
QVariantMap postMap = parseResult(data, apiType(), Danbooru::Pool, &ok).at(0);
|
|
auto postData = postMap.value("raw_post_data").toList();
|
|
for (const auto &post: postData) {
|
|
postList.append(extractPostData(post, apiType()));
|
|
}
|
|
|
|
} else {
|
|
postList = parseResult(data, apiType(), Danbooru::Post, &ok);
|
|
}
|
|
|
|
if (!ok) {
|
|
Q_EMIT(downloadError(QString("Unable to decode data")));
|
|
return;
|
|
}
|
|
|
|
// How many posts do we have to fetch?
|
|
|
|
if (postList.isEmpty()) {
|
|
qCDebug(LIBDANBOORU) << "No posts found";
|
|
Q_EMIT(postDownloadFinished());
|
|
return;
|
|
}
|
|
|
|
m_postsToFetch = postList.length();
|
|
qCDebug(LIBDANBOORU) << "Found " << m_postsToFetch << "posts to fetch" << "with limit" << m_maxPosts;
|
|
|
|
// This is mostly needed for pools
|
|
if (postList.length() > m_maxPosts) {
|
|
m_postsToFetch = m_maxPosts;
|
|
postList = postList.mid(0, m_maxPosts);
|
|
}
|
|
|
|
for (const QVariantMap &element : qAsConst(postList)) {
|
|
|
|
DanbooruPost *post = new DanbooruPost(element);
|
|
|
|
// Remove unwanted posts
|
|
|
|
if (isPostBlacklisted(post, m_blacklist, m_maxRating)) {
|
|
m_postsToFetch--;
|
|
delete post;
|
|
continue;
|
|
}
|
|
|
|
QPixmap pix;
|
|
|
|
qCDebug(LIBDANBOORU) << "About to download images";
|
|
qCDebug(LIBDANBOORU) << "Downloading image" << post->thumbnailUrl();
|
|
StoredTransferJob *pixmapJob = KIO::storedGet(post->thumbnailUrl(),
|
|
KIO::NoReload, KIO::HideProgressInfo);
|
|
|
|
// We don't want to overload the servers, so set some rational
|
|
// priority
|
|
|
|
KIO::Scheduler::setJobPriority(static_cast<KIO::SimpleJob *>(pixmapJob), 1);
|
|
|
|
QVariant variant;
|
|
variant.setValue(post);
|
|
pixmapJob->setProperty("post", variant);
|
|
pixmapJob->setProperty("pix", pix);
|
|
|
|
connect(pixmapJob, &StoredTransferJob::result, this, &DanbooruServiceBase::processPixmap);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void DanbooruServiceBase::setMinimumHeight(int height) {
|
|
|
|
if (height > 0) {
|
|
m_minimumHeight = height;
|
|
}
|
|
|
|
}
|
|
|
|
void DanbooruServiceBase::setMinimumWidth(int width) {
|
|
|
|
if (width > 0) {
|
|
m_minimumWidth = width;
|
|
}
|
|
|
|
}
|
|
|
|
} // namespace Danbooru
|
|
|