Merge pull request #10790 from davidkelly/dk/scriptsSwitch

Command line switch to override default scripts location
This commit is contained in:
David Kelly 2017-06-23 08:53:40 -07:00 committed by GitHub
commit 63279f4525
8 changed files with 83 additions and 49 deletions

View file

@ -903,6 +903,11 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
_saveAvatarOverrideUrl = true; _saveAvatarOverrideUrl = true;
} }
QString defaultScriptsLocation = getCmdOption(argc, constArgv, "--scripts");
if (!defaultScriptsLocation.isEmpty()) {
PathUtils::defaultScriptsLocation(defaultScriptsLocation);
}
_glWidget = new GLCanvas(); _glWidget = new GLCanvas();
getApplicationCompositor().setRenderingWidget(_glWidget); getApplicationCompositor().setRenderingWidget(_glWidget);
_window->setCentralWidget(_glWidget); _window->setCentralWidget(_glWidget);
@ -1167,7 +1172,15 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
// force the model the look at the correct directory (weird order of operations issue) // force the model the look at the correct directory (weird order of operations issue)
scriptEngines->setScriptsLocation(scriptEngines->getScriptsLocation()); scriptEngines->setScriptsLocation(scriptEngines->getScriptsLocation());
// do this as late as possible so that all required subsystems are initialized // do this as late as possible so that all required subsystems are initialized
scriptEngines->loadScripts(); // If we've overridden the default scripts location, just load default scripts
// otherwise, load 'em all
if (!defaultScriptsLocation.isEmpty()) {
scriptEngines->loadDefaultScripts();
scriptEngines->defaultScriptsLocationOverridden(true);
} else {
scriptEngines->loadScripts();
}
// Make sure we don't time out during slow operations at startup // Make sure we don't time out during slow operations at startup
updateHeartbeat(); updateHeartbeat();
@ -5855,7 +5868,7 @@ void Application::showDialog(const QUrl& widgetUrl, const QUrl& tabletUrl, const
void Application::showScriptLogs() { void Application::showScriptLogs() {
auto scriptEngines = DependencyManager::get<ScriptEngines>(); auto scriptEngines = DependencyManager::get<ScriptEngines>();
QUrl defaultScriptsLoc = defaultScriptsLocation(); QUrl defaultScriptsLoc = PathUtils::defaultScriptsLocation();
defaultScriptsLoc.setPath(defaultScriptsLoc.path() + "developer/debugging/debugWindow.js"); defaultScriptsLoc.setPath(defaultScriptsLoc.path() + "developer/debugging/debugWindow.js");
scriptEngines->loadScript(defaultScriptsLoc.toString()); scriptEngines->loadScript(defaultScriptsLoc.toString());
} }

View file

@ -303,7 +303,7 @@ Menu::Menu() {
// Settings > Avatar... // Settings > Avatar...
action = addActionToQMenuAndActionHash(settingsMenu, "Avatar..."); action = addActionToQMenuAndActionHash(settingsMenu, "Avatar...");
connect(action, &QAction::triggered, [] { connect(action, &QAction::triggered, [] {
qApp->showDialog(QString("hifi/dialogs/AvatarPreferencesDialog.qml"), qApp->showDialog(QString("hifi/dialogs/AvatarPreferencesDialog.qml"),
QString("../../hifi/tablet/TabletAvatarPreferences.qml"), "AvatarPreferencesDialog"); QString("../../hifi/tablet/TabletAvatarPreferences.qml"), "AvatarPreferencesDialog");
}); });
@ -629,7 +629,7 @@ Menu::Menu() {
action = addActionToQMenuAndActionHash(audioDebugMenu, "Stats..."); action = addActionToQMenuAndActionHash(audioDebugMenu, "Stats...");
connect(action, &QAction::triggered, [] { connect(action, &QAction::triggered, [] {
auto scriptEngines = DependencyManager::get<ScriptEngines>(); auto scriptEngines = DependencyManager::get<ScriptEngines>();
QUrl defaultScriptsLoc = defaultScriptsLocation(); QUrl defaultScriptsLoc = PathUtils::defaultScriptsLocation();
defaultScriptsLoc.setPath(defaultScriptsLoc.path() + "developer/utilities/audio/stats.js"); defaultScriptsLoc.setPath(defaultScriptsLoc.path() + "developer/utilities/audio/stats.js");
scriptEngines->loadScript(defaultScriptsLoc.toString()); scriptEngines->loadScript(defaultScriptsLoc.toString());
}); });

View file

@ -172,7 +172,7 @@ ScriptEngine::ScriptEngine(Context context, const QString& scriptContents, const
emit unhandledException(exception); emit unhandledException(exception);
} }
}, Qt::DirectConnection); }, Qt::DirectConnection);
setProcessEventsInterval(MSECS_PER_SECOND); setProcessEventsInterval(MSECS_PER_SECOND);
if (isEntityServerScript()) { if (isEntityServerScript()) {
qCDebug(scriptengine) << "isEntityServerScript() -- limiting maxRetries to 1"; qCDebug(scriptengine) << "isEntityServerScript() -- limiting maxRetries to 1";
@ -281,7 +281,7 @@ void ScriptEngine::runDebuggable() {
scriptDebugMenu = nullptr; scriptDebugMenu = nullptr;
} }
} }
disconnect(timer); disconnect(timer);
}); });
connect(timer, &QTimer::timeout, [this, timer] { connect(timer, &QTimer::timeout, [this, timer] {
@ -340,7 +340,7 @@ void ScriptEngine::runInThread() {
QThread* workerThread = new QThread(); QThread* workerThread = new QThread();
workerThread->setObjectName(QString("js:") + getFilename().replace("about:","")); workerThread->setObjectName(QString("js:") + getFilename().replace("about:",""));
moveToThread(workerThread); moveToThread(workerThread);
// NOTE: If you connect any essential signals for proper shutdown or cleanup of // NOTE: If you connect any essential signals for proper shutdown or cleanup of
// the script engine, make sure to add code to "reconnect" them to the // the script engine, make sure to add code to "reconnect" them to the
// disconnectNonEssentialSignals() method // disconnectNonEssentialSignals() method
@ -1047,26 +1047,26 @@ void ScriptEngine::run() {
auto beforeSleep = clock::now(); auto beforeSleep = clock::now();
// Throttle to SCRIPT_FPS // Throttle to SCRIPT_FPS
// We'd like to try to keep the script at a solid SCRIPT_FPS update rate. And so we will // We'd like to try to keep the script at a solid SCRIPT_FPS update rate. And so we will
// calculate a sleepUntil to be the time from our start time until the original target // calculate a sleepUntil to be the time from our start time until the original target
// sleepUntil for this frame. This approach will allow us to "catch up" in the event // sleepUntil for this frame. This approach will allow us to "catch up" in the event
// that some of our script udpates/frames take a little bit longer than the target average // that some of our script udpates/frames take a little bit longer than the target average
// to execute. // to execute.
// NOTE: if we go to variable SCRIPT_FPS, then we will need to reconsider this approach // NOTE: if we go to variable SCRIPT_FPS, then we will need to reconsider this approach
const std::chrono::microseconds TARGET_SCRIPT_FRAME_DURATION(USECS_PER_SECOND / SCRIPT_FPS + 1); const std::chrono::microseconds TARGET_SCRIPT_FRAME_DURATION(USECS_PER_SECOND / SCRIPT_FPS + 1);
clock::time_point targetSleepUntil(startTime + (thisFrame++ * TARGET_SCRIPT_FRAME_DURATION)); clock::time_point targetSleepUntil(startTime + (thisFrame++ * TARGET_SCRIPT_FRAME_DURATION));
// However, if our sleepUntil is not at least our average update and timer execution time // However, if our sleepUntil is not at least our average update and timer execution time
// into the future it means our script is taking too long in its updates, and we want to // into the future it means our script is taking too long in its updates, and we want to
// punish the script a little bit. So we will force the sleepUntil to be at least our // punish the script a little bit. So we will force the sleepUntil to be at least our
// averageUpdate + averageTimerPerFrame time into the future. // averageUpdate + averageTimerPerFrame time into the future.
auto averageUpdate = totalUpdates / thisFrame; auto averageUpdate = totalUpdates / thisFrame;
auto averageTimerPerFrame = _totalTimerExecution / thisFrame; auto averageTimerPerFrame = _totalTimerExecution / thisFrame;
auto averageTimerAndUpdate = averageUpdate + averageTimerPerFrame; auto averageTimerAndUpdate = averageUpdate + averageTimerPerFrame;
auto sleepUntil = std::max(targetSleepUntil, beforeSleep + averageTimerAndUpdate); auto sleepUntil = std::max(targetSleepUntil, beforeSleep + averageTimerAndUpdate);
// We don't want to actually sleep for too long, because it causes our scripts to hang // We don't want to actually sleep for too long, because it causes our scripts to hang
// on shutdown and stop... so we want to loop and sleep until we've spent our time in // on shutdown and stop... so we want to loop and sleep until we've spent our time in
// purgatory, constantly checking to see if our script was asked to end // purgatory, constantly checking to see if our script was asked to end
bool processedEvents = false; bool processedEvents = false;
while (!_isFinished && clock::now() < sleepUntil) { while (!_isFinished && clock::now() < sleepUntil) {
@ -1399,7 +1399,7 @@ QString ScriptEngine::_requireResolve(const QString& moduleId, const QString& re
if (!IS_THREADSAFE_INVOCATION(thread(), __FUNCTION__)) { if (!IS_THREADSAFE_INVOCATION(thread(), __FUNCTION__)) {
return QString(); return QString();
} }
QUrl defaultScriptsLoc = defaultScriptsLocation(); QUrl defaultScriptsLoc = PathUtils::defaultScriptsLocation();
QUrl url(moduleId); QUrl url(moduleId);
auto displayId = moduleId; auto displayId = moduleId;
@ -1465,7 +1465,7 @@ QString ScriptEngine::_requireResolve(const QString& moduleId, const QString& re
canonical.setPath(file.canonicalFilePath()); canonical.setPath(file.canonicalFilePath());
} }
bool disallowOutsideFiles = !defaultScriptsLocation().isParentOf(canonical) && !currentSandboxURL.isLocalFile(); bool disallowOutsideFiles = !PathUtils::defaultScriptsLocation().isParentOf(canonical) && !currentSandboxURL.isLocalFile();
if (disallowOutsideFiles && !PathUtils::isDescendantOf(canonical, currentSandboxURL)) { if (disallowOutsideFiles && !PathUtils::isDescendantOf(canonical, currentSandboxURL)) {
return throwResolveError(makeError(message.arg( return throwResolveError(makeError(message.arg(
QString("path '%1' outside of origin script '%2' '%3'") QString("path '%1' outside of origin script '%2' '%3'")
@ -1750,7 +1750,7 @@ void ScriptEngine::include(const QStringList& includeFiles, QScriptValue callbac
return; return;
} }
if (DependencyManager::get<ScriptEngines>()->isStopped()) { if (DependencyManager::get<ScriptEngines>()->isStopped()) {
scriptWarningMessage("Script.include() while shutting down is ignored... includeFiles:" scriptWarningMessage("Script.include() while shutting down is ignored... includeFiles:"
+ includeFiles.join(",") + "parent script:" + getFilename()); + includeFiles.join(",") + "parent script:" + getFilename());
return; // bail early return; // bail early
} }
@ -1762,7 +1762,7 @@ void ScriptEngine::include(const QStringList& includeFiles, QScriptValue callbac
bool isStandardLibrary = false; bool isStandardLibrary = false;
if (file.startsWith("/~/")) { if (file.startsWith("/~/")) {
thisURL = expandScriptUrl(QUrl::fromLocalFile(expandScriptPath(file))); thisURL = expandScriptUrl(QUrl::fromLocalFile(expandScriptPath(file)));
QUrl defaultScriptsLoc = defaultScriptsLocation(); QUrl defaultScriptsLoc = PathUtils::defaultScriptsLocation();
if (!defaultScriptsLoc.isParentOf(thisURL)) { if (!defaultScriptsLoc.isParentOf(thisURL)) {
scriptWarningMessage("Script.include() -- skipping" + file + "-- outside of standard libraries"); scriptWarningMessage("Script.include() -- skipping" + file + "-- outside of standard libraries");
continue; continue;
@ -1774,7 +1774,7 @@ void ScriptEngine::include(const QStringList& includeFiles, QScriptValue callbac
bool disallowOutsideFiles = thisURL.isLocalFile() && !isStandardLibrary && !currentSandboxURL.isLocalFile(); bool disallowOutsideFiles = thisURL.isLocalFile() && !isStandardLibrary && !currentSandboxURL.isLocalFile();
if (disallowOutsideFiles && !PathUtils::isDescendantOf(thisURL, currentSandboxURL)) { if (disallowOutsideFiles && !PathUtils::isDescendantOf(thisURL, currentSandboxURL)) {
scriptWarningMessage("Script.include() ignoring file path" + thisURL.toString() scriptWarningMessage("Script.include() ignoring file path" + thisURL.toString()
+ "outside of original entity script" + currentSandboxURL.toString()); + "outside of original entity script" + currentSandboxURL.toString());
} else { } else {
// We could also check here for CORS, but we don't yet. // We could also check here for CORS, but we don't yet.
@ -1844,7 +1844,7 @@ void ScriptEngine::include(const QStringList& includeFiles, QScriptValue callbac
void ScriptEngine::include(const QString& includeFile, QScriptValue callback) { void ScriptEngine::include(const QString& includeFile, QScriptValue callback) {
if (DependencyManager::get<ScriptEngines>()->isStopped()) { if (DependencyManager::get<ScriptEngines>()->isStopped()) {
scriptWarningMessage("Script.include() while shutting down is ignored... includeFile:" scriptWarningMessage("Script.include() while shutting down is ignored... includeFile:"
+ includeFile + "parent script:" + getFilename()); + includeFile + "parent script:" + getFilename());
return; // bail early return; // bail early
} }
@ -1862,12 +1862,12 @@ void ScriptEngine::load(const QString& loadFile) {
return; return;
} }
if (DependencyManager::get<ScriptEngines>()->isStopped()) { if (DependencyManager::get<ScriptEngines>()->isStopped()) {
scriptWarningMessage("Script.load() while shutting down is ignored... loadFile:" scriptWarningMessage("Script.load() while shutting down is ignored... loadFile:"
+ loadFile + "parent script:" + getFilename()); + loadFile + "parent script:" + getFilename());
return; // bail early return; // bail early
} }
if (!currentEntityIdentifier.isInvalidID()) { if (!currentEntityIdentifier.isInvalidID()) {
scriptWarningMessage("Script.load() from entity script is ignored... loadFile:" scriptWarningMessage("Script.load() from entity script is ignored... loadFile:"
+ loadFile + "parent script:" + getFilename() + "entity: " + currentEntityIdentifier.toString()); + loadFile + "parent script:" + getFilename() + "entity: " + currentEntityIdentifier.toString());
return; // bail early return; // bail early
} }
@ -2548,7 +2548,7 @@ void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QS
qCDebug(scriptengine) << "ScriptEngine::callEntityScriptMethod() called on correct thread [" << thread() << "] " qCDebug(scriptengine) << "ScriptEngine::callEntityScriptMethod() called on correct thread [" << thread() << "] "
"entityID:" << entityID << "methodName:" << methodName << "otherID:" << otherID << "collision: collision"; "entityID:" << entityID << "methodName:" << methodName << "otherID:" << otherID << "collision: collision";
#endif #endif
if (HIFI_AUTOREFRESH_FILE_SCRIPTS) { if (HIFI_AUTOREFRESH_FILE_SCRIPTS) {
refreshFileScript(entityID); refreshFileScript(entityID);
} }

View file

@ -74,7 +74,7 @@ ScriptEngines::ScriptEngines(ScriptEngine::Context context)
QUrl normalizeScriptURL(const QUrl& rawScriptURL) { QUrl normalizeScriptURL(const QUrl& rawScriptURL) {
if (rawScriptURL.scheme() == "file") { if (rawScriptURL.scheme() == "file") {
QUrl fullNormal = rawScriptURL; QUrl fullNormal = rawScriptURL;
QUrl defaultScriptLoc = defaultScriptsLocation(); QUrl defaultScriptLoc = PathUtils::defaultScriptsLocation();
// if this url is something "beneath" the default script url, replace the local path with ~ // if this url is something "beneath" the default script url, replace the local path with ~
if (fullNormal.scheme() == defaultScriptLoc.scheme() && if (fullNormal.scheme() == defaultScriptLoc.scheme() &&
@ -93,7 +93,7 @@ QUrl normalizeScriptURL(const QUrl& rawScriptURL) {
QString expandScriptPath(const QString& rawPath) { QString expandScriptPath(const QString& rawPath) {
QStringList splitPath = rawPath.split("/"); QStringList splitPath = rawPath.split("/");
QUrl defaultScriptsLoc = defaultScriptsLocation(); QUrl defaultScriptsLoc = PathUtils::defaultScriptsLocation();
return defaultScriptsLoc.path() + "/" + splitPath.mid(2).join("/"); // 2 to skip the slashes in /~/ return defaultScriptsLoc.path() + "/" + splitPath.mid(2).join("/"); // 2 to skip the slashes in /~/
} }
@ -112,7 +112,7 @@ QUrl expandScriptUrl(const QUrl& rawScriptURL) {
QFileInfo fileInfo(url.toLocalFile()); QFileInfo fileInfo(url.toLocalFile());
url = QUrl::fromLocalFile(fileInfo.canonicalFilePath()); url = QUrl::fromLocalFile(fileInfo.canonicalFilePath());
QUrl defaultScriptsLoc = defaultScriptsLocation(); QUrl defaultScriptsLoc = PathUtils::defaultScriptsLocation();
if (!defaultScriptsLoc.isParentOf(url)) { if (!defaultScriptsLoc.isParentOf(url)) {
qCWarning(scriptengine) << "Script.include() ignoring file path" << rawScriptURL qCWarning(scriptengine) << "Script.include() ignoring file path" << rawScriptURL
<< "-- outside of standard libraries: " << "-- outside of standard libraries: "
@ -327,6 +327,13 @@ void ScriptEngines::saveScripts() {
return; return;
} }
// don't save scripts if we started with --scripts, as we would overwrite
// the scripts that the user expects to be there when launched without the
// --scripts override.
if (_defaultScriptsLocationOverridden) {
return;
}
// Saves all currently running user-loaded scripts // Saves all currently running user-loaded scripts
QVariantList list; QVariantList list;
@ -541,11 +548,11 @@ void ScriptEngines::launchScriptEngine(ScriptEngine* scriptEngine) {
initializer(scriptEngine); initializer(scriptEngine);
} }
// FIXME disabling 'shift key' debugging for now. If you start up the application with // FIXME disabling 'shift key' debugging for now. If you start up the application with
// the shift key held down, it triggers a deadlock because of script interfaces running // the shift key held down, it triggers a deadlock because of script interfaces running
// on the main thread // on the main thread
auto const wantDebug = scriptEngine->isDebuggable(); // || (qApp->queryKeyboardModifiers() & Qt::ShiftModifier); auto const wantDebug = scriptEngine->isDebuggable(); // || (qApp->queryKeyboardModifiers() & Qt::ShiftModifier);
if (HIFI_SCRIPT_DEBUGGABLES && wantDebug) { if (HIFI_SCRIPT_DEBUGGABLES && wantDebug) {
scriptEngine->runDebuggable(); scriptEngine->runDebuggable();
} else { } else {
@ -581,5 +588,5 @@ void ScriptEngines::onScriptEngineError(const QString& scriptFilename) {
} }
QString ScriptEngines::getDefaultScriptsLocation() const { QString ScriptEngines::getDefaultScriptsLocation() const {
return defaultScriptsLocation().toString(); return PathUtils::defaultScriptsLocation().toString();
} }

View file

@ -66,6 +66,8 @@ public:
Q_PROPERTY(QString defaultScriptsPath READ getDefaultScriptsLocation) Q_PROPERTY(QString defaultScriptsPath READ getDefaultScriptsLocation)
void defaultScriptsLocationOverridden(bool overridden) { _defaultScriptsLocationOverridden = overridden; };
// Called at shutdown time // Called at shutdown time
void shutdownScripting(); void shutdownScripting();
bool isStopped() const { return _isStopped; } bool isStopped() const { return _isStopped; }
@ -113,6 +115,7 @@ protected:
ScriptsModelFilter _scriptsModelFilter; ScriptsModelFilter _scriptsModelFilter;
std::atomic<bool> _isStopped { false }; std::atomic<bool> _isStopped { false };
std::atomic<bool> _isReloading { false }; std::atomic<bool> _isReloading { false };
bool _defaultScriptsLocationOverridden { false };
}; };
QUrl normalizeScriptURL(const QUrl& rawScriptURL); QUrl normalizeScriptURL(const QUrl& rawScriptURL);

View file

@ -125,15 +125,15 @@ int ScriptsModel::columnCount(const QModelIndex& parent) const {
void ScriptsModel::updateScriptsLocation(const QString& newPath) { void ScriptsModel::updateScriptsLocation(const QString& newPath) {
_fsWatcher.removePath(_localDirectory.absolutePath()); _fsWatcher.removePath(_localDirectory.absolutePath());
if (!newPath.isEmpty()) { if (!newPath.isEmpty()) {
_localDirectory.setPath(newPath); _localDirectory.setPath(newPath);
if (!_localDirectory.absolutePath().isEmpty()) { if (!_localDirectory.absolutePath().isEmpty()) {
_fsWatcher.addPath(_localDirectory.absolutePath()); _fsWatcher.addPath(_localDirectory.absolutePath());
} }
} }
reloadLocalFiles(); reloadLocalFiles();
} }
@ -154,7 +154,7 @@ void ScriptsModel::reloadDefaultFiles() {
} }
void ScriptsModel::requestDefaultFiles(QString marker) { void ScriptsModel::requestDefaultFiles(QString marker) {
QUrl url(defaultScriptsLocation()); QUrl url(PathUtils::defaultScriptsLocation());
// targets that don't have a scripts folder in the appropriate location will have an empty URL here // targets that don't have a scripts folder in the appropriate location will have an empty URL here
if (!url.isEmpty()) { if (!url.isEmpty()) {
@ -244,7 +244,7 @@ bool ScriptsModel::parseXML(QByteArray xmlFile) {
lastKey = xml.text().toString(); lastKey = xml.text().toString();
if (jsRegex.exactMatch(xml.text().toString())) { if (jsRegex.exactMatch(xml.text().toString())) {
QString localPath = lastKey.split("/").mid(1).join("/"); QString localPath = lastKey.split("/").mid(1).join("/");
QUrl fullPath = defaultScriptsLocation(); QUrl fullPath = PathUtils::defaultScriptsLocation();
fullPath.setPath(fullPath.path() + lastKey); fullPath.setPath(fullPath.path() + lastKey);
const QString fullPathStr = normalizeScriptURL(fullPath).toString(); const QString fullPathStr = normalizeScriptURL(fullPath).toString();
_treeNodes.append(new TreeNodeScript(localPath, fullPathStr, SCRIPT_ORIGIN_DEFAULT)); _treeNodes.append(new TreeNodeScript(localPath, fullPathStr, SCRIPT_ORIGIN_DEFAULT));

View file

@ -71,21 +71,33 @@ QString findMostRecentFileExtension(const QString& originalFileName, QVector<QSt
return newestFileName; return newestFileName;
} }
QUrl defaultScriptsLocation() { QUrl PathUtils::defaultScriptsLocation(const QString& newDefaultPath) {
// return "http://s3.amazonaws.com/hifi-public"; static QString overriddenDefaultScriptsLocation = "";
#ifdef Q_OS_WIN QString path;
QString path = QCoreApplication::applicationDirPath() + "/scripts";
#elif defined(Q_OS_OSX)
QString path = QCoreApplication::applicationDirPath() + "/../Resources/scripts";
#else
QString path = QCoreApplication::applicationDirPath() + "/scripts";
#endif
// set overriddenDefaultScriptLocation if it was passed in
if (!newDefaultPath.isEmpty()) {
overriddenDefaultScriptsLocation = newDefaultPath;
}
// use the overridden location if it is set
if (!overriddenDefaultScriptsLocation.isEmpty()) {
path = overriddenDefaultScriptsLocation;
} else {
#ifdef Q_OS_WIN
path = QCoreApplication::applicationDirPath() + "/scripts";
#elif defined(Q_OS_OSX)
path = QCoreApplication::applicationDirPath() + "/../Resources/scripts";
#else
path = QCoreApplication::applicationDirPath() + "/scripts";
#endif
}
// turn the string into a legit QUrl
QFileInfo fileInfo(path); QFileInfo fileInfo(path);
return QUrl::fromLocalFile(fileInfo.canonicalFilePath()); return QUrl::fromLocalFile(fileInfo.canonicalFilePath());
} }
QString PathUtils::stripFilename(const QUrl& url) { QString PathUtils::stripFilename(const QUrl& url) {
// Guard against meaningless query and fragment parts. // Guard against meaningless query and fragment parts.
// Do NOT use PreferLocalFile as its behavior is unpredictable (e.g., on defaultScriptsLocation()) // Do NOT use PreferLocalFile as its behavior is unpredictable (e.g., on defaultScriptsLocation())

View file

@ -13,7 +13,6 @@
#define hifi_PathUtils_h #define hifi_PathUtils_h
#include <QtCore/QObject> #include <QtCore/QObject>
#include "DependencyManager.h" #include "DependencyManager.h"
/**jsdoc /**jsdoc
@ -38,11 +37,11 @@ public:
static QString stripFilename(const QUrl& url); static QString stripFilename(const QUrl& url);
// note: this is FS-case-sensitive version of parentURL.isParentOf(childURL) // note: this is FS-case-sensitive version of parentURL.isParentOf(childURL)
static bool isDescendantOf(const QUrl& childURL, const QUrl& parentURL); static bool isDescendantOf(const QUrl& childURL, const QUrl& parentURL);
static QUrl defaultScriptsLocation(const QString& newDefault = "");
}; };
QString fileNameWithoutExtension(const QString& fileName, const QVector<QString> possibleExtensions); QString fileNameWithoutExtension(const QString& fileName, const QVector<QString> possibleExtensions);
QString findMostRecentFileExtension(const QString& originalFileName, QVector<QString> possibleExtensions); QString findMostRecentFileExtension(const QString& originalFileName, QVector<QString> possibleExtensions);
QUrl defaultScriptsLocation();
#endif // hifi_PathUtils_h #endif // hifi_PathUtils_h