Some work about adaptive color scheme for Web UI (PR #19901)
http://[316:c51a:62a3:8b9::4]/d4708/qBittorrent/src/branch/adaptive-webui
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
531 lines
22 KiB
531 lines
22 KiB
/* |
|
* Bittorrent Client using Qt and libtorrent. |
|
* Copyright (C) 2017 Vladimir Golovnev <glassez@yandex.ru> |
|
* Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org> |
|
* Copyright (C) 2006 Arnaud Demaiziere <arnaud@qbittorrent.org> |
|
* |
|
* 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. |
|
* |
|
* In addition, as a special exception, the copyright holders give permission to |
|
* link this program with the OpenSSL project's "OpenSSL" library (or with |
|
* modified versions of it that use the same license as the "OpenSSL" library), |
|
* and distribute the linked executables. You must obey the GNU General Public |
|
* License in all respects for all of the code used other than "OpenSSL". If you |
|
* modify file(s), you may extend this exception to your version of the file(s), |
|
* but you are not obligated to do so. If you do not wish to do so, delete this |
|
* exception statement from your version. |
|
*/ |
|
|
|
#include "rsswidget.h" |
|
|
|
#include <QClipboard> |
|
#include <QDebug> |
|
#include <QDesktopServices> |
|
#include <QDragMoveEvent> |
|
#include <QMenu> |
|
#include <QMessageBox> |
|
#include <QRegularExpression> |
|
#include <QStandardItemModel> |
|
#include <QString> |
|
|
|
#include "base/bittorrent/session.h" |
|
#include "base/global.h" |
|
#include "base/net/downloadmanager.h" |
|
#include "base/preferences.h" |
|
#include "base/rss/rss_article.h" |
|
#include "base/rss/rss_feed.h" |
|
#include "base/rss/rss_folder.h" |
|
#include "base/rss/rss_session.h" |
|
#include "addnewtorrentdialog.h" |
|
#include "articlelistwidget.h" |
|
#include "autoexpandabledialog.h" |
|
#include "automatedrssdownloader.h" |
|
#include "feedlistwidget.h" |
|
#include "guiiconprovider.h" |
|
#include "ui_rsswidget.h" |
|
|
|
RSSWidget::RSSWidget(QWidget *parent) |
|
: QWidget(parent) |
|
, m_ui(new Ui::RSSWidget) |
|
{ |
|
m_ui->setupUi(this); |
|
|
|
// Icons |
|
m_ui->actionCopyFeedURL->setIcon(GuiIconProvider::instance()->getIcon("edit-copy")); |
|
m_ui->actionDelete->setIcon(GuiIconProvider::instance()->getIcon("edit-delete")); |
|
m_ui->actionDownloadTorrent->setIcon(GuiIconProvider::instance()->getIcon("download")); |
|
m_ui->actionMarkItemsRead->setIcon(GuiIconProvider::instance()->getIcon("mail-mark-read")); |
|
m_ui->actionNewFolder->setIcon(GuiIconProvider::instance()->getIcon("folder-new")); |
|
m_ui->actionNewSubscription->setIcon(GuiIconProvider::instance()->getIcon("list-add")); |
|
m_ui->actionOpenNewsURL->setIcon(GuiIconProvider::instance()->getIcon("application-x-mswinurl")); |
|
m_ui->actionRename->setIcon(GuiIconProvider::instance()->getIcon("edit-rename")); |
|
m_ui->actionUpdate->setIcon(GuiIconProvider::instance()->getIcon("view-refresh")); |
|
m_ui->actionUpdateAllFeeds->setIcon(GuiIconProvider::instance()->getIcon("view-refresh")); |
|
#ifndef Q_OS_MAC |
|
m_ui->newFeedButton->setIcon(GuiIconProvider::instance()->getIcon("list-add")); |
|
m_ui->markReadButton->setIcon(GuiIconProvider::instance()->getIcon("mail-mark-read")); |
|
m_ui->updateAllButton->setIcon(GuiIconProvider::instance()->getIcon("view-refresh")); |
|
m_ui->rssDownloaderBtn->setIcon(GuiIconProvider::instance()->getIcon("download")); |
|
#endif |
|
|
|
m_articleListWidget = new ArticleListWidget(m_ui->splitterMain); |
|
m_ui->splitterMain->insertWidget(0, m_articleListWidget); |
|
connect(m_articleListWidget, &ArticleListWidget::customContextMenuRequested, this, &RSSWidget::displayItemsListMenu); |
|
connect(m_articleListWidget, &ArticleListWidget::currentItemChanged, this, &RSSWidget::handleCurrentArticleItemChanged); |
|
connect(m_articleListWidget, &ArticleListWidget::itemDoubleClicked, this, &RSSWidget::downloadSelectedTorrents); |
|
|
|
m_feedListWidget = new FeedListWidget(m_ui->splitterSide); |
|
m_ui->splitterSide->insertWidget(0, m_feedListWidget); |
|
connect(m_feedListWidget, &QAbstractItemView::doubleClicked, this, &RSSWidget::renameSelectedRSSItem); |
|
connect(m_feedListWidget, &QTreeWidget::currentItemChanged, this, &RSSWidget::handleCurrentFeedItemChanged); |
|
connect(m_feedListWidget, &QWidget::customContextMenuRequested, this, &RSSWidget::displayRSSListMenu); |
|
loadFoldersOpenState(); |
|
m_feedListWidget->setCurrentItem(m_feedListWidget->stickyUnreadItem()); |
|
|
|
m_editHotkey = new QShortcut(Qt::Key_F2, m_feedListWidget, nullptr, nullptr, Qt::WidgetShortcut); |
|
connect(m_editHotkey, &QShortcut::activated, this, &RSSWidget::renameSelectedRSSItem); |
|
m_deleteHotkey = new QShortcut(QKeySequence::Delete, m_feedListWidget, nullptr, nullptr, Qt::WidgetShortcut); |
|
connect(m_deleteHotkey, &QShortcut::activated, this, &RSSWidget::deleteSelectedItems); |
|
|
|
// Feeds list actions |
|
connect(m_ui->actionDelete, &QAction::triggered, this, &RSSWidget::deleteSelectedItems); |
|
connect(m_ui->actionRename, &QAction::triggered, this, &RSSWidget::renameSelectedRSSItem); |
|
connect(m_ui->actionUpdate, &QAction::triggered, this, &RSSWidget::refreshSelectedItems); |
|
connect(m_ui->actionNewFolder, &QAction::triggered, this, &RSSWidget::askNewFolder); |
|
connect(m_ui->actionNewSubscription, &QAction::triggered, this, &RSSWidget::on_newFeedButton_clicked); |
|
connect(m_ui->actionUpdateAllFeeds, &QAction::triggered, this, &RSSWidget::refreshAllFeeds); |
|
connect(m_ui->updateAllButton, &QAbstractButton::clicked, this, &RSSWidget::refreshAllFeeds); |
|
connect(m_ui->actionCopyFeedURL, &QAction::triggered, this, &RSSWidget::copySelectedFeedsURL); |
|
connect(m_ui->actionMarkItemsRead, &QAction::triggered, this, &RSSWidget::on_markReadButton_clicked); |
|
|
|
// News list actions |
|
connect(m_ui->actionOpenNewsURL, &QAction::triggered, this, &RSSWidget::openSelectedArticlesUrls); |
|
connect(m_ui->actionDownloadTorrent, &QAction::triggered, this, &RSSWidget::downloadSelectedTorrents); |
|
|
|
// Restore sliders position |
|
restoreSlidersPosition(); |
|
// Bind saveSliders slots |
|
connect(m_ui->splitterMain, &QSplitter::splitterMoved, this, &RSSWidget::saveSlidersPosition); |
|
connect(m_ui->splitterSide, &QSplitter::splitterMoved, this, &RSSWidget::saveSlidersPosition); |
|
|
|
if (RSS::Session::instance()->isProcessingEnabled()) |
|
m_ui->labelWarn->hide(); |
|
connect(RSS::Session::instance(), &RSS::Session::processingStateChanged |
|
, this, &RSSWidget::handleSessionProcessingStateChanged); |
|
connect(RSS::Session::instance()->rootFolder(), &RSS::Folder::unreadCountChanged |
|
, this, &RSSWidget::handleUnreadCountChanged); |
|
} |
|
|
|
RSSWidget::~RSSWidget() |
|
{ |
|
// we need it here to properly mark latest article |
|
// as read without having additional code |
|
m_articleListWidget->clear(); |
|
|
|
saveFoldersOpenState(); |
|
|
|
delete m_editHotkey; |
|
delete m_deleteHotkey; |
|
delete m_feedListWidget; |
|
delete m_ui; |
|
} |
|
|
|
// display a right-click menu |
|
void RSSWidget::displayRSSListMenu(const QPoint &pos) |
|
{ |
|
if (!m_feedListWidget->indexAt(pos).isValid()) |
|
// No item under the mouse, clear selection |
|
m_feedListWidget->clearSelection(); |
|
QMenu myRSSListMenu(this); |
|
QList<QTreeWidgetItem *> selectedItems = m_feedListWidget->selectedItems(); |
|
if (selectedItems.size() > 0) { |
|
myRSSListMenu.addAction(m_ui->actionUpdate); |
|
myRSSListMenu.addAction(m_ui->actionMarkItemsRead); |
|
myRSSListMenu.addSeparator(); |
|
if (selectedItems.size() == 1) { |
|
if (selectedItems.first() != m_feedListWidget->stickyUnreadItem()) { |
|
myRSSListMenu.addAction(m_ui->actionRename); |
|
myRSSListMenu.addAction(m_ui->actionDelete); |
|
myRSSListMenu.addSeparator(); |
|
if (m_feedListWidget->isFolder(selectedItems.first())) |
|
myRSSListMenu.addAction(m_ui->actionNewFolder); |
|
} |
|
} |
|
else { |
|
myRSSListMenu.addAction(m_ui->actionDelete); |
|
myRSSListMenu.addSeparator(); |
|
} |
|
myRSSListMenu.addAction(m_ui->actionNewSubscription); |
|
if (m_feedListWidget->isFeed(selectedItems.first())) { |
|
myRSSListMenu.addSeparator(); |
|
myRSSListMenu.addAction(m_ui->actionCopyFeedURL); |
|
} |
|
} |
|
else { |
|
myRSSListMenu.addAction(m_ui->actionNewSubscription); |
|
myRSSListMenu.addAction(m_ui->actionNewFolder); |
|
myRSSListMenu.addSeparator(); |
|
myRSSListMenu.addAction(m_ui->actionUpdateAllFeeds); |
|
} |
|
myRSSListMenu.exec(QCursor::pos()); |
|
} |
|
|
|
void RSSWidget::displayItemsListMenu(const QPoint &) |
|
{ |
|
bool hasTorrent = false; |
|
bool hasLink = false; |
|
for (const QListWidgetItem *item : asConst(m_articleListWidget->selectedItems())) { |
|
auto article = reinterpret_cast<RSS::Article *>(item->data(Qt::UserRole).value<quintptr>()); |
|
Q_ASSERT(article); |
|
|
|
if (!article->torrentUrl().isEmpty()) |
|
hasTorrent = true; |
|
if (!article->link().isEmpty()) |
|
hasLink = true; |
|
if (hasTorrent && hasLink) |
|
break; |
|
} |
|
|
|
QMenu myItemListMenu(this); |
|
if (hasTorrent) |
|
myItemListMenu.addAction(m_ui->actionDownloadTorrent); |
|
if (hasLink) |
|
myItemListMenu.addAction(m_ui->actionOpenNewsURL); |
|
if (hasTorrent || hasLink) |
|
myItemListMenu.exec(QCursor::pos()); |
|
} |
|
|
|
void RSSWidget::askNewFolder() |
|
{ |
|
bool ok; |
|
QString newName = AutoExpandableDialog::getText( |
|
this, tr("Please choose a folder name"), tr("Folder name:"), QLineEdit::Normal |
|
, tr("New folder"), &ok); |
|
if (!ok) return; |
|
|
|
newName = newName.trimmed(); |
|
if (newName.isEmpty()) return; |
|
|
|
// Determine destination folder for new item |
|
QTreeWidgetItem *destItem = nullptr; |
|
QList<QTreeWidgetItem *> selectedItems = m_feedListWidget->selectedItems(); |
|
if (!selectedItems.empty()) { |
|
destItem = selectedItems.first(); |
|
if (!m_feedListWidget->isFolder(destItem)) |
|
destItem = destItem->parent(); |
|
} |
|
// Consider the case where the user clicked on Unread item |
|
RSS::Folder *rssDestFolder = ((!destItem || (destItem == m_feedListWidget->stickyUnreadItem())) |
|
? RSS::Session::instance()->rootFolder() |
|
: qobject_cast<RSS::Folder *>(m_feedListWidget->getRSSItem(destItem))); |
|
|
|
QString error; |
|
const QString newFolderPath = RSS::Item::joinPath(rssDestFolder->path(), newName); |
|
if (!RSS::Session::instance()->addFolder(newFolderPath, &error)) |
|
QMessageBox::warning(this, "qBittorrent", error, QMessageBox::Ok); |
|
|
|
// Expand destination folder to display new feed |
|
if (destItem && (destItem != m_feedListWidget->stickyUnreadItem())) |
|
destItem->setExpanded(true); |
|
// As new RSS items are added synchronously, we can do the following here. |
|
m_feedListWidget->setCurrentItem(m_feedListWidget->mapRSSItem(RSS::Session::instance()->itemByPath(newFolderPath))); |
|
} |
|
|
|
// add a stream by a button |
|
void RSSWidget::on_newFeedButton_clicked() |
|
{ |
|
// Ask for feed URL |
|
const QString clipText = qApp->clipboard()->text(); |
|
const QString defaultURL = Net::DownloadManager::hasSupportedScheme(clipText) ? clipText : "http://"; |
|
|
|
bool ok; |
|
QString newURL = AutoExpandableDialog::getText( |
|
this, tr("Please type a RSS feed URL"), tr("Feed URL:"), QLineEdit::Normal, defaultURL, &ok); |
|
if (!ok) return; |
|
|
|
newURL = newURL.trimmed(); |
|
if (newURL.isEmpty()) return; |
|
|
|
// Determine destination folder for new item |
|
QTreeWidgetItem *destItem = nullptr; |
|
QList<QTreeWidgetItem *> selectedItems = m_feedListWidget->selectedItems(); |
|
if (!selectedItems.empty()) { |
|
destItem = selectedItems.first(); |
|
if (!m_feedListWidget->isFolder(destItem)) |
|
destItem = destItem->parent(); |
|
} |
|
// Consider the case where the user clicked on Unread item |
|
RSS::Folder *rssDestFolder = ((!destItem || (destItem == m_feedListWidget->stickyUnreadItem())) |
|
? RSS::Session::instance()->rootFolder() |
|
: qobject_cast<RSS::Folder *>(m_feedListWidget->getRSSItem(destItem))); |
|
|
|
QString error; |
|
// NOTE: We still add feed using legacy way (with URL as feed name) |
|
const QString newFeedPath = RSS::Item::joinPath(rssDestFolder->path(), newURL); |
|
if (!RSS::Session::instance()->addFeed(newURL, newFeedPath, &error)) |
|
QMessageBox::warning(this, "qBittorrent", error, QMessageBox::Ok); |
|
|
|
// Expand destination folder to display new feed |
|
if (destItem && (destItem != m_feedListWidget->stickyUnreadItem())) |
|
destItem->setExpanded(true); |
|
// As new RSS items are added synchronously, we can do the following here. |
|
m_feedListWidget->setCurrentItem(m_feedListWidget->mapRSSItem(RSS::Session::instance()->itemByPath(newFeedPath))); |
|
} |
|
|
|
void RSSWidget::deleteSelectedItems() |
|
{ |
|
const QList<QTreeWidgetItem *> selectedItems = m_feedListWidget->selectedItems(); |
|
if (selectedItems.isEmpty()) |
|
return; |
|
if ((selectedItems.size() == 1) && (selectedItems.first() == m_feedListWidget->stickyUnreadItem())) |
|
return; |
|
|
|
QMessageBox::StandardButton answer = QMessageBox::question( |
|
this, tr("Deletion confirmation"), tr("Are you sure you want to delete the selected RSS feeds?") |
|
, QMessageBox::Yes | QMessageBox::No, QMessageBox::No); |
|
if (answer == QMessageBox::No) |
|
return; |
|
|
|
for (QTreeWidgetItem *item : selectedItems) |
|
if (item != m_feedListWidget->stickyUnreadItem()) |
|
RSS::Session::instance()->removeItem(m_feedListWidget->itemPath(item)); |
|
} |
|
|
|
void RSSWidget::loadFoldersOpenState() |
|
{ |
|
const QStringList openedFolders = Preferences::instance()->getRssOpenFolders(); |
|
for (const QString &varPath : openedFolders) { |
|
QTreeWidgetItem *parent = nullptr; |
|
for (const QString &name : asConst(varPath.split('\\'))) { |
|
int nbChildren = (parent ? parent->childCount() : m_feedListWidget->topLevelItemCount()); |
|
for (int i = 0; i < nbChildren; ++i) { |
|
QTreeWidgetItem *child = (parent ? parent->child(i) : m_feedListWidget->topLevelItem(i)); |
|
if (m_feedListWidget->getRSSItem(child)->name() == name) { |
|
parent = child; |
|
parent->setExpanded(true); |
|
break; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
void RSSWidget::saveFoldersOpenState() |
|
{ |
|
QStringList openedFolders; |
|
for (QTreeWidgetItem *item : asConst(m_feedListWidget->getAllOpenedFolders())) |
|
openedFolders << m_feedListWidget->itemPath(item); |
|
Preferences::instance()->setRssOpenFolders(openedFolders); |
|
} |
|
|
|
void RSSWidget::refreshAllFeeds() |
|
{ |
|
RSS::Session::instance()->refresh(); |
|
} |
|
|
|
void RSSWidget::downloadSelectedTorrents() |
|
{ |
|
for (QListWidgetItem *item : asConst(m_articleListWidget->selectedItems())) { |
|
auto article = reinterpret_cast<RSS::Article *>(item->data(Qt::UserRole).value<quintptr>()); |
|
Q_ASSERT(article); |
|
|
|
// Mark as read |
|
article->markAsRead(); |
|
|
|
if (!article->torrentUrl().isEmpty()) { |
|
if (AddNewTorrentDialog::isEnabled()) |
|
AddNewTorrentDialog::show(article->torrentUrl(), window()); |
|
else |
|
BitTorrent::Session::instance()->addTorrent(article->torrentUrl()); |
|
} |
|
} |
|
} |
|
|
|
// open the url of the selected RSS articles in the Web browser |
|
void RSSWidget::openSelectedArticlesUrls() |
|
{ |
|
for (QListWidgetItem *item : asConst(m_articleListWidget->selectedItems())) { |
|
auto article = reinterpret_cast<RSS::Article *>(item->data(Qt::UserRole).value<quintptr>()); |
|
Q_ASSERT(article); |
|
|
|
// Mark as read |
|
article->markAsRead(); |
|
|
|
if (!article->link().isEmpty()) |
|
QDesktopServices::openUrl(QUrl(article->link())); |
|
} |
|
} |
|
|
|
void RSSWidget::renameSelectedRSSItem() |
|
{ |
|
QList<QTreeWidgetItem *> selectedItems = m_feedListWidget->selectedItems(); |
|
if (selectedItems.size() != 1) return; |
|
|
|
QTreeWidgetItem *item = selectedItems.first(); |
|
if (item == m_feedListWidget->stickyUnreadItem()) |
|
return; |
|
|
|
RSS::Item *rssItem = m_feedListWidget->getRSSItem(item); |
|
const QString parentPath = RSS::Item::parentPath(rssItem->path()); |
|
bool ok; |
|
do { |
|
QString newName = AutoExpandableDialog::getText( |
|
this, tr("Please choose a new name for this RSS feed"), tr("New feed name:") |
|
, QLineEdit::Normal, rssItem->name(), &ok); |
|
// Check if name is already taken |
|
if (!ok) return; |
|
|
|
QString error; |
|
if (!RSS::Session::instance()->moveItem(rssItem, RSS::Item::joinPath(parentPath, newName), &error)) { |
|
QMessageBox::warning(nullptr, tr("Rename failed"), error); |
|
ok = false; |
|
} |
|
} while (!ok); |
|
} |
|
|
|
void RSSWidget::refreshSelectedItems() |
|
{ |
|
for (QTreeWidgetItem *item : asConst(m_feedListWidget->selectedItems())) { |
|
if (item == m_feedListWidget->stickyUnreadItem()) { |
|
refreshAllFeeds(); |
|
return; |
|
} |
|
|
|
m_feedListWidget->getRSSItem(item)->refresh(); |
|
} |
|
} |
|
|
|
void RSSWidget::copySelectedFeedsURL() |
|
{ |
|
QStringList URLs; |
|
for (QTreeWidgetItem *item : asConst(m_feedListWidget->selectedItems())) { |
|
if (auto feed = qobject_cast<RSS::Feed *>(m_feedListWidget->getRSSItem(item))) |
|
URLs << feed->url(); |
|
} |
|
qApp->clipboard()->setText(URLs.join('\n')); |
|
} |
|
|
|
void RSSWidget::handleCurrentFeedItemChanged(QTreeWidgetItem *currentItem) |
|
{ |
|
m_articleListWidget->setRSSItem(m_feedListWidget->getRSSItem(currentItem) |
|
, (currentItem == m_feedListWidget->stickyUnreadItem())); |
|
} |
|
|
|
void RSSWidget::on_markReadButton_clicked() |
|
{ |
|
for (QTreeWidgetItem *item : asConst(m_feedListWidget->selectedItems())) { |
|
m_feedListWidget->getRSSItem(item)->markAsRead(); |
|
if (item == m_feedListWidget->stickyUnreadItem()) |
|
break; // all items was read |
|
} |
|
} |
|
|
|
// display a news |
|
void RSSWidget::handleCurrentArticleItemChanged(QListWidgetItem *currentItem, QListWidgetItem *previousItem) |
|
{ |
|
m_ui->textBrowser->clear(); |
|
|
|
if (previousItem) { |
|
auto article = m_articleListWidget->getRSSArticle(previousItem); |
|
Q_ASSERT(article); |
|
article->markAsRead(); |
|
} |
|
|
|
if (!currentItem) return; |
|
|
|
auto article = m_articleListWidget->getRSSArticle(currentItem); |
|
Q_ASSERT(article); |
|
|
|
QString html; |
|
html += "<div style='border: 2px solid red; margin-left: 5px; margin-right: 5px; margin-bottom: 5px;'>"; |
|
html += "<div style='background-color: #678db2; font-weight: bold; color: #fff;'>" + article->title() + "</div>"; |
|
if (article->date().isValid()) |
|
html += "<div style='background-color: #efefef;'><b>" + tr("Date: ") + "</b>" + article->date().toLocalTime().toString(Qt::SystemLocaleLongDate) + "</div>"; |
|
if (!article->author().isEmpty()) |
|
html += "<div style='background-color: #efefef;'><b>" + tr("Author: ") + "</b>" + article->author() + "</div>"; |
|
html += "</div>"; |
|
html += "<div style='margin-left: 5px; margin-right: 5px;'>"; |
|
if (Qt::mightBeRichText(article->description())) { |
|
html += article->description(); |
|
} |
|
else { |
|
QString description = article->description(); |
|
QRegularExpression rx; |
|
// If description is plain text, replace BBCode tags with HTML and wrap everything in <pre></pre> so it looks nice |
|
rx.setPatternOptions(QRegularExpression::InvertedGreedinessOption |
|
| QRegularExpression::CaseInsensitiveOption); |
|
|
|
rx.setPattern("\\[img\\](.+)\\[/img\\]"); |
|
description = description.replace(rx, "<img src=\"\\1\">"); |
|
|
|
rx.setPattern("\\[url=(\")?(.+)\\1\\]"); |
|
description = description.replace(rx, "<a href=\"\\2\">"); |
|
description = description.replace("[/url]", "</a>", Qt::CaseInsensitive); |
|
|
|
rx.setPattern("\\[(/)?([bius])\\]"); |
|
description = description.replace(rx, "<\\1\\2>"); |
|
|
|
rx.setPattern("\\[color=(\")?(.+)\\1\\]"); |
|
description = description.replace(rx, "<span style=\"color:\\2\">"); |
|
description = description.replace("[/color]", "</span>", Qt::CaseInsensitive); |
|
|
|
rx.setPattern("\\[size=(\")?(.+)\\d\\1\\]"); |
|
description = description.replace(rx, "<span style=\"font-size:\\2px\">"); |
|
description = description.replace("[/size]", "</span>", Qt::CaseInsensitive); |
|
|
|
html += "<pre>" + description + "</pre>"; |
|
} |
|
html += "</div>"; |
|
m_ui->textBrowser->setHtml(html); |
|
} |
|
|
|
void RSSWidget::saveSlidersPosition() |
|
{ |
|
// Remember sliders positions |
|
Preferences *const pref = Preferences::instance(); |
|
pref->setRssSideSplitterState(m_ui->splitterSide->saveState()); |
|
pref->setRssMainSplitterState(m_ui->splitterMain->saveState()); |
|
} |
|
|
|
void RSSWidget::restoreSlidersPosition() |
|
{ |
|
const Preferences *const pref = Preferences::instance(); |
|
const QByteArray stateSide = pref->getRssSideSplitterState(); |
|
if (!stateSide.isEmpty()) |
|
m_ui->splitterSide->restoreState(stateSide); |
|
const QByteArray stateMain = pref->getRssMainSplitterState(); |
|
if (!stateMain.isEmpty()) |
|
m_ui->splitterMain->restoreState(stateMain); |
|
} |
|
|
|
void RSSWidget::updateRefreshInterval(uint val) |
|
{ |
|
RSS::Session::instance()->setRefreshInterval(val); |
|
} |
|
|
|
void RSSWidget::on_rssDownloaderBtn_clicked() |
|
{ |
|
AutomatedRssDownloader(this).exec(); |
|
} |
|
|
|
void RSSWidget::handleSessionProcessingStateChanged(bool enabled) |
|
{ |
|
m_ui->labelWarn->setVisible(!enabled); |
|
} |
|
|
|
void RSSWidget::handleUnreadCountChanged() |
|
{ |
|
emit unreadCountUpdated(RSS::Session::instance()->rootFolder()->unreadCount()); |
|
}
|
|
|