673 lines · 26.7 KB · C++
RawDownload
////  WindowScriptingInterface.cpp//  interface/src/scripting////  Created by Ryan Huffman on 4/29/14.//  Copyright 2014 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// #include <QDir>#include <QDialogButtonBox>#include <QFileDialog>#include <QInputDialog>#include <QMessageBox>#include <QScriptValue>#include <QScrollArea> #include "Application.h"#include "DomainHandler.h"#include "MainWindow.h"#include "Menu.h"#include "ui/ModelsBrowser.h" #include "WindowScriptingInterface.h" WindowScriptingInterface::WindowScriptingInterface() :    _editDialog(NULL),    _nonBlockingFormActive(false),    _formResult(QDialog::Rejected) {    const DomainHandler& domainHandler = DependencyManager::get<NodeList>()->getDomainHandler();    connect(&domainHandler, &DomainHandler::hostnameChanged, this, &WindowScriptingInterface::domainChanged);    connect(Application::getInstance(), &Application::svoImportRequested, this, &WindowScriptingInterface::svoImportRequested);    connect(Application::getInstance(), &Application::domainConnectionRefused, this, &WindowScriptingInterface::domainConnectionRefused);} WebWindowClass* WindowScriptingInterface::doCreateWebWindow(const QString& title, const QString& url, int width, int height, bool isToolWindow) {    return new WebWindowClass(title, url, width, height, isToolWindow);} QScriptValue WindowScriptingInterface::hasFocus() {    return Application::getInstance()->hasFocus();} void WindowScriptingInterface::setFocus() {    // It's forbidden to call focus() from another thread.    Application::getInstance()->postLambdaEvent([] {        auto window = Application::getInstance()->getWindow();        window->activateWindow();        window->setFocus();    });} void WindowScriptingInterface::raiseMainWindow() {    // It's forbidden to call raise() from another thread.    Application::getInstance()->postLambdaEvent([] {        Application::getInstance()->getWindow()->raise();    });} void WindowScriptingInterface::setCursorVisible(bool visible) {    QMetaObject::invokeMethod(Application::getInstance(), "setCursorVisible", Qt::BlockingQueuedConnection,                              Q_ARG(bool, visible));} bool WindowScriptingInterface::isCursorVisible() const {    return !Application::getInstance()->isMouseHidden();} void WindowScriptingInterface::setCursorPosition(int x, int y) {    QCursor::setPos(x, y);} QScriptValue WindowScriptingInterface::getCursorPositionX() {    return QCursor::pos().x();} QScriptValue WindowScriptingInterface::getCursorPositionY() {    return QCursor::pos().y();} QScriptValue WindowScriptingInterface::alert(const QString& message) {    QScriptValue retVal;    QMetaObject::invokeMethod(this, "showAlert", Qt::BlockingQueuedConnection, Q_RETURN_ARG(QScriptValue, retVal), Q_ARG(const QString&, message));    return retVal;} QScriptValue WindowScriptingInterface::confirm(const QString& message) {    QScriptValue retVal;    QMetaObject::invokeMethod(this, "showConfirm", Qt::BlockingQueuedConnection,                              Q_RETURN_ARG(QScriptValue, retVal), Q_ARG(const QString&, message));    return retVal;} QScriptValue WindowScriptingInterface::form(const QString& title, QScriptValue form) {    QScriptValue retVal;    QMetaObject::invokeMethod(this, "showForm", Qt::BlockingQueuedConnection,                              Q_RETURN_ARG(QScriptValue, retVal),                              Q_ARG(const QString&, title), Q_ARG(QScriptValue, form));    return retVal;} QScriptValue WindowScriptingInterface::prompt(const QString& message, const QString& defaultText) {    QScriptValue retVal;    QMetaObject::invokeMethod(this, "showPrompt", Qt::BlockingQueuedConnection,                              Q_RETURN_ARG(QScriptValue, retVal),                              Q_ARG(const QString&, message), Q_ARG(const QString&, defaultText));    return retVal;} QScriptValue WindowScriptingInterface::browse(const QString& title, const QString& directory,  const QString& nameFilter) {    QScriptValue retVal;    QMetaObject::invokeMethod(this, "showBrowse", Qt::BlockingQueuedConnection,                              Q_RETURN_ARG(QScriptValue, retVal),                              Q_ARG(const QString&, title), Q_ARG(const QString&, directory), Q_ARG(const QString&, nameFilter));    return retVal;} QScriptValue WindowScriptingInterface::save(const QString& title, const QString& directory,  const QString& nameFilter) {    QScriptValue retVal;    QMetaObject::invokeMethod(this, "showBrowse", Qt::BlockingQueuedConnection,                              Q_RETURN_ARG(QScriptValue, retVal),                              Q_ARG(const QString&, title), Q_ARG(const QString&, directory), Q_ARG(const QString&, nameFilter),                              Q_ARG(QFileDialog::AcceptMode, QFileDialog::AcceptSave));    return retVal;} QScriptValue WindowScriptingInterface::s3Browse(const QString& nameFilter) {    QScriptValue retVal;    QMetaObject::invokeMethod(this, "showS3Browse", Qt::BlockingQueuedConnection,                              Q_RETURN_ARG(QScriptValue, retVal),                              Q_ARG(const QString&, nameFilter));    return retVal;} void WindowScriptingInterface::nonBlockingForm(const QString& title, QScriptValue form) {    QMetaObject::invokeMethod(this, "showNonBlockingForm", Qt::BlockingQueuedConnection,                              Q_ARG(const QString&, title), Q_ARG(QScriptValue, form));} void WindowScriptingInterface::reloadNonBlockingForm(QScriptValue newValues) {    QMetaObject::invokeMethod(this, "doReloadNonBlockingForm", Qt::BlockingQueuedConnection,                              Q_ARG(QScriptValue, newValues));}  QScriptValue WindowScriptingInterface::getNonBlockingFormResult(QScriptValue form) {    QScriptValue retVal;    QMetaObject::invokeMethod(this, "doGetNonBlockingFormResult", Qt::BlockingQueuedConnection,                              Q_RETURN_ARG(QScriptValue, retVal),                              Q_ARG(QScriptValue, form));    return retVal;} QScriptValue WindowScriptingInterface::peekNonBlockingFormResult(QScriptValue form) {    QScriptValue retVal;    QMetaObject::invokeMethod(this, "doPeekNonBlockingFormResult", Qt::BlockingQueuedConnection,                              Q_RETURN_ARG(QScriptValue, retVal),                              Q_ARG(QScriptValue, form));    return retVal;}  /// Display an alert box/// \param const QString& message message to display/// \return QScriptValue::UndefinedValueQScriptValue WindowScriptingInterface::showAlert(const QString& message) {    QMessageBox::warning(Application::getInstance()->getWindow(), "", message);    return QScriptValue::UndefinedValue;} /// Display a confirmation box with the options 'Yes' and 'No'/// \param const QString& message message to display/// \return QScriptValue `true` if 'Yes' was clicked, `false` otherwiseQScriptValue WindowScriptingInterface::showConfirm(const QString& message) {    QMessageBox::StandardButton response = QMessageBox::question(Application::getInstance()->getWindow(), "", message);    return QScriptValue(response == QMessageBox::Yes);} void WindowScriptingInterface::chooseDirectory() {    QPushButton* button = reinterpret_cast<QPushButton*>(sender());     QString title = button->property("title").toString();    QString path = button->property("path").toString();    QRegExp displayAs = button->property("displayAs").toRegExp();    QRegExp validateAs = button->property("validateAs").toRegExp();    QString errorMessage = button->property("errorMessage").toString();     QString directory = QFileDialog::getExistingDirectory(button, title, path);    if (directory.isEmpty()) {        return;    }     if (!validateAs.exactMatch(directory)) {        QMessageBox::warning(NULL, "Invalid Directory", errorMessage);        return;    }     button->setProperty("path", directory);     displayAs.indexIn(directory);    QString buttonText = displayAs.cap(1) != "" ? displayAs.cap(1) : ".";    button->setText(buttonText);} void WindowScriptingInterface::inlineButtonClicked() {    QPushButton* button = reinterpret_cast<QPushButton*>(sender());    QString name = button->property("name").toString();    emit inlineButtonClicked(name);} QString WindowScriptingInterface::jsRegExp2QtRegExp(QString string) {    // Converts string representation of RegExp from JavaScript format to Qt format.    return string.mid(1, string.length() - 2)  // No enclosing slashes.        .replace("\\/", "/");                  // No escaping of forward slash.} void WindowScriptingInterface::showNonBlockingForm(const QString& title, QScriptValue form) {    if (!form.isArray() || (form.isArray() && form.property("length").toInt32() <= 0)) {        return;    }        // what should we do if someone calls us while we still think we have a dialog showing???    if (_nonBlockingFormActive) {        qDebug() << "Show Non-Blocking Form called when form already active.";        return;    }        _form = form;    _editDialog = createForm(title, _form);    _nonBlockingFormActive = true;        connect(_editDialog, SIGNAL(accepted()), this, SLOT(nonBlockingFormAccepted()));    connect(_editDialog, SIGNAL(rejected()), this, SLOT(nonBlockingFormRejected()));        _editDialog->setModal(true);    _editDialog->show();} void WindowScriptingInterface::doReloadNonBlockingForm(QScriptValue newValues) {    if (!newValues.isArray() || (newValues.isArray() && newValues.property("length").toInt32() <= 0)) {        return;    }        // what should we do if someone calls us while we still think we have a dialog showing???    if (!_editDialog) {        qDebug() << "Reload Non-Blocking Form called when no form is active.";        return;    }     for (int i = 0; i < newValues.property("length").toInt32(); ++i) {        QScriptValue item = newValues.property(i);                if (item.property("oldIndex").isValid()) {            int oldIndex = item.property("oldIndex").toInt32();            QScriptValue oldItem = _form.property(oldIndex);            if (oldItem.isValid()) {                QLineEdit* originalEdit = _edits[oldItem.property("editIndex").toInt32()];                originalEdit->setText(item.property("value").toString());            }        }    }}  bool WindowScriptingInterface::nonBlockingFormActive() {    return _nonBlockingFormActive;} QScriptValue WindowScriptingInterface::doPeekNonBlockingFormResult(QScriptValue array) {    QScriptValue retVal;        int e = -1;    int d = -1;    int c = -1;    int h = -1;    for (int i = 0; i < _form.property("length").toInt32(); ++i) {        QScriptValue item = _form.property(i);        QScriptValue value = item.property("value");         if (item.property("button").toString() != "") {            // Nothing to do        } else if (item.property("type").toString() == "inlineButton") {            // Nothing to do        } else if (item.property("type").toString() == "header") {            // Nothing to do        } else if (item.property("directory").toString() != "") {            d += 1;            value = _directories.at(d)->property("path").toString();            item.setProperty("directory", value);            _form.setProperty(i, item);        } else if (item.property("options").isArray()) {            c += 1;            item.setProperty("value",                _combos.at(c)->currentIndex() < item.property("options").property("length").toInt32() ?                item.property("options").property(_combos.at(c)->currentIndex()) :                array.engine()->undefinedValue()            );            _form.setProperty(i, item);        } else if (item.property("type").toString() == "checkbox") {            h++;            value = _checks.at(h)->checkState() == Qt::Checked;            item.setProperty("value", value);            _form.setProperty(i, item);        } else {            e += 1;            bool ok = true;            if (value.isNumber()) {                value = _edits.at(e)->text().toDouble(&ok);            } else if (value.isString()) {                value = _edits.at(e)->text();            } else if (value.isBool()) {                if (_edits.at(e)->text() == "true") {                    value = true;                } else if (_edits.at(e)->text() == "false") {                    value = false;                } else {                    ok = false;                }            }            if (ok) {                item.setProperty("value", value);                _form.setProperty(i, item);            }        }    }        array = _form;    return (_formResult == QDialog::Accepted);    } QScriptValue WindowScriptingInterface::doGetNonBlockingFormResult(QScriptValue array) {    QScriptValue retVal;        if (_formResult == QDialog::Accepted) {        int e = -1;        int d = -1;        int c = -1;        int h = -1;        for (int i = 0; i < _form.property("length").toInt32(); ++i) {            QScriptValue item = _form.property(i);            QScriptValue value = item.property("value");             if (item.property("button").toString() != "") {                // Nothing to do            } else if (item.property("type").toString() == "inlineButton") {                // Nothing to do            } else if (item.property("type").toString() == "header") {                // Nothing to do            } else if (item.property("directory").toString() != "") {                d += 1;                value = _directories.at(d)->property("path").toString();                item.setProperty("directory", value);                _form.setProperty(i, item);            } else if (item.property("options").isArray()) {                c += 1;                item.setProperty("value",                    _combos.at(c)->currentIndex() < item.property("options").property("length").toInt32() ?                    item.property("options").property(_combos.at(c)->currentIndex()) :                    array.engine()->undefinedValue()                );                _form.setProperty(i, item);            } else if (item.property("type").toString() == "checkbox") {                h++;                value = _checks.at(h)->checkState() == Qt::Checked;                item.setProperty("value", value);                _form.setProperty(i, item);            } else {                e += 1;                bool ok = true;                if (value.isNumber()) {                    value = _edits.at(e)->text().toDouble(&ok);                } else if (value.isString()) {                    value = _edits.at(e)->text();                } else if (value.isBool()) {                    if (_edits.at(e)->text() == "true") {                        value = true;                    } else if (_edits.at(e)->text() == "false") {                        value = false;                    } else {                        ok = false;                    }                }                if (ok) {                    item.setProperty("value", value);                    _form.setProperty(i, item);                }            }        }    }        delete _editDialog;    _editDialog = NULL;    _form = QScriptValue();    _edits.clear();    _directories.clear();    _combos.clear();    _checks.clear();        array = _form;    return (_formResult == QDialog::Accepted);    }  /// Display a form layout with an edit box/// \param const QString& title title to display/// \param const QScriptValue form to display as an array of objects:/// - label, value/// - label, directory, title, display regexp, validate regexp, error message/// - button ("Cancel")/// \return QScriptValue `true` if 'OK' was clicked, `false` otherwiseQScriptValue WindowScriptingInterface::showForm(const QString& title, QScriptValue form) {    if (form.isArray() && form.property("length").toInt32() <= 0) {        return false;    }    QDialog* editDialog = createForm(title, form);     int result = editDialog->exec();        if (result == QDialog::Accepted) {        int e = -1;        int d = -1;        int c = -1;        int h = -1;        for (int i = 0; i < form.property("length").toInt32(); ++i) {            QScriptValue item = form.property(i);            QScriptValue value = item.property("value");             if (item.property("button").toString() != "") {                // Nothing to do            } else if (item.property("type").toString() == "inlineButton") {                // Nothing to do            } else if (item.property("type").toString() == "header") {                // Nothing to do            } else if (item.property("directory").toString() != "") {                d += 1;                value = _directories.at(d)->property("path").toString();                item.setProperty("directory", value);                form.setProperty(i, item);            } else if (item.property("options").isArray()) {                c += 1;                item.setProperty("value",                     _combos.at(c)->currentIndex() < item.property("options").property("length").toInt32() ?                    item.property("options").property(_combos.at(c)->currentIndex()) :                    form.engine()->undefinedValue()                );                form.setProperty(i, item);            } else if (item.property("type").toString() == "checkbox") {                h++;                value = _checks.at(h)->checkState() == Qt::Checked;                item.setProperty("value", value);                form.setProperty(i, item);            } else {                e += 1;                bool ok = true;                if (value.isNumber()) {                    value = _edits.at(e)->text().toDouble(&ok);                } else if (value.isString()) {                    value = _edits.at(e)->text();                } else if (value.isBool()) {                    if (_edits.at(e)->text() == "true") {                        value = true;                    } else if (_edits.at(e)->text() == "false") {                        value = false;                    } else {                        ok = false;                    }                }                if (ok) {                    item.setProperty("value", value);                    form.setProperty(i, item);                }            }        }    }        delete editDialog;    _combos.clear();    _checks.clear();    _edits.clear();    _directories.clear();    return (result == QDialog::Accepted);}   QDialog* WindowScriptingInterface::createForm(const QString& title, QScriptValue form) {    QDialog* editDialog = new QDialog(Application::getInstance()->getWindow());    editDialog->setWindowTitle(title);     bool cancelButton = false;        QVBoxLayout* layout = new QVBoxLayout();    editDialog->setLayout(layout);        QScrollArea* area = new QScrollArea();    layout->addWidget(area);    area->setWidgetResizable(true);

Lines 1–500 of 673.