Extend filtering (#678)

* Unified naming in message highlighter related code

* Added extended filtering logic

* Added UI for extended filtering

* Removed ShowOnlyUnreadMessages from Articles menu

* Added filter to messagestoolbar defaults

* Implemented QToolButton state saving

* Review fixes

* Changed titles for article filter buttons
This commit is contained in:
brkgbr 2022-04-09 07:14:25 +02:00 committed by GitHub
parent d3ec7ac4b3
commit e3096aee4f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 275 additions and 65 deletions

View file

@ -172,8 +172,8 @@ bool MessagesModel::setMessageImportantById(int id, RootItem::Importance importa
return false; return false;
} }
void MessagesModel::highlightMessages(MessagesModel::MessageHighlighter highlight) { void MessagesModel::highlightMessages(MessagesModel::MessageHighlighter highlighter) {
m_messageHighlighter = highlight; m_messageHighlighter = highlighter;
emit layoutAboutToBeChanged(); emit layoutAboutToBeChanged();
emit layoutChanged(); emit layoutChanged();
} }

View file

@ -21,7 +21,7 @@ class MessagesModel : public QSqlQueryModel, public MessagesModelSqlLayer {
public: public:
// Enum which describes basic filtering schemes // Enum which describes basic highlighting schemes
// for messages. // for messages.
enum class MessageHighlighter { enum class MessageHighlighter {
NoHighlighting = 100, NoHighlighting = 100,
@ -70,7 +70,7 @@ class MessagesModel : public QSqlQueryModel, public MessagesModelSqlLayer {
bool setBatchMessagesRestored(const QModelIndexList& messages); bool setBatchMessagesRestored(const QModelIndexList& messages);
// Highlights messages. // Highlights messages.
void highlightMessages(MessageHighlighter highlight); void highlightMessages(MessageHighlighter highlighter);
// Loads messages of given feeds. // Loads messages of given feeds.
void loadMessages(RootItem* item); void loadMessages(RootItem* item);

View file

@ -11,7 +11,7 @@
#include <QTimer> #include <QTimer>
MessagesProxyModel::MessagesProxyModel(MessagesModel* source_model, QObject* parent) MessagesProxyModel::MessagesProxyModel(MessagesModel* source_model, QObject* parent)
: QSortFilterProxyModel(parent), m_sourceModel(source_model), m_showUnreadOnly(false) { : QSortFilterProxyModel(parent), m_sourceModel(source_model), m_filter(MessageListFilter::NoFiltering) {
setObjectName(QSL("MessagesProxyModel")); setObjectName(QSL("MessagesProxyModel"));
setSortRole(Qt::ItemDataRole::EditRole); setSortRole(Qt::ItemDataRole::EditRole);
@ -100,6 +100,81 @@ bool MessagesProxyModel::lessThan(const QModelIndex& left, const QModelIndex& ri
return false; return false;
} }
bool MessagesProxyModel::filterAcceptsMessage(Message currentMessage) const {
switch (m_filter) {
case MessageListFilter::NoFiltering:
return true;
case MessageListFilter::ShowUnread:
return !currentMessage.m_isRead;
case MessageListFilter::ShowImportant:
return currentMessage.m_isImportant;
case MessageListFilter::ShowToday:
{
const QDateTime currentDateTime = QDateTime::currentDateTime();
const QDate currentDate = currentDateTime.date();
return
currentDate.startOfDay() <= currentMessage.m_created &&
currentMessage.m_created <= currentDate.endOfDay();
}
case MessageListFilter::ShowYesterday:
{
const QDateTime currentDateTime = QDateTime::currentDateTime();
const QDate currentDate = currentDateTime.date();
return
currentDate.addDays(-1).startOfDay() <= currentMessage.m_created &&
currentMessage.m_created <= currentDate.addDays(-1).endOfDay();
}
case MessageListFilter::ShowLast24Hours:
{
const QDateTime currentDateTime = QDateTime::currentDateTime();
const QDate currentDate = currentDateTime.date();
return
currentDateTime.addSecs(-24 * 60 * 60) <= currentMessage.m_created &&
currentMessage.m_created <= currentDateTime;
}
case MessageListFilter::ShowLast48Hours:
{
const QDateTime currentDateTime = QDateTime::currentDateTime();
const QDate currentDate = currentDateTime.date();
return
currentDateTime.addSecs(-48 * 60 * 60) <= currentMessage.m_created &&
currentMessage.m_created <= currentDateTime;
}
case MessageListFilter::ShowThisWeek:
{
const QDateTime currentDateTime = QDateTime::currentDateTime();
const QDate currentDate = currentDateTime.date();
return
currentDate.year() == currentMessage.m_created.date().year() &&
currentDate.weekNumber() == currentMessage.m_created.date().weekNumber();
}
case MessageListFilter::ShowLastWeek:
{
const QDateTime currentDateTime = QDateTime::currentDateTime();
const QDate currentDate = currentDateTime.date();
return
currentDate.addDays(-7).year() == currentMessage.m_created.date().year() &&
currentDate.addDays(-7).weekNumber() == currentMessage.m_created.date().weekNumber();
}
}
return false;
}
bool MessagesProxyModel::filterAcceptsRow(int source_row, const QModelIndex& source_parent) const { bool MessagesProxyModel::filterAcceptsRow(int source_row, const QModelIndex& source_parent) const {
// We want to show only regexped messages when "all" should be visible // We want to show only regexped messages when "all" should be visible
// and we want to show only regexped AND unread messages when unread should be visible. // and we want to show only regexped AND unread messages when unread should be visible.
@ -110,16 +185,11 @@ bool MessagesProxyModel::filterAcceptsRow(int source_row, const QModelIndex& sou
return return
QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent) && QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent) &&
(m_sourceModel->cache()->containsData(source_row) || (m_sourceModel->cache()->containsData(source_row) ||
(!m_showUnreadOnly || !m_sourceModel->messageAt(source_row).m_isRead)); filterAcceptsMessage(m_sourceModel->messageAt(source_row)));
} }
bool MessagesProxyModel::showUnreadOnly() const { void MessagesProxyModel::setFilter(MessageListFilter filter) {
return m_showUnreadOnly; m_filter = filter;
}
void MessagesProxyModel::setShowUnreadOnly(bool show_unread_only) {
m_showUnreadOnly = show_unread_only;
qApp->settings()->setValue(GROUP(Messages), Messages::ShowOnlyUnreadMessages, show_unread_only);
} }
QModelIndexList MessagesProxyModel::mapListFromSource(const QModelIndexList& indexes, bool deep) const { QModelIndexList MessagesProxyModel::mapListFromSource(const QModelIndexList& indexes, bool deep) const {

View file

@ -6,11 +6,27 @@
#include <QSortFilterProxyModel> #include <QSortFilterProxyModel>
class MessagesModel; class MessagesModel;
class Message;
class MessagesProxyModel : public QSortFilterProxyModel { class MessagesProxyModel : public QSortFilterProxyModel {
Q_OBJECT Q_OBJECT
public: public:
// Enum which describes basic filtering schemes
// for messages.
enum class MessageListFilter {
NoFiltering = 100,
ShowUnread = 101,
ShowImportant = 102,
ShowToday = 103,
ShowYesterday = 104,
ShowLast24Hours = 105,
ShowLast48Hours = 106,
ShowThisWeek = 107,
ShowLastWeek = 108
};
explicit MessagesProxyModel(MessagesModel* source_model, QObject* parent = nullptr); explicit MessagesProxyModel(MessagesModel* source_model, QObject* parent = nullptr);
virtual ~MessagesProxyModel(); virtual ~MessagesProxyModel();
@ -27,19 +43,21 @@ class MessagesProxyModel : public QSortFilterProxyModel {
// Performs sort of items. // Performs sort of items.
void sort(int column, Qt::SortOrder order = Qt::AscendingOrder); void sort(int column, Qt::SortOrder order = Qt::AscendingOrder);
bool showUnreadOnly() const; void setFilter(MessageListFilter filter);
void setShowUnreadOnly(bool show_unread_only);
private: private:
QModelIndex getNextImportantItemIndex(int default_row, int max_row) const; QModelIndex getNextImportantItemIndex(int default_row, int max_row) const;
QModelIndex getNextUnreadItemIndex(int default_row, int max_row) const; QModelIndex getNextUnreadItemIndex(int default_row, int max_row) const;
bool lessThan(const QModelIndex& left, const QModelIndex& right) const; bool lessThan(const QModelIndex& left, const QModelIndex& right) const;
bool filterAcceptsMessage(Message currentMessage) const;
bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const; bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const;
// Source model pointer. // Source model pointer.
MessagesModel* m_sourceModel; MessagesModel* m_sourceModel;
bool m_showUnreadOnly; MessageListFilter m_filter;
}; };
Q_DECLARE_METATYPE(MessagesProxyModel::MessageListFilter)
#endif // MESSAGESPROXYMODEL_H #endif // MESSAGESPROXYMODEL_H

View file

@ -80,6 +80,7 @@
#define FLAG_ICON_SUBFOLDER "flags" #define FLAG_ICON_SUBFOLDER "flags"
#define SEARCH_BOX_ACTION_NAME "search" #define SEARCH_BOX_ACTION_NAME "search"
#define HIGHLIGHTER_ACTION_NAME "highlighter" #define HIGHLIGHTER_ACTION_NAME "highlighter"
#define FILTER_ACTION_NAME "filter"
#define SPACER_ACTION_NAME "spacer" #define SPACER_ACTION_NAME "spacer"
#define SEPARATOR_ACTION_NAME "separator" #define SEPARATOR_ACTION_NAME "separator"
#define FILTER_WIDTH 125 #define FILTER_WIDTH 125

View file

@ -197,7 +197,6 @@ QList<QAction*> FormMain::allActions() const {
actions << m_ui->m_actionSortFeedsAlphabetically; actions << m_ui->m_actionSortFeedsAlphabetically;
actions << m_ui->m_actionShowTreeBranches; actions << m_ui->m_actionShowTreeBranches;
actions << m_ui->m_actionAutoExpandItemsWhenSelected; actions << m_ui->m_actionAutoExpandItemsWhenSelected;
actions << m_ui->m_actionShowOnlyUnreadMessages;
actions << m_ui->m_actionMarkSelectedMessagesAsRead; actions << m_ui->m_actionMarkSelectedMessagesAsRead;
actions << m_ui->m_actionMarkSelectedMessagesAsUnread; actions << m_ui->m_actionMarkSelectedMessagesAsUnread;
actions << m_ui->m_actionSwitchImportanceOfSelectedMessages; actions << m_ui->m_actionSwitchImportanceOfSelectedMessages;
@ -599,7 +598,6 @@ void FormMain::setupIcons() {
m_ui->m_actionSelectNextUnreadMessage->setIcon(icon_theme_factory->fromTheme(QSL("mail-mark-unread"))); m_ui->m_actionSelectNextUnreadMessage->setIcon(icon_theme_factory->fromTheme(QSL("mail-mark-unread")));
m_ui->m_actionSortFeedsAlphabetically->setIcon(icon_theme_factory->fromTheme(QSL("format-text-bold"))); m_ui->m_actionSortFeedsAlphabetically->setIcon(icon_theme_factory->fromTheme(QSL("format-text-bold")));
m_ui->m_actionShowOnlyUnreadItems->setIcon(icon_theme_factory->fromTheme(QSL("mail-mark-unread"))); m_ui->m_actionShowOnlyUnreadItems->setIcon(icon_theme_factory->fromTheme(QSL("mail-mark-unread")));
m_ui->m_actionShowOnlyUnreadMessages->setIcon(icon_theme_factory->fromTheme(QSL("mail-mark-unread")));
m_ui->m_actionExpandCollapseItem->setIcon(icon_theme_factory->fromTheme(QSL("format-indent-more"))); m_ui->m_actionExpandCollapseItem->setIcon(icon_theme_factory->fromTheme(QSL("format-indent-more")));
m_ui->m_actionExpandCollapseItemRecursively->setIcon(icon_theme_factory->fromTheme(QSL("format-indent-more"))); m_ui->m_actionExpandCollapseItemRecursively->setIcon(icon_theme_factory->fromTheme(QSL("format-indent-more")));
m_ui->m_actionRestoreSelectedMessages->setIcon(icon_theme_factory->fromTheme(QSL("view-refresh"))); m_ui->m_actionRestoreSelectedMessages->setIcon(icon_theme_factory->fromTheme(QSL("view-refresh")));
@ -683,8 +681,6 @@ void FormMain::loadSize() {
SETTING(Feeds::ShowTreeBranches)).toBool()); SETTING(Feeds::ShowTreeBranches)).toBool());
m_ui->m_actionAutoExpandItemsWhenSelected->setChecked(settings->value(GROUP(Feeds), m_ui->m_actionAutoExpandItemsWhenSelected->setChecked(settings->value(GROUP(Feeds),
SETTING(Feeds::AutoExpandOnSelection)).toBool()); SETTING(Feeds::AutoExpandOnSelection)).toBool());
m_ui->m_actionShowOnlyUnreadMessages->setChecked(settings->value(GROUP(Messages),
SETTING(Messages::ShowOnlyUnreadMessages)).toBool());
m_ui->m_actionAlternateColorsInLists->setChecked(settings->value(GROUP(GUI), m_ui->m_actionAlternateColorsInLists->setChecked(settings->value(GROUP(GUI),
SETTING(GUI::AlternateRowColorsInLists)).toBool()); SETTING(GUI::AlternateRowColorsInLists)).toBool());
} }
@ -876,8 +872,6 @@ void FormMain::createConnections() {
tabWidget()->feedMessageViewer(), &FeedMessageViewer::toggleItemsAutoExpandingOnSelection); tabWidget()->feedMessageViewer(), &FeedMessageViewer::toggleItemsAutoExpandingOnSelection);
connect(m_ui->m_actionAlternateColorsInLists, &QAction::toggled, connect(m_ui->m_actionAlternateColorsInLists, &QAction::toggled,
tabWidget()->feedMessageViewer(), &FeedMessageViewer::alternateRowColorsInLists); tabWidget()->feedMessageViewer(), &FeedMessageViewer::alternateRowColorsInLists);
connect(m_ui->m_actionShowOnlyUnreadMessages, &QAction::toggled,
tabWidget()->feedMessageViewer(), &FeedMessageViewer::toggleShowOnlyUnreadMessages);
connect(m_ui->m_actionRestoreSelectedMessages, &QAction::triggered, connect(m_ui->m_actionRestoreSelectedMessages, &QAction::triggered,
tabWidget()->feedMessageViewer()->messagesView(), &MessagesView::restoreSelectedMessages); tabWidget()->feedMessageViewer()->messagesView(), &MessagesView::restoreSelectedMessages);
connect(m_ui->m_actionRestoreAllRecycleBins, &QAction::triggered, connect(m_ui->m_actionRestoreAllRecycleBins, &QAction::triggered,

View file

@ -155,7 +155,6 @@
<addaction name="m_actionOpenSelectedMessagesInternallyNoTab"/> <addaction name="m_actionOpenSelectedMessagesInternallyNoTab"/>
<addaction name="m_actionSendMessageViaEmail"/> <addaction name="m_actionSendMessageViaEmail"/>
<addaction name="m_actionMessagePreviewEnabled"/> <addaction name="m_actionMessagePreviewEnabled"/>
<addaction name="m_actionShowOnlyUnreadMessages"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="m_actionSelectNextMessage"/> <addaction name="m_actionSelectNextMessage"/>
<addaction name="m_actionSelectPreviousMessage"/> <addaction name="m_actionSelectPreviousMessage"/>
@ -792,14 +791,6 @@
<string>&amp;Copy URL of selected item</string> <string>&amp;Copy URL of selected item</string>
</property> </property>
</action> </action>
<action name="m_actionShowOnlyUnreadMessages">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Show &amp;unread articles only</string>
</property>
</action>
<action name="m_actionMessageFilters"> <action name="m_actionMessageFilters">
<property name="text"> <property name="text">
<string>Article &amp;filters</string> <string>Article &amp;filters</string>

View file

@ -183,15 +183,8 @@ void FeedMessageViewer::switchFeedComponentVisibility() {
} }
} }
void FeedMessageViewer::toggleShowOnlyUnreadMessages() { void FeedMessageViewer::changeMessageFilter(MessagesProxyModel::MessageListFilter filter) {
const QAction* origin = qobject_cast<QAction*>(sender()); m_messagesView->changeFilter(filter);
if (origin == nullptr) {
m_messagesView->switchShowUnreadOnly(true, false);
}
else {
m_messagesView->switchShowUnreadOnly(true, origin->isChecked());
}
} }
void FeedMessageViewer::toggleShowOnlyUnreadFeeds() { void FeedMessageViewer::toggleShowOnlyUnreadFeeds() {
@ -244,7 +237,8 @@ void FeedMessageViewer::createConnections() {
// Filtering & searching. // Filtering & searching.
connect(m_toolBarMessages, &MessagesToolBar::messageSearchPatternChanged, m_messagesView, &MessagesView::searchMessages); connect(m_toolBarMessages, &MessagesToolBar::messageSearchPatternChanged, m_messagesView, &MessagesView::searchMessages);
connect(m_toolBarFeeds, &FeedsToolBar::feedsFilterPatternChanged, m_feedsView, &FeedsView::filterItems); connect(m_toolBarFeeds, &FeedsToolBar::feedsFilterPatternChanged, m_feedsView, &FeedsView::filterItems);
connect(m_toolBarMessages, &MessagesToolBar::messageFilterChanged, m_messagesView, &MessagesView::filterMessages); connect(m_toolBarMessages, &MessagesToolBar::messageHighlighterChanged, m_messagesView, &MessagesView::highlightMessages);
connect(m_toolBarMessages, &MessagesToolBar::messageFilterChanged, this, &FeedMessageViewer::changeMessageFilter);
connect(m_feedSplitter, &QSplitter::splitterMoved, this, &FeedMessageViewer::onFeedSplitterResized); connect(m_feedSplitter, &QSplitter::splitterMoved, this, &FeedMessageViewer::onFeedSplitterResized);
connect(m_messageSplitter, &QSplitter::splitterMoved, this, &FeedMessageViewer::onMessageSplitterResized); connect(m_messageSplitter, &QSplitter::splitterMoved, this, &FeedMessageViewer::onMessageSplitterResized);

View file

@ -6,6 +6,7 @@
#include "gui/tabcontent.h" #include "gui/tabcontent.h"
#include "core/messagesmodel.h" #include "core/messagesmodel.h"
#include "core/messagesproxymodel.h"
class WebBrowser; class WebBrowser;
class MessagePreviewer; class MessagePreviewer;
@ -57,7 +58,7 @@ class RSSGUARD_DLLSPEC FeedMessageViewer : public TabContent {
// toolbar. // toolbar.
void switchFeedComponentVisibility(); void switchFeedComponentVisibility();
void toggleShowOnlyUnreadMessages(); void changeMessageFilter(MessagesProxyModel::MessageListFilter filter);
void toggleShowOnlyUnreadFeeds(); void toggleShowOnlyUnreadFeeds();
void toggleShowFeedTreeBranches(); void toggleShowFeedTreeBranches();
void toggleItemsAutoExpandingOnSelection(); void toggleItemsAutoExpandingOnSelection();

View file

@ -499,11 +499,8 @@ void MessagesView::loadItem(RootItem* item) {
emit currentMessageRemoved(); emit currentMessageRemoved();
} }
void MessagesView::switchShowUnreadOnly(bool set_new_value, bool show_unread_only) { void MessagesView::changeFilter(MessagesProxyModel::MessageListFilter filter) {
if (set_new_value) { m_proxyModel->setFilter(filter);
m_proxyModel->setShowUnreadOnly(show_unread_only);
}
reloadSelections(); reloadSelections();
} }
@ -784,8 +781,8 @@ void MessagesView::searchMessages(const QString& pattern) {
} }
} }
void MessagesView::filterMessages(MessagesModel::MessageHighlighter filter) { void MessagesView::highlightMessages(MessagesModel::MessageHighlighter highlighter) {
m_sourceModel->highlightMessages(filter); m_sourceModel->highlightMessages(highlighter);
} }
void MessagesView::openSelectedMessagesWithExternalTool() { void MessagesView::openSelectedMessagesWithExternalTool() {

View file

@ -6,6 +6,7 @@
#include "gui/reusable/basetreeview.h" #include "gui/reusable/basetreeview.h"
#include "core/messagesmodel.h" #include "core/messagesmodel.h"
#include "core/messagesproxymodel.h"
#include "services/abstract/rootitem.h" #include "services/abstract/rootitem.h"
#include <QHeaderView> #include <QHeaderView>
@ -62,9 +63,8 @@ class MessagesView : public BaseTreeView {
// Searchs the visible message according to given pattern. // Searchs the visible message according to given pattern.
void searchMessages(const QString& pattern); void searchMessages(const QString& pattern);
void filterMessages(MessagesModel::MessageHighlighter filter); void highlightMessages(MessagesModel::MessageHighlighter highlighter);
void changeFilter(MessagesProxyModel::MessageListFilter filter);
void switchShowUnreadOnly(bool set_new_value = false, bool show_unread_only = false);
private slots: private slots:
void openSelectedMessagesWithExternalTool(); void openSelectedMessagesWithExternalTool();

View file

@ -25,6 +25,7 @@ QList<QAction*> MessagesToolBar::availableActions() const {
available_actions.append(m_actionSearchMessages); available_actions.append(m_actionSearchMessages);
available_actions.append(m_actionMessageHighlighter); available_actions.append(m_actionMessageHighlighter);
available_actions.append(m_actionMessageFilter);
return available_actions; return available_actions;
} }
@ -66,9 +67,15 @@ QList<QAction*> MessagesToolBar::convertActions(const QStringList& actions) {
// Add search box. // Add search box.
spec_actions.append(m_actionSearchMessages); spec_actions.append(m_actionSearchMessages);
} }
else if (action_name == QSL(HIGHLIGHTER_ACTION_NAME)) { else if (action_name.startsWith(QSL(HIGHLIGHTER_ACTION_NAME))) {
// Add filter button. // Add highlighter button.
spec_actions.append(m_actionMessageHighlighter); spec_actions.append(m_actionMessageHighlighter);
activateAction(action_name, m_actionMessageHighlighter);
}
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)) { else if (action_name == QSL(SPACER_ACTION_NAME)) {
// Add new spacer. // Add new spacer.
@ -99,9 +106,17 @@ void MessagesToolBar::loadSpecificActions(const QList<QAction*>& actions, bool i
} }
void MessagesToolBar::handleMessageHighlighterChange(QAction* action) { void MessagesToolBar::handleMessageHighlighterChange(QAction* action) {
m_btnMessageHighlighter->setIcon(action->icon()); m_btnMessageHighlighter->setDefaultAction(action);
m_btnMessageHighlighter->setToolTip(action->text()); saveToolButtonSelection(HIGHLIGHTER_ACTION_NAME, action);
emit messageFilterChanged(action->data().value<MessagesModel::MessageHighlighter>());
emit messageHighlighterChanged(action->data().value<MessagesModel::MessageHighlighter>());
}
void MessagesToolBar::handleMessageFilterChange(QAction* action) {
m_btnMessageFilter->setDefaultAction(action);
saveToolButtonSelection(FILTER_ACTION_NAME, action);
emit messageFilterChanged(action->data().value<MessagesProxyModel::MessageListFilter>());
} }
void MessagesToolBar::initializeSearchBox() { void MessagesToolBar::initializeSearchBox() {
@ -125,26 +140,133 @@ void MessagesToolBar::initializeSearchBox() {
}); });
} }
void MessagesToolBar::addActionToMenu(QMenu* menu, const QIcon& icon, const QString& title, const QVariant& value, const QString& name) {
QAction* action = menu->addAction(icon, title);
action->setData(value);
action->setObjectName(name);
}
void MessagesToolBar::initializeHighlighter() { void MessagesToolBar::initializeHighlighter() {
m_menuMessageHighlighter = new QMenu(tr("Menu for highlighting articles"), this); m_menuMessageHighlighter = new QMenu(tr("Menu for highlighting articles"), this);
m_menuMessageHighlighter->addAction(qApp->icons()->fromTheme(QSL("mail-mark-read")), addActionToMenu(m_menuMessageHighlighter,
tr("No extra highlighting"))->setData(QVariant::fromValue(MessagesModel::MessageHighlighter::NoHighlighting)); qApp->icons()->fromTheme(QSL("mail-mark-read")),
m_menuMessageHighlighter->addAction(qApp->icons()->fromTheme(QSL("mail-mark-unread")), tr("No extra highlighting"),
tr("Highlight unread articles"))->setData(QVariant::fromValue(MessagesModel::MessageHighlighter::HighlightUnread)); QVariant::fromValue(MessagesModel::MessageHighlighter::NoHighlighting),
m_menuMessageHighlighter->addAction(qApp->icons()->fromTheme(QSL("mail-mark-important")), "no_highlighting");
tr("Highlight important articles"))->setData(QVariant::fromValue(MessagesModel::MessageHighlighter::HighlightImportant)); addActionToMenu(m_menuMessageHighlighter,
qApp->icons()->fromTheme(QSL("mail-mark-unread")),
tr("Highlight unread articles"),
QVariant::fromValue(MessagesModel::MessageHighlighter::HighlightUnread),
"highlight_unread");
addActionToMenu(m_menuMessageHighlighter,
qApp->icons()->fromTheme(QSL("mail-mark-important")),
tr("Highlight important articles"),
QVariant::fromValue(MessagesModel::MessageHighlighter::HighlightImportant),
"highlight_important");
m_menuMessageFilter = new QMenu(tr("Menu for filtering articles"), this);
addActionToMenu(m_menuMessageFilter,
qApp->icons()->fromTheme(QSL("mail-mark-read")),
tr("No extra filtering"),
QVariant::fromValue(MessagesProxyModel::MessageListFilter::NoFiltering),
"no_filtering");
addActionToMenu(m_menuMessageFilter,
qApp->icons()->fromTheme(QSL("mail-mark-unread")),
tr("Show unread articles"),
QVariant::fromValue(MessagesProxyModel::MessageListFilter::ShowUnread),
"show_unread");
addActionToMenu(m_menuMessageFilter,
qApp->icons()->fromTheme(QSL("mail-mark-important")),
tr("Show important articles"),
QVariant::fromValue(MessagesProxyModel::MessageListFilter::ShowImportant),
"show_important");
addActionToMenu(m_menuMessageFilter,
qApp->icons()->fromTheme(QSL("mail-mark-read")),
tr("Show today's articles"),
QVariant::fromValue(MessagesProxyModel::MessageListFilter::ShowToday),
"show_today");
addActionToMenu(m_menuMessageFilter,
qApp->icons()->fromTheme(QSL("mail-mark-read")),
tr("Show yesterday's articles"),
QVariant::fromValue(MessagesProxyModel::MessageListFilter::ShowYesterday),
"show_yesterday");
addActionToMenu(m_menuMessageFilter,
qApp->icons()->fromTheme(QSL("mail-mark-read")),
tr("Show articles in last 24 hours"),
QVariant::fromValue(MessagesProxyModel::MessageListFilter::ShowLast24Hours),
"show_last24hours");
addActionToMenu(m_menuMessageFilter,
qApp->icons()->fromTheme(QSL("mail-mark-read")),
tr("Show articles in last 48 hours"),
QVariant::fromValue(MessagesProxyModel::MessageListFilter::ShowLast48Hours),
"show_last48hours");
addActionToMenu(m_menuMessageFilter,
qApp->icons()->fromTheme(QSL("mail-mark-read")),
tr("Show this week's articles"),
QVariant::fromValue(MessagesProxyModel::MessageListFilter::ShowThisWeek),
"show_this_week");
addActionToMenu(m_menuMessageFilter,
qApp->icons()->fromTheme(QSL("mail-mark-read")),
tr("Show last week's articles"),
QVariant::fromValue(MessagesProxyModel::MessageListFilter::ShowLastWeek),
"show_last_week");
m_btnMessageHighlighter = new QToolButton(this); m_btnMessageHighlighter = new QToolButton(this);
m_btnMessageHighlighter->setToolTip(tr("Display all articles")); m_btnMessageHighlighter->setToolTip(tr("Display all articles"));
m_btnMessageHighlighter->setMenu(m_menuMessageHighlighter); m_btnMessageHighlighter->setMenu(m_menuMessageHighlighter);
m_btnMessageHighlighter->setPopupMode(QToolButton::ToolButtonPopupMode::MenuButtonPopup); m_btnMessageHighlighter->setPopupMode(QToolButton::ToolButtonPopupMode::MenuButtonPopup);
m_btnMessageHighlighter->setIcon(qApp->icons()->fromTheme(QSL("mail-mark-read"))); m_btnMessageHighlighter->setIcon(qApp->icons()->fromTheme(QSL("mail-mark-read")));
m_btnMessageHighlighter->setDefaultAction(m_menuMessageHighlighter->actions().front());
m_btnMessageFilter = new QToolButton(this);
m_btnMessageFilter->setToolTip(tr("Display all articles"));
m_btnMessageFilter->setMenu(m_menuMessageFilter);
m_btnMessageFilter->setPopupMode(QToolButton::ToolButtonPopupMode::MenuButtonPopup);
m_btnMessageFilter->setIcon(qApp->icons()->fromTheme(QSL("mail-mark-read")));
m_btnMessageFilter->setDefaultAction(m_menuMessageFilter->actions().front());
m_actionMessageHighlighter = new QWidgetAction(this); m_actionMessageHighlighter = new QWidgetAction(this);
m_actionMessageHighlighter->setDefaultWidget(m_btnMessageHighlighter); m_actionMessageHighlighter->setDefaultWidget(m_btnMessageHighlighter);
m_actionMessageHighlighter->setIcon(m_btnMessageHighlighter->icon()); m_actionMessageHighlighter->setIcon(m_btnMessageHighlighter->icon());
m_actionMessageHighlighter->setProperty("type", HIGHLIGHTER_ACTION_NAME); m_actionMessageHighlighter->setProperty("type", HIGHLIGHTER_ACTION_NAME);
m_actionMessageHighlighter->setProperty("name", tr("Article highlighter")); m_actionMessageHighlighter->setProperty("name", tr("Article highlighter"));
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("Article filter"));
connect(m_menuMessageHighlighter, &QMenu::triggered, this, &MessagesToolBar::handleMessageHighlighterChange); connect(m_menuMessageHighlighter, &QMenu::triggered, this, &MessagesToolBar::handleMessageHighlighterChange);
connect(m_menuMessageFilter, &QMenu::triggered, this, &MessagesToolBar::handleMessageFilterChange);
}
void MessagesToolBar::saveToolButtonSelection(const QString& button_name, const QAction* action) const {
QStringList action_names = savedActions();
for (QString& action_name : action_names) {
if (action_name.startsWith(button_name)) {
action_name = button_name + (action->objectName().isEmpty() ? "" : "[" + action->objectName().toStdString() + "]").c_str();
}
}
qApp->settings()->setValue(GROUP(GUI), GUI::MessagesToolbarDefaultButtons, action_names.join(QSL(",")));
}
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 QString menu_action_name = action_name.chopped(1).right(end - start - 1);
auto toolButton = qobject_cast<QToolButton*>(widget_action->defaultWidget());
for (QAction* action : toolButton->menu()->actions()) {
if (action->objectName() == menu_action_name) {
toolButton->setDefaultAction(action);
toolButton->menu()->triggered(action);
break;
}
}
}
} }
QStringList MessagesToolBar::defaultActions() const { QStringList MessagesToolBar::defaultActions() const {

View file

@ -6,6 +6,7 @@
#include "gui/toolbars/basetoolbar.h" #include "gui/toolbars/basetoolbar.h"
#include "core/messagesmodel.h" #include "core/messagesmodel.h"
#include "core/messagesproxymodel.h"
class BaseLineEdit; class BaseLineEdit;
class QWidgetAction; class QWidgetAction;
@ -29,20 +30,28 @@ class MessagesToolBar : public BaseToolBar {
signals: signals:
void messageSearchPatternChanged(const QString& pattern); void messageSearchPatternChanged(const QString& pattern);
void messageFilterChanged(MessagesModel::MessageHighlighter filter); void messageHighlighterChanged(MessagesModel::MessageHighlighter highlighter);
void messageFilterChanged(MessagesProxyModel::MessageListFilter filter);
private slots: private slots:
void onSearchPatternChanged(const QString& search_pattern); void onSearchPatternChanged(const QString& search_pattern);
void handleMessageHighlighterChange(QAction* action); void handleMessageHighlighterChange(QAction* action);
void handleMessageFilterChange(QAction* action);
private: private:
void initializeSearchBox(); void initializeSearchBox();
void addActionToMenu(QMenu* menu, const QIcon& icon, const QString& title, const QVariant& value, const QString& name);
void initializeHighlighter(); void initializeHighlighter();
void activateAction(const QString& action_name, QWidgetAction* widget_action);
void saveToolButtonSelection(const QString& button_name, const QAction* action) const;
private: private:
QWidgetAction* m_actionMessageHighlighter; QWidgetAction* m_actionMessageHighlighter;
QWidgetAction* m_actionMessageFilter;
QToolButton* m_btnMessageHighlighter; QToolButton* m_btnMessageHighlighter;
QToolButton* m_btnMessageFilter;
QMenu* m_menuMessageHighlighter; QMenu* m_menuMessageHighlighter;
QMenu* m_menuMessageFilter;
QWidgetAction* m_actionSearchMessages; QWidgetAction* m_actionSearchMessages;
BaseLineEdit* m_txtSearchMessages; BaseLineEdit* m_txtSearchMessages;
QTimer* m_tmrSearchPattern; QTimer* m_tmrSearchPattern;

View file

@ -6,6 +6,7 @@
#include "gui/toolbars/basetoolbar.h" #include "gui/toolbars/basetoolbar.h"
#include <QKeyEvent> #include <QKeyEvent>
#include <QWidgetAction>
ToolBarEditor::ToolBarEditor(QWidget* parent) ToolBarEditor::ToolBarEditor(QWidget* parent)
: QWidget(parent), m_ui(new Ui::ToolBarEditor), m_toolBar(nullptr) { : QWidget(parent), m_ui(new Ui::ToolBarEditor), m_toolBar(nullptr) {
@ -86,6 +87,18 @@ void ToolBarEditor::loadEditor(const QList<QAction*>& activated_actions, const Q
action_item->setData(Qt::ItemDataRole::UserRole, action->objectName()); action_item->setData(Qt::ItemDataRole::UserRole, action->objectName());
action_item->setToolTip(action->toolTip()); action_item->setToolTip(action->toolTip());
} }
if (auto widgetAction = qobject_cast<const QWidgetAction*>(action); widgetAction) {
if (auto toolButton = qobject_cast<const QToolButton*>(widgetAction->defaultWidget()); toolButton) {
if (const QAction* action = toolButton->defaultAction(); action) {
const QString objectName = action->objectName();
const QString name = action_item->data(Qt::ItemDataRole::UserRole).toString() +
(objectName.isEmpty() ? "" : "[" + objectName.toStdString() + "]").c_str();
action_item->setData(Qt::ItemDataRole::UserRole, name);
}
}
}
} }
for (QAction* action : available_actions) { for (QAction* action : available_actions) {

View file

@ -281,7 +281,7 @@ DVALUE(bool) GUI::HideTabBarIfOnlyOneTabDef = false;
DKEY GUI::MessagesToolbarDefaultButtons = "messages_toolbar"; DKEY GUI::MessagesToolbarDefaultButtons = "messages_toolbar";
DVALUE(char*) GUI::MessagesToolbarDefaultButtonsDef = DVALUE(char*) GUI::MessagesToolbarDefaultButtonsDef =
"m_actionMarkSelectedMessagesAsRead,m_actionMarkSelectedMessagesAsUnread,m_actionSwitchImportanceOfSelectedMessages,separator,highlighter,spacer,search"; "m_actionMarkSelectedMessagesAsRead,m_actionMarkSelectedMessagesAsUnread,m_actionSwitchImportanceOfSelectedMessages,separator,highlighter,filter,spacer,search";
DKEY GUI::DefaultSortColumnFeeds = "default_sort_column_feeds"; DKEY GUI::DefaultSortColumnFeeds = "default_sort_column_feeds";
DVALUE(int) GUI::DefaultSortColumnFeedsDef = FDS_MODEL_TITLE_INDEX; DVALUE(int) GUI::DefaultSortColumnFeedsDef = FDS_MODEL_TITLE_INDEX;