Warning, file /plasma/kdeplasma-addons/applets/comic/engine/comicproviderwrapper.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: 2008 Petri Damstén <damu@iki.fi> 0003 * SPDX-FileCopyrightText: 2010 Matthias Fuchs <mat69@gmx.net> 0004 * 0005 * SPDX-License-Identifier: LGPL-2.0-only 0006 */ 0007 0008 #include "comicproviderwrapper.h" 0009 #include "comic_debug.h" 0010 #include "comicproviderkross.h" 0011 0012 #include <KPackage/Package> 0013 #include <KPackage/PackageLoader> 0014 #include <QFile> 0015 #include <QFileInfo> 0016 #include <QJSEngine> 0017 #include <QJSValueIterator> 0018 #include <QJSValueList> 0019 #include <QPainter> 0020 #include <QStandardPaths> 0021 #include <QTextCodec> 0022 #include <QTimer> 0023 #include <QUrl> 0024 0025 QStringList ComicProviderWrapper::mExtensions; 0026 0027 ImageWrapper::ImageWrapper(QObject *parent, const QByteArray &data) 0028 : QObject(parent) 0029 , mImage(QImage::fromData(data)) 0030 , mRawData(data) 0031 { 0032 resetImageReader(); 0033 } 0034 0035 QImage ImageWrapper::image() const 0036 { 0037 return mImage; 0038 } 0039 0040 void ImageWrapper::setImage(const QImage &image) 0041 { 0042 mImage = image; 0043 mRawData.clear(); 0044 0045 resetImageReader(); 0046 } 0047 0048 QByteArray ImageWrapper::rawData() const 0049 { 0050 if (mRawData.isNull()) { 0051 QBuffer buffer(&mRawData); 0052 mImage.save(&buffer); 0053 } 0054 0055 return mRawData; 0056 } 0057 0058 void ImageWrapper::setRawData(const QByteArray &rawData) 0059 { 0060 mRawData = rawData; 0061 mImage = QImage::fromData(mRawData); 0062 0063 resetImageReader(); 0064 } 0065 0066 void ImageWrapper::resetImageReader() 0067 { 0068 if (mBuffer.isOpen()) { 0069 mBuffer.close(); 0070 } 0071 rawData(); // to update the rawData if needed 0072 mBuffer.setBuffer(&mRawData); 0073 mBuffer.open(QIODevice::ReadOnly); 0074 mImageReader.setDevice(&mBuffer); 0075 } 0076 0077 int ImageWrapper::imageCount() const 0078 { 0079 return mImageReader.imageCount(); 0080 } 0081 0082 QImage ImageWrapper::read() 0083 { 0084 return mImageReader.read(); 0085 } 0086 0087 DateWrapper::DateWrapper(const QDate &date) 0088 : mDate(date) 0089 { 0090 } 0091 0092 QDate DateWrapper::date() const 0093 { 0094 return mDate; 0095 } 0096 0097 void DateWrapper::setDate(const QDate &date) 0098 { 0099 mDate = date; 0100 } 0101 0102 QDate DateWrapper::fromVariant(const QVariant &variant) 0103 { 0104 if (variant.type() == QVariant::Date || variant.type() == QVariant::DateTime) { 0105 return variant.toDate(); 0106 } else if (variant.type() == QVariant::String) { 0107 return QDate::fromString(variant.toString(), Qt::ISODate); 0108 } else { 0109 if (variant.canConvert<DateWrapper>()) { 0110 return variant.value<DateWrapper>().date(); 0111 } 0112 } 0113 return QDate(); 0114 } 0115 0116 DateWrapper DateWrapper::addDays(int ndays) 0117 { 0118 return DateWrapper(mDate.addDays(ndays)); 0119 } 0120 0121 DateWrapper DateWrapper::addMonths(int nmonths) 0122 { 0123 return DateWrapper(mDate.addMonths(nmonths)); 0124 } 0125 0126 DateWrapper DateWrapper::addYears(int nyears) 0127 { 0128 return DateWrapper(mDate.addYears(nyears)); 0129 } 0130 0131 int DateWrapper::day() const 0132 { 0133 return mDate.day(); 0134 } 0135 0136 int DateWrapper::dayOfWeek() const 0137 { 0138 return mDate.dayOfWeek(); 0139 } 0140 0141 int DateWrapper::dayOfYear() const 0142 { 0143 return mDate.dayOfYear(); 0144 } 0145 0146 int DateWrapper::daysInMonth() const 0147 { 0148 return mDate.daysInMonth(); 0149 } 0150 0151 int DateWrapper::daysInYear() const 0152 { 0153 return mDate.daysInYear(); 0154 } 0155 0156 int DateWrapper::daysTo(const QVariant d) const 0157 { 0158 return mDate.daysTo(fromVariant(d)); 0159 } 0160 0161 bool DateWrapper::isNull() const 0162 { 0163 return mDate.isNull(); 0164 } 0165 0166 bool DateWrapper::isValid() const 0167 { 0168 return mDate.isValid(); 0169 } 0170 0171 int DateWrapper::month() const 0172 { 0173 return mDate.month(); 0174 } 0175 0176 bool DateWrapper::setDate(int year, int month, int day) 0177 { 0178 return mDate.setDate(year, month, day); 0179 } 0180 0181 int DateWrapper::toJulianDay() const 0182 { 0183 return mDate.toJulianDay(); 0184 } 0185 0186 QString DateWrapper::toString(const QString &format) const 0187 { 0188 return mDate.toString(format); 0189 } 0190 0191 QString DateWrapper::toString(int format) const 0192 { 0193 return mDate.toString((Qt::DateFormat)format); 0194 } 0195 0196 int DateWrapper::weekNumber() const 0197 { 0198 return mDate.weekNumber(); 0199 } 0200 0201 int DateWrapper::year() const 0202 { 0203 return mDate.year(); 0204 } 0205 0206 StaticDateWrapper::StaticDateWrapper(QObject *parent) 0207 : QObject(parent) 0208 { 0209 } 0210 0211 DateWrapper StaticDateWrapper::currentDate() 0212 { 0213 return DateWrapper(QDate::currentDate()); 0214 } 0215 0216 DateWrapper StaticDateWrapper::fromJulianDay(int jd) 0217 { 0218 return DateWrapper(QDate::fromJulianDay(jd)); 0219 } 0220 0221 DateWrapper StaticDateWrapper::fromString(const QString &string, int format) 0222 { 0223 return DateWrapper(QDate::fromString(string, (Qt::DateFormat)format)); 0224 } 0225 0226 DateWrapper StaticDateWrapper::fromString(const QString &string, const QString &format) 0227 { 0228 return DateWrapper(QDate::fromString(string, format)); 0229 } 0230 0231 bool StaticDateWrapper::isLeapYear(int year) 0232 { 0233 return QDate::isLeapYear(year); 0234 } 0235 0236 bool StaticDateWrapper::isValid(int year, int month, int day) 0237 { 0238 return QDate::isValid(year, month, day); 0239 } 0240 0241 QString StaticDateWrapper::longDayName(int weekday) 0242 { 0243 return QLocale::system().dayName(weekday, QLocale::LongFormat); 0244 } 0245 0246 QString StaticDateWrapper::longMonthName(int month) 0247 { 0248 return QLocale::system().monthName(month, QLocale::LongFormat); 0249 } 0250 0251 QString StaticDateWrapper::shortDayName(int weekday) 0252 { 0253 return QLocale::system().dayName(weekday, QLocale::ShortFormat); 0254 } 0255 0256 QString StaticDateWrapper::shortMonthName(int month) 0257 { 0258 return QLocale::system().monthName(month, QLocale::ShortFormat); 0259 } 0260 0261 ComicProviderWrapper::ComicProviderWrapper(ComicProviderKross *parent) 0262 : QObject(parent) 0263 , mProvider(parent) 0264 , mKrossImage(nullptr) 0265 , mPackage(nullptr) 0266 , mRequests(0) 0267 , mIdentifierSpecified(false) 0268 , mIsLeftToRight(true) 0269 , mIsTopToBottom(true) 0270 { 0271 QTimer::singleShot(0, this, &ComicProviderWrapper::init); 0272 } 0273 0274 ComicProviderWrapper::~ComicProviderWrapper() 0275 { 0276 delete mPackage; 0277 } 0278 0279 void ComicProviderWrapper::init() 0280 { 0281 const QString path = QStandardPaths::locate(QStandardPaths::GenericDataLocation, 0282 QLatin1String("plasma/comics/") + mProvider->pluginName() + QLatin1Char('/'), 0283 QStandardPaths::LocateDirectory); 0284 qCDebug(PLASMA_COMIC) << "ComicProviderWrapper::init() package is" << mProvider->pluginName() << " at " << path; 0285 0286 if (!path.isEmpty()) { 0287 mPackage = new KPackage::Package(KPackage::PackageLoader::self()->loadPackageStructure(QStringLiteral("Plasma/Comic"))); 0288 mPackage->setPath(path); 0289 0290 if (mPackage->isValid()) { 0291 // QString mainscript = mPackage->filePath("mainscript") 0292 // doesn't work because the mainscript file can be a different Kross script type ending with main.es or main.kjs etc. 0293 // Maybe this should be added to Plasma::Package or maybe directly change the packagestructure mainscript definition as "main.es" and avoid all 0294 // this. https://techbase.kde.org/Development/Tutorials/Plasma4/ComicPlugin#Package_Structure has main.es defined as mainscript. Also 0295 // Package::isValid() fails because the mainscript search fails to find the "main" file from mainscript. 0296 0297 QString mainscript = mPackage->filePath("scripts") + QLatin1String("/main"); 0298 const QStringList extensions{QStringLiteral(".es"), QStringLiteral(".js")}; 0299 QFileInfo info(mainscript); 0300 for (int i = 0; i < extensions.count() && !info.exists(); ++i) { 0301 info.setFile(mainscript + extensions.value(i)); 0302 qCDebug(PLASMA_COMIC) << "ComicProviderWrapper::init() mainscript found as" << info.filePath(); 0303 } 0304 0305 if (info.exists()) { 0306 m_engine = new QJSEngine(this); 0307 QFile f(info.absoluteFilePath()); 0308 if (f.open(QFile::ReadOnly)) { 0309 m_engine->globalObject().setProperty("Comic", m_engine->newQMetaObject(&ComicProviderWrapper::staticMetaObject)); 0310 auto obj = m_engine->newQObject(this); 0311 0312 // If we set the comic in the global object we can not access the staticMetaObject 0313 // consequently the values have to be written manually 0314 obj.setProperty("Page", ComicProvider::Page); 0315 obj.setProperty("Image", ComicProvider::Image); 0316 obj.setProperty("User", ComicProvider::User); 0317 obj.setProperty("Left", ComicProviderWrapper::Left); 0318 obj.setProperty("Top", ComicProviderWrapper::Top); 0319 obj.setProperty("Right", ComicProviderWrapper::Right); 0320 obj.setProperty("Bottom", ComicProviderWrapper::Bottom); 0321 obj.setProperty("DateIdentifier", (int)IdentifierType::DateIdentifier); 0322 obj.setProperty("NumberIdentifier", (int)IdentifierType::NumberIdentifier); 0323 obj.setProperty("StringIdentifier", (int)IdentifierType::StringIdentifier); 0324 0325 m_engine->globalObject().setProperty("comic", obj); 0326 m_engine->globalObject().setProperty("date", m_engine->newQObject(new StaticDateWrapper(this))); 0327 m_engine->evaluate("var print = comic.print"); 0328 mIdentifierSpecified = !mProvider->isCurrent(); 0329 m_engine->evaluate(f.readAll(), info.absoluteFilePath()); 0330 QJSValueIterator it(m_engine->globalObject()); 0331 while (it.hasNext()) { 0332 it.next(); 0333 if (it.value().isCallable()) { 0334 mFunctions << it.name(); 0335 } 0336 } 0337 setIdentifierToDefault(); 0338 callFunction(QStringLiteral("init")); 0339 } 0340 } 0341 } 0342 } 0343 } 0344 0345 IdentifierType ComicProviderWrapper::identifierType() const 0346 { 0347 IdentifierType result = IdentifierType::StringIdentifier; 0348 const QString type = mProvider->description().value(QLatin1String("X-KDE-PlasmaComicProvider-SuffixType")); 0349 if (type == QLatin1String("Date")) { 0350 result = IdentifierType::DateIdentifier; 0351 } else if (type == QLatin1String("Number")) { 0352 result = IdentifierType::NumberIdentifier; 0353 } else if (type == QLatin1String("String")) { 0354 result = IdentifierType::StringIdentifier; 0355 } 0356 return result; 0357 } 0358 0359 QImage ComicProviderWrapper::comicImage() 0360 { 0361 ImageWrapper *img = qobject_cast<ImageWrapper *>(callFunction(QLatin1String("image")).value<QObject *>()); 0362 if (functionCalled() && img) { 0363 return img->image(); 0364 } 0365 if (mKrossImage) { 0366 return mKrossImage->image(); 0367 } 0368 return QImage(); 0369 } 0370 0371 QJSValue ComicProviderWrapper::identifierToScript(const QVariant &identifier) 0372 { 0373 if (identifierType() == IdentifierType::DateIdentifier && identifier.type() != QVariant::Bool) { 0374 return m_engine->toScriptValue(DateWrapper(identifier.toDate())); 0375 } 0376 return m_engine->toScriptValue(identifier); 0377 } 0378 0379 QVariant ComicProviderWrapper::identifierFromScript(const QJSValue &identifier) const 0380 { 0381 if (identifier.toVariant().canConvert<DateWrapper>()) { 0382 return identifier.toVariant().value<DateWrapper>().date(); 0383 } 0384 return identifier.toVariant(); 0385 } 0386 0387 void ComicProviderWrapper::checkIdentifier(QVariant *identifier) 0388 { 0389 switch (identifierType()) { 0390 case IdentifierType::DateIdentifier: 0391 if (!mLastIdentifier.isNull() && !identifier->isNull() && (!mIdentifierSpecified || identifier->toDate() > mLastIdentifier.toDate())) { 0392 *identifier = mLastIdentifier; 0393 } 0394 if (!mFirstIdentifier.isNull() && !identifier->isNull() && identifier->toDate() < mFirstIdentifier.toDate()) { 0395 *identifier = mFirstIdentifier; 0396 } 0397 break; 0398 case IdentifierType::NumberIdentifier: 0399 if (!mLastIdentifier.isNull() && !identifier->isNull() && (!mIdentifierSpecified || identifier->toInt() > mLastIdentifier.toInt())) { 0400 *identifier = mLastIdentifier; 0401 } 0402 if (!mFirstIdentifier.isNull() && !identifier->isNull() && identifier->toInt() < mFirstIdentifier.toInt()) { 0403 *identifier = mFirstIdentifier; 0404 } 0405 break; 0406 case IdentifierType::StringIdentifier: 0407 if (!mLastIdentifier.isNull() && !mLastIdentifier.toString().isEmpty() && !mIdentifierSpecified) { 0408 *identifier = mLastIdentifier; 0409 } 0410 break; 0411 } 0412 } 0413 0414 void ComicProviderWrapper::setIdentifierToDefault() 0415 { 0416 switch (identifierType()) { 0417 case IdentifierType::DateIdentifier: 0418 mIdentifier = mProvider->requestedDate(); 0419 mLastIdentifier = QDate::currentDate(); 0420 break; 0421 case IdentifierType::NumberIdentifier: 0422 mIdentifier = mProvider->requestedNumber(); 0423 mFirstIdentifier = 1; 0424 break; 0425 case IdentifierType::StringIdentifier: 0426 mIdentifier = mProvider->requestedString(); 0427 break; 0428 } 0429 } 0430 0431 bool ComicProviderWrapper::identifierSpecified() const 0432 { 0433 return mIdentifierSpecified; 0434 } 0435 0436 bool ComicProviderWrapper::isLeftToRight() const 0437 { 0438 return mIsLeftToRight; 0439 } 0440 0441 void ComicProviderWrapper::setLeftToRight(bool ltr) 0442 { 0443 mIsLeftToRight = ltr; 0444 } 0445 0446 bool ComicProviderWrapper::isTopToBottom() const 0447 { 0448 return mIsTopToBottom; 0449 } 0450 0451 void ComicProviderWrapper::setTopToBottom(bool ttb) 0452 { 0453 mIsTopToBottom = ttb; 0454 } 0455 0456 QString ComicProviderWrapper::textCodec() const 0457 { 0458 return QString::fromLatin1(mTextCodec); 0459 } 0460 0461 void ComicProviderWrapper::setTextCodec(const QString &textCodec) 0462 { 0463 mTextCodec = textCodec.toLatin1(); 0464 } 0465 0466 QString ComicProviderWrapper::comicAuthor() const 0467 { 0468 return mProvider->comicAuthor(); 0469 } 0470 0471 void ComicProviderWrapper::setComicAuthor(const QString &author) 0472 { 0473 mProvider->setComicAuthor(author); 0474 } 0475 0476 QString ComicProviderWrapper::websiteUrl() const 0477 { 0478 return mWebsiteUrl; 0479 } 0480 0481 void ComicProviderWrapper::setWebsiteUrl(const QString &websiteUrl) 0482 { 0483 mWebsiteUrl = websiteUrl; 0484 } 0485 0486 QString ComicProviderWrapper::shopUrl() const 0487 { 0488 return mShopUrl; 0489 } 0490 0491 void ComicProviderWrapper::setShopUrl(const QString &shopUrl) 0492 { 0493 mShopUrl = shopUrl; 0494 } 0495 0496 QString ComicProviderWrapper::title() const 0497 { 0498 return mTitle; 0499 } 0500 0501 void ComicProviderWrapper::setTitle(const QString &title) 0502 { 0503 mTitle = title; 0504 } 0505 0506 QString ComicProviderWrapper::additionalText() const 0507 { 0508 return mAdditionalText; 0509 } 0510 0511 void ComicProviderWrapper::setAdditionalText(const QString &additionalText) 0512 { 0513 mAdditionalText = additionalText; 0514 } 0515 0516 QJSValue ComicProviderWrapper::identifier() 0517 { 0518 return identifierToScript(mIdentifier); 0519 } 0520 0521 void ComicProviderWrapper::setIdentifier(const QJSValue &identifier) 0522 { 0523 mIdentifier = identifierFromScript(identifier); 0524 checkIdentifier(&mIdentifier); 0525 } 0526 0527 QJSValue ComicProviderWrapper::nextIdentifier() 0528 { 0529 return identifierToScript(mNextIdentifier); 0530 } 0531 0532 void ComicProviderWrapper::setNextIdentifier(const QJSValue &nextIdentifier) 0533 { 0534 mNextIdentifier = identifierFromScript(nextIdentifier); 0535 if (mNextIdentifier == mIdentifier) { 0536 mNextIdentifier.clear(); 0537 qCWarning(PLASMA_COMIC) << "Next identifier is the same as the current one, clearing next identifier."; 0538 } 0539 } 0540 0541 QJSValue ComicProviderWrapper::previousIdentifier() 0542 { 0543 return identifierToScript(mPreviousIdentifier); 0544 } 0545 0546 void ComicProviderWrapper::setPreviousIdentifier(const QJSValue &previousIdentifier) 0547 { 0548 mPreviousIdentifier = identifierFromScript(previousIdentifier); 0549 if (mPreviousIdentifier == mIdentifier) { 0550 mPreviousIdentifier.clear(); 0551 qCWarning(PLASMA_COMIC) << "Previous identifier is the same as the current one, clearing previous identifier."; 0552 } 0553 } 0554 0555 QJSValue ComicProviderWrapper::firstIdentifier() 0556 { 0557 return identifierToScript(mFirstIdentifier); 0558 } 0559 0560 void ComicProviderWrapper::setFirstIdentifier(const QJSValue &firstIdentifier) 0561 { 0562 switch (identifierType()) { 0563 case IdentifierType::DateIdentifier: 0564 mProvider->setFirstStripDate(DateWrapper::fromVariant(QVariant::fromValue(firstIdentifier.toQObject()))); 0565 break; 0566 case IdentifierType::NumberIdentifier: 0567 mProvider->setFirstStripNumber(firstIdentifier.toInt()); 0568 break; 0569 case IdentifierType::StringIdentifier: 0570 break; 0571 } 0572 mFirstIdentifier = identifierFromScript(firstIdentifier); 0573 checkIdentifier(&mIdentifier); 0574 } 0575 0576 QJSValue ComicProviderWrapper::lastIdentifier() 0577 { 0578 return identifierToScript(mLastIdentifier); 0579 } 0580 0581 void ComicProviderWrapper::setLastIdentifier(const QJSValue &lastIdentifier) 0582 { 0583 mLastIdentifier = identifierFromScript(lastIdentifier); 0584 checkIdentifier(&mIdentifier); 0585 } 0586 0587 QVariant ComicProviderWrapper::identifierVariant() const 0588 { 0589 return mIdentifier; 0590 } 0591 0592 QVariant ComicProviderWrapper::firstIdentifierVariant() const 0593 { 0594 return mFirstIdentifier; 0595 } 0596 0597 QVariant ComicProviderWrapper::lastIdentifierVariant() const 0598 { 0599 return mLastIdentifier; 0600 } 0601 0602 QVariant ComicProviderWrapper::nextIdentifierVariant() const 0603 { 0604 // either handle both previousIdentifier and nextIdentifier or handle none 0605 if (mPreviousIdentifier.isNull() && mNextIdentifier.isNull()) { 0606 switch (identifierType()) { 0607 case IdentifierType::DateIdentifier: 0608 if ((mLastIdentifier.isNull() && mIdentifier.toDate() < QDate::currentDate()) 0609 || (!mLastIdentifier.isNull() && mIdentifier.toDate() < mLastIdentifier.toDate())) { 0610 return mIdentifier.toDate().addDays(1); 0611 } else { 0612 return false; 0613 } 0614 case IdentifierType::NumberIdentifier: 0615 if (mLastIdentifier.isNull() || mIdentifier.toInt() < mLastIdentifier.toInt()) { 0616 return mIdentifier.toInt() + 1; 0617 } else { 0618 return false; 0619 } 0620 case IdentifierType::StringIdentifier: 0621 break; 0622 } 0623 // check if the nextIdentifier is correct 0624 } else if (!mNextIdentifier.isNull()) { 0625 // no nextIdentifier if mIdentifier == mLastIdentifier or if no identifier has been specified 0626 switch (identifierType()) { 0627 case IdentifierType::DateIdentifier: 0628 if ((!mLastIdentifier.isNull() && (mIdentifier.toDate() == mLastIdentifier.toDate())) || !mIdentifierSpecified) { 0629 return false; 0630 } 0631 break; 0632 case IdentifierType::NumberIdentifier: 0633 if ((!mLastIdentifier.isNull() && (mIdentifier.toInt() == mLastIdentifier.toInt())) || !mIdentifierSpecified) { 0634 return false; 0635 } 0636 break; 0637 case IdentifierType::StringIdentifier: 0638 if (!mIdentifierSpecified) { 0639 return false; 0640 } 0641 break; 0642 } 0643 } 0644 return mNextIdentifier; 0645 } 0646 0647 QVariant ComicProviderWrapper::previousIdentifierVariant() const 0648 { 0649 // either handle both previousIdentifier and nextIdentifier or handle none 0650 if (mPreviousIdentifier.isNull() && mNextIdentifier.isNull()) { 0651 switch (identifierType()) { 0652 case IdentifierType::DateIdentifier: 0653 if (mFirstIdentifier.isNull() || mIdentifier.toDate() > mFirstIdentifier.toDate()) { 0654 return mIdentifier.toDate().addDays(-1); 0655 } else { 0656 return false; 0657 } 0658 case IdentifierType::NumberIdentifier: 0659 if ((mFirstIdentifier.isNull() && mIdentifier.toInt() > 1) || (!mFirstIdentifier.isNull() && mIdentifier.toInt() > mFirstIdentifier.toInt())) { 0660 return mIdentifier.toInt() - 1; 0661 } else { 0662 return false; 0663 } 0664 case IdentifierType::StringIdentifier: 0665 break; 0666 } 0667 } else if (!mPreviousIdentifier.isNull()) { 0668 // no previousIdentifier if mIdentifier == mFirstIdentifier 0669 switch (identifierType()) { 0670 case IdentifierType::DateIdentifier: 0671 if (!mFirstIdentifier.isNull() && (mIdentifier.toDate() == mFirstIdentifier.toDate())) { 0672 return false; 0673 } 0674 break; 0675 case IdentifierType::NumberIdentifier: 0676 if (!mFirstIdentifier.isNull() && (mIdentifier.toInt() == mFirstIdentifier.toInt())) { 0677 return false; 0678 } 0679 break; 0680 case IdentifierType::StringIdentifier: 0681 break; 0682 } 0683 } 0684 return mPreviousIdentifier; 0685 } 0686 0687 void ComicProviderWrapper::pageRetrieved(int id, const QByteArray &data) 0688 { 0689 --mRequests; 0690 if (id == ComicProvider::Image) { 0691 mKrossImage = new ImageWrapper(this, data); 0692 callFunction(QLatin1String("pageRetrieved"), {id, m_engine->newQObject(mKrossImage)}); 0693 if (mRequests < 1) { // Don't finish if we still have pageRequests 0694 finished(); 0695 } 0696 } else { 0697 QTextCodec *codec = nullptr; 0698 if (!mTextCodec.isEmpty()) { 0699 codec = QTextCodec::codecForName(mTextCodec); 0700 } 0701 if (!codec) { 0702 codec = QTextCodec::codecForHtml(data); 0703 } 0704 QString html = codec->toUnicode(data); 0705 0706 callFunction(QLatin1String("pageRetrieved"), {id, html}); 0707 } 0708 } 0709 0710 void ComicProviderWrapper::pageError(int id, const QString &message) 0711 { 0712 --mRequests; 0713 callFunction(QLatin1String("pageError"), {id, message}); 0714 if (!functionCalled()) { 0715 Q_EMIT mProvider->error(mProvider); 0716 } 0717 } 0718 0719 void ComicProviderWrapper::redirected(int id, const QUrl &newUrl) 0720 { 0721 --mRequests; 0722 callFunction(QLatin1String("redirected"), {id, newUrl.toString()}); 0723 if (mRequests < 1) { // Don't finish while there are still requests 0724 finished(); 0725 } 0726 } 0727 0728 void ComicProviderWrapper::finished() const 0729 { 0730 qCDebug(PLASMA_COMIC) << QString::fromLatin1("Author").leftJustified(22, QLatin1Char('.')) << comicAuthor(); 0731 qCDebug(PLASMA_COMIC) << QString::fromLatin1("Website URL").leftJustified(22, QLatin1Char('.')) << mWebsiteUrl; 0732 qCDebug(PLASMA_COMIC) << QString::fromLatin1("Shop URL").leftJustified(22, QLatin1Char('.')) << mShopUrl; 0733 qCDebug(PLASMA_COMIC) << QString::fromLatin1("Title").leftJustified(22, QLatin1Char('.')) << mTitle; 0734 qCDebug(PLASMA_COMIC) << QString::fromLatin1("Additional Text").leftJustified(22, QLatin1Char('.')) << mAdditionalText; 0735 qCDebug(PLASMA_COMIC) << QString::fromLatin1("Identifier").leftJustified(22, QLatin1Char('.')) << mIdentifier; 0736 qCDebug(PLASMA_COMIC) << QString::fromLatin1("First Identifier").leftJustified(22, QLatin1Char('.')) << mFirstIdentifier; 0737 qCDebug(PLASMA_COMIC) << QString::fromLatin1("Last Identifier").leftJustified(22, QLatin1Char('.')) << mLastIdentifier; 0738 qCDebug(PLASMA_COMIC) << QString::fromLatin1("Next Identifier").leftJustified(22, QLatin1Char('.')) << mNextIdentifier; 0739 qCDebug(PLASMA_COMIC) << QString::fromLatin1("Previous Identifier").leftJustified(22, QLatin1Char('.')) << mPreviousIdentifier; 0740 Q_EMIT mProvider->finished(mProvider); 0741 } 0742 0743 void ComicProviderWrapper::error() const 0744 { 0745 Q_EMIT mProvider->error(mProvider); 0746 } 0747 0748 void ComicProviderWrapper::requestPage(const QString &url, int id, const QVariantMap &infos) 0749 { 0750 QMap<QString, QString> map; 0751 0752 for (auto it = infos.begin(), end = infos.end(); it != end; ++it) { 0753 map[it.key()] = it.value().toString(); 0754 } 0755 mProvider->requestPage(QUrl(url), id, map); 0756 ++mRequests; 0757 } 0758 0759 void ComicProviderWrapper::requestRedirectedUrl(const QString &url, int id, const QVariantMap &infos) 0760 { 0761 QMap<QString, QString> map; 0762 0763 for (auto it = infos.begin(), end = infos.end(); it != end; ++it) { 0764 map[it.key()] = it.value().toString(); 0765 } 0766 mProvider->requestRedirectedUrl(QUrl(url), id, map); 0767 ++mRequests; 0768 } 0769 0770 bool ComicProviderWrapper::functionCalled() const 0771 { 0772 return mFuncFound; 0773 } 0774 0775 QVariant ComicProviderWrapper::callFunction(const QString &name, const QJSValueList &args) 0776 { 0777 if (m_engine) { 0778 mFuncFound = mFunctions.contains(name); 0779 if (mFuncFound) { 0780 auto val = m_engine->globalObject().property(name).call(args); 0781 if (val.isError()) { 0782 qCWarning(PLASMA_COMIC) << "Error when calling function" << name << "with arguments" << QVariant::fromValue(args) << val.toString(); 0783 return QVariant(); 0784 } else { 0785 return val.toVariant(); 0786 } 0787 } 0788 } 0789 return QVariant(); 0790 } 0791 0792 void ComicProviderWrapper::combine(const QVariant &image, PositionType position) 0793 { 0794 if (!mKrossImage) { 0795 return; 0796 } 0797 0798 QImage header; 0799 if (image.type() == QVariant::String) { 0800 const QString path(mPackage->filePath("images", image.toString())); 0801 if (QFile::exists(path)) { 0802 header = QImage(path); 0803 } else { 0804 return; 0805 } 0806 } else { 0807 ImageWrapper *img = qobject_cast<ImageWrapper *>(image.value<QObject *>()); 0808 if (img) { 0809 header = img->image(); 0810 } else { 0811 return; 0812 } 0813 } 0814 const QImage comic = mKrossImage->image(); 0815 int height = 0; 0816 int width = 0; 0817 0818 switch (position) { 0819 case Top: 0820 case Bottom: 0821 height = header.height() + comic.height(); 0822 width = (header.width() >= comic.width()) ? header.width() : comic.width(); 0823 break; 0824 case Left: 0825 case Right: 0826 height = (header.height() >= comic.height()) ? header.height() : comic.height(); 0827 width = header.width() + comic.width(); 0828 break; 0829 } 0830 0831 QImage img = QImage(QSize(width, height), QImage::Format_RGB32); 0832 img.fill(header.pixel(QPoint(0, 0))); 0833 0834 QPainter painter(&img); 0835 0836 // center and draw the Images 0837 QPoint headerPos; 0838 QPoint comicPos; 0839 0840 switch (position) { 0841 case Top: 0842 headerPos = QPoint(((width - header.width()) / 2), 0); 0843 comicPos = QPoint(((width - comic.width()) / 2), header.height()); 0844 break; 0845 case Bottom: 0846 headerPos = QPoint(((width - header.width()) / 2), comic.height()); 0847 comicPos = QPoint(((width - comic.width()) / 2), 0); 0848 break; 0849 case Left: 0850 headerPos = QPoint(0, ((height - header.height()) / 2)); 0851 comicPos = QPoint(header.width(), ((height - comic.height()) / 2)); 0852 break; 0853 case Right: 0854 headerPos = QPoint(comic.width(), ((height - header.height()) / 2)); 0855 comicPos = QPoint(0, ((height - comic.height()) / 2)); 0856 break; 0857 } 0858 painter.drawImage(headerPos, header); 0859 painter.drawImage(comicPos, comic); 0860 mKrossImage->setImage(img); 0861 } 0862 0863 QObject *ComicProviderWrapper::image() 0864 { 0865 return qobject_cast<QObject *>(mKrossImage); 0866 }