diff --git a/interface/src/scripting/WindowScriptingInterface.cpp b/interface/src/scripting/WindowScriptingInterface.cpp index d5c645d176..698e6ebb29 100644 --- a/interface/src/scripting/WindowScriptingInterface.cpp +++ b/interface/src/scripting/WindowScriptingInterface.cpp @@ -116,7 +116,17 @@ QScriptValue WindowScriptingInterface::confirm(const QString& message) { /// Display a prompt with a text box /// \param const QString& message message to display /// \param const QString& defaultText default text in the text box -void WindowScriptingInterface::prompt(const QString& message, const QString& defaultText) { +/// \return QScriptValue string text value in text box if the dialog was accepted, `null` otherwise. +QScriptValue WindowScriptingInterface::prompt(const QString& message, const QString& defaultText) { + bool ok = false; + QString result = OffscreenUi::getText(nullptr, "", message, QLineEdit::Normal, defaultText, &ok); + return ok ? QScriptValue(result) : QScriptValue::NullValue; +} + +/// Display a prompt with a text box +/// \param const QString& message message to display +/// \param const QString& defaultText default text in the text box +void WindowScriptingInterface::promptAsync(const QString& message, const QString& defaultText) { auto offscreenUi = DependencyManager::get(); connect(offscreenUi.data(), &OffscreenUi::inputDialogResponse, this, [=] (QVariant result) { @@ -180,7 +190,29 @@ void WindowScriptingInterface::ensureReticleVisible() const { /// \param const QString& title title of the window /// \param const QString& directory directory to start the file browser at /// \param const QString& nameFilter filter to filter filenames by - see `QFileDialog` -void WindowScriptingInterface::browseDir(const QString& title, const QString& directory) { +/// \return QScriptValue file path as a string if one was selected, otherwise `QScriptValue::NullValue` +QScriptValue WindowScriptingInterface::browseDir(const QString& title, const QString& directory) { + ensureReticleVisible(); + QString path = directory; + if (path.isEmpty()) { + path = getPreviousBrowseLocation(); + } +#ifndef Q_OS_WIN + path = fixupPathForMac(directory); +#endif + QString result = OffscreenUi::getExistingDirectory(nullptr, title, path); + if (!result.isEmpty()) { + setPreviousBrowseLocation(QFileInfo(result).absolutePath()); + } + return result.isEmpty() ? QScriptValue::NullValue : QScriptValue(result); +} + +/// Display a "browse to directory" dialog. If `directory` is an invalid file or directory the browser will start at the current +/// working directory. +/// \param const QString& title title of the window +/// \param const QString& directory directory to start the file browser at +/// \param const QString& nameFilter filter to filter filenames by - see `QFileDialog` +void WindowScriptingInterface::browseDirAsync(const QString& title, const QString& directory) { ensureReticleVisible(); QString path = directory; if (path.isEmpty()) { @@ -204,12 +236,32 @@ void WindowScriptingInterface::browseDir(const QString& title, const QString& di OffscreenUi::getExistingDirectoryAsync(nullptr, title, path); } +/// \param const QString& title title of the window +/// \param const QString& directory directory to start the file browser at +/// \param const QString& nameFilter filter to filter filenames by - see `QFileDialog` +/// \return QScriptValue file path as a string if one was selected, otherwise `QScriptValue::NullValue` +QScriptValue WindowScriptingInterface::browse(const QString& title, const QString& directory, const QString& nameFilter) { + ensureReticleVisible(); + QString path = directory; + if (path.isEmpty()) { + path = getPreviousBrowseLocation(); + } +#ifndef Q_OS_WIN + path = fixupPathForMac(directory); +#endif + QString result = OffscreenUi::getOpenFileName(nullptr, title, path, nameFilter); + if (!result.isEmpty()) { + setPreviousBrowseLocation(QFileInfo(result).absolutePath()); + } + return result.isEmpty() ? QScriptValue::NullValue : QScriptValue(result); +} + /// Display an open file dialog. If `directory` is an invalid file or directory the browser will start at the current /// working directory. /// \param const QString& title title of the window /// \param const QString& directory directory to start the file browser at /// \param const QString& nameFilter filter to filter filenames by - see `QFileDialog` -void WindowScriptingInterface::browse(const QString& title, const QString& directory, const QString& nameFilter) { +void WindowScriptingInterface::browseAsync(const QString& title, const QString& directory, const QString& nameFilter) { ensureReticleVisible(); QString path = directory; if (path.isEmpty()) { @@ -238,7 +290,29 @@ void WindowScriptingInterface::browse(const QString& title, const QString& direc /// \param const QString& title title of the window /// \param const QString& directory directory to start the file browser at /// \param const QString& nameFilter filter to filter filenames by - see `QFileDialog` -void WindowScriptingInterface::save(const QString& title, const QString& directory, const QString& nameFilter) { +/// \return QScriptValue file path as a string if one was selected, otherwise `QScriptValue::NullValue` +QScriptValue WindowScriptingInterface::save(const QString& title, const QString& directory, const QString& nameFilter) { + ensureReticleVisible(); + QString path = directory; + if (path.isEmpty()) { + path = getPreviousBrowseLocation(); + } +#ifndef Q_OS_WIN + path = fixupPathForMac(directory); +#endif + QString result = OffscreenUi::getSaveFileName(nullptr, title, path, nameFilter); + if (!result.isEmpty()) { + setPreviousBrowseLocation(QFileInfo(result).absolutePath()); + } + return result.isEmpty() ? QScriptValue::NullValue : QScriptValue(result); +} + +/// Display a save file dialog. If `directory` is an invalid file or directory the browser will start at the current +/// working directory. +/// \param const QString& title title of the window +/// \param const QString& directory directory to start the file browser at +/// \param const QString& nameFilter filter to filter filenames by - see `QFileDialog` +void WindowScriptingInterface::saveAsync(const QString& title, const QString& directory, const QString& nameFilter) { ensureReticleVisible(); QString path = directory; if (path.isEmpty()) { @@ -262,12 +336,37 @@ void WindowScriptingInterface::save(const QString& title, const QString& directo OffscreenUi::getSaveFileNameAsync(nullptr, title, path, nameFilter); } +/// Display a select asset dialog that lets the user select an asset from the Asset Server. If `directory` is an invalid +/// directory the browser will start at the root directory. +/// \param const QString& title title of the window +/// \param const QString& directory directory to start the asset browser at +/// \param const QString& nameFilter filter to filter asset names by - see `QFileDialog` +/// \return QScriptValue asset path as a string if one was selected, otherwise `QScriptValue::NullValue` +QScriptValue WindowScriptingInterface::browseAssets(const QString& title, const QString& directory, const QString& nameFilter) { + ensureReticleVisible(); + QString path = directory; + if (path.isEmpty()) { + path = getPreviousBrowseAssetLocation(); + } + if (path.left(1) != "/") { + path = "/" + path; + } + if (path.right(1) != "/") { + path = path + "/"; + } + QString result = OffscreenUi::getOpenAssetName(nullptr, title, path, nameFilter); + if (!result.isEmpty()) { + setPreviousBrowseAssetLocation(QFileInfo(result).absolutePath()); + } + return result.isEmpty() ? QScriptValue::NullValue : QScriptValue(result); +} + /// Display a select asset dialog that lets the user select an asset from the Asset Server. If `directory` is an invalid /// directory the browser will start at the root directory. /// \param const QString& title title of the window /// \param const QString& directory directory to start the asset browser at /// \param const QString& nameFilter filter to filter asset names by - see `QFileDialog` -void WindowScriptingInterface::browseAssets(const QString& title, const QString& directory, const QString& nameFilter) { +void WindowScriptingInterface::browseAssetsAsync(const QString& title, const QString& directory, const QString& nameFilter) { ensureReticleVisible(); QString path = directory; if (path.isEmpty()) { diff --git a/interface/src/scripting/WindowScriptingInterface.h b/interface/src/scripting/WindowScriptingInterface.h index 401f47bcdd..3304aed4ee 100644 --- a/interface/src/scripting/WindowScriptingInterface.h +++ b/interface/src/scripting/WindowScriptingInterface.h @@ -51,12 +51,17 @@ public slots: void raiseMainWindow(); void alert(const QString& message = ""); QScriptValue confirm(const QString& message = ""); - void prompt(const QString& message = "", const QString& defaultText = ""); + QScriptValue prompt(const QString& message, const QString& defaultText); + void promptAsync(const QString& message = "", const QString& defaultText = ""); CustomPromptResult customPrompt(const QVariant& config); - void browseDir(const QString& title = "", const QString& directory = ""); - void browse(const QString& title = "", const QString& directory = "", const QString& nameFilter = ""); - void save(const QString& title = "", const QString& directory = "", const QString& nameFilter = ""); - void browseAssets(const QString& title = "", const QString& directory = "", const QString& nameFilter = ""); + QScriptValue browseDir(const QString& title = "", const QString& directory = ""); + void browseDirAsync(const QString& title = "", const QString& directory = ""); + QScriptValue browse(const QString& title = "", const QString& directory = "", const QString& nameFilter = ""); + void browseAsync(const QString& title = "", const QString& directory = "", const QString& nameFilter = ""); + QScriptValue save(const QString& title = "", const QString& directory = "", const QString& nameFilter = ""); + void saveAsync(const QString& title = "", const QString& directory = "", const QString& nameFilter = ""); + QScriptValue browseAssets(const QString& title = "", const QString& directory = "", const QString& nameFilter = ""); + void browseAssetsAsync(const QString& title = "", const QString& directory = "", const QString& nameFilter = ""); void showAssetServer(const QString& upload = ""); void copyToClipboard(const QString& text); void takeSnapshot(bool notify = true, bool includeAnimated = false, float aspectRatio = 0.0f); diff --git a/scripts/system/edit.js b/scripts/system/edit.js index 1828146182..75510a31b3 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -432,7 +432,7 @@ var toolBar = (function () { addButton("importEntitiesButton", "assets-01.svg", function() { Window.openFileChanged.connect(onFileOpenChanged); - Window.browse("Select Model to Import", "", "*.json"); + Window.browseAsync("Select Model to Import", "", "*.json"); }); addButton("openAssetBrowserButton", "assets-01.svg", function() { @@ -1501,15 +1501,15 @@ function handeMenuEvent(menuItem) { Window.notifyEditError("No entities have been selected."); } else { Window.saveFileChanged.connect(onFileSaveChanged); - Window.save("Select Where to Save", "", "*.json"); + Window.saveAsync("Select Where to Save", "", "*.json"); } } else if (menuItem === "Import Entities" || menuItem === "Import Entities from URL") { if (menuItem === "Import Entities") { Window.openFileChanged.connect(onFileOpenChanged); - Window.browse("Select Model to Import", "", "*.json"); + Window.browseAsync("Select Model to Import", "", "*.json"); } else { Window.promptTextChanged.connect(onFileOpenChanged); - Window.prompt("URL of SVO to import", ""); + Window.promptAsync("URL of SVO to import", ""); } } else if (menuItem === "Entity List...") { entityListTool.toggleVisible(); diff --git a/scripts/system/libraries/entityList.js b/scripts/system/libraries/entityList.js index d2d815f9e3..9d9689000e 100644 --- a/scripts/system/libraries/entityList.js +++ b/scripts/system/libraries/entityList.js @@ -150,7 +150,7 @@ EntityListTool = function(opts) { Window.notifyEditError("No entities have been selected."); } else { Window.saveFileChanged.connect(onFileSaveChanged); - Window.save("Select Where to Save", "", "*.json"); + Window.saveAsync("Select Where to Save", "", "*.json"); } } else if (data.type == "pal") { var sessionIds = {}; // Collect the sessionsIds of all selected entitities, w/o duplicates. diff --git a/scripts/system/snapshot.js b/scripts/system/snapshot.js index 08614c2030..bf0ab69789 100644 --- a/scripts/system/snapshot.js +++ b/scripts/system/snapshot.js @@ -121,7 +121,7 @@ function onMessage(message) { break; case 'chooseSnapshotLocation': Window.browseDirChanged.connect(snapshotDirChanged); - Window.browseDir("Choose Snapshots Directory", "", ""); + Window.browseDirAsync("Choose Snapshots Directory", "", ""); break; case 'openSettings': if ((HMD.active && Settings.getValue("hmdTabletBecomesToolbar", false)) diff --git a/unpublishedScripts/marketplace/record/record.js b/unpublishedScripts/marketplace/record/record.js index 84f631f307..a3f9d6ca0d 100644 --- a/unpublishedScripts/marketplace/record/record.js +++ b/unpublishedScripts/marketplace/record/record.js @@ -530,7 +530,7 @@ case LOAD_RECORDING_ACTION: // User wants to select an ATP recording to play. Window.assetsDirChanged.connect(onAssetsDirChanged); - Window.browseAssets("Select Recording to Play", "recordings", "*.hfr"); + Window.browseAssetsAsync("Select Recording to Play", "recordings", "*.hfr"); break; case START_RECORDING_ACTION: // Start making a recording.