File indexing completed on 2024-07-14 14:27:37

0001 /*
0002     This file is part of the KDE project
0003     SPDX-FileCopyrightText: 2021 Felix Ernst <fe.a.ernst@gmail.com>
0004 
0005     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0006 */
0007 
0008 #ifndef KHAMBURGERMENUHELPERS_P_H
0009 #define KHAMBURGERMENUHELPERS_P_H
0010 
0011 #include "khamburgermenu_p.h"
0012 
0013 #include <QObject>
0014 
0015 #include <memory>
0016 #include <vector>
0017 
0018 class QFont;
0019 class QWidget;
0020 
0021 /**
0022  * @brief Makes sure there are no redundant event listeners.
0023  *
0024  * Functionally identical event listeners are needed throughout khamburgermenu.cpp.
0025  * This class makes sure only one of each is created when needed and then reused.
0026  * This also simplifies the removal of event listeners.
0027  * \internal
0028  */
0029 class ListenerContainer : private QObject
0030 {
0031 public:
0032     explicit ListenerContainer(KHamburgerMenuPrivate *hamburgerMenuPrivate);
0033     ~ListenerContainer() override;
0034 
0035     /**
0036      * @return an object of class @p Listener with the same parent as ListenerContainer.
0037      */
0038     template<class Listener>
0039     Listener *get()
0040     {
0041         for (auto &i : m_listeners) {
0042             if (auto existingListener = qobject_cast<Listener *>(i.get())) {
0043                 return existingListener;
0044             }
0045         }
0046 
0047         KHamburgerMenuPrivate *hamburgerMenuPrivate = static_cast<KHamburgerMenuPrivate *>(parent());
0048         m_listeners.push_back(std::unique_ptr<QObject>(new Listener(hamburgerMenuPrivate)));
0049         return static_cast<Listener *>(m_listeners.back().get());
0050     }
0051 
0052 protected:
0053     std::vector<std::unique_ptr<QObject>> m_listeners;
0054 };
0055 
0056 /**
0057  * When an action is added or removed, calls KHamburgerMenuPrivate::notifyMenuResetNeeded().
0058  * \internal
0059  */
0060 class AddOrRemoveActionListener : public QObject
0061 {
0062     Q_OBJECT
0063 
0064 protected:
0065     inline AddOrRemoveActionListener(QObject *parent)
0066         : QObject{parent} {};
0067 
0068     bool eventFilter(QObject * /*watched*/, QEvent *event) override;
0069 
0070     friend class ListenerContainer;
0071 };
0072 
0073 /**
0074  * When the button is pressed, emits KHamburgerMenu::aboutToShowMenu(), then calls
0075  * KHamburgerMenuPrivate::resetMenu() (which will only actually reset the menu if
0076  * a menu reset is needed).
0077  * \internal
0078  */
0079 class ButtonPressListener : public QObject
0080 {
0081     Q_OBJECT
0082 
0083 protected:
0084     inline ButtonPressListener(QObject *parent)
0085         : QObject{parent} {};
0086 
0087     bool eventFilter(QObject *watched, QEvent *event) override;
0088 
0089     friend class ListenerContainer;
0090 };
0091 
0092 /**
0093  * When either
0094  * - the visibility of the widget changes or
0095  * - actions are added or removed from the widget while it isVisible()
0096  * calls KHamburgerMenuPrivate::notifyMenuResetNeeded().
0097  * \internal
0098  */
0099 class VisibleActionsChangeListener : public QObject
0100 {
0101     Q_OBJECT
0102 
0103 protected:
0104     inline VisibleActionsChangeListener(QObject *parent)
0105         : QObject{parent} {};
0106 
0107     /**
0108      * Listen for events that potentially lead to a change in user-visible actions.
0109      * Examples: Adding an action or hiding a toolbar.
0110      */
0111     bool eventFilter(QObject *watched, QEvent *event) override;
0112 
0113     friend class ListenerContainer;
0114 };
0115 
0116 /**
0117  * When the visibility of the widget changes calls KHamburgerMenuPrivate::updateVisibility().
0118  * \internal
0119  */
0120 class VisibilityChangesListener : public QObject
0121 {
0122     Q_OBJECT
0123 
0124 protected:
0125     inline VisibilityChangesListener(QObject *parent)
0126         : QObject{parent} {};
0127 
0128     bool eventFilter(QObject * /*watched*/, QEvent *event) override;
0129 
0130     friend class ListenerContainer;
0131 };
0132 
0133 /**
0134  * Is the widget and all of its ancestors visible?
0135  */
0136 bool isWidgetActuallyVisible(const QWidget *widget);
0137 
0138 /**
0139  * Does the @p list contain the @p widget?
0140  */
0141 bool listContainsWidget(const std::forward_list<QPointer<const QWidget>> &list, const QWidget *widget);
0142 
0143 #endif // KHAMBURGERMENUHELPERS_P_H