diff --git a/libs/ui/KisMultiFeedRSSModel.cpp b/libs/ui/KisMultiFeedRSSModel.cpp index 11028fdefe..20c93ef791 100644 --- a/libs/ui/KisMultiFeedRSSModel.cpp +++ b/libs/ui/KisMultiFeedRSSModel.cpp @@ -1,216 +1,221 @@ /************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** ** GNU Lesser General Public License Usage ** ** This file may be used under the terms of the GNU Lesser General Public ** License version 2.1 as published by the Free Software Foundation and ** appearing in the file LICENSE.LGPL included in the packaging of this file. ** Please review the following information to ensure the GNU Lesser General ** Public License version 2.1 requirements will be met: ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** Other Usage ** ** Alternatively, this file may be used in accordance with the terms and ** conditions contained in a signed written agreement between you and Nokia. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** **************************************************************************/ #include "KisMultiFeedRSSModel.h" #include #include #include #include #include #include #include #include QString shortenHtml(QString html) { html.replace(QLatin1String("")); uint firstParaEndHtml = (uint) html.indexOf(QLatin1String("

"), html.indexOf(QLatin1String("

"))+1); uint firstParaEndBr = (uint) html.indexOf(QLatin1String("request().url(); requestUrl = source.toString(); streamReader.setDevice(reply); RssItemList list; while (!streamReader.atEnd()) { switch (streamReader.readNext()) { case QXmlStreamReader::StartElement: if (streamReader.name() == QLatin1String("item")) list.append(parseItem()); else if (streamReader.name() == QLatin1String("title")) blogName = streamReader.readElementText(); else if (streamReader.name() == QLatin1String("link")) { if (!streamReader.namespaceUri().isEmpty()) break; QString favIconString(streamReader.readElementText()); QUrl favIconUrl(favIconString); favIconUrl.setPath(QLatin1String("favicon.ico")); blogIcon = favIconUrl.toString(); blogIcon = QString(); // XXX: fix the favicon on krita.org! } break; default: break; } } return list; } private: QXmlStreamReader streamReader; QString requestUrl; QString blogIcon; QString blogName; }; MultiFeedRssModel::MultiFeedRssModel(QObject *parent) : QAbstractListModel(parent), m_networkAccessManager(new KisNetworkAccessManager), m_articleCount(0) { connect(m_networkAccessManager, SIGNAL(finished(QNetworkReply*)), SLOT(appendFeedData(QNetworkReply*)), Qt::QueuedConnection); } MultiFeedRssModel::~MultiFeedRssModel() { } QHash MultiFeedRssModel::roleNames() const { QHash roleNames; roleNames[TitleRole] = "title"; roleNames[DescriptionRole] = "description"; roleNames[PubDateRole] = "pubDate"; roleNames[LinkRole] = "link"; roleNames[BlogNameRole] = "blogName"; roleNames[BlogIconRole] = "blogIcon"; return roleNames; } void MultiFeedRssModel::addFeed(const QString& feed) { const QUrl feedUrl(feed); QMetaObject::invokeMethod(m_networkAccessManager, "getUrl", Qt::QueuedConnection, Q_ARG(QUrl, feedUrl)); } bool sortForPubDate(const RssItem& item1, const RssItem& item2) { return item1.pubDate > item2.pubDate; } void MultiFeedRssModel::appendFeedData(QNetworkReply *reply) { RssReader reader; m_aggregatedFeed.append(reader.parse(reply)); std::sort(m_aggregatedFeed.begin(), m_aggregatedFeed.end(), sortForPubDate); setArticleCount(m_aggregatedFeed.size()); beginResetModel(); endResetModel(); } void MultiFeedRssModel::removeFeed(const QString &feed) { QMutableListIterator it(m_aggregatedFeed); while (it.hasNext()) { RssItem item = it.next(); if (item.source == feed) it.remove(); } setArticleCount(m_aggregatedFeed.size()); } int MultiFeedRssModel::rowCount(const QModelIndex &) const { return m_aggregatedFeed.size(); } QVariant MultiFeedRssModel::data(const QModelIndex &index, int role) const { RssItem item = m_aggregatedFeed.at(index.row()); switch (role) { - case Qt::DisplayRole: // fall through + case Qt::DisplayRole: + { + return QString("" + item.title + "" + "

" + item.pubDate.toString("dd-MM-yyyy hh:mm") + "

" + "

" + item.description + "


"); + } case TitleRole: return item.title; case DescriptionRole: return item.description; case PubDateRole: return item.pubDate.toString("dd-MM-yyyy hh:mm"); case LinkRole: return item.link; case BlogNameRole: return item.blogName; case BlogIconRole: return item.blogIcon; } return QVariant(); } diff --git a/libs/ui/widgets/KisNewsWidget.cpp b/libs/ui/widgets/KisNewsWidget.cpp index 8bd165eabd..15b7d73965 100644 --- a/libs/ui/widgets/KisNewsWidget.cpp +++ b/libs/ui/widgets/KisNewsWidget.cpp @@ -1,66 +1,121 @@ /* * Copyright (c) 2018 boud * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "KisNewsWidget.h" #include #include +#include +#include +#include +#include +#include #include "kis_config.h" #include "KisMultiFeedRSSModel.h" + +KisNewsDelegate::KisNewsDelegate(QObject *parent) + : QStyledItemDelegate(parent) +{ + qDebug() << "Delegate created"; +} + +void KisNewsDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + painter->save(); + + QStyleOptionViewItem optionCopy = option; + initStyleOption(&optionCopy, index); + + QStyle *style = optionCopy.widget? optionCopy.widget->style() : QApplication::style(); + + QTextDocument doc; + doc.setHtml(optionCopy.text); + + /// Painting item without text + optionCopy.text = QString(); + style->drawControl(QStyle::CE_ItemViewItem, &optionCopy, painter); + + QAbstractTextDocumentLayout::PaintContext ctx; + + // Highlighting text if item is selected + if (optionCopy.state & QStyle::State_Selected) { + ctx.palette.setColor(QPalette::Text, optionCopy.palette.color(QPalette::Active, QPalette::HighlightedText)); + } + + painter->translate(optionCopy.rect.left(), optionCopy.rect.top()); + QRect clip(0, 0, optionCopy.rect.width(), optionCopy.rect.height()); + doc.setPageSize(clip.size()); + doc.drawContents(painter, clip); + painter->restore(); +} + +QSize KisNewsDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + QStyleOptionViewItem optionCopy = option; + initStyleOption(&optionCopy, index); + + QTextDocument doc; + doc.setHtml(optionCopy.text); + doc.setTextWidth(optionCopy.rect.width()); + return QSize(doc.idealWidth(), doc.size().height()); +} + KisNewsWidget::KisNewsWidget(QWidget *parent) : QWidget(parent) { setupUi(this); KisConfig cfg(true); m_getNews = cfg.readEntry("FetchNews", false); chkShowNews->setChecked(m_getNews); connect(chkShowNews, SIGNAL(toggled(bool)), this, SLOT(toggleNews(bool))); m_rssModel = new MultiFeedRssModel(this); if (m_getNews) { m_rssModel->addFeed(QLatin1String("https://krita.org/en/feed/")); } else { m_rssModel->removeFeed(QLatin1String("https://krita.org/en/feed/")); } + listNews->setModel(m_rssModel); + listNews->setItemDelegate(new KisNewsDelegate(listNews)); connect(listNews, SIGNAL(clicked(const QModelIndex&)), this, SLOT(itemSelected(const QModelIndex&))); } void KisNewsWidget::toggleNews(bool toggle) { KisConfig cfg(false); cfg.writeEntry("FetchNews", toggle); m_getNews = toggle; if (m_getNews) { m_rssModel->addFeed(QLatin1String("https://krita.org/en/feed/")); } else { m_rssModel->removeFeed(QLatin1String("https://krita.org/en/feed/")); } } void KisNewsWidget::itemSelected(const QModelIndex &idx) { if (idx.isValid()) { QString link = idx.data(RssRoles::LinkRole).toString(); QDesktopServices::openUrl(QUrl(link)); } } diff --git a/libs/ui/widgets/KisNewsWidget.h b/libs/ui/widgets/KisNewsWidget.h index 7966726c63..acb3e66b3a 100644 --- a/libs/ui/widgets/KisNewsWidget.h +++ b/libs/ui/widgets/KisNewsWidget.h @@ -1,44 +1,54 @@ /* * Copyright (c) 2018 boud * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KISNEWSWIDGET_H #define KISNEWSWIDGET_H #include #include +#include #include class MultiFeedRssModel; +class KisNewsDelegate : public QStyledItemDelegate +{ + Q_OBJECT +public: + KisNewsDelegate(QObject *parent = 0); + void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override; + QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override; +}; + /** * @brief The KisNewsWidget class shows the latest news from Krita.org */ class KisNewsWidget : public QWidget, public Ui::KisNewsPage { Q_OBJECT public: explicit KisNewsWidget(QWidget *parent = nullptr); private Q_SLOTS: void toggleNews(bool toggle); void itemSelected(const QModelIndex &idx); private: bool m_getNews {false}; MultiFeedRssModel *m_rssModel {0}; }; #endif // KISNEWSWIDGET_H