From fc691a9301367bd2a2f90319e0bbb12c02d6816d Mon Sep 17 00:00:00 2001 From: Luca Beltrame Date: Sun, 24 Feb 2013 18:28:37 +0100 Subject: [PATCH] First semi-working implementation in c++ of remote Danbooru calls --- src/libdanbooru/CMakeLists.txt | 20 ++ src/libdanbooru/danboorupool.cpp | 79 +++++++ src/libdanbooru/danboorupool.h | 108 +++++++++ src/libdanbooru/danboorupost.cpp | 132 +++++++++++ src/libdanbooru/danboorupost.h | 188 +++++++++++++++ src/libdanbooru/danbooruservice.cpp | 340 ++++++++++++++++++++++++++++ src/libdanbooru/danbooruservice.h | 265 ++++++++++++++++++++++ src/libdanbooru/utils.cpp | 105 +++++++++ src/libdanbooru/utils.h | 104 +++++++++ 9 files changed, 1341 insertions(+) create mode 100644 src/libdanbooru/CMakeLists.txt create mode 100644 src/libdanbooru/danboorupool.cpp create mode 100644 src/libdanbooru/danboorupool.h create mode 100644 src/libdanbooru/danboorupost.cpp create mode 100644 src/libdanbooru/danboorupost.h create mode 100644 src/libdanbooru/danbooruservice.cpp create mode 100644 src/libdanbooru/danbooruservice.h create mode 100644 src/libdanbooru/utils.cpp create mode 100644 src/libdanbooru/utils.h diff --git a/src/libdanbooru/CMakeLists.txt b/src/libdanbooru/CMakeLists.txt new file mode 100644 index 0000000..55e4f04 --- /dev/null +++ b/src/libdanbooru/CMakeLists.txt @@ -0,0 +1,20 @@ +project(libdanbooru) +include (KDE4Defaults) + +set (libdanbooru_VERSION_MAJOR 0) +set (libdanbooru_VERSION_MINOR 0) +set (libdanbooru_VERSION_PATCH 1) + +set (libdanbooru_SRCS + danboorupool.cpp + danbooruservice.cpp + danboorupost.cpp + utils.cpp) + +include_directories( ${CMAKE_CURRENT_BINARY_DIR}/) + +kde4_add_library(danbooru STATIC ${libdanbooru_SRCS}) + +target_link_libraries(danbooru ${KDE4_KIO_LIBS}) + +install(TARGETS danbooru ${INSTALL_TARGETS_DEFAULT_ARGS}) diff --git a/src/libdanbooru/danboorupool.cpp b/src/libdanbooru/danboorupool.cpp new file mode 100644 index 0000000..3e63adc --- /dev/null +++ b/src/libdanbooru/danboorupool.cpp @@ -0,0 +1,79 @@ +/* + * This file is part of libdanbooru. + * Copyright 2013 Luca Beltrame + * + * 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) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * 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. If not, see . + * + */ + +#include "danboorupool.h" + +namespace Danbooru { + +DanbooruPool::DanbooruPool(const QVariantMap& postData, QObject* parent): + QObject(parent), m_posts(QList()) +{ + m_id = postData.value("id").toInt(); + m_name = postData.value("name").toString(); + m_postCount = postData.value("post_count").toInt(); + m_description = postData.value("description").toString(); +} + +int DanbooruPool::id() const +{ + return m_id; +} + +QString DanbooruPool::name() const +{ + return m_name; +} + +QString DanbooruPool::description() const +{ + return m_description; +} + +int DanbooruPool::postCount() const +{ + return m_postCount; +} + +QList< int > DanbooruPool::posts() const +{ + return m_posts; +} + +void DanbooruPool::addPost(int post) +{ + m_posts.append(post); +} + +void DanbooruPool::addPosts(QList< int > posts) +{ + m_posts.append(posts); +} + +void DanbooruPool::addPosts(QStringList posts) +{ + foreach (QString post, posts) { + m_posts.append(post.toInt()); + } +} + + +} // namespace Danbooru diff --git a/src/libdanbooru/danboorupool.h b/src/libdanbooru/danboorupool.h new file mode 100644 index 0000000..36f0425 --- /dev/null +++ b/src/libdanbooru/danboorupool.h @@ -0,0 +1,108 @@ +/* + * This file is part of libdanbooru. + * Copyright 2013 Luca Beltrame + * + * 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) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * 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. If not, see . + * + */ + +#ifndef DANBOORUPOOL_H +#define DANBOORUPOOL_H + +/** + * @brief This file includes classes which models Danbooru pools. + * @file danboorupool.h + * + **/ + +#include +#include +#include +#include +#include + +namespace Danbooru { + + /** + * @brief Class representing a Danbooru pool. + * + * Pools are organized groups of images, often by a common theme, for + * example taken from the same artbook. They are identified by unique IDs + * and are represented by a name, a description, and the posts they + * contain. + * + * @author Luca Beltrame (lbeltrame@kde.org) + * + * **/ + class DanbooruPool : public QObject + { + + Q_OBJECT + + private: + int m_id; + int m_postCount; + QString m_name; + QString m_description; + QList m_posts; + + public: + + /** + * @brief Construct a Danbooru pool from a QVariantMap. + * + * This form is the easiest to use and should be used when dealing with + * responses in JSON format. Unfortunately most Danbooru + * implementations produce broken JSON for some responses. + * + * @param postData A QVariantMap from parsed JSON representing the + * data from a single pool. + * + * + **/ + DanbooruPool(const QVariantMap& postData, QObject* parent = 0); + + /** + * @brief Construct a Danbooru pool from a QVariantMap. + * + * This form is the easiest to use and should be used when dealing with + * responses in JSON format. Unfortunately most Danbooru + * implementations produce broken JSON for some responses. + * + * @param postData A QXmlStreamAttributes instance holding the + * attributes for the given pool. + * + * + **/ + DanbooruPool(const QXmlStreamAttributes& postData, QObject* parent=0); + + int id() const; + int postCount() const; + QString name() const; + QString description() const; + QList posts() const; + + void addPost(int post); + void addPosts(QList posts); + void addPosts(QStringList posts); + }; + +}; // namespace Danbooru + +Q_DECLARE_METATYPE(Danbooru::DanbooruPool*) + +#endif // DANBOORUPOOL_H diff --git a/src/libdanbooru/danboorupost.cpp b/src/libdanbooru/danboorupost.cpp new file mode 100644 index 0000000..52e2e44 --- /dev/null +++ b/src/libdanbooru/danboorupost.cpp @@ -0,0 +1,132 @@ +/* + * This file is part of libdanbooru. + * Copyright 2013 Luca Beltrame + * + * 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) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * 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. If not, see . + * + */ + +// Qt + +#include +#include + +// KDE + +#include + +// Own + +#include "danboorupost.h" + + +namespace Danbooru { + + DanbooruPost::DanbooruPost(QVariantMap postData, QPixmap* pixmap, + QObject* parent): + QObject(parent), + m_pixmap(pixmap) + { + + m_tags = postData.value("tags").toString().split(' '); + m_id = postData.value("id").toString().toInt(); + m_height = postData.value("height").toString().toInt(); + m_width = postData.value("width").toString().toInt(); + + m_url = KUrl(postData.value("file_url").toUrl() ); + m_thumbnailUrl = KUrl(postData.value("preview_url").toUrl()); + m_size = postData.value("file_size").toInt(); + + } + + DanbooruPost::DanbooruPost(QXmlStreamAttributes& postData, + QPixmap* pixmap, + QObject* parent): + QObject(parent), + m_pixmap(pixmap) + { + Q_UNUSED(postData) + } + + + DanbooruPost::~DanbooruPost() + { + delete m_pixmap; + } + + + bool DanbooruPost::operator==(const Danbooru::DanbooruPost& other) + { + return m_url == other.m_url && m_id == other.m_id; + } + + + void DanbooruPost::setPixmap(QPixmap* pixmap) + { + m_pixmap = pixmap; + } + + const QString DanbooruPost::toString() + { + QString display = QString("Danbooru Post with ID %1 and URL %2, width %3 height %4 "); + display = display.arg(id()).arg(fileUrl().url()).arg(width()).arg(height()); + return display; + } + + int DanbooruPost::id() const + { + return m_id; + } + + int DanbooruPost::height() const + { + return m_height; + } + + int DanbooruPost::width() const + { + return m_width; + } + + QStringList DanbooruPost::tags() const + { + return m_tags; + } + + const KUrl DanbooruPost::thumbnailUrl() const + { + return m_thumbnailUrl; + } + + QPixmap* DanbooruPost::pixmap() const + { + return m_pixmap; + } + + int DanbooruPost::size() const + { + return m_size; + } + + const KUrl DanbooruPost::fileUrl() const + { + return m_url; + } + +} // namespace Danbooru + + diff --git a/src/libdanbooru/danboorupost.h b/src/libdanbooru/danboorupost.h new file mode 100644 index 0000000..c6c1128 --- /dev/null +++ b/src/libdanbooru/danboorupost.h @@ -0,0 +1,188 @@ +/* + * + * Copyright 2013 Luca Beltrame + * + * 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) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * 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. If not, see . + * + */ + +#ifndef DANBOORUPOST_H +#define DANBOORUPOST_H + +/** + * @brief File containing classes to represent Danbooru posts. + * @file danboorupost.h + **/ + +// Qt + +#include +#include +#include +#include + +// KDE + +#include + +class QPixmap; + + +namespace Danbooru { + + /** + * @brief A class representing a Danbooru post. + * + * A Danbooru post is an object that models the posts present in a + * Danbooru board, that is an image with associated information. + * + * In particular, posts contain information on the id, size and dimensions + * of the image, its tags, "preview url" (URL to the thumbnail) and + * file URL. + * + * This is used directly by the DanbooruService class. + * + * @author Luca Beltrame (lbeltrame@kde.org) + * + * @see DanbooruService, DanbooruPool + * + **/ + class DanbooruPost : public QObject + { + + Q_OBJECT + + Q_PROPERTY(QPixmap* pixmap READ pixmap WRITE setPixmap) + Q_PROPERTY(int id READ id) + Q_PROPERTY(KUrl fileUrl READ fileUrl) + Q_PROPERTY(QStringList tags READ tags) + Q_PROPERTY(KUrl thumbnailUrl READ thumbnailUrl) + + private: + + QPixmap* m_pixmap; + + // basic features of a post + + int m_id; + int m_height; + int m_width; + int m_size; + + KUrl m_url; + KUrl m_thumbnailUrl; + QStringList m_tags; + + public: + + /** + * @brief Construct a Danbooru post from a QVariantMap. + * + * This form is the easiest to use and should be used when dealing with + * responses in JSON format. Unfortunately most Danbooru + * implementations produce broken JSON for some responses. + * + * @param postData A QVariantMap from parsed JSON representing the + * data from a single post. + * @param pixmap A QPixmap pointer to the post thumbnail. + * @param parent A pointer to the parent QObject. + * + **/ + explicit DanbooruPost(QVariantMap postData, QPixmap* pixmap = 0, + QObject* parent = 0); + + /** + * @brief Construct a Danbooru post from XML attributes + * + * This is an overloaded function which uses XML attributes rather + * than JSON. It should be used in case the JSON responses aren't + * complete or broken (for example pools' posts in most Danbooru + * instances). + * + * @param postData A QXmlStreamAttributes instance holding the + * attributes for the given post. + * @param pixmap A QPixmap pointer to the post thumbnail. + * @param parent A pointer to the parent QObject. + * + **/ + explicit DanbooruPost(QXmlStreamAttributes& postData, + QPixmap* pixmap = 0, QObject* parent=0); + + bool operator==(const DanbooruPost&); + + ~DanbooruPost(); + + // Post attributes + + /** + * @return The ID of the post. + **/ + int id() const; + + /** + * @return The height in pixels of the post's image. + **/ + int height() const; + + /** + * @return The width in pixels of the post's image. + **/ + int width() const; + + /** + * @return The size in bytes of the post's image. + **/ + int size() const; + + /** + * @return The URL to the post's image. + **/ + const KUrl fileUrl() const; + + /** + * @return The tags associated to the post. + **/ + QStringList tags() const; + + /** + * @return The URL to the post's thumbnail. + **/ + const KUrl thumbnailUrl() const; + + /** + * @return A pointer to the thumbnail's pixmap. + **/ + QPixmap* pixmap() const; + + /** + * Set the post's pixmap to a specific QPixmap instance's pointer. + * + **/ + void setPixmap(QPixmap* pixmap); + + /** + * @return A string representation of the post. + * + * **/ + const QString toString(); + + }; + +}; // namespace Danbooru + +Q_DECLARE_METATYPE(Danbooru::DanbooruPost*) +#endif // DANBOORUPOST_H diff --git a/src/libdanbooru/danbooruservice.cpp b/src/libdanbooru/danbooruservice.cpp new file mode 100644 index 0000000..24132a8 --- /dev/null +++ b/src/libdanbooru/danbooruservice.cpp @@ -0,0 +1,340 @@ +/* + * + * Copyright 2013 Luca Beltrame + * + * 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) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * 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. If not, see . + * + */ + +#include +#include + +#include +#include + +#include "utils.h" + +#include "danbooruservice.h" +#include "danboorupost.h" +#include "danboorupool.h" + + +namespace Danbooru { + + using KIO::StoredTransferJob; + + const QString DanbooruService::POST_URL ="post/index.json" ; + const QString DanbooruService::TAG_URL = "tag/index.json"; + const QString DanbooruService::POOL_URL = "pool/index.json"; + const QString DanbooruService::ARTIST_URL = "artist/index.json"; + const QString DanbooruService::POOL_DATA_URL = "pool/show.xml"; + const QString DanbooruService::RELATED_TAG_URL = "tag/related.json"; + const QMap DanbooruService::RATINGS = initRatings(); + + DanbooruService::DanbooruService(KUrl& boardUrl, QString username, + QString password, + QObject* parent): + QObject(parent), + m_url(boardUrl), + m_username(username), + m_password(password), + m_maxRating("Safe"), + m_currentPosts(0) + { + } + + DanbooruService::~DanbooruService() + { + + } + + const QMap< QString, QStringList > DanbooruService::initRatings() + { + QMap map; + + QStringList safeRatings; + safeRatings.append(QString("Safe")); + + QStringList questionableRatings = QStringList(safeRatings); + questionableRatings.append(QString("Questionable")); + + QStringList explicitRatings = QStringList(questionableRatings); + explicitRatings.append(QString("Explicit")); + + map.insert("Safe", safeRatings); + map.insert("Questionable", questionableRatings); + map.insert("Explicit", explicitRatings); + + return map; + + } + + void DanbooruService::getPostList(int page, QStringList tags, int limit) + { + + // We can't fetch more than 100 items, API limitation + + limit = limit > 100 ? 100: limit; + + QMap map; + + map.insert("limit", QString::number(limit)); + map.insert("page", QString::number(page)); + + KUrl danbooruUrl = requestUrl(m_url, POST_URL, m_username, + m_password, map, tags); + + qDebug() << "Final constructed URL" << danbooruUrl.url(); + + KIO::StoredTransferJob* job = KIO::storedGet(danbooruUrl, KIO::NoReload, + KIO::HideProgressInfo); + + connect(job, SIGNAL(result(KJob*)), this, + SLOT(processPostList(KJob*))); + + } + + void DanbooruService::getTagList(int limit, QString name) + { + + } + + void DanbooruService::getPool(int poolId, int page) + { + + } + + void DanbooruService::getPoolList(int page) + { + + KUrl danbooruUrl; + + if (page == 0) { + danbooruUrl = requestUrl(m_url, POOL_URL, m_username, m_password); + } else { + QMap map; + map.insert("page", QString::number(page)); + + danbooruUrl = requestUrl(m_url, POOL_URL, m_username, + m_password, map); + } + + qDebug() << "Final constructed URL" << danbooruUrl.url(); + + KIO::StoredTransferJob* job = KIO::storedGet(danbooruUrl, KIO::NoReload, + KIO::HideProgressInfo); + + connect(job, SIGNAL(result(KJob*)), this, + SLOT(processPoolList(KJob*))); + + } + + void DanbooruService::getRelatedTags(QStringList tags, + Danbooru::TagType tagType) + { + + } + + // Getters / setters + + QStringList DanbooruService::blacklist() const + { + return m_blacklist; + } + + const QStringList DanbooruService::allowedRatings() const + { + return RATINGS.value(m_maxRating); + } + + void DanbooruService::setMaximumAllowedRating(QString rating) + { + if (RATINGS.contains(rating)) { + m_maxRating = rating; + } + } + + const QString DanbooruService::maximumAllowedRating() const + { + return m_maxRating; + } + + // Slots + + void DanbooruService::processPostList(KJob* job) + { + + qDebug() << "Got post data OK"; + + if (job->error()) { + Q_EMIT(downloadError(job->errorString())); + } + + StoredTransferJob* jobResult = qobject_cast(job); + + if (jobResult == 0) { + Q_EMIT(downloadError(QString("Internal error"))); + return; + + } + + QByteArray data = jobResult->data(); + + QJson::Parser parser; + + bool ok; + + QVariant result = parser.parse(data, &ok); + + if (!ok) { + Q_EMIT(downloadError(QString("Unable to decode data"))); + return; + } + + QList postList = result.toList(); + + // How many posts do we have to fetch? + + m_currentPosts = postList.length(); + + Q_FOREACH(QVariant element, postList) { + + QVariantMap map = element.toMap(); + + DanbooruPost* post = new DanbooruPost(map); + + 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(job), + 1); + + QVariant variant; + + variant.setValue(post); + + pixmapJob->setProperty("danbooruPost", variant); + connect(pixmapJob, SIGNAL(result(KJob*)), this, + SLOT(downloadThumbnail(KJob*))); + + } + + } + + void DanbooruService::processRelatedTagList(KJob* job) + { + Q_UNUSED(job) + } + + void DanbooruService::processPoolList(KJob* job) + { + + qDebug() << "Got pool data OK"; + + if (job->error()) { + Q_EMIT(downloadError(job->errorString())); + } + + StoredTransferJob* jobResult = qobject_cast(job); + + if (jobResult == 0) { + Q_EMIT(downloadError(QString("Internal error"))); + return; + + } + + QByteArray data = jobResult->data(); + + QJson::Parser parser; + + bool ok; + + QVariant result = parser.parse(data, &ok); + + if (!ok) { + Q_EMIT(downloadError(QString("Unable to decode data"))); + return; + } + + QList poolList = result.toList(); + + int currentPools = poolList.length(); + + Q_FOREACH(QVariant element, poolList) { + QVariantMap map = element.toMap(); + + DanbooruPool* pool = new DanbooruPool(map); + Q_EMIT(poolDownloaded(pool)); + } + + qDebug() << "Pool download finished!"; + Q_EMIT(poolDownloadFinished()); + + } + + void DanbooruService::downloadAllTags(KJob* job) + { + Q_UNUSED(job) + } + + void DanbooruService::downloadThumbnail(KJob* job) + { + + if (job->error()) { + Q_EMIT(downloadError(job->errorString())); + } + + QVariant postData = job->property("danbooruPost"); + + DanbooruPost* post = postData.value(); + QPixmap* pix = new QPixmap(); + + StoredTransferJob* jobResult = qobject_cast(job); + + if (jobResult == 0) { + Q_EMIT(downloadError(QString("Internal error"))); + return; + + } + + bool ok = pix->loadFromData(jobResult->data()); + + if (!ok) { + Q_EMIT(downloadError(QString("Pixmap data could not be loaded"))); + return; + } + + post->setPixmap(pix); + + m_currentPosts--; // One less post to do + + qDebug() << "Current posts remaining" << m_currentPosts; + Q_EMIT(postDownloaded(post)); + + if (m_currentPosts == 0) { + qDebug() << "Post download finished"; + Q_EMIT(postDownloadFinished()); + } + + } + + +} // namespace Danbooru + diff --git a/src/libdanbooru/danbooruservice.h b/src/libdanbooru/danbooruservice.h new file mode 100644 index 0000000..e0d4306 --- /dev/null +++ b/src/libdanbooru/danbooruservice.h @@ -0,0 +1,265 @@ +/* + * This file is part of libdanbooru. + * Copyright 2013 Luca Beltrame + * + * 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) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * 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. If not, see . + * + * + */ + +#ifndef DANBOORUSERVICE_H +#define DANBOORUSERVICE_H + + +/** + * @brief Classes to interact with Danbooru boards + * @file danbooruservice.h + * +**/ + +#include +#include +#include + +#include +#include + +class QPixmap; +class KUrl; +class KJob; + +/** + * @brief The Danbooru namespace. + * + **/ +namespace Danbooru { + + /** + * @brief Types of tags + * + * A Danbooru tag is not simply a string, but carries some (limited) + * semantic information. In particular, tags are organized in what they + * refer to, either something related to the image itself, or to the + * artist that drew it, or the copyrights associated to the image, or even + * the characters that are represented in it. + * + **/ + enum TagType { + General, /**< Generic tags **/ + Artist, /**< Tags related to artists **/ + Copyright, /** RATINGS; + + // member variables + + KUrl m_url; + QString m_username; + QString m_password; + QStringList m_blacklist; + QString m_maxRating; + + unsigned int m_currentPosts; // To tell when to quit + + // private functions + + /** + * @internal + * + **/ + static const QMap< QString, QStringList > initRatings(); + + + public: + + /** + * @brief Construct a default instance of the service. + * + * @param boardUrl The URL to connect to. + * @param username Username to use (optional) + * @param password Password to use (optional) + * @param parent The parent QObject + * + **/ + DanbooruService(KUrl& boardUrl, QString username = QString(), + QString password = QString(), QObject* parent = 0); + + /** + * Default destructor. + **/ + ~DanbooruService(); + + /** + *@brief Get posts from a the board. + * + * @param page The page containing posts (default: 1) + * @param tags The specific tags to query for (default: all tags) + * @param limit The number of posts to fetch (maximum 100) + * + **/ + void getPostList(int page=1, QStringList tags=QStringList(), + int limit=100); + + /** + * @brief Get a list of pools from the board. + * + * @param page The page to get pools from (default: 1) + * + **/ + void getPoolList(int page = 1); + + /** + * @brief Get the posts associated with a specific pool ID. + * + * @param poolId The ID of the pool to fetch posts from. + * @param page The page of the pool posts (if > 100) + * + **/ + void getPool(int poolId, int page=1); + + /** + * @brief Get a list of tags from the board + * + * The tagDownloaded signal is emitted every time a tag has been + * retrieved. + * + * @param limit The number of tags to get. + * + **/ + void getTagList(int limit=10, QString name=""); + + /** + * @brief Get tags related to a specific, user supplied list. + * + * @param tags The tags to query for related terms + * @param tagType The type of tag to query for + **/ + void getRelatedTags(QStringList tags=QStringList(), + TagType tagType=General); + + /** + * @return The currently allowed ratings when downloading posts. + **/ + const QStringList allowedRatings() const; + + /** + * @return The maximum allowed rating for a post. + **/ + const QString maximumAllowedRating() const; + + /** + * @return The currently blacklisted tags. + **/ + QStringList blacklist() const; + + /** + * @brief Set the maximum allowed rating for the board. + * + * Posts whose rating is higher than the maximuk allowed will not be + * downloaded. + * + **/ + void setMaximumAllowedRating(QString rating); + + /** + * @brief Set the tag blacklist. + * + * If a tag is in the blacklist, posts tagged with it will not be downloaded. + * + **/ + void setBlackList(QStringList blacklist); + + private Q_SLOTS: + void processPostList(KJob* job); + void processPoolList(KJob* job); + void processRelatedTagList(KJob* job); + void downloadThumbnail(KJob* job); + void downloadAllTags(KJob* job); + + Q_SIGNALS: + + /** + * Emitted when there are no more posts to download. + * + * Connect to this signal to know when downloading is complete. + * + **/ + void postDownloadFinished(); + + /** + * Emitted when there are no more pools to download. + **/ + void poolDownloadFinished(); + + + /** + * Emitted when a download error occurred. + * + * The parameter contains the error string. + * + **/ + void downloadError(QString error); + + /** + * Emitted when a post has been downloaded. + * + * The parameter contains a pointer to the post that has been + * downloaded. + **/ + void postDownloaded(Danbooru::DanbooruPost* post); + + void poolDownloaded(Danbooru::DanbooruPool* pool); + // TODO: Tags and similar + + }; +}; +#endif // DANBOORUSERVICE_H diff --git a/src/libdanbooru/utils.cpp b/src/libdanbooru/utils.cpp new file mode 100644 index 0000000..ebbc99e --- /dev/null +++ b/src/libdanbooru/utils.cpp @@ -0,0 +1,105 @@ +/* + * + * Copyright 2013 Luca Beltrame + * + * 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) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * 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. If not, see . + * + */ + +#include "utils.h" + +namespace Danbooru { + + KUrl requestUrl(KUrl& url, const QString& path, + const QString& username, const QString& password, + const dictMap& parameters, const QStringList& tags) + { + + KUrl danbooruUrl = KUrl(url); + danbooruUrl.addPath(path); + + // If we have parameters, add them + + if (!parameters.isEmpty()) { + + QMap::const_iterator iter; + + for (iter = parameters.constBegin(); iter!= parameters.constEnd(); + ++iter) { + danbooruUrl.addQueryItem(iter.key(), iter.value()); + } + + } + // Now, let's add tags should we have them + + if (!tags.isEmpty()) { + QByteArray encoded_tags = QUrl::toPercentEncoding(tags.join(" ")); + danbooruUrl.addEncodedQueryItem("tags", encoded_tags); + } + + if (!username.isEmpty() && !password.isEmpty()) { + danbooruUrl.setUserName(username); + danbooruUrl.setPassword(password); + } + + return danbooruUrl; + } + + KUrl requestUrl(KUrl& url, const QString& path, const QString& username, + const QString& password, const dictMap& parameters) + { + + KUrl danbooruUrl = KUrl(url); + danbooruUrl.addPath(path); + + // If we have parameters, add them + + if (!parameters.isEmpty()) { + + QMap::const_iterator iter; + + for (iter = parameters.constBegin(); iter!= parameters.constEnd(); + ++iter) { + danbooruUrl.addQueryItem(iter.key(), iter.value()); + } + + } + + if (!username.isEmpty() && !password.isEmpty()) { + danbooruUrl.setUserName(username); + danbooruUrl.setPassword(password); + } + + return danbooruUrl; + } + + KUrl requestUrl(KUrl& url, const QString& path, const QString& username, + const QString& password) + { + KUrl danbooruUrl = KUrl(url); + danbooruUrl.addPath(path); + + if (!username.isEmpty() && !password.isEmpty()) { + danbooruUrl.setUserName(username); + danbooruUrl.setPassword(password); + } + + return danbooruUrl; + } + + +} // namespace Danbooru diff --git a/src/libdanbooru/utils.h b/src/libdanbooru/utils.h new file mode 100644 index 0000000..185e984 --- /dev/null +++ b/src/libdanbooru/utils.h @@ -0,0 +1,104 @@ +/* + * This file is part of libdanbooru. + * Copyright 2013 Luca Beltrame + * + * 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) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * 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. If not, see . + * + */ + +#ifndef UTILS_H +#define UTILS_H + +#include + +#include + +/** + * @brief Commmon utilities for Danbooru classes. + * @file utils.h + * + **/ + +namespace Danbooru { + + typedef QMap dictMap; + + /** @brief Generate a request URL for a Danbooru board. + * + * Given an URL and an API path, this function builds a + * proper URL which is used for the specific API operation. + * The processing follows the "normal" way of encoding URLs. + * + * @param url The board URL. + * @param path The API path of the call to use + * @param username The username to supply (optional) + * @param password The password to use (optional) + * @param parameters A map of key,values representing the parameters + * to use. + * @param tags The tags to supply (optional). + * + * @return A constructed URL to be used for a Danbooru API call. + * @author Luca Beltrame (lbeltrame@kde.org) + * + * + **/ + KUrl requestUrl(KUrl& url, const QString& path, const QString& username, + const QString& password, const dictMap& parameters, + const QStringList& tags); + + + /** @brief Generate a request URL for a Danbooru board. + * + * This is an overloaded function provided for convenience. + * + * + * @param url The board URL. + * @param path The API path of the call to use + * @param username The username to supply (optional) + * @param password The password to use (optional) + * @param parameters A map of key,values representing the parameters + * to use. + * + * @return A constructed URL to be used for a Danbooru API call. + * @author Luca Beltrame (lbeltrame@kde.org) + * + * + **/ + KUrl requestUrl(KUrl& url, const QString& path, const QString& username, + const QString& password, const dictMap& parameters); + + + /** @brief Generate a request URL for a Danbooru board. + * + * This is an overloaded function provided for convenience. + * + * @param url The board URL. + * @param path The API path of the call to use + * @param username The username to supply (optional) + * @param password The password to use (optional) + * + * @return A constructed URL to be used for a Danbooru API call. + * @author Luca Beltrame (lbeltrame@kde.org) + * + * + **/ + KUrl requestUrl(KUrl& url, const QString& path, const QString& username, + const QString& password); + + +} +#endif // UTILS_H