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_H |
9 | #define |
10 | |
11 | #include <kconfigwidgets_export.h> |
12 | |
13 | #include <QWidgetAction> |
14 | |
15 | #include <memory> |
16 | |
17 | class ; |
18 | |
19 | class ; |
20 | |
21 | /** |
22 | * @class KHamburgerMenu khamburgermenu.h KHamburgerMenu |
23 | * |
24 | * @short A menu that substitutes a menu bar when necessary |
25 | * |
26 | * Allowing users to toggle the visibility of the menu bar and/or toolbars, |
27 | * while pretty/"simple by default", can lead to various grave usability issues. |
28 | * This class makes it easy to prevent all of them. |
29 | * |
30 | * Simply add a KHamburgerMenu to your UI (typically to a QToolBar) and make |
31 | * it aware of a QMenuBar like this: |
32 | * |
33 | * \code |
34 | * auto hamburgerMenu = KStandardAction::hamburgerMenu(nullptr, nullptr, actionCollection()); |
35 | * toolBar()->addAction(hamburgerMenu); |
36 | * hamburgerMenu->hideActionsOf(toolBar()); |
37 | * // after the QMenuBar has been initialised |
38 | * hamburgerMenu->setMenuBar(menuBar()); // line not needed if there is no QMenuBar |
39 | * \endcode |
40 | * |
41 | * The added menu button will only be visible when the QMenuBar is hidden. |
42 | * With this minimal initialisation it will contain the contents of the menu bar. |
43 | * If a user (also) hides the container the KHamburgerMenu was added to they |
44 | * might find themselves without a way to get a menu back. To prevent this, it is |
45 | * recommended to add the hamburgerMenu to prominent context menus like the one |
46 | * of your central widget preferably at the first position. Simply write: |
47 | * |
48 | * \code |
49 | * hamburgerMenu->addActionToMenu(contextMenu); |
50 | * \endcode |
51 | * |
52 | * The added menu will only be visible if the QMenuBar is hidden and the |
53 | * hamburgerMenu->createdWidgets() are all invisible to the user. |
54 | * |
55 | * **Populating the KHamburgerMenu** |
56 | * |
57 | * This is easy: |
58 | * |
59 | * \code |
60 | * auto menu = new QMenu(this); |
61 | * menu->addAction(action); |
62 | * // Add actions, separators, etc. like usual. |
63 | * hamburgerMenu->setMenu(menu); |
64 | * \endcode |
65 | * |
66 | * You probably do not want this to happen on startup. Therefore KHamburgerMenu |
67 | * provides the signal aboutToShowMenu that you can connect to a function containing |
68 | * the previous statements. |
69 | * |
70 | * \code |
71 | * connect(hamburgerMenu, &KHamburgerMenu::aboutToShowMenu, |
72 | * this, &MainWindow::updateHamburgerMenu); |
73 | * // You might want to disconnect the signal after initial creation if the contents never change. |
74 | * \endcode |
75 | * |
76 | * **Deciding what to put on the hamburger menu** |
77 | * |
78 | * 1. Be sure to add all of the most important actions. Actions which are already |
79 | * visible on QToolBars, etc. will not show up in the hamburgerMenu. To manage |
80 | * which containers KHamburgerMenu should watch for redundancy use |
81 | * hideActionsOf(QWidget *) and showActionsOf(QWidget *). |
82 | * When a KHamburgerMenu is added to a widget, hideActionsOf(that widget) |
83 | * will automatically be called. |
84 | * 2. Do not worry about adding all actions the application has to offer. |
85 | * The KHamburgerMenu will automatically have a section advertising excluded |
86 | * actions which can be found in the QMenuBar. There will also be the |
87 | * showMenuBarAction if you set it with setShowMenuBarAction(). |
88 | * 3. Do not worry about the help menu. KHamburgerMenu will automatically contain |
89 | * a help menu as the second to last item (if you set a QMenuBar which is |
90 | * expected to have the help menu as the last action). |
91 | * |
92 | * **Open menu by shortcut** |
93 | * |
94 | * For visually impaired users it is important to have a consistent way to open a general-purpose |
95 | * menu. Triggering the keyboard shortcut bound to KHamburgerMenu will always open a menu. |
96 | * - If setMenuBar() was called and that menu bar is visible, the shortcut will open the first menu |
97 | * of that menu bar. |
98 | * - Otherwise, if there is a visible KHamburgerMenu button in the user interface, that menu will |
99 | * open. |
100 | * - Otherwise, KHamburgerMenu's menu will open at the mouse cursor position. |
101 | * |
102 | * @since 5.81 |
103 | */ |
104 | class KCONFIGWIDGETS_EXPORT : public QWidgetAction |
105 | { |
106 | Q_OBJECT |
107 | Q_DECLARE_PRIVATE(KHamburgerMenu) |
108 | |
109 | public: |
110 | explicit (QObject *parent); |
111 | |
112 | () override; |
113 | |
114 | /** |
115 | * Associates this KHamburgerMenu with @p menuBar. The KHamburgerMenu will from now |
116 | * on only be visible when @p menuBar is hidden. |
117 | * (Menu bars with QMenuBar::isNativeMenuBar() == true are considered hidden.) |
118 | * |
119 | * Furthermore the KHamburgerMenu will have the help menu from the @p menuBar added |
120 | * at the end. There will also be a special sub-menu advertising actions which are |
121 | * only available in the menu bar unless advertiseMenuBar(false) was called. |
122 | * |
123 | * @param menuBar The QMenuBar the KHamburgerMenu should be associated with. |
124 | * This can be set to nullptr. |
125 | */ |
126 | void (QMenuBar *); |
127 | |
128 | /** @see setMenuBar() */ |
129 | QMenuBar *() const; |
130 | |
131 | /** |
132 | * By default the KHamburgerMenu contains a special sub-menu that advertises actions |
133 | * of the menu bar which would otherwise not be visible or discoverable for the user. |
134 | * This method removes or re-adds that sub-menu. |
135 | * |
136 | * @param advertise sets whether the special sub-menu that advertises menu bar only |
137 | * actions should exist. |
138 | */ |
139 | void (bool advertise); |
140 | |
141 | /** @see setMenuBarAdvertised() */ |
142 | bool () const; |
143 | |
144 | /** |
145 | * Adds the @p showMenuBarAction as the first item of the sub-menu which advertises actions |
146 | * from the menu bar. |
147 | * @see setMenuBarAdvertised() |
148 | */ |
149 | void (QAction *); |
150 | |
151 | /** |
152 | * Adds this KHamburgerMenu to @p menu. |
153 | * It will only be visible in the menu if both the menu bar and all of this |
154 | * QWidgetAction's createdWidgets() are invisible. |
155 | * If it is visible in the menu, then opening the menu emits the aboutToShowMenu |
156 | * signal. |
157 | * |
158 | * @param menu The menu this KHamburgerMenu is supposed to appear in. |
159 | */ |
160 | void (QMenu *); |
161 | |
162 | /** |
163 | * Inserts this KHamburgerMenu to @p menu's list of actions, before the action @p before. |
164 | * It will only be visible in the menu if both the menu bar and all of this |
165 | * QWidgetAction's createdWidgets() are invisible. |
166 | * If it is visible in the menu, then opening the menu emits the aboutToShowMenu |
167 | * signal. |
168 | * |
169 | * @param before The action before which KHamburgerMenu should be inserted. |
170 | * @param menu The menu this KHamburgerMenu is supposed to appear in. |
171 | * |
172 | * @see QWidget::insertAction(), QMenu::insertMenu() |
173 | * |
174 | * @since 5.99 |
175 | */ |
176 | void (QMenu *, QAction *before); |
177 | |
178 | /** |
179 | * Adds @p widget to a list of widgets that should be monitored for their actions(). |
180 | * If the widget is a QMenu, its actions will be treated as known to the user. |
181 | * If the widget isn't a QMenu, its actions will only be treated as known to the user |
182 | * when the widget is actually visible. |
183 | * @param widget A widget that contains actions which should not show up in the |
184 | * KHamburgerMenu redundantly. |
185 | */ |
186 | void (QWidget *widget); |
187 | |
188 | /** |
189 | * Reverses a hideActionsOf(widget) method call. |
190 | * @see hideActionsOf() |
191 | */ |
192 | void (QWidget *widget); |
193 | |
194 | Q_SIGNALS: |
195 | /** |
196 | * This signal is emitted when a hamburger menu button is about to be pressed down. |
197 | * It is also emitted when a QMenu that contains a visible KHamburgerMenu emits |
198 | * QMenu::aboutToShow. |
199 | */ |
200 | void (); |
201 | |
202 | protected: |
203 | /** |
204 | * @see QWidgetAction::createWidget |
205 | */ |
206 | virtual QWidget *(QWidget *parent) override; |
207 | |
208 | private: |
209 | std::unique_ptr<KHamburgerMenuPrivate> const ; |
210 | }; |
211 | |
212 | #endif // KHamburgerMenu_H |
213 | |