1 /*
2 SPDX-FileCopyrightText: 2008 Joris Guisson <joris.guisson@gmail.com>
3 SPDX-FileCopyrightText: 2008 Ivan Vasic <ivasic@gmail.com>
4 SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
7 #include <QApplication>
8 #include <QColor>
9 #include <QHeaderView>
10 #include <QInputDialog>
11 #include <QLocale>
12 #include <QPalette>
13
14 #include <KRun>
15
16 #include "feedwidget.h"
17 #include "feedwidgetmodel.h"
18 #include "filterlist.h"
19 #include "ktfeed.h"
20 #include "managefiltersdlg.h"
21 #include "syndicationplugin.h"
22 #include <util/log.h>
23
24 using namespace bt;
25
26 namespace kt
27 {
28 QString FeedWidget::item_template = i18n(
29 "\
30 <html>\
31 <body style=\"color:%4\">\
32 <div style=\"border-style:solid; border-width:1px; border-color:%4; margin:5px; padding:5px\">\
33 <b>Title:</b> %1<br/>\
34 <b>Date:</b> %2<br/>\
35 </div>\
36 <p>%3</p>\
37 </body>\
38 </html>\
39 ");
40
FeedWidget(FilterList * filters,SyndicationActivity * act,QWidget * parent)41 FeedWidget::FeedWidget(FilterList *filters, SyndicationActivity *act, QWidget *parent)
42 : QWidget(parent)
43 , feed(nullptr)
44 , filters(filters)
45 , act(act)
46 {
47 setupUi(this);
48 m_splitter->setStretchFactor(0, 3);
49 m_splitter->setStretchFactor(1, 1);
50
51 connect(m_download, &QPushButton::clicked, this, &FeedWidget::downloadClicked);
52 connect(m_refresh, &QPushButton::clicked, this, &FeedWidget::refreshClicked);
53 connect(m_filters, &QPushButton::clicked, this, &FeedWidget::filtersClicked);
54 connect(m_refresh_rate, qOverload<int>(&QSpinBox::valueChanged), this, &FeedWidget::refreshRateChanged);
55 connect(m_cookies, &QPushButton::clicked, this, &FeedWidget::cookiesClicked);
56
57 m_refresh->setIcon(QIcon::fromTheme(QStringLiteral("view-refresh")));
58 m_filters->setIcon(QIcon::fromTheme(QStringLiteral("view-filter")));
59 m_cookies->setIcon(QIcon::fromTheme(QStringLiteral("preferences-web-browser-cookies")));
60 m_download->setIcon(QIcon::fromTheme(QStringLiteral("ktorrent")));
61
62 model = new FeedWidgetModel(this);
63 m_item_list->setModel(model);
64 m_item_list->setAlternatingRowColors(true);
65 m_item_list->setSelectionMode(QAbstractItemView::ExtendedSelection);
66
67 QHeaderView *hv = m_item_list->header();
68 hv->setSectionResizeMode(QHeaderView::Interactive);
69 connect(m_item_list->selectionModel(), &QItemSelectionModel::selectionChanged, this, &FeedWidget::selectionChanged);
70
71 m_download->setEnabled(false);
72 m_url->clear();
73 m_refresh_rate->clear();
74 m_active_filters->clear();
75
76 m_item_view->setEnabled(false);
77
78 setEnabled(false);
79 }
80
~FeedWidget()81 FeedWidget::~FeedWidget()
82 {
83 }
84
loadState(KConfigGroup & g)85 void FeedWidget::loadState(KConfigGroup &g)
86 {
87 m_splitter->restoreState(g.readEntry("feed_widget_splitter", QByteArray()));
88
89 QHeaderView *hv = m_item_list->header();
90 QByteArray state = g.readEntry("feed_widget_list_header", QByteArray());
91 if (!state.isEmpty())
92 hv->restoreState(state);
93 else
94 QTimer::singleShot(3000, this, &FeedWidget::resizeColumns);
95 }
96
saveState(KConfigGroup & g)97 void FeedWidget::saveState(KConfigGroup &g)
98 {
99 g.writeEntry("feed_widget_splitter", m_splitter->saveState());
100 QHeaderView *hv = m_item_list->header();
101 g.writeEntry("feed_widget_list_header", hv->saveState());
102 }
103
resizeColumns()104 void FeedWidget::resizeColumns()
105 {
106 m_item_list->header()->resizeSections(QHeaderView::ResizeToContents);
107 }
108
setFeed(Feed * f)109 void FeedWidget::setFeed(Feed *f)
110 {
111 if (feed) {
112 disconnect(feed, &Feed::updated, this, &FeedWidget::updated);
113 disconnect(feed, &Feed::feedRenamed, this, &FeedWidget::onFeedRenamed);
114 feed = nullptr;
115 }
116
117 feed = f;
118 setEnabled(feed != nullptr);
119 model->setCurrentFeed(f);
120 if (feed) {
121 connect(feed, &Feed::updated, this, &FeedWidget::updated);
122 connect(feed, &Feed::feedRenamed, this, &FeedWidget::onFeedRenamed);
123
124 m_url->setText(QStringLiteral("<b>%1</b>").arg(feed->feedUrl().toDisplayString()));
125 m_refresh_rate->setValue(feed->refreshRate());
126 updated();
127 selectionChanged(m_item_list->selectionModel()->selection(), QItemSelection());
128 }
129 }
130
downloadClicked()131 void FeedWidget::downloadClicked()
132 {
133 if (!feed)
134 return;
135
136 const QModelIndexList sel = m_item_list->selectionModel()->selectedRows();
137 for (const QModelIndex &idx : sel) {
138 Syndication::ItemPtr ptr = model->itemForIndex(idx);
139 if (ptr)
140 feed->downloadItem(ptr, QString(), QString(), QString(), false);
141 }
142 }
143
refreshClicked()144 void FeedWidget::refreshClicked()
145 {
146 if (feed)
147 feed->refresh();
148 }
149
refreshRateChanged(int v)150 void FeedWidget::refreshRateChanged(int v)
151 {
152 if (v > 0 && feed)
153 feed->setRefreshRate(v);
154 }
155
filtersClicked()156 void FeedWidget::filtersClicked()
157 {
158 if (!feed)
159 return;
160
161 ManageFiltersDlg dlg(feed, filters, act, this);
162 if (dlg.exec() == QDialog::Accepted) {
163 feed->save();
164 feed->runFilters();
165 }
166 }
167
cookiesClicked()168 void FeedWidget::cookiesClicked()
169 {
170 if (!feed)
171 return;
172
173 bool ok = false;
174 QString cookie = feed->authenticationCookie();
175 QString nc = QInputDialog::getText(nullptr, i18n("Authentication Cookie"), i18n("Enter the new authentication cookie"), QLineEdit::Normal, cookie, &ok);
176 if (ok) {
177 feed->setAuthenticationCookie(nc);
178 feed->save();
179 }
180 }
181
selectionChanged(const QItemSelection & sel,const QItemSelection & prev)182 void FeedWidget::selectionChanged(const QItemSelection &sel, const QItemSelection &prev)
183 {
184 Q_UNUSED(prev);
185 m_download->setEnabled(sel.count() > 0);
186 m_item_view->setEnabled(sel.count() > 0);
187 if (sel.count() > 0 && feed) {
188 Syndication::ItemPtr item = model->itemForIndex(m_item_list->selectionModel()->selectedRows().front());
189 if (item) {
190 m_item_view->setHtml(item_template.arg(item->title())
191 .arg(QLocale().toString(QDateTime::fromTime_t(item->datePublished()), QLocale::ShortFormat))
192 .arg(item->description())
193 .arg(QApplication::palette().text().color().name(QColor::NameFormat::HexRgb)),
194 QUrl(feed->feedData()->link()));
195 }
196 }
197 }
198
updated()199 void FeedWidget::updated()
200 {
201 if (!feed)
202 return;
203
204 switch (feed->feedStatus()) {
205 case Feed::OK:
206 m_status->setText(i18n("<b>OK</b>"));
207 break;
208 case Feed::UNLOADED:
209 m_status->setText(i18n("<b>Not Loaded</b>"));
210 break;
211 case Feed::FAILED_TO_DOWNLOAD:
212 m_status->setText(i18n("<b>Download Failed: %1</b>", feed->errorString()));
213 break;
214 case Feed::DOWNLOADING:
215 m_status->setText(i18n("<b>Downloading</b>"));
216 break;
217 }
218 updateCaption(this, feed->title());
219 m_active_filters->setText(QStringLiteral("<b>") + feed->filterNamesString() + QStringLiteral("</b>"));
220 }
221
onFeedRenamed(kt::Feed * f)222 void FeedWidget::onFeedRenamed(kt::Feed *f)
223 {
224 updateCaption(this, f->displayName());
225 }
226
227 }
228