Warning, file /plasma/kdeplasma-addons/applets/comic/engine/comicprovider.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /*
0002  *   SPDX-FileCopyrightText: 2007 Tobias Koenig <tokoe@kde.org>
0003  *   SPDX-FileCopyrightText: 2022 Alexander Lohnau <alexander.lohnau@gmx.de>
0004  *
0005  *   SPDX-License-Identifier: LGPL-2.0-only
0006  */
0007 
0008 #include "comicprovider.h"
0009 #include "comic_debug.h"
0010 
0011 #include <QTimer>
0012 #include <QUrl>
0013 
0014 #include <KIO/Job>
0015 #include <KIO/StoredTransferJob>
0016 
0017 class ComicProvider::Private
0018 {
0019 public:
0020     Private(ComicProvider *parent, const KPluginMetaData &data, IdentifierType suffixType)
0021         : mParent(parent)
0022         , mIsCurrent(false)
0023         , mFirstStripNumber(1)
0024         , mComicDescription(data)
0025         , mSuffixType(suffixType)
0026     {
0027         mTimer = new QTimer(parent);
0028         mTimer->setSingleShot(true);
0029         mTimer->setInterval(60000); // timeout after 1 minute
0030         connect(mTimer, &QTimer::timeout, mParent, [this]() {
0031             // operation took too long, abort it
0032             Q_EMIT mParent->error(mParent);
0033         });
0034     }
0035 
0036     void jobDone(KJob *job)
0037     {
0038         if (job->error()) {
0039             mParent->pageError(job->property("uid").toInt(), job->errorText());
0040         } else {
0041             KIO::StoredTransferJob *storedJob = qobject_cast<KIO::StoredTransferJob *>(job);
0042             mParent->pageRetrieved(job->property("uid").toInt(), storedJob->data());
0043         }
0044     }
0045 
0046     void slotRedirection(KIO::Job *job, const QUrl &oldUrl, const QUrl &newUrl)
0047     {
0048         Q_UNUSED(oldUrl)
0049 
0050         mParent->redirected(job->property("uid").toInt(), newUrl);
0051         mRedirections.remove(job);
0052     }
0053 
0054     void slotRedirectionDone(KJob *job)
0055     {
0056         if (job->error()) {
0057             qCDebug(PLASMA_COMIC) << "Redirection job with id" << job->property("uid").toInt() << "finished with an error.";
0058         }
0059 
0060         if (mRedirections.contains(job)) {
0061             // no redirection took place, return the original url
0062             mParent->redirected(job->property("uid").toInt(), mRedirections[job]);
0063             mRedirections.remove(job);
0064         }
0065     }
0066 
0067     ComicProvider *mParent;
0068     QString mRequestedId;
0069     QString mRequestedComicName;
0070     QString mComicAuthor;
0071     QUrl mImageUrl;
0072     bool mIsCurrent;
0073     bool mIsLeftToRight;
0074     bool mIsTopToBottom;
0075     QDate mRequestedDate;
0076     QDate mFirstStripDate;
0077     int mRequestedNumber;
0078     int mFirstStripNumber;
0079     const KPluginMetaData mComicDescription;
0080     QTimer *mTimer;
0081     QHash<KJob *, QUrl> mRedirections;
0082     const IdentifierType mSuffixType;
0083 };
0084 
0085 ComicProvider::ComicProvider(QObject *parent, const KPluginMetaData &data, IdentifierType type, const QVariant &identifier)
0086     : QObject(parent)
0087     , d(new Private(this, data, type))
0088 {
0089     if (type == IdentifierType::DateIdentifier) {
0090         d->mRequestedDate = identifier.toDate();
0091     } else if (type == IdentifierType::NumberIdentifier) {
0092         d->mRequestedNumber = identifier.toInt();
0093     } else if (type == IdentifierType::StringIdentifier) {
0094         d->mRequestedId = identifier.toString();
0095 
0096         int index = d->mRequestedId.indexOf(QLatin1Char(':'));
0097         d->mRequestedComicName = d->mRequestedId.mid(0, index);
0098     } else {
0099         qFatal("Invalid type passed to comic provider");
0100     }
0101 
0102     d->mTimer->start();
0103     connect(this, &ComicProvider::finished, this, [this]() {
0104         // everything finished, stop the timeout timer
0105         d->mTimer->stop();
0106     });
0107 }
0108 
0109 ComicProvider::~ComicProvider()
0110 {
0111     delete d;
0112 }
0113 
0114 QString ComicProvider::nextIdentifier() const
0115 {
0116     if (identifierType() == IdentifierType::DateIdentifier && d->mRequestedDate != QDate::currentDate()) {
0117         return d->mRequestedDate.addDays(1).toString(Qt::ISODate);
0118     }
0119 
0120     return QString();
0121 }
0122 
0123 QString ComicProvider::previousIdentifier() const
0124 {
0125     if ((identifierType() == IdentifierType::DateIdentifier) && (!firstStripDate().isValid() || d->mRequestedDate > firstStripDate())) {
0126         return d->mRequestedDate.addDays(-1).toString(Qt::ISODate);
0127     }
0128 
0129     return QString();
0130 }
0131 
0132 QString ComicProvider::stripTitle() const
0133 {
0134     return QString();
0135 }
0136 
0137 QString ComicProvider::additionalText() const
0138 {
0139     return QString();
0140 }
0141 
0142 void ComicProvider::setIsCurrent(bool value)
0143 {
0144     d->mIsCurrent = value;
0145 }
0146 
0147 bool ComicProvider::isCurrent() const
0148 {
0149     return d->mIsCurrent;
0150 }
0151 
0152 QDate ComicProvider::requestedDate() const
0153 {
0154     return d->mRequestedDate;
0155 }
0156 
0157 QDate ComicProvider::firstStripDate() const
0158 {
0159     return d->mFirstStripDate;
0160 }
0161 
0162 QString ComicProvider::comicAuthor() const
0163 {
0164     return d->mComicAuthor;
0165 }
0166 
0167 void ComicProvider::setComicAuthor(const QString &author)
0168 {
0169     d->mComicAuthor = author;
0170 }
0171 
0172 void ComicProvider::setFirstStripDate(const QDate &date)
0173 {
0174     d->mFirstStripDate = date;
0175 }
0176 
0177 int ComicProvider::firstStripNumber() const
0178 {
0179     return d->mFirstStripNumber;
0180 }
0181 
0182 void ComicProvider::setFirstStripNumber(int number)
0183 {
0184     d->mFirstStripNumber = number;
0185 }
0186 
0187 QString ComicProvider::firstStripIdentifier() const
0188 {
0189     if ((identifierType() == IdentifierType::DateIdentifier) && d->mFirstStripDate.isValid()) {
0190         return d->mFirstStripDate.toString(Qt::ISODate);
0191     } else if (identifierType() == IdentifierType::NumberIdentifier) {
0192         return QString::number(d->mFirstStripNumber);
0193     }
0194 
0195     return QString();
0196 }
0197 
0198 int ComicProvider::requestedNumber() const
0199 {
0200     return d->mRequestedNumber;
0201 }
0202 
0203 QString ComicProvider::requestedString() const
0204 {
0205     return d->mRequestedId;
0206 }
0207 
0208 QString ComicProvider::requestedComicName() const
0209 {
0210     return d->mRequestedComicName;
0211 }
0212 
0213 void ComicProvider::requestPage(const QUrl &url, int id, const MetaInfos &infos)
0214 {
0215     qCDebug(PLASMA_COMIC) << "Requested page" << url << "with id" << id << "and additional metadata" << infos;
0216     // each request restarts the timer
0217     d->mTimer->start();
0218 
0219     if (id == Image) {
0220         d->mImageUrl = url;
0221     }
0222 
0223     KIO::StoredTransferJob *job;
0224     if (id == Image) {
0225         // use cached information for the image if available
0226         job = KIO::storedGet(url, KIO::NoReload, KIO::HideProgressInfo);
0227     } else {
0228         // for webpages we always reload, making sure, that changes are recognised
0229         job = KIO::storedGet(url, KIO::Reload, KIO::HideProgressInfo);
0230     }
0231     job->setProperty("uid", id);
0232     connect(job, &KJob::result, this, [this](KJob *job) {
0233         d->jobDone(job);
0234     });
0235 
0236     if (!infos.isEmpty()) {
0237         QMapIterator<QString, QString> it(infos);
0238         while (it.hasNext()) {
0239             it.next();
0240             job->addMetaData(it.key(), it.value());
0241         }
0242     }
0243 }
0244 
0245 void ComicProvider::requestRedirectedUrl(const QUrl &url, int id, const MetaInfos &infos)
0246 {
0247     // each request restarts the timer
0248     d->mTimer->start();
0249 
0250     KIO::MimetypeJob *job = KIO::mimetype(url, KIO::HideProgressInfo);
0251     job->setProperty("uid", id);
0252     d->mRedirections[job] = url;
0253     connect(job, &KIO::MimetypeJob::redirection, this, [this](KIO::Job *job, const QUrl &newUrl) {
0254         d->slotRedirection(job, QUrl(), newUrl);
0255     });
0256     connect(job, &KIO::MimetypeJob::permanentRedirection, this, [this](KIO::Job *job, const QUrl &oldUrl, const QUrl &newUrl) {
0257         d->slotRedirection(job, oldUrl, newUrl);
0258     });
0259     connect(job, &KIO::MimetypeJob::result, this, [this](KJob *job) {
0260         d->slotRedirectionDone(job);
0261     });
0262 
0263     if (!infos.isEmpty()) {
0264         QMapIterator<QString, QString> it(infos);
0265         while (it.hasNext()) {
0266             it.next();
0267             job->addMetaData(it.key(), it.value());
0268         }
0269     }
0270 }
0271 
0272 void ComicProvider::pageRetrieved(int, const QByteArray &)
0273 {
0274 }
0275 
0276 void ComicProvider::pageError(int, const QString &)
0277 {
0278 }
0279 
0280 void ComicProvider::redirected(int, const QUrl &)
0281 {
0282 }
0283 
0284 QString ComicProvider::pluginName() const
0285 {
0286     if (!d->mComicDescription.isValid()) {
0287         return QString();
0288     }
0289     return d->mComicDescription.pluginId();
0290 }
0291 
0292 QString ComicProvider::name() const
0293 {
0294     if (!d->mComicDescription.isValid()) {
0295         return QString();
0296     }
0297     return d->mComicDescription.name();
0298 }
0299 
0300 KPluginMetaData ComicProvider::description() const
0301 {
0302     return d->mComicDescription;
0303 }
0304 
0305 QUrl ComicProvider::shopUrl() const
0306 {
0307     return QUrl();
0308 }
0309 
0310 QUrl ComicProvider::imageUrl() const
0311 {
0312     return d->mImageUrl;
0313 }
0314 
0315 bool ComicProvider::isLeftToRight() const
0316 {
0317     return true;
0318 }
0319 
0320 bool ComicProvider::isTopToBottom() const
0321 {
0322     return true;
0323 }
0324 
0325 #include "moc_comicprovider.cpp"