File indexing completed on 2024-04-28 15:52:00

0001 /*
0002     SPDX-FileCopyrightText: 2019-2021 David Hurka <david.hurka@mailbox.org>
0003 
0004     Inspired by and replacing toolaction.h by:
0005     SPDX-FileCopyrightText: 2004-2006 Albert Astals Cid <aacid@kde.org>
0006 
0007     SPDX-License-Identifier: GPL-2.0-or-later
0008 */
0009 
0010 #include "toggleactionmenu.h"
0011 
0012 #include <QActionEvent>
0013 #include <QMenu>
0014 
0015 ToggleActionMenu::ToggleActionMenu(QObject *parent)
0016     : ToggleActionMenu(QIcon(), QString(), parent)
0017 {
0018 }
0019 
0020 ToggleActionMenu::ToggleActionMenu(const QString &text, QObject *parent)
0021     : ToggleActionMenu(QIcon(), text, parent)
0022 {
0023 }
0024 
0025 ToggleActionMenu::ToggleActionMenu(const QIcon &icon, const QString &text, QObject *parent)
0026     : KActionMenu(icon, text, parent)
0027     , m_defaultAction(nullptr)
0028 {
0029     slotMenuChanged();
0030 }
0031 
0032 QWidget *ToggleActionMenu::createWidget(QWidget *parent)
0033 {
0034     QWidget *buttonWidget = KActionMenu::createWidget(parent);
0035     QToolButton *button = qobject_cast<QToolButton *>(buttonWidget);
0036     if (!button) {
0037         // This function is used to add a button into the toolbar.
0038         // QWidgetAction::createWidget() is also called with other parents,
0039         // e. g. when this ToggleActionMenu is added to a QMenu.
0040         // Therefore, reaching this code path is a valid use case.
0041         return buttonWidget;
0042     }
0043 
0044     // BEGIN QToolButton hack
0045     // Setting the default action of a QToolButton
0046     // to an action of its menu() is tricky.
0047     // Remove this menu action from the button,
0048     // so it doesn't compose a menu of this menu action and its own menu.
0049     button->removeAction(this);
0050     // The button has lost the menu now, let it use the correct menu.
0051     button->setMenu(menu());
0052     // END QToolButton hack
0053 
0054     m_buttons.append(button);
0055     m_originalToolButtonStyle[button] = button->toolButtonStyle();
0056 
0057     // Apply other properties to the button.
0058     updateButtons();
0059 
0060     return button;
0061 }
0062 
0063 QAction *ToggleActionMenu::defaultAction()
0064 {
0065     return m_defaultAction ? m_defaultAction : this;
0066 }
0067 
0068 void ToggleActionMenu::setDefaultAction(QAction *action)
0069 {
0070     if (action && menu()->actions().contains(action)) {
0071         m_defaultAction = action;
0072     } else {
0073         m_defaultAction = nullptr;
0074     }
0075     updateButtons();
0076 }
0077 
0078 Qt::ToolButtonStyle ToggleActionMenu::styleFor(QToolButton *button) const
0079 {
0080     Qt::ToolButtonStyle style = m_originalToolButtonStyle[button];
0081 
0082     if (style == Qt::ToolButtonTextBesideIcon && priority() < QAction::NormalPriority) {
0083         style = Qt::ToolButtonIconOnly;
0084     }
0085 
0086     return style;
0087 }
0088 
0089 void ToggleActionMenu::updateButtons()
0090 {
0091     for (QToolButton *button : std::as_const(m_buttons)) {
0092         if (button) {
0093             button->setDefaultAction(this->defaultAction());
0094             // If *this action* is low priority we need to tell the button
0095             // so that it hides the text
0096             button->setToolButtonStyle(styleFor(button));
0097 
0098             button->setPopupMode(popupMode());
0099         }
0100     }
0101 }
0102 
0103 bool ToggleActionMenu::eventFilter(QObject *watched, QEvent *event)
0104 {
0105     // If the defaultAction() is removed from the menu, reset the default action.
0106     if (watched == menu() && event->type() == QEvent::ActionRemoved) {
0107         QActionEvent *actionEvent = static_cast<QActionEvent *>(event);
0108         if (actionEvent->action() == defaultAction()) {
0109             setDefaultAction(nullptr);
0110         }
0111     }
0112 
0113     return KActionMenu::eventFilter(watched, event);
0114 }
0115 
0116 void ToggleActionMenu::slotMenuChanged()
0117 {
0118     menu()->installEventFilter(this);
0119     // Not removing old event filter, because we would need to remember the old menu.
0120 }
0121 
0122 #include "moc_toggleactionmenu.cpp"