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:
Zander Otavka 2016-07-15 11:20:26 -07:00
parent 6417bb1859
commit 71f62c02fc
7 changed files with 336 additions and 7 deletions

View file

@ -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);

View 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();
}
}

View file

@ -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.

View file

@ -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.

View file

@ -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);

View file

@ -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();

View file

@ -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;