History

Merge branch 'master' of https://github.com/highfidelity/hifi into android

Atlante45 committed 11 years ago

Commit 4ef87b92 parents df96e02 347c74e113 files · +3501 −2168Browse files

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

Unified · Split

interface/src/Menu.cpp+127−932
@@ -9,34 +9,16 @@ · 8 unmodified lines
9// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html9// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
10//10//
11 11
12#include <cstdlib>
13
14#include <QBoxLayout>
15#include <QColorDialog>
16#include <QClipboard>
17#include <QDialogButtonBox>
18#include <QDoubleSpinBox>
19#include <QFileDialog>12#include <QFileDialog>
20#include <QFormLayout>
21#include <QInputDialog>
22#include <QLineEdit>
23#include <QMainWindow>
24#include <QMenuBar>13#include <QMenuBar>
25#include <QMessageBox>
26#include <QShortcut>14#include <QShortcut>
27#include <QSlider>
28#include <QUuid>
29#include <QHBoxLayout>
30#include <QDesktopServices>
31 15
32#include <AccountManager.h>
33#include <AddressManager.h>16#include <AddressManager.h>
34#include <AudioClient.h>17#include <AudioClient.h>
35#include <DependencyManager.h>18#include <DependencyManager.h>
36#include <MainWindow.h>
37#include <GlowEffect.h>19#include <GlowEffect.h>
38#include <PathUtils.h>20#include <PathUtils.h>
39#include <UUID.h>21#include <Settings.h>
40#include <UserActivityLogger.h>22#include <UserActivityLogger.h>
41#include <XmppClient.h>23#include <XmppClient.h>
42 24
@@ -44,28 +26,20 @@ · 1 unmodified line
44#include "AccountManager.h"26#include "AccountManager.h"
45#include "audio/AudioIOStatsRenderer.h"27#include "audio/AudioIOStatsRenderer.h"
46#include "audio/AudioScope.h"28#include "audio/AudioScope.h"
29#include "devices/Faceshift.h"
47#include "devices/RealSense.h"30#include "devices/RealSense.h"
31#include "devices/SixenseManager.h"
48#include "devices/Visage.h"32#include "devices/Visage.h"
49#include "Menu.h"33#include "MainWindow.h"
50#include "scripting/LocationScriptingInterface.h"
51#include "scripting/MenuScriptingInterface.h"34#include "scripting/MenuScriptingInterface.h"
52#include "Util.h"35#if defined(Q_OS_MAC) || defined(Q_OS_WIN)
53#include "ui/AddressBarDialog.h"36#include "SpeechRecognizer.h"
54#include "ui/AnimationsDialog.h"37#endif
55#include "ui/AttachmentsDialog.h"38#include "ui/DialogsManager.h"
56#include "ui/BandwidthDialog.h"
57#include "ui/CachesSizeDialog.h"
58#include "ui/DataWebDialog.h"
59#include "ui/HMDToolsDialog.h"
60#include "ui/LodToolsDialog.h"
61#include "ui/LoginDialog.h"
62#include "ui/OctreeStatsDialog.h"
63#include "ui/PreferencesDialog.h"
64#include "ui/InfoView.h"
65#include "ui/MetavoxelEditor.h"
66#include "ui/MetavoxelNetworkSimulator.h"
67#include "ui/ModelsBrowser.h"
68#include "ui/NodeBounds.h"39#include "ui/NodeBounds.h"
40#include "ui/StandAloneJSConsole.h"
41
42#include "Menu.h"
69 43
70Menu* Menu::_instance = NULL;44Menu* Menu::_instance = NULL;
71 45
@@ -86,88 +60,71 @@ Menu* Menu::getInstance() { · 14 unmodified lines
86 return _instance;60 return _instance;
87}61}
88 62
89Menu::Menu() :63Menu::Menu() {
90 _lastAdjust(usecTimestampNow()),
91 _lastAvatarDetailDrop(usecTimestampNow())
92{
93 Application *appInstance = Application::getInstance();
94
95 QMenu* fileMenu = addMenu("File");64 QMenu* fileMenu = addMenu("File");
96 65
97#ifdef Q_OS_MAC66#ifdef Q_OS_MAC
98 addActionToQMenuAndActionHash(fileMenu,67 addActionToQMenuAndActionHash(fileMenu, MenuOption::AboutApp, 0, qApp, SLOT(aboutApp()), QAction::AboutRole);
99 MenuOption::AboutApp,
100 0,
101 this,
102 SLOT(aboutApp()),
103 QAction::AboutRole);
104#endif68#endif
105 69 auto dialogsManager = DependencyManager::get<DialogsManager>();
106 AccountManager& accountManager = AccountManager::getInstance();70 AccountManager& accountManager = AccountManager::getInstance();
107 71
108 _loginAction = addActionToQMenuAndActionHash(fileMenu, MenuOption::Logout);72 {
109 73 addActionToQMenuAndActionHash(fileMenu, MenuOption::Login);
110 // call our toggle login function now so the menu option is setup properly74
111 toggleLoginMenuItem();75 // connect to the appropriate signal of the AccountManager so that we can change the Login/Logout menu item
112 76 connect(&accountManager, &AccountManager::profileChanged,
113 // connect to the appropriate signal of the AccountManager so that we can change the Login/Logout menu item77 dialogsManager.data(), &DialogsManager::toggleLoginDialog);
114 connect(&accountManager, &AccountManager::profileChanged, this, &Menu::toggleLoginMenuItem);78 connect(&accountManager, &AccountManager::logoutComplete,
115 connect(&accountManager, &AccountManager::logoutComplete, this, &Menu::toggleLoginMenuItem);79 dialogsManager.data(), &DialogsManager::toggleLoginDialog);
116 80 }
81
117 addDisabledActionAndSeparator(fileMenu, "Scripts");82 addDisabledActionAndSeparator(fileMenu, "Scripts");
118 addActionToQMenuAndActionHash(fileMenu, MenuOption::LoadScript, Qt::CTRL | Qt::Key_O, appInstance, SLOT(loadDialog()));83 addActionToQMenuAndActionHash(fileMenu, MenuOption::LoadScript, Qt::CTRL | Qt::Key_O,
84 qApp, SLOT(loadDialog()));
119 addActionToQMenuAndActionHash(fileMenu, MenuOption::LoadScriptURL,85 addActionToQMenuAndActionHash(fileMenu, MenuOption::LoadScriptURL,
120 Qt::CTRL | Qt::SHIFT | Qt::Key_O, appInstance, SLOT(loadScriptURLDialog()));86 Qt::CTRL | Qt::SHIFT | Qt::Key_O, qApp, SLOT(loadScriptURLDialog()));
121 addActionToQMenuAndActionHash(fileMenu, MenuOption::StopAllScripts, 0, appInstance, SLOT(stopAllScripts()));87 addActionToQMenuAndActionHash(fileMenu, MenuOption::StopAllScripts, 0, qApp, SLOT(stopAllScripts()));
122 addActionToQMenuAndActionHash(fileMenu, MenuOption::ReloadAllScripts, Qt::CTRL | Qt::Key_R,88 addActionToQMenuAndActionHash(fileMenu, MenuOption::ReloadAllScripts, Qt::CTRL | Qt::Key_R,
123 appInstance, SLOT(reloadAllScripts()));89 qApp, SLOT(reloadAllScripts()));
124 addActionToQMenuAndActionHash(fileMenu, MenuOption::RunningScripts, Qt::CTRL | Qt::Key_J,90 addActionToQMenuAndActionHash(fileMenu, MenuOption::RunningScripts, Qt::CTRL | Qt::Key_J,
125 appInstance, SLOT(toggleRunningScriptsWidget()));91 qApp, SLOT(toggleRunningScriptsWidget()));
126 92
127 addDisabledActionAndSeparator(fileMenu, "Location");93 addDisabledActionAndSeparator(fileMenu, "Location");
128 addActionToQMenuAndActionHash(fileMenu, MenuOption::BookmarkLocation, 0,94 qApp->getBookmarks()->setupMenus(this, fileMenu);
129 this, SLOT(bookmarkLocation()));95
130 _bookmarksMenu = fileMenu->addMenu(MenuOption::Bookmarks);
131 _bookmarksMenu->setEnabled(false);
132 _deleteBookmarksMenu = addActionToQMenuAndActionHash(fileMenu,
133 MenuOption::DeleteBookmark, 0,
134 this, SLOT(deleteBookmark()));
135 _deleteBookmarksMenu->setEnabled(false);
136 loadBookmarks();
137 addActionToQMenuAndActionHash(fileMenu,96 addActionToQMenuAndActionHash(fileMenu,
138 MenuOption::AddressBar,97 MenuOption::AddressBar,
139 Qt::Key_Enter,98 Qt::Key_Enter,
140 this,99 dialogsManager.data(),
141 SLOT(toggleAddressBar()));100 SLOT(toggleAddressBar()));
101 auto addressManager = DependencyManager::get<AddressManager>();
142 addActionToQMenuAndActionHash(fileMenu, MenuOption::CopyAddress, 0,102 addActionToQMenuAndActionHash(fileMenu, MenuOption::CopyAddress, 0,
143 this, SLOT(copyAddress()));103 addressManager.data(), SLOT(copyAddress()));
144 addActionToQMenuAndActionHash(fileMenu, MenuOption::CopyPath, 0,104 addActionToQMenuAndActionHash(fileMenu, MenuOption::CopyPath, 0,
145 this, SLOT(copyPath()));105 addressManager.data(), SLOT(copyPath()));
146 106
147 addDisabledActionAndSeparator(fileMenu, "Upload Avatar Model");107 addDisabledActionAndSeparator(fileMenu, "Upload Avatar Model");
148 addActionToQMenuAndActionHash(fileMenu, MenuOption::UploadHead, 0,108 addActionToQMenuAndActionHash(fileMenu, MenuOption::UploadHead, 0,
149 Application::getInstance(), SLOT(uploadHead()));109 qApp, SLOT(uploadHead()));
150 addActionToQMenuAndActionHash(fileMenu, MenuOption::UploadSkeleton, 0,110 addActionToQMenuAndActionHash(fileMenu, MenuOption::UploadSkeleton, 0,
151 Application::getInstance(), SLOT(uploadSkeleton()));111 qApp, SLOT(uploadSkeleton()));
152 addActionToQMenuAndActionHash(fileMenu, MenuOption::UploadAttachment, 0,112 addActionToQMenuAndActionHash(fileMenu, MenuOption::UploadAttachment, 0,
153 Application::getInstance(), SLOT(uploadAttachment()));113 qApp, SLOT(uploadAttachment()));
154 addActionToQMenuAndActionHash(fileMenu, MenuOption::UploadEntity, 0,114 addActionToQMenuAndActionHash(fileMenu, MenuOption::UploadEntity, 0,
155 Application::getInstance(), SLOT(uploadEntity()));115 qApp, SLOT(uploadEntity()));
156 addDisabledActionAndSeparator(fileMenu, "Settings");
157 addActionToQMenuAndActionHash(fileMenu, MenuOption::SettingsImport, 0, this, SLOT(importSettings()));
158 addActionToQMenuAndActionHash(fileMenu, MenuOption::SettingsExport, 0, this, SLOT(exportSettings()));
159 116
160 addActionToQMenuAndActionHash(fileMenu,117 addActionToQMenuAndActionHash(fileMenu,
161 MenuOption::Quit,118 MenuOption::Quit,
162 Qt::CTRL | Qt::Key_Q,119 Qt::CTRL | Qt::Key_Q,
163 appInstance,120 qApp,
164 SLOT(quit()),121 SLOT(quit()),
165 QAction::QuitRole);122 QAction::QuitRole);
166 123
167 124
168 QMenu* editMenu = addMenu("Edit");125 QMenu* editMenu = addMenu("Edit");
169 126
170 QUndoStack* undoStack = Application::getInstance()->getUndoStack();127 QUndoStack* undoStack = qApp->getUndoStack();
171 QAction* undoAction = undoStack->createUndoAction(editMenu);128 QAction* undoAction = undoStack->createUndoAction(editMenu);
172 undoAction->setShortcut(Qt::CTRL | Qt::Key_Z);129 undoAction->setShortcut(Qt::CTRL | Qt::Key_Z);
173 addActionToQMenuAndActionHash(editMenu, undoAction);130 addActionToQMenuAndActionHash(editMenu, undoAction);
@@ -179,56 +136,53 @@ Menu::Menu() : · 5 unmodified lines
179 addActionToQMenuAndActionHash(editMenu,136 addActionToQMenuAndActionHash(editMenu,
180 MenuOption::Preferences,137 MenuOption::Preferences,
181 Qt::CTRL | Qt::Key_Comma,138 Qt::CTRL | Qt::Key_Comma,
182 this,139 dialogsManager.data(),
183 SLOT(editPreferences()),140 SLOT(editPreferences()),
184 QAction::PreferencesRole);141 QAction::PreferencesRole);
185 142
186 addActionToQMenuAndActionHash(editMenu, MenuOption::Attachments, 0, this, SLOT(editAttachments()));143 addActionToQMenuAndActionHash(editMenu, MenuOption::Attachments, 0,
187 addActionToQMenuAndActionHash(editMenu, MenuOption::Animations, 0, this, SLOT(editAnimations()));144 dialogsManager.data(), SLOT(editAttachments()));
145 addActionToQMenuAndActionHash(editMenu, MenuOption::Animations, 0,
146 dialogsManager.data(), SLOT(editAnimations()));
188 147
189 QMenu* toolsMenu = addMenu("Tools");148 QMenu* toolsMenu = addMenu("Tools");
190 addActionToQMenuAndActionHash(toolsMenu, MenuOption::MetavoxelEditor, 0, this, SLOT(showMetavoxelEditor()));149 addActionToQMenuAndActionHash(toolsMenu, MenuOption::MetavoxelEditor, 0,
191 addActionToQMenuAndActionHash(toolsMenu, MenuOption::ScriptEditor, Qt::ALT | Qt::Key_S, this, SLOT(showScriptEditor()));150 dialogsManager.data(), SLOT(showMetavoxelEditor()));
151 addActionToQMenuAndActionHash(toolsMenu, MenuOption::ScriptEditor, Qt::ALT | Qt::Key_S,
152 dialogsManager.data(), SLOT(showScriptEditor()));
192 153
193#if defined(Q_OS_MAC) || defined(Q_OS_WIN)154#if defined(Q_OS_MAC) || defined(Q_OS_WIN)
155 auto speechRecognizer = DependencyManager::get<SpeechRecognizer>();
194 QAction* speechRecognizerAction = addCheckableActionToQMenuAndActionHash(toolsMenu, MenuOption::ControlWithSpeech,156 QAction* speechRecognizerAction = addCheckableActionToQMenuAndActionHash(toolsMenu, MenuOption::ControlWithSpeech,
195 Qt::CTRL | Qt::SHIFT | Qt::Key_C, _speechRecognizer.getEnabled(), &_speechRecognizer, SLOT(setEnabled(bool)));157 Qt::CTRL | Qt::SHIFT | Qt::Key_C,
196 connect(&_speechRecognizer, SIGNAL(enabledUpdated(bool)), speechRecognizerAction, SLOT(setChecked(bool)));158 speechRecognizer->getEnabled(),
159 speechRecognizer.data(),
160 SLOT(setEnabled(bool)));
161 connect(speechRecognizer.data(), SIGNAL(enabledUpdated(bool)), speechRecognizerAction, SLOT(setChecked(bool)));
197#endif162#endif
198 163
199#ifdef HAVE_QXMPP164#ifdef HAVE_QXMPP
200 _chatAction = addActionToQMenuAndActionHash(toolsMenu,165 addActionToQMenuAndActionHash(toolsMenu, MenuOption::Chat, Qt::Key_Backslash,
201 MenuOption::Chat,166 dialogsManager.data(), SLOT(showChat()));
202 Qt::Key_Backslash,167 dialogsManager->setupChat();
203 this,
204 SLOT(showChat()));
205
206 const QXmppClient& xmppClient = XmppClient::getInstance().getXMPPClient();
207 toggleChat();
208 connect(&xmppClient, &QXmppClient::connected, this, &Menu::toggleChat);
209 connect(&xmppClient, &QXmppClient::disconnected, this, &Menu::toggleChat);
210
211 QDir::setCurrent(PathUtils::resourcesPath());
212 // init chat window to listen chat
213 _chatWindow = new ChatWindow(Application::getInstance()->getWindow());
214#endif168#endif
215 169
216 addActionToQMenuAndActionHash(toolsMenu,170 addActionToQMenuAndActionHash(toolsMenu,
217 MenuOption::ToolWindow,171 MenuOption::ToolWindow,
218 Qt::CTRL | Qt::ALT | Qt::Key_T,172 Qt::CTRL | Qt::ALT | Qt::Key_T,
219 this,173 dialogsManager.data(),
220 SLOT(toggleToolWindow()));174 SLOT(toggleToolWindow()));
221 175
222 addActionToQMenuAndActionHash(toolsMenu,176 addActionToQMenuAndActionHash(toolsMenu,
223 MenuOption::Console,177 MenuOption::Console,
224 Qt::CTRL | Qt::ALT | Qt::Key_J,178 Qt::CTRL | Qt::ALT | Qt::Key_J,
225 this,179 DependencyManager::get<StandAloneJSConsole>().data(),
226 SLOT(toggleConsole()));180 SLOT(toggleConsole()));
227 181
228 addActionToQMenuAndActionHash(toolsMenu,182 addActionToQMenuAndActionHash(toolsMenu,
229 MenuOption::ResetSensors,183 MenuOption::ResetSensors,
230 Qt::Key_Apostrophe,184 Qt::Key_Apostrophe,
231 appInstance,185 qApp,
232 SLOT(resetSensors()));186 SLOT(resetSensors()));
233 187
234 QMenu* avatarMenu = addMenu("Avatar");188 QMenu* avatarMenu = addMenu("Avatar");
@@ -237,20 +191,20 @@ Menu::Menu() : · 2 unmodified lines
237 addActionToQMenuAndActionHash(avatarSizeMenu,191 addActionToQMenuAndActionHash(avatarSizeMenu,
238 MenuOption::IncreaseAvatarSize,192 MenuOption::IncreaseAvatarSize,
239 Qt::Key_Plus,193 Qt::Key_Plus,
240 appInstance->getAvatar(),194 qApp->getAvatar(),
241 SLOT(increaseSize()));195 SLOT(increaseSize()));
242 addActionToQMenuAndActionHash(avatarSizeMenu,196 addActionToQMenuAndActionHash(avatarSizeMenu,
243 MenuOption::DecreaseAvatarSize,197 MenuOption::DecreaseAvatarSize,
244 Qt::Key_Minus,198 Qt::Key_Minus,
245 appInstance->getAvatar(),199 qApp->getAvatar(),
246 SLOT(decreaseSize()));200 SLOT(decreaseSize()));
247 addActionToQMenuAndActionHash(avatarSizeMenu,201 addActionToQMenuAndActionHash(avatarSizeMenu,
248 MenuOption::ResetAvatarSize,202 MenuOption::ResetAvatarSize,
249 Qt::Key_Equal,203 Qt::Key_Equal,
250 appInstance->getAvatar(),204 qApp->getAvatar(),
251 SLOT(resetSize()));205 SLOT(resetSize()));
252 206
253 QObject* avatar = appInstance->getAvatar();207 QObject* avatar = qApp->getAvatar();
254 addCheckableActionToQMenuAndActionHash(avatarMenu, MenuOption::KeyboardMotorControl, 208 addCheckableActionToQMenuAndActionHash(avatarMenu, MenuOption::KeyboardMotorControl,
255 Qt::CTRL | Qt::SHIFT | Qt::Key_K, true, avatar, SLOT(updateMotionBehavior()));209 Qt::CTRL | Qt::SHIFT | Qt::Key_K, true, avatar, SLOT(updateMotionBehavior()));
256 addCheckableActionToQMenuAndActionHash(avatarMenu, MenuOption::ScriptedMotorControl, 0, true,210 addCheckableActionToQMenuAndActionHash(avatarMenu, MenuOption::ScriptedMotorControl, 0, true,
@@ -281,42 +235,42 @@ Menu::Menu() : · 24 unmodified lines
281 MenuOption::Fullscreen,235 MenuOption::Fullscreen,
282 Qt::CTRL | Qt::META | Qt::Key_F,236 Qt::CTRL | Qt::META | Qt::Key_F,
283 false,237 false,
284 appInstance,238 qApp,
285 SLOT(setFullscreen(bool)));239 SLOT(setFullscreen(bool)));
286#else240#else
287 addCheckableActionToQMenuAndActionHash(viewMenu,241 addCheckableActionToQMenuAndActionHash(viewMenu,
288 MenuOption::Fullscreen,242 MenuOption::Fullscreen,
289 Qt::CTRL | Qt::Key_F,243 Qt::CTRL | Qt::Key_F,
290 false,244 false,
291 appInstance,245 qApp,
292 SLOT(setFullscreen(bool)));246 SLOT(setFullscreen(bool)));
293#endif247#endif
294 addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::FirstPerson, Qt::Key_P, true,248 addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::FirstPerson, Qt::Key_P, true,
295 appInstance,SLOT(cameraMenuChanged()));249 qApp,SLOT(cameraMenuChanged()));
296 addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Mirror, Qt::SHIFT | Qt::Key_H, true);250 addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Mirror, Qt::SHIFT | Qt::Key_H, true);
297 addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::FullscreenMirror, Qt::Key_H, false,251 addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::FullscreenMirror, Qt::Key_H, false,
298 appInstance, SLOT(cameraMenuChanged()));252 qApp, SLOT(cameraMenuChanged()));
299 addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::UserInterface, Qt::Key_Slash, true);253 addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::UserInterface, Qt::Key_Slash, true);
300 254
301 addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::HMDTools, Qt::META | Qt::Key_H,255 addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::HMDTools, Qt::META | Qt::Key_H,
302 false,256 false,
303 this,257 dialogsManager.data(),
304 SLOT(hmdTools(bool)));258 SLOT(hmdTools(bool)));
305 259
306 260
307 addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::EnableVRMode, 0,261 addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::EnableVRMode, 0,
308 false,262 false,
309 appInstance,263 qApp,
310 SLOT(setEnableVRMode(bool)));264 SLOT(setEnableVRMode(bool)));
311 265
312 addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Enable3DTVMode, 0,266 addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Enable3DTVMode, 0,
313 false,267 false,
314 appInstance,268 qApp,
315 SLOT(setEnable3DTVMode(bool)));269 SLOT(setEnable3DTVMode(bool)));
316 270
317 271
318 QMenu* nodeBordersMenu = viewMenu->addMenu("Server Borders");272 QMenu* nodeBordersMenu = viewMenu->addMenu("Server Borders");
319 NodeBounds& nodeBounds = appInstance->getNodeBoundsDisplay();273 NodeBounds& nodeBounds = qApp->getNodeBoundsDisplay();
320 addCheckableActionToQMenuAndActionHash(nodeBordersMenu, MenuOption::ShowBordersEntityNodes,274 addCheckableActionToQMenuAndActionHash(nodeBordersMenu, MenuOption::ShowBordersEntityNodes,
321 Qt::CTRL | Qt::SHIFT | Qt::Key_1, false,275 Qt::CTRL | Qt::SHIFT | Qt::Key_1, false,
322 &nodeBounds, SLOT(setShowEntityNodes(bool)));276 &nodeBounds, SLOT(setShowEntityNodes(bool)));
@@ -327,11 +281,13 @@ Menu::Menu() : · 4 unmodified lines
327 281
328 addDisabledActionAndSeparator(viewMenu, "Stats");282 addDisabledActionAndSeparator(viewMenu, "Stats");
329 addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Stats, Qt::Key_Percent);283 addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Stats, Qt::Key_Percent);
330 addActionToQMenuAndActionHash(viewMenu, MenuOption::Log, Qt::CTRL | Qt::Key_L, appInstance, SLOT(toggleLogDialog()));284 addActionToQMenuAndActionHash(viewMenu, MenuOption::Log, Qt::CTRL | Qt::Key_L, qApp, SLOT(toggleLogDialog()));
331 addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Bandwidth, 0, true);285 addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Bandwidth, 0, true);
332 addActionToQMenuAndActionHash(viewMenu, MenuOption::BandwidthDetails, 0, this, SLOT(bandwidthDetails()));286 addActionToQMenuAndActionHash(viewMenu, MenuOption::BandwidthDetails, 0,
333 addActionToQMenuAndActionHash(viewMenu, MenuOption::OctreeStats, 0, this, SLOT(octreeStatsDetails()));287 dialogsManager.data(), SLOT(bandwidthDetails()));
334 addActionToQMenuAndActionHash(viewMenu, MenuOption::EditEntitiesHelp, 0, this, SLOT(showEditEntitiesHelp()));288 addActionToQMenuAndActionHash(viewMenu, MenuOption::OctreeStats, 0,
289 dialogsManager.data(), SLOT(octreeStatsDetails()));
290 addActionToQMenuAndActionHash(viewMenu, MenuOption::EditEntitiesHelp, 0, qApp, SLOT(showEditEntitiesHelp()));
335 291
336 QMenu* developerMenu = addMenu("Developer");292 QMenu* developerMenu = addMenu("Developer");
337 293
@@ -377,7 +333,8 @@ Menu::Menu() : · 39 unmodified lines
377 333
378#if defined(Q_OS_MAC)334#if defined(Q_OS_MAC)
379#else335#else
380 addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::RenderTargetFramerateVSyncOn, 0, true, this, SLOT(changeVSync()));336 addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::RenderTargetFramerateVSyncOn, 0, true,
337 qApp, SLOT(changeVSync()));
381#endif338#endif
382 }339 }
383 340
@@ -396,7 +353,8 @@ Menu::Menu() : · 12 unmodified lines
396 DependencyManager::get<GlowEffect>().data(), SLOT(toggleGlowEffect(bool)));353 DependencyManager::get<GlowEffect>().data(), SLOT(toggleGlowEffect(bool)));
397 354
398 addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Wireframe, Qt::ALT | Qt::Key_W, false);355 addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Wireframe, Qt::ALT | Qt::Key_W, false);
399 addActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::LodTools, Qt::SHIFT | Qt::Key_L, this, SLOT(lodTools()));356 addActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::LodTools, Qt::SHIFT | Qt::Key_L,
357 dialogsManager.data(), SLOT(lodTools()));
400 358
401 QMenu* avatarDebugMenu = developerMenu->addMenu("Avatar");359 QMenu* avatarDebugMenu = developerMenu->addMenu("Avatar");
402#ifdef HAVE_FACESHIFT360#ifdef HAVE_FACESHIFT
@@ -422,8 +380,8 @@ Menu::Menu() : · 19 unmodified lines
422 addCheckableActionToQMenuAndActionHash(metavoxelOptionsMenu, MenuOption::DisplayHermiteData, 0, false);380 addCheckableActionToQMenuAndActionHash(metavoxelOptionsMenu, MenuOption::DisplayHermiteData, 0, false);
423 addCheckableActionToQMenuAndActionHash(metavoxelOptionsMenu, MenuOption::RenderHeightfields, 0, true);381 addCheckableActionToQMenuAndActionHash(metavoxelOptionsMenu, MenuOption::RenderHeightfields, 0, true);
424 addCheckableActionToQMenuAndActionHash(metavoxelOptionsMenu, MenuOption::RenderDualContourSurfaces, 0, true);382 addCheckableActionToQMenuAndActionHash(metavoxelOptionsMenu, MenuOption::RenderDualContourSurfaces, 0, true);
425 addActionToQMenuAndActionHash(metavoxelOptionsMenu, MenuOption::NetworkSimulator, 0, this,383 addActionToQMenuAndActionHash(metavoxelOptionsMenu, MenuOption::NetworkSimulator, 0,
426 SLOT(showMetavoxelNetworkSimulator()));384 dialogsManager.data(), SLOT(showMetavoxelNetworkSimulator()));
427 385
428 QMenu* handOptionsMenu = developerMenu->addMenu("Hands");386 QMenu* handOptionsMenu = developerMenu->addMenu("Hands");
429 addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::AlignForearmsWithWrists, 0, false);387 addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::AlignForearmsWithWrists, 0, false);
@@ -437,7 +395,7 @@ Menu::Menu() : · 7 unmodified lines
437 addCheckableActionToQMenuAndActionHash(sixenseOptionsMenu,395 addCheckableActionToQMenuAndActionHash(sixenseOptionsMenu,
438 MenuOption::SixenseEnabled,396 MenuOption::SixenseEnabled,
439 0, false,397 0, false,
440 this,398 &SixenseManager::getInstance(),
441 SLOT(toggleSixense(bool)));399 SLOT(toggleSixense(bool)));
442#endif400#endif
443 addCheckableActionToQMenuAndActionHash(sixenseOptionsMenu,401 addCheckableActionToQMenuAndActionHash(sixenseOptionsMenu,
@@ -450,7 +408,7 @@ Menu::Menu() : · 6 unmodified lines
450 MenuOption::LowVelocityFilter,408 MenuOption::LowVelocityFilter,
451 0,409 0,
452 true,410 true,
453 appInstance,411 qApp,
454 SLOT(setLowVelocityFilter(bool)));412 SLOT(setLowVelocityFilter(bool)));
455 addCheckableActionToQMenuAndActionHash(sixenseOptionsMenu, MenuOption::SixenseMouseInput, 0, true);413 addCheckableActionToQMenuAndActionHash(sixenseOptionsMenu, MenuOption::SixenseMouseInput, 0, true);
456 addCheckableActionToQMenuAndActionHash(sixenseOptionsMenu, MenuOption::SixenseLasers, 0, false);414 addCheckableActionToQMenuAndActionHash(sixenseOptionsMenu, MenuOption::SixenseLasers, 0, false);
@@ -460,7 +418,8 @@ Menu::Menu() : · 3 unmodified lines
460 418
461#ifdef HAVE_RSSDK419#ifdef HAVE_RSSDK
462 QMenu* realSenseOptionsMenu = handOptionsMenu->addMenu("RealSense");420 QMenu* realSenseOptionsMenu = handOptionsMenu->addMenu("RealSense");
463 addActionToQMenuAndActionHash(realSenseOptionsMenu, MenuOption::LoadRSSDKFile, 0, this, SLOT(loadRSSDKFile()));421 addActionToQMenuAndActionHash(realSenseOptionsMenu, MenuOption::LoadRSSDKFile, 0,
422 RealSense::getInstance(), SLOT(loadRSSDKFile()));
464#endif423#endif
465 424
466 QMenu* networkMenu = developerMenu->addMenu("Network");425 QMenu* networkMenu = developerMenu->addMenu("Network");
@@ -471,9 +430,8 @@ Menu::Menu() : · 4 unmodified lines
471 false,430 false,
472 &UserActivityLogger::getInstance(),431 &UserActivityLogger::getInstance(),
473 SLOT(disable(bool)));432 SLOT(disable(bool)));
474 addActionToQMenuAndActionHash(networkMenu, MenuOption::CachesSize, 0, this, SLOT(cachesSizeDialog()));433 addActionToQMenuAndActionHash(networkMenu, MenuOption::CachesSize, 0,
475 434 dialogsManager.data(), SLOT(cachesSizeDialog()));
476 addActionToQMenuAndActionHash(developerMenu, MenuOption::WalletPrivateKey, 0, this, SLOT(changePrivateKey()));
477 435
478 QMenu* timingMenu = developerMenu->addMenu("Timing and Stats");436 QMenu* timingMenu = developerMenu->addMenu("Timing and Stats");
479 QMenu* perfTimerMenu = timingMenu->addMenu("Performance Timer");437 QMenu* perfTimerMenu = timingMenu->addMenu("Performance Timer");
@@ -486,7 +444,7 @@ Menu::Menu() : · 6 unmodified lines
486 444
487 addCheckableActionToQMenuAndActionHash(timingMenu, MenuOption::TestPing, 0, true);445 addCheckableActionToQMenuAndActionHash(timingMenu, MenuOption::TestPing, 0, true);
488 addCheckableActionToQMenuAndActionHash(timingMenu, MenuOption::FrameTimer);446 addCheckableActionToQMenuAndActionHash(timingMenu, MenuOption::FrameTimer);
489 addActionToQMenuAndActionHash(timingMenu, MenuOption::RunTimingTests, 0, this, SLOT(runTests()));447 addActionToQMenuAndActionHash(timingMenu, MenuOption::RunTimingTests, 0, qApp, SLOT(runTests()));
490 addCheckableActionToQMenuAndActionHash(timingMenu, MenuOption::PipelineWarnings);448 addCheckableActionToQMenuAndActionHash(timingMenu, MenuOption::PipelineWarnings);
491 addCheckableActionToQMenuAndActionHash(timingMenu, MenuOption::SuppressShortTimings);449 addCheckableActionToQMenuAndActionHash(timingMenu, MenuOption::SuppressShortTimings);
492 450
@@ -590,189 +548,48 @@ Menu::Menu() : · 97 unmodified lines
590 statsRenderer.data(),548 statsRenderer.data(),
591 SLOT(toggleShowInjectedStreams()));549 SLOT(toggleShowInjectedStreams()));
592 550
593 connect(audioIO.data(), SIGNAL(muteToggled()), this, SLOT(audioMuteToggled()));
594
595#ifndef Q_OS_MAC551#ifndef Q_OS_MAC
596 QMenu* helpMenu = addMenu("Help");552 QMenu* helpMenu = addMenu("Help");
597 QAction* helpAction = helpMenu->addAction(MenuOption::AboutApp);553 QAction* helpAction = helpMenu->addAction(MenuOption::AboutApp);
598 connect(helpAction, SIGNAL(triggered()), this, SLOT(aboutApp()));554 connect(helpAction, SIGNAL(triggered()), qApp, SLOT(aboutApp()));
599#endif555#endif
600}556}
601 557
602void Menu::loadSettings(QSettings* settings) {558void Menu::loadSettings() {
603 bool lockedSettings = false;559 scanMenuBar(&Menu::loadAction);
604 if (!settings) {
605 settings = Application::getInstance()->lockSettings();
606 lockedSettings = true;
607 }
608
609 _receivedAudioStreamSettings._dynamicJitterBuffers = settings->value("dynamicJitterBuffers", DEFAULT_DYNAMIC_JITTER_BUFFERS).toBool();
610 _receivedAudioStreamSettings._maxFramesOverDesired = settings->value("maxFramesOverDesired", DEFAULT_MAX_FRAMES_OVER_DESIRED).toInt();
611 _receivedAudioStreamSettings._staticDesiredJitterBufferFrames = settings->value("staticDesiredJitterBufferFrames", DEFAULT_STATIC_DESIRED_JITTER_BUFFER_FRAMES).toInt();
612 _receivedAudioStreamSettings._useStDevForJitterCalc = settings->value("useStDevForJitterCalc", DEFAULT_USE_STDEV_FOR_JITTER_CALC).toBool();
613 _receivedAudioStreamSettings._windowStarveThreshold = settings->value("windowStarveThreshold", DEFAULT_WINDOW_STARVE_THRESHOLD).toInt();
614 _receivedAudioStreamSettings._windowSecondsForDesiredCalcOnTooManyStarves = settings->value("windowSecondsForDesiredCalcOnTooManyStarves", DEFAULT_WINDOW_SECONDS_FOR_DESIRED_CALC_ON_TOO_MANY_STARVES).toInt();
615 _receivedAudioStreamSettings._windowSecondsForDesiredReduction = settings->value("windowSecondsForDesiredReduction", DEFAULT_WINDOW_SECONDS_FOR_DESIRED_REDUCTION).toInt();
616 _receivedAudioStreamSettings._repetitionWithFade = settings->value("repetitionWithFade", DEFAULT_REPETITION_WITH_FADE).toBool();
617
618 auto audio = DependencyManager::get<AudioClient>();
619 audio->setOutputStarveDetectionEnabled(settings->value("audioOutputStarveDetectionEnabled", DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_ENABLED).toBool());
620 audio->setOutputStarveDetectionThreshold(settings->value("audioOutputStarveDetectionThreshold", DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_THRESHOLD).toInt());
621 audio->setOutputStarveDetectionPeriod(settings->value("audioOutputStarveDetectionPeriod", DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_PERIOD).toInt());
622 int bufferSize = settings->value("audioOutputBufferSize", DEFAULT_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES).toInt();
623 QMetaObject::invokeMethod(audio.data(), "setOutputBufferSize", Q_ARG(int, bufferSize));
624
625 _fieldOfView = loadSetting(settings, "fieldOfView", DEFAULT_FIELD_OF_VIEW_DEGREES);
626 _realWorldFieldOfView = loadSetting(settings, "realWorldFieldOfView", DEFAULT_REAL_WORLD_FIELD_OF_VIEW_DEGREES);
627 _faceshiftEyeDeflection = loadSetting(settings, "faceshiftEyeDeflection", DEFAULT_FACESHIFT_EYE_DEFLECTION);
628 _faceshiftHostname = settings->value("faceshiftHostname", DEFAULT_FACESHIFT_HOSTNAME).toString();
629 _maxOctreePacketsPerSecond = loadSetting(settings, "maxOctreePPS", DEFAULT_MAX_OCTREE_PPS);
630 _octreeSizeScale = loadSetting(settings, "octreeSizeScale", DEFAULT_OCTREE_SIZE_SCALE);
631 _automaticAvatarLOD = settings->value("automaticAvatarLOD", true).toBool();
632 _avatarLODDecreaseFPS = loadSetting(settings, "avatarLODDecreaseFPS", DEFAULT_ADJUST_AVATAR_LOD_DOWN_FPS);
633 _avatarLODIncreaseFPS = loadSetting(settings, "avatarLODIncreaseFPS", ADJUST_LOD_UP_FPS);
634 _avatarLODDistanceMultiplier = loadSetting(settings, "avatarLODDistanceMultiplier",
635 DEFAULT_AVATAR_LOD_DISTANCE_MULTIPLIER);
636 _boundaryLevelAdjust = loadSetting(settings, "boundaryLevelAdjust", 0);
637 _snapshotsLocation = settings->value("snapshotsLocation",
638 QStandardPaths::writableLocation(QStandardPaths::DesktopLocation)).toString();
639 setScriptsLocation(settings->value("scriptsLocation", QString()).toString());
640
641#if defined(Q_OS_MAC) || defined(Q_OS_WIN)
642 _speechRecognizer.setEnabled(settings->value("speechRecognitionEnabled", false).toBool());
643#endif
644
645 _walletPrivateKey = settings->value("privateKey").toByteArray();
646
647 scanMenuBar(&loadAction, settings);
648 Application::getInstance()->getAvatar()->loadData(settings);
649 Application::getInstance()->updateWindowTitle();
650
651 // notify that a settings has changed
652 connect(&DependencyManager::get<NodeList>()->getDomainHandler(), &DomainHandler::hostnameChanged, this, &Menu::bumpSettings);
653
654 // MyAvatar caches some menu options, so we have to update them whenever we load settings.
655 // TODO: cache more settings in MyAvatar that are checked with very high frequency.
656 setIsOptionChecked(MenuOption::KeyboardMotorControl , true);
657 MyAvatar* myAvatar = Application::getInstance()->getAvatar();
658 myAvatar->updateCollisionGroups();
659 myAvatar->onToggleRagdoll();
660 myAvatar->updateMotionBehavior();
661
662 if (lockedSettings) {
663 Application::getInstance()->unlockSettings();
664 }
665}560}
666 561
667void Menu::saveSettings(QSettings* settings) {562void Menu::saveSettings() {
668 bool lockedSettings = false;563 scanMenuBar(&Menu::saveAction);
669 if (!settings) {
670 settings = Application::getInstance()->lockSettings();
671 lockedSettings = true;
672 }
673
674 settings->setValue("dynamicJitterBuffers", _receivedAudioStreamSettings._dynamicJitterBuffers);
675 settings->setValue("maxFramesOverDesired", _receivedAudioStreamSettings._maxFramesOverDesired);
676 settings->setValue("staticDesiredJitterBufferFrames", _receivedAudioStreamSettings._staticDesiredJitterBufferFrames);
677 settings->setValue("useStDevForJitterCalc", _receivedAudioStreamSettings._useStDevForJitterCalc);
678 settings->setValue("windowStarveThreshold", _receivedAudioStreamSettings._windowStarveThreshold);
679 settings->setValue("windowSecondsForDesiredCalcOnTooManyStarves", _receivedAudioStreamSettings._windowSecondsForDesiredCalcOnTooManyStarves);
680 settings->setValue("windowSecondsForDesiredReduction", _receivedAudioStreamSettings._windowSecondsForDesiredReduction);
681 settings->setValue("repetitionWithFade", _receivedAudioStreamSettings._repetitionWithFade);
682
683 auto audio = DependencyManager::get<AudioClient>();
684 settings->setValue("audioOutputStarveDetectionEnabled", audio->getOutputStarveDetectionEnabled());
685 settings->setValue("audioOutputStarveDetectionThreshold", audio->getOutputStarveDetectionThreshold());
686 settings->setValue("audioOutputStarveDetectionPeriod", audio->getOutputStarveDetectionPeriod());
687 settings->setValue("audioOutputBufferSize", audio->getOutputBufferSize());
688
689 settings->setValue("fieldOfView", _fieldOfView);
690 settings->setValue("faceshiftEyeDeflection", _faceshiftEyeDeflection);
691 settings->setValue("faceshiftHostname", _faceshiftHostname);
692 settings->setValue("maxOctreePPS", _maxOctreePacketsPerSecond);
693 settings->setValue("octreeSizeScale", _octreeSizeScale);
694 settings->setValue("automaticAvatarLOD", _automaticAvatarLOD);
695 settings->setValue("avatarLODDecreaseFPS", _avatarLODDecreaseFPS);
696 settings->setValue("avatarLODIncreaseFPS", _avatarLODIncreaseFPS);
697 settings->setValue("avatarLODDistanceMultiplier", _avatarLODDistanceMultiplier);
698 settings->setValue("boundaryLevelAdjust", _boundaryLevelAdjust);
699 settings->setValue("snapshotsLocation", _snapshotsLocation);
700 settings->setValue("scriptsLocation", _scriptsLocation);
701#if defined(Q_OS_MAC) || defined(Q_OS_WIN)
702 settings->setValue("speechRecognitionEnabled", _speechRecognizer.getEnabled());
703#endif
704 settings->setValue("privateKey", _walletPrivateKey);
705
706 scanMenuBar(&saveAction, settings);
707 Application::getInstance()->getAvatar()->saveData(settings);
708
709 DependencyManager::get<AddressManager>()->storeCurrentAddress();
710
711 if (lockedSettings) {
712 Application::getInstance()->unlockSettings();
713 }
714}
715
716void Menu::importSettings() {
717 QString locationDir(QStandardPaths::displayName(QStandardPaths::DesktopLocation));
718 QString fileName = QFileDialog::getOpenFileName(Application::getInstance()->getWindow(),
719 tr("Open .ini config file"),
720 locationDir,
721 tr("Text files (*.ini)"));
722 if (fileName != "") {
723 QSettings tmp(fileName, QSettings::IniFormat);
724 loadSettings(&tmp);
725 }
726}564}
727 565
728void Menu::exportSettings() {566void Menu::loadAction(Settings& settings, QAction& action) {
729 QString locationDir(QStandardPaths::displayName(QStandardPaths::DesktopLocation));567 if (action.isChecked() != settings.value(action.text(), action.isChecked()).toBool()) {
730 QString fileName = QFileDialog::getSaveFileName(Application::getInstance()->getWindow(),568 action.trigger();
731 tr("Save .ini config file"),
732 locationDir,
733 tr("Text files (*.ini)"));
734 if (fileName != "") {
735 QSettings tmp(fileName, QSettings::IniFormat);
736 saveSettings(&tmp);
737 tmp.sync();
738 }569 }
739}570}
740 571
741void Menu::loadAction(QSettings* set, QAction* action) {572void Menu::saveAction(Settings& settings, QAction& action) {
742 if (action->isChecked() != set->value(action->text(), action->isChecked()).toBool()) {573 settings.setValue(action.text(), action.isChecked());
743 action->trigger();
744 }
745}574}
746 575
747void Menu::saveAction(QSettings* set, QAction* action) {576void Menu::scanMenuBar(settingsAction modifySetting) {
748 set->setValue(action->text(), action->isChecked());577 Settings settings;
749}578 foreach (QMenu* menu, findChildren<QMenu*>()) {
750 579 scanMenu(*menu, modifySetting, settings);
751void Menu::scanMenuBar(settingsAction modifySetting, QSettings* set) {
752 QList<QMenu*> menus = this->findChildren<QMenu *>();
753
754 for (QList<QMenu *>::const_iterator it = menus.begin(); menus.end() != it; ++it) {
755 scanMenu(*it, modifySetting, set);
756 }580 }
757}581}
758 582
759void Menu::scanMenu(QMenu* menu, settingsAction modifySetting, QSettings* set) {583void Menu::scanMenu(QMenu& menu, settingsAction modifySetting, Settings& settings) {
760 QList<QAction*> actions = menu->actions();584 settings.beginGroup(menu.title());
761 585 foreach (QAction* action, menu.actions()) {
762 set->beginGroup(menu->title());586 if (action->menu()) {
763 for (QList<QAction *>::const_iterator it = actions.begin(); actions.end() != it; ++it) {587 scanMenu(*action->menu(), modifySetting, settings);
764 if ((*it)->menu()) {588 } else if (action->isCheckable()) {
765 scanMenu((*it)->menu(), modifySetting, set);589 modifySetting(settings, *action);
766 }
767 if ((*it)->isCheckable()) {
768 modifySetting(set, *it);
769 }590 }
770 }591 }
771 set->endGroup();592 settings.endGroup();
772}
773
774bool Menu::getShadowsEnabled() const {
775 return isOptionChecked(MenuOption::SimpleShadows) || isOptionChecked(MenuOption::CascadedShadows);
776}593}
777 594
778void Menu::addDisabledActionAndSeparator(QMenu* destinationMenu, const QString& actionName, int menuItemLocation) {595void Menu::addDisabledActionAndSeparator(QMenu* destinationMenu, const QString& actionName, int menuItemLocation) {
@@ -879,7 +696,6 @@ QAction* Menu::addCheckableActionToQMenuAndActionHash(QMenu* destinationMenu, · 100 unmodified lines
879 QAction::NoRole, menuItemLocation);696 QAction::NoRole, menuItemLocation);
880 action->setCheckable(true);697 action->setCheckable(true);
881 action->setChecked(checked);698 action->setChecked(checked);
882 connect(action, SIGNAL(changed()), this, SLOT(bumpSettings()));
883 699
884 return action;700 return action;
885}701}
@@ -917,614 +733,6 @@ QAction* Menu::getActionForOption(const QString& menuOption) { · 31 unmodified lines
917 return _actionHash.value(menuOption);733 return _actionHash.value(menuOption);
918}734}
919 735
920void Menu::aboutApp() {
921 InfoView::forcedShow(INFO_HELP_PATH);
922}
923
924void Menu::showEditEntitiesHelp() {
925 InfoView::forcedShow(INFO_EDIT_ENTITIES_PATH);
926}
927
928void Menu::bumpSettings() {
929 Application::getInstance()->bumpSettings();
930}
931
932void sendFakeEnterEvent() {
933 QPoint lastCursorPosition = QCursor::pos();
934 auto glCanvas = DependencyManager::get<GLCanvas>();
935
936 QPoint windowPosition = glCanvas->mapFromGlobal(lastCursorPosition);
937 QEnterEvent enterEvent = QEnterEvent(windowPosition, windowPosition, lastCursorPosition);
938 QCoreApplication::sendEvent(glCanvas.data(), &enterEvent);
939}
940
941const float DIALOG_RATIO_OF_WINDOW = 0.30f;
942
943void Menu::clearLoginDialogDisplayedFlag() {
944 // Needed for domains that don't require login.
945 _hasLoginDialogDisplayed = false;
946}
947
948void Menu::loginForCurrentDomain() {
949 if (!_loginDialog && !_hasLoginDialogDisplayed) {
950 _loginDialog = new LoginDialog(Application::getInstance()->getWindow());
951 _loginDialog->show();
952 _loginDialog->resizeAndPosition(false);
953 }
954
955 _hasLoginDialogDisplayed = true;
956}
957
958void Menu::showLoginForCurrentDomain() {
959 _hasLoginDialogDisplayed = false;
960 loginForCurrentDomain();
961}
962
963void Menu::editPreferences() {
964 if (!_preferencesDialog) {
965 _preferencesDialog = new PreferencesDialog();
966 _preferencesDialog->show();
967 } else {
968 _preferencesDialog->close();
969 }
970}
971
972void Menu::editAttachments() {
973 if (!_attachmentsDialog) {
974 _attachmentsDialog = new AttachmentsDialog();
975 _attachmentsDialog->show();
976 } else {
977 _attachmentsDialog->close();
978 }
979}
980
981void Menu::editAnimations() {
982 if (!_animationsDialog) {
983 _animationsDialog = new AnimationsDialog();
984 _animationsDialog->show();
985 } else {
986 _animationsDialog->close();
987 }
988}
989
990void Menu::toggleSixense(bool shouldEnable) {
991 SixenseManager& sixenseManager = SixenseManager::getInstance();
992
993 if (shouldEnable && !sixenseManager.isInitialized()) {
994 sixenseManager.initialize();
995 sixenseManager.setFilter(isOptionChecked(MenuOption::FilterSixense));
996 sixenseManager.setLowVelocityFilter(isOptionChecked(MenuOption::LowVelocityFilter));
997 }
998
999 sixenseManager.setIsEnabled(shouldEnable);
1000}
1001
1002void Menu::changePrivateKey() {
1003 // setup the dialog
1004 QInputDialog privateKeyDialog(Application::getInstance()->getWindow());
1005 privateKeyDialog.setWindowTitle("Change Private Key");
1006 privateKeyDialog.setLabelText("RSA 2048-bit Private Key:");
1007 privateKeyDialog.setWindowFlags(Qt::Sheet);
1008 privateKeyDialog.setTextValue(QString(_walletPrivateKey));
1009 privateKeyDialog.resize(privateKeyDialog.parentWidget()->size().width() * DIALOG_RATIO_OF_WINDOW,
1010 privateKeyDialog.size().height());
1011
1012 int dialogReturn = privateKeyDialog.exec();
1013 if (dialogReturn == QDialog::Accepted) {
1014 // pull the private key from the dialog
1015 _walletPrivateKey = privateKeyDialog.textValue().toUtf8();
1016 }
1017
1018 bumpSettings();
1019
1020 sendFakeEnterEvent();
1021}
1022
1023void Menu::toggleAddressBar() {
1024 if (!_addressBarDialog) {
1025 _addressBarDialog = new AddressBarDialog();
1026 }
1027
1028 if (!_addressBarDialog->isVisible()) {
1029 _addressBarDialog->show();
1030 }
1031}
1032
1033void Menu::copyAddress() {
1034 auto addressManager = DependencyManager::get<AddressManager>();
1035 QString address = addressManager->currentAddress().toString();
1036 QClipboard* clipboard = QApplication::clipboard();
1037 clipboard->setText(address);
1038}
1039
1040void Menu::copyPath() {
1041 auto addressManager = DependencyManager::get<AddressManager>();
1042 QString path = addressManager->currentPath();
1043 QClipboard* clipboard = QApplication::clipboard();
1044 clipboard->setText(path);
1045}
1046
1047void Menu::changeVSync() {
1048 Application::getInstance()->setVSyncEnabled(isOptionChecked(MenuOption::RenderTargetFramerateVSyncOn));
1049}
1050
1051void Menu::loadBookmarks() {
1052 QVariantMap* bookmarks = Application::getInstance()->getBookmarks()->getBookmarks();
1053 if (bookmarks->count() > 0) {
1054
1055 QMapIterator<QString, QVariant> i(*bookmarks);
1056 while (i.hasNext()) {
1057 i.next();
1058
1059 QString bookmarkName = i.key();
1060 QString bookmarkAddress = i.value().toString();
1061
1062 QAction* teleportAction = new QAction(getMenu(MenuOption::Bookmarks));
1063 teleportAction->setData(bookmarkAddress);
1064 connect(teleportAction, SIGNAL(triggered()), this, SLOT(teleportToBookmark()));
1065
1066 addActionToQMenuAndActionHash(_bookmarksMenu, teleportAction, bookmarkName, 0, QAction::NoRole);
1067 }
1068
1069 _bookmarksMenu->setEnabled(true);
1070 _deleteBookmarksMenu->setEnabled(true);
1071 }
1072}
1073
1074void Menu::bookmarkLocation() {
1075
1076 QInputDialog bookmarkLocationDialog(Application::getInstance()->getWindow());
1077 bookmarkLocationDialog.setWindowTitle("Bookmark Location");
1078 bookmarkLocationDialog.setLabelText("Name:");
1079 bookmarkLocationDialog.setInputMode(QInputDialog::TextInput);
1080 bookmarkLocationDialog.resize(400, 200);
1081
1082 if (bookmarkLocationDialog.exec() == QDialog::Rejected) {
1083 return;
1084 }
1085
1086 QString bookmarkName = bookmarkLocationDialog.textValue().trimmed();
1087 bookmarkName = bookmarkName.replace(QRegExp("(\r\n|[\r\n\t\v ])+"), " ");
1088 if (bookmarkName.length() == 0) {
1089 return;
1090 }
1091
1092 auto addressManager = DependencyManager::get<AddressManager>();
1093 QString bookmarkAddress = addressManager->currentAddress().toString();
1094
1095 Bookmarks* bookmarks = Application::getInstance()->getBookmarks();
1096 if (bookmarks->contains(bookmarkName)) {
1097 QMessageBox duplicateBookmarkMessage;
1098 duplicateBookmarkMessage.setIcon(QMessageBox::Warning);
1099 duplicateBookmarkMessage.setText("The bookmark name you entered already exists in your list.");
1100 duplicateBookmarkMessage.setInformativeText("Would you like to overwrite it?");
1101 duplicateBookmarkMessage.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
1102 duplicateBookmarkMessage.setDefaultButton(QMessageBox::Yes);
1103 if (duplicateBookmarkMessage.exec() == QMessageBox::No) {
1104 return;
1105 }
1106 removeAction(_bookmarksMenu, bookmarkName);
1107 }
1108
1109 QAction* teleportAction = new QAction(getMenu(MenuOption::Bookmarks));
1110 teleportAction->setData(bookmarkAddress);
1111 connect(teleportAction, SIGNAL(triggered()), this, SLOT(teleportToBookmark()));
1112
1113 QList<QAction*> menuItems = _bookmarksMenu->actions();
1114 int position = 0;
1115 while (position < menuItems.count() && bookmarkName > menuItems[position]->text()) {
1116 position += 1;
1117 }
1118
1119 addActionToQMenuAndActionHash(_bookmarksMenu, teleportAction, bookmarkName, 0,
1120 QAction::NoRole, position);
1121
1122 bookmarks->insert(bookmarkName, bookmarkAddress); // Overwrites any item with the same bookmarkName.
1123
1124 _bookmarksMenu->setEnabled(true);
1125 _deleteBookmarksMenu->setEnabled(true);
1126}
1127
1128void Menu::teleportToBookmark() {
1129 QAction *action = qobject_cast<QAction *>(sender());
1130 QString address = action->data().toString();
1131 DependencyManager::get<AddressManager>()->handleLookupString(address);
1132}
1133
1134void Menu::deleteBookmark() {
1135
1136 QStringList bookmarkList;
1137 QList<QAction*> menuItems = _bookmarksMenu->actions();
1138 for (int i = 0; i < menuItems.count(); i += 1) {
1139 bookmarkList.append(menuItems[i]->text());
1140 }
1141
1142 QInputDialog deleteBookmarkDialog(Application::getInstance()->getWindow());
1143 deleteBookmarkDialog.setWindowTitle("Delete Bookmark");
1144 deleteBookmarkDialog.setLabelText("Select the bookmark to delete");
1145 deleteBookmarkDialog.resize(400, 400);
1146 deleteBookmarkDialog.setOption(QInputDialog::UseListViewForComboBoxItems);
1147 deleteBookmarkDialog.setComboBoxItems(bookmarkList);
1148 deleteBookmarkDialog.setOkButtonText("Delete");
1149
1150 if (deleteBookmarkDialog.exec() == QDialog::Rejected) {
1151 return;
1152 }
1153
1154 QString bookmarkName = deleteBookmarkDialog.textValue().trimmed();
1155 if (bookmarkName.length() == 0) {
1156 return;
1157 }
1158
1159 removeAction(_bookmarksMenu, bookmarkName);
1160
1161 Bookmarks* bookmarks = Application::getInstance()->getBookmarks();
1162 bookmarks->remove(bookmarkName);
1163
1164 if (_bookmarksMenu->actions().count() == 0) {
1165 _bookmarksMenu->setEnabled(false);
1166 _deleteBookmarksMenu->setEnabled(false);
1167 }
1168}
1169
1170void Menu::displayNameLocationResponse(const QString& errorString) {
1171
1172 if (!errorString.isEmpty()) {
1173 QMessageBox msgBox;
1174 msgBox.setText(errorString);
1175 msgBox.exec();
1176 }
1177}
1178
1179void Menu::toggleLoginMenuItem() {
1180 AccountManager& accountManager = AccountManager::getInstance();
1181
1182 disconnect(_loginAction, 0, 0, 0);
1183
1184 if (accountManager.isLoggedIn()) {
1185 // change the menu item to logout
1186 _loginAction->setText("Logout " + accountManager.getAccountInfo().getUsername());
1187 connect(_loginAction, &QAction::triggered, &accountManager, &AccountManager::logout);
1188 } else {
1189 // change the menu item to login
1190 _loginAction->setText("Login");
1191
1192 connect(_loginAction, &QAction::triggered, this, &Menu::showLoginForCurrentDomain);
1193 }
1194}
1195
1196void Menu::bandwidthDetails() {
1197 if (! _bandwidthDialog) {
1198 _bandwidthDialog = new BandwidthDialog(DependencyManager::get<GLCanvas>().data(),
1199 Application::getInstance()->getBandwidthMeter());
1200 connect(_bandwidthDialog, SIGNAL(closed()), _bandwidthDialog, SLOT(deleteLater()));
1201
1202 _bandwidthDialog->show();
1203
1204 if (_hmdToolsDialog) {
1205 _hmdToolsDialog->watchWindow(_bandwidthDialog->windowHandle());
1206 }
1207 }
1208 _bandwidthDialog->raise();
1209}
1210
1211void Menu::showMetavoxelEditor() {
1212 if (!_MetavoxelEditor) {
1213 _MetavoxelEditor = new MetavoxelEditor();
1214 }
1215 _MetavoxelEditor->raise();
1216}
1217
1218void Menu::showMetavoxelNetworkSimulator() {
1219 if (!_metavoxelNetworkSimulator) {
1220 _metavoxelNetworkSimulator = new MetavoxelNetworkSimulator();
1221 }
1222 _metavoxelNetworkSimulator->raise();
1223}
1224
1225void Menu::showScriptEditor() {
1226 if(!_ScriptEditor || !_ScriptEditor->isVisible()) {
1227 _ScriptEditor = new ScriptEditorWindow();
1228 }
1229 _ScriptEditor->raise();
1230}
1231
1232void Menu::showChat() {
1233 if (AccountManager::getInstance().isLoggedIn()) {
1234 QMainWindow* mainWindow = Application::getInstance()->getWindow();
1235 if (!_chatWindow) {
1236 _chatWindow = new ChatWindow(mainWindow);
1237 }
1238
1239 if (_chatWindow->isHidden()) {
1240 _chatWindow->show();
1241 }
1242 _chatWindow->raise();
1243 _chatWindow->activateWindow();
1244 _chatWindow->setFocus();
1245 } else {
1246 Application::getInstance()->getTrayIcon()->showMessage("Interface", "You need to login to be able to chat with others on this domain.");
1247 }
1248}
1249
1250void Menu::loadRSSDKFile() {
1251 RealSense::getInstance()->loadRSSDKFile();
1252}
1253
1254void Menu::toggleChat() {
1255#ifdef HAVE_QXMPP
1256 _chatAction->setEnabled(XmppClient::getInstance().getXMPPClient().isConnected());
1257 if (!_chatAction->isEnabled() && _chatWindow && AccountManager::getInstance().isLoggedIn()) {
1258 if (_chatWindow->isHidden()) {
1259 _chatWindow->show();
1260 _chatWindow->raise();
1261 _chatWindow->activateWindow();
1262 _chatWindow->setFocus();
1263 } else {
1264 _chatWindow->hide();
1265 }
1266 }
1267#endif
1268}
1269
1270void Menu::toggleConsole() {
1271 QMainWindow* mainWindow = Application::getInstance()->getWindow();
1272 if (!_jsConsole) {
1273 QDialog* dialog = new QDialog(mainWindow, Qt::WindowStaysOnTopHint);
1274 QVBoxLayout* layout = new QVBoxLayout(dialog);
1275 dialog->setLayout(new QVBoxLayout(dialog));
1276
1277 dialog->resize(QSize(CONSOLE_WIDTH, CONSOLE_HEIGHT));
1278 layout->setMargin(0);
1279 layout->setSpacing(0);
1280 layout->addWidget(new JSConsole(dialog));
1281 dialog->setWindowOpacity(CONSOLE_WINDOW_OPACITY);
1282 dialog->setWindowTitle(CONSOLE_TITLE);
1283
1284 _jsConsole = dialog;
1285 }
1286 _jsConsole->setVisible(!_jsConsole->isVisible());
1287}
1288
1289void Menu::toggleToolWindow() {
1290 QMainWindow* toolWindow = Application::getInstance()->getToolWindow();
1291 toolWindow->setVisible(!toolWindow->isVisible());
1292 if (_hmdToolsDialog) {
1293 _hmdToolsDialog->watchWindow(toolWindow->windowHandle());
1294 }
1295}
1296
1297void Menu::audioMuteToggled() {
1298 QAction *muteAction = _actionHash.value(MenuOption::MuteAudio);
1299 if (muteAction) {
1300 muteAction->setChecked(DependencyManager::get<AudioClient>()->isMuted());
1301 }
1302}
1303
1304void Menu::octreeStatsDetails() {
1305 if (!_octreeStatsDialog) {
1306 _octreeStatsDialog = new OctreeStatsDialog(DependencyManager::get<GLCanvas>().data(),
1307 Application::getInstance()->getOcteeSceneStats());
1308 connect(_octreeStatsDialog, SIGNAL(closed()), _octreeStatsDialog, SLOT(deleteLater()));
1309 _octreeStatsDialog->show();
1310 if (_hmdToolsDialog) {
1311 _hmdToolsDialog->watchWindow(_octreeStatsDialog->windowHandle());
1312 }
1313 }
1314 _octreeStatsDialog->raise();
1315}
1316
1317QString Menu::getLODFeedbackText() {
1318 // determine granularity feedback
1319 int boundaryLevelAdjust = getBoundaryLevelAdjust();
1320 QString granularityFeedback;
1321
1322 switch (boundaryLevelAdjust) {
1323 case 0: {
1324 granularityFeedback = QString("at standard granularity.");
1325 } break;
1326 case 1: {
1327 granularityFeedback = QString("at half of standard granularity.");
1328 } break;
1329 case 2: {
1330 granularityFeedback = QString("at a third of standard granularity.");
1331 } break;
1332 default: {
1333 granularityFeedback = QString("at 1/%1th of standard granularity.").arg(boundaryLevelAdjust + 1);
1334 } break;
1335 }
1336
1337 // distance feedback
1338 float octreeSizeScale = getOctreeSizeScale();
1339 float relativeToDefault = octreeSizeScale / DEFAULT_OCTREE_SIZE_SCALE;
1340 QString result;
1341 if (relativeToDefault > 1.01) {
1342 result = QString("%1 further %2").arg(relativeToDefault,8,'f',2).arg(granularityFeedback);
1343 } else if (relativeToDefault > 0.99) {
1344 result = QString("the default distance %1").arg(granularityFeedback);
1345 } else {
1346 result = QString("%1 of default %2").arg(relativeToDefault,8,'f',3).arg(granularityFeedback);
1347 }
1348 return result;
1349}
1350
1351void Menu::autoAdjustLOD(float currentFPS) {
1352 // NOTE: our first ~100 samples at app startup are completely all over the place, and we don't
1353 // really want to count them in our average, so we will ignore the real frame rates and stuff
1354 // our moving average with simulated good data
1355 const int IGNORE_THESE_SAMPLES = 100;
1356 const float ASSUMED_FPS = 60.0f;
1357 if (_fpsAverage.getSampleCount() < IGNORE_THESE_SAMPLES) {
1358 currentFPS = ASSUMED_FPS;
1359 }
1360 _fpsAverage.updateAverage(currentFPS);
1361 _fastFPSAverage.updateAverage(currentFPS);
1362
1363 quint64 now = usecTimestampNow();
1364
1365 const quint64 ADJUST_AVATAR_LOD_DOWN_DELAY = 1000 * 1000;
1366 if (_automaticAvatarLOD) {
1367 if (_fastFPSAverage.getAverage() < _avatarLODDecreaseFPS) {
1368 if (now - _lastAvatarDetailDrop > ADJUST_AVATAR_LOD_DOWN_DELAY) {
1369 // attempt to lower the detail in proportion to the fps difference
1370 float targetFps = (_avatarLODDecreaseFPS + _avatarLODIncreaseFPS) * 0.5f;
1371 float averageFps = _fastFPSAverage.getAverage();
1372 const float MAXIMUM_MULTIPLIER_SCALE = 2.0f;
1373 _avatarLODDistanceMultiplier = qMin(MAXIMUM_AVATAR_LOD_DISTANCE_MULTIPLIER, _avatarLODDistanceMultiplier *
1374 (averageFps < EPSILON ? MAXIMUM_MULTIPLIER_SCALE :
1375 qMin(MAXIMUM_MULTIPLIER_SCALE, targetFps / averageFps)));
1376 _lastAvatarDetailDrop = now;
1377 }
1378 } else if (_fastFPSAverage.getAverage() > _avatarLODIncreaseFPS) {
1379 // let the detail level creep slowly upwards
1380 const float DISTANCE_DECREASE_RATE = 0.05f;
1381 _avatarLODDistanceMultiplier = qMax(MINIMUM_AVATAR_LOD_DISTANCE_MULTIPLIER,
1382 _avatarLODDistanceMultiplier - DISTANCE_DECREASE_RATE);
1383 }
1384 }
1385
1386 bool changed = false;
1387 quint64 elapsed = now - _lastAdjust;
1388
1389 if (elapsed > ADJUST_LOD_DOWN_DELAY && _fpsAverage.getAverage() < ADJUST_LOD_DOWN_FPS
1390 && _octreeSizeScale > ADJUST_LOD_MIN_SIZE_SCALE) {
1391
1392 _octreeSizeScale *= ADJUST_LOD_DOWN_BY;
1393
1394 if (_octreeSizeScale < ADJUST_LOD_MIN_SIZE_SCALE) {
1395 _octreeSizeScale = ADJUST_LOD_MIN_SIZE_SCALE;
1396 }
1397 changed = true;
1398 _lastAdjust = now;
1399 qDebug() << "adjusting LOD down... average fps for last approximately 5 seconds=" << _fpsAverage.getAverage()
1400 << "_octreeSizeScale=" << _octreeSizeScale;
1401 }
1402
1403 if (elapsed > ADJUST_LOD_UP_DELAY && _fpsAverage.getAverage() > ADJUST_LOD_UP_FPS
1404 && _octreeSizeScale < ADJUST_LOD_MAX_SIZE_SCALE) {
1405 _octreeSizeScale *= ADJUST_LOD_UP_BY;
1406 if (_octreeSizeScale > ADJUST_LOD_MAX_SIZE_SCALE) {
1407 _octreeSizeScale = ADJUST_LOD_MAX_SIZE_SCALE;
1408 }
1409 changed = true;
1410 _lastAdjust = now;
1411 qDebug() << "adjusting LOD up... average fps for last approximately 5 seconds=" << _fpsAverage.getAverage()
1412 << "_octreeSizeScale=" << _octreeSizeScale;
1413 }
1414
1415 if (changed) {
1416 _shouldRenderTableNeedsRebuilding = true;
1417 if (_lodToolsDialog) {
1418 _lodToolsDialog->reloadSliders();
1419 }
1420 }
1421}
1422
1423void Menu::resetLODAdjust() {
1424 _fpsAverage.reset();
1425 _fastFPSAverage.reset();
1426 _lastAvatarDetailDrop = _lastAdjust = usecTimestampNow();
1427}
1428
1429void Menu::setOctreeSizeScale(float sizeScale) {
1430 _octreeSizeScale = sizeScale;
1431 _shouldRenderTableNeedsRebuilding = true;
1432 bumpSettings();
1433}
1434
1435void Menu::setBoundaryLevelAdjust(int boundaryLevelAdjust) {
1436 _boundaryLevelAdjust = boundaryLevelAdjust;
1437 _shouldRenderTableNeedsRebuilding = true;
1438 bumpSettings();
1439}
1440
1441// TODO: This is essentially the same logic used to render octree cells, but since models are more detailed then octree cells
1442// I've added a voxelToModelRatio that adjusts how much closer to a model you have to be to see it.
1443bool Menu::shouldRenderMesh(float largestDimension, float distanceToCamera) {
1444 const float octreeToMeshRatio = 4.0f; // must be this many times closer to a mesh than a voxel to see it.
1445 float octreeSizeScale = getOctreeSizeScale();
1446 int boundaryLevelAdjust = getBoundaryLevelAdjust();
1447 float maxScale = (float)TREE_SCALE;
1448 float visibleDistanceAtMaxScale = boundaryDistanceForRenderLevel(boundaryLevelAdjust, octreeSizeScale) / octreeToMeshRatio;
1449
1450 if (_shouldRenderTableNeedsRebuilding) {
1451 _shouldRenderTable.clear();
1452
1453 float SMALLEST_SCALE_IN_TABLE = 0.001f; // 1mm is plenty small
1454 float scale = maxScale;
1455 float visibleDistanceAtScale = visibleDistanceAtMaxScale;
1456
1457 while (scale > SMALLEST_SCALE_IN_TABLE) {
1458 scale /= 2.0f;
1459 visibleDistanceAtScale /= 2.0f;
1460 _shouldRenderTable[scale] = visibleDistanceAtScale;
1461 }
1462 _shouldRenderTableNeedsRebuilding = false;
1463 }
1464
1465 float closestScale = maxScale;
1466 float visibleDistanceAtClosestScale = visibleDistanceAtMaxScale;
1467 QMap<float, float>::const_iterator lowerBound = _shouldRenderTable.lowerBound(largestDimension);
1468 if (lowerBound != _shouldRenderTable.constEnd()) {
1469 closestScale = lowerBound.key();
1470 visibleDistanceAtClosestScale = lowerBound.value();
1471 }
1472
1473 if (closestScale < largestDimension) {
1474 visibleDistanceAtClosestScale *= 2.0f;
1475 }
1476
1477 return (distanceToCamera <= visibleDistanceAtClosestScale);
1478}
1479
1480void Menu::cachesSizeDialog() {
1481 qDebug() << "Caches size:" << _cachesSizeDialog.isNull();
1482 if (!_cachesSizeDialog) {
1483 _cachesSizeDialog = new CachesSizeDialog(DependencyManager::get<GLCanvas>().data());
1484 connect(_cachesSizeDialog, SIGNAL(closed()), _cachesSizeDialog, SLOT(deleteLater()));
1485 _cachesSizeDialog->show();
1486 if (_hmdToolsDialog) {
1487 _hmdToolsDialog->watchWindow(_cachesSizeDialog->windowHandle());
1488 }
1489 }
1490 _cachesSizeDialog->raise();
1491}
1492
1493void Menu::lodTools() {
1494 if (!_lodToolsDialog) {
1495 _lodToolsDialog = new LodToolsDialog(DependencyManager::get<GLCanvas>().data());
1496 connect(_lodToolsDialog, SIGNAL(closed()), _lodToolsDialog, SLOT(deleteLater()));
1497 _lodToolsDialog->show();
1498 if (_hmdToolsDialog) {
1499 _hmdToolsDialog->watchWindow(_lodToolsDialog->windowHandle());
1500 }
1501 }
1502 _lodToolsDialog->raise();
1503}
1504
1505void Menu::hmdTools(bool showTools) {
1506 if (showTools) {
1507 if (!_hmdToolsDialog) {
1508 _hmdToolsDialog = new HMDToolsDialog(DependencyManager::get<GLCanvas>().data());
1509 connect(_hmdToolsDialog, SIGNAL(closed()), SLOT(hmdToolsClosed()));
1510 }
1511 _hmdToolsDialog->show();
1512 _hmdToolsDialog->raise();
1513 } else {
1514 hmdToolsClosed();
1515 }
1516 Application::getInstance()->getWindow()->activateWindow();
1517}
1518
1519void Menu::hmdToolsClosed() {
1520 Menu::getInstance()->getActionForOption(MenuOption::HMDTools)->setChecked(false);
1521 _hmdToolsDialog->hide();
1522}
1523
1524void Menu::runTests() {
1525 runTimingTests();
1526}
1527
1528QAction* Menu::getActionFromName(const QString& menuName, QMenu* menu) {736QAction* Menu::getActionFromName(const QString& menuName, QMenu* menu) {
1529 QList<QAction*> menuActions;737 QList<QAction*> menuActions;
1530 if (menu) {738 if (menu) {
@@ -1532,7 +740,7 @@ QAction* Menu::getActionFromName(const QString& menuName, QMenu* menu) { · 1 unmodified line
1532 } else {740 } else {
1533 menuActions = actions();741 menuActions = actions();
1534 }742 }
1535 743
1536 foreach (QAction* menuAction, menuActions) {744 foreach (QAction* menuAction, menuActions) {
1537 if (menuName == menuAction->text()) {745 if (menuName == menuAction->text()) {
1538 return menuAction;746 return menuAction;
@@ -1632,14 +840,14 @@ QMenu* Menu::addMenu(const QString& menuName) { · 93 unmodified lines
1632 }840 }
1633 addTo = menu;841 addTo = menu;
1634 }842 }
1635 843
1636 QMenuBar::repaint();844 QMenuBar::repaint();
1637 return menu;845 return menu;
1638}846}
1639 847
1640void Menu::removeMenu(const QString& menuName) {848void Menu::removeMenu(const QString& menuName) {
1641 QAction* action = getMenuAction(menuName);849 QAction* action = getMenuAction(menuName);
1642 850
1643 // only proceed if the menu actually exists851 // only proceed if the menu actually exists
1644 if (action) {852 if (action) {
1645 QString finalMenuPart;853 QString finalMenuPart;
@@ -1649,14 +857,14 @@ void Menu::removeMenu(const QString& menuName) { · 3 unmodified lines
1649 } else {857 } else {
1650 QMenuBar::removeAction(action);858 QMenuBar::removeAction(action);
1651 }859 }
1652 860
1653 QMenuBar::repaint();861 QMenuBar::repaint();
1654 }862 }
1655}863}
1656 864
1657bool Menu::menuExists(const QString& menuName) {865bool Menu::menuExists(const QString& menuName) {
1658 QAction* action = getMenuAction(menuName);866 QAction* action = getMenuAction(menuName);
1659 867
1660 // only proceed if the menu actually exists868 // only proceed if the menu actually exists
1661 if (action) {869 if (action) {
1662 return true;870 return true;
@@ -1701,7 +909,7 @@ void Menu::addMenuItem(const MenuItemProperties& properties) { · 38 unmodified lines
1701 if (!properties.shortcutKeySequence.isEmpty()) {909 if (!properties.shortcutKeySequence.isEmpty()) {
1702 shortcut = new QShortcut(properties.shortcutKeySequence, this);910 shortcut = new QShortcut(properties.shortcutKeySequence, this);
1703 }911 }
1704 912
1705 // check for positioning requests913 // check for positioning requests
1706 int requestedPosition = properties.position;914 int requestedPosition = properties.position;
1707 if (requestedPosition == UNSPECIFIED_POSITION && !properties.beforeItem.isEmpty()) {915 if (requestedPosition == UNSPECIFIED_POSITION && !properties.beforeItem.isEmpty()) {
@@ -1715,18 +923,18 @@ void Menu::addMenuItem(const MenuItemProperties& properties) { · 7 unmodified lines
1715 requestedPosition = afterPosition + 1;923 requestedPosition = afterPosition + 1;
1716 }924 }
1717 }925 }
1718 926
1719 QAction* menuItemAction = NULL;927 QAction* menuItemAction = NULL;
1720 if (properties.isSeparator) {928 if (properties.isSeparator) {
1721 addDisabledActionAndSeparator(menuObj, properties.menuItemName, requestedPosition);929 addDisabledActionAndSeparator(menuObj, properties.menuItemName, requestedPosition);
1722 } else if (properties.isCheckable) {930 } else if (properties.isCheckable) {
1723 menuItemAction = addCheckableActionToQMenuAndActionHash(menuObj, properties.menuItemName,931 menuItemAction = addCheckableActionToQMenuAndActionHash(menuObj, properties.menuItemName,
1724 properties.shortcutKeySequence, properties.isChecked,932 properties.shortcutKeySequence, properties.isChecked,
1725 MenuScriptingInterface::getInstance(), SLOT(menuItemTriggered()), requestedPosition);933 MenuScriptingInterface::getInstance(), SLOT(menuItemTriggered()), requestedPosition);
1726 } else {934 } else {
1727 menuItemAction = addActionToQMenuAndActionHash(menuObj, properties.menuItemName, properties.shortcutKeySequence,935 menuItemAction = addActionToQMenuAndActionHash(menuObj, properties.menuItemName, properties.shortcutKeySequence,
1728 MenuScriptingInterface::getInstance(), SLOT(menuItemTriggered()),936 MenuScriptingInterface::getInstance(), SLOT(menuItemTriggered()),
1729 QAction::NoRole, requestedPosition);937 QAction::NoRole, requestedPosition);
1730 }938 }
1731 if (shortcut && menuItemAction) {939 if (shortcut && menuItemAction) {
1732 connect(shortcut, SIGNAL(activated()), menuItemAction, SLOT(trigger()));940 connect(shortcut, SIGNAL(activated()), menuItemAction, SLOT(trigger()));
@@ -1750,16 +958,3 @@ bool Menu::menuItemExists(const QString& menu, const QString& menuitem) { · 17 unmodified lines
1750 }958 }
1751 return false;959 return false;
1752};960};
1753
1754QString Menu::getSnapshotsLocation() const {
1755 if (_snapshotsLocation.isNull() || _snapshotsLocation.isEmpty() || QDir(_snapshotsLocation).exists() == false) {
1756 return QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
1757 }
1758 return _snapshotsLocation;
1759}
1760
1761void Menu::setScriptsLocation(const QString& scriptsLocation) {
1762 _scriptsLocation = scriptsLocation;
1763 bumpSettings();
1764 emit scriptLocationChanged(scriptsLocation);
1765}