Stub desktop dialog to select recording to play from ATP assets

This commit is contained in:
David Rowe 2017-04-18 11:43:42 +12:00
parent f920192244
commit dae6d6fb69
9 changed files with 291 additions and 2 deletions

View file

@ -466,6 +466,11 @@ FocusScope {
return fileDialogBuilder.createObject(desktop, properties);
}
Component { id: assetDialogBuilder; AssetDialog { } }
function assetDialog(properties) {
return assetDialogBuilder.createObject(desktop, properties);
}
function unfocusWindows() {
// First find the active focus item, and unfocus it, all the way
// up the parent chain to the window

View file

@ -0,0 +1,137 @@
//
// AssetDialog.qml
//
// Created by David Rowe on 18 Apr 2017
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import QtQuick 2.5
import QtQuick.Controls 1.4
import Qt.labs.settings 1.0
import "../controls-uit"
import "../styles-uit"
import "../windows"
ModalWindow {
id: root
resizable: true
implicitWidth: 480
implicitHeight: 360 + (fileDialogItem.keyboardEnabled && fileDialogItem.keyboardRaised ? keyboard.raisedHeight + hifi.dimensions.contentSpacing.y : 0)
minSize: Qt.vector2d(360, 240)
draggable: true
HifiConstants { id: hifi }
Settings {
category: "FileDialog"
property alias width: root.width
property alias height: root.height
property alias x: root.x
property alias y: root.y
}
// Set from OffscreenUi::assetDialog()
//property alias caption: root.title;
property string caption
//property alias dir: fileTableModel.folder;
property string dir
//property alias filter: selectionType.filtersString;
property string filter
property int options // Unused
// TODO: Other properties
signal selectedAsset(var asset);
signal canceled();
Component.onCompleted: {
// TODO: Required?
}
Item {
id: assetDialogItem
clip: true
width: pane.width
height: pane.height
anchors.margins: 0
Action {
id: okAction
// TODO
/*
text: currentSelection.text ? (root.selectDirectory && fileTableView.currentRow === -1 ? "Choose" : (root.saveDialog ? "Save" : "Open")) : "Open"
enabled: currentSelection.text || !root.selectDirectory && d.currentSelectionIsFolder ? true : false
onTriggered: {
if (!root.selectDirectory && !d.currentSelectionIsFolder
|| root.selectDirectory && fileTableView.currentRow === -1) {
okActionTimer.start();
} else {
fileTableView.navigateToCurrentRow();
}
}
*/
text: "Choose"
onTriggered: {
selectedAsset("/recordings/20170417-233012.hfr");
root.destroy(); // TODO: root.shown = false?
}
}
Action {
id: cancelAction
text: "Cancel"
onTriggered: {
canceled();
root.shown = false;
}
}
Row {
id: buttonRow
anchors {
right: parent.right
bottom: parent.bottom
}
spacing: hifi.dimensions.contentSpacing.y
Button {
id: openButton
color: hifi.buttons.blue
action: okAction
Keys.onReturnPressed: okAction.trigger()
KeyNavigation.up: selectionType
KeyNavigation.left: selectionType
KeyNavigation.right: cancelButton
}
Button {
id: cancelButton
action: cancelAction
KeyNavigation.up: selectionType
KeyNavigation.left: openButton
KeyNavigation.right: fileTableView.contentItem
Keys.onReturnPressed: { canceled(); root.enabled = false }
}
}
}
Keys.onPressed: {
switch (event.key) {
case Qt.Key_Backspace:
event.accepted = d.navigateUp();
break;
case Qt.Key_Home:
event.accepted = d.navigateHome();
break;
}
}
}

View file

@ -0,0 +1,16 @@
//
// TabletAssetDialog.qml
//
// Created by David Rowe on 18 Apr 2017
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import QtQuick 2.5
import QtQuick.Controls 1.4
AssetDialog {
}

View file

@ -44,6 +44,12 @@ Item {
return openModal;
}
Component { id: assetDialogBuilder; TabletAssetDialog { } }
function assetDialog(properties) {
openModal = assetDialogBuilder.createObject(tabletRoot, properties);
return openModal;
}
function setMenuProperties(rootMenu, subMenu) {
tabletRoot.rootMenu = rootMenu;
tabletRoot.subMenu = subMenu;

View file

@ -28,6 +28,7 @@
static const QString DESKTOP_LOCATION = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
static const QString LAST_BROWSE_LOCATION_SETTING = "LastBrowseLocation";
static const QString LAST_BROWSE_ASSETS_LOCATION_SETTING = "LastBrowseAssetsLocation";
QScriptValue CustomPromptResultToScriptValue(QScriptEngine* engine, const CustomPromptResult& result) {
@ -149,6 +150,15 @@ void WindowScriptingInterface::setPreviousBrowseLocation(const QString& location
Setting::Handle<QVariant>(LAST_BROWSE_LOCATION_SETTING).set(location);
}
QString WindowScriptingInterface::getPreviousBrowseAssetLocation() const {
QString ASSETS_ROOT_PATH = "/";
return Setting::Handle<QString>(LAST_BROWSE_ASSETS_LOCATION_SETTING, ASSETS_ROOT_PATH).get();
}
void WindowScriptingInterface::setPreviousBrowseAssetLocation(const QString& location) {
Setting::Handle<QVariant>(LAST_BROWSE_ASSETS_LOCATION_SETTING).set(location);
}
/// Makes sure that the reticle is visible, use this in blocking forms that require a reticle and
/// might be in same thread as a script that sets the reticle to invisible
void WindowScriptingInterface::ensureReticleVisible() const {
@ -202,6 +212,25 @@ QScriptValue WindowScriptingInterface::save(const QString& title, const QString&
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`
/// \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();
}
QString result = OffscreenUi::getOpenAssetName(nullptr, title, path, nameFilter);
if (!result.isEmpty()) {
setPreviousBrowseAssetLocation(QFileInfo(result).absolutePath());
}
return result.isEmpty() ? QScriptValue::NullValue : QScriptValue(result);
}
void WindowScriptingInterface::showAssetServer(const QString& upload) {
QMetaObject::invokeMethod(qApp, "showAssetServerWidget", Qt::QueuedConnection, Q_ARG(QString, upload));
}

View file

@ -53,6 +53,7 @@ public slots:
CustomPromptResult customPrompt(const QVariant& config);
QScriptValue browse(const QString& title = "", const QString& directory = "", const QString& nameFilter = "");
QScriptValue save(const QString& title = "", const QString& directory = "", const QString& nameFilter = "");
QScriptValue browseAssets(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);
@ -88,6 +89,9 @@ private:
QString getPreviousBrowseLocation() const;
void setPreviousBrowseLocation(const QString& location);
QString getPreviousBrowseAssetLocation() const;
void setPreviousBrowseAssetLocation(const QString& location);
void ensureReticleVisible() const;
int createMessageBox(QString title, QString text, int buttons, int defaultButton);

View file

@ -713,6 +713,86 @@ QString OffscreenUi::getExistingDirectory(void* ignored, const QString &caption,
return DependencyManager::get<OffscreenUi>()->existingDirectoryDialog(caption, dir, filter, selectedFilter, options);
}
class AssetDialogListener : public ModalDialogListener {
// ATP equivalent of FileDialogListener.
Q_OBJECT
friend class OffscreenUi;
AssetDialogListener(QQuickItem* messageBox) : ModalDialogListener(messageBox) {
if (_finished) {
return;
}
connect(_dialog, SIGNAL(selectedAsset(QVariant)), this, SLOT(onSelectedAsset(QVariant)));
}
private slots:
void onSelectedAsset(QVariant asset) {
_result = asset;
_finished = true;
disconnect(_dialog);
}
};
QString OffscreenUi::assetDialog(const QVariantMap& properties) {
// ATP equivalent of fileDialog().
QVariant buildDialogResult;
bool invokeResult;
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
TabletProxy* tablet = dynamic_cast<TabletProxy*>(tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system"));
if (tablet->getToolbarMode()) {
invokeResult = QMetaObject::invokeMethod(_desktop, "assetDialog",
Q_RETURN_ARG(QVariant, buildDialogResult),
Q_ARG(QVariant, QVariant::fromValue(properties)));
} else {
QQuickItem* tabletRoot = tablet->getTabletRoot();
invokeResult = QMetaObject::invokeMethod(tabletRoot, "assetDialog",
Q_RETURN_ARG(QVariant, buildDialogResult),
Q_ARG(QVariant, QVariant::fromValue(properties)));
emit tabletScriptingInterface->tabletNotification();
}
if (!invokeResult) {
qWarning() << "Failed to create asset open dialog";
return QString();
}
QVariant result = AssetDialogListener(qvariant_cast<QQuickItem*>(buildDialogResult)).waitForResult();
if (!result.isValid()) {
return QString();
}
qCDebug(uiLogging) << result.toString();
return result.toUrl().toString();
}
QString OffscreenUi::assetOpenDialog(const QString& caption, const QString& dir, const QString& filter, QString* selectedFilter, QFileDialog::Options options) {
// ATP equivalent of fileOpenDialog().
if (QThread::currentThread() != thread()) {
QString result;
QMetaObject::invokeMethod(this, "assetOpenDialog", Qt::BlockingQueuedConnection,
Q_RETURN_ARG(QString, result),
Q_ARG(QString, caption),
Q_ARG(QString, dir),
Q_ARG(QString, filter),
Q_ARG(QString*, selectedFilter),
Q_ARG(QFileDialog::Options, options));
return result;
}
// FIXME support returning the selected filter... somehow?
QVariantMap map;
map.insert("caption", caption);
map.insert("dir", QUrl::fromLocalFile(dir));
map.insert("filter", filter);
map.insert("options", static_cast<int>(options));
return assetDialog(map);
}
QString OffscreenUi::getOpenAssetName(void* ignored, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options) {
// ATP equivalent of getOpenFileName().
return DependencyManager::get<OffscreenUi>()->assetOpenDialog(caption, dir, filter, selectedFilter, options);
}
bool OffscreenUi::eventFilter(QObject* originalDestination, QEvent* event) {
if (!filterEnabled(originalDestination, event)) {
return false;

View file

@ -118,6 +118,8 @@ public:
Q_INVOKABLE QString fileSaveDialog(const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = 0, QFileDialog::Options options = 0);
Q_INVOKABLE QString existingDirectoryDialog(const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = 0, QFileDialog::Options options = 0);
Q_INVOKABLE QString assetOpenDialog(const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = 0, QFileDialog::Options options = 0);
// Compatibility with QFileDialog::getOpenFileName
static QString getOpenFileName(void* ignored, const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = 0, QFileDialog::Options options = 0);
// Compatibility with QFileDialog::getSaveFileName
@ -125,6 +127,8 @@ public:
// Compatibility with QFileDialog::getExistingDirectory
static QString getExistingDirectory(void* ignored, const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = 0, QFileDialog::Options options = 0);
static QString getOpenAssetName(void* ignored, const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = 0, QFileDialog::Options options = 0);
Q_INVOKABLE QVariant inputDialog(const Icon icon, const QString& title, const QString& label = QString(), const QVariant& current = QVariant());
Q_INVOKABLE QVariant customInputDialog(const Icon icon, const QString& title, const QVariantMap& config);
QQuickItem* createInputDialog(const Icon icon, const QString& title, const QString& label, const QVariant& current);
@ -155,6 +159,7 @@ signals:
private:
QString fileDialog(const QVariantMap& properties);
QString assetDialog(const QVariantMap& properties);
QQuickItem* _desktop { nullptr };
QQuickItem* _toolWindow { nullptr };

View file

@ -458,7 +458,10 @@
}
function onWebEventReceived(data) {
var message = JSON.parse(data);
var message,
recording;
message = JSON.parse(data);
if (message.type === EVENT_BRIDGE_TYPE) {
switch (message.action) {
case BODY_LOADED_ACTION:
@ -486,7 +489,11 @@
break;
case LOAD_RECORDING_ACTION:
// User wants to select an ATP recording to play.
log("TODO: Open dialog for user to select ATP recording to play");
recording = Window.browseAssets("Select Recording to Play", "recordings", "*.hrf");
if (recording) {
log("Load recording " + recording);
Player.playRecording("atp:" + recording, MyAvatar.position, MyAvatar.orientation);
}
break;
case START_RECORDING_ACTION:
// Start making a recording.