History

Switching to a wrapper mechanism for VR menus

Brad Davis committed 11 years ago

Commit a96f69a1 parent ee3058830 files · +1335 −1045Browse files

Showing the changes to interface/src/Menu.cpp (1 of 30 files). Show all

Unified · Split

interface/src/Menu.cpp+878−573
@@ -12,7 +12,6 @@ · 11 unmodified lines
1212 #include <QFileDialog>
1313 #include <QMenuBar>
1414 #include <QShortcut>
15−#include <QQmlContext>
1615
1716 #include <AddressManager.h>
1817 #include <AudioClient.h>
@@ -21,7 +20,8 @@ · 2 unmodified lines
2120 #include <PathUtils.h>
2221 #include <SettingHandle.h>
2322 #include <UserActivityLogger.h>
24−#include <OffscreenUi.h>
23+#include <HifiMenu.h>
24+
2525 #include "Application.h"
2626 #include "AccountManager.h"
2727 #include "audio/AudioIOStatsRenderer.h"
@@ -42,625 +42,529 @@ · 14 unmodified lines
4242 #include "InterfaceLogging.h"
4343
4444 #include "Menu.h"
45−#include "Util.h"
46−
47−// Proxy object to simplify porting over
48−HifiAction::HifiAction(const QString& menuOption) : _menuOption(menuOption) {
49−}
50−
51−void HifiAction::setCheckable(bool checkable) {
52− Menu::getInstance()->setCheckable(_menuOption, checkable);
53−}
54−
55−void HifiAction::setChecked(bool checked) {
56− Menu::getInstance()->setChecked(_menuOption, checked);
57−}
5845
59−void HifiAction::setVisible(bool visible) {
60− return Menu::getInstance()->setItemVisible(_menuOption);
61−}
46+Menu* Menu::_instance = NULL;
6247
63−QString HifiAction::shortcut() const {
64− return Menu::getInstance()->getItemShortcut(_menuOption);
65−}
66−
67−void HifiAction::setText(const QString& text) {
68− Menu::getInstance()->setItemText(_menuOption, text);
69−}
70−
71−void HifiAction::setTriggerAction(std::function<void()> f) {
72− Menu::getInstance()->setTriggerAction(_menuOption, f);
73−}
74−
75−void HifiAction::setToggleAction(std::function<void(bool)> f) {
76− Menu::getInstance()->setToggleAction(_menuOption, f);
77−}
48+Menu* Menu::getInstance() {
49+ static QMutex menuInstanceMutex;
7850
79−Menu* Menu::_instance = nullptr;
51+ // lock the menu instance mutex to make sure we don't race and create two menus and crash
52+ menuInstanceMutex.lock();
8053
81−Menu* Menu::getInstance() {
82− // Optimistic check for menu existence
8354 if (!_instance) {
84− static QMutex menuInstanceMutex;
85− withLock(menuInstanceMutex, [] {
86− if (!_instance) {
87− qmlRegisterType<Menu>("Hifi", 1, 0, NAME.toLocal8Bit().constData());
88− qCDebug(interfaceapp, "First call to Menu::getInstance() - initing menu.");
89− Menu::load();
90− auto uiRoot = DependencyManager::get<OffscreenUi>()->getRootItem();
91− _instance = uiRoot->findChild<Menu*>(NAME);
92− if (!_instance) {
93− qFatal("Could not load menu QML");
94− } else {
95− _instance->init();
96− }
97− }
98− });
55+ qCDebug(interfaceapp, "First call to Menu::getInstance() - initing menu.");
56+ _instance = new Menu();
9957 }
100− return _instance;
101−}
10258
103−Menu::Menu(QQuickItem* parent) : HifiMenu(parent) {
59+ menuInstanceMutex.unlock();
60+
61+ return _instance;
10462 }
10563
106−void Menu::init() {
64+Menu::Menu() {
65+ MenuWrapper * fileMenu = addMenu("File");
66+#ifdef Q_OS_MAC
67+ addActionToQMenuAndActionHash(fileMenu, MenuOption::AboutApp, 0, qApp, SLOT(aboutApp()), QAction::AboutRole);
68+#endif
10769 auto dialogsManager = DependencyManager::get<DialogsManager>();
10870 AccountManager& accountManager = AccountManager::getInstance();
109− static const QString ROOT_MENU;
71+
11072 {
111− static const QString FILE_MENU{ "File" };
112− addMenu(ROOT_MENU, FILE_MENU);
113− {
114− addItem(FILE_MENU, MenuOption::Login);
115− // connect to the appropriate signal of the AccountManager so that we can change the Login/Logout menu item
116− connect(&accountManager, &AccountManager::profileChanged,
73+ addActionToQMenuAndActionHash(fileMenu, MenuOption::Login);
74+
75+ // connect to the appropriate signal of the AccountManager so that we can change the Login/Logout menu item
76+ connect(&accountManager, &AccountManager::profileChanged,
11777 dialogsManager.data(), &DialogsManager::toggleLoginDialog);
118− connect(&accountManager, &AccountManager::logoutComplete,
78+ connect(&accountManager, &AccountManager::logoutComplete,
11979 dialogsManager.data(), &DialogsManager::toggleLoginDialog);
120− }
121−
122−#ifdef Q_OS_MAC
123− addActionToQMenuAndActionHash(fileMenu, MenuOption::AboutApp, 0, qApp, SLOT(aboutApp()), QAction::AboutRole);
124−#endif
125−
126− {
127−#if 0
128− static const QString SCRIPTS_MENU{ "Scripts" };
129− addMenu(FILE_MENU, LOCATION_MENU);
130−#else
131− static const QString SCRIPTS_MENU{ FILE_MENU };
132− addSeparator(FILE_MENU, "Scripts");
133−#endif
134− //Qt::CTRL | Qt::Key_O
135− addItem(SCRIPTS_MENU, MenuOption::LoadScript, qApp, SLOT(loadDialog()));
136− //Qt::CTRL | Qt::SHIFT | Qt::Key_O
137− addItem(SCRIPTS_MENU, MenuOption::LoadScriptURL, [=] {
138− qApp->loadScriptURLDialog();
139− });
140− addItem(SCRIPTS_MENU, MenuOption::StopAllScripts, [=] {
141− qApp->stopAllScripts();
142− });
143− //Qt::CTRL | Qt::Key_R,
144− addItem(SCRIPTS_MENU, MenuOption::ReloadAllScripts, [=] {
145− qApp->reloadAllScripts();
146− });
147− // Qt::CTRL | Qt::Key_J,
148− addItem(SCRIPTS_MENU, MenuOption::RunningScripts, [=] {
149− qApp->toggleRunningScriptsWidget();
150− });
151− }
152−
153− {
154−#if 0
155− static const QString LOCATION_MENU{ "Location" };
156− addMenu(FILE_MENU, LOCATION_MENU);
157−#else
158− addSeparator(FILE_MENU, "Location");
159− static const QString LOCATION_MENU{ FILE_MENU };
160−#endif
161− qApp->getBookmarks()->setupMenus(LOCATION_MENU);
162−
163− //Qt::CTRL | Qt::Key_L
164− addItem(LOCATION_MENU, MenuOption::AddressBar, [=] {
165− auto dialogsManager = DependencyManager::get<DialogsManager>();
166− dialogsManager->toggleAddressBar();
167− });
168− addItem(LOCATION_MENU, MenuOption::CopyAddress, [=] {
169− auto addressManager = DependencyManager::get<AddressManager>();
170− addressManager->copyAddress();
171− });
172− addItem(LOCATION_MENU, MenuOption::CopyPath, [=] {
173− auto addressManager = DependencyManager::get<AddressManager>();
174− addressManager->copyPath();
175− });
176− }
177−
178− // Qt::CTRL | Qt::Key_Q
179− // QAction::QuitRole
180− addItem(FILE_MENU, MenuOption::Quit, [=] {
181− qApp->quit();
182− });
18380 }
81+
82+ addDisabledActionAndSeparator(fileMenu, "Scripts");
83+ addActionToQMenuAndActionHash(fileMenu, MenuOption::LoadScript, Qt::CTRL | Qt::Key_O,
84+ qApp, SLOT(loadDialog()));
85+ addActionToQMenuAndActionHash(fileMenu, MenuOption::LoadScriptURL,
86+ Qt::CTRL | Qt::SHIFT | Qt::Key_O, qApp, SLOT(loadScriptURLDialog()));
87+ addActionToQMenuAndActionHash(fileMenu, MenuOption::StopAllScripts, 0, qApp, SLOT(stopAllScripts()));
88+ addActionToQMenuAndActionHash(fileMenu, MenuOption::ReloadAllScripts, Qt::CTRL | Qt::Key_R,
89+ qApp, SLOT(reloadAllScripts()));
90+ addActionToQMenuAndActionHash(fileMenu, MenuOption::RunningScripts, Qt::CTRL | Qt::Key_J,
91+ qApp, SLOT(toggleRunningScriptsWidget()));
92+
93+ addDisabledActionAndSeparator(fileMenu, "Location");
94+ qApp->getBookmarks()->setupMenus(this, fileMenu);
95+
96+ addActionToQMenuAndActionHash(fileMenu,
97+ MenuOption::AddressBar,
98+ Qt::CTRL | Qt::Key_L,
99+ dialogsManager.data(),
100+ SLOT(toggleAddressBar()));
101+ auto addressManager = DependencyManager::get<AddressManager>();
102+ addActionToQMenuAndActionHash(fileMenu, MenuOption::CopyAddress, 0,
103+ addressManager.data(), SLOT(copyAddress()));
104+ addActionToQMenuAndActionHash(fileMenu, MenuOption::CopyPath, 0,
105+ addressManager.data(), SLOT(copyPath()));
106+
107+ addActionToQMenuAndActionHash(fileMenu,
108+ MenuOption::Quit,
109+ Qt::CTRL | Qt::Key_Q,
110+ qApp,
111+ SLOT(quit()),
112+ QAction::QuitRole);
113+
114+
115+ MenuWrapper* editMenu = addMenu("Edit");
116+
117+ QUndoStack* undoStack = qApp->getUndoStack();
118+ QAction* undoAction = undoStack->createUndoAction(editMenu);
119+ undoAction->setShortcut(Qt::CTRL | Qt::Key_Z);
120+ addActionToQMenuAndActionHash(editMenu, undoAction);
121+
122+ QAction* redoAction = undoStack->createRedoAction(editMenu);
123+ redoAction->setShortcut(Qt::CTRL | Qt::SHIFT | Qt::Key_Z);
124+ addActionToQMenuAndActionHash(editMenu, redoAction);
125+
126+ addActionToQMenuAndActionHash(editMenu,
127+ MenuOption::Preferences,
128+ Qt::CTRL | Qt::Key_Comma,
129+ dialogsManager.data(),
130+ SLOT(editPreferences()),
131+ QAction::PreferencesRole);
132+
133+ addActionToQMenuAndActionHash(editMenu, MenuOption::Attachments, 0,
134+ dialogsManager.data(), SLOT(editAttachments()));
135+ addActionToQMenuAndActionHash(editMenu, MenuOption::Animations, 0,
136+ dialogsManager.data(), SLOT(editAnimations()));
137+
138+ MenuWrapper* toolsMenu = addMenu("Tools");
139+ addActionToQMenuAndActionHash(toolsMenu, MenuOption::ScriptEditor, Qt::ALT | Qt::Key_S,
140+ dialogsManager.data(), SLOT(showScriptEditor()));
184141
185−
142+#if defined(Q_OS_MAC) || defined(Q_OS_WIN)
143+ auto speechRecognizer = DependencyManager::get<SpeechRecognizer>();
144+ QAction* speechRecognizerAction = addCheckableActionToQMenuAndActionHash(toolsMenu, MenuOption::ControlWithSpeech,
145+ Qt::CTRL | Qt::SHIFT | Qt::Key_C,
146+ speechRecognizer->getEnabled(),
147+ speechRecognizer.data(),
148+ SLOT(setEnabled(bool)));
149+ connect(speechRecognizer.data(), SIGNAL(enabledUpdated(bool)), speechRecognizerAction, SLOT(setChecked(bool)));
150+#endif
151+
152+ addActionToQMenuAndActionHash(toolsMenu, MenuOption::Chat,
153+ 0, // QML Qt::Key_Backslash,
154+ dialogsManager.data(), SLOT(showIRCLink()));
155+ addActionToQMenuAndActionHash(toolsMenu, MenuOption::AddRemoveFriends, 0,
156+ qApp, SLOT(showFriendsWindow()));
157+
158+ MenuWrapper* visibilityMenu = toolsMenu->addMenu("I Am Visible To");
186159 {
187− static const QString EDIT_MENU{ "Edit" };
188− addMenu(ROOT_MENU, EDIT_MENU);
160+ QActionGroup* visibilityGroup = new QActionGroup(toolsMenu);
161+ auto discoverabilityManager = DependencyManager::get<DiscoverabilityManager>();
162+
163+ QAction* visibleToEveryone = addCheckableActionToQMenuAndActionHash(visibilityMenu, MenuOption::VisibleToEveryone,
164+ 0, discoverabilityManager->getDiscoverabilityMode() == Discoverability::All,
165+ discoverabilityManager.data(), SLOT(setVisibility()));
166+ visibilityGroup->addAction(visibleToEveryone);
167+
168+ QAction* visibleToFriends = addCheckableActionToQMenuAndActionHash(visibilityMenu, MenuOption::VisibleToFriends,
169+ 0, discoverabilityManager->getDiscoverabilityMode() == Discoverability::Friends,
170+ discoverabilityManager.data(), SLOT(setVisibility()));
171+ visibilityGroup->addAction(visibleToFriends);
172+
173+ QAction* visibleToNoOne = addCheckableActionToQMenuAndActionHash(visibilityMenu, MenuOption::VisibleToNoOne,
174+ 0, discoverabilityManager->getDiscoverabilityMode() == Discoverability::None,
175+ discoverabilityManager.data(), SLOT(setVisibility()));
176+ visibilityGroup->addAction(visibleToNoOne);
177+
178+ connect(discoverabilityManager.data(), &DiscoverabilityManager::discoverabilityModeChanged,
179+ discoverabilityManager.data(), &DiscoverabilityManager::visibilityChanged);
180+ }
189181
190− QUndoStack* undoStack = qApp->getUndoStack();
191− QAction* undoAction = undoStack->createUndoAction(this);
192− //undoAction->setShortcut(Qt::CTRL | Qt::Key_Z);
193− addItem(EDIT_MENU, undoAction->text(), undoAction, SLOT(trigger()));
182+ addActionToQMenuAndActionHash(toolsMenu,
183+ MenuOption::ToolWindow,
184+ Qt::CTRL | Qt::ALT | Qt::Key_T,
185+ dialogsManager.data(),
186+ SLOT(toggleToolWindow()));
187+
188+ addActionToQMenuAndActionHash(toolsMenu,
189+ MenuOption::Console,
190+ Qt::CTRL | Qt::ALT | Qt::Key_J,
191+ DependencyManager::get<StandAloneJSConsole>().data(),
192+ SLOT(toggleConsole()));
193+
194+ addActionToQMenuAndActionHash(toolsMenu,
195+ MenuOption::ResetSensors,
196+ 0, // QML Qt::Key_Apostrophe,
197+ qApp,
198+ SLOT(resetSensors()));
199+
200+ addActionToQMenuAndActionHash(toolsMenu, MenuOption::PackageModel, 0,
201+ qApp, SLOT(packageModel()));
202+
203+ MenuWrapper* avatarMenu = addMenu("Avatar");
204+ QObject* avatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
205+
206+ MenuWrapper* avatarSizeMenu = avatarMenu->addMenu("Size");
207+ addActionToQMenuAndActionHash(avatarSizeMenu,
208+ MenuOption::IncreaseAvatarSize,
209+ 0, // QML Qt::Key_Plus,
210+ avatar,
211+ SLOT(increaseSize()));
212+ addActionToQMenuAndActionHash(avatarSizeMenu,
213+ MenuOption::DecreaseAvatarSize,
214+ 0, // QML Qt::Key_Minus,
215+ avatar,
216+ SLOT(decreaseSize()));
217+ addActionToQMenuAndActionHash(avatarSizeMenu,
218+ MenuOption::ResetAvatarSize,
219+ 0, // QML Qt::Key_Equal,
220+ avatar,
221+ SLOT(resetSize()));
222+
223+ addCheckableActionToQMenuAndActionHash(avatarMenu, MenuOption::KeyboardMotorControl,
224+ Qt::CTRL | Qt::SHIFT | Qt::Key_K, true, avatar, SLOT(updateMotionBehavior()));
225+ addCheckableActionToQMenuAndActionHash(avatarMenu, MenuOption::ScriptedMotorControl, 0, true,
226+ avatar, SLOT(updateMotionBehavior()));
227+ addCheckableActionToQMenuAndActionHash(avatarMenu, MenuOption::NamesAboveHeads, 0, true);
228+ addCheckableActionToQMenuAndActionHash(avatarMenu, MenuOption::GlowWhenSpeaking, 0, true);
229+ addCheckableActionToQMenuAndActionHash(avatarMenu, MenuOption::BlueSpeechSphere, 0, true);
230+ addCheckableActionToQMenuAndActionHash(avatarMenu, MenuOption::EnableCharacterController, 0, true,
231+ avatar, SLOT(updateMotionBehavior()));
232+ addCheckableActionToQMenuAndActionHash(avatarMenu, MenuOption::ShiftHipsForIdleAnimations, 0, false,
233+ avatar, SLOT(updateMotionBehavior()));
194234
195− QAction* redoAction = undoStack->createRedoAction(this);
196− //redoAction->setShortcut(Qt::CTRL | Qt::SHIFT | Qt::Key_Z);
197− addItem(EDIT_MENU, redoAction->text(), redoAction, SLOT(trigger()));
235+ MenuWrapper* viewMenu = addMenu("View");
198236
199− // Qt::CTRL | Qt::Key_Comma
200− // QAction::PreferencesRole
201− addItem(EDIT_MENU, MenuOption::Preferences, [=] {
202− dialogsManager->editPreferences();
203− });
204− addItem(EDIT_MENU, MenuOption::Animations, [=] {
205− dialogsManager->editAnimations();
206− });
207− }
237+ addCheckableActionToQMenuAndActionHash(viewMenu,
238+ MenuOption::Fullscreen,
239+#ifdef Q_OS_MAC
240+ Qt::CTRL | Qt::META | Qt::Key_F,
241+#else
242+ Qt::CTRL | Qt::Key_F,
243+#endif
244+ false,
245+ qApp,
246+ SLOT(setFullscreen(bool)));
247+
248+ addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::FirstPerson,
249+ 0, // QML Qt::Key_P,
250+ true, qApp, SLOT(cameraMenuChanged()));
251+ addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Mirror,
252+ 0, //QML Qt::SHIFT | Qt::Key_H,
253+ true);
254+ addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::FullscreenMirror,
255+ 0, // QML Qt::Key_H,
256+ false, qApp, SLOT(cameraMenuChanged()));
257+
258+ addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::HMDTools,
259+#ifdef Q_OS_MAC
260+ Qt::META | Qt::Key_H,
261+#else
262+ Qt::CTRL | Qt::Key_H,
263+#endif
264+ false,
265+ dialogsManager.data(),
266+ SLOT(hmdTools(bool)));
267+
268+ addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::EnableVRMode, 0,
269+ false,
270+ qApp,
271+ SLOT(setEnableVRMode(bool)));
272+
273+ addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Enable3DTVMode, 0,
274+ false,
275+ qApp,
276+ SLOT(setEnable3DTVMode(bool)));
277+
278+
279+ MenuWrapper* nodeBordersMenu = viewMenu->addMenu("Server Borders");
280+ NodeBounds& nodeBounds = qApp->getNodeBoundsDisplay();
281+ addCheckableActionToQMenuAndActionHash(nodeBordersMenu, MenuOption::ShowBordersEntityNodes,
282+ Qt::CTRL | Qt::SHIFT | Qt::Key_1, false,
283+ &nodeBounds, SLOT(setShowEntityNodes(bool)));
284+
285+ addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::OffAxisProjection, 0, false);
286+ addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::TurnWithHead, 0, false);
287+
288+
289+ addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Stats,
290+ 0); // QML Qt::Key_Slash);
291+ addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Stats);
292+ addActionToQMenuAndActionHash(viewMenu, MenuOption::Log,
293+ Qt::CTRL | Qt::SHIFT | Qt::Key_L,
294+ qApp, SLOT(toggleLogDialog()));
295+ addActionToQMenuAndActionHash(viewMenu, MenuOption::BandwidthDetails, 0,
296+ dialogsManager.data(), SLOT(bandwidthDetails()));
297+ addActionToQMenuAndActionHash(viewMenu, MenuOption::OctreeStats, 0,
298+ dialogsManager.data(), SLOT(octreeStatsDetails()));
299+
300+
301+ MenuWrapper* developerMenu = addMenu("Developer");
302+
303+ MenuWrapper* renderOptionsMenu = developerMenu->addMenu("Render");
304+ addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Atmosphere,
305+ 0, // QML Qt::SHIFT | Qt::Key_A,
306+ true);
307+ addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::AmbientOcclusion);
308+ addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::DontFadeOnOctreeServerChanges);
309+
310+ MenuWrapper* ambientLightMenu = renderOptionsMenu->addMenu(MenuOption::RenderAmbientLight);
311+ QActionGroup* ambientLightGroup = new QActionGroup(ambientLightMenu);
312+ ambientLightGroup->setExclusive(true);
313+ ambientLightGroup->addAction(addCheckableActionToQMenuAndActionHash(ambientLightMenu, MenuOption::RenderAmbientLightGlobal, 0, true));
314+ ambientLightGroup->addAction(addCheckableActionToQMenuAndActionHash(ambientLightMenu, MenuOption::RenderAmbientLight0, 0, false));
315+ ambientLightGroup->addAction(addCheckableActionToQMenuAndActionHash(ambientLightMenu, MenuOption::RenderAmbientLight1, 0, false));
316+ ambientLightGroup->addAction(addCheckableActionToQMenuAndActionHash(ambientLightMenu, MenuOption::RenderAmbientLight2, 0, false));
317+ ambientLightGroup->addAction(addCheckableActionToQMenuAndActionHash(ambientLightMenu, MenuOption::RenderAmbientLight3, 0, false));
318+ ambientLightGroup->addAction(addCheckableActionToQMenuAndActionHash(ambientLightMenu, MenuOption::RenderAmbientLight4, 0, false));
319+ ambientLightGroup->addAction(addCheckableActionToQMenuAndActionHash(ambientLightMenu, MenuOption::RenderAmbientLight5, 0, false));
320+ ambientLightGroup->addAction(addCheckableActionToQMenuAndActionHash(ambientLightMenu, MenuOption::RenderAmbientLight6, 0, false));
321+ ambientLightGroup->addAction(addCheckableActionToQMenuAndActionHash(ambientLightMenu, MenuOption::RenderAmbientLight7, 0, false));
322+ ambientLightGroup->addAction(addCheckableActionToQMenuAndActionHash(ambientLightMenu, MenuOption::RenderAmbientLight8, 0, false));
323+ ambientLightGroup->addAction(addCheckableActionToQMenuAndActionHash(ambientLightMenu, MenuOption::RenderAmbientLight9, 0, false));
324+
325+ MenuWrapper* shadowMenu = renderOptionsMenu->addMenu("Shadows");
326+ QActionGroup* shadowGroup = new QActionGroup(shadowMenu);
327+ shadowGroup->addAction(addCheckableActionToQMenuAndActionHash(shadowMenu, "None", 0, true));
328+ shadowGroup->addAction(addCheckableActionToQMenuAndActionHash(shadowMenu, MenuOption::SimpleShadows, 0, false));
329+ shadowGroup->addAction(addCheckableActionToQMenuAndActionHash(shadowMenu, MenuOption::CascadedShadows, 0, false));
208330
209331 {
210− static const QString TOOLS_MENU{ "Tools" };
211− addMenu(ROOT_MENU, TOOLS_MENU);
212−
213−#if defined(Q_OS_MAC) || defined(Q_OS_WIN)
214− auto speechRecognizer = DependencyManager::get<SpeechRecognizer>();
215− //Qt::CTRL | Qt::SHIFT | Qt::Key_C
216− addItem(TOOLS_MENU, MenuOption::ControlWithSpeech);
217− setChecked(MenuOption::ControlWithSpeech, speechRecognizer->getEnabled());
218− connect(speechRecognizer.data(), &SpeechRecognizer::enabledUpdated, [=] {
219− setChecked(MenuOption::ControlWithSpeech, speechRecognizer->getEnabled());
220− });
332+ MenuWrapper* framerateMenu = renderOptionsMenu->addMenu(MenuOption::RenderTargetFramerate);
333+ QActionGroup* framerateGroup = new QActionGroup(framerateMenu);
334+ framerateGroup->setExclusive(true);
335+ framerateGroup->addAction(addCheckableActionToQMenuAndActionHash(framerateMenu, MenuOption::RenderTargetFramerateUnlimited, 0, true));
336+ framerateGroup->addAction(addCheckableActionToQMenuAndActionHash(framerateMenu, MenuOption::RenderTargetFramerate60, 0, false));
337+ framerateGroup->addAction(addCheckableActionToQMenuAndActionHash(framerateMenu, MenuOption::RenderTargetFramerate50, 0, false));
338+ framerateGroup->addAction(addCheckableActionToQMenuAndActionHash(framerateMenu, MenuOption::RenderTargetFramerate40, 0, false));
339+ framerateGroup->addAction(addCheckableActionToQMenuAndActionHash(framerateMenu, MenuOption::RenderTargetFramerate30, 0, false));
340+
341+#if defined(Q_OS_MAC)
342+#else
343+ addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::RenderTargetFramerateVSyncOn, 0, true,
344+ qApp, SLOT(setVSyncEnabled()));
221345 #endif
222− // Qt::ALT | Qt::Key_S,
223− addItem(TOOLS_MENU, MenuOption::ScriptEditor, [=] {
224− dialogsManager->showScriptEditor();
225− });
226− // QML Qt::Key_Backslash,
227− addItem(TOOLS_MENU, MenuOption::Chat, [=] {
228− dialogsManager->showIRCLink();
229− });
230− addItem(TOOLS_MENU, MenuOption::AddRemoveFriends, [=] {
231− qApp->showFriendsWindow();
232− });
233−
234− {
235− static const QString VIZ_MENU{ "I Am Visible To" };
236− addMenu(TOOLS_MENU, VIZ_MENU);
237− auto discoverabilityManager = DependencyManager::get<DiscoverabilityManager>();
238− // FIXME group
239− addCheckableItem(VIZ_MENU, MenuOption::VisibleToEveryone,
240− discoverabilityManager->getDiscoverabilityMode() == Discoverability::All,
241− discoverabilityManager.data(), SLOT(setVisibility()));
242− addCheckableItem(VIZ_MENU, MenuOption::VisibleToFriends,
243− discoverabilityManager->getDiscoverabilityMode() == Discoverability::Friends,
244− discoverabilityManager.data(), SLOT(setVisibility()));
245− addCheckableItem(VIZ_MENU, MenuOption::VisibleToNoOne,
246− discoverabilityManager->getDiscoverabilityMode() == Discoverability::None,
247− discoverabilityManager.data(), SLOT(setVisibility()));
248− connect(discoverabilityManager.data(), &DiscoverabilityManager::discoverabilityModeChanged,
249− discoverabilityManager.data(), &DiscoverabilityManager::visibilityChanged);
250− }
346+ }
251347
252− //Qt::CTRL | Qt::ALT | Qt::Key_T,
253− addItem(TOOLS_MENU, MenuOption::ToolWindow,
254− dialogsManager.data(), SLOT(toggleToolWindow()));
255348
256− //Qt::CTRL | Qt::ALT | Qt::Key_J,
257− addItem(TOOLS_MENU, MenuOption::Console, [=] {
258− DependencyManager::get<StandAloneJSConsole>()->toggleConsole();
259− });
349+ MenuWrapper* resolutionMenu = renderOptionsMenu->addMenu(MenuOption::RenderResolution);
350+ QActionGroup* resolutionGroup = new QActionGroup(resolutionMenu);
351+ resolutionGroup->setExclusive(true);
352+ resolutionGroup->addAction(addCheckableActionToQMenuAndActionHash(resolutionMenu, MenuOption::RenderResolutionOne, 0, true));
353+ resolutionGroup->addAction(addCheckableActionToQMenuAndActionHash(resolutionMenu, MenuOption::RenderResolutionTwoThird, 0, false));
354+ resolutionGroup->addAction(addCheckableActionToQMenuAndActionHash(resolutionMenu, MenuOption::RenderResolutionHalf, 0, false));
355+ resolutionGroup->addAction(addCheckableActionToQMenuAndActionHash(resolutionMenu, MenuOption::RenderResolutionThird, 0, false));
356+ resolutionGroup->addAction(addCheckableActionToQMenuAndActionHash(resolutionMenu, MenuOption::RenderResolutionQuarter, 0, false));
260357
261− // QML Qt::Key_Apostrophe,
262− addItem(TOOLS_MENU, MenuOption::ResetSensors, [=] {
263− qApp->resetSensors();
264− });
358+ addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Stars,
359+ 0, // QML Qt::Key_Asterisk,
360+ true);
361+ addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::EnableGlowEffect, 0, true,
362+ DependencyManager::get<GlowEffect>().data(), SLOT(toggleGlowEffect(bool)));
265363
266− addItem(TOOLS_MENU, MenuOption::PackageModel, [=] {
267− qApp->packageModel();
268− });
269− }
270−
271− {
272− static const QString AVATAR_MENU{ "Avatar" };
273− addMenu(ROOT_MENU, AVATAR_MENU);
274− auto avatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
275− {
276− static const QString SIZE_MENU{ "Size" };
277− addMenu(AVATAR_MENU, SIZE_MENU);
278− // QML Qt::Key_Plus,
279− addItem(SIZE_MENU, MenuOption::IncreaseAvatarSize, [=] {
280− avatar->increaseSize();
281− });
282− // QML Qt::Key_Minus,
283− addItem(SIZE_MENU, MenuOption::DecreaseAvatarSize, [=] {
284− avatar->decreaseSize();
285− });
286− // QML Qt::Key_Equal,
287− addItem(SIZE_MENU, MenuOption::ResetAvatarSize, [=] {
288− avatar->resetSize();
289− });
290−
291− addItem(SIZE_MENU, MenuOption::ResetAvatarSize, [=] {
292− avatar->resetSize();
293− });
294− }
364+ addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Wireframe, Qt::ALT | Qt::Key_W, false);
365+ addActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::LodTools,
366+ 0, // QML Qt::SHIFT | Qt::Key_L,
367+ dialogsManager.data(), SLOT(lodTools()));
295368
296− //Qt::CTRL | Qt::SHIFT | Qt::Key_K
297− addCheckableItem(AVATAR_MENU, MenuOption::KeyboardMotorControl, true, [=](bool) {
298− avatar->updateMotionBehavior();
299− });
300− addCheckableItem(AVATAR_MENU, MenuOption::ScriptedMotorControl, true);
301− addCheckableItem(AVATAR_MENU, MenuOption::NamesAboveHeads, true);
302− addCheckableItem(AVATAR_MENU, MenuOption::GlowWhenSpeaking, true);
303− addCheckableItem(AVATAR_MENU, MenuOption::BlueSpeechSphere, true);
304− addCheckableItem(AVATAR_MENU, MenuOption::EnableCharacterController, true,
305− avatar, SLOT(updateMotionBehavior()));
306− addCheckableItem(AVATAR_MENU, MenuOption::ShiftHipsForIdleAnimations, false,
307− avatar, SLOT(updateMotionBehavior()));
308− }
369+ MenuWrapper* avatarDebugMenu = developerMenu->addMenu("Avatar");
309370
371+ MenuWrapper* faceTrackingMenu = avatarDebugMenu->addMenu("Face Tracking");
310372 {
311− static const QString VIEW_MENU{ "View" };
312− addMenu(ROOT_MENU, VIEW_MENU);
313−
314− // Mac Qt::CTRL | Qt::META | Qt::Key_F,
315− // Win32/Linux Qt::CTRL | Qt::Key_F,
316− addCheckableItem(VIEW_MENU, MenuOption::Fullscreen, false);
317− connectCheckable(MenuOption::Fullscreen, qApp, SLOT(setFullscreen(bool)));
318− // QML Qt::Key_P,
319− addCheckableItem(VIEW_MENU, MenuOption::FirstPerson, true,
320− qApp, SLOT(cameraMenuChanged()));
321− //QML Qt::SHIFT | Qt::Key_H,
322− addCheckableItem(VIEW_MENU, MenuOption::Mirror, true,
323− qApp, SLOT(cameraMenuChanged()));
324− // QML Qt::Key_H,
325− addCheckableItem(VIEW_MENU, MenuOption::FullscreenMirror, false,
326− qApp, SLOT(cameraMenuChanged()));
327−
328−
329− // Mac Qt::META | Qt::Key_H,
330− // Win32/Linux Qt::CTRL | Qt::Key_H,
331− addCheckableItem(VIEW_MENU, MenuOption::HMDTools, false, [=](bool checked) {
332− dialogsManager->hmdTools(checked);
333− });
334− addCheckableItem(VIEW_MENU, MenuOption::EnableVRMode, false);
335− connectCheckable(MenuOption::EnableVRMode, qApp, SLOT(setEnableVRMode(bool)));
336− addCheckableItem(VIEW_MENU, MenuOption::Enable3DTVMode, false);
337− connectCheckable(MenuOption::Enable3DTVMode, qApp, SLOT(setEnable3DTVMode(bool)));
338−
339− {
340− static const QString BORDER_MENU{ "Server Borders" };
341− addMenu(VIEW_MENU, BORDER_MENU);
342− // Qt::CTRL | Qt::SHIFT | Qt::Key_1
343− addCheckableItem(BORDER_MENU, MenuOption::ShowBordersEntityNodes, false, [=](bool checked) {
344− qApp->getNodeBoundsDisplay().setShowEntityNodes(checked);
345− });
346− }
347− addCheckableItem(VIEW_MENU, MenuOption::OffAxisProjection, false);
348− addCheckableItem(VIEW_MENU, MenuOption::TurnWithHead, false);
349− // QML Qt::Key_Slash
350− addCheckableItem(VIEW_MENU, MenuOption::Stats, false);
351−
352− // Qt::CTRL | Qt::SHIFT | Qt::Key_L
353− addItem(VIEW_MENU, MenuOption::Log, [=] {
354− qApp->toggleLogDialog();
355− });
356− addItem(VIEW_MENU, MenuOption::BandwidthDetails, [=] {
357− dialogsManager->bandwidthDetails();
358− });
359− addItem(VIEW_MENU, MenuOption::OctreeStats, [=] {
360− dialogsManager->octreeStatsDetails();
361− });
362− }
373+ QActionGroup* faceTrackerGroup = new QActionGroup(avatarDebugMenu);
374+
375+ QAction* noFaceTracker = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::NoFaceTracking,
376+ 0, true,
377+ qApp, SLOT(setActiveFaceTracker()));
378+ faceTrackerGroup->addAction(noFaceTracker);
363379
364− {
365− static const QString DEV_MENU{ "Developer" };
366− addMenu(ROOT_MENU, DEV_MENU);
367− {
368− static const QString RENDER_MENU{ "Render" };
369− addMenu(DEV_MENU, RENDER_MENU);
370− // QML Qt::SHIFT | Qt::Key_A,
371− addCheckableItem(RENDER_MENU, MenuOption::Atmosphere, true);
372− addCheckableItem(RENDER_MENU, MenuOption::AmbientOcclusion);
373− addCheckableItem(RENDER_MENU, MenuOption::DontFadeOnOctreeServerChanges);
374− {
375− static const QString LIGHT_MENU{ MenuOption::RenderAmbientLight };
376− addMenu(RENDER_MENU, LIGHT_MENU);
377− static QStringList LIGHTS{
378− MenuOption::RenderAmbientLightGlobal,
379− MenuOption::RenderAmbientLight0,
380− MenuOption::RenderAmbientLight1,
381− MenuOption::RenderAmbientLight2,
382− MenuOption::RenderAmbientLight3,
383− MenuOption::RenderAmbientLight4,
384− MenuOption::RenderAmbientLight5,
385− MenuOption::RenderAmbientLight6,
386− MenuOption::RenderAmbientLight7,
387− MenuOption::RenderAmbientLight8,
388− MenuOption::RenderAmbientLight9,
389− };
390− foreach(QString option, LIGHTS) {
391− addCheckableItem(LIGHT_MENU, option);
392− // FIXME
393− // setExclusiveGroup()
394− }
395− setChecked(MenuOption::RenderAmbientLightGlobal, true);
396− }
397− {
398− static const QString SHADOWS_MENU{ "Shadows" };
399− addMenu(RENDER_MENU, SHADOWS_MENU);
400− addCheckableItem(SHADOWS_MENU, "No Shadows", true);
401− addCheckableItem(SHADOWS_MENU, MenuOption::SimpleShadows);
402− addCheckableItem(SHADOWS_MENU, MenuOption::CascadedShadows);
403− }
404− {
405− static const QString FRAMERATE_MENU{ MenuOption::RenderTargetFramerate };
406− addMenu(RENDER_MENU, FRAMERATE_MENU);
407− //framerateGroup->setExclusive(true);
408− addCheckableItem(FRAMERATE_MENU, MenuOption::RenderTargetFramerateUnlimited, true);
409− addCheckableItem(FRAMERATE_MENU, MenuOption::RenderTargetFramerate60);
410− addCheckableItem(FRAMERATE_MENU, MenuOption::RenderTargetFramerate50);
411− addCheckableItem(FRAMERATE_MENU, MenuOption::RenderTargetFramerate40);
412− addCheckableItem(FRAMERATE_MENU, MenuOption::RenderTargetFramerate30);
413− }
414−#if !defined(Q_OS_MAC)
415− addCheckableItem(RENDER_MENU, MenuOption::RenderTargetFramerateVSyncOn, true, [](bool checked) {
416− qApp->setVSyncEnabled();
417− });
418−#endif
419− {
420− static const QString RES_MENU{ MenuOption::RenderResolution };
421− addMenu(RENDER_MENU, RES_MENU);
422− // resolutionGroup->setExclusive(true);
423− addCheckableItem(RES_MENU, MenuOption::RenderResolutionOne, true);
424− addCheckableItem(RES_MENU, MenuOption::RenderResolutionTwoThird);
425− addCheckableItem(RES_MENU, MenuOption::RenderResolutionHalf);
426− addCheckableItem(RES_MENU, MenuOption::RenderResolutionThird);
427− addCheckableItem(RES_MENU, MenuOption::RenderResolutionQuarter);
428− }
429− // QML Qt::Key_Asterisk,
430− addCheckableItem(RENDER_MENU, MenuOption::Stars, true);
431− addCheckableItem(RENDER_MENU, MenuOption::EnableGlowEffect, true, [](bool checked){
432− DependencyManager::get<GlowEffect>()->toggleGlowEffect(checked);
433− });
434− //Qt::ALT | Qt::Key_W
435− addCheckableItem(RENDER_MENU, MenuOption::Wireframe);
436− // QML Qt::SHIFT | Qt::Key_L,
437− addItem(RENDER_MENU, MenuOption::LodTools, [=] {
438− dialogsManager->lodTools();
439− });
440− } // Developer -> Render
441−
442− {
443− static const QString AVATAR_MENU{ "Avatar Dev" };
444− addMenu(DEV_MENU, AVATAR_MENU);
445− setItemText(AVATAR_MENU, "Avatar");
446− {
447− static const QString FACE_MENU{ "Face Tracking" };
448− addMenu(AVATAR_MENU, FACE_MENU);
449− // FIXME GROUP
450− addCheckableItem(FACE_MENU, MenuOption::NoFaceTracking, true, [](bool checked) {
451− qApp->setActiveFaceTracker();
452− });
453380 #ifdef HAVE_FACESHIFT
454− addCheckableItem(FACE_MENU, MenuOption::Faceshift, true, [](bool checked) {
455− qApp->setActiveFaceTracker();
456− });
381+ QAction* faceshiftFaceTracker = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::Faceshift,
382+ 0, false,
383+ qApp, SLOT(setActiveFaceTracker()));
384+ faceTrackerGroup->addAction(faceshiftFaceTracker);
457385 #endif
458386 #ifdef HAVE_DDE
459− addCheckableItem(FACE_MENU, MenuOption::UseCamera, true, [](bool checked) {
460− qApp->setActiveFaceTracker();
461− });
387+ QAction* ddeFaceTracker = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::UseCamera,
388+ 0, false,
389+ qApp, SLOT(setActiveFaceTracker()));
390+ faceTrackerGroup->addAction(ddeFaceTracker);
391+#endif
392+ }
393+#ifdef HAVE_DDE
394+ faceTrackingMenu->addSeparator();
395+ QAction* useAudioForMouth = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::UseAudioForMouth, 0, true);
396+ useAudioForMouth->setVisible(false);
397+ QAction* ddeFiltering = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::VelocityFilter, 0, true);
398+ ddeFiltering->setVisible(false);
462399 #endif
463− addCheckableItem(FACE_MENU, MenuOption::UseAudioForMouth, true);
464− // FIXME integrate the visibility into the main API
465− getActionForOption(MenuOption::UseAudioForMouth)->setVisible(false);
466400
467− addCheckableItem(FACE_MENU, MenuOption::VelocityFilter, true);
468− // FIXME integrate the visibility into the main API
469− getActionForOption(MenuOption::VelocityFilter)->setVisible(false);
470− }
471− addCheckableItem(AVATAR_MENU, MenuOption::RenderSkeletonCollisionShapes);
472− addCheckableItem(AVATAR_MENU, MenuOption::RenderHeadCollisionShapes);
473− addCheckableItem(AVATAR_MENU, MenuOption::RenderBoundingCollisionShapes);
474− addCheckableItem(AVATAR_MENU, MenuOption::RenderLookAtVectors);
475− addCheckableItem(AVATAR_MENU, MenuOption::RenderFocusIndicator);
476− {
477− static const QString HANDS_MENU{ "Hands" };
478− addMenu(AVATAR_MENU, HANDS_MENU);
479− addCheckableItem(HANDS_MENU, MenuOption::AlignForearmsWithWrists);
480− addCheckableItem(HANDS_MENU, MenuOption::AlternateIK);
481− addCheckableItem(HANDS_MENU, MenuOption::DisplayHands, true);
482− addCheckableItem(HANDS_MENU, MenuOption::DisplayHandTargets);
483− addCheckableItem(HANDS_MENU, MenuOption::ShowIKConstraints);
484− {
485− static const QString SIXENSE_MENU{ "Sixense" };
486− addMenu(HANDS_MENU, SIXENSE_MENU);
401+ addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderSkeletonCollisionShapes);
402+ addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderHeadCollisionShapes);
403+ addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderBoundingCollisionShapes);
404+ addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderLookAtVectors, 0, false);
405+ addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderFocusIndicator, 0, false);
406+
407+ MenuWrapper* handOptionsMenu = developerMenu->addMenu("Hands");
408+ addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::AlignForearmsWithWrists, 0, false);
409+ addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::AlternateIK, 0, false);
410+ addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::DisplayHands, 0, true);
411+ addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::DisplayHandTargets, 0, false);
412+ addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::ShowIKConstraints, 0, false);
413+
414+ MenuWrapper* sixenseOptionsMenu = handOptionsMenu->addMenu("Sixense");
487415 #ifdef __APPLE__
488− addCheckableItem(SIXENSE_MENU, MenuOption::SixenseEnabled, false, [](bool checked) {
489− SixenseManager::getInstance().toggleSixense(checked);
490− });
416+ addCheckableActionToQMenuAndActionHash(sixenseOptionsMenu,
417+ MenuOption::SixenseEnabled,
418+ 0, false,
419+ &SixenseManager::getInstance(),
420+ SLOT(toggleSixense(bool)));
491421 #endif
492− addCheckableItem(SIXENSE_MENU, MenuOption::FilterSixense, true, [](bool checked) {
493− SixenseManager::getInstance().setFilter(checked);
494− });
495− addCheckableItem(SIXENSE_MENU, MenuOption::LowVelocityFilter, true, [](bool checked) {
496− qApp->setLowVelocityFilter(checked);
497− });
498− addCheckableItem(SIXENSE_MENU, MenuOption::SixenseMouseInput, true);
499− addCheckableItem(SIXENSE_MENU, MenuOption::SixenseLasers);
500− }
501−
502− {
503− static const QString LEAP_MENU{ "Leap Motion" };
504− addMenu(HANDS_MENU, LEAP_MENU);
505− addCheckableItem(LEAP_MENU, MenuOption::LeapMotionOnHMD);
506− addCheckableItem(LEAP_MENU, MenuOption::LeapMotionOnHMD);
507− }
422+ addCheckableActionToQMenuAndActionHash(sixenseOptionsMenu,
423+ MenuOption::FilterSixense,
424+ 0,
425+ true,
426+ &SixenseManager::getInstance(),
427+ SLOT(setFilter(bool)));
428+ addCheckableActionToQMenuAndActionHash(sixenseOptionsMenu,
429+ MenuOption::LowVelocityFilter,
430+ 0,
431+ true,
432+ qApp,
433+ SLOT(setLowVelocityFilter(bool)));
434+ addCheckableActionToQMenuAndActionHash(sixenseOptionsMenu, MenuOption::SixenseMouseInput, 0, true);
435+ addCheckableActionToQMenuAndActionHash(sixenseOptionsMenu, MenuOption::SixenseLasers, 0, false);
436+
437+ MenuWrapper* leapOptionsMenu = handOptionsMenu->addMenu("Leap Motion");
438+ addCheckableActionToQMenuAndActionHash(leapOptionsMenu, MenuOption::LeapMotionOnHMD, 0, false);
508439
509440 #ifdef HAVE_RSSDK
510− {
511− static const QString RSS_MENU{ "RealSense" };
512− addMenu(HANDS_MENU, RSS_MENU);
513− addItem(RSS_MENU, MenuOption::LoadRSSDKFile, [] {
514− RealSense::getInstance()->loadRSSDKFile();
515− });
516− addCheckableItem(RSS_MENU, MenuOption::LeapMotionOnHMD);
517− }
441+ QMenu* realSenseOptionsMenu = handOptionsMenu->addMenu("RealSense");
442+ addActionToQMenuAndActionHash(realSenseOptionsMenu, MenuOption::LoadRSSDKFile, 0,
443+ RealSense::getInstance(), SLOT(loadRSSDKFile()));
518444 #endif
519− } // Developer -> Hands
520−
521− {
522− static const QString NETWORK_MENU{ "Network" };
523− addMenu(DEV_MENU, NETWORK_MENU);
524− addCheckableItem(NETWORK_MENU, MenuOption::DisableNackPackets);
525− addCheckableItem(NETWORK_MENU, MenuOption::DisableActivityLogger, false, [](bool checked) {
526− UserActivityLogger::getInstance().disable(checked);
527− });
528− addItem(NETWORK_MENU, MenuOption::CachesSize, [=] {
529− dialogsManager->cachesSizeDialog();
530− });
531− addItem(NETWORK_MENU, MenuOption::DiskCacheEditor, [=] {
532− dialogsManager->toggleDiskCacheEditor();
533− });
534− } // Developer -> Network
535−
536− {
537− static const QString TIMING_MENU{ "Timing and Stats" };
538− addMenu(DEV_MENU, TIMING_MENU);
539− {
540− static const QString PERF_MENU{ "Performance Timer" };
541− addMenu(TIMING_MENU, PERF_MENU);
542− addCheckableItem(PERF_MENU, MenuOption::DisplayDebugTimingDetails);
543− addCheckableItem(PERF_MENU, MenuOption::OnlyDisplayTopTen, true);
544− addCheckableItem(PERF_MENU, MenuOption::ExpandUpdateTiming);
545− addCheckableItem(PERF_MENU, MenuOption::ExpandMyAvatarTiming);
546− addCheckableItem(PERF_MENU, MenuOption::ExpandMyAvatarSimulateTiming);
547− addCheckableItem(PERF_MENU, MenuOption::ExpandOtherAvatarTiming);
548− addCheckableItem(PERF_MENU, MenuOption::ExpandPaintGLTiming);
549− }
550− addCheckableItem(TIMING_MENU, MenuOption::TestPing, true);
551− addCheckableItem(TIMING_MENU, MenuOption::FrameTimer);
552− addItem(TIMING_MENU, MenuOption::RunTimingTests, [] { runTimingTests(); });
553− addCheckableItem(TIMING_MENU, MenuOption::PipelineWarnings);
554− addCheckableItem(TIMING_MENU, MenuOption::SuppressShortTimings);
555− } // Developer -> Timing and Stats
556−
557− {
558− static const QString AUDIO_MENU{ "Audio" };
559− addMenu(DEV_MENU, AUDIO_MENU);
560− auto audioIO = DependencyManager::get<AudioClient>();
561− addCheckableItem(AUDIO_MENU, MenuOption::AudioNoiseReduction, true,
562− audioIO.data(), SLOT(toggleAudioNoiseReduction()));
563− addCheckableItem(AUDIO_MENU, MenuOption::EchoServerAudio, false,
564− audioIO.data(), SLOT(toggleServerEcho()));
565− addCheckableItem(AUDIO_MENU, MenuOption::EchoLocalAudio, false,
566− audioIO.data(), SLOT(toggleLocalEcho()));
567− addCheckableItem(AUDIO_MENU, MenuOption::StereoAudio, false,
568− audioIO.data(), SLOT(toggleStereoInput()));
569− // Qt::CTRL | Qt::Key_M,
570− addCheckableItem(AUDIO_MENU, MenuOption::MuteAudio, false,
571− audioIO.data(), SLOT(toggleMute()));
572− addCheckableItem(AUDIO_MENU, MenuOption::MuteEnvironment, false,
573− audioIO.data(), SLOT(sendMuteEnvironmentPacket()));
574− {
575− static const QString SCOPE_MENU{ "Audio Scope" };
576− addMenu(AUDIO_MENU, SCOPE_MENU);
577− auto scope = DependencyManager::get<AudioScope>();
578− // Qt::CTRL | Qt::Key_P
579− addCheckableItem(SCOPE_MENU, MenuOption::AudioScope, false, [=](bool checked) {
580− scope->toggle();
581− });
582− // Qt::CTRL | Qt::SHIFT | Qt::Key_P
583− addCheckableItem(SCOPE_MENU, MenuOption::AudioScopePause, false, [=](bool checked) {
584− scope->togglePause();
585− });
586− addSeparator(SCOPE_MENU, "Display Frames");
587−
588− // FIXME GROUP
589− addCheckableItem(SCOPE_MENU, MenuOption::AudioScopeFiveFrames, true, [=](bool checked) {
590− scope->selectAudioScopeFiveFrames();
591− });
592− addCheckableItem(SCOPE_MENU, MenuOption::AudioScopeTwentyFrames, false, [=](bool checked) {
593− scope->selectAudioScopeTwentyFrames();
594− });
595− addCheckableItem(SCOPE_MENU, MenuOption::AudioScopeFiftyFrames, false, [=](bool checked) {
596− scope->selectAudioScopeFiftyFrames();
597− });
598− }
599− auto statsRenderer = DependencyManager::get<AudioIOStatsRenderer>();
600−
601− // Qt::CTRL | Qt::SHIFT | Qt::Key_A,
602− addCheckableItem(AUDIO_MENU, MenuOption::AudioStats, false, [=](bool checked) {
603− statsRenderer->toggle();
604− });
605− addCheckableItem(AUDIO_MENU, MenuOption::AudioStatsShowInjectedStreams, false, [=](bool checked) {
606− statsRenderer->toggleShowInjectedStreams();
607− });
608− } // Developer -> Audio
609− } // Developer
610−
611− {
612− static const QString HELP_MENU{ "Help" };
613− addMenu(ROOT_MENU, HELP_MENU);
614− addItem(HELP_MENU, MenuOption::EditEntitiesHelp, [] {
615− qApp->showEditEntitiesHelp();
616− });
617− addItem(HELP_MENU, MenuOption::AboutApp, [] {
618− qApp->aboutApp();
619− });
620− } // Help
445+
446+ MenuWrapper* networkMenu = developerMenu->addMenu("Network");
447+ addCheckableActionToQMenuAndActionHash(networkMenu, MenuOption::DisableNackPackets, 0, false);
448+ addCheckableActionToQMenuAndActionHash(networkMenu,
449+ MenuOption::DisableActivityLogger,
450+ 0,
451+ false,
452+ &UserActivityLogger::getInstance(),
453+ SLOT(disable(bool)));
454+ addActionToQMenuAndActionHash(networkMenu, MenuOption::CachesSize, 0,
455+ dialogsManager.data(), SLOT(cachesSizeDialog()));
456+ addActionToQMenuAndActionHash(networkMenu, MenuOption::DiskCacheEditor, 0,
457+ dialogsManager.data(), SLOT(toggleDiskCacheEditor()));
458+
459+ MenuWrapper* timingMenu = developerMenu->addMenu("Timing and Stats");
460+ MenuWrapper* perfTimerMenu = timingMenu->addMenu("Performance Timer");
461+ addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::DisplayDebugTimingDetails, 0, false);
462+ addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::OnlyDisplayTopTen, 0, true);
463+ addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::ExpandUpdateTiming, 0, false);
464+ addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::ExpandMyAvatarTiming, 0, false);
465+ addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::ExpandMyAvatarSimulateTiming, 0, false);
466+ addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::ExpandOtherAvatarTiming, 0, false);
467+ addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::ExpandPaintGLTiming, 0, false);
468+
469+ addCheckableActionToQMenuAndActionHash(timingMenu, MenuOption::TestPing, 0, true);
470+ addCheckableActionToQMenuAndActionHash(timingMenu, MenuOption::FrameTimer);
471+ addActionToQMenuAndActionHash(timingMenu, MenuOption::RunTimingTests, 0, qApp, SLOT(runTests()));
472+ addCheckableActionToQMenuAndActionHash(timingMenu, MenuOption::PipelineWarnings);
473+ addCheckableActionToQMenuAndActionHash(timingMenu, MenuOption::SuppressShortTimings);
474+
475+ auto audioIO = DependencyManager::get<AudioClient>();
476+ MenuWrapper* audioDebugMenu = developerMenu->addMenu("Audio");
477+ addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::AudioNoiseReduction,
478+ 0,
479+ true,
480+ audioIO.data(),
481+ SLOT(toggleAudioNoiseReduction()));
482+
483+ addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::EchoServerAudio, 0, false,
484+ audioIO.data(), SLOT(toggleServerEcho()));
485+ addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::EchoLocalAudio, 0, false,
486+ audioIO.data(), SLOT(toggleLocalEcho()));
487+ addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::StereoAudio, 0, false,
488+ audioIO.data(), SLOT(toggleStereoInput()));
489+ addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::MuteAudio,
490+ Qt::CTRL | Qt::Key_M,
491+ false,
492+ audioIO.data(),
493+ SLOT(toggleMute()));
494+ addActionToQMenuAndActionHash(audioDebugMenu,
495+ MenuOption::MuteEnvironment,
496+ 0,
497+ audioIO.data(),
498+ SLOT(sendMuteEnvironmentPacket()));
499+
500+ auto scope = DependencyManager::get<AudioScope>();
501+
502+ MenuWrapper* audioScopeMenu = audioDebugMenu->addMenu("Audio Scope");
503+ addCheckableActionToQMenuAndActionHash(audioScopeMenu, MenuOption::AudioScope,
504+ Qt::CTRL | Qt::Key_P, false,
505+ scope.data(),
506+ SLOT(toggle()));
507+ addCheckableActionToQMenuAndActionHash(audioScopeMenu, MenuOption::AudioScopePause,
508+ Qt::CTRL | Qt::SHIFT | Qt::Key_P ,
509+ false,
510+ scope.data(),
511+ SLOT(togglePause()));
512+ addDisabledActionAndSeparator(audioScopeMenu, "Display Frames");
513+ {
514+ QAction *fiveFrames = addCheckableActionToQMenuAndActionHash(audioScopeMenu, MenuOption::AudioScopeFiveFrames,
515+ 0,
516+ true,
517+ scope.data(),
518+ SLOT(selectAudioScopeFiveFrames()));
519+
520+ QAction *twentyFrames = addCheckableActionToQMenuAndActionHash(audioScopeMenu, MenuOption::AudioScopeTwentyFrames,
521+ 0,
522+ false,
523+ scope.data(),
524+ SLOT(selectAudioScopeTwentyFrames()));
525+
526+ QAction *fiftyFrames = addCheckableActionToQMenuAndActionHash(audioScopeMenu, MenuOption::AudioScopeFiftyFrames,
527+ 0,
528+ false,
529+ scope.data(),
530+ SLOT(selectAudioScopeFiftyFrames()));
531+
532+ QActionGroup* audioScopeFramesGroup = new QActionGroup(audioScopeMenu);
533+ audioScopeFramesGroup->addAction(fiveFrames);
534+ audioScopeFramesGroup->addAction(twentyFrames);
535+ audioScopeFramesGroup->addAction(fiftyFrames);
621536 }
537+
538+ auto statsRenderer = DependencyManager::get<AudioIOStatsRenderer>();
539+ addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::AudioStats,
540+ Qt::CTRL | Qt::SHIFT | Qt::Key_A,
541+ false,
542+ statsRenderer.data(),
543+ SLOT(toggle()));
544+
545+ addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::AudioStatsShowInjectedStreams,
546+ 0,
547+ false,
548+ statsRenderer.data(),
549+ SLOT(toggleShowInjectedStreams()));
550+
551+ MenuWrapper* helpMenu = addMenu("Help");
552+ addActionToQMenuAndActionHash(helpMenu, MenuOption::EditEntitiesHelp, 0, qApp, SLOT(showEditEntitiesHelp()));
553+
554+#ifndef Q_OS_MAC
555+ QAction* aboutAction = helpMenu->addAction(MenuOption::AboutApp);
556+ connect(aboutAction, SIGNAL(triggered()), qApp, SLOT(aboutApp()));
557+#endif
622558 }
623559
624560 void Menu::loadSettings() {
625−// scanMenuBar(&Menu::loadAction);
561+ scanMenuBar(&Menu::loadAction);
626562 }
627563
628564 void Menu::saveSettings() {
629−// scanMenuBar(&Menu::saveAction);
565+ scanMenuBar(&Menu::saveAction);
630566 }
631567
632−void Menu::addMenuItem(const MenuItemProperties& properties) {
633− if (QThread::currentThread() != Application::getInstance()->getMainThread()) {
634− Application::getInstance()->postLambdaEvent([=]{
635− addMenuItem(properties);
636− });
637− return;
638− }
639− // Shortcut key items: in order of priority
640− //QString shortcutKey;
641− //KeyEvent shortcutKeyEvent;
642− //QKeySequence shortcutKeySequence; // this is what we actually use, it's set from one of the above
643−
644− //// location related items: in order of priority
645− //int position;
646− //QString beforeItem;
647− //QString afterItem;
648−
649− if (properties.isSeparator) {
650− addSeparator(properties.menuName, properties.menuItemName);
651− return;
652− }
653− addItem(properties.menuName, properties.menuItemName);
654− if (properties.isCheckable) {
655− setCheckable(properties.menuItemName);
656− if (properties.isChecked) {
657− setChecked(properties.menuItemName);
658− }
659− }
660− }
661−
662−#if 0
663−
664568 void Menu::loadAction(Settings& settings, QAction& action) {
665569 if (action.isChecked() != settings.value(action.text(), action.isChecked()).toBool()) {
666570 action.trigger();
@@ -690,7 +594,7 @@ void Menu::scanMenu(QMenu& menu, settingsAction modifySetting, Settings& setting · 23 unmodified lines
690594 settings.endGroup();
691595 }
692596
693−void Menu::addDisabledActionAndSeparator(QMenu* destinationMenu, const QString& actionName, int menuItemLocation) {
597+void Menu::addDisabledActionAndSeparator(MenuWrapper* destinationMenu, const QString& actionName, int menuItemLocation) {
694598 QAction* actionBefore = NULL;
695599 if (menuItemLocation >= 0 && destinationMenu->actions().size() > menuItemLocation) {
696600 actionBefore = destinationMenu->actions()[menuItemLocation];
@@ -710,5 +614,406 @@ void Menu::addDisabledActionAndSeparator(QMenu* destinationMenu, const QString& · 13 unmodified lines
710614 }
711615 }
712616
617+QAction* Menu::addActionToQMenuAndActionHash(MenuWrapper* destinationMenu,
618+ const QString& actionName,
619+ const QKeySequence& shortcut,
620+ const QObject* receiver,
621+ const char* member,
622+ QAction::MenuRole role,
623+ int menuItemLocation) {
624+ QAction* action = NULL;
625+ QAction* actionBefore = NULL;
713626
714−#endif
627+ if (menuItemLocation >= 0 && destinationMenu->actions().size() > menuItemLocation) {
628+ actionBefore = destinationMenu->actions()[menuItemLocation];
629+ }
630+
631+ if (!actionBefore) {
632+ if (receiver && member) {
633+ action = destinationMenu->addAction(actionName, receiver, member, shortcut);
634+ } else {
635+ action = destinationMenu->addAction(actionName);
636+ action->setShortcut(shortcut);
637+ }
638+ } else {
639+ action = new QAction(actionName, destinationMenu);
640+ action->setShortcut(shortcut);
641+ destinationMenu->insertAction(actionBefore, action);
642+
643+ if (receiver && member) {
644+ connect(action, SIGNAL(triggered()), receiver, member);
645+ }
646+ }
647+ action->setMenuRole(role);
648+
649+ _actionHash.insert(actionName, action);
650+
651+ return action;
652+}
653+
654+QAction* Menu::addActionToQMenuAndActionHash(MenuWrapper* destinationMenu,
655+ QAction* action,
656+ const QString& actionName,
657+ const QKeySequence& shortcut,
658+ QAction::MenuRole role,
659+ int menuItemLocation) {
660+ QAction* actionBefore = NULL;
661+
662+ if (menuItemLocation >= 0 && destinationMenu->actions().size() > menuItemLocation) {
663+ actionBefore = destinationMenu->actions()[menuItemLocation];
664+ }
665+
666+ if (!actionName.isEmpty()) {
667+ action->setText(actionName);
668+ }
669+
670+ if (shortcut != 0) {
671+ action->setShortcut(shortcut);
672+ }
673+
674+ if (role != QAction::NoRole) {
675+ action->setMenuRole(role);
676+ }
677+
678+ if (!actionBefore) {
679+ destinationMenu->addAction(action);
680+ } else {
681+ destinationMenu->insertAction(actionBefore, action);
682+ }
683+
684+ _actionHash.insert(action->text(), action);
685+
686+ return action;
687+}
688+
689+QAction* Menu::addCheckableActionToQMenuAndActionHash(MenuWrapper* destinationMenu,
690+ const QString& actionName,
691+ const QKeySequence& shortcut,
692+ const bool checked,
693+ const QObject* receiver,
694+ const char* member,
695+ int menuItemLocation) {
696+
697+ QAction* action = addActionToQMenuAndActionHash(destinationMenu, actionName, shortcut, receiver, member,
698+ QAction::NoRole, menuItemLocation);
699+ action->setCheckable(true);
700+ action->setChecked(checked);
701+
702+ return action;
703+}
704+
705+void Menu::removeAction(MenuWrapper* menu, const QString& actionName) {
706+ menu->removeAction(_actionHash.value(actionName));
707+ _actionHash.remove(actionName);
708+}
709+
710+void Menu::setIsOptionChecked(const QString& menuOption, bool isChecked) {
711+ if (thread() != QThread::currentThread()) {
712+ QMetaObject::invokeMethod(Menu::getInstance(), "setIsOptionChecked", Qt::BlockingQueuedConnection,
713+ Q_ARG(const QString&, menuOption),
714+ Q_ARG(bool, isChecked));
715+ return;
716+ }
717+ QAction* menu = _actionHash.value(menuOption);
718+ if (menu) {
719+ menu->setChecked(isChecked);
720+ }
721+}
722+
723+bool Menu::isOptionChecked(const QString& menuOption) const {
724+ const QAction* menu = _actionHash.value(menuOption);
725+ if (menu) {
726+ return menu->isChecked();
727+ }
728+ return false;
729+}
730+
731+void Menu::triggerOption(const QString& menuOption) {
732+ QAction* action = _actionHash.value(menuOption);
733+ if (action) {
734+ action->trigger();
735+ } else {
736+ qCDebug(interfaceapp) << "NULL Action for menuOption '" << menuOption << "'";
737+ }
738+}
739+
740+QAction* Menu::getActionForOption(const QString& menuOption) {
741+ return _actionHash.value(menuOption);
742+}
743+
744+QAction* Menu::getActionFromName(const QString& menuName, MenuWrapper* menu) {
745+ QList<QAction*> menuActions;
746+ if (menu) {
747+ menuActions = menu->actions();
748+ } else {
749+ menuActions = actions();
750+ }
751+
752+ foreach (QAction* menuAction, menuActions) {
753+ QString actionText = menuAction->text();
754+ if (menuName == menuAction->text()) {
755+ return menuAction;
756+ }
757+ }
758+ return NULL;
759+}
760+
761+MenuWrapper* Menu::getSubMenuFromName(const QString& menuName, MenuWrapper* menu) {
762+ QAction* action = getActionFromName(menuName, menu);
763+ if (action) {
764+ return MenuWrapper::fromMenu(action->menu());
765+ }
766+ return NULL;
767+}
768+
769+MenuWrapper* Menu::getMenuParent(const QString& menuName, QString& finalMenuPart) {
770+ QStringList menuTree = menuName.split(">");
771+ MenuWrapper* parent = NULL;
772+ MenuWrapper* menu = NULL;
773+ foreach (QString menuTreePart, menuTree) {
774+ parent = menu;
775+ finalMenuPart = menuTreePart.trimmed();
776+ menu = getSubMenuFromName(finalMenuPart, parent);
777+ if (!menu) {
778+ break;
779+ }
780+ }
781+ return parent;
782+}
783+
784+MenuWrapper* Menu::getMenu(const QString& menuName) {
785+ QStringList menuTree = menuName.split(">");
786+ MenuWrapper* parent = NULL;
787+ MenuWrapper* menu = NULL;
788+ int item = 0;
789+ foreach (QString menuTreePart, menuTree) {
790+ menu = getSubMenuFromName(menuTreePart.trimmed(), parent);
791+ if (!menu) {
792+ break;
793+ }
794+ parent = menu;
795+ item++;
796+ }
797+ return menu;
798+}
799+
800+QAction* Menu::getMenuAction(const QString& menuName) {
801+ QStringList menuTree = menuName.split(">");
802+ MenuWrapper* parent = NULL;
803+ QAction* action = NULL;
804+ foreach (QString menuTreePart, menuTree) {
805+ action = getActionFromName(menuTreePart.trimmed(), parent);
806+ if (!action) {
807+ break;
808+ }
809+ parent = MenuWrapper::fromMenu(action->menu());
810+ }
811+ return action;
812+}
813+
814+int Menu::findPositionOfMenuItem(MenuWrapper* menu, const QString& searchMenuItem) {
815+ int position = 0;
816+ foreach(QAction* action, menu->actions()) {
817+ if (action->text() == searchMenuItem) {
818+ return position;
819+ }
820+ position++;
821+ }
822+ return UNSPECIFIED_POSITION; // not found
823+}
824+
825+int Menu::positionBeforeSeparatorIfNeeded(MenuWrapper* menu, int requestedPosition) {
826+ QList<QAction*> menuActions = menu->actions();
827+ if (requestedPosition > 1 && requestedPosition < menuActions.size()) {
828+ QAction* beforeRequested = menuActions[requestedPosition - 1];
829+ if (beforeRequested->isSeparator()) {
830+ requestedPosition--;
831+ }
832+ }
833+ return requestedPosition;
834+}
835+
836+
837+MenuWrapper* Menu::addMenu(const QString& menuName) {
838+ QStringList menuTree = menuName.split(">");
839+ MenuWrapper* addTo = NULL;
840+ MenuWrapper* menu = NULL;
841+ foreach (QString menuTreePart, menuTree) {
842+ menu = getSubMenuFromName(menuTreePart.trimmed(), addTo);
843+ if (!menu) {
844+ if (!addTo) {
845+ menu = new MenuWrapper(QMenuBar::addMenu(menuTreePart.trimmed()));
846+ } else {
847+ menu = addTo->addMenu(menuTreePart.trimmed());
848+ }
849+ }
850+ addTo = menu;
851+ }
852+
853+ QMenuBar::repaint();
854+ return menu;
855+}
856+
857+void Menu::removeMenu(const QString& menuName) {
858+ QAction* action = getMenuAction(menuName);
859+
860+ // only proceed if the menu actually exists
861+ if (action) {
862+ QString finalMenuPart;
863+ MenuWrapper* parent = getMenuParent(menuName, finalMenuPart);
864+ if (parent) {
865+ parent->removeAction(action);
866+ } else {
867+ QMenuBar::removeAction(action);
868+ }
869+
870+ QMenuBar::repaint();
871+ }
872+}
873+
874+bool Menu::menuExists(const QString& menuName) {
875+ QAction* action = getMenuAction(menuName);
876+
877+ // only proceed if the menu actually exists
878+ if (action) {
879+ return true;
880+ }
881+ return false;
882+}
883+
884+void Menu::addSeparator(const QString& menuName, const QString& separatorName) {
885+ MenuWrapper* menuObj = getMenu(menuName);
886+ if (menuObj) {
887+ addDisabledActionAndSeparator(menuObj, separatorName);
888+ }
889+}
890+
891+void Menu::removeSeparator(const QString& menuName, const QString& separatorName) {
892+ MenuWrapper* menu = getMenu(menuName);
893+ bool separatorRemoved = false;
894+ if (menu) {
895+ int textAt = findPositionOfMenuItem(menu, separatorName);
896+ QList<QAction*> menuActions = menu->actions();
897+ QAction* separatorText = menuActions[textAt];
898+ if (textAt > 0 && textAt < menuActions.size()) {
899+ QAction* separatorLine = menuActions[textAt - 1];
900+ if (separatorLine) {
901+ if (separatorLine->isSeparator()) {
902+ menu->removeAction(separatorText);
903+ menu->removeAction(separatorLine);
904+ separatorRemoved = true;
905+ }
906+ }
907+ }
908+ }
909+ if (separatorRemoved) {
910+ QMenuBar::repaint();
911+ }
912+}
913+
914+void Menu::addMenuItem(const MenuItemProperties& properties) {
915+ MenuWrapper* menuObj = getMenu(properties.menuName);
916+ if (menuObj) {
917+ QShortcut* shortcut = NULL;
918+ if (!properties.shortcutKeySequence.isEmpty()) {
919+ shortcut = new QShortcut(properties.shortcutKeySequence, this);
920+ }
921+
922+ // check for positioning requests
923+ int requestedPosition = properties.position;
924+ if (requestedPosition == UNSPECIFIED_POSITION && !properties.beforeItem.isEmpty()) {
925+ requestedPosition = findPositionOfMenuItem(menuObj, properties.beforeItem);
926+ // double check that the requested location wasn't a separator label
927+ requestedPosition = positionBeforeSeparatorIfNeeded(menuObj, requestedPosition);
928+ }
929+ if (requestedPosition == UNSPECIFIED_POSITION && !properties.afterItem.isEmpty()) {
930+ int afterPosition = findPositionOfMenuItem(menuObj, properties.afterItem);
931+ if (afterPosition != UNSPECIFIED_POSITION) {
932+ requestedPosition = afterPosition + 1;
933+ }
934+ }
935+
936+ QAction* menuItemAction = NULL;
937+ if (properties.isSeparator) {
938+ addDisabledActionAndSeparator(menuObj, properties.menuItemName, requestedPosition);
939+ } else if (properties.isCheckable) {
940+ menuItemAction = addCheckableActionToQMenuAndActionHash(menuObj, properties.menuItemName,
941+ properties.shortcutKeySequence, properties.isChecked,
942+ MenuScriptingInterface::getInstance(), SLOT(menuItemTriggered()), requestedPosition);
943+ } else {
944+ menuItemAction = addActionToQMenuAndActionHash(menuObj, properties.menuItemName, properties.shortcutKeySequence,
945+ MenuScriptingInterface::getInstance(), SLOT(menuItemTriggered()),
946+ QAction::NoRole, requestedPosition);
947+ }
948+ if (shortcut && menuItemAction) {
949+ connect(shortcut, SIGNAL(activated()), menuItemAction, SLOT(trigger()));
950+ }
951+ QMenuBar::repaint();
952+ }
953+}
954+
955+void Menu::removeMenuItem(const QString& menu, const QString& menuitem) {
956+ MenuWrapper* menuObj = getMenu(menu);
957+ if (menuObj) {
958+ removeAction(menuObj, menuitem);
959+ QMenuBar::repaint();
960+ }
961+};
962+
963+bool Menu::menuItemExists(const QString& menu, const QString& menuitem) {
964+ QAction* menuItemAction = _actionHash.value(menuitem);
965+ if (menuItemAction) {
966+ return (getMenu(menu) != NULL);
967+ }
968+ return false;
969+};
970+
971+
972+MenuWrapper::MenuWrapper(QMenu* menu) : _realMenu(menu) {
973+ VrMenu::instance()->addMenu(menu);
974+ _backMap[menu] = this;
975+}
976+
977+QList<QAction*> MenuWrapper::actions() {
978+ return _realMenu->actions();
979+}
980+
981+MenuWrapper* MenuWrapper::addMenu(const QString& menuName) {
982+ return new MenuWrapper(_realMenu->addMenu(menuName));
983+}
984+
985+void MenuWrapper::setEnabled(bool enabled) {
986+ _realMenu->setEnabled(enabled);
987+}
988+
989+void MenuWrapper::addSeparator() {
990+ _realMenu->addSeparator();
991+}
992+
993+void MenuWrapper::addAction(QAction* action) {
994+ _realMenu->addAction(action);
995+ VrMenu::instance()->addAction(_realMenu, action);
996+}
997+
998+QAction* MenuWrapper::addAction(const QString& menuName) {
999+ QAction* action = _realMenu->addAction(menuName);
1000+ VrMenu::instance()->addAction(_realMenu, action);
1001+ return action;
1002+}
1003+
1004+QAction* MenuWrapper::addAction(const QString& menuName, const QObject* receiver, const char* member, const QKeySequence& shortcut) {
1005+ QAction* action = _realMenu->addAction(menuName, receiver, member, shortcut);
1006+ VrMenu::instance()->addAction(_realMenu, action);
1007+ return action;
1008+}
1009+
1010+void MenuWrapper::removeAction(QAction* action) {
1011+ _realMenu->removeAction(action);
1012+}
1013+
1014+void MenuWrapper::insertAction(QAction* before, QAction* action) {
1015+ _realMenu->insertAction(before, action);
1016+ VrMenu::instance()->insertAction(before, action);
1017+}
1018+
1019+QHash<QMenu*, MenuWrapper*> MenuWrapper::_backMap;

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t