mirror of
https://github.com/lubosz/overte.git
synced 2025-04-23 01:04:06 +02:00
Add basic implementation of customPrompt
Still missing the warning and diabling of dynamic checkbox when the static mesh is selected.
This commit is contained in:
parent
6417bb1859
commit
71f62c02fc
7 changed files with 336 additions and 7 deletions
|
@ -35,7 +35,7 @@ FocusScope {
|
|||
}
|
||||
|
||||
onHeightChanged: d.handleSizeChanged();
|
||||
|
||||
|
||||
onWidthChanged: d.handleSizeChanged();
|
||||
|
||||
// Controls and windows can trigger this signal to ensure the desktop becomes visible
|
||||
|
@ -70,8 +70,8 @@ FocusScope {
|
|||
}
|
||||
var oldRecommendedRect = recommendedRect;
|
||||
var newRecommendedRectJS = (typeof Controller === "undefined") ? Qt.rect(0,0,0,0) : Controller.getRecommendedOverlayRect();
|
||||
var newRecommendedRect = Qt.rect(newRecommendedRectJS.x, newRecommendedRectJS.y,
|
||||
newRecommendedRectJS.width,
|
||||
var newRecommendedRect = Qt.rect(newRecommendedRectJS.x, newRecommendedRectJS.y,
|
||||
newRecommendedRectJS.width,
|
||||
newRecommendedRectJS.height);
|
||||
|
||||
var oldChildren = expectedChildren;
|
||||
|
@ -366,8 +366,8 @@ FocusScope {
|
|||
}
|
||||
|
||||
var newRecommendedRectJS = (typeof Controller === "undefined") ? Qt.rect(0,0,0,0) : Controller.getRecommendedOverlayRect();
|
||||
var newRecommendedRect = Qt.rect(newRecommendedRectJS.x, newRecommendedRectJS.y,
|
||||
newRecommendedRectJS.width,
|
||||
var newRecommendedRect = Qt.rect(newRecommendedRectJS.x, newRecommendedRectJS.y,
|
||||
newRecommendedRectJS.width,
|
||||
newRecommendedRectJS.height);
|
||||
var newRecommendedDimmensions = { x: newRecommendedRect.width, y: newRecommendedRect.height };
|
||||
var newX = newRecommendedRect.x + ((newRecommendedRect.width - targetWindow.width) / 2);
|
||||
|
@ -402,7 +402,7 @@ FocusScope {
|
|||
repositionWindow(targetWindow, false, oldRecommendedRect, oldRecommendedDimmensions, newRecommendedRect, newRecommendedDimmensions);
|
||||
}
|
||||
|
||||
function repositionWindow(targetWindow, forceReposition,
|
||||
function repositionWindow(targetWindow, forceReposition,
|
||||
oldRecommendedRect, oldRecommendedDimmensions, newRecommendedRect, newRecommendedDimmensions) {
|
||||
|
||||
if (desktop.width === 0 || desktop.height === 0) {
|
||||
|
@ -456,6 +456,11 @@ FocusScope {
|
|||
return inputDialogBuilder.createObject(desktop, properties);
|
||||
}
|
||||
|
||||
Component { id: customInputDialogBuilder; CustomQueryDialog { } }
|
||||
function customInputDialog(properties) {
|
||||
return customInputDialogBuilder.createObject(desktop, properties);
|
||||
}
|
||||
|
||||
Component { id: fileDialogBuilder; FileDialog { } }
|
||||
function fileDialog(properties) {
|
||||
return fileDialogBuilder.createObject(desktop, properties);
|
||||
|
@ -487,7 +492,7 @@ FocusScope {
|
|||
}
|
||||
|
||||
function unfocusWindows() {
|
||||
// First find the active focus item, and unfocus it, all the way
|
||||
// First find the active focus item, and unfocus it, all the way
|
||||
// up the parent chain to the window
|
||||
var currentFocus = offscreenWindow.activeFocusItem;
|
||||
var targetWindow = d.getDesktopWindow(currentFocus);
|
||||
|
|
237
interface/resources/qml/dialogs/CustomQueryDialog.qml
Normal file
237
interface/resources/qml/dialogs/CustomQueryDialog.qml
Normal file
|
@ -0,0 +1,237 @@
|
|||
//
|
||||
// CustomQueryDialog.qml
|
||||
//
|
||||
// Created by Zander Otavka on 7/14/16
|
||||
// Copyright 2016 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 QtQuick.Dialogs 1.2 as OriginalDialogs;
|
||||
|
||||
import "../controls-uit";
|
||||
import "../styles-uit";
|
||||
import "../windows";
|
||||
|
||||
ModalWindow {
|
||||
id: root;
|
||||
HifiConstants { id: hifi; }
|
||||
implicitWidth: 640;
|
||||
implicitHeight: 320;
|
||||
visible: true;
|
||||
|
||||
signal selected(var result);
|
||||
signal canceled();
|
||||
|
||||
property int icon: hifi.icons.none;
|
||||
property string iconText: "";
|
||||
property int iconSize: 35;
|
||||
onIconChanged: updateIcon();
|
||||
|
||||
property var textInput;
|
||||
property var comboBox;
|
||||
property var checkBox;
|
||||
|
||||
property var result;
|
||||
property alias current: textField.text;
|
||||
|
||||
// For text boxes
|
||||
property alias placeholderText: textField.placeholderText;
|
||||
|
||||
// For combo boxes
|
||||
property bool editable: true;
|
||||
|
||||
property int titleWidth: 0;
|
||||
onTitleWidthChanged: d.resize();
|
||||
|
||||
function updateIcon() {
|
||||
if (!root) {
|
||||
return;
|
||||
}
|
||||
iconText = hifi.glyphForIcon(root.icon);
|
||||
}
|
||||
|
||||
Item {
|
||||
clip: true;
|
||||
width: pane.width;
|
||||
height: pane.height;
|
||||
anchors.margins: 0;
|
||||
|
||||
QtObject {
|
||||
id: d;
|
||||
readonly property int minWidth: 480;
|
||||
readonly property int maxWdith: 1280;
|
||||
readonly property int minHeight: 120;
|
||||
readonly property int maxHeight: 720;
|
||||
|
||||
function resize() {
|
||||
var targetWidth = Math.max(titleWidth, pane.width);
|
||||
var targetHeight = (textInput ? textField.controlHeight : 0) + extraInputs.height +
|
||||
(6 * hifi.dimensions.contentSpacing.y) + buttons.height;
|
||||
// var targetHeight = 720;
|
||||
print("CQD extraInputs.height = " + extraInputs.height);
|
||||
print("CQD textField.controlHeight = " + textField.controlHeight);
|
||||
print("CQD buttons.height = " + buttons.height);
|
||||
print("CQD targetHeight = " + targetHeight);
|
||||
root.width = (targetWidth < d.minWidth) ? d.minWidth : ((targetWidth > d.maxWdith) ? d.maxWidth : targetWidth);
|
||||
root.height = (targetHeight < d.minHeight) ? d.minHeight: ((targetHeight > d.maxHeight) ?
|
||||
d.maxHeight : targetHeight);
|
||||
print("CQD comboBoxField.visible = " + comboBoxField.visible);
|
||||
if (comboBoxField.visible) {
|
||||
print("CQD parent = " + parent);
|
||||
comboBoxField.width = extraInputs.width / 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
anchors {
|
||||
top: parent.top;
|
||||
bottom: extraInputs.top;
|
||||
left: parent.left;
|
||||
right: parent.right;
|
||||
margins: 0;
|
||||
bottomMargin: 2 * hifi.dimensions.contentSpacing.y;
|
||||
}
|
||||
|
||||
// FIXME make a text field type that can be bound to a history for autocompletion
|
||||
TextField {
|
||||
id: textField;
|
||||
label: root.textInput.label;
|
||||
focus: root.textInput ? true : false;
|
||||
visible: root.textInput ? true : false;
|
||||
anchors {
|
||||
left: parent.left;
|
||||
right: parent.right;
|
||||
bottom: parent.bottom;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
id: extraInputs;
|
||||
spacing: hifi.dimensions.contentSpacing.x;
|
||||
anchors {
|
||||
left: parent.left;
|
||||
right: parent.right;
|
||||
bottom: buttons.top;
|
||||
bottomMargin: hifi.dimensions.contentSpacing.y;
|
||||
}
|
||||
height: comboBoxField.controlHeight;
|
||||
onHeightChanged: d.resize();
|
||||
onWidthChanged: d.resize();
|
||||
|
||||
CheckBox {
|
||||
id: checkBoxField;
|
||||
text: root.checkBox.label;
|
||||
focus: root.checkBox ? true : false;
|
||||
visible: root.checkBox ? true : false;
|
||||
anchors {
|
||||
left: parent.left;
|
||||
bottom: parent.bottom;
|
||||
}
|
||||
}
|
||||
|
||||
ComboBox {
|
||||
id: comboBoxField;
|
||||
label: root.comboBox.label;
|
||||
focus: root.comboBox ? true : false;
|
||||
visible: root.comboBox ? true : false;
|
||||
anchors {
|
||||
right: parent.right;
|
||||
bottom: parent.bottom;
|
||||
}
|
||||
model: root.comboBox ? root.comboBox.items : [];
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
id: buttons;
|
||||
focus: true;
|
||||
spacing: hifi.dimensions.contentSpacing.x;
|
||||
onHeightChanged: d.resize();
|
||||
onWidthChanged: d.resize();
|
||||
anchors {
|
||||
bottom: parent.bottom;
|
||||
left: parent.left;
|
||||
right: parent.right;
|
||||
bottomMargin: hifi.dimensions.contentSpacing.y;
|
||||
}
|
||||
|
||||
Button {
|
||||
id: acceptButton;
|
||||
action: acceptAction;
|
||||
// anchors {
|
||||
// bottom: parent.bottom;
|
||||
// right: cancelButton.left;
|
||||
// leftMargin: hifi.dimensions.contentSpacing.x;
|
||||
// }
|
||||
}
|
||||
|
||||
Button {
|
||||
id: cancelButton;
|
||||
action: cancelAction;
|
||||
// anchors {
|
||||
// bottom: parent.bottom;
|
||||
// right: parent.right;
|
||||
// leftMargin: hifi.dimensions.contentSpacing.x;
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
Action {
|
||||
id: cancelAction;
|
||||
text: qsTr("Cancel");
|
||||
shortcut: Qt.Key_Escape;
|
||||
onTriggered: {
|
||||
root.result = null;
|
||||
root.canceled();
|
||||
root.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
Action {
|
||||
id: acceptAction;
|
||||
text: qsTr("Add");
|
||||
shortcut: Qt.Key_Return;
|
||||
onTriggered: {
|
||||
root.result = {
|
||||
textInput: textField.text,
|
||||
comboBox: comboBoxField.currentText,
|
||||
checkBox: checkBoxField.checked
|
||||
};
|
||||
root.selected(root.result);
|
||||
root.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Keys.onPressed: {
|
||||
if (!visible) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (event.key) {
|
||||
case Qt.Key_Escape:
|
||||
case Qt.Key_Back:
|
||||
cancelAction.trigger();
|
||||
event.accepted = true;
|
||||
break;
|
||||
|
||||
case Qt.Key_Return:
|
||||
case Qt.Key_Enter:
|
||||
acceptAction.trigger();
|
||||
event.accepted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
updateIcon();
|
||||
d.resize();
|
||||
textField.forceActiveFocus();
|
||||
}
|
||||
}
|
|
@ -4710,6 +4710,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri
|
|||
scriptEngine->registerGlobalObject("Toolbars", DependencyManager::get<ToolbarScriptingInterface>().data());
|
||||
|
||||
scriptEngine->registerGlobalObject("Window", DependencyManager::get<WindowScriptingInterface>().data());
|
||||
qScriptRegisterMetaType(scriptEngine, CustomPromptResultToScriptValue, CustomPromptResultFromScriptValue);
|
||||
scriptEngine->registerGetterSetter("location", LocationScriptingInterface::locationGetter,
|
||||
LocationScriptingInterface::locationSetter, "Window");
|
||||
// register `location` on the global object.
|
||||
|
|
|
@ -29,6 +29,20 @@ static const QString DESKTOP_LOCATION = QStandardPaths::writableLocation(QStanda
|
|||
static const QString LAST_BROWSE_LOCATION_SETTING = "LastBrowseLocation";
|
||||
|
||||
|
||||
QScriptValue CustomPromptResultToScriptValue(QScriptEngine* engine, const CustomPromptResult& result) {
|
||||
if (!result.value.isValid()) {
|
||||
return QScriptValue::UndefinedValue;
|
||||
}
|
||||
|
||||
Q_ASSERT(result.value.userType() == qMetaTypeId<QVariantMap>());
|
||||
return engine->toScriptValue(result.value.toMap());
|
||||
}
|
||||
|
||||
void CustomPromptResultFromScriptValue(const QScriptValue& object, CustomPromptResult& result) {
|
||||
result.value = object.toVariant();
|
||||
}
|
||||
|
||||
|
||||
WindowScriptingInterface::WindowScriptingInterface() {
|
||||
const DomainHandler& domainHandler = DependencyManager::get<NodeList>()->getDomainHandler();
|
||||
connect(&domainHandler, &DomainHandler::connectedToDomain, this, &WindowScriptingInterface::domainChanged);
|
||||
|
@ -95,6 +109,14 @@ QScriptValue WindowScriptingInterface::prompt(const QString& message, const QStr
|
|||
return ok ? QScriptValue(result) : QScriptValue::NullValue;
|
||||
}
|
||||
|
||||
CustomPromptResult WindowScriptingInterface::customPrompt(const QVariant& config) {
|
||||
CustomPromptResult result;
|
||||
bool ok = false;
|
||||
auto configMap = config.toMap();
|
||||
result.value = OffscreenUi::getCustomInfo(OffscreenUi::ICON_NONE, "", configMap, &ok);
|
||||
return ok ? result : CustomPromptResult();
|
||||
}
|
||||
|
||||
QString fixupPathForMac(const QString& directory) {
|
||||
// On OS X `directory` does not work as expected unless a file is included in the path, so we append a bogus
|
||||
// filename if the directory is valid.
|
||||
|
|
|
@ -18,6 +18,18 @@
|
|||
|
||||
class WebWindowClass;
|
||||
|
||||
|
||||
class CustomPromptResult {
|
||||
public:
|
||||
QVariant value;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(CustomPromptResult);
|
||||
|
||||
QScriptValue CustomPromptResultToScriptValue(QScriptEngine* engine, const CustomPromptResult& result);
|
||||
void CustomPromptResultFromScriptValue(const QScriptValue& object, CustomPromptResult& result);
|
||||
|
||||
|
||||
class WindowScriptingInterface : public QObject, public Dependency {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int innerWidth READ getInnerWidth)
|
||||
|
@ -38,6 +50,7 @@ public slots:
|
|||
void alert(const QString& message = "");
|
||||
QScriptValue confirm(const QString& message = "");
|
||||
QScriptValue prompt(const QString& message = "", const QString& defaultText = "");
|
||||
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 = "");
|
||||
void copyToClipboard(const QString& text);
|
||||
|
|
|
@ -343,6 +343,23 @@ QString OffscreenUi::getItem(const Icon icon, const QString& title, const QStrin
|
|||
return result.toString();
|
||||
}
|
||||
|
||||
QVariant OffscreenUi::getCustomInfo(const Icon icon, const QString& title, const QVariantMap& config, bool* ok) {
|
||||
if (ok) {
|
||||
*ok = false;
|
||||
}
|
||||
|
||||
QVariant result = DependencyManager::get<OffscreenUi>()->customInputDialog(icon, title, config);
|
||||
if (ok && result.isValid()) {
|
||||
*ok = true;
|
||||
}
|
||||
|
||||
// Casts from QJSValue to QVariantMap (not sure how, just copied from http://lists.qt-project.org/pipermail/development/2014-September/018513.html)
|
||||
Q_ASSERT(result.userType() == qMetaTypeId<QJSValue>());
|
||||
result = qvariant_cast<QJSValue>(result).toVariant();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
QVariant OffscreenUi::inputDialog(const Icon icon, const QString& title, const QString& label, const QVariant& current) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QVariant result;
|
||||
|
@ -358,6 +375,20 @@ QVariant OffscreenUi::inputDialog(const Icon icon, const QString& title, const Q
|
|||
return waitForInputDialogResult(createInputDialog(icon, title, label, current));
|
||||
}
|
||||
|
||||
QVariant OffscreenUi::customInputDialog(const Icon icon, const QString& title, const QVariantMap& config) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QVariant result;
|
||||
QMetaObject::invokeMethod(this, "customInputDialog", Qt::BlockingQueuedConnection,
|
||||
Q_RETURN_ARG(QVariant, result),
|
||||
Q_ARG(Icon, icon),
|
||||
Q_ARG(QString, title),
|
||||
Q_ARG(QVariantMap, config));
|
||||
return result;
|
||||
}
|
||||
|
||||
return waitForInputDialogResult(createCustomInputDialog(icon, title, config));
|
||||
}
|
||||
|
||||
void OffscreenUi::togglePinned() {
|
||||
bool invokeResult = QMetaObject::invokeMethod(_desktop, "togglePinned");
|
||||
if (!invokeResult) {
|
||||
|
@ -401,6 +432,23 @@ QQuickItem* OffscreenUi::createInputDialog(const Icon icon, const QString& title
|
|||
return qvariant_cast<QQuickItem*>(result);
|
||||
}
|
||||
|
||||
QQuickItem* OffscreenUi::createCustomInputDialog(const Icon icon, const QString& title, const QVariantMap& config) {
|
||||
QVariantMap map = config;
|
||||
map.insert("title", title);
|
||||
map.insert("icon", icon);
|
||||
QVariant result;
|
||||
bool invokeResult = QMetaObject::invokeMethod(_desktop, "customInputDialog",
|
||||
Q_RETURN_ARG(QVariant, result),
|
||||
Q_ARG(QVariant, QVariant::fromValue(map)));
|
||||
|
||||
if (!invokeResult) {
|
||||
qWarning() << "Failed to create custom message box";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return qvariant_cast<QQuickItem*>(result);
|
||||
}
|
||||
|
||||
QVariant OffscreenUi::waitForInputDialogResult(QQuickItem* inputDialog) {
|
||||
if (!inputDialog) {
|
||||
return QVariant();
|
||||
|
|
|
@ -122,7 +122,9 @@ public:
|
|||
static QString getSaveFileName(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);
|
||||
QQuickItem* createCustomInputDialog(const Icon icon, const QString& title, const QVariantMap& config);
|
||||
QVariant waitForInputDialogResult(QQuickItem* inputDialog);
|
||||
|
||||
// Compatibility with QInputDialog::getText
|
||||
|
@ -140,6 +142,7 @@ public:
|
|||
|
||||
static QString getText(const Icon icon, const QString & title, const QString & label, const QString & text = QString(), bool * ok = 0);
|
||||
static QString getItem(const Icon icon, const QString & title, const QString & label, const QStringList & items, int current = 0, bool editable = true, bool * ok = 0);
|
||||
static QVariant getCustomInfo(const Icon icon, const QString& title, const QVariantMap& config, bool* ok = 0);
|
||||
|
||||
unsigned int getMenuUserDataId() const;
|
||||
|
||||
|
|
Loading…
Reference in a new issue