1 // For license of this file, see <project-root-folder>/LICENSE.md.
2 
3 #include "gui/toolbars/statusbar.h"
4 
5 #include "gui/dialogs/formmain.h"
6 #include "gui/reusable/plaintoolbutton.h"
7 #include "gui/reusable/progressbarwithtext.h"
8 #include "gui/tabwidget.h"
9 #include "miscellaneous/iconfactory.h"
10 #include "miscellaneous/mutex.h"
11 
12 #include <QLabel>
13 #include <QToolButton>
14 
StatusBar(QWidget * parent)15 StatusBar::StatusBar(QWidget* parent) : QStatusBar(parent) {
16   setSizeGripEnabled(false);
17   setContentsMargins(2, 0, 2, 2);
18 
19   m_barProgressFeeds = new ProgressBarWithText(this);
20   m_barProgressFeeds->setTextVisible(true);
21   m_barProgressFeeds->setFixedWidth(230);
22   m_barProgressFeeds->setVisible(false);
23   m_barProgressFeeds->setObjectName(QSL("m_barProgressFeeds"));
24 
25   m_barProgressFeedsAction = new QAction(qApp->icons()->fromTheme(QSL("application-rss+xml")), tr("Feed update progress bar"), this);
26   m_barProgressFeedsAction->setObjectName(QSL("m_barProgressFeedsAction"));
27 
28   m_barProgressDownload = new ProgressBarWithText(this);
29   m_barProgressDownload->setTextVisible(true);
30   m_barProgressDownload->setFixedWidth(230);
31   m_barProgressDownload->setVisible(false);
32   m_barProgressDownload->setObjectName(QSL("m_barProgressDownload"));
33 
34   m_barProgressDownloadAction = new QAction(qApp->icons()->fromTheme(QSL("emblem-downloads")), tr("File download progress bar"), this);
35   m_barProgressDownloadAction->setObjectName(QSL("m_barProgressDownloadAction"));
36 
37   m_barProgressDownload->installEventFilter(this);
38 }
39 
~StatusBar()40 StatusBar::~StatusBar() {
41   clear();
42   qDebugNN << LOGSEC_GUI "Destroying StatusBar instance.";
43 }
44 
availableActions() const45 QList<QAction*> StatusBar::availableActions() const {
46   QList<QAction*> actions = qApp->userActions();
47 
48   // Now, add placeholder actions for custom stuff.
49   actions << m_barProgressDownloadAction
50           << m_barProgressFeedsAction;
51 
52   return actions;
53 }
54 
activatedActions() const55 QList<QAction*> StatusBar::activatedActions() const {
56   return actions();
57 }
58 
saveAndSetActions(const QStringList & actions)59 void StatusBar::saveAndSetActions(const QStringList& actions) {
60   qApp->settings()->setValue(GROUP(GUI), GUI::StatusbarActions, actions.join(QSL(",")));
61   loadSpecificActions(convertActions(actions));
62 }
63 
defaultActions() const64 QStringList StatusBar::defaultActions() const {
65   return QString(GUI::StatusbarActionsDef).split(',',
66 #if QT_VERSION >= 0x050F00 // Qt >= 5.15.0
67                                                  Qt::SplitBehaviorFlags::SkipEmptyParts);
68 #else
69                                                  QString::SplitBehavior::SkipEmptyParts);
70 #endif
71 }
72 
savedActions() const73 QStringList StatusBar::savedActions() const {
74   return qApp->settings()->value(GROUP(GUI),
75                                  SETTING(GUI::StatusbarActions)).toString().split(',',
76 #if QT_VERSION >= 0x050F00 // Qt >= 5.15.0
77                                                                                   Qt::SplitBehaviorFlags::SkipEmptyParts);
78 #else
79                                                                                   QString::SplitBehavior::SkipEmptyParts);
80 #endif
81 }
82 
convertActions(const QStringList & actions)83 QList<QAction*> StatusBar::convertActions(const QStringList& actions) {
84   bool progress_visible = this->actions().contains(m_barProgressFeedsAction) && m_barProgressFeeds->isVisible();
85   QList<QAction*> available_actions = availableActions();
86   QList<QAction*> spec_actions;
87 
88   // Iterate action names and add respectable
89   // actions into the toolbar.
90   for (const QString& action_name : actions) {
91     QAction* matching_action = findMatchingAction(action_name, available_actions);
92     QAction* action_to_add;
93     QWidget* widget_to_add;
94 
95     if (matching_action == m_barProgressDownloadAction) {
96       widget_to_add = m_barProgressDownload;
97       action_to_add = m_barProgressDownloadAction;
98       widget_to_add->setVisible(false);
99     }
100     else if (matching_action == m_barProgressFeedsAction) {
101       widget_to_add = m_barProgressFeeds;
102       action_to_add = m_barProgressFeedsAction;
103       widget_to_add->setVisible(progress_visible);
104     }
105     else {
106       if (action_name == QSL(SEPARATOR_ACTION_NAME)) {
107         QLabel* lbl = new QLabel(QSL("•"), this);
108 
109         widget_to_add = lbl;
110         action_to_add = new QAction(this);
111         action_to_add->setSeparator(true);
112       }
113       else if (action_name == QSL(SPACER_ACTION_NAME)) {
114         QLabel* lbl = new QLabel(QSL("\t\t"), this);
115 
116         widget_to_add = lbl;
117         action_to_add = new QAction(this);
118         action_to_add->setIcon(qApp->icons()->fromTheme(QSL("system-search")));
119         action_to_add->setProperty("type", SPACER_ACTION_NAME);
120         action_to_add->setProperty("name", tr("Toolbar spacer"));
121       }
122       else if (matching_action != nullptr) {
123         // Add originally toolbar action.
124         auto* tool_button = new PlainToolButton(this);
125 
126         tool_button->reactOnActionChange(matching_action);
127         widget_to_add = tool_button;
128         action_to_add = matching_action;
129         connect(tool_button, &PlainToolButton::clicked, matching_action, &QAction::trigger);
130         connect(matching_action, &QAction::changed, tool_button, &PlainToolButton::reactOnSenderActionChange);
131       }
132       else {
133         action_to_add = nullptr;
134         widget_to_add = nullptr;
135       }
136     }
137 
138     if (action_to_add != nullptr && widget_to_add != nullptr) {
139       action_to_add->setProperty("widget", QVariant::fromValue(widget_to_add));
140       spec_actions.append(action_to_add);
141     }
142   }
143 
144   return spec_actions;
145 }
146 
loadSpecificActions(const QList<QAction * > & actions,bool initial_load)147 void StatusBar::loadSpecificActions(const QList<QAction*>& actions, bool initial_load) {
148   if (initial_load) {
149     clear();
150 
151     for (QAction* act : actions) {
152       QWidget* widget = act->property("widget").isValid() ? qvariant_cast<QWidget*>(act->property("widget")) : nullptr;
153 
154       addAction(act);
155 
156       // And also add widget.
157       if (widget != nullptr) {
158         addPermanentWidget(widget);
159       }
160     }
161   }
162 }
163 
eventFilter(QObject * watched,QEvent * event)164 bool StatusBar::eventFilter(QObject* watched, QEvent* event) {
165   if (watched == m_barProgressDownload) {
166     if (event->type() == QEvent::Type::MouseButtonPress) {
167       qApp->mainForm()->tabWidget()->showDownloadManager();
168     }
169   }
170 
171   return false;
172 }
173 
clear()174 void StatusBar::clear() {
175   while (!actions().isEmpty()) {
176     QAction* act = actions().at(0);
177     QWidget* widget = act->property("widget").isValid() ? static_cast<QWidget*>(act->property("widget").value<void*>()) : nullptr;
178 
179     if (widget != nullptr) {
180       removeWidget(widget);
181 
182       widget->setParent(qApp->mainFormWidget());
183       widget->setVisible(false);
184     }
185 
186     removeAction(act);
187   }
188 }
189 
showProgressFeeds(int progress,const QString & label)190 void StatusBar::showProgressFeeds(int progress, const QString& label) {
191   if (actions().contains(m_barProgressFeedsAction)) {
192     m_barProgressFeeds->setVisible(true);
193     m_barProgressFeeds->setFormat(label);
194 
195     if (progress < 0) {
196       m_barProgressFeeds->setRange(0, 0);
197     }
198     else {
199       m_barProgressFeeds->setRange(0, 100);
200       m_barProgressFeeds->setValue(progress);
201     }
202   }
203 }
204 
clearProgressFeeds()205 void StatusBar::clearProgressFeeds() {
206   m_barProgressFeeds->setVisible(false);
207 }
208 
showProgressDownload(int progress,const QString & tooltip)209 void StatusBar::showProgressDownload(int progress, const QString& tooltip) {
210   if (actions().contains(m_barProgressDownloadAction)) {
211     m_barProgressDownload->setVisible(true);
212     m_barProgressDownload->setFormat(tooltip);
213     m_barProgressDownload->setToolTip(tooltip);
214 
215     if (progress < 0) {
216       m_barProgressDownload->setRange(0, 0);
217     }
218     else {
219       m_barProgressDownload->setRange(0, 100);
220       m_barProgressDownload->setValue(progress);
221     }
222   }
223 }
224 
clearProgressDownload()225 void StatusBar::clearProgressDownload() {
226   m_barProgressDownload->setVisible(false);
227   m_barProgressDownload->setValue(0);
228 }
229