added feed filtering dropdown the same way as article filtering dropdown

This commit is contained in:
Martin Rotter 2025-05-22 09:43:59 +02:00
parent 28adf6379c
commit 542ae73b2b
14 changed files with 348 additions and 117 deletions

View file

@ -19,9 +19,11 @@ using RootItemPtr = RootItem*;
FeedsProxyModel::FeedsProxyModel(FeedsModel* source_model, QObject* parent)
: QSortFilterProxyModel(parent), m_sourceModel(source_model), m_view(nullptr), m_selectedItem(nullptr),
m_showUnreadOnly(false), m_sortAlphabetically(false) {
m_showUnreadOnly(false), m_sortAlphabetically(false), m_filter(FeedListFilter::NoFiltering) {
setObjectName(QSL("FeedsProxyModel"));
initializeFilters();
setSortRole(Qt::ItemDataRole::EditRole);
setSortCaseSensitivity(Qt::CaseSensitivity::CaseInsensitive);
setRecursiveFilteringEnabled(true);
@ -397,6 +399,43 @@ bool FeedsProxyModel::filterAcceptsRow(int source_row, const QModelIndex& source
return should_show;
}
void FeedsProxyModel::initializeFilters() {
m_filters[FeedListFilter::ShowEmpty] = [this](const Feed* feed) {
return feed->countOfAllMessages() == 0;
};
m_filters[FeedListFilter::ShowNonEmpty] = [this](const Feed* feed) {
return feed->countOfAllMessages() != 0;
};
m_filters[FeedListFilter::ShowQuiet] = [this](const Feed* feed) {
return feed->isQuiet();
};
m_filters[FeedListFilter::ShowSwitchedOff] = [this](const Feed* feed) {
return feed->isSwitchedOff();
};
m_filters[FeedListFilter::ShowUnread] = [this](const Feed* feed) {
return feed->countOfUnreadMessages() > 0;
};
m_filters[FeedListFilter::ShowWithArticleFilters] = [this](const Feed* feed) {
return !feed->messageFilters().isEmpty();
};
m_filters[FeedListFilter::ShowWithError] = [this](const Feed* feed) {
return feed->status() == Feed::Status::AuthError || feed->status() == Feed::Status::NetworkError ||
feed->status() == Feed::Status::OtherError || feed->status() == Feed::Status::ParsingError;
};
m_filters[FeedListFilter::ShowWithNewArticles] = [this](const Feed* feed) {
return feed->status() == Feed::Status::NewMessages;
};
m_filterKeys = m_filters.keys();
}
bool FeedsProxyModel::filterAcceptsRowInternal(int source_row, const QModelIndex& source_parent) const {
const QModelIndex idx = m_sourceModel->index(source_row, 0, source_parent);
@ -406,6 +445,10 @@ bool FeedsProxyModel::filterAcceptsRowInternal(int source_row, const QModelIndex
const RootItem* item = m_sourceModel->itemForIndex(idx);
if (m_selectedItem == item) {
return true;
}
if (item->kind() == RootItem::Kind::Important && !item->getParentServiceRoot()->nodeShowImportant()) {
return false;
}
@ -428,22 +471,26 @@ bool FeedsProxyModel::filterAcceptsRowInternal(int source_row, const QModelIndex
return true;
}
if (!m_showUnreadOnly) {
// Take only regexp filtering into account.
if (item->kind() == RootItem::Kind::Feed) {
const Feed* feed = item->toFeed();
for (FeedListFilter val : m_filterKeys) {
if (Globals::hasFlag(m_filter, val)) {
// This particular filter is enabled.
if (m_filters[val](feed)) {
// The item matches the feed filter.
// Display it if it matches internal string-based filter too.
return QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent);
}
else {
// NOTE: If item has < 0 of unread messages it may mean, that the count
// of unread messages is not (yet) known, display that item too.
//
// Also, the actual selected item should not be filtered out too.
// This is primarily to make sure that the selection does not "vanish", this
// particularly manifests itself if user uses "next unread item" action and
// "show unread only" is enabled too and user for example selects last unread
// article in a feed -> then the feed would disappear from list suddenly.
return m_selectedItem == item ||
(item->countOfUnreadMessages() != 0 && QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent));
}
}
// The item does not match feed filter.
// Display it only if it is selected.
return m_filter == FeedListFilter::NoFiltering;
}
return QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent);
}
bool FeedsProxyModel::sortAlphabetically() const {
@ -500,3 +547,9 @@ QModelIndexList FeedsProxyModel::mapListToSource(const QModelIndexList& indexes)
return source_indexes;
}
void FeedsProxyModel::setFeedListFilter(FeedListFilter filter) {
m_filter = filter;
invalidateRowsFilter();
}

View file

@ -14,9 +14,25 @@ class FeedsProxyModel : public QSortFilterProxyModel {
Q_OBJECT
public:
// Enum which describes basic filtering schemes
// for feeds.
enum class FeedListFilter {
NoFiltering = 1,
ShowUnread = 2,
ShowEmpty = 4,
ShowNonEmpty = 8,
ShowWithNewArticles = 16,
ShowWithError = 32,
ShowSwitchedOff = 64,
ShowQuiet = 128,
ShowWithArticleFilters = 256
};
explicit FeedsProxyModel(FeedsModel* source_model, QObject* parent = nullptr);
virtual ~FeedsProxyModel();
void setFeedListFilter(FeedListFilter filter);
virtual bool canDropMimeData(const QMimeData* data,
Qt::DropAction action,
int row,
@ -45,8 +61,8 @@ class FeedsProxyModel : public QSortFilterProxyModel {
void setShowUnreadOnly(bool show_unread_only);
const RootItem* selectedItem() const;
void setSelectedItem(const RootItem* selected_item);
void setView(FeedsView* newView);
bool sortAlphabetically() const;
@ -66,6 +82,8 @@ class FeedsProxyModel : public QSortFilterProxyModel {
virtual bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const;
private:
void initializeFilters();
virtual bool filterAcceptsRowInternal(int source_row, const QModelIndex& source_parent) const;
// Source model pointer.
@ -80,6 +98,12 @@ class FeedsProxyModel : public QSortFilterProxyModel {
bool m_showNodeImportant;
QList<RootItem::Kind> m_priorities;
QList<QPair<int, QModelIndex>> m_hiddenIndices;
FeedListFilter m_filter;
QMap<FeedListFilter, std::function<bool(const Feed*)>> m_filters;
QList<FeedListFilter> m_filterKeys;
};
Q_DECLARE_METATYPE(FeedsProxyModel::FeedListFilter)
#endif // FEEDSPROXYMODEL_H

View file

@ -186,6 +186,10 @@ void FeedMessageViewer::changeMessageFilter(MessagesProxyModel::MessageListFilte
m_messagesView->changeFilter(filter);
}
void FeedMessageViewer::changeFeedFilter(FeedsProxyModel::FeedListFilter filter) {
m_feedsView->changeFilter(filter);
}
void FeedMessageViewer::toggleShowOnlyUnreadFeeds() {
const QAction* origin = qobject_cast<QAction*>(sender());
@ -288,7 +292,9 @@ void FeedMessageViewer::createConnections() {
&MessagesToolBar::messageHighlighterChanged,
m_messagesView,
&MessagesView::highlightMessages);
connect(m_toolBarMessages, &MessagesToolBar::messageFilterChanged, this, &FeedMessageViewer::changeMessageFilter);
connect(m_toolBarFeeds, &FeedsToolBar::feedFilterChanged, this, &FeedMessageViewer::changeFeedFilter);
connect(m_feedSplitter, &QSplitter::splitterMoved, this, &FeedMessageViewer::onFeedSplitterResized);
connect(m_messageSplitter, &QSplitter::splitterMoved, this, &FeedMessageViewer::onMessageSplitterResized);

View file

@ -3,6 +3,7 @@
#ifndef FEEDMESSAGEVIEWER_H
#define FEEDMESSAGEVIEWER_H
#include "core/feedsproxymodel.h"
#include "core/messagesmodel.h"
#include "core/messagesproxymodel.h"
#include "gui/tabcontent.h"
@ -62,6 +63,8 @@ class RSSGUARD_DLLSPEC FeedMessageViewer : public TabContent {
void switchFeedComponentVisibility();
void changeMessageFilter(MessagesProxyModel::MessageListFilter filter);
void changeFeedFilter(FeedsProxyModel::FeedListFilter filter);
void toggleShowOnlyUnreadFeeds();
void toggleShowFeedTreeBranches();
void toggleItemsAutoExpandingOnSelection();

View file

@ -407,6 +407,10 @@ void FeedsView::editRecursiveFeeds() {
}
}
void FeedsView::changeFilter(FeedsProxyModel::FeedListFilter filter) {
m_proxyModel->setFeedListFilter(filter);
}
void FeedsView::editSelectedItems() {
editItems(selectedItems());
}
@ -787,9 +791,9 @@ void FeedsView::filterItems(SearchLineEdit::SearchMode mode,
m_proxyModel->setFilterCaseSensitivity(sensitivity);
FeedsToolBar::SearchFields where_search = FeedsToolBar::SearchFields(custom_criteria);
BaseToolBar::SearchFields where_search = BaseToolBar::SearchFields(custom_criteria);
m_proxyModel->setFilterKeyColumn(where_search == FeedsToolBar::SearchFields::SearchTitleOnly ? FDS_MODEL_TITLE_INDEX
m_proxyModel->setFilterKeyColumn(where_search == BaseToolBar::SearchFields::SearchTitleOnly ? FDS_MODEL_TITLE_INDEX
: -1);
if (phrase.isEmpty()) {

View file

@ -86,6 +86,8 @@ class RSSGUARD_DLLSPEC FeedsView : public BaseTreeView {
// Switches visibility of the widget.
void switchVisibility();
void changeFilter(FeedsProxyModel::FeedListFilter filter);
void filterItems(SearchLineEdit::SearchMode mode,
Qt::CaseSensitivity sensitivity,
int custom_criteria,

View file

@ -871,9 +871,9 @@ void MessagesView::searchMessages(SearchLineEdit::SearchMode mode,
m_proxyModel->setFilterCaseSensitivity(sensitivity);
MessagesToolBar::SearchFields where_search = MessagesToolBar::SearchFields(custom_criteria);
BaseToolBar::SearchFields where_search = BaseToolBar::SearchFields(custom_criteria);
m_proxyModel->setFilterKeyColumn(where_search == MessagesToolBar::SearchFields::SearchTitleOnly ? MSG_DB_TITLE_INDEX
m_proxyModel->setFilterKeyColumn(where_search == BaseToolBar::SearchFields::SearchTitleOnly ? MSG_DB_TITLE_INDEX
: -1);
if (selectionModel()->selectedRows().isEmpty()) {

View file

@ -2,8 +2,12 @@
#include "gui/toolbars/basetoolbar.h"
#include "3rd-party/boolinq/boolinq.h"
#include "definitions/definitions.h"
#include "miscellaneous/settings.h"
#include <QFont>
#include <QPainter>
#include <QWidgetAction>
BaseToolBar::BaseToolBar(const QString& title, QWidget* parent) : QToolBar(title, parent) {
@ -31,3 +35,69 @@ QAction* BaseBar::findMatchingAction(const QString& action, const QList<QAction*
return nullptr;
}
void BaseToolBar::addActionToMenu(QMenu* menu,
const QIcon& icon,
const QString& title,
const QVariant& value,
const QString& name) {
QAction* action = menu->addAction(icon, title);
action->setCheckable(true);
action->setData(value);
action->setObjectName(name);
}
void BaseToolBar::activateAction(const QString& action_name, QWidgetAction* widget_action) {
const int start = action_name.indexOf('[');
const int end = action_name.indexOf(']');
if (start != -1 && end != -1 && end == action_name.length() - 1) {
const QStringList menu_action_names = action_name.chopped(1).right(end - start - 1).split(QL1C(';'));
auto tool_btn = qobject_cast<QToolButton*>(widget_action->defaultWidget());
for (QAction* action : tool_btn->menu()->actions()) {
if (menu_action_names.contains(action->objectName())) {
action->trigger();
}
}
}
}
void BaseToolBar::saveToolButtonSelection(const QString& button_name,
const QString& setting_name,
const QList<QAction*>& actions) const {
QStringList action_names = savedActions();
auto opts_list = boolinq::from(actions)
.select([](const QAction* act) {
return act->objectName();
})
.toStdList();
QStringList opts = FROM_STD_LIST(QStringList, opts_list);
for (QString& action_name : action_names) {
if (action_name.startsWith(button_name)) {
action_name = button_name + QSL("[%1]").arg(opts.join(QL1C(';')));
}
}
qApp->settings()->setValue(GROUP(GUI), setting_name, action_names.join(QSL(",")));
}
void BaseToolBar::drawNumberOfCriterias(QToolButton* btn, int count) {
QPixmap px(128, 128);
px.fill(Qt::GlobalColor::transparent);
QPainter p(&px);
auto fon = p.font();
fon.setPixelSize(40);
p.setFont(fon);
p.drawPixmap(0, 0, 80, 80, btn->defaultAction()->icon().pixmap(128, 128));
p.drawText(65, 65, 50, 50, Qt::AlignmentFlag::AlignCenter, QString::number(count));
btn->setIcon(px);
}

View file

@ -3,7 +3,10 @@
#ifndef TOOLBAR_H
#define TOOLBAR_H
#include <QMenu>
#include <QToolBar>
#include <QToolButton>
#include <QWidgetAction>
class BaseBar {
public:
@ -41,8 +44,25 @@ class BaseToolBar : public QToolBar, public BaseBar {
Q_OBJECT
public:
enum class SearchFields {
SearchTitleOnly = 1,
SearchAll = 2
};
explicit BaseToolBar(const QString& title, QWidget* parent = nullptr);
virtual ~BaseToolBar();
protected:
void saveToolButtonSelection(const QString& button_name,
const QString& setting_name,
const QList<QAction*>& actions) const;
void activateAction(const QString& action_name, QWidgetAction* widget_action);
void addActionToMenu(QMenu* menu,
const QIcon& icon,
const QString& title,
const QVariant& value,
const QString& name);
void drawNumberOfCriterias(QToolButton* btn, int count);
};
#endif // TOOLBAR_H

View file

@ -2,6 +2,9 @@
#include "gui/toolbars/feedstoolbar.h"
#include "3rd-party/boolinq/boolinq.h"
#include "core/feedsproxymodel.h"
#include "gui/reusable/nonclosablemenu.h"
#include "miscellaneous/application.h"
#include "miscellaneous/iconfactory.h"
#include "miscellaneous/settings.h"
@ -15,6 +18,7 @@ FeedsToolBar::FeedsToolBar(const QString& title, QWidget* parent) : BaseToolBar(
margins.setRight(margins.right() + FILTER_RIGHT_MARGIN);
setContentsMargins(margins);
initializeFilter();
initializeSearchBox();
}
@ -22,6 +26,7 @@ QList<QAction*> FeedsToolBar::availableActions() const {
QList<QAction*> available_actions = qApp->userActions();
available_actions.append(m_actionSearchMessages);
available_actions.append(m_actionMessageFilter);
return available_actions;
}
@ -65,6 +70,11 @@ QList<QAction*> FeedsToolBar::convertActions(const QStringList& actions) {
// Add search box.
spec_actions.append(m_actionSearchMessages);
}
else if (action_name.startsWith(QSL(FILTER_ACTION_NAME))) {
// Add filter button.
spec_actions.append(m_actionMessageFilter);
activateAction(action_name, m_actionMessageFilter);
}
else if (action_name == QSL(SPACER_ACTION_NAME)) {
// Add new spacer.
auto* spacer = new QWidget(this);
@ -93,6 +103,53 @@ void FeedsToolBar::loadSpecificActions(const QList<QAction*>& actions, bool init
}
}
inline FeedsProxyModel::FeedListFilter operator|(FeedsProxyModel::FeedListFilter a, FeedsProxyModel::FeedListFilter b) {
return static_cast<FeedsProxyModel::FeedListFilter>(static_cast<int>(a) | static_cast<int>(b));
}
void FeedsToolBar::handleMessageFilterChange(QAction* action) {
FeedsProxyModel::FeedListFilter task = action->data().value<FeedsProxyModel::FeedListFilter>();
std::list<QAction*> checked_tasks_std = boolinq::from(m_menuMessageFilter->actions())
.where([](QAction* act) {
return act->isChecked();
})
.toStdList();
if (task == FeedsProxyModel::FeedListFilter::NoFiltering || checked_tasks_std.empty()) {
task = FeedsProxyModel::FeedListFilter::NoFiltering;
checked_tasks_std.clear();
// Uncheck everything.
m_menuMessageFilter->blockSignals(true);
for (QAction* tsk : m_menuMessageFilter->actions()) {
tsk->setChecked(false);
}
m_menuMessageFilter->blockSignals(false);
}
else {
task = FeedsProxyModel::FeedListFilter(0);
for (QAction* tsk : checked_tasks_std) {
task = task | tsk->data().value<FeedsProxyModel::FeedListFilter>();
}
}
m_btnMessageFilter->setDefaultAction(checked_tasks_std.empty() ? m_menuMessageFilter->actions().constFirst()
: checked_tasks_std.front());
if (checked_tasks_std.size() > 1) {
drawNumberOfCriterias(m_btnMessageFilter, int(checked_tasks_std.size()));
}
saveToolButtonSelection(QSL(FILTER_ACTION_NAME),
GUI::FeedsToolbarActions,
FROM_STD_LIST(QList<QAction*>, checked_tasks_std));
emit feedFilterChanged(task);
}
QStringList FeedsToolBar::defaultActions() const {
return QString(GUI::FeedsToolbarActionsDef)
.split(',',
@ -139,3 +196,66 @@ void FeedsToolBar::initializeSearchBox() {
SearchLineEdit* FeedsToolBar::searchBox() const {
return m_txtSearchMessages;
}
void FeedsToolBar::initializeFilter() {
m_menuMessageFilter = new NonClosableMenu(tr("Menu for filtering feeds"), this);
addActionToMenu(m_menuMessageFilter,
qApp->icons()->fromTheme(QSL("mail-mark-read")),
tr("No extra filtering"),
QVariant::fromValue(FeedsProxyModel::FeedListFilter::NoFiltering),
QSL("no_filtering"));
addActionToMenu(m_menuMessageFilter,
qApp->icons()->fromTheme(QSL("mail-mark-read")),
tr("Show unread feeds"),
QVariant::fromValue(FeedsProxyModel::FeedListFilter::ShowUnread),
QSL("show_unread"));
addActionToMenu(m_menuMessageFilter,
qApp->icons()->fromTheme(QSL("mail-mark-read")),
tr("Show non-empty feeds"),
QVariant::fromValue(FeedsProxyModel::FeedListFilter::ShowNonEmpty),
QSL("non_empty"));
addActionToMenu(m_menuMessageFilter,
qApp->icons()->fromTheme(QSL("mail-mark-read")),
tr("Show feeds with new articles"),
QVariant::fromValue(FeedsProxyModel::FeedListFilter::ShowWithNewArticles),
QSL("new_articles"));
addActionToMenu(m_menuMessageFilter,
qApp->icons()->fromTheme(QSL("mail-mark-read")),
tr("Show feeds with error"),
QVariant::fromValue(FeedsProxyModel::FeedListFilter::ShowWithError),
QSL("with_error"));
addActionToMenu(m_menuMessageFilter,
qApp->icons()->fromTheme(QSL("mail-mark-read")),
tr("Show switched off feeds"),
QVariant::fromValue(FeedsProxyModel::FeedListFilter::ShowSwitchedOff),
QSL("switched_off"));
addActionToMenu(m_menuMessageFilter,
qApp->icons()->fromTheme(QSL("mail-mark-read")),
tr("Show quiet feeds"),
QVariant::fromValue(FeedsProxyModel::FeedListFilter::ShowQuiet),
QSL("quiet"));
addActionToMenu(m_menuMessageFilter,
qApp->icons()->fromTheme(QSL("mail-mark-read")),
tr("Show feeds with article filters"),
QVariant::fromValue(FeedsProxyModel::FeedListFilter::ShowWithArticleFilters),
QSL("with_filters"));
m_btnMessageFilter = new QToolButton(this);
m_btnMessageFilter->setToolTip(tr("Display all feeds"));
m_btnMessageFilter->setMenu(m_menuMessageFilter);
m_btnMessageFilter->setPopupMode(QToolButton::ToolButtonPopupMode::InstantPopup);
m_btnMessageFilter->setIcon(qApp->icons()->fromTheme(QSL("mail-mark-read")));
m_btnMessageFilter->setDefaultAction(m_menuMessageFilter->actions().constFirst());
m_actionMessageFilter = new QWidgetAction(this);
m_actionMessageFilter->setDefaultWidget(m_btnMessageFilter);
m_actionMessageFilter->setIcon(m_btnMessageFilter->icon());
m_actionMessageFilter->setProperty("type", FILTER_ACTION_NAME);
m_actionMessageFilter->setProperty("name", tr("Feed list filter"));
connect(m_menuMessageFilter, &QMenu::triggered, this, &FeedsToolBar::handleMessageFilterChange);
connect(this, &FeedsToolBar::toolButtonStyleChanged, this, [=](Qt::ToolButtonStyle style) {
m_btnMessageFilter->setToolButtonStyle(style);
});
}

View file

@ -3,6 +3,7 @@
#ifndef FEEDSTOOLBAR_H
#define FEEDSTOOLBAR_H
#include "core/feedsproxymodel.h"
#include "gui/reusable/searchlineedit.h"
#include "gui/toolbars/basetoolbar.h"
@ -12,11 +13,6 @@ class FeedsToolBar : public BaseToolBar {
Q_OBJECT
public:
enum class SearchFields {
SearchTitleOnly = 1,
SearchAll = 2
};
explicit FeedsToolBar(const QString& title, QWidget* parent = nullptr);
virtual QList<QAction*> availableActions() const;
@ -30,15 +26,24 @@ class FeedsToolBar : public BaseToolBar {
SearchLineEdit* searchBox() const;
signals:
void feedFilterChanged(FeedsProxyModel::FeedListFilter filter);
void searchCriteriaChanged(SearchLineEdit::SearchMode mode,
Qt::CaseSensitivity sensitivity,
int custom_criteria,
const QString& phrase);
private slots:
void handleMessageFilterChange(QAction* action);
private:
void initializeFilter();
void initializeSearchBox();
private:
QWidgetAction* m_actionMessageFilter;
QToolButton* m_btnMessageFilter;
QMenu* m_menuMessageFilter;
SearchLineEdit* m_txtSearchMessages;
QWidgetAction* m_actionSearchMessages;
};

View file

@ -11,10 +11,7 @@
#include <chrono>
#include <QMenu>
#include <QPainter>
#include <QTimer>
#include <QToolButton>
#include <QWidgetAction>
using namespace std::chrono_literals;
@ -155,27 +152,12 @@ void MessagesToolBar::handleMessageHighlighterChange(QAction* action) {
drawNumberOfCriterias(m_btnMessageHighlighter, int(checked_tasks_std.size()));
}
saveToolButtonSelection(QSL(HIGHLIGHTER_ACTION_NAME), FROM_STD_LIST(QList<QAction*>, checked_tasks_std));
saveToolButtonSelection(QSL(HIGHLIGHTER_ACTION_NAME),
GUI::MessagesToolbarDefaultButtons,
FROM_STD_LIST(QList<QAction*>, checked_tasks_std));
emit messageHighlighterChanged(task);
}
void MessagesToolBar::drawNumberOfCriterias(QToolButton* btn, int count) {
QPixmap px(128, 128);
px.fill(Qt::GlobalColor::transparent);
QPainter p(&px);
auto fon = p.font();
fon.setPixelSize(40);
p.setFont(fon);
p.drawPixmap(0, 0, 80, 80, btn->defaultAction()->icon().pixmap(128, 128));
p.drawText(65, 65, 50, 50, Qt::AlignmentFlag::AlignCenter, QString::number(count));
btn->setIcon(px);
}
void MessagesToolBar::handleMessageFilterChange(QAction* action) {
MessagesProxyModel::MessageListFilter task = action->data().value<MessagesProxyModel::MessageListFilter>();
std::list<QAction*> checked_tasks_std = boolinq::from(m_menuMessageFilter->actions())
@ -185,6 +167,8 @@ void MessagesToolBar::handleMessageFilterChange(QAction* action) {
.toStdList();
if (task == MessagesProxyModel::MessageListFilter::NoFiltering || checked_tasks_std.empty()) {
task = MessagesProxyModel::MessageListFilter::NoFiltering;
checked_tasks_std.clear();
// Uncheck everything.
@ -211,7 +195,9 @@ void MessagesToolBar::handleMessageFilterChange(QAction* action) {
drawNumberOfCriterias(m_btnMessageFilter, int(checked_tasks_std.size()));
}
saveToolButtonSelection(QSL(FILTER_ACTION_NAME), FROM_STD_LIST(QList<QAction*>, checked_tasks_std));
saveToolButtonSelection(QSL(FILTER_ACTION_NAME),
GUI::MessagesToolbarDefaultButtons,
FROM_STD_LIST(QList<QAction*>, checked_tasks_std));
emit messageFilterChanged(task);
}
@ -235,18 +221,6 @@ void MessagesToolBar::initializeSearchBox() {
connect(m_txtSearchMessages, &SearchLineEdit::searchCriteriaChanged, this, &MessagesToolBar::searchCriteriaChanged);
}
void MessagesToolBar::addActionToMenu(QMenu* menu,
const QIcon& icon,
const QString& title,
const QVariant& value,
const QString& name) {
QAction* action = menu->addAction(icon, title);
action->setCheckable(true);
action->setData(value);
action->setObjectName(name);
}
void MessagesToolBar::initializeHighlighter() {
m_menuMessageHighlighter = new NonClosableMenu(tr("Menu for highlighting articles"), this);
@ -357,53 +331,16 @@ void MessagesToolBar::initializeHighlighter() {
connect(m_menuMessageHighlighter, &QMenu::triggered, this, &MessagesToolBar::handleMessageHighlighterChange);
connect(m_menuMessageFilter, &QMenu::triggered, this, &MessagesToolBar::handleMessageFilterChange);
connect(this, &MessagesToolBar::toolButtonStyleChanged, this, [=](Qt::ToolButtonStyle style) {
m_btnMessageHighlighter->setToolButtonStyle(style);
m_btnMessageFilter->setToolButtonStyle(style);
});
}
void MessagesToolBar::saveToolButtonSelection(const QString& button_name, const QList<QAction*>& actions) const {
QStringList action_names = savedActions();
auto opts_list = boolinq::from(actions)
.select([](const QAction* act) {
return act->objectName();
})
.toStdList();
QStringList opts = FROM_STD_LIST(QStringList, opts_list);
for (QString& action_name : action_names) {
if (action_name.startsWith(button_name)) {
action_name = button_name + QSL("[%1]").arg(opts.join(QL1C(';')));
}
}
qApp->settings()->setValue(GROUP(GUI), GUI::MessagesToolbarDefaultButtons, action_names.join(QSL(",")));
}
SearchLineEdit* MessagesToolBar::searchBox() const {
return m_txtSearchMessages;
}
void MessagesToolBar::activateAction(const QString& action_name, QWidgetAction* widget_action) {
const int start = action_name.indexOf('[');
const int end = action_name.indexOf(']');
if (start != -1 && end != -1 && end == action_name.length() - 1) {
const QStringList menu_action_names = action_name.chopped(1).right(end - start - 1).split(QL1C(';'));
auto tool_btn = qobject_cast<QToolButton*>(widget_action->defaultWidget());
for (QAction* action : tool_btn->menu()->actions()) {
if (menu_action_names.contains(action->objectName())) {
// tool_btn->setDefaultAction(action);
action->trigger();
}
}
}
}
QStringList MessagesToolBar::defaultActions() const {
return QString(GUI::MessagesToolbarDefaultButtonsDef)
.split(QL1C(','),

View file

@ -8,8 +8,6 @@
#include "gui/reusable/searchlineedit.h"
#include "gui/toolbars/basetoolbar.h"
class QWidgetAction;
class QToolButton;
class QMenu;
class QTimer;
@ -17,11 +15,6 @@ class MessagesToolBar : public BaseToolBar {
Q_OBJECT
public:
enum class SearchFields {
SearchTitleOnly = 1,
SearchAll = 2
};
explicit MessagesToolBar(const QString& title, QWidget* parent = nullptr);
virtual QList<QAction*> availableActions() const;
@ -48,23 +41,17 @@ class MessagesToolBar : public BaseToolBar {
private:
void initializeSearchBox();
void addActionToMenu(QMenu* menu,
const QIcon& icon,
const QString& title,
const QVariant& value,
const QString& name);
void initializeHighlighter();
void activateAction(const QString& action_name, QWidgetAction* widget_action);
void saveToolButtonSelection(const QString& button_name, const QList<QAction*>& actions) const;
void drawNumberOfCriterias(QToolButton* btn, int count);
private:
QWidgetAction* m_actionMessageHighlighter;
QWidgetAction* m_actionMessageFilter;
QToolButton* m_btnMessageHighlighter;
QToolButton* m_btnMessageFilter;
QMenu* m_menuMessageHighlighter;
QWidgetAction* m_actionMessageFilter;
QToolButton* m_btnMessageFilter;
QMenu* m_menuMessageFilter;
QWidgetAction* m_actionSearchMessages;
SearchLineEdit* m_txtSearchMessages;
};

View file

@ -299,7 +299,7 @@ DVALUE(int) GUI::HeightRowFeedsDef = -1;
DKEY GUI::FeedsToolbarActions = "feeds_toolbar";
DVALUE(char*)
GUI::FeedsToolbarActionsDef = "m_actionUpdateAllItems,m_actionStopRunningItemsUpdate,m_actionPauseFeedFetching,m_"
"actionMarkAllItemsRead,spacer,search";
"actionMarkAllItemsRead,filter,spacer,search";
DKEY GUI::StatusbarActions = "status_bar";
DVALUE(char*)