File indexing completed on 2024-05-12 04:58:26
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 "buttonwithmenu.h" 0019 0020 #include <QMenu> 0021 #include <QWheelEvent> 0022 0023 ButtonWithMenu::ButtonWithMenu(QWidget* parent) 0024 : ToolButton(parent) 0025 , m_menu(new QMenu(this)) 0026 { 0027 setCursor(Qt::ArrowCursor); 0028 setFocusPolicy(Qt::NoFocus); 0029 0030 connect(this, &ToolButton::aboutToShowMenu, this, &ButtonWithMenu::generateMenu); 0031 connect(m_menu, &QMenu::aboutToShow, this, std::bind(&ButtonWithMenu::setDown, this, true)); 0032 connect(m_menu, &QMenu::aboutToHide, this, std::bind(&ButtonWithMenu::setDown, this, false)); 0033 } 0034 0035 void ButtonWithMenu::setCurrentItem() 0036 { 0037 if (auto* action = qobject_cast<QAction*>(sender())) { 0038 setCurrentItem(action->data().value<Item>()); 0039 } 0040 } 0041 0042 void ButtonWithMenu::clearItems() 0043 { 0044 m_menu->clear(); 0045 m_items.clear(); 0046 } 0047 0048 void ButtonWithMenu::selectNextItem() 0049 { 0050 int index = m_items.indexOf(m_currentItem) + 1; 0051 0052 if (index < m_items.size()) { 0053 setCurrentIndex(index); 0054 } 0055 } 0056 0057 void ButtonWithMenu::selectPreviousItem() 0058 { 0059 int index = m_items.indexOf(m_currentItem) - 1; 0060 0061 if (index >= 0) { 0062 setCurrentIndex(index); 0063 } 0064 } 0065 0066 void ButtonWithMenu::addItem(const Item &item) 0067 { 0068 m_items.append(item); 0069 0070 if (m_items.count() == 1) { 0071 setCurrentItem(item); 0072 } 0073 0074 Q_EMIT itemAdded(item); 0075 } 0076 0077 void ButtonWithMenu::addItems(const QVector<Item> &items) 0078 { 0079 for (const Item &item : items) { 0080 addItem(item); 0081 } 0082 } 0083 0084 void ButtonWithMenu::removeItem(const Item &item) 0085 { 0086 int index = m_items.indexOf(item); 0087 if (index < 0) { 0088 return; 0089 } 0090 0091 m_items.remove(index); 0092 0093 if (m_items.isEmpty()) { 0094 setIcon(QIcon()); 0095 return; 0096 } 0097 0098 if (m_currentItem == item) { 0099 setCurrentItem(m_items.at(0)); 0100 } 0101 } 0102 0103 void ButtonWithMenu::setCurrentItem(const Item &item, bool emitSignal) 0104 { 0105 int index = m_items.indexOf(item); 0106 if (index < 0 || m_currentItem == item) { 0107 return; 0108 } 0109 0110 m_currentItem = item; 0111 0112 setIcon(m_currentItem.icon); 0113 setToolTip(m_currentItem.text); 0114 0115 if (emitSignal) { 0116 Q_EMIT activeItemChanged(m_currentItem); 0117 } 0118 } 0119 0120 void ButtonWithMenu::setCurrentIndex(int index, bool emitSignal) 0121 { 0122 setCurrentItem(m_items.at(index), emitSignal); 0123 } 0124 0125 void ButtonWithMenu::wheelEvent(QWheelEvent* event) 0126 { 0127 m_wheelHelper.processEvent(event); 0128 while (WheelHelper::Direction direction = m_wheelHelper.takeDirection()) { 0129 switch (direction) { 0130 case WheelHelper::WheelUp: 0131 case WheelHelper::WheelLeft: 0132 selectPreviousItem(); 0133 break; 0134 0135 case WheelHelper::WheelDown: 0136 case WheelHelper::WheelRight: 0137 selectNextItem(); 0138 break; 0139 0140 default: 0141 break; 0142 } 0143 } 0144 event->accept(); 0145 } 0146 0147 ButtonWithMenu::Item ButtonWithMenu::currentItem() 0148 { 0149 return m_currentItem; 0150 } 0151 0152 QMenu* ButtonWithMenu::menu() const 0153 { 0154 return m_menu; 0155 } 0156 0157 void ButtonWithMenu::generateMenu() 0158 { 0159 m_menu->clear(); 0160 0161 for (const Item &item : std::as_const(m_items)) { 0162 QVariant variant; 0163 variant.setValue(item); 0164 m_menu->addAction(item.icon, item.text, this, SLOT(setCurrentItem()))->setData(variant); 0165 } 0166 } 0167 0168 void ButtonWithMenu::mousePressEvent(QMouseEvent *event) 0169 { 0170 if (event->buttons() == Qt::LeftButton && parentWidget() && parentWidget()->parentWidget()) { 0171 Q_EMIT aboutToShowMenu(); 0172 QWidget *w = parentWidget()->parentWidget(); 0173 m_menu->popup(w->mapToGlobal(w->rect().bottomLeft())); 0174 } 0175 0176 ToolButton::mousePressEvent(event); 0177 } 0178 0179 ButtonWithMenu::~ButtonWithMenu() 0180 = default;