Falkon Develop
Cross-platform Qt-based web browser
toolbutton.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 "toolbutton.h"
19
20#include <QMenu>
21#include <QStyle>
22#include <QPainter>
23#include <QMouseEvent>
24#include <QApplication>
25#include <QStyleOptionToolButton>
26
27ToolButton::ToolButton(QWidget* parent)
28 : QToolButton(parent)
29 , m_menu(nullptr)
30{
31 setMinimumWidth(16);
32
33 QStyleOptionToolButton opt;
34 initStyleOption(&opt);
35
36 m_pressTimer.setSingleShot(true);
37 m_pressTimer.setInterval(QApplication::style()->styleHint(QStyle::SH_ToolButton_PopupDelay, &opt, this));
38 connect(&m_pressTimer, SIGNAL(timeout()), this, SLOT(showMenu()));
39}
40
42{
43 return m_multiIcon;
44}
45
46void ToolButton::setMultiIcon(const QImage &image)
47{
48 m_options |= MultiIconOption;
49 m_multiIcon = image;
50 setFixedSize(m_multiIcon.width(), m_multiIcon.height() / 4);
51
52 update();
53}
54
55QString ToolButton::themeIcon() const
56{
57 return m_themeIcon;
58}
59
60void ToolButton::setThemeIcon(const QString &icon)
61{
62 const QIcon ic = QIcon::fromTheme(icon);
63 if (!ic.isNull()) {
64 m_themeIcon = icon;
65 setIcon(QIcon::fromTheme(m_themeIcon));
66 }
67}
68
70{
71 return icon();
72}
73
74void ToolButton::setFallbackIcon(const QIcon &fallbackIcon)
75{
76 if (icon().isNull())
78}
79
80QIcon ToolButton::icon() const
81{
82 return QToolButton::icon();
83}
84
85void ToolButton::setIcon(const QIcon &icon)
86{
87 if (m_options & MultiIconOption)
88 setFixedSize(sizeHint());
89
90 m_options &= ~MultiIconOption;
91 QToolButton::setIcon(icon);
92}
93
94QMenu* ToolButton::menu() const
95{
96 return m_menu;
97}
98
99void ToolButton::setMenu(QMenu* menu)
100{
101 Q_ASSERT(menu);
102
103 if (m_menu)
104 disconnect(m_menu, &QMenu::aboutToHide, this, &ToolButton::menuAboutToHide);
105
106 m_menu = menu;
107 connect(m_menu, &QMenu::aboutToHide, this, &ToolButton::menuAboutToHide);
108}
109
111{
112 return m_options & ShowMenuInsideOption;
113}
114
116{
117 if (enable)
118 m_options |= ShowMenuInsideOption;
119 else
120 m_options &= ~ShowMenuInsideOption;
121}
122
124{
125 return m_options & ShowMenuOnRightClick;
126}
127
129{
130 m_options.setFlag(ShowMenuOnRightClick, enable);
131}
132
134{
135 return m_options & ToolBarLookOption;
136}
137
139{
140 if (enable) {
141 m_options |= ToolBarLookOption;
142
143 QStyleOption opt;
144 opt.initFrom(this);
145 int size = style()->pixelMetric(QStyle::PM_ToolBarIconSize, &opt, this);
146 setIconSize(QSize(size, size));
147 }
148 else {
149 m_options &= ~ToolBarLookOption;
150 }
151
152 setProperty("toolbar-look", QVariant(enable));
153 style()->unpolish(this);
154 style()->polish(this);
155}
156
157void ToolButton::menuAboutToHide()
158{
159 setDown(false);
160 Q_EMIT aboutToHideMenu();
161}
162
163void ToolButton::showMenu()
164{
165 if (!m_menu || m_menu->isVisible())
166 return;
167
168 Q_EMIT aboutToShowMenu();
169
170 QPoint pos;
171
172 if (m_options & ShowMenuInsideOption) {
173 pos = mapToGlobal(rect().bottomRight());
174 if (QApplication::layoutDirection() == Qt::RightToLeft)
175 pos.setX(pos.x() - rect().width());
176 else
177 pos.setX(pos.x() - m_menu->sizeHint().width());
178 }
179 else {
180 pos = mapToGlobal(rect().bottomLeft());
181 }
182
183 m_menu->popup(pos);
184}
185
186void ToolButton::mousePressEvent(QMouseEvent* e)
187{
188 if (e->buttons() == Qt::LeftButton && popupMode() == QToolButton::DelayedPopup)
189 m_pressTimer.start();
190
191 if (e->buttons() == Qt::LeftButton && menu() && popupMode() == QToolButton::InstantPopup) {
192 setDown(true);
193 showMenu();
194 }
195 else if (e->buttons() == Qt::RightButton && menu() && m_options & ShowMenuOnRightClick) {
196 setDown(true);
197 showMenu();
198 } else {
199 QToolButton::mousePressEvent(e);
200 }
201}
202
204{
205 m_pressTimer.stop();
206
207 if (e->button() == Qt::MiddleButton && rect().contains(e->pos())) {
208 Q_EMIT middleMouseClicked();
209 setDown(false);
210 }
211 else if (e->button() == Qt::LeftButton && rect().contains(e->pos()) && e->modifiers() == Qt::ControlModifier) {
212 Q_EMIT controlClicked();
213 setDown(false);
214 } else {
215 QToolButton::mouseReleaseEvent(e);
216 }
217}
218
220{
221 QToolButton::mouseDoubleClickEvent(e);
222
223 m_pressTimer.stop();
224
225 if (e->buttons() == Qt::LeftButton) {
226 Q_EMIT doubleClicked();
227 }
228}
229
230void ToolButton::contextMenuEvent(QContextMenuEvent *e)
231{
232 // Block to prevent showing both context menu and button menu
233 if (menu() && m_options & ShowMenuOnRightClick)
234 return;
235
236 QToolButton::contextMenuEvent(e);
237}
238
239void ToolButton::paintEvent(QPaintEvent* e)
240{
241 if (!(m_options & MultiIconOption)) {
242 QToolButton::paintEvent(e);
243 return;
244 }
245
246 QPainter p(this);
247
248 const int w = m_multiIcon.width();
249 const int h4 = m_multiIcon.height() / 4;
250
251 if (!isEnabled())
252 p.drawImage(0, 0, m_multiIcon, 0, h4 * 3, w, h4);
253 else if (isDown())
254 p.drawImage(0, 0, m_multiIcon, 0, h4 * 2, w, h4);
255 else if (underMouse())
256 p.drawImage(0, 0, m_multiIcon, 0, h4 * 1, w, h4);
257 else
258 p.drawImage(0, 0, m_multiIcon, 0, h4 * 0, w, h4);
259}
void mousePressEvent(QMouseEvent *e) override
Definition: toolbutton.cpp:186
void mouseReleaseEvent(QMouseEvent *e) override
Definition: toolbutton.cpp:203
void doubleClicked()
void setMenu(QMenu *menu)
Definition: toolbutton.cpp:99
bool showMenuInside() const
Definition: toolbutton.cpp:110
void mouseDoubleClickEvent(QMouseEvent *e) override
Definition: toolbutton.cpp:219
void controlClicked()
QImage multiIcon
Definition: toolbutton.h:33
void paintEvent(QPaintEvent *e) override
Definition: toolbutton.cpp:239
void setShowMenuInside(bool enable)
Definition: toolbutton.cpp:115
void setToolbarButtonLook(bool enable)
Definition: toolbutton.cpp:138
QIcon fallbackIcon
Definition: toolbutton.h:36
void aboutToShowMenu()
void setMultiIcon(const QImage &image)
Definition: toolbutton.cpp:46
void setFallbackIcon(const QIcon &fallbackIcon)
Definition: toolbutton.cpp:74
void contextMenuEvent(QContextMenuEvent *e) override
Definition: toolbutton.cpp:230
QIcon icon
Definition: toolbutton.h:34
ToolButton(QWidget *parent=nullptr)
Definition: toolbutton.cpp:27
QString themeIcon
Definition: toolbutton.h:35
bool showMenuOnRightClick() const
Definition: toolbutton.cpp:123
void setIcon(const QIcon &icon)
Definition: toolbutton.cpp:85
void aboutToHideMenu()
void setThemeIcon(const QString &icon)
Definition: toolbutton.cpp:60
bool toolbarButtonLook() const
Definition: toolbutton.cpp:133
void middleMouseClicked()
void setShowMenuOnRightClick(bool enable)
Definition: toolbutton.cpp:128
QMenu * menu() const
Definition: toolbutton.cpp:94