File indexing completed on 2024-05-12 04:58:28
0001 /* ============================================================ 0002 * Falkon - Qt web browser 0003 * Copyright (C) 2010-2018 David Rosca <nowrep@gmail.com> 0004 * 0005 * This program is free software: you can redistribute it and/or modify 0006 * it under the terms of the GNU General Public License as published by 0007 * the Free Software Foundation, either version 3 of the License, or 0008 * (at your option) any later version. 0009 * 0010 * This program is distributed in the hope that it will be useful, 0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0013 * GNU General Public License for more details. 0014 * 0015 * You should have received a copy of the GNU General Public License 0016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 0017 * ============================================================ */ 0018 #include "toolbutton.h" 0019 0020 #include <QMenu> 0021 #include <QStyle> 0022 #include <QPainter> 0023 #include <QMouseEvent> 0024 #include <QApplication> 0025 #include <QStyleOptionToolButton> 0026 0027 ToolButton::ToolButton(QWidget* parent) 0028 : QToolButton(parent) 0029 , m_menu(nullptr) 0030 { 0031 setMinimumWidth(16); 0032 0033 QStyleOptionToolButton opt; 0034 initStyleOption(&opt); 0035 0036 m_pressTimer.setSingleShot(true); 0037 m_pressTimer.setInterval(QApplication::style()->styleHint(QStyle::SH_ToolButton_PopupDelay, &opt, this)); 0038 connect(&m_pressTimer, SIGNAL(timeout()), this, SLOT(showMenu())); 0039 } 0040 0041 QImage ToolButton::multiIcon() const 0042 { 0043 return m_multiIcon; 0044 } 0045 0046 void ToolButton::setMultiIcon(const QImage &image) 0047 { 0048 m_options |= MultiIconOption; 0049 m_multiIcon = image; 0050 setFixedSize(m_multiIcon.width(), m_multiIcon.height() / 4); 0051 0052 update(); 0053 } 0054 0055 QString ToolButton::themeIcon() const 0056 { 0057 return m_themeIcon; 0058 } 0059 0060 void ToolButton::setThemeIcon(const QString &icon) 0061 { 0062 const QIcon ic = QIcon::fromTheme(icon); 0063 if (!ic.isNull()) { 0064 m_themeIcon = icon; 0065 setIcon(QIcon::fromTheme(m_themeIcon)); 0066 } 0067 } 0068 0069 QIcon ToolButton::fallbackIcon() const 0070 { 0071 return icon(); 0072 } 0073 0074 void ToolButton::setFallbackIcon(const QIcon &fallbackIcon) 0075 { 0076 if (icon().isNull()) 0077 setIcon(fallbackIcon); 0078 } 0079 0080 QIcon ToolButton::icon() const 0081 { 0082 return QToolButton::icon(); 0083 } 0084 0085 void ToolButton::setIcon(const QIcon &icon) 0086 { 0087 if (m_options & MultiIconOption) 0088 setFixedSize(sizeHint()); 0089 0090 m_options &= ~MultiIconOption; 0091 QToolButton::setIcon(icon); 0092 } 0093 0094 QMenu* ToolButton::menu() const 0095 { 0096 return m_menu; 0097 } 0098 0099 void ToolButton::setMenu(QMenu* menu) 0100 { 0101 Q_ASSERT(menu); 0102 0103 if (m_menu) 0104 disconnect(m_menu, &QMenu::aboutToHide, this, &ToolButton::menuAboutToHide); 0105 0106 m_menu = menu; 0107 connect(m_menu, &QMenu::aboutToHide, this, &ToolButton::menuAboutToHide); 0108 } 0109 0110 bool ToolButton::showMenuInside() const 0111 { 0112 return m_options & ShowMenuInsideOption; 0113 } 0114 0115 void ToolButton::setShowMenuInside(bool enable) 0116 { 0117 if (enable) 0118 m_options |= ShowMenuInsideOption; 0119 else 0120 m_options &= ~ShowMenuInsideOption; 0121 } 0122 0123 bool ToolButton::showMenuOnRightClick() const 0124 { 0125 return m_options & ShowMenuOnRightClick; 0126 } 0127 0128 void ToolButton::setShowMenuOnRightClick(bool enable) 0129 { 0130 m_options.setFlag(ShowMenuOnRightClick, enable); 0131 } 0132 0133 bool ToolButton::toolbarButtonLook() const 0134 { 0135 return m_options & ToolBarLookOption; 0136 } 0137 0138 void ToolButton::setToolbarButtonLook(bool enable) 0139 { 0140 if (enable) { 0141 m_options |= ToolBarLookOption; 0142 0143 QStyleOption opt; 0144 opt.initFrom(this); 0145 int size = style()->pixelMetric(QStyle::PM_ToolBarIconSize, &opt, this); 0146 setIconSize(QSize(size, size)); 0147 } 0148 else { 0149 m_options &= ~ToolBarLookOption; 0150 } 0151 0152 setProperty("toolbar-look", QVariant(enable)); 0153 style()->unpolish(this); 0154 style()->polish(this); 0155 } 0156 0157 void ToolButton::menuAboutToHide() 0158 { 0159 setDown(false); 0160 Q_EMIT aboutToHideMenu(); 0161 } 0162 0163 void ToolButton::showMenu() 0164 { 0165 if (!m_menu || m_menu->isVisible()) 0166 return; 0167 0168 Q_EMIT aboutToShowMenu(); 0169 0170 QPoint pos; 0171 0172 if (m_options & ShowMenuInsideOption) { 0173 pos = mapToGlobal(rect().bottomRight()); 0174 if (QApplication::layoutDirection() == Qt::RightToLeft) 0175 pos.setX(pos.x() - rect().width()); 0176 else 0177 pos.setX(pos.x() - m_menu->sizeHint().width()); 0178 } 0179 else { 0180 pos = mapToGlobal(rect().bottomLeft()); 0181 } 0182 0183 m_menu->popup(pos); 0184 } 0185 0186 void ToolButton::mousePressEvent(QMouseEvent* e) 0187 { 0188 if (e->buttons() == Qt::LeftButton && popupMode() == QToolButton::DelayedPopup) 0189 m_pressTimer.start(); 0190 0191 if (e->buttons() == Qt::LeftButton && menu() && popupMode() == QToolButton::InstantPopup) { 0192 setDown(true); 0193 showMenu(); 0194 } 0195 else if (e->buttons() == Qt::RightButton && menu() && m_options & ShowMenuOnRightClick) { 0196 setDown(true); 0197 showMenu(); 0198 } else { 0199 QToolButton::mousePressEvent(e); 0200 } 0201 } 0202 0203 void ToolButton::mouseReleaseEvent(QMouseEvent* e) 0204 { 0205 m_pressTimer.stop(); 0206 0207 if (e->button() == Qt::MiddleButton && rect().contains(e->pos())) { 0208 Q_EMIT middleMouseClicked(); 0209 setDown(false); 0210 } 0211 else if (e->button() == Qt::LeftButton && rect().contains(e->pos()) && e->modifiers() == Qt::ControlModifier) { 0212 Q_EMIT controlClicked(); 0213 setDown(false); 0214 } else { 0215 QToolButton::mouseReleaseEvent(e); 0216 } 0217 } 0218 0219 void ToolButton::mouseDoubleClickEvent(QMouseEvent* e) 0220 { 0221 QToolButton::mouseDoubleClickEvent(e); 0222 0223 m_pressTimer.stop(); 0224 0225 if (e->buttons() == Qt::LeftButton) { 0226 Q_EMIT doubleClicked(); 0227 } 0228 } 0229 0230 void ToolButton::contextMenuEvent(QContextMenuEvent *e) 0231 { 0232 // Block to prevent showing both context menu and button menu 0233 if (menu() && m_options & ShowMenuOnRightClick) 0234 return; 0235 0236 QToolButton::contextMenuEvent(e); 0237 } 0238 0239 void ToolButton::paintEvent(QPaintEvent* e) 0240 { 0241 if (!(m_options & MultiIconOption)) { 0242 QToolButton::paintEvent(e); 0243 return; 0244 } 0245 0246 QPainter p(this); 0247 0248 const int w = m_multiIcon.width(); 0249 const int h4 = m_multiIcon.height() / 4; 0250 0251 if (!isEnabled()) 0252 p.drawImage(0, 0, m_multiIcon, 0, h4 * 3, w, h4); 0253 else if (isDown()) 0254 p.drawImage(0, 0, m_multiIcon, 0, h4 * 2, w, h4); 0255 else if (underMouse()) 0256 p.drawImage(0, 0, m_multiIcon, 0, h4 * 1, w, h4); 0257 else 0258 p.drawImage(0, 0, m_multiIcon, 0, h4 * 0, w, h4); 0259 }