File indexing completed on 2024-05-12 05:12:54

0001 /*
0002    SPDX-FileCopyrightText: 2016-2024 Laurent Montel <montel@kde.org>
0003 
0004    SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "grantleeviewformatter.h"
0008 #include "akregatorconfig.h"
0009 #include "articlegrantleeobject.h"
0010 #include "grantleeutil.h"
0011 #include "utils.h"
0012 #include <KLocalizedString>
0013 
0014 #include "feed.h"
0015 #include "folder.h"
0016 #include <QApplication>
0017 #include <QVariantHash>
0018 #include <QVariantList>
0019 
0020 using namespace Akregator;
0021 
0022 GrantleeViewFormatter::GrantleeViewFormatter(const QString &htmlFileName, const QString &themePath, int deviceDpiY)
0023     : GrantleeTheme::GenericFormatter(htmlFileName, themePath)
0024     , mHtmlArticleFileName(htmlFileName)
0025     , mDirectionString(QApplication::isRightToLeft() ? QStringLiteral("rtl") : QStringLiteral("ltr"))
0026     , mGrantleeThemePath(QStringLiteral("file://") + themePath + QLatin1Char('/'))
0027     , mDeviceDpiY(deviceDpiY)
0028 {
0029     setApplicationDomain("akregator");
0030 }
0031 
0032 GrantleeViewFormatter::~GrantleeViewFormatter() = default;
0033 
0034 int GrantleeViewFormatter::pointsToPixel(int pointSize) const
0035 {
0036     return (pointSize * mDeviceDpiY + 36) / 72;
0037 }
0038 
0039 void GrantleeViewFormatter::addStandardObject(QVariantHash &grantleeObject) const
0040 {
0041     grantleeObject.insert(QStringLiteral("absoluteThemePath"), mGrantleeThemePath);
0042     grantleeObject.insert(QStringLiteral("applicationDir"), mDirectionString);
0043     grantleeObject.insert(QStringLiteral("standardFamilyFont"), Settings::standardFont());
0044     grantleeObject.insert(QStringLiteral("mediumFontSize"), Settings::mediumFontSize());
0045     grantleeObject.insert(QStringLiteral("sidebarCss"), sidebarCss());
0046 }
0047 
0048 QString GrantleeViewFormatter::sidebarCss() const
0049 {
0050     return QStringLiteral(
0051         "html::-webkit-scrollbar {\n"
0052         "  /* we'll add padding as \"border\" in the thumb*/\n"
0053         "    height: 20px;\n"
0054         "    width: 20px;\n"
0055         "    background: white;\n"
0056         "    border-left: 1px solid #e5e5e5;\n"
0057         "    padding-left: 1px;\n"
0058         "}\n\n"
0059 
0060         "html::-webkit-scrollbar-track {\n"
0061         "    border-radius: 20px;\n"
0062         "    width: 6px !important;\n"
0063         "    box-sizing: content-box;\n"
0064         "}\n\n"
0065 
0066         "html::-webkit-scrollbar-thumb {\n"
0067         "    background-color: #CBCDCD;\n"
0068         "    border: 6px solid transparent;\n"
0069         "    border-radius: 20px;\n"
0070         "    background-clip: content-box;\n"
0071         "    width: 8px !important; /* 20px scrollbar - 2 * 6px border */\n"
0072         "    box-sizing: content-box;\n"
0073         "    min-height: 30px;\n"
0074         "}\n\n"
0075 
0076         "html::-webkit-scrollbar-thumb:window-inactive {\n"
0077         "   background-color: #949699; /* when window is inactive it's gray */\n"
0078         "}\n\n"
0079 
0080         "html::-webkit-scrollbar-thumb:hover {\n"
0081         "    background-color: #93CEE9; /* hovered is a lighter blue */\n"
0082         "}\n\n"
0083 
0084         "html::-webkit-scrollbar-corner {\n"
0085         "    background-color: white;\n"
0086         "}\n\n");
0087 }
0088 
0089 QString GrantleeViewFormatter::formatFeed(Akregator::Feed *feed)
0090 {
0091     setDefaultHtmlMainFile(QStringLiteral("defaultnormalvisitfeed.html"));
0092     if (!errorMessage().isEmpty()) {
0093         return errorMessage();
0094     }
0095     QVariantHash feedObject;
0096     addStandardObject(feedObject);
0097     feedObject.insert(QStringLiteral("strippedTitle"), Utils::stripTags(feed->title()));
0098     QString numberOfArticle;
0099     if (feed->unread() == 0) {
0100         numberOfArticle = i18n(" (no unread articles)");
0101     } else {
0102         numberOfArticle = i18np(" (1 unread article)", " (%1 unread articles)", feed->unread());
0103     }
0104 
0105     feedObject.insert(QStringLiteral("feedCount"), numberOfArticle);
0106 
0107     QString feedImage;
0108     if (!feed->logoInfo().imageUrl.isEmpty()) { // image
0109         feedImage = GrantleeUtil::imageFeed(feed);
0110     } else {
0111         feedImage = QStringLiteral("<div class=\"body\">");
0112     }
0113     feedObject.insert(QStringLiteral("feedImage"), feedImage);
0114 
0115     if (!feed->description().isEmpty()) {
0116         QString feedDescription = QStringLiteral("<div dir=\"%1\">").arg(mDirectionString);
0117         feedDescription += i18n("<b>Description:</b> %1<br />", feed->description());
0118         feedDescription += QStringLiteral("</div>"); // /description
0119         feedObject.insert(QStringLiteral("feedDescription"), feedDescription);
0120     }
0121 
0122     if (!feed->htmlUrl().isEmpty()) {
0123         QString feedHomePage = QStringLiteral("<div dir=\"%1\">").arg(mDirectionString);
0124         feedHomePage += i18n("<b>Homepage:</b> <a href=\"%1\">%1</a>", feed->htmlUrl());
0125         feedHomePage += QStringLiteral("</div>"); // / link
0126         feedObject.insert(QStringLiteral("feedHomePage"), feedHomePage);
0127     }
0128 
0129     if (!feed->copyright().isEmpty()) {
0130         QString feedCopyright = QStringLiteral("<div dir=\"%1\">").arg(mDirectionString);
0131         feedCopyright += i18n("<b>Copyright:</b> %1</a>", feed->copyright());
0132         feedCopyright += QStringLiteral("</div>");
0133         feedObject.insert(QStringLiteral("feedCopyright"), feedCopyright);
0134     }
0135 
0136     return render(feedObject);
0137 }
0138 
0139 QString GrantleeViewFormatter::formatFolder(Akregator::Folder *node)
0140 {
0141     setDefaultHtmlMainFile(QStringLiteral("defaultnormalvisitfolder.html"));
0142     if (!errorMessage().isEmpty()) {
0143         return errorMessage();
0144     }
0145     QVariantHash folderObject;
0146     addStandardObject(folderObject);
0147 
0148     folderObject.insert(QStringLiteral("nodeTitle"), node->title());
0149     QString numberOfArticle;
0150     if (node->unread() == 0) {
0151         numberOfArticle = i18n(" (no unread articles)");
0152     } else {
0153         numberOfArticle = i18np(" (1 unread article)", " (%1 unread articles)", node->unread());
0154     }
0155 
0156     folderObject.insert(QStringLiteral("nodeCount"), numberOfArticle);
0157     return render(folderObject);
0158 }
0159 
0160 QString GrantleeViewFormatter::formatArticles(const QList<Article> &article, ArticleFormatter::IconOption icon)
0161 {
0162     setDefaultHtmlMainFile(mHtmlArticleFileName);
0163     if (!errorMessage().isEmpty()) {
0164         return errorMessage();
0165     }
0166 
0167     QVariantHash articleObject;
0168 
0169     QVariantList articlesList;
0170     const int nbArticles(article.count());
0171     articlesList.reserve(nbArticles);
0172     QList<ArticleGrantleeObject *> lstObj;
0173     lstObj.reserve(nbArticles);
0174     for (int i = 0; i < nbArticles; ++i) {
0175         auto articleObj = new ArticleGrantleeObject(article.at(i), icon);
0176         articlesList << QVariant::fromValue(static_cast<QObject *>(articleObj));
0177         lstObj.append(articleObj);
0178     }
0179     articleObject.insert(QStringLiteral("articles"), articlesList);
0180 
0181     addStandardObject(articleObject);
0182     articleObject.insert(QStringLiteral("loadExternalReference"), Settings::loadExternalReferences());
0183     articleObject.insert(QStringLiteral("dateI18n"), i18n("Date"));
0184     articleObject.insert(QStringLiteral("commentI18n"), i18n("Comment"));
0185     articleObject.insert(QStringLiteral("completeStoryI18n"), i18n("Complete Story"));
0186     articleObject.insert(QStringLiteral("authorI18n"), i18n("Author"));
0187     articleObject.insert(QStringLiteral("enclosureI18n"), i18n("Enclosure"));
0188 
0189     const QString str = render(articleObject);
0190     qDeleteAll(lstObj);
0191     return str;
0192 }