File indexing completed on 2024-06-09 04:25:09

0001 /*
0002  * SPDX-FileCopyrightText: 2018 boud <boud@valdyas.org>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 #include "KisNewsWidget.h"
0007 
0008 #include <QDesktopServices>
0009 #include <QUrl>
0010 #include <QPainter>
0011 #include <QStyleOptionViewItem>
0012 #include <QModelIndex>
0013 #include <QTextDocument>
0014 #include <QAbstractTextDocumentLayout>
0015 #include <QRegularExpression>
0016 #include <QScrollBar>
0017 
0018 #include "kis_config.h"
0019 #include "KisMultiFeedRSSModel.h"
0020 #include <KisKineticScroller.h>
0021 
0022 KisNewsDelegate::KisNewsDelegate(QObject *parent)
0023     : QStyledItemDelegate(parent)
0024 {
0025 }
0026 
0027 void KisNewsDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
0028 {
0029     painter->save();
0030 
0031     QStyleOptionViewItem optionCopy = option;
0032     initStyleOption(&optionCopy, index);
0033 
0034     QStyle *style = optionCopy.widget? optionCopy.widget->style() : QApplication::style();
0035 
0036     QTextDocument doc;
0037     doc.setDocumentMargin(6);
0038     doc.setHtml(optionCopy.text);
0039     doc.setTextWidth(optionCopy.rect.width());
0040 
0041     /// Painting item without text
0042     optionCopy.text = QString();
0043     style->drawControl(QStyle::CE_ItemViewItem, &optionCopy, painter);
0044 
0045     QAbstractTextDocumentLayout::PaintContext ctx;
0046 
0047     // Highlighting text if item is selected
0048     QColor textColor;
0049     if (optionCopy.state & QStyle::State_Selected) {
0050         textColor = optionCopy.palette.color(QPalette::Active, QPalette::HighlightedText);
0051     } else {
0052         textColor = optionCopy.palette.color(QPalette::Text);
0053     }
0054     ctx.palette.setColor(QPalette::Text, textColor);
0055 
0056     painter->translate(optionCopy.rect.left(), optionCopy.rect.top());
0057     QRect clip(0, 0, optionCopy.rect.width(), optionCopy.rect.height());
0058     ctx.clip = clip;
0059     doc.setPageSize(clip.size());
0060     doc.documentLayout()->draw(painter, ctx);
0061 
0062     painter->restore();
0063 }
0064 
0065 QSize KisNewsDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
0066 {
0067     QStyleOptionViewItem optionCopy = option;
0068     initStyleOption(&optionCopy, index);
0069 
0070     QTextDocument doc;
0071     doc.setDocumentMargin(6);
0072     doc.setHtml(optionCopy.text);
0073     doc.setTextWidth(optionCopy.rect.width());
0074     return QSize(doc.idealWidth(), doc.size().height());
0075 }
0076 
0077 KisNewsWidget::KisNewsWidget(QWidget *parent)
0078     : QWidget(parent)
0079     , m_getNews(false)
0080     , m_rssModel(0)
0081 {
0082     setupUi(this);
0083     listNews->viewport()->setAutoFillBackground(false);
0084     listNews->installEventFilter(this);
0085     listNews->setVerticalScrollMode(QListView::ScrollPerPixel);
0086     listNews->verticalScrollBar()->setSingleStep(50);
0087     {
0088         QScroller* scroller = KisKineticScroller::createPreconfiguredScroller(listNews);
0089         if (scroller) {
0090             connect(scroller, SIGNAL(stateChanged(QScroller::State)), this, SLOT(slotScrollerStateChanged(QScroller::State)));
0091         }
0092     }
0093 
0094     m_rssModel = new MultiFeedRssModel(this);
0095     connect(m_rssModel, SIGNAL(feedDataChanged()), this, SLOT(rssDataChanged()), Qt::UniqueConnection);
0096 
0097     listNews->setModel(m_rssModel);
0098     listNews->setItemDelegate(new KisNewsDelegate(listNews));
0099     connect(listNews, SIGNAL(clicked(QModelIndex)), this, SLOT(itemSelected(QModelIndex)));
0100 }
0101 
0102 void KisNewsWidget::setAnalyticsTracking(QString text)
0103 {
0104     m_analyticsTrackingParameters = text;
0105 }
0106 
0107 bool KisNewsWidget::eventFilter(QObject *watched, QEvent *event)
0108 {
0109     if (watched == listNews && event->type() == QEvent::Leave) {
0110         listNews->clearSelection();
0111         listNews->setCurrentIndex(QModelIndex());
0112     }
0113     return QWidget::eventFilter(watched, event);
0114 }
0115 
0116 void KisNewsWidget::toggleNewsLanguage(QString langCode, bool enabled)
0117 {
0118     // Sanity check: Since the code is adding the language code directly into
0119     // the URL, this prevents any nasty surprises with malformed URLs.
0120     Q_FOREACH(const char &ch, langCode.toLatin1()) {
0121         bool isValidChar = (ch >= 'a' && ch <= 'z') || ch == '-';
0122         if (!isValidChar) {
0123             warnUI << "Ignoring attempt to toggle malformed news lang:" << langCode;
0124             return;
0125         }
0126     }
0127 
0128     QString feed = QStringLiteral("https://krita.org/%1/feed/").arg(langCode);
0129     if (enabled) {
0130         m_enabledFeeds.insert(feed);
0131         if (m_getNews) {
0132             m_rssModel->addFeed(feed);
0133         }
0134     } else {
0135         m_enabledFeeds.remove(feed);
0136         if (m_getNews) {
0137             m_rssModel->removeFeed(feed);
0138         }
0139     }
0140 }
0141 
0142 void KisNewsWidget::toggleNews(bool toggle)
0143 {
0144     m_getNews = toggle;
0145 
0146     KisConfig cfg(false);
0147     cfg.writeEntry<bool>("FetchNews", toggle);
0148 
0149     Q_FOREACH(const QString &feed, m_enabledFeeds) {
0150         if (toggle) {
0151             m_rssModel->addFeed(feed);
0152         } else {
0153             m_rssModel->removeFeed(feed);
0154         }
0155     }
0156 }
0157 
0158 void KisNewsWidget::itemSelected(const QModelIndex &idx)
0159 {
0160     if (idx.isValid()) {
0161         QString link = idx.data(KisRssReader::RssRoles::LinkRole).toString();
0162 
0163         // append query string for analytics tracking if we set it
0164         if (m_analyticsTrackingParameters != "") {
0165 
0166             // use title in analytics query string
0167             QString linkTitle = idx.data(KisRssReader::RssRoles::TitleRole).toString();
0168             linkTitle = linkTitle.simplified(); // trims and makes 1 white space
0169             linkTitle = linkTitle.replace(" ", "");
0170 
0171             m_analyticsTrackingParameters = m_analyticsTrackingParameters.append(linkTitle);
0172             QDesktopServices::openUrl(QUrl(link.append(m_analyticsTrackingParameters)));
0173 
0174         } else {
0175             QDesktopServices::openUrl(QUrl(link));
0176         }
0177 
0178 
0179     }
0180 }
0181 
0182 void KisNewsWidget::rssDataChanged()
0183 {
0184     emit newsDataChanged();
0185 }
0186