From d2c4417b24d5dd78bf98d6ae35d553758b6184b5 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Wed, 14 Dec 2016 17:05:47 -0800 Subject: [PATCH] Hook up Help button to the new Tablet interface --- .../resources/qml/hifi/tablet/Tablet.qml | 21 ++++++++ .../qml/hifi/tablet/TabletButton.qml | 3 ++ .../src/RenderableWebEntityItem.cpp | 2 +- .../src/TabletScriptingInterface.cpp | 54 +++++++++++++++++-- .../src/TabletScriptingInterface.h | 20 ++++--- scripts/system/help.js | 18 +++---- 6 files changed, 95 insertions(+), 23 deletions(-) diff --git a/interface/resources/qml/hifi/tablet/Tablet.qml b/interface/resources/qml/hifi/tablet/Tablet.qml index 1f45d6cf4c..4ea1891737 100644 --- a/interface/resources/qml/hifi/tablet/Tablet.qml +++ b/interface/resources/qml/hifi/tablet/Tablet.qml @@ -10,6 +10,27 @@ Item { width: 480 height: 720 + // called by C++ code when a button should be added to the tablet + function addButtonProxy(properties) { + var component = Qt.createComponent("TabletButton.qml"); + var button = component.createObject(flowMain); + if (properties.icon) { + button.icon = properties.icon; + } + if (properties.color) { + button.color = properties.color; + } + if (properties.text) { + button.text = properties.text; + } + return button; + } + + // called by C++ code when a button should be removed from the tablet + function removeButtonProxy(properties) { + console.log("TABLET_UI_HACK: removeButtonProxy, NOT IMPLEMENTED!, properties = " + JSON.stringify(properties)); + } + Rectangle { id: bgAudio height: 90 diff --git a/interface/resources/qml/hifi/tablet/TabletButton.qml b/interface/resources/qml/hifi/tablet/TabletButton.qml index 75f5423f41..92a7ee2865 100644 --- a/interface/resources/qml/hifi/tablet/TabletButton.qml +++ b/interface/resources/qml/hifi/tablet/TabletButton.qml @@ -9,6 +9,8 @@ Item { width: 132 height: 132 + signal clicked() + Rectangle { id: buttonBg color: tabletButton.color @@ -62,6 +64,7 @@ Item { MouseArea { anchors.fill: parent hoverEnabled: true + onClicked: tabletButton.clicked(); onEntered: { console.log("Tablet Button Hovered!"); tabletButton.state = "hover state"; diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index 29f6a3afd1..cba6842ba9 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -261,7 +261,7 @@ void RenderableWebEntityItem::loadSourceURL() { // TABLET_UI_HACK: move this to overlays as well! if (_webSurface->getRootItem() && _webSurface->getRootItem()->objectName() == "tablet") { auto tabletScriptingInterface = DependencyManager::get(); - tabletScriptingInterface->setupTablet("com.highfidelity.interface.tablet.system", _webSurface->getRootItem()); + tabletScriptingInterface->setQmlTablet("com.highfidelity.interface.tablet.system", _webSurface->getRootItem()); } } } diff --git a/libraries/script-engine/src/TabletScriptingInterface.cpp b/libraries/script-engine/src/TabletScriptingInterface.cpp index e1dd466f59..1bcdfc6013 100644 --- a/libraries/script-engine/src/TabletScriptingInterface.cpp +++ b/libraries/script-engine/src/TabletScriptingInterface.cpp @@ -27,11 +27,16 @@ QObject* TabletScriptingInterface::getTablet(const QString& tabletId) { } } -void TabletScriptingInterface::setupTablet(QString tabletId, QQuickItem* qmlTablet) { - // AJT: TODO - qDebug() << "AJT: setupTablet objname = " << qmlTablet->objectName(); +void TabletScriptingInterface::setQmlTablet(QString tabletId, QQuickItem* qmlTablet) { + TabletProxy* tablet = qobject_cast(getTablet(tabletId)); + if (tablet) { + tablet->setQmlTablet(qmlTablet); + } else { + qWarning() << "TabletScriptingInterface::setupTablet() bad tablet object"; + } } + // // TabletProxy // @@ -40,10 +45,47 @@ TabletProxy::TabletProxy(QString name) : _name(name) { ; } +static void addButtonProxyToQmlTablet(QQuickItem* qmlTablet, TabletButtonProxy* buttonProxy) { + QVariant resultVar; + Qt::ConnectionType connectionType = Qt::AutoConnection; + if (QThread::currentThread() != qmlTablet->thread()) { + connectionType = Qt::BlockingQueuedConnection; + } + bool hasResult = QMetaObject::invokeMethod(qmlTablet, "addButtonProxy", connectionType, + Q_RETURN_ARG(QVariant, resultVar), Q_ARG(QVariant, buttonProxy->getProperties())); + if (!hasResult) { + qWarning() << "TabletScriptingInterface addButtonProxyToQmlTablet has no result"; + return; + } + + QObject* qmlButton = qvariant_cast(resultVar); + if (!qmlButton) { + qWarning() << "TabletScriptingInterface addButtonProxyToQmlTablet result not a QObject"; + return; + } + QObject::connect(qmlButton, SIGNAL(clicked()), buttonProxy, SLOT(clickedSlot())); +} + +void TabletProxy::setQmlTablet(QQuickItem* qmlTablet) { + if (qmlTablet) { + _qmlTablet = qmlTablet; + std::lock_guard guard(_tabletButtonProxiesMutex); + for (auto& buttonProxy : _tabletButtonProxies) { + addButtonProxyToQmlTablet(_qmlTablet, buttonProxy.data()); + } + } else { + _qmlTablet = nullptr; + } + +} + QObject* TabletProxy::addButton(const QVariant& properties) { auto tabletButtonProxy = QSharedPointer(new TabletButtonProxy(properties.toMap())); std::lock_guard guard(_tabletButtonProxiesMutex); _tabletButtonProxies.push_back(tabletButtonProxy); + if (_qmlTablet) { + addButtonProxyToQmlTablet(_qmlTablet, tabletButtonProxy.data()); + } return tabletButtonProxy.data(); } @@ -51,6 +93,9 @@ void TabletProxy::removeButton(QObject* tabletButtonProxy) { std::lock_guard guard(_tabletButtonProxiesMutex); auto iter = std::find(_tabletButtonProxies.begin(), _tabletButtonProxies.end(), tabletButtonProxy); if (iter != _tabletButtonProxies.end()) { + if (_qmlTablet) { + QMetaObject::invokeMethod(_qmlTablet, "removeButton", Qt::AutoConnection, Q_ARG(QVariant, (*iter)->getProperties())); + } _tabletButtonProxies.erase(iter); } else { qWarning() << "TabletProxy::removeButton() could not find button " << tabletButtonProxy; @@ -69,6 +114,8 @@ void TabletButtonProxy::setInitRequestHandler(const QScriptValue& handler) { _initRequestHandler = handler; } +// TABLET_UI_HACK remove +/* static QString IMAGE_URL_KEY = "imageUrl"; static QString IMAGE_URL_DEFAULT = ""; @@ -81,5 +128,6 @@ void TabletButtonProxy::setImageUrl(QString imageUrl) { std::lock_guard guard(_propertiesMutex); _properties[IMAGE_URL_KEY] = imageUrl; } +*/ #include "TabletScriptingInterface.moc" diff --git a/libraries/script-engine/src/TabletScriptingInterface.h b/libraries/script-engine/src/TabletScriptingInterface.h index ee2b22eed6..13d7219306 100644 --- a/libraries/script-engine/src/TabletScriptingInterface.h +++ b/libraries/script-engine/src/TabletScriptingInterface.h @@ -36,7 +36,8 @@ public: */ Q_INVOKABLE QObject* getTablet(const QString& tabletId); - void setupTablet(QString tabletId, QQuickItem* qmlTablet); + void setQmlTablet(QString tabletId, QQuickItem* qmlTablet); + protected: std::mutex _tabletProxiesMutex; std::map> _tabletProxies; @@ -52,10 +53,12 @@ class TabletProxy : public QObject { public: TabletProxy(QString name); + void setQmlTablet(QQuickItem* qmlTablet); + /**jsdoc * @function TabletProxy#addButton * Creates a new button, adds it to this and returns it. - * @param properties {Object} button properties AJT: TODO: enumerate these... + * @param properties {Object} button properties UI_TABLET_HACK: enumerate these when we figure out what they should be! * @returns {TabletButtonProxy} */ Q_INVOKABLE QObject* addButton(const QVariant& properties); @@ -72,6 +75,7 @@ protected: QString _name; std::mutex _tabletButtonProxiesMutex; std::vector> _tabletButtonProxies; + QQuickItem* _qmlTablet { nullptr }; }; /**jsdoc @@ -80,7 +84,6 @@ protected: */ class TabletButtonProxy : public QObject { Q_OBJECT - Q_PROPERTY(QString imageUrl READ getImageUrl WRITE setImageUrl) public: TabletButtonProxy(const QVariantMap& properties); @@ -90,16 +93,19 @@ public: */ Q_INVOKABLE void setInitRequestHandler(const QScriptValue& handler); - QString getImageUrl() const; - void setImageUrl(QString imageUrl); + const QVariantMap& getProperties() const { return _properties; } + +public slots: + void clickedSlot() { emit clicked(); } signals: /**jsdoc * Signaled when this button has been clicked on by the user. - * @function TabletButtonProxy#onClick + * @function TabletButtonProxy#clicked * @returns {Signal} */ - void onClick(); + void clicked(); + protected: mutable std::mutex _propertiesMutex; QVariantMap _properties; diff --git a/scripts/system/help.js b/scripts/system/help.js index e79ed0444c..a577688032 100644 --- a/scripts/system/help.js +++ b/scripts/system/help.js @@ -13,20 +13,14 @@ (function() { // BEGIN LOCAL_SCOPE - var toolBar = Toolbars.getToolbar("com.highfidelity.interface.toolbar.system"); - var buttonName = "help"; // matching location reserved in Desktop.qml - var button = toolBar.addButton({ - objectName: buttonName, - imageURL: Script.resolvePath("assets/images/tools/help.svg"), - visible: true, - hoverState: 2, - defaultState: 1, - buttonState: 1, - alpha: 0.9 + var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + var button = tablet.addButton({ + //icon: "help.svg", + color: "#ff6f6f", + text: "HELP" }); // TODO: make button state reflect whether the window is opened or closed (independently from us). - function onClicked(){ Menu.triggerOption('Help...') } @@ -34,7 +28,7 @@ button.clicked.connect(onClicked); Script.scriptEnding.connect(function () { - toolBar.removeButton(buttonName); + tablet.removeButton(buttonName); button.clicked.disconnect(onClicked); });