1/*
2 This file is part of the KDE project
3 SPDX-FileCopyrightText: 2021 Felix Ernst <fe.a.ernst@gmail.com>
4
5 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
6*/
7
8#ifndef KHamburgerMenu_P_H
9#define KHamburgerMenu_P_H
10
11#include "khamburgermenu.h"
12
13#include <QWidgetAction>
14
15#include <QPointer>
16#include <QScopedPointer>
17
18#include <forward_list>
19#include <unordered_set>
20
21class ListenerContainer;
22
23class QMenu;
24class QMenuBar;
25class QToolButton;
26
27/**
28 * The private class of KHamburgerMenu used for the PIMPL idiom.
29 * \internal
30 */
31class KHamburgerMenuPrivate : public QObject
32{
33 Q_OBJECT
34 Q_DECLARE_PUBLIC(KHamburgerMenu)
35
36public:
37 explicit KHamburgerMenuPrivate(KHamburgerMenu *qq);
38
39 ~KHamburgerMenuPrivate() override;
40
41 /** @see KHamburgerMenu::setMenuBar() */
42 void setMenuBar(QMenuBar *menuBar);
43
44 /** @see KHamburgerMenu::setMenuBar() */
45 QMenuBar *menuBar() const;
46
47 /** @see KHamburgerMenu::setMenuBarAdvertised() */
48 void setMenuBarAdvertised(bool advertise);
49
50 /** @see KHamburgerMenu::setMenuBarAdvertised() */
51 bool menuBarAdvertised() const;
52
53 /** @see KHamburgerMenu::setShowMenuBarAction() */
54 void setShowMenuBarAction(QAction *showMenuBarAction);
55
56 /** @see KHamburgerMenu::insertIntoMenuBefore() */
57 void insertIntoMenuBefore(QMenu *menu, QAction *before);
58
59 /** @see KHamburgerMenu::hideActionsOf() */
60 void hideActionsOf(QWidget *widget);
61
62 /** @see KHamburgerMenu::showActionsOf() */
63 void showActionsOf(QWidget *widget);
64
65 /** @see KHamburgerMenu::createWidget() */
66 QWidget *createWidget(QWidget *parent);
67
68 /**
69 * This method only returns exclusive actions. The idea is to remove any @p nonExclusives
70 * from @p from and all of its sub-menus. This means a copy of @p from is created when
71 * necessary that has a menu() that only contains the exclusive actions from @p from.
72 * @param from the action this method extracts the exclusive actions from.
73 * @param parent the widget that is to become the parent if a copy of @p from needs
74 * to be created.
75 * @param nonExclusives the actions which will not be anywhere within the returned action.
76 * @return either nullptr, @p from unchanged or a copy of @p from without the @p nonExclusives.
77 * In the last case, the caller gets ownership of this new copy with parent @p parent.
78 */
79 QAction *actionWithExclusivesFrom(QAction *from, QWidget *parent, std::unordered_set<const QAction *> &nonExclusives) const;
80
81 /**
82 * @return a new menu with all actions from KHamburgerMenu::menu() which aren't
83 * exempted from being displayed (@see hideActionsOf()).
84 * Next adds the help menu.
85 * At last adds a special sub-menu by calling newMenuBarAdvertisementMenu() if this step
86 * was not explicitly set to be skipped (@see KHamburgerMenu::setMenuBarAdvertised()).
87 */
88 std::unique_ptr<QMenu> newMenu();
89
90 /**
91 * @return a special sub-menu that advertises actions of the menu bar which would otherwise
92 * not be visible or discoverable for the user
93 * @see KHamburgerMenu::setMenuBarAdvertised()
94 */
95 std::unique_ptr<QMenu> newMenuBarAdvertisementMenu(std::unordered_set<const QAction *> &visibleActions);
96
97 /** @see resetMenu() */
98 inline void notifyMenuResetNeeded()
99 {
100 m_menuResetNeeded = true;
101 }
102
103 /**
104 * Does nothing if m_menuResetNeeded is false.
105 * Otherwise deletes m_actualMenu and creates a newMenu() in its place. This new menu
106 * is then set to be used whenever the hamburger menu is opened.
107 * @see newMenu()
108 */
109 void resetMenu();
110
111 /**
112 * Sets the correct visibility for KHamburgerMenu buttons based on the visibility of the
113 * menu bar (@see setMenuBar()).
114 * Also sets the correct visibility of the menu item (@see addToMenu()) based on the visibility
115 * of the menu bar and of the KHamburgerMenu buttons.
116 */
117 void updateVisibility();
118
119protected:
120 /**
121 * Makes the KHamburgerMenu buttons change style just like other toolbuttons would
122 * when their associated action changes.
123 */
124 void slotActionChanged();
125
126 /**
127 * When m_menuBar->isVisible(): Opens the first menu of the menu bar.
128 * Otherwise it acts the same way as clicking on a visible KHamburgerMenu button.
129 * If no KHamburgerMenu button is visible, open its menu anyway.
130 *
131 * @note The action triggered signal is not emitted when a normal button that contains a menu
132 * is pressed. So this slot will effectively only be called by keyboard shortcut.
133 */
134 void slotActionTriggered();
135
136 /**
137 * Updates the style of @p hamburgerMenuButton based on its parent's style and q->priority().
138 */
139 void updateButtonStyle(QToolButton *hamburgerMenuButton) const;
140
141public:
142 KHamburgerMenu *const q_ptr;
143
144protected:
145 /** @see newMenu(). Do not confuse this menu with QAction::menu(). */
146 std::unique_ptr<QMenu> m_actualMenu;
147 /** @see KHamburgerMenu::setMenuBarAdvertised() */
148 bool m_advertiseMenuBar = true;
149 /** @see newMenuBarAdvertisementMenu() */
150 std::unique_ptr<QMenu> m_menuBarAdvertisementMenu;
151 /** @see KHamburgerMenu::hideActionsOf() */
152 std::forward_list<QPointer<const QWidget>> m_widgetsWithActionsToBeHidden;
153 /** The menu that was used as a base when newMenu() was last called. With this we
154 * make sure to reset the m_actualMenu if the q->menu() has been changed or replaced. */
155 QPointer<QMenu> m_lastUsedMenu;
156 /** Makes sure there are no redundant event listeners of the same class. */
157 std::unique_ptr<ListenerContainer> m_listeners;
158 /** The action that is put into QMenus to represent the KHamburgerMenu.
159 * @see KHamburgerMenu::addToMenu() */
160 QPointer<QAction> m_menuAction;
161 /** @see KHamburgerMenu::setMenuBar() */
162 QPointer<QMenuBar> m_menuBar;
163 /** @see resetMenu() */
164 bool m_menuResetNeeded = false;
165 /** @see KHamburgerMenu::setShowMenuBarAction */
166 QPointer<QAction> m_showMenuBarAction;
167 /** Keeps track of changes to the "Show Menubar" button text. */
168 QString m_showMenuBarText;
169 QString m_showMenuBarWithAllActionsText;
170 /** Identifies if the application set an icon for "Help" menu. */
171 bool m_helpIconIsSet = false;
172};
173
174#endif // KHamburgerMenu_P_H
175

source code of kconfigwidgets/src/khamburgermenu_p.h