Falkon Develop
Cross-platform Qt-based web browser
statusbar.cpp
Go to the documentation of this file.
1/* ============================================================
2* Falkon - Qt web browser
3* Copyright (C) 2010-2018 David Rosca <nowrep@gmail.com>
4*
5* This program is free software: you can redistribute it and/or modify
6* it under the terms of the GNU General Public License as published by
7* the Free Software Foundation, either version 3 of the License, or
8* (at your option) any later version.
9*
10* This program is distributed in the hope that it will be useful,
11* but WITHOUT ANY WARRANTY; without even the implied warranty of
12* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13* GNU General Public License for more details.
14*
15* You should have received a copy of the GNU General Public License
16* along with this program. If not, see <http://www.gnu.org/licenses/>.
17* ============================================================ */
18#include "statusbar.h"
19#include "browserwindow.h"
20#include "tabwidget.h"
21#include "tabbedwebview.h"
22#include "mainapplication.h"
23#include "webpage.h"
24#include "proxystyle.h"
25#include "qztools.h"
27#include "clickablelabel.h"
28
29#include <QStyleOptionFrame>
30#include <QToolTip>
31#include <QStylePainter>
32#include <QTimer>
33#include <QMouseEvent>
34
36{
37public:
38 explicit StatusBarButton(AbstractButtonInterface *button, QWidget *parent = nullptr);
39
40private:
41 void clicked();
42 void updateIcon();
43 void updateToolTip();
44
46};
47
49 : ClickableLabel(parent)
50 , m_button(button)
51{
52 setFixedSize(16, 16);
53 setCursor(Qt::PointingHandCursor);
54
55 updateIcon();
56 updateToolTip();
57 setVisible(m_button->isVisible());
58
59 connect(this, &ClickableLabel::clicked, this, &StatusBarButton::clicked);
60 connect(m_button, &AbstractButtonInterface::iconChanged, this, &StatusBarButton::updateIcon);
61 connect(m_button, &AbstractButtonInterface::activeChanged, this, &StatusBarButton::updateIcon);
62 connect(m_button, &AbstractButtonInterface::toolTipChanged, this, &StatusBarButton::updateToolTip);
63 connect(m_button, &AbstractButtonInterface::badgeTextChanged, this, &StatusBarButton::updateToolTip);
64 connect(m_button, &AbstractButtonInterface::visibleChanged, this, &StatusBarButton::setVisible);
65}
66
67void StatusBarButton::clicked()
68{
70 c->visualParent = this;
71 c->popupPosition = [=](const QSize &size) {
72 QPoint pos = mapToGlobal(rect().topRight());
73 if (QApplication::isRightToLeft()) {
74 pos.setX(pos.x() - rect().width());
75 } else {
76 pos.setX(pos.x() - size.width());
77 }
78 pos.setY(pos.y() - size.height());
79 c->popupOpened = true;
80 return pos;
81 };
82 c->popupClosed = [=]() {
83 delete c;
84 };
85 Q_EMIT m_button->clicked(c);
86 if (!c->popupOpened) {
87 c->popupClosed();
88 }
89}
90
91void StatusBarButton::updateIcon()
92{
93 const QIcon::Mode mode = m_button->isActive() ? QIcon::Normal : QIcon::Disabled;
94 const QImage img = m_button->icon().pixmap(size(), mode).toImage();
95 setPixmap(QPixmap::fromImage(img, Qt::MonoOnly));
96}
97
98void StatusBarButton::updateToolTip()
99{
100 QString text = m_button->toolTip();
101 if (!m_button->badgeText().isEmpty()) {
102 text.append(QSL(" (%1)").arg(m_button->badgeText()));
103 }
104 setToolTip(text);
105}
106
107TipLabel::TipLabel(QWidget* parent)
108 : SqueezeLabelV1(parent)
109{
110 setWindowFlags(Qt::ToolTip);
111 setForegroundRole(QPalette::ToolTipText);
112 setBackgroundRole(QPalette::ToolTipBase);
113 setPalette(QToolTip::palette());
114 ensurePolished();
115 setFrameStyle(QFrame::NoFrame);
116 setContentsMargins(3, 3, 3, 3);
117
118 m_timer = new QTimer(this);
119 m_timer->setSingleShot(true);
120 m_timer->setInterval(500);
121 connect(m_timer, &QTimer::timeout, this, &QWidget::hide);
122}
123
124void TipLabel::show(QWidget* widget)
125{
126 m_timer->stop();
127
128 widget->installEventFilter(this);
129 SqueezeLabelV1::show();
130}
131
133{
134 m_timer->start();
135}
136
137void TipLabel::paintEvent(QPaintEvent* ev)
138{
139 QStylePainter p(this);
140 QStyleOptionFrame opt;
141 opt.initFrom(this);
142 p.drawPrimitive(QStyle::PE_PanelTipLabel, opt);
143 p.end();
144
146}
147
148bool TipLabel::eventFilter(QObject* o, QEvent* e)
149{
150 Q_UNUSED(o);
151
152 switch (e->type()) {
153 case QEvent::Leave:
154 case QEvent::WindowDeactivate:
155 case QEvent::Wheel:
156 hide();
157 break;
158
159 case QEvent::MouseMove:
160 case QEvent::MouseButtonPress:
161 case QEvent::MouseButtonRelease:
162 if (o == this)
163 hide();
164 break;
165
166 default:
167 break;
168 }
169
170 return false;
171}
172
174 : m_window(window)
175 , m_statusBarText(new TipLabel(window))
176{
177}
178
179void StatusBar::showMessage(const QString &message, int timeout)
180{
181 if (isVisible()) {
182 const static QChar LRE(0x202a);
183 QStatusBar::showMessage(message.isRightToLeft() ? message : (LRE + message), timeout);
184 return;
185 }
186
187 if (mApp->activeWindow() != m_window) {
188 return;
189 }
190
191 WebView* view = m_window->weView();
192
193 const int verticalScrollSize = view->scrollBarGeometry(Qt::Vertical).width();;
194 const int horizontalScrollSize = view->scrollBarGeometry(Qt::Horizontal).height();
195
196 m_statusBarText->setText(message);
197 m_statusBarText->setMaximumWidth(view->width() - verticalScrollSize);
198 m_statusBarText->resize(m_statusBarText->sizeHint());
199
200 QPoint position(0, view->height() - horizontalScrollSize - m_statusBarText->height());
201 const QRect statusRect = QRect(view->mapToGlobal(QPoint(0, position.y())), m_statusBarText->size());
202
203 if (statusRect.contains(QCursor::pos())) {
204 position.setY(position.y() - m_statusBarText->height());
205 }
206
207 m_statusBarText->move(view->mapToGlobal(position));
208 m_statusBarText->show(view);
209}
210
212{
213 QStatusBar::clearMessage();
214 m_statusBarText->hideDelayed();
215}
216
218{
219 if (!button || !button->isValid()) {
220 return;
221 }
222
223 auto *widget = new StatusBarButton(button, this);
224 widget->setProperty("button-id", button->id());
225
226 WidgetData data;
227 data.id = button->id();
228 data.widget = widget;
229 data.button = button;
230 m_widgets[data.id] = data;
231
232 addPermanentWidget(widget);
233}
234
236{
237 if (!button || !m_widgets.contains(button->id())) {
238 return;
239 }
240
241 delete m_widgets.take(button->id()).widget;
242}
243
244void StatusBar::mousePressEvent(QMouseEvent *event)
245{
246 if (event->button() == Qt::RightButton) {
247 QMenu context;
248 context.addAction(tr("Hide"), m_window, &BrowserWindow::toggleShowStatusBar);
249 context.exec(QCursor::pos());
250 }
251
252 QStatusBar::mousePressEvent(event);
253}
virtual QString id() const =0
void iconChanged(const QIcon &icon)
void clicked(AbstractButtonInterface::ClickController *controller)
void badgeTextChanged(const QString &badgeText)
void activeChanged(bool active)
void visibleChanged(bool visible)
void toolTipChanged(const QString &toolTip)
void toggleShowStatusBar()
TabbedWebView * weView() const
void clicked(QPoint)
void paintEvent(QPaintEvent *event) override
StatusBarButton(AbstractButtonInterface *button, QWidget *parent=nullptr)
Definition: statusbar.cpp:48
void clearMessage()
Definition: statusbar.cpp:211
void mousePressEvent(QMouseEvent *event) override
Definition: statusbar.cpp:244
StatusBar(BrowserWindow *window)
Definition: statusbar.cpp:173
void addButton(AbstractButtonInterface *button)
Definition: statusbar.cpp:217
void removeButton(AbstractButtonInterface *button)
Definition: statusbar.cpp:235
void showMessage(const QString &message, int timeout=0)
Definition: statusbar.cpp:179
bool eventFilter(QObject *o, QEvent *e) override
Definition: statusbar.cpp:148
TipLabel(QWidget *parent)
Definition: statusbar.cpp:107
void show(QWidget *widget)
Definition: statusbar.cpp:124
void hideDelayed()
Definition: statusbar.cpp:132
QRect scrollBarGeometry(Qt::Orientation orientation) const
Definition: webview.cpp:245
#define mApp
#define QSL(x)
Definition: qzcommon.h:40