1 // For license of this file, see <project-root-folder>/LICENSE.md.
2
3 #include "gui/toolbars/messagestoolbar.h"
4
5 #include "definitions/definitions.h"
6 #include "gui/reusable/baselineedit.h"
7 #include "miscellaneous/iconfactory.h"
8 #include "miscellaneous/settings.h"
9
10 #include <chrono>
11 #include <QMenu>
12 #include <QTimer>
13 #include <QToolButton>
14 #include <QWidgetAction>
15
16 using namespace std::chrono_literals;
17
MessagesToolBar(const QString & title,QWidget * parent)18 MessagesToolBar::MessagesToolBar(const QString& title, QWidget* parent) : BaseToolBar(title, parent) {
19 initializeSearchBox();
20 initializeHighlighter();
21 }
22
availableActions() const23 QList<QAction*> MessagesToolBar::availableActions() const {
24 QList<QAction*> available_actions = qApp->userActions();
25
26 available_actions.append(m_actionSearchMessages);
27 available_actions.append(m_actionMessageHighlighter);
28
29 return available_actions;
30 }
31
activatedActions() const32 QList<QAction*> MessagesToolBar::activatedActions() const {
33 return actions();
34 }
35
saveAndSetActions(const QStringList & actions)36 void MessagesToolBar::saveAndSetActions(const QStringList& actions) {
37 qApp->settings()->setValue(GROUP(GUI), GUI::MessagesToolbarDefaultButtons, actions.join(QSL(",")));
38 loadSpecificActions(convertActions(actions));
39
40 // If user hidden search messages box, then remove the filter.
41 if (!activatedActions().contains(m_actionSearchMessages)) {
42 m_txtSearchMessages->clear();
43 }
44 }
45
convertActions(const QStringList & actions)46 QList<QAction*> MessagesToolBar::convertActions(const QStringList& actions) {
47 QList<QAction*> available_actions = availableActions();
48 QList<QAction*> spec_actions;
49
50 // Iterate action names and add respectable actions into the toolbar.
51 for (const QString& action_name : actions) {
52 auto* matching_action = findMatchingAction(action_name, available_actions);
53
54 if (matching_action != nullptr) {
55 // Add existing standard action.
56 spec_actions.append(matching_action);
57 }
58 else if (action_name == QSL(SEPARATOR_ACTION_NAME)) {
59 // Add new separator.
60 auto* act = new QAction(this);
61
62 act->setSeparator(true);
63 spec_actions.append(act);
64 }
65 else if (action_name == QSL(SEARCH_BOX_ACTION_NAME)) {
66 // Add search box.
67 spec_actions.append(m_actionSearchMessages);
68 }
69 else if (action_name == QSL(HIGHLIGHTER_ACTION_NAME)) {
70 // Add filter button.
71 spec_actions.append(m_actionMessageHighlighter);
72 }
73 else if (action_name == QSL(SPACER_ACTION_NAME)) {
74 // Add new spacer.
75 auto* spacer = new QWidget(this);
76
77 spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
78 auto* action = new QWidgetAction(this);
79
80 action->setDefaultWidget(spacer);
81 action->setIcon(qApp->icons()->fromTheme(QSL("go-jump")));
82 action->setProperty("type", SPACER_ACTION_NAME);
83 action->setProperty("name", tr("Toolbar spacer"));
84 spec_actions.append(action);
85 }
86 }
87
88 return spec_actions;
89 }
90
loadSpecificActions(const QList<QAction * > & actions,bool initial_load)91 void MessagesToolBar::loadSpecificActions(const QList<QAction*>& actions, bool initial_load) {
92 Q_UNUSED(initial_load)
93
94 clear();
95
96 for (QAction* act : actions) {
97 addAction(act);
98 }
99 }
100
handleMessageHighlighterChange(QAction * action)101 void MessagesToolBar::handleMessageHighlighterChange(QAction* action) {
102 m_btnMessageHighlighter->setIcon(action->icon());
103 m_btnMessageHighlighter->setToolTip(action->text());
104 emit messageFilterChanged(action->data().value<MessagesModel::MessageHighlighter>());
105 }
106
initializeSearchBox()107 void MessagesToolBar::initializeSearchBox() {
108 m_tmrSearchPattern = new QTimer(this);
109 m_tmrSearchPattern->setSingleShot(true);
110
111 m_txtSearchMessages = new BaseLineEdit(this);
112 m_txtSearchMessages->setSizePolicy(QSizePolicy::Policy::Expanding, m_txtSearchMessages->sizePolicy().verticalPolicy());
113 m_txtSearchMessages->setPlaceholderText(tr("Search articles"));
114
115 // Setup wrapping action for search box.
116 m_actionSearchMessages = new QWidgetAction(this);
117 m_actionSearchMessages->setDefaultWidget(m_txtSearchMessages);
118 m_actionSearchMessages->setIcon(qApp->icons()->fromTheme(QSL("system-search")));
119 m_actionSearchMessages->setProperty("type", SEARCH_BOX_ACTION_NAME);
120 m_actionSearchMessages->setProperty("name", tr("Article search box"));
121
122 connect(m_txtSearchMessages, &BaseLineEdit::textChanged, this, &MessagesToolBar::onSearchPatternChanged);
123 connect(m_tmrSearchPattern, &QTimer::timeout, this, [this]() {
124 emit messageSearchPatternChanged(m_searchPattern);
125 });
126 }
127
initializeHighlighter()128 void MessagesToolBar::initializeHighlighter() {
129 m_menuMessageHighlighter = new QMenu(tr("Menu for highlighting articles"), this);
130 m_menuMessageHighlighter->addAction(qApp->icons()->fromTheme(QSL("mail-mark-read")),
131 tr("No extra highlighting"))->setData(QVariant::fromValue(MessagesModel::MessageHighlighter::NoHighlighting));
132 m_menuMessageHighlighter->addAction(qApp->icons()->fromTheme(QSL("mail-mark-unread")),
133 tr("Highlight unread articles"))->setData(QVariant::fromValue(MessagesModel::MessageHighlighter::HighlightUnread));
134 m_menuMessageHighlighter->addAction(qApp->icons()->fromTheme(QSL("mail-mark-important")),
135 tr("Highlight important articles"))->setData(QVariant::fromValue(MessagesModel::MessageHighlighter::HighlightImportant));
136 m_btnMessageHighlighter = new QToolButton(this);
137 m_btnMessageHighlighter->setToolTip(tr("Display all articles"));
138 m_btnMessageHighlighter->setMenu(m_menuMessageHighlighter);
139 m_btnMessageHighlighter->setPopupMode(QToolButton::ToolButtonPopupMode::MenuButtonPopup);
140 m_btnMessageHighlighter->setIcon(qApp->icons()->fromTheme(QSL("mail-mark-read")));
141 m_actionMessageHighlighter = new QWidgetAction(this);
142 m_actionMessageHighlighter->setDefaultWidget(m_btnMessageHighlighter);
143 m_actionMessageHighlighter->setIcon(m_btnMessageHighlighter->icon());
144 m_actionMessageHighlighter->setProperty("type", HIGHLIGHTER_ACTION_NAME);
145 m_actionMessageHighlighter->setProperty("name", tr("Article highlighter"));
146
147 connect(m_menuMessageHighlighter, &QMenu::triggered, this, &MessagesToolBar::handleMessageHighlighterChange);
148 }
149
defaultActions() const150 QStringList MessagesToolBar::defaultActions() const {
151 return QString(GUI::MessagesToolbarDefaultButtonsDef).split(QL1C(','),
152 #if QT_VERSION >= 0x050F00 // Qt >= 5.15.0
153 Qt::SplitBehaviorFlags::SkipEmptyParts);
154 #else
155 QString::SplitBehavior::SkipEmptyParts);
156 #endif
157 }
158
savedActions() const159 QStringList MessagesToolBar::savedActions() const {
160 return qApp->settings()->value(GROUP(GUI),
161 SETTING(GUI::MessagesToolbarDefaultButtons)).toString().split(QL1C(','),
162 #if QT_VERSION >= 0x050F00 // Qt >= 5.15.0
163 Qt::SplitBehaviorFlags::SkipEmptyParts);
164 #else
165 QString::SplitBehavior::SkipEmptyParts);
166 #endif
167 }
168
onSearchPatternChanged(const QString & search_pattern)169 void MessagesToolBar::onSearchPatternChanged(const QString& search_pattern) {
170 m_searchPattern = search_pattern;
171 m_tmrSearchPattern->start(search_pattern.isEmpty() ? 0ms : 300ms);
172 }
173