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 }