Experimentally fixed #52.
This commit is contained in:
parent
41c239ff03
commit
1e12713a1a
@ -1,7 +1,29 @@
|
||||
<body>
|
||||
<style>
|
||||
body {
|
||||
font-size: 150%;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style-type: square;
|
||||
}
|
||||
|
||||
ul > li {
|
||||
margin-top: 3px;
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
</style>
|
||||
<center><h2>2.5.0</h2></center>
|
||||
Added:
|
||||
<ul>
|
||||
<li>Implemented ability to display <b>ONLY FEEDS WITH SOME UNREAD MESSAGES</b>. This behavior can be controlled by action in menu 'Feeds -> Show only unread feeds/categories' (issue #52). Behavior is this:
|
||||
<ol>
|
||||
<li>User selects some feeds with unread messages, reads them all.</li>
|
||||
<li>User switches to another feed.</li>
|
||||
<li>Previously selected feed (now has no unread messages) is now hidden.</li>
|
||||
</ol>
|
||||
Note that this feature also works when you e.g. mark message(s) as read/unread or when you restore some messages from recycle bin. Also when feeds are updated, then filter is invalidated.
|
||||
</li>
|
||||
<li><b>Password in feeds & proxy & MySQL are now saved in encrypted form. This means that all passwords from RSS Guard older than 2.5.0 are lost!!! Set your passwords again.</b> Used encryption scheme is meant to only make sure that passwords are not stored in DB/settings in plain form. It is not meant to protect your passwords in any broader way. Attacker can exploit your passwords if he really wants.</li>
|
||||
<li><b>Fancy & modern popup notifications</b> (turned on by default).</li>
|
||||
<li>Enhanced information in download manager.</li>
|
||||
|
@ -94,6 +94,10 @@ class FeedsModelRootItem {
|
||||
// Checks whether THIS object is child (direct or indirect)
|
||||
// of the given root.
|
||||
bool isChildOf(FeedsModelRootItem *root) {
|
||||
if (root == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
FeedsModelRootItem *this_item = this;
|
||||
|
||||
while (this_item->kind() != FeedsModelRootItem::RootItem) {
|
||||
@ -108,6 +112,15 @@ class FeedsModelRootItem {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isParentOf(FeedsModelRootItem *child) {
|
||||
if (child == NULL) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
return child->isChildOf(this);
|
||||
}
|
||||
}
|
||||
|
||||
// Removes all children from this item.
|
||||
// NOTE: Children are NOT freed from the memory.
|
||||
inline void clearChildren() {
|
||||
|
@ -25,7 +25,7 @@
|
||||
|
||||
|
||||
FeedsProxyModel::FeedsProxyModel(QObject *parent)
|
||||
: QSortFilterProxyModel(parent) {
|
||||
: QSortFilterProxyModel(parent), m_selectedItem(NULL), m_showUnreadOnly(false) {
|
||||
m_sourceModel = new FeedsModel(this);
|
||||
|
||||
setObjectName(QSL("FeedsProxyModel"));
|
||||
@ -34,7 +34,7 @@ FeedsProxyModel::FeedsProxyModel(QObject *parent)
|
||||
setFilterCaseSensitivity(Qt::CaseInsensitive);
|
||||
setFilterKeyColumn(-1);
|
||||
setFilterRole(Qt::EditRole);
|
||||
setDynamicSortFilter(true);
|
||||
setDynamicSortFilter(false);
|
||||
setSourceModel(m_sourceModel);
|
||||
}
|
||||
|
||||
@ -180,7 +180,53 @@ bool FeedsProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right
|
||||
}
|
||||
|
||||
bool FeedsProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const {
|
||||
return QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent);
|
||||
if (!m_showUnreadOnly) {
|
||||
return QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent);
|
||||
}
|
||||
|
||||
// TODO: učechrat
|
||||
QModelIndex idx = m_sourceModel->index(source_row, 0, source_parent);
|
||||
|
||||
if (!idx.isValid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
FeedsModelRootItem *item = m_sourceModel->itemForIndex(idx);
|
||||
|
||||
if (item->kind() == FeedsModelRootItem::RecycleBin) {
|
||||
// Recycle bin is always displayed.
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
if (m_selectedItem == NULL) {
|
||||
return item->countOfUnreadMessages() > 0;
|
||||
}
|
||||
*/
|
||||
|
||||
if (item->isParentOf(m_selectedItem)/* || item->isChildOf(m_selectedItem)*/ || m_selectedItem == item) {
|
||||
// Currently selected item and all its parents and children must be displayed.
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return item->countOfUnreadMessages() > 0;
|
||||
}
|
||||
}
|
||||
|
||||
FeedsModelRootItem *FeedsProxyModel::selectedItem() const {
|
||||
return m_selectedItem;
|
||||
}
|
||||
|
||||
void FeedsProxyModel::setSelectedItem(FeedsModelRootItem *selectedItem) {
|
||||
m_selectedItem = selectedItem;
|
||||
}
|
||||
|
||||
bool FeedsProxyModel::showUnreadOnly() const {
|
||||
return m_showUnreadOnly;
|
||||
}
|
||||
|
||||
void FeedsProxyModel::setShowUnreadOnly(bool showUnreadOnly) {
|
||||
m_showUnreadOnly = showUnreadOnly;
|
||||
}
|
||||
|
||||
QModelIndexList FeedsProxyModel::mapListToSource(const QModelIndexList &indexes) {
|
||||
|
@ -18,6 +18,8 @@
|
||||
#ifndef FEEDSPROXYMODEL_H
|
||||
#define FEEDSPROXYMODEL_H
|
||||
|
||||
#include "feedsmodelrootitem.h"
|
||||
|
||||
#include <QSortFilterProxyModel>
|
||||
|
||||
|
||||
@ -41,6 +43,12 @@ class FeedsProxyModel : public QSortFilterProxyModel {
|
||||
// Maps list of indexes.
|
||||
QModelIndexList mapListToSource(const QModelIndexList &indexes);
|
||||
|
||||
bool showUnreadOnly() const;
|
||||
void setShowUnreadOnly(bool showUnreadOnly);
|
||||
|
||||
FeedsModelRootItem *selectedItem() const;
|
||||
void setSelectedItem(FeedsModelRootItem *selectedItem);
|
||||
|
||||
public slots:
|
||||
void invalidateFilter();
|
||||
|
||||
@ -52,6 +60,9 @@ class FeedsProxyModel : public QSortFilterProxyModel {
|
||||
private:
|
||||
// Source model pointer.
|
||||
FeedsModel *m_sourceModel;
|
||||
|
||||
FeedsModelRootItem *m_selectedItem;
|
||||
bool m_showUnreadOnly;
|
||||
};
|
||||
|
||||
#endif // FEEDSPROXYMODEL_H
|
||||
|
@ -276,6 +276,7 @@ void FormMain::setupIcons() {
|
||||
m_ui->m_actionSelectPreviousFeedCategory->setIcon(icon_theme_factory->fromTheme(QSL("go-up")));
|
||||
m_ui->m_actionSelectNextMessage->setIcon(icon_theme_factory->fromTheme(QSL("go-down")));
|
||||
m_ui->m_actionSelectPreviousMessage->setIcon(icon_theme_factory->fromTheme(QSL("go-up")));
|
||||
m_ui->m_actionShowOnlyUnreadFeeds->setIcon(icon_theme_factory->fromTheme(QSL("mail-mark-unread")));
|
||||
|
||||
// Setup icons for underlying components: opened web browsers...
|
||||
foreach (WebBrowser *browser, WebBrowser::runningWebBrowsers()) {
|
||||
|
@ -144,6 +144,8 @@
|
||||
<addaction name="m_actionEditSelectedFeedCategory"/>
|
||||
<addaction name="m_actionDeleteSelectedFeedCategory"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="m_actionShowOnlyUnreadFeeds"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="m_actionSelectNextFeedCategory"/>
|
||||
<addaction name="m_actionSelectPreviousFeedCategory"/>
|
||||
<addaction name="separator"/>
|
||||
@ -649,6 +651,17 @@
|
||||
<string notr="true">Ctrl+Shift+Del</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="m_actionShowOnlyUnreadFeeds">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Show only unread feeds/categories</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+Shift+U</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
|
@ -276,6 +276,10 @@ void FeedMessageViewer::switchFeedComponentVisibility() {
|
||||
m_feedsWidget->setVisible(!m_feedsWidget->isVisible());
|
||||
}
|
||||
|
||||
void FeedMessageViewer::toggleShowOnlyUnreadFeeds() {
|
||||
m_feedsView->invalidateReadFeedsFilter(true, qobject_cast<QAction*>(sender())->isChecked());
|
||||
}
|
||||
|
||||
void FeedMessageViewer::updateMessageButtonsAvailability() {
|
||||
bool one_message_selected = m_messagesView->selectionModel()->selectedRows().size() == 1;
|
||||
bool atleast_one_message_selected = !m_messagesView->selectionModel()->selectedRows().isEmpty();
|
||||
@ -423,6 +427,8 @@ void FeedMessageViewer::createConnections() {
|
||||
SIGNAL(triggered()), m_messagesView, SLOT(selectPreviousItem()));
|
||||
connect(form_main->m_ui->m_actionSwitchMessageListOrientation, SIGNAL(triggered()),
|
||||
this, SLOT(switchMessageSplitterOrientation()));
|
||||
connect(form_main->m_ui->m_actionShowOnlyUnreadFeeds, SIGNAL(toggled(bool)),
|
||||
this, SLOT(toggleShowOnlyUnreadFeeds()));
|
||||
}
|
||||
|
||||
void FeedMessageViewer::initialize() {
|
||||
|
@ -118,6 +118,8 @@ class FeedMessageViewer : public TabContent {
|
||||
// toolbar.
|
||||
void switchFeedComponentVisibility();
|
||||
|
||||
void toggleShowOnlyUnreadFeeds();
|
||||
|
||||
void updateMessageButtonsAvailability();
|
||||
void updateFeedButtonsAvailability();
|
||||
|
||||
|
@ -165,6 +165,14 @@ void FeedsView::loadExpandedStates() {
|
||||
}
|
||||
}
|
||||
|
||||
void FeedsView::invalidateReadFeedsFilter(bool set_new_value, bool show_unread_only) {
|
||||
if (set_new_value) {
|
||||
m_proxyModel->setShowUnreadOnly(show_unread_only);
|
||||
}
|
||||
|
||||
QTimer::singleShot(0, m_proxyModel, SLOT(invalidateFilter()));
|
||||
}
|
||||
|
||||
void FeedsView::updateAllFeeds() {
|
||||
emit feedsUpdateRequested(allFeeds());
|
||||
}
|
||||
@ -329,6 +337,9 @@ void FeedsView::receiveMessageCountsChange(FeedsSelection::SelectionMode mode,
|
||||
else {
|
||||
updateCountsOfSelectedFeeds(total_msg_count_changed);
|
||||
}
|
||||
|
||||
// TODO: učechrat
|
||||
invalidateReadFeedsFilter();
|
||||
}
|
||||
|
||||
void FeedsView::editSelectedItem() {
|
||||
@ -510,6 +521,9 @@ void FeedsView::updateCountsOfParticularFeed(FeedsModelFeed *feed, bool update_t
|
||||
m_sourceModel->reloadChangedLayout(QModelIndexList() << index);
|
||||
}
|
||||
|
||||
// TODO: učechrat
|
||||
invalidateReadFeedsFilter();
|
||||
|
||||
notifyWithCounts();
|
||||
}
|
||||
|
||||
@ -609,9 +623,14 @@ void FeedsView::setupAppearance() {
|
||||
}
|
||||
|
||||
void FeedsView::selectionChanged(const QItemSelection &selected, const QItemSelection &deselected) {
|
||||
// TODO: učechrat
|
||||
FeedsModelRootItem *selected_item = selectedItem();
|
||||
m_proxyModel->setSelectedItem(selected_item);
|
||||
|
||||
QTreeView::selectionChanged(selected, deselected);
|
||||
|
||||
emit feedsSelected(FeedsSelection(selectedItem()));
|
||||
emit feedsSelected(FeedsSelection(selected_item));
|
||||
invalidateReadFeedsFilter();
|
||||
}
|
||||
|
||||
void FeedsView::keyPressEvent(QKeyEvent *event) {
|
||||
|
@ -75,6 +75,8 @@ class FeedsView : public QTreeView {
|
||||
void loadExpandedStates();
|
||||
|
||||
public slots:
|
||||
void invalidateReadFeedsFilter(bool set_new_value = false, bool show_unread_only = false);
|
||||
|
||||
// Feed updating.
|
||||
void updateAllFeeds();
|
||||
void updateAllFeedsOnStartup();
|
||||
|
@ -34,6 +34,7 @@
|
||||
#define DVALUE(x) const x
|
||||
#define NON_CONST_DVALUE(x) x
|
||||
#define SETTING(x) x, x##Def
|
||||
#define DEFAULT_VALUE(x) x##Def
|
||||
#define GROUP(x) x::ID
|
||||
|
||||
// Feeds.
|
||||
|
Loading…
x
Reference in New Issue
Block a user