Showing the changes to interface/src/Menu.cpp (1 of 30 files). Show all
Unified · Split
| @@ -12,7 +12,6 @@ · 11 unmodified lines | |||
| 12 | #include <QFileDialog> | 12 | #include <QFileDialog> |
| 13 | #include <QMenuBar> | 13 | #include <QMenuBar> |
| 14 | #include <QShortcut> | 14 | #include <QShortcut> |
| 15 | #include <QQmlContext> | ||
| 16 | 15 | ||
| 17 | #include <AddressManager.h> | 16 | #include <AddressManager.h> |
| 18 | #include <AudioClient.h> | 17 | #include <AudioClient.h> |
| @@ -21,7 +20,8 @@ · 2 unmodified lines | |||
| 21 | #include <PathUtils.h> | 20 | #include <PathUtils.h> |
| 22 | #include <SettingHandle.h> | 21 | #include <SettingHandle.h> |
| 23 | #include <UserActivityLogger.h> | 22 | #include <UserActivityLogger.h> |
| 24 | #include <OffscreenUi.h> | 23 | #include <HifiMenu.h> |
| 24 | |||
| 25 | #include "Application.h" | 25 | #include "Application.h" |
| 26 | #include "AccountManager.h" | 26 | #include "AccountManager.h" |
| 27 | #include "audio/AudioIOStatsRenderer.h" | 27 | #include "audio/AudioIOStatsRenderer.h" |
| @@ -42,625 +42,529 @@ · 14 unmodified lines | |||
| 42 | #include "InterfaceLogging.h" | 42 | #include "InterfaceLogging.h" |
| 43 | 43 | ||
| 44 | #include "Menu.h" | 44 | #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 | } | ||
| 58 | 45 | ||
| 59 | void HifiAction::setVisible(bool visible) { | 46 | Menu* Menu::_instance = NULL; |
| 60 | return Menu::getInstance()->setItemVisible(_menuOption); | ||
| 61 | } | ||
| 62 | 47 | ||
| 63 | QString HifiAction::shortcut() const { | 48 | Menu* Menu::getInstance() { |
| 64 | return Menu::getInstance()->getItemShortcut(_menuOption); | 49 | static QMutex menuInstanceMutex; |
| 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 | } | ||
| 78 | 50 | ||
| 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(); | ||
| 80 | 53 | ||
| 81 | Menu* Menu::getInstance() { | ||
| 82 | // Optimistic check for menu existence | ||
| 83 | if (!_instance) { | 54 | if (!_instance) { |
| 84 | static QMutex menuInstanceMutex; | 55 | qCDebug(interfaceapp, "First call to Menu::getInstance() - initing menu."); |
| 85 | withLock(menuInstanceMutex, [] { | 56 | _instance = new Menu(); |
| 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 | }); | ||
| 99 | } | 57 | } |
| 100 | return _instance; | ||
| 101 | } | ||
| 102 | 58 | ||
| 103 | Menu::Menu(QQuickItem* parent) : HifiMenu(parent) { | 59 | menuInstanceMutex.unlock(); |
| 60 | |||
| 61 | return _instance; | ||
| 104 | } | 62 | } |
| 105 | 63 | ||
| 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 | ||
| 107 | auto dialogsManager = DependencyManager::get<DialogsManager>(); | 69 | auto dialogsManager = DependencyManager::get<DialogsManager>(); |
| 108 | AccountManager& accountManager = AccountManager::getInstance(); | 70 | AccountManager& accountManager = AccountManager::getInstance(); |
| 109 | static const QString ROOT_MENU; | 71 | |
| 110 | { | 72 | { |
| 111 | static const QString FILE_MENU{ "File" }; | 73 | addActionToQMenuAndActionHash(fileMenu, MenuOption::Login); |
| 112 | addMenu(ROOT_MENU, FILE_MENU); | 74 | |
| 113 | { | 75 | // connect to the appropriate signal of the AccountManager so that we can change the Login/Logout menu item |
| 114 | addItem(FILE_MENU, MenuOption::Login); | 76 | connect(&accountManager, &AccountManager::profileChanged, |
| 115 | // connect to the appropriate signal of the AccountManager so that we can change the Login/Logout menu item | ||
| 116 | connect(&accountManager, &AccountManager::profileChanged, | ||
| 117 | dialogsManager.data(), &DialogsManager::toggleLoginDialog); | 77 | dialogsManager.data(), &DialogsManager::toggleLoginDialog); |
| 118 | connect(&accountManager, &AccountManager::logoutComplete, | 78 | connect(&accountManager, &AccountManager::logoutComplete, |
| 119 | dialogsManager.data(), &DialogsManager::toggleLoginDialog); | 79 | 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 | }); | ||
| 183 | } | 80 | } |
| 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())); | ||
| 184 | 141 | ||
| 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"); | ||
| 186 | { | 159 | { |
| 187 | static const QString EDIT_MENU{ "Edit" }; | 160 | QActionGroup* visibilityGroup = new QActionGroup(toolsMenu); |
| 188 | addMenu(ROOT_MENU, EDIT_MENU); | 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 | } | ||
| 189 | 181 | ||
| 190 | QUndoStack* undoStack = qApp->getUndoStack(); | 182 | addActionToQMenuAndActionHash(toolsMenu, |
| 191 | QAction* undoAction = undoStack->createUndoAction(this); | 183 | MenuOption::ToolWindow, |
| 192 | //undoAction->setShortcut(Qt::CTRL | Qt::Key_Z); | 184 | Qt::CTRL | Qt::ALT | Qt::Key_T, |
| 193 | addItem(EDIT_MENU, undoAction->text(), undoAction, SLOT(trigger())); | 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())); | ||
| 194 | 234 | ||
| 195 | QAction* redoAction = undoStack->createRedoAction(this); | 235 | MenuWrapper* viewMenu = addMenu("View"); |
| 196 | //redoAction->setShortcut(Qt::CTRL | Qt::SHIFT | Qt::Key_Z); | ||
| 197 | addItem(EDIT_MENU, redoAction->text(), redoAction, SLOT(trigger())); | ||
| 198 | 236 | ||
| 199 | // Qt::CTRL | Qt::Key_Comma | 237 | addCheckableActionToQMenuAndActionHash(viewMenu, |
| 200 | // QAction::PreferencesRole | 238 | MenuOption::Fullscreen, |
| 201 | addItem(EDIT_MENU, MenuOption::Preferences, [=] { | 239 | #ifdef Q_OS_MAC |
| 202 | dialogsManager->editPreferences(); | 240 | Qt::CTRL | Qt::META | Qt::Key_F, |
| 203 | }); | 241 | #else |
| 204 | addItem(EDIT_MENU, MenuOption::Animations, [=] { | 242 | Qt::CTRL | Qt::Key_F, |
| 205 | dialogsManager->editAnimations(); | 243 | #endif |
| 206 | }); | 244 | false, |
| 207 | } | 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)); | ||
| 208 | 330 | ||
| 209 | { | 331 | { |
| 210 | static const QString TOOLS_MENU{ "Tools" }; | 332 | MenuWrapper* framerateMenu = renderOptionsMenu->addMenu(MenuOption::RenderTargetFramerate); |
| 211 | addMenu(ROOT_MENU, TOOLS_MENU); | 333 | QActionGroup* framerateGroup = new QActionGroup(framerateMenu); |
| 212 | 334 | framerateGroup->setExclusive(true); | |
| 213 | #if defined(Q_OS_MAC) || defined(Q_OS_WIN) | 335 | framerateGroup->addAction(addCheckableActionToQMenuAndActionHash(framerateMenu, MenuOption::RenderTargetFramerateUnlimited, 0, true)); |
| 214 | auto speechRecognizer = DependencyManager::get<SpeechRecognizer>(); | 336 | framerateGroup->addAction(addCheckableActionToQMenuAndActionHash(framerateMenu, MenuOption::RenderTargetFramerate60, 0, false)); |
| 215 | //Qt::CTRL | Qt::SHIFT | Qt::Key_C | 337 | framerateGroup->addAction(addCheckableActionToQMenuAndActionHash(framerateMenu, MenuOption::RenderTargetFramerate50, 0, false)); |
| 216 | addItem(TOOLS_MENU, MenuOption::ControlWithSpeech); | 338 | framerateGroup->addAction(addCheckableActionToQMenuAndActionHash(framerateMenu, MenuOption::RenderTargetFramerate40, 0, false)); |
| 217 | setChecked(MenuOption::ControlWithSpeech, speechRecognizer->getEnabled()); | 339 | framerateGroup->addAction(addCheckableActionToQMenuAndActionHash(framerateMenu, MenuOption::RenderTargetFramerate30, 0, false)); |
| 218 | connect(speechRecognizer.data(), &SpeechRecognizer::enabledUpdated, [=] { | 340 | |
| 219 | setChecked(MenuOption::ControlWithSpeech, speechRecognizer->getEnabled()); | 341 | #if defined(Q_OS_MAC) |
| 220 | }); | 342 | #else |
| 343 | addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::RenderTargetFramerateVSyncOn, 0, true, | ||
| 344 | qApp, SLOT(setVSyncEnabled())); | ||
| 221 | #endif | 345 | #endif |
| 222 | // Qt::ALT | Qt::Key_S, | 346 | } |
| 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 | } | ||
| 251 | 347 | ||
| 252 | //Qt::CTRL | Qt::ALT | Qt::Key_T, | ||
| 253 | addItem(TOOLS_MENU, MenuOption::ToolWindow, | ||
| 254 | dialogsManager.data(), SLOT(toggleToolWindow())); | ||
| 255 | 348 | ||
| 256 | //Qt::CTRL | Qt::ALT | Qt::Key_J, | 349 | MenuWrapper* resolutionMenu = renderOptionsMenu->addMenu(MenuOption::RenderResolution); |
| 257 | addItem(TOOLS_MENU, MenuOption::Console, [=] { | 350 | QActionGroup* resolutionGroup = new QActionGroup(resolutionMenu); |
| 258 | DependencyManager::get<StandAloneJSConsole>()->toggleConsole(); | 351 | resolutionGroup->setExclusive(true); |
| 259 | }); | 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)); | ||
| 260 | 357 | ||
| 261 | // QML Qt::Key_Apostrophe, | 358 | addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Stars, |
| 262 | addItem(TOOLS_MENU, MenuOption::ResetSensors, [=] { | 359 | 0, // QML Qt::Key_Asterisk, |
| 263 | qApp->resetSensors(); | 360 | true); |
| 264 | }); | 361 | addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::EnableGlowEffect, 0, true, |
| 362 | DependencyManager::get<GlowEffect>().data(), SLOT(toggleGlowEffect(bool))); | ||
| 265 | 363 | ||
| 266 | addItem(TOOLS_MENU, MenuOption::PackageModel, [=] { | 364 | addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Wireframe, Qt::ALT | Qt::Key_W, false); |
| 267 | qApp->packageModel(); | 365 | addActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::LodTools, |
| 268 | }); | 366 | 0, // QML Qt::SHIFT | Qt::Key_L, |
| 269 | } | 367 | dialogsManager.data(), SLOT(lodTools())); |
| 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 | } | ||
| 295 | 368 | ||
| 296 | //Qt::CTRL | Qt::SHIFT | Qt::Key_K | 369 | MenuWrapper* avatarDebugMenu = developerMenu->addMenu("Avatar"); |
| 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 | } | ||
| 309 | 370 | ||
| 371 | MenuWrapper* faceTrackingMenu = avatarDebugMenu->addMenu("Face Tracking"); | ||
| 310 | { | 372 | { |
| 311 | static const QString VIEW_MENU{ "View" }; | 373 | QActionGroup* faceTrackerGroup = new QActionGroup(avatarDebugMenu); |
| 312 | addMenu(ROOT_MENU, VIEW_MENU); | 374 | |
| 313 | 375 | QAction* noFaceTracker = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::NoFaceTracking, | |
| 314 | // Mac Qt::CTRL | Qt::META | Qt::Key_F, | 376 | 0, true, |
| 315 | // Win32/Linux Qt::CTRL | Qt::Key_F, | 377 | qApp, SLOT(setActiveFaceTracker())); |
| 316 | addCheckableItem(VIEW_MENU, MenuOption::Fullscreen, false); | 378 | faceTrackerGroup->addAction(noFaceTracker); |
| 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 | } | ||
| 363 | 379 | ||
| 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 | }); | ||
| 453 | #ifdef HAVE_FACESHIFT | 380 | #ifdef HAVE_FACESHIFT |
| 454 | addCheckableItem(FACE_MENU, MenuOption::Faceshift, true, [](bool checked) { | 381 | QAction* faceshiftFaceTracker = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::Faceshift, |
| 455 | qApp->setActiveFaceTracker(); | 382 | 0, false, |
| 456 | }); | 383 | qApp, SLOT(setActiveFaceTracker())); |
| 384 | faceTrackerGroup->addAction(faceshiftFaceTracker); | ||
| 457 | #endif | 385 | #endif |
| 458 | #ifdef HAVE_DDE | 386 | #ifdef HAVE_DDE |
| 459 | addCheckableItem(FACE_MENU, MenuOption::UseCamera, true, [](bool checked) { | 387 | QAction* ddeFaceTracker = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::UseCamera, |
| 460 | qApp->setActiveFaceTracker(); | 388 | 0, false, |
| 461 | }); | 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); | ||
| 462 | #endif | 399 | #endif |
| 463 | addCheckableItem(FACE_MENU, MenuOption::UseAudioForMouth, true); | ||
| 464 | // FIXME integrate the visibility into the main API | ||
| 465 | getActionForOption(MenuOption::UseAudioForMouth)->setVisible(false); | ||
| 466 | 400 | ||
| 467 | addCheckableItem(FACE_MENU, MenuOption::VelocityFilter, true); | 401 | addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderSkeletonCollisionShapes); |
| 468 | // FIXME integrate the visibility into the main API | 402 | addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderHeadCollisionShapes); |
| 469 | getActionForOption(MenuOption::VelocityFilter)->setVisible(false); | 403 | addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderBoundingCollisionShapes); |
| 470 | } | 404 | addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderLookAtVectors, 0, false); |
| 471 | addCheckableItem(AVATAR_MENU, MenuOption::RenderSkeletonCollisionShapes); | 405 | addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderFocusIndicator, 0, false); |
| 472 | addCheckableItem(AVATAR_MENU, MenuOption::RenderHeadCollisionShapes); | 406 | |
| 473 | addCheckableItem(AVATAR_MENU, MenuOption::RenderBoundingCollisionShapes); | 407 | MenuWrapper* handOptionsMenu = developerMenu->addMenu("Hands"); |
| 474 | addCheckableItem(AVATAR_MENU, MenuOption::RenderLookAtVectors); | 408 | addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::AlignForearmsWithWrists, 0, false); |
| 475 | addCheckableItem(AVATAR_MENU, MenuOption::RenderFocusIndicator); | 409 | addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::AlternateIK, 0, false); |
| 476 | { | 410 | addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::DisplayHands, 0, true); |
| 477 | static const QString HANDS_MENU{ "Hands" }; | 411 | addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::DisplayHandTargets, 0, false); |
| 478 | addMenu(AVATAR_MENU, HANDS_MENU); | 412 | addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::ShowIKConstraints, 0, false); |
| 479 | addCheckableItem(HANDS_MENU, MenuOption::AlignForearmsWithWrists); | 413 | |
| 480 | addCheckableItem(HANDS_MENU, MenuOption::AlternateIK); | 414 | MenuWrapper* sixenseOptionsMenu = handOptionsMenu->addMenu("Sixense"); |
| 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); | ||
| 487 | #ifdef __APPLE__ | 415 | #ifdef __APPLE__ |
| 488 | addCheckableItem(SIXENSE_MENU, MenuOption::SixenseEnabled, false, [](bool checked) { | 416 | addCheckableActionToQMenuAndActionHash(sixenseOptionsMenu, |
| 489 | SixenseManager::getInstance().toggleSixense(checked); | 417 | MenuOption::SixenseEnabled, |
| 490 | }); | 418 | 0, false, |
| 419 | &SixenseManager::getInstance(), | ||
| 420 | SLOT(toggleSixense(bool))); | ||
| 491 | #endif | 421 | #endif |
| 492 | addCheckableItem(SIXENSE_MENU, MenuOption::FilterSixense, true, [](bool checked) { | 422 | addCheckableActionToQMenuAndActionHash(sixenseOptionsMenu, |
| 493 | SixenseManager::getInstance().setFilter(checked); | 423 | MenuOption::FilterSixense, |
| 494 | }); | 424 | 0, |
| 495 | addCheckableItem(SIXENSE_MENU, MenuOption::LowVelocityFilter, true, [](bool checked) { | 425 | true, |
| 496 | qApp->setLowVelocityFilter(checked); | 426 | &SixenseManager::getInstance(), |
| 497 | }); | 427 | SLOT(setFilter(bool))); |
| 498 | addCheckableItem(SIXENSE_MENU, MenuOption::SixenseMouseInput, true); | 428 | addCheckableActionToQMenuAndActionHash(sixenseOptionsMenu, |
| 499 | addCheckableItem(SIXENSE_MENU, MenuOption::SixenseLasers); | 429 | MenuOption::LowVelocityFilter, |
| 500 | } | 430 | 0, |
| 501 | 431 | true, | |
| 502 | { | 432 | qApp, |
| 503 | static const QString LEAP_MENU{ "Leap Motion" }; | 433 | SLOT(setLowVelocityFilter(bool))); |
| 504 | addMenu(HANDS_MENU, LEAP_MENU); | 434 | addCheckableActionToQMenuAndActionHash(sixenseOptionsMenu, MenuOption::SixenseMouseInput, 0, true); |
| 505 | addCheckableItem(LEAP_MENU, MenuOption::LeapMotionOnHMD); | 435 | addCheckableActionToQMenuAndActionHash(sixenseOptionsMenu, MenuOption::SixenseLasers, 0, false); |
| 506 | addCheckableItem(LEAP_MENU, MenuOption::LeapMotionOnHMD); | 436 | |
| 507 | } | 437 | MenuWrapper* leapOptionsMenu = handOptionsMenu->addMenu("Leap Motion"); |
| 438 | addCheckableActionToQMenuAndActionHash(leapOptionsMenu, MenuOption::LeapMotionOnHMD, 0, false); | ||
| 508 | 439 | ||
| 509 | #ifdef HAVE_RSSDK | 440 | #ifdef HAVE_RSSDK |
| 510 | { | 441 | QMenu* realSenseOptionsMenu = handOptionsMenu->addMenu("RealSense"); |
| 511 | static const QString RSS_MENU{ "RealSense" }; | 442 | addActionToQMenuAndActionHash(realSenseOptionsMenu, MenuOption::LoadRSSDKFile, 0, |
| 512 | addMenu(HANDS_MENU, RSS_MENU); | 443 | RealSense::getInstance(), SLOT(loadRSSDKFile())); |
| 513 | addItem(RSS_MENU, MenuOption::LoadRSSDKFile, [] { | ||
| 514 | RealSense::getInstance()->loadRSSDKFile(); | ||
| 515 | }); | ||
| 516 | addCheckableItem(RSS_MENU, MenuOption::LeapMotionOnHMD); | ||
| 517 | } | ||
| 518 | #endif | 444 | #endif |
| 519 | } // Developer -> Hands | 445 | |
| 520 | 446 | MenuWrapper* networkMenu = developerMenu->addMenu("Network"); | |
| 521 | { | 447 | addCheckableActionToQMenuAndActionHash(networkMenu, MenuOption::DisableNackPackets, 0, false); |
| 522 | static const QString NETWORK_MENU{ "Network" }; | 448 | addCheckableActionToQMenuAndActionHash(networkMenu, |
| 523 | addMenu(DEV_MENU, NETWORK_MENU); | 449 | MenuOption::DisableActivityLogger, |
| 524 | addCheckableItem(NETWORK_MENU, MenuOption::DisableNackPackets); | 450 | 0, |
| 525 | addCheckableItem(NETWORK_MENU, MenuOption::DisableActivityLogger, false, [](bool checked) { | 451 | false, |
| 526 | UserActivityLogger::getInstance().disable(checked); | 452 | &UserActivityLogger::getInstance(), |
| 527 | }); | 453 | SLOT(disable(bool))); |
| 528 | addItem(NETWORK_MENU, MenuOption::CachesSize, [=] { | 454 | addActionToQMenuAndActionHash(networkMenu, MenuOption::CachesSize, 0, |
| 529 | dialogsManager->cachesSizeDialog(); | 455 | dialogsManager.data(), SLOT(cachesSizeDialog())); |
| 530 | }); | 456 | addActionToQMenuAndActionHash(networkMenu, MenuOption::DiskCacheEditor, 0, |
| 531 | addItem(NETWORK_MENU, MenuOption::DiskCacheEditor, [=] { | 457 | dialogsManager.data(), SLOT(toggleDiskCacheEditor())); |
| 532 | dialogsManager->toggleDiskCacheEditor(); | 458 | |
| 533 | }); | 459 | MenuWrapper* timingMenu = developerMenu->addMenu("Timing and Stats"); |
| 534 | } // Developer -> Network | 460 | MenuWrapper* perfTimerMenu = timingMenu->addMenu("Performance Timer"); |
| 535 | 461 | addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::DisplayDebugTimingDetails, 0, false); | |
| 536 | { | 462 | addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::OnlyDisplayTopTen, 0, true); |
| 537 | static const QString TIMING_MENU{ "Timing and Stats" }; | 463 | addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::ExpandUpdateTiming, 0, false); |
| 538 | addMenu(DEV_MENU, TIMING_MENU); | 464 | addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::ExpandMyAvatarTiming, 0, false); |
| 539 | { | 465 | addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::ExpandMyAvatarSimulateTiming, 0, false); |
| 540 | static const QString PERF_MENU{ "Performance Timer" }; | 466 | addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::ExpandOtherAvatarTiming, 0, false); |
| 541 | addMenu(TIMING_MENU, PERF_MENU); | 467 | addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::ExpandPaintGLTiming, 0, false); |
| 542 | addCheckableItem(PERF_MENU, MenuOption::DisplayDebugTimingDetails); | 468 | |
| 543 | addCheckableItem(PERF_MENU, MenuOption::OnlyDisplayTopTen, true); | 469 | addCheckableActionToQMenuAndActionHash(timingMenu, MenuOption::TestPing, 0, true); |
| 544 | addCheckableItem(PERF_MENU, MenuOption::ExpandUpdateTiming); | 470 | addCheckableActionToQMenuAndActionHash(timingMenu, MenuOption::FrameTimer); |
| 545 | addCheckableItem(PERF_MENU, MenuOption::ExpandMyAvatarTiming); | 471 | addActionToQMenuAndActionHash(timingMenu, MenuOption::RunTimingTests, 0, qApp, SLOT(runTests())); |
| 546 | addCheckableItem(PERF_MENU, MenuOption::ExpandMyAvatarSimulateTiming); | 472 | addCheckableActionToQMenuAndActionHash(timingMenu, MenuOption::PipelineWarnings); |
| 547 | addCheckableItem(PERF_MENU, MenuOption::ExpandOtherAvatarTiming); | 473 | addCheckableActionToQMenuAndActionHash(timingMenu, MenuOption::SuppressShortTimings); |
| 548 | addCheckableItem(PERF_MENU, MenuOption::ExpandPaintGLTiming); | 474 | |
| 549 | } | 475 | auto audioIO = DependencyManager::get<AudioClient>(); |
| 550 | addCheckableItem(TIMING_MENU, MenuOption::TestPing, true); | 476 | MenuWrapper* audioDebugMenu = developerMenu->addMenu("Audio"); |
| 551 | addCheckableItem(TIMING_MENU, MenuOption::FrameTimer); | 477 | addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::AudioNoiseReduction, |
| 552 | addItem(TIMING_MENU, MenuOption::RunTimingTests, [] { runTimingTests(); }); | 478 | 0, |
| 553 | addCheckableItem(TIMING_MENU, MenuOption::PipelineWarnings); | 479 | true, |
| 554 | addCheckableItem(TIMING_MENU, MenuOption::SuppressShortTimings); | 480 | audioIO.data(), |
| 555 | } // Developer -> Timing and Stats | 481 | SLOT(toggleAudioNoiseReduction())); |
| 556 | 482 | ||
| 557 | { | 483 | addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::EchoServerAudio, 0, false, |
| 558 | static const QString AUDIO_MENU{ "Audio" }; | 484 | audioIO.data(), SLOT(toggleServerEcho())); |
| 559 | addMenu(DEV_MENU, AUDIO_MENU); | 485 | addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::EchoLocalAudio, 0, false, |
| 560 | auto audioIO = DependencyManager::get<AudioClient>(); | 486 | audioIO.data(), SLOT(toggleLocalEcho())); |
| 561 | addCheckableItem(AUDIO_MENU, MenuOption::AudioNoiseReduction, true, | 487 | addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::StereoAudio, 0, false, |
| 562 | audioIO.data(), SLOT(toggleAudioNoiseReduction())); | 488 | audioIO.data(), SLOT(toggleStereoInput())); |
| 563 | addCheckableItem(AUDIO_MENU, MenuOption::EchoServerAudio, false, | 489 | addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::MuteAudio, |
| 564 | audioIO.data(), SLOT(toggleServerEcho())); | 490 | Qt::CTRL | Qt::Key_M, |
| 565 | addCheckableItem(AUDIO_MENU, MenuOption::EchoLocalAudio, false, | 491 | false, |
| 566 | audioIO.data(), SLOT(toggleLocalEcho())); | 492 | audioIO.data(), |
| 567 | addCheckableItem(AUDIO_MENU, MenuOption::StereoAudio, false, | 493 | SLOT(toggleMute())); |
| 568 | audioIO.data(), SLOT(toggleStereoInput())); | 494 | addActionToQMenuAndActionHash(audioDebugMenu, |
| 569 | // Qt::CTRL | Qt::Key_M, | 495 | MenuOption::MuteEnvironment, |
| 570 | addCheckableItem(AUDIO_MENU, MenuOption::MuteAudio, false, | 496 | 0, |
| 571 | audioIO.data(), SLOT(toggleMute())); | 497 | audioIO.data(), |
| 572 | addCheckableItem(AUDIO_MENU, MenuOption::MuteEnvironment, false, | 498 | SLOT(sendMuteEnvironmentPacket())); |
| 573 | audioIO.data(), SLOT(sendMuteEnvironmentPacket())); | 499 | |
| 574 | { | 500 | auto scope = DependencyManager::get<AudioScope>(); |
| 575 | static const QString SCOPE_MENU{ "Audio Scope" }; | 501 | |
| 576 | addMenu(AUDIO_MENU, SCOPE_MENU); | 502 | MenuWrapper* audioScopeMenu = audioDebugMenu->addMenu("Audio Scope"); |
| 577 | auto scope = DependencyManager::get<AudioScope>(); | 503 | addCheckableActionToQMenuAndActionHash(audioScopeMenu, MenuOption::AudioScope, |
| 578 | // Qt::CTRL | Qt::Key_P | 504 | Qt::CTRL | Qt::Key_P, false, |
| 579 | addCheckableItem(SCOPE_MENU, MenuOption::AudioScope, false, [=](bool checked) { | 505 | scope.data(), |
| 580 | scope->toggle(); | 506 | SLOT(toggle())); |
| 581 | }); | 507 | addCheckableActionToQMenuAndActionHash(audioScopeMenu, MenuOption::AudioScopePause, |
| 582 | // Qt::CTRL | Qt::SHIFT | Qt::Key_P | 508 | Qt::CTRL | Qt::SHIFT | Qt::Key_P , |
| 583 | addCheckableItem(SCOPE_MENU, MenuOption::AudioScopePause, false, [=](bool checked) { | 509 | false, |
| 584 | scope->togglePause(); | 510 | scope.data(), |
| 585 | }); | 511 | SLOT(togglePause())); |
| 586 | addSeparator(SCOPE_MENU, "Display Frames"); | 512 | addDisabledActionAndSeparator(audioScopeMenu, "Display Frames"); |
| 587 | 513 | { | |
| 588 | // FIXME GROUP | 514 | QAction *fiveFrames = addCheckableActionToQMenuAndActionHash(audioScopeMenu, MenuOption::AudioScopeFiveFrames, |
| 589 | addCheckableItem(SCOPE_MENU, MenuOption::AudioScopeFiveFrames, true, [=](bool checked) { | 515 | 0, |
| 590 | scope->selectAudioScopeFiveFrames(); | 516 | true, |
| 591 | }); | 517 | scope.data(), |
| 592 | addCheckableItem(SCOPE_MENU, MenuOption::AudioScopeTwentyFrames, false, [=](bool checked) { | 518 | SLOT(selectAudioScopeFiveFrames())); |
| 593 | scope->selectAudioScopeTwentyFrames(); | 519 | |
| 594 | }); | 520 | QAction *twentyFrames = addCheckableActionToQMenuAndActionHash(audioScopeMenu, MenuOption::AudioScopeTwentyFrames, |
| 595 | addCheckableItem(SCOPE_MENU, MenuOption::AudioScopeFiftyFrames, false, [=](bool checked) { | 521 | 0, |
| 596 | scope->selectAudioScopeFiftyFrames(); | 522 | false, |
| 597 | }); | 523 | scope.data(), |
| 598 | } | 524 | SLOT(selectAudioScopeTwentyFrames())); |
| 599 | auto statsRenderer = DependencyManager::get<AudioIOStatsRenderer>(); | 525 | |
| 600 | 526 | QAction *fiftyFrames = addCheckableActionToQMenuAndActionHash(audioScopeMenu, MenuOption::AudioScopeFiftyFrames, | |
| 601 | // Qt::CTRL | Qt::SHIFT | Qt::Key_A, | 527 | 0, |
| 602 | addCheckableItem(AUDIO_MENU, MenuOption::AudioStats, false, [=](bool checked) { | 528 | false, |
| 603 | statsRenderer->toggle(); | 529 | scope.data(), |
| 604 | }); | 530 | SLOT(selectAudioScopeFiftyFrames())); |
| 605 | addCheckableItem(AUDIO_MENU, MenuOption::AudioStatsShowInjectedStreams, false, [=](bool checked) { | 531 | |
| 606 | statsRenderer->toggleShowInjectedStreams(); | 532 | QActionGroup* audioScopeFramesGroup = new QActionGroup(audioScopeMenu); |
| 607 | }); | 533 | audioScopeFramesGroup->addAction(fiveFrames); |
| 608 | } // Developer -> Audio | 534 | audioScopeFramesGroup->addAction(twentyFrames); |
| 609 | } // Developer | 535 | audioScopeFramesGroup->addAction(fiftyFrames); |
| 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 | ||
| 621 | } | 536 | } |
| 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 | ||
| 622 | } | 558 | } |
| 623 | 559 | ||
| 624 | void Menu::loadSettings() { | 560 | void Menu::loadSettings() { |
| 625 | // scanMenuBar(&Menu::loadAction); | 561 | scanMenuBar(&Menu::loadAction); |
| 626 | } | 562 | } |
| 627 | 563 | ||
| 628 | void Menu::saveSettings() { | 564 | void Menu::saveSettings() { |
| 629 | // scanMenuBar(&Menu::saveAction); | 565 | scanMenuBar(&Menu::saveAction); |
| 630 | } | 566 | } |
| 631 | 567 | ||
| 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 | |||
| 664 | void Menu::loadAction(Settings& settings, QAction& action) { | 568 | void Menu::loadAction(Settings& settings, QAction& action) { |
| 665 | if (action.isChecked() != settings.value(action.text(), action.isChecked()).toBool()) { | 569 | if (action.isChecked() != settings.value(action.text(), action.isChecked()).toBool()) { |
| 666 | action.trigger(); | 570 | action.trigger(); |
| @@ -690,7 +594,7 @@ void Menu::scanMenu(QMenu& menu, settingsAction modifySetting, Settings& setting · 23 unmodified lines | |||
| 690 | settings.endGroup(); | 594 | settings.endGroup(); |
| 691 | } | 595 | } |
| 692 | 596 | ||
| 693 | void Menu::addDisabledActionAndSeparator(QMenu* destinationMenu, const QString& actionName, int menuItemLocation) { | 597 | void Menu::addDisabledActionAndSeparator(MenuWrapper* destinationMenu, const QString& actionName, int menuItemLocation) { |
| 694 | QAction* actionBefore = NULL; | 598 | QAction* actionBefore = NULL; |
| 695 | if (menuItemLocation >= 0 && destinationMenu->actions().size() > menuItemLocation) { | 599 | if (menuItemLocation >= 0 && destinationMenu->actions().size() > menuItemLocation) { |
| 696 | actionBefore = destinationMenu->actions()[menuItemLocation]; | 600 | actionBefore = destinationMenu->actions()[menuItemLocation]; |
| @@ -710,5 +614,406 @@ void Menu::addDisabledActionAndSeparator(QMenu* destinationMenu, const QString& · 13 unmodified lines | |||
| 710 | } | 614 | } |
| 711 | } | 615 | } |
| 712 | 616 | ||
| 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; | ||
| 713 | 626 | ||
| 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; | ||