File indexing completed on 2024-05-05 17:33:57

0001 /*
0002  *   SPDX-FileCopyrightText: 2007 Tobias Koenig <tokoe@kde.org>
0003  *   SPDX-FileCopyrightText: 2008 Marco Martin <notmart@gmail.com>
0004  *   SPDX-FileCopyrightText: 2008-2011 Matthias Fuchs <mat69@gmx.net>
0005  *   SPDX-FileCopyrightText: 2012 Reza Fatahilah Shah <rshah0385@kireihana.com>
0006  *   SPDX-FileCopyrightText: 2015 Marco Martin <mart@kde.org>
0007  *   SPDX-FileCopyrightText: 2022 Alexander Lohnau <alexander.lohnau@gmx.de>
0008  *
0009  *   SPDX-License-Identifier: GPL-2.0-or-later
0010  */
0011 
0012 #include "comic.h"
0013 #include "checknewstrips.h"
0014 #include "comic_debug.h"
0015 #include "comicsaver.h"
0016 #include "stripselector.h"
0017 
0018 #include <QAction>
0019 #include <QDebug>
0020 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
0021 #include <QNetworkInformation>
0022 #endif
0023 #include <QScreen>
0024 #include <QSortFilterProxyModel>
0025 #include <QTimer>
0026 #include <QWindow>
0027 
0028 #include <KActionCollection>
0029 #include <KApplicationTrader>
0030 #include <KConfigDialog>
0031 #include <KIO/OpenUrlJob>
0032 #include <KLocalizedString>
0033 #include <KNotification>
0034 #include <KService>
0035 #include <KStandardShortcut>
0036 #include <kuiserverjobtracker.h>
0037 
0038 #include <Plasma/Containment>
0039 
0040 #include "comicmodel.h"
0041 #include "comicupdater.h"
0042 
0043 Q_GLOBAL_STATIC(ComicUpdater, globalComicUpdater)
0044 
0045 ComicApplet::ComicApplet(QObject *parent, const KPluginMetaData &data, const QVariantList &args)
0046     : Plasma::Applet(parent, data, args)
0047     , mProxy(nullptr)
0048     , mActiveComicModel(new ActiveComicModel(parent))
0049     , mDifferentComic(true)
0050     , mShowComicUrl(false)
0051     , mShowComicAuthor(false)
0052     , mShowComicTitle(false)
0053     , mShowComicIdentifier(false)
0054     , mShowErrorPicture(true)
0055     , mArrowsOnHover(true)
0056     , mMiddleClick(true)
0057     , mCheckNewComicStripsInterval(0)
0058     , mMaxComicLimit(0)
0059     , mCheckNewStrips(nullptr)
0060     , mActionShop(nullptr)
0061     , mEngine(new ComicEngine(this))
0062     , mSavingDir(nullptr)
0063 {
0064     setHasConfigurationInterface(true);
0065     connect(mEngine, &ComicEngine::requestFinished, this, &ComicApplet::dataUpdated);
0066 }
0067 
0068 void ComicApplet::init()
0069 {
0070     globalComicUpdater->init(globalConfig());
0071     mSavingDir = new SavingDir(config());
0072 
0073     configChanged();
0074 
0075     mModel = new ComicModel(mEngine, mTabIdentifier, this);
0076     mProxy = new QSortFilterProxyModel(this);
0077     mProxy->setSourceModel(mModel);
0078     mProxy->setSortCaseSensitivity(Qt::CaseInsensitive);
0079     mProxy->sort(1, Qt::AscendingOrder);
0080 
0081     mCurrentDay = QDate::currentDate();
0082     mDateChangedTimer = new QTimer(this);
0083     connect(mDateChangedTimer, &QTimer::timeout, this, &ComicApplet::checkDayChanged);
0084     mDateChangedTimer->setInterval(5 * 60 * 1000); // every 5 minutes
0085     mDateChangedTimer->start();
0086 
0087     mActionNextNewStripTab = new QAction(QIcon::fromTheme(QStringLiteral("go-next-view")), i18nc("@action comic strip", "&Next Tab with a New Strip"), this);
0088     mActionNextNewStripTab->setShortcuts(KStandardShortcut::openNew());
0089     actions()->addAction(QStringLiteral("next new strip"), mActionNextNewStripTab);
0090     mActions.append(mActionNextNewStripTab);
0091     connect(mActionNextNewStripTab, &QAction::triggered, this, &ComicApplet::showNextNewStrip);
0092 
0093     mActionGoFirst = new QAction(QIcon::fromTheme(QStringLiteral("go-first")), i18nc("@action", "Jump to &First Strip"), this);
0094     mActions.append(mActionGoFirst);
0095     connect(mActionGoFirst, &QAction::triggered, this, &ComicApplet::slotFirstDay);
0096 
0097     mActionGoLast = new QAction(QIcon::fromTheme(QStringLiteral("go-last")), i18nc("@action", "Jump to &Current Strip"), this);
0098     mActions.append(mActionGoLast);
0099     connect(mActionGoLast, &QAction::triggered, this, &ComicApplet::slotCurrentDay);
0100 
0101     mActionGoJump = new QAction(QIcon::fromTheme(QStringLiteral("go-jump")), i18nc("@action", "Jump to Strip…"), this);
0102     mActions.append(mActionGoJump);
0103     connect(mActionGoJump, &QAction::triggered, this, &ComicApplet::slotGoJump);
0104 
0105     mActionWebsite = new QAction(i18nc("@action", "Visit the Website"), this);
0106     KService::Ptr browser = KApplicationTrader::preferredService(QStringLiteral("x-scheme-handler/https"));
0107 
0108     if (browser) {
0109         mActionWebsite->setText(i18nc("@action:inmenu %1 is the name of a web browser", "View in %1", browser->name()));
0110         mActionWebsite->setIcon(QIcon::fromTheme(browser->icon()));
0111     }
0112 
0113     mActionWebsite->setEnabled(false);
0114     mActions.append(mActionWebsite);
0115     connect(mActionWebsite, &QAction::triggered, this, &ComicApplet::slotWebsite);
0116 
0117     mActionShop = new QAction(i18nc("@action", "Visit the Shop &Website"), this);
0118     mActionShop->setEnabled(false);
0119     mActions.append(mActionShop);
0120     connect(mActionShop, &QAction::triggered, this, &ComicApplet::slotShop);
0121 
0122     mActionSaveComicAs = new QAction(QIcon::fromTheme(QStringLiteral("document-save-as")), i18nc("@action", "&Save Comic As…"), this);
0123     mActions.append(mActionSaveComicAs);
0124     connect(mActionSaveComicAs, &QAction::triggered, this, &ComicApplet::slotSaveComicAs);
0125 
0126     mActionScaleContent = new QAction(QIcon::fromTheme(QStringLiteral("zoom-original")), //
0127                                       i18nc("@option:check Context menu of comic image", "&Actual Size"),
0128                                       this);
0129     mActionScaleContent->setCheckable(true);
0130     mActionScaleContent->setChecked(mCurrent.scaleComic());
0131     mActions.append(mActionScaleContent);
0132     connect(mActionScaleContent, &QAction::triggered, this, &ComicApplet::slotScaleToContent);
0133 
0134     mActionStorePosition =
0135         new QAction(QIcon::fromTheme(QStringLiteral("go-home")), i18nc("@option:check Context menu of comic image", "Store Current &Position"), this);
0136     mActionStorePosition->setCheckable(true);
0137     mActionStorePosition->setChecked(mCurrent.hasStored());
0138     mActions.append(mActionStorePosition);
0139     connect(mActionStorePosition, &QAction::triggered, this, &ComicApplet::slotStorePosition);
0140 
0141     // make sure that tabs etc. are displayed even if the comic strip in the first tab does not work
0142     updateView();
0143 
0144     updateUsedComics();
0145     changeComic(true);
0146 
0147 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0148     QT_WARNING_PUSH
0149     QT_WARNING_DISABLE_DEPRECATED
0150     connect(&m_networkConfigurationManager, &QNetworkConfigurationManager::onlineStateChanged, this, [this](bool isOnline) {
0151         if (!isOnline) {
0152             return;
0153         }
0154         qCDebug(PLASMA_COMIC) << "Online status changed to true, requesting comic" << mPreviousFailedIdentifier;
0155         mEngine->requestSource(mPreviousFailedIdentifier);
0156     });
0157     QT_WARNING_POP
0158 #else
0159     QNetworkInformation::instance()->load(QNetworkInformation::Feature::Reachability);
0160     connect(QNetworkInformation::instance(), &QNetworkInformation::reachabilityChanged, this, [this](auto reachability) {
0161         if (reachability != QNetworkInformation::Reachability::Online) {
0162             return;
0163         }
0164         qCDebug(PLASMA_COMIC) << "Online status changed to true, requesting comic" << mPreviousFailedIdentifier;
0165         mEngine->requestSource(mPreviousFailedIdentifier);
0166     });
0167 #endif
0168 }
0169 
0170 ComicApplet::~ComicApplet()
0171 {
0172     delete mSavingDir;
0173 }
0174 
0175 void ComicApplet::dataUpdated(const ComicMetaData &data)
0176 {
0177     const QString source = data.identifier;
0178     setBusy(false);
0179 
0180     // disconnect prefetched comic strips
0181     if (source != mOldSource) {
0182         return;
0183     }
0184 
0185     setConfigurationRequired(mCurrent.id().isEmpty());
0186 
0187     // there was an error, display information as image
0188     if (data.error) {
0189         mPreviousFailedIdentifier = source;
0190         if (!mShowErrorPicture && !data.previousIdentifier.isEmpty()) {
0191             updateComic(data.previousIdentifier);
0192         }
0193         return;
0194     }
0195 
0196     mCurrent.setData(data);
0197 
0198     // looking at the last index, thus not mark it as new
0199     KConfigGroup cg = config();
0200     if (!mCurrent.hasNext() && mCheckNewComicStripsInterval) {
0201         setTabHighlighted(mCurrent.id(), false);
0202         mActionNextNewStripTab->setEnabled(isTabHighlighted(mCurrent.id()));
0203     }
0204 
0205     // call the slot to check if the position needs to be saved
0206     slotStorePosition();
0207 
0208     // prefetch the previous and following comic for faster navigation
0209     if (mCurrent.hasNext()) {
0210         const QString prefetch = mCurrent.id() + QLatin1Char(':') + mCurrent.next();
0211         mEngine->requestSource(prefetch);
0212     }
0213     if (mCurrent.hasPrev()) {
0214         const QString prefetch = mCurrent.id() + QLatin1Char(':') + mCurrent.prev();
0215         mEngine->requestSource(prefetch);
0216     }
0217 
0218     updateView();
0219 
0220     refreshComicData();
0221 }
0222 
0223 void ComicApplet::updateView()
0224 {
0225     updateContextMenu();
0226 }
0227 
0228 void ComicApplet::positionFullView(QWindow *window)
0229 {
0230     if (!window || !window->screen()) {
0231         return;
0232     }
0233 
0234     window->setPosition(window->screen()->availableGeometry().center() - QPoint(window->size().width() / 2, window->size().height() / 2));
0235 }
0236 
0237 void ComicApplet::changeComic(bool differentComic)
0238 {
0239     if (differentComic) {
0240         KConfigGroup cg = config();
0241         mActionStorePosition->setChecked(mCurrent.storePosition());
0242 
0243         // assign mScaleComic the moment the new strip has been loaded (dataUpdated) as up to this point
0244         // the old one should be still shown with its scaling settings
0245         mActionScaleContent->setChecked(mCurrent.scaleComic());
0246 
0247         updateComic(mCurrent.stored());
0248     } else {
0249         updateComic(mCurrent.current());
0250     }
0251 }
0252 
0253 void ComicApplet::updateUsedComics()
0254 {
0255     const QString oldIdentifier = mCurrent.id();
0256 
0257     mActiveComicModel->clear();
0258     mCurrent = ComicData();
0259 
0260     bool isFirst = true;
0261     QModelIndex data;
0262     KConfigGroup cg = config();
0263     int tab = 0;
0264     for (int i = 0; i < mProxy->rowCount(); ++i) {
0265         if (mTabIdentifier.contains(mProxy->index(i, 0).data(Qt::UserRole).toString())) {
0266             data = mProxy->index(i, 1);
0267 
0268             if (isFirst) {
0269                 isFirst = false;
0270                 const QString id = data.data(Qt::UserRole).toString();
0271                 mDifferentComic = (oldIdentifier != id);
0272                 const QString title = data.data().toString();
0273                 mCurrent.init(id, config());
0274                 mCurrent.setTitle(title);
0275             }
0276 
0277             const QString name = data.data().toString();
0278             const QString identifier = data.data(Qt::UserRole).toString();
0279             const QIcon icon = data.data(Qt::DecorationRole).value<QIcon>();
0280             // found a newer strip last time, which was not visited
0281 
0282             if (mCheckNewComicStripsInterval && !cg.readEntry(QLatin1String("lastStripVisited_") + identifier, true)) {
0283                 mActiveComicModel->addComic(identifier, name, icon, true);
0284             } else {
0285                 mActiveComicModel->addComic(identifier, name, icon);
0286             }
0287 
0288             ++tab;
0289         }
0290     }
0291 
0292     mActionNextNewStripTab->setVisible(mCheckNewComicStripsInterval);
0293     mActionNextNewStripTab->setEnabled(isTabHighlighted(mCurrent.id()));
0294 
0295     delete mCheckNewStrips;
0296     mCheckNewStrips = nullptr;
0297     if (mCheckNewComicStripsInterval) {
0298         mCheckNewStrips = new CheckNewStrips(mTabIdentifier, mEngine, mCheckNewComicStripsInterval, this);
0299         connect(mCheckNewStrips, &CheckNewStrips::lastStrip, this, &ComicApplet::slotFoundLastStrip);
0300     }
0301 
0302     Q_EMIT comicModelChanged();
0303 }
0304 
0305 void ComicApplet::slotTabChanged(const QString &identifier)
0306 {
0307     bool differentComic = (mCurrent.id() != identifier);
0308     mCurrent = ComicData();
0309     mCurrent.init(identifier, config());
0310     changeComic(differentComic);
0311 }
0312 
0313 void ComicApplet::checkDayChanged()
0314 {
0315     if (mCurrentDay != QDate::currentDate()) {
0316         updateComic(mCurrent.current());
0317         mCurrentDay = QDate::currentDate();
0318     } else if (!mCurrent.hasImage()) {
0319         updateComic(mCurrent.stored());
0320     }
0321 }
0322 
0323 void ComicApplet::configChanged()
0324 {
0325     KConfigGroup cg = config();
0326     mTabIdentifier = cg.readEntry("tabIdentifier", QStringList());
0327 
0328     if (mProxy) {
0329         updateUsedComics();
0330     }
0331 
0332     const QString id = mTabIdentifier.count() ? mTabIdentifier.at(0) : QString();
0333     mCurrent = ComicData();
0334     mCurrent.init(id, cg);
0335 
0336     mShowComicUrl = cg.readEntry("showComicUrl", false);
0337     mShowComicAuthor = cg.readEntry("showComicAuthor", false);
0338     mShowComicTitle = cg.readEntry("showComicTitle", false);
0339     mShowComicIdentifier = cg.readEntry("showComicIdentifier", false);
0340     mShowErrorPicture = cg.readEntry("showErrorPicture", true);
0341     mArrowsOnHover = cg.readEntry("arrowsOnHover", true);
0342     mMiddleClick = cg.readEntry("middleClick", true);
0343     mCheckNewComicStripsInterval = cg.readEntry("checkNewComicStripsIntervall", 30);
0344 
0345     auto oldMaxComicLimit = mMaxComicLimit;
0346     mMaxComicLimit = cg.readEntry("maxComicLimit", 29);
0347     if (oldMaxComicLimit != mMaxComicLimit) {
0348         mEngine->setMaxComicLimit(mMaxComicLimit);
0349     }
0350 
0351     globalComicUpdater->load();
0352 }
0353 
0354 void ComicApplet::saveConfig()
0355 {
0356     KConfigGroup cg = config();
0357     cg.writeEntry("comic", mCurrent.id());
0358     cg.writeEntry("showComicUrl", mShowComicUrl);
0359     cg.writeEntry("showComicAuthor", mShowComicAuthor);
0360     cg.writeEntry("showComicTitle", mShowComicTitle);
0361     cg.writeEntry("showComicIdentifier", mShowComicIdentifier);
0362     cg.writeEntry("showErrorPicture", mShowErrorPicture);
0363     cg.writeEntry("arrowsOnHover", mArrowsOnHover);
0364     cg.writeEntry("middleClick", mMiddleClick);
0365     cg.writeEntry("tabIdentifier", mTabIdentifier);
0366     cg.writeEntry("checkNewComicStripsIntervall", mCheckNewComicStripsInterval);
0367     cg.writeEntry("maxComicLimit", mMaxComicLimit);
0368 
0369     globalComicUpdater->save();
0370 }
0371 
0372 void ComicApplet::slotNextDay()
0373 {
0374     updateComic(mCurrent.next());
0375 }
0376 
0377 void ComicApplet::slotPreviousDay()
0378 {
0379     updateComic(mCurrent.prev());
0380 }
0381 
0382 void ComicApplet::slotFirstDay()
0383 {
0384     updateComic(mCurrent.first());
0385 }
0386 
0387 void ComicApplet::slotCurrentDay()
0388 {
0389     updateComic(QString());
0390 }
0391 
0392 void ComicApplet::slotFoundLastStrip(int index, const QString &identifier, const QString &suffix)
0393 {
0394     Q_UNUSED(index)
0395 
0396     if (mCurrent.id() != identifier) {
0397         return;
0398     }
0399 
0400     KConfigGroup cg = config();
0401     if (suffix != cg.readEntry(QLatin1String("lastStrip_") + identifier, QString())) {
0402         qDebug() << identifier << "has a newer strip.";
0403         cg.writeEntry(QLatin1String("lastStripVisited_") + identifier, false);
0404         updateComic(suffix);
0405     }
0406 }
0407 
0408 void ComicApplet::slotGoJump()
0409 {
0410     StripSelector *selector = StripSelectorFactory::create(mCurrent.type());
0411     connect(selector, &StripSelector::stripChosen, this, &ComicApplet::updateComic);
0412 
0413     selector->select(mCurrent);
0414 }
0415 
0416 void ComicApplet::slotStorePosition()
0417 {
0418     mCurrent.storePosition(mActionStorePosition->isChecked());
0419 }
0420 
0421 void ComicApplet::slotWebsite()
0422 {
0423     auto *job = new KIO::OpenUrlJob(mCurrent.websiteUrl());
0424     job->start();
0425 }
0426 
0427 void ComicApplet::slotShop()
0428 {
0429     auto *job = new KIO::OpenUrlJob(mCurrent.shopUrl());
0430     job->start();
0431 }
0432 
0433 QList<QAction *> ComicApplet::contextualActions()
0434 {
0435     return mActions;
0436 }
0437 
0438 void ComicApplet::updateComic(const QString &identifierSuffix)
0439 {
0440     const QString id = mCurrent.id();
0441     setConfigurationRequired(id.isEmpty());
0442 
0443     if (!id.isEmpty()) {
0444         setBusy(true);
0445 
0446         const QString identifier = id + QLatin1Char(':') + identifierSuffix;
0447 
0448         // disconnecting of the oldSource is needed, otherwise you could get data for comics you are not looking at if you use tabs
0449         // if there was an error only disconnect the oldSource if it had nothing to do with the error or if the comic changed, that way updates of the error can
0450         // come in
0451         if (!mIdentifierError.isEmpty() && !mIdentifierError.contains(id)) {
0452             mIdentifierError.clear();
0453         }
0454         mOldSource = identifier;
0455         mEngine->requestSource(identifier);
0456         slotScaleToContent();
0457     } else {
0458         setBusy(false);
0459         qWarning() << "Either no identifier was specified or the engine could not be created:"
0460                    << "id" << id;
0461     }
0462     updateContextMenu();
0463 }
0464 
0465 void ComicApplet::updateContextMenu()
0466 {
0467     if (mCurrent.id().isEmpty()) {
0468         mActiveComicModel->clear();
0469     }
0470 
0471     if (mCurrent.id().isEmpty() || !mCurrent.ready()) {
0472         mActionNextNewStripTab->setEnabled(false);
0473         mActionGoFirst->setEnabled(false);
0474         mActionGoLast->setEnabled(false);
0475         mActionScaleContent->setEnabled(false);
0476         mActionWebsite->setEnabled(false);
0477         mActionShop->setEnabled(false);
0478         mActionStorePosition->setEnabled(false);
0479         mActionGoJump->setEnabled(false);
0480         mActionSaveComicAs->setEnabled(false);
0481         mActionScaleContent->setChecked(false);
0482     } else {
0483         mActionGoFirst->setVisible(mCurrent.hasFirst());
0484         mActionGoFirst->setEnabled(mCurrent.hasPrev());
0485         mActionGoLast->setEnabled(true);
0486         mActionWebsite->setEnabled(true);
0487         mActionShop->setEnabled(mCurrent.shopUrl().isValid());
0488         mActionScaleContent->setEnabled(true);
0489         mActionStorePosition->setEnabled(true);
0490         mActionGoJump->setEnabled(true);
0491         mActionSaveComicAs->setEnabled(true);
0492     }
0493 }
0494 
0495 void ComicApplet::slotSaveComicAs()
0496 {
0497     ComicSaver saver(mSavingDir);
0498     saver.save(mCurrent);
0499 }
0500 
0501 void ComicApplet::slotScaleToContent()
0502 {
0503     setShowActualSize(mActionScaleContent->isChecked());
0504 }
0505 
0506 // QML
0507 QObject *ComicApplet::comicsModel() const
0508 {
0509     return mActiveComicModel;
0510 }
0511 
0512 QObject *ComicApplet::availableComicsModel() const
0513 {
0514     return mProxy;
0515 }
0516 
0517 bool ComicApplet::showComicUrl() const
0518 {
0519     return mShowComicUrl;
0520 }
0521 
0522 void ComicApplet::setShowComicUrl(bool show)
0523 {
0524     if (show == mShowComicUrl) {
0525         return;
0526     }
0527 
0528     mShowComicUrl = show;
0529 
0530     Q_EMIT showComicUrlChanged();
0531 }
0532 
0533 bool ComicApplet::showComicAuthor() const
0534 {
0535     return mShowComicAuthor;
0536 }
0537 
0538 void ComicApplet::setShowComicAuthor(bool show)
0539 {
0540     if (show == mShowComicAuthor) {
0541         return;
0542     }
0543 
0544     mShowComicAuthor = show;
0545 
0546     Q_EMIT showComicAuthorChanged();
0547 }
0548 
0549 bool ComicApplet::showComicTitle() const
0550 {
0551     return mShowComicTitle;
0552 }
0553 
0554 void ComicApplet::setShowComicTitle(bool show)
0555 {
0556     if (show == mShowComicTitle) {
0557         return;
0558     }
0559 
0560     mShowComicTitle = show;
0561 
0562     Q_EMIT showComicTitleChanged();
0563 }
0564 
0565 bool ComicApplet::showComicIdentifier() const
0566 {
0567     return mShowComicIdentifier;
0568 }
0569 
0570 void ComicApplet::setShowComicIdentifier(bool show)
0571 {
0572     if (show == mShowComicIdentifier) {
0573         return;
0574     }
0575 
0576     mShowComicIdentifier = show;
0577 
0578     Q_EMIT showComicIdentifierChanged();
0579 }
0580 
0581 bool ComicApplet::showErrorPicture() const
0582 {
0583     return mShowErrorPicture;
0584 }
0585 
0586 void ComicApplet::setShowErrorPicture(bool show)
0587 {
0588     if (show == mShowErrorPicture) {
0589         return;
0590     }
0591 
0592     mShowErrorPicture = show;
0593 
0594     Q_EMIT showErrorPictureChanged();
0595 }
0596 
0597 bool ComicApplet::arrowsOnHover() const
0598 {
0599     return mArrowsOnHover;
0600 }
0601 
0602 void ComicApplet::setArrowsOnHover(bool show)
0603 {
0604     if (show == mArrowsOnHover) {
0605         return;
0606     }
0607 
0608     mArrowsOnHover = show;
0609 
0610     Q_EMIT arrowsOnHoverChanged();
0611 }
0612 
0613 bool ComicApplet::middleClick() const
0614 {
0615     return mMiddleClick;
0616 }
0617 
0618 void ComicApplet::setMiddleClick(bool show)
0619 {
0620     if (show == mMiddleClick) {
0621         return;
0622     }
0623 
0624     mMiddleClick = show;
0625 
0626     Q_EMIT middleClickChanged();
0627     saveConfig();
0628 }
0629 
0630 QVariantMap ComicApplet::comicData() const
0631 {
0632     return mComicData;
0633 }
0634 
0635 QStringList ComicApplet::tabIdentifiers() const
0636 {
0637     return mTabIdentifier;
0638 }
0639 
0640 void ComicApplet::setTabIdentifiers(const QStringList &tabs)
0641 {
0642     if (mTabIdentifier == tabs) {
0643         return;
0644     }
0645 
0646     mTabIdentifier = tabs;
0647     Q_EMIT tabIdentifiersChanged();
0648     saveConfig();
0649     changeComic(mDifferentComic);
0650 }
0651 
0652 void ComicApplet::refreshComicData()
0653 {
0654     mComicData[QStringLiteral("image")] = mCurrent.image();
0655     mComicData[QStringLiteral("prev")] = mCurrent.prev();
0656     mComicData[QStringLiteral("next")] = mCurrent.next();
0657     mComicData[QStringLiteral("additionalText")] = mCurrent.additionalText();
0658 
0659     mComicData[QStringLiteral("websiteUrl")] = mCurrent.websiteUrl().toString();
0660     mComicData[QStringLiteral("websiteHost")] = mCurrent.websiteUrl().host();
0661     mComicData[QStringLiteral("imageUrl")] = mCurrent.websiteUrl().toString();
0662     mComicData[QStringLiteral("shopUrl")] = mCurrent.websiteUrl().toString();
0663     mComicData[QStringLiteral("first")] = mCurrent.first();
0664     mComicData[QStringLiteral("stripTitle")] = mCurrent.stripTitle();
0665     mComicData[QStringLiteral("author")] = mCurrent.author();
0666     mComicData[QStringLiteral("title")] = mCurrent.title();
0667 
0668     mComicData[QStringLiteral("suffixType")] = QStringLiteral("Date");
0669     mComicData[QStringLiteral("current")] = mCurrent.current();
0670     // mComicData[QStringLiteral("last")] = mCurrent.last();
0671     mComicData[QStringLiteral("currentReadable")] = mCurrent.currentReadable();
0672     mComicData[QStringLiteral("firstStripNum")] = mCurrent.firstStripNum();
0673     mComicData[QStringLiteral("maxStripNum")] = mCurrent.maxStripNum();
0674     mComicData[QStringLiteral("isLeftToRight")] = mCurrent.isLeftToRight();
0675     mComicData[QStringLiteral("isTopToBottom")] = mCurrent.isTopToBottom();
0676 
0677     Q_EMIT comicDataChanged();
0678 }
0679 
0680 bool ComicApplet::showActualSize() const
0681 {
0682     return mCurrent.scaleComic();
0683 }
0684 
0685 void ComicApplet::setShowActualSize(bool show)
0686 {
0687     if (show == mCurrent.scaleComic()) {
0688         return;
0689     }
0690 
0691     mCurrent.setScaleComic(show);
0692 
0693     Q_EMIT showActualSizeChanged();
0694 }
0695 
0696 int ComicApplet::checkNewComicStripsInterval() const
0697 {
0698     return mCheckNewComicStripsInterval;
0699 }
0700 
0701 void ComicApplet::setCheckNewComicStripsInterval(int interval)
0702 {
0703     if (mCheckNewComicStripsInterval == interval) {
0704         return;
0705     }
0706 
0707     mCheckNewComicStripsInterval = interval;
0708     Q_EMIT checkNewComicStripsIntervalChanged();
0709 }
0710 
0711 int ComicApplet::providerUpdateInterval() const
0712 {
0713     return globalComicUpdater->interval();
0714 }
0715 
0716 void ComicApplet::setProviderUpdateInterval(int interval)
0717 {
0718     if (globalComicUpdater->interval() == interval) {
0719         return;
0720     }
0721 
0722     globalComicUpdater->setInterval(interval);
0723     Q_EMIT providerUpdateIntervalChanged();
0724 }
0725 
0726 void ComicApplet::setMaxComicLimit(int limit)
0727 {
0728     if (mMaxComicLimit == limit) {
0729         return;
0730     }
0731 
0732     mMaxComicLimit = limit;
0733     Q_EMIT maxComicLimitChanged();
0734 }
0735 
0736 int ComicApplet::maxComicLimit() const
0737 {
0738     return mMaxComicLimit;
0739 }
0740 
0741 // Endof QML
0742 void ComicApplet::setTabHighlighted(const QString &id, bool highlight)
0743 {
0744     // Search for matching id
0745     for (int i = 0; i < mActiveComicModel->rowCount(); ++i) {
0746         QStandardItem *item = mActiveComicModel->item(i);
0747 
0748         QString currentId = item->data(ActiveComicModel::ComicKeyRole).toString();
0749         if (id == currentId) {
0750             if (highlight != item->data(ActiveComicModel::ComicHighlightRole).toBool()) {
0751                 item->setData(highlight, ActiveComicModel::ComicHighlightRole);
0752                 Q_EMIT tabHighlightRequest(id, highlight);
0753             }
0754         }
0755     }
0756 }
0757 
0758 bool ComicApplet::isTabHighlighted(const QString &id) const
0759 {
0760     for (int i = 0; i < mActiveComicModel->rowCount(); ++i) {
0761         QStandardItem *item = mActiveComicModel->item(i);
0762 
0763         QString currentId = item->data(ActiveComicModel::ComicKeyRole).toString();
0764         if (id == currentId) {
0765             return item->data(ActiveComicModel::ComicHighlightRole).toBool();
0766         }
0767     }
0768     return false;
0769 }
0770 
0771 void ComicApplet::loadProviders()
0772 {
0773     mModel->load();
0774 }
0775 
0776 K_PLUGIN_CLASS(ComicApplet)
0777 
0778 #include "comic.moc"