262 lines · 9.9 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 "OffscreenUi.h"#include "ui/ModelsBrowser.h"#include "WebWindowClass.h" #include "WindowScriptingInterface.h" WindowScriptingInterface::WindowScriptingInterface() {    const DomainHandler& domainHandler = DependencyManager::get<NodeList>()->getDomainHandler();    connect(&domainHandler, &DomainHandler::connectedToDomain, this, &WindowScriptingInterface::domainChanged);    connect(qApp, &Application::domainConnectionRefused, this, &WindowScriptingInterface::domainConnectionRefused);     connect(qApp, &Application::svoImportRequested, [this](const QString& urlString) {        static const QMetaMethod svoImportRequestedSignal =            QMetaMethod::fromSignal(&WindowScriptingInterface::svoImportRequested);         if (isSignalConnected(svoImportRequestedSignal)) {            QUrl url(urlString);            emit svoImportRequested(url.url());        } else {            OffscreenUi::warning("Import SVO Error", "You need to be running edit.js to import entities.");        }    });} WebWindowClass* WindowScriptingInterface::doCreateWebWindow(const QString& title, const QString& url, int width, int height) {    return new WebWindowClass(title, url, width, height);} QScriptValue WindowScriptingInterface::hasFocus() {    return qApp->hasFocus();} void WindowScriptingInterface::setFocus() {    // It's forbidden to call focus() from another thread.    qApp->postLambdaEvent([] {        auto window = qApp->getWindow();        window->activateWindow();        window->setFocus();    });} void WindowScriptingInterface::raiseMainWindow() {    // It's forbidden to call raise() from another thread.    qApp->postLambdaEvent([] {        qApp->getWindow()->raise();    });} 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::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;}  /// Display an alert box/// \param const QString& message message to display/// \return QScriptValue::UndefinedValueQScriptValue WindowScriptingInterface::showAlert(const QString& message) {    OffscreenUi::warning("", 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) {    bool confirm = false;    if (QMessageBox::Yes == OffscreenUi::question("", message)) {        confirm = true;    }    return QScriptValue(confirm);} 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)) {        OffscreenUi::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(const 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.} /// Display a prompt with a text box/// \param const QString& message message to display/// \param const QString& defaultText default text in the text box/// \return QScriptValue string text value in text box if the dialog was accepted, `null` otherwise.QScriptValue WindowScriptingInterface::showPrompt(const QString& message, const QString& defaultText) {    bool ok = false;    QString result = OffscreenUi::getText(nullptr, "", message, QLineEdit::Normal, defaultText, &ok);    if (!ok) {        return QScriptValue::NullValue;    }    return QScriptValue(result);} /// Display a file dialog.  If `directory` is an invalid file or directory the browser will start at the current/// working directory./// \param const QString& title title of the window/// \param const QString& directory directory to start the file browser at/// \param const QString& nameFilter filter to filter filenames by - see `QFileDialog`/// \return QScriptValue file path as a string if one was selected, otherwise `QScriptValue::NullValue`QScriptValue WindowScriptingInterface::showBrowse(const QString& title, const QString& directory, const QString& nameFilter,                                                  QFileDialog::AcceptMode acceptMode) {    // 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.    QString path = "";    QFileInfo fileInfo = QFileInfo(directory);    if (fileInfo.isDir()) {        fileInfo.setFile(directory, "__HIFI_INVALID_FILE__");        path = fileInfo.filePath();    }        QFileDialog fileDialog(qApp->getWindow(), title, path, nameFilter);    fileDialog.setAcceptMode(acceptMode);    QUrl fileUrl(directory);    if (acceptMode == QFileDialog::AcceptSave) {        // TODO -- Setting this breaks the dialog on Linux.  Does it help something on other platforms?        // fileDialog.setFileMode(QFileDialog::Directory);        fileDialog.selectFile(fileUrl.fileName());    }    if (fileDialog.exec()) {        return QScriptValue(fileDialog.selectedFiles().first());    }    return QScriptValue::NullValue;} /// Display a browse window for S3 models/// \param const QString& nameFilter filter to filter filenames/// \return QScriptValue file path as a string if one was selected, otherwise `QScriptValue::NullValue`QScriptValue WindowScriptingInterface::showS3Browse(const QString& nameFilter) {    ModelsBrowser browser(FSTReader::ENTITY_MODEL);    if (nameFilter != "") {        browser.setNameFilter(nameFilter);    }    QEventLoop loop;    connect(&browser, &ModelsBrowser::selected, &loop, &QEventLoop::quit);    QMetaObject::invokeMethod(&browser, "browse", Qt::QueuedConnection);    loop.exec();        return browser.getSelectedFile();} int WindowScriptingInterface::getInnerWidth() {    return qApp->getWindow()->geometry().width();} int WindowScriptingInterface::getInnerHeight() {    return qApp->getWindow()->geometry().height();} int WindowScriptingInterface::getX() {    return qApp->getWindow()->x();} int WindowScriptingInterface::getY() {    return qApp->getWindow()->y();}