File indexing completed on 2024-05-19 05:51:04

0001 /* Atelier KDE Printer Host for 3D Printing
0002     Copyright (C) <2018>
0003     Author: Lays Rodrigues - lays.rodrigues@kde.org
0004             Chris Rizzitello - rizzitello@kde.org
0005 
0006     This program is free software: you can redistribute it and/or modify
0007     it under the terms of the GNU General Public License as published by
0008     the Free Software Foundation, either version 3 of the License, or
0009     (at your option) any later version.
0010 
0011     This program is distributed in the hope that it will be useful,
0012     but WITHOUT ANY WARRANTY; without even the implied warranty of
0013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0014     GNU General Public License for more details.
0015 
0016     You should have received a copy of the GNU General Public License
0017     along with this program.  If not, see <http://www.gnu.org/licenses/>.
0018 */
0019 #include "welcomewidget.h"
0020 #include <KLocalizedString>
0021 #include <QDomDocument>
0022 #include <QHBoxLayout>
0023 #include <QLabel>
0024 #include <QNetworkAccessManager>
0025 #include <QNetworkReply>
0026 #include <QNetworkRequest>
0027 #include <QRegularExpression>
0028 #include <QRegularExpressionMatch>
0029 #include <QScrollArea>
0030 #include <QStyle>
0031 #include <QTimer>
0032 #include <QToolButton>
0033 #include <QVBoxLayout>
0034 #include <algorithm>
0035 
0036 #define POSTS_LIMIT 5
0037 const QString WelcomeWidget::m_telegramLink = QStringLiteral(R"(<a href="http://t.me/KDEAtelier">)");
0038 const QString WelcomeWidget::m_documentsLink = QStringLiteral(R"(<a href="http://atelier.kde.org/documentation/atelier">)");
0039 const QString WelcomeWidget::m_linkClose = QStringLiteral("</a>");
0040 
0041 WelcomeWidget::WelcomeWidget(QWidget *parent)
0042     : QWidget(parent)
0043     , m_newsFeedWidget(new QWidget(this))
0044 {
0045     QFont appFont = font();
0046 
0047     auto hlayout = new QHBoxLayout;
0048     auto layout = new QVBoxLayout;
0049     auto label = new QLabel(this);
0050 
0051     label->setText(i18n("Welcome to Atelier!"));
0052     appFont.setPointSize(font().pointSize() + 4);
0053     label->setFont(appFont);
0054     hlayout->addWidget(label);
0055 
0056     label = new QLabel(this);
0057     label->setPixmap(QPixmap(":/icon/logo"));
0058     label->setLayoutDirection(Qt::LayoutDirection::RightToLeft);
0059     hlayout->addWidget(label);
0060     layout->addItem(hlayout);
0061 
0062     auto line = new QFrame(this);
0063     line->setFrameShape(QFrame::HLine);
0064     layout->addWidget(line);
0065 
0066     appFont.setPointSize(font().pointSize() + 2);
0067     label = new QLabel(i18n("Quick Connect Guide"), this);
0068     label->setFont(appFont);
0069     layout->addWidget(label);
0070 
0071     for (const QString &sentence : {i18n("1 - Create a Profile."), i18n("2 - Select the device."), i18n("3 - Select the profile and connect.")}) {
0072         label = new QLabel(sentence, this);
0073         layout->addWidget(label);
0074     }
0075 
0076     label = new QLabel(i18n("Having a connection problem?"), this);
0077     label->setFont(appFont);
0078     layout->addWidget(label);
0079 
0080     label = new QLabel(i18n("See the info section of the Log for common problems."), this);
0081     layout->addWidget(label);
0082 
0083     label = new QLabel(i18n("Check our %1Atelier Docs%2 for more information.", m_documentsLink, m_linkClose), this);
0084     label->setOpenExternalLinks(true);
0085     layout->addWidget(label);
0086 
0087     label = new QLabel(i18n("Atelier news!"), this);
0088     label->setFont(appFont);
0089     layout->addWidget(label);
0090     retrieveRssFeed();
0091     layout->addWidget(m_newsFeedWidget);
0092 
0093     label = new QLabel(i18n("Get Involved"), this);
0094     label->setFont(appFont);
0095     layout->addWidget(label);
0096 
0097     label = new QLabel(i18n("Join our %1Telegram Group%2!", m_telegramLink, m_linkClose), this);
0098     label->setOpenExternalLinks(true);
0099     layout->addWidget(label);
0100 
0101     label = new QLabel(i18n("You can also find us on Libera Chat IRC #kde-atelier"), this);
0102     layout->addWidget(label);
0103 
0104     layout->addStretch();
0105 
0106     auto infoWidget = new QWidget(this);
0107     infoWidget->setLayout(layout);
0108 
0109     auto scrollArea = new QScrollArea(this);
0110     scrollArea->setWidget(infoWidget);
0111     scrollArea->setWidgetResizable(true);
0112 
0113     layout = new QVBoxLayout;
0114     layout->addWidget(scrollArea);
0115     setLayout(layout);
0116 }
0117 
0118 void WelcomeWidget::retrieveRssFeed()
0119 {
0120     m_postList.clear();
0121     auto manager = new QNetworkAccessManager(this);
0122     for (const QUrl &url : {QUrl("https://rizzitello.wordpress.com/category/atelier/feed/"), QUrl("https://laysrodriguesdev.wordpress.com/category/atelier/feed/")}) {
0123         QNetworkRequest request(url);
0124         request.setRawHeader("User-Agent", "Atelier 1.0");
0125         manager->get(request);
0126         connect(manager, &QNetworkAccessManager::finished, this, [&](QNetworkReply *reply) {
0127             if (reply->error()) {
0128                 return;
0129             }
0130             QDomDocument document;
0131             if (document.setContent(reply->readAll())) {
0132                 parseRss(document);
0133             }
0134         });
0135     }
0136 }
0137 
0138 void WelcomeWidget::parseRss(const QDomDocument &document)
0139 {
0140     auto itemList = document.elementsByTagName("item");
0141     QRegularExpression dateRegex(QStringLiteral(R"((?<date>\d{2} \w{3} \d{4}))"));
0142 
0143     for (int i = 0; i < itemList.count(); ++i) {
0144         auto node = itemList.at(i);
0145         if (node.isElement()) {
0146             // Sample of date format Wed, 24 May 2017 13:46:07 +0000
0147             QString pDate = node.firstChildElement("pubDate").toElement().text();
0148             QRegularExpressionMatch match = dateRegex.match(pDate);
0149             if (match.hasMatch()) {
0150                 Post p;
0151                 p.title = node.firstChildElement("title").toElement().text();
0152                 p.url = node.firstChildElement("link").toElement().text();
0153                 p.date = match.captured("date");
0154                 m_postList.append(p);
0155             }
0156         }
0157     }
0158     setupRssFeed();
0159 }
0160 
0161 void WelcomeWidget::setupRssFeed()
0162 {
0163     if (m_postList.empty()) {
0164         fallback();
0165         return;
0166     }
0167     QLocale locale(QLocale::English);
0168     std::sort(m_postList.begin(), m_postList.end(), [locale](const Post &p1, const Post &p2) { return locale.toDate(p1.date, "dd MMM yyyy") > locale.toDate(p2.date, "dd MMM yyyy"); });
0169     auto layout = new QVBoxLayout;
0170     int count = m_postList.count() > POSTS_LIMIT ? POSTS_LIMIT : m_postList.count();
0171     for (int i = 0; i < count; ++i) {
0172         Post item = m_postList.at(i);
0173         QString url = QString("<a href=\"%1\">%2</a>").arg(item.url, QString(item.title + " - " + item.date));
0174         auto lb = new QLabel(url);
0175         lb->setOpenExternalLinks(true);
0176         layout->addWidget(lb);
0177     }
0178     setNewsLayout(layout);
0179 }
0180 
0181 void WelcomeWidget::fallback()
0182 {
0183     auto theme = palette().text().color().value() >= QColor(Qt::lightGray).value() ? QStringLiteral("dark") : QStringLiteral("light");
0184     auto layout = new QHBoxLayout;
0185     layout->addWidget(new QLabel(i18n("Failed to fetch the News.")));
0186     auto button = new QToolButton;
0187     button->setIcon(QIcon::fromTheme("view-refresh", QIcon(QString(":/%1/refresh").arg(theme))));
0188     button->setIconSize(QSize(fontMetrics().lineSpacing(), fontMetrics().lineSpacing()));
0189     layout->addWidget(button);
0190     layout->addStretch();
0191     connect(button, &QToolButton::clicked, this, &WelcomeWidget::retrieveRssFeed);
0192     setNewsLayout(layout);
0193 }
0194 
0195 void WelcomeWidget::setNewsLayout(QLayout *newLayout)
0196 {
0197     if (m_newsFeedWidget->layout()) {
0198         qDeleteAll(m_newsFeedWidget->children());
0199     }
0200     m_newsFeedWidget->setLayout(newLayout);
0201 }