diff options
author | Janne Kangas <janne.kangas@qt.io> | 2019-05-14 11:02:30 +0300 |
---|---|---|
committer | Janne Kangas <janne.kangas@qt.io> | 2019-06-05 10:55:03 +0300 |
commit | f5819c8149ecef193619cbd33589a5652fd79ee6 (patch) | |
tree | c74f04765c40034b2683999e27b1c61dcadb3de3 | |
parent | 0cc10ec7d2c15f8c7ce531bee23ad9ca7e0557cc (diff) |
Implement datainput metadata getter
Implement metadata for both C++ and QML APIs. As a basic rule, defer to
viewer app as metadata source whenever possible. For QML side separated
by asynchronous command queue, fetch metadata at UIA load and store it
locally in datainput and/or presentation items.
Task-id: QT3DS-3579
Change-Id: Ife323f427da301ee8e6bfe9a9dccfe599ee2e5dd
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
13 files changed, 198 insertions, 8 deletions
diff --git a/src/Runtime/ogl-runtime/src/api/studio3d/q3dsdatainput.cpp b/src/Runtime/ogl-runtime/src/api/studio3d/q3dsdatainput.cpp index 2e6281e6..a15f9fb7 100644 --- a/src/Runtime/ogl-runtime/src/api/studio3d/q3dsdatainput.cpp +++ b/src/Runtime/ogl-runtime/src/api/studio3d/q3dsdatainput.cpp @@ -257,8 +257,56 @@ bool Q3DSDataInput::isValid() const } /*! - \brief Q3DSDataInput::setValue Set value of the data input. - \param value New value to be set. + Returns the metadata defined for this datainput with metadata \a key. + + Metadata is user-defined key-value table that can be used, for example, to better describe the + usage of, or to indicate the external data source that should be bound to this datainput. + Metadata has no impact on presentation rendering. + + \note Datainput metadata is read-only. + */ +/*! + \qmlmethod string DataInput::metadata + Returns the metadata defined for this datainput with metadata \a key. + + Metadata is user-defined key-value table that can be used, for example, to better describe the + usage of, or to indicate the external data source that should be bound to this datainput. + Metadata has no impact on presentation rendering. + + \note Datainput metadata is read-only. + */ +QString Q3DSDataInput::metadata(const QString &key) const +{ + if (!d_ptr->m_presentation) + return {}; + + auto metadata = d_ptr->m_presentation->d_ptr->dataInputMetadata(name()); + + return metadata[key]; +} + +/*! + Returns the metadata keys defined for this datainput. + + \sa metadata + */ +/*! + \qmlmethod var DataInput::metadataKeys + Returns the metadata keys defined for this datainput. + + \note Datainput metadata is read-only. + \sa metadata + */ +QStringList Q3DSDataInput::metadataKeys() const +{ + if (!d_ptr->m_presentation) + return {}; + + return d_ptr->m_presentation->d_ptr->dataInputMetadata(name()).keys(); +} + +/*! + \brief Q3DSDataInput::setValue Set a new \a value for this data input. \note For performance reasons do not call setValue unnecessarily. */ void Q3DSDataInput::setValue(const QVariant &value) diff --git a/src/Runtime/ogl-runtime/src/api/studio3d/q3dsdatainput.h b/src/Runtime/ogl-runtime/src/api/studio3d/q3dsdatainput.h index 4504e5d2..3617dcd1 100644 --- a/src/Runtime/ogl-runtime/src/api/studio3d/q3dsdatainput.h +++ b/src/Runtime/ogl-runtime/src/api/studio3d/q3dsdatainput.h @@ -68,6 +68,9 @@ public: float max() const; bool isValid() const; + Q_INVOKABLE QString metadata(const QString &key) const; + Q_INVOKABLE QStringList metadataKeys() const; + public Q_SLOTS: void setName(const QString &name); void setValue(const QVariant &value); diff --git a/src/Runtime/ogl-runtime/src/api/studio3d/q3dsdatainput_p.h b/src/Runtime/ogl-runtime/src/api/studio3d/q3dsdatainput_p.h index 6107add9..19b06f9d 100644 --- a/src/Runtime/ogl-runtime/src/api/studio3d/q3dsdatainput_p.h +++ b/src/Runtime/ogl-runtime/src/api/studio3d/q3dsdatainput_p.h @@ -74,6 +74,12 @@ protected: float m_max = 0; float m_min = 0; + // Note: Qt3d Runtime allows metadata to be both read and set, therefore requiring + // internal representation of both keys and values to be QVariant as per API convention. + // OpenGL Runtime, in contrast, only allows metadata to be read. As metadata now can only + // come from UIA file where it is stored as string, we use QStrings in API as well. + QHash<QString, QString> m_metadata; + friend class Q3DSPresentationPrivate; friend class Q3DSRenderer; }; diff --git a/src/Runtime/ogl-runtime/src/api/studio3d/q3dspresentation.cpp b/src/Runtime/ogl-runtime/src/api/studio3d/q3dspresentation.cpp index f6de2fd8..59bd91a4 100644 --- a/src/Runtime/ogl-runtime/src/api/studio3d/q3dspresentation.cpp +++ b/src/Runtime/ogl-runtime/src/api/studio3d/q3dspresentation.cpp @@ -305,6 +305,7 @@ Q3DSDataOutput *Q3DSPresentation::registeredDataOutput(const QString &name) cons QVector<Q3DSDataInput *> Q3DSPresentation::dataInputs() const { QVector<Q3DSDataInput *> ret; + // Just return local datainput list const auto datainputs = d_ptr->m_dataInputs; for (const auto &it : datainputs) ret.append(it); @@ -313,7 +314,7 @@ QVector<Q3DSDataInput *> Q3DSPresentation::dataInputs() const } /*! - \qmlmethod variant Presentation::getDataInputs + \qmlmethod var Presentation::getDataInputs Returns a list of datainputs defined for this presentation. Use setDataInputValue() interface to set a datainput value using datainput name, or call Q3DSDataInput::setValue directly for a specific datainput. @@ -341,6 +342,46 @@ QVariantList Q3DSPresentation::getDataInputs() const } /*! + Returns a list of datainputs defined for this presentation that have the specified + \a metadataKey. + + \sa setDataInputValue + \sa Q3DSDataInput + */ + +/*! + \qmlmethod var Presentation::getDataInputs + Returns a list of datainputs defined for this presentation that have the specified + \a metadataKey. + + \sa DataInput + */ +QVariantList Q3DSPresentation::getDataInputs(const QString &metadataKey) const +{ + QVariantList ret; + const auto datainputs = dataInputs(metadataKey); + + for (const auto &it : datainputs) + ret.append(QVariant::fromValue(it)); + + return ret; +} + +/*! + Returns a list of datainputs defined for this presentation that have the specified + \a metadataKey. + + \sa setDataInputValue + \sa Q3DSDataInput + */ +QVector<Q3DSDataInput *> Q3DSPresentation::dataInputs(const QString &metadataKey) const +{ + // Defer to presentation item as we want to read metadata from viewer app whenever + // possible. + return d_ptr->dataInputs(metadataKey); +} + +/*! Returns a list of dataoutputs defined for this presentation. Use Qt's connect() method to connect slots to the valueChanged() signal in the required \l{DataOutput}s to get notified when the value tracked by the DataOutput is changed. @@ -358,7 +399,7 @@ QVector<Q3DSDataOutput *> Q3DSPresentation::dataOutputs() const } /*! - \qmlmethod variant Presentation::getDataOutputs + \qmlmethod var Presentation::getDataOutputs Returns a list of dataoutputs defined for this presentation. Connect slots to the \c{valueChanged()} signal in the required \l{DataOutput}s to get notified @@ -1327,17 +1368,19 @@ void Q3DSPresentationPrivate::requestResponseHandler(CommandType commandType, vo // Check and append to QML-side list if the (UIA) presentation has additional datainputs // that are not explicitly defined in QML code. auto receivedDI = response->at(i).value<Q3DSDataInput *>(); - // For QML behind async command queue, we cache min/max values in addition + // For QML behind async command queue, we cache min/max and metadata values in addition // to name, in order to be able to return values initially set in UIA file (in QML // getters). if (!m_dataInputs.contains(receivedDI->name())) { auto newDI = new Q3DSDataInput(receivedDI->name(), nullptr); newDI->d_ptr->m_min = receivedDI->d_ptr->m_min; newDI->d_ptr->m_max = receivedDI->d_ptr->m_max; + newDI->d_ptr->m_metadata = receivedDI->d_ptr->m_metadata; registerDataInput(newDI); } else { m_dataInputs[receivedDI->name()]->d_ptr->m_min = receivedDI->d_ptr->m_min; m_dataInputs[receivedDI->name()]->d_ptr->m_max = receivedDI->d_ptr->m_max; + m_dataInputs[receivedDI->name()]->d_ptr->m_metadata = receivedDI->d_ptr->m_metadata; } } delete response; @@ -1504,6 +1547,43 @@ float Q3DSPresentationPrivate::dataInputMax(const QString &name) const return m_viewerApp->dataInputMax(name); } +QHash<QString, QString> Q3DSPresentationPrivate::dataInputMetadata(const QString &name) const +{ + // For QML instance separated from runtime engine by command queue, + // return locally cached value (initialised at presentation load). + if (!m_viewerApp) { + if (m_dataInputs.contains(name)) + return m_dataInputs[name]->d_ptr->m_metadata; + else + return {}; + } + return m_viewerApp->dataInputMetadata(name); +} + +QVector<Q3DSDataInput *> Q3DSPresentationPrivate::dataInputs(const QString &key) const +{ + QVector<Q3DSDataInput *> ret; + // For QML instance separated from runtime engine by command queue, + // return locally cached value (initialised at presentation load). + if (!m_viewerApp) { + for (const auto &it : m_dataInputs) { + if (it->metadataKeys().contains(key)) + ret.append(it); + } + } else { + // Otherwise, defer to viewer app. + const auto &diList = m_viewerApp->dataInputs(); + // We fetch the metadata(s) from the source (viewer app) but + // return the corresponding datainput object(s) held by presentation item. + for (const auto &it : diList) { + if (m_viewerApp->dataInputMetadata(it).contains(key)) + ret.append(m_dataInputs[it]); + } + } + + return ret; +} + void Q3DSPresentationPrivate::registerDataOutput(Q3DSDataOutput *dataOutput) { Q_ASSERT(!dataOutput->name().isEmpty()); diff --git a/src/Runtime/ogl-runtime/src/api/studio3d/q3dspresentation.h b/src/Runtime/ogl-runtime/src/api/studio3d/q3dspresentation.h index 436e6844..4566443d 100644 --- a/src/Runtime/ogl-runtime/src/api/studio3d/q3dspresentation.h +++ b/src/Runtime/ogl-runtime/src/api/studio3d/q3dspresentation.h @@ -76,6 +76,8 @@ public: Q_INVOKABLE QVariantList getDataInputs() const; QVector<Q3DSDataInput *> dataInputs() const; + Q_INVOKABLE QVariantList getDataInputs(const QString &metadataKey) const; + QVector<Q3DSDataInput *> dataInputs(const QString &metadataKey) const; Q_INVOKABLE QVariantList getDataOutputs() const; QVector<Q3DSDataOutput *> dataOutputs() const; diff --git a/src/Runtime/ogl-runtime/src/api/studio3d/q3dspresentation_p.h b/src/Runtime/ogl-runtime/src/api/studio3d/q3dspresentation_p.h index 7b4877d9..c30eb82d 100644 --- a/src/Runtime/ogl-runtime/src/api/studio3d/q3dspresentation_p.h +++ b/src/Runtime/ogl-runtime/src/api/studio3d/q3dspresentation_p.h @@ -86,6 +86,8 @@ public: bool isValidDataInput(const Q3DSDataInput *dataInput) const; float dataInputMin(const QString &name) const; float dataInputMax(const QString &name) const; + QHash<QString, QString> dataInputMetadata(const QString &name) const; + QVector<Q3DSDataInput *> dataInputs(const QString &key) const; bool isValidDataOutput(const Q3DSDataOutput *dataOutput) const; ViewerQmlStreamProxy *streamProxy(); diff --git a/src/Runtime/ogl-runtime/src/api/studio3dqml/q3dsrenderer.cpp b/src/Runtime/ogl-runtime/src/api/studio3dqml/q3dsrenderer.cpp index bbfee502..4bd8ed0a 100644 --- a/src/Runtime/ogl-runtime/src/api/studio3dqml/q3dsrenderer.cpp +++ b/src/Runtime/ogl-runtime/src/api/studio3dqml/q3dsrenderer.cpp @@ -421,7 +421,7 @@ void Q3DSRenderer::processCommands() Q3DSDataInput *newIt = new Q3DSDataInput(it, nullptr); newIt->d_ptr->m_max = m_runtime->dataInputMax(it); newIt->d_ptr->m_min = m_runtime->dataInputMin(it); - + newIt->d_ptr->m_metadata = m_runtime->dataInputMetadata(it); requestData->append(QVariant::fromValue(newIt)); } } diff --git a/src/Runtime/ogl-runtime/src/engine/Qt3DSRuntimeView.cpp b/src/Runtime/ogl-runtime/src/engine/Qt3DSRuntimeView.cpp index fc6c3cac..5b79234c 100644 --- a/src/Runtime/ogl-runtime/src/engine/Qt3DSRuntimeView.cpp +++ b/src/Runtime/ogl-runtime/src/engine/Qt3DSRuntimeView.cpp @@ -212,6 +212,7 @@ public: QList<QString> dataOutputs() const override; float dataInputMax(const QString &name) const override; float dataInputMin(const QString &name) const override; + QHash<QString, QString> dataInputMetadata(const QString &name) const override; void createElements(const QString &parentElementPath, const QString &slideName, const QVector<QHash<QString, QVariant>> &properties) override; @@ -637,6 +638,14 @@ float CRuntimeView::dataInputMin(const QString &name) const return 0; } +QHash<QString, QString> CRuntimeView::dataInputMetadata(const QString &name) const +{ + if (m_Application) + return m_Application->dataInputMetadata(name); + + return {}; +} + void CRuntimeView::createElements(const QString &parentElementPath, const QString &slideName, const QVector<QHash<QString, QVariant>> &properties) { diff --git a/src/Runtime/ogl-runtime/src/engine/Qt3DSRuntimeView.h b/src/Runtime/ogl-runtime/src/engine/Qt3DSRuntimeView.h index 9ade9c7f..6d0e45cb 100644 --- a/src/Runtime/ogl-runtime/src/engine/Qt3DSRuntimeView.h +++ b/src/Runtime/ogl-runtime/src/engine/Qt3DSRuntimeView.h @@ -200,6 +200,7 @@ public: virtual QList<QString> dataOutputs() const = 0; virtual float dataInputMax(const QString &name) const = 0; virtual float dataInputMin(const QString &name) const = 0; + virtual QHash<QString, QString> dataInputMetadata(const QString &name) const = 0; virtual void createElements(const QString &parentElementPath, const QString &slideName, const QVector<QHash<QString, QVariant>> &properties) = 0; virtual void deleteElements(const QStringList &elementPaths) = 0; diff --git a/src/Runtime/ogl-runtime/src/runtime/Qt3DSApplication.cpp b/src/Runtime/ogl-runtime/src/runtime/Qt3DSApplication.cpp index 8be219c1..baa94ddd 100644 --- a/src/Runtime/ogl-runtime/src/runtime/Qt3DSApplication.cpp +++ b/src/Runtime/ogl-runtime/src/runtime/Qt3DSApplication.cpp @@ -1314,6 +1314,7 @@ struct SApp : public IApplication const char8_t *name = ""; const char8_t *type = ""; const char8_t *evaluator = ""; + const char8_t *metadataStr = ""; diDef.value = QVariant::Invalid; inReader.UnregisteredAtt("name", name); inReader.UnregisteredAtt("type", type); @@ -1342,6 +1343,27 @@ struct SApp : public IApplication diDef.evaluator = QString::fromUtf8(evaluator); } + inReader.UnregisteredAtt("metadata", metadataStr); + QString metaData = QString(metadataStr); + if (!metaData.isEmpty()) { + auto metadataList = metaData.split(QLatin1Char('$')); + + if (metadataList.size() & 1) { + qWarning("Malformed datainput metadata for datainput %s, cannot" + "parse key - value pairs. Stop parsing metadata.", + qUtf8Printable(name)); + } else { + for (int i = 0; i < metadataList.size(); i += 2) { + if (metadataList[i].isEmpty()) { + qWarning("Malformed datainput metadata for datainput %s " + "- metadata key empty. Stop parsing metadata.", + qUtf8Printable(name)); + break; + } + diDef.metadata.insert(metadataList[i], metadataList[i+1]); + } + } + } m_dataInputDefs.insert(QString::fromUtf8(name), diDef); // #TODO Remove below once QT3DS-3510 task has been completed. // By default data inputs should not have data outputs, but this is needed @@ -1439,6 +1461,11 @@ struct SApp : public IApplication return m_dataInputDefs[name].min; } + QHash<QString, QString> dataInputMetadata(const QString &name) const override + { + return m_dataInputDefs[name].metadata; + } + struct SAppXMLErrorHandler : public qt3ds::foundation::CXmlErrorHandler { NVFoundationBase &m_Foundation; @@ -2117,6 +2144,9 @@ QDebug operator<<(QDebug debug, const DataInputValueRole &value) return debug; } +// TODO: optionally print out also metadata, but note that it is not +// relevant for any runtime or editor -side code debugging (strictly user-side +// information). QDebug operator<<(QDebug debug, const DataInputDef &value) { QDebugStateSaver saver(debug); diff --git a/src/Runtime/ogl-runtime/src/runtime/Qt3DSApplication.h b/src/Runtime/ogl-runtime/src/runtime/Qt3DSApplication.h index 39cd3c4b..f38b1821 100644 --- a/src/Runtime/ogl-runtime/src/runtime/Qt3DSApplication.h +++ b/src/Runtime/ogl-runtime/src/runtime/Qt3DSApplication.h @@ -123,7 +123,7 @@ struct DataInputDef QVariant value; // most recently set value // evaluator datainputs that need to re-evaluate when this datainput changes value QVector<QString> dependents; - + QHash<QString, QString> metadata; }; struct DataOutputDef @@ -186,8 +186,8 @@ public: virtual QList<QString> dataOutputs() const = 0; virtual float dataInputMax(const QString &name) const = 0; - virtual float dataInputMin(const QString &name) const = 0; + virtual QHash<QString, QString> dataInputMetadata(const QString &name) const = 0; virtual void setPresentationId(const QString &id) = 0; diff --git a/src/Runtime/ogl-runtime/src/viewer/Qt3DSViewerApp.cpp b/src/Runtime/ogl-runtime/src/viewer/Qt3DSViewerApp.cpp index 094f140f..4c7be294 100644 --- a/src/Runtime/ogl-runtime/src/viewer/Qt3DSViewerApp.cpp +++ b/src/Runtime/ogl-runtime/src/viewer/Qt3DSViewerApp.cpp @@ -910,6 +910,14 @@ float Q3DSViewerApp::dataInputMin(const QString &name) const return m_Impl.m_view->dataInputMin(name); } +QHash<QString, QString> Q3DSViewerApp::dataInputMetadata(const QString &name) const +{ + if (!m_Impl.m_view) + return {}; + + return m_Impl.m_view->dataInputMetadata(name); +} + void Q3DSViewerApp::createElements(const QString &parentElementPath, const QString &slideName, const QVector<QHash<QString, QVariant>> &properties) { diff --git a/src/Runtime/ogl-runtime/src/viewer/Qt3DSViewerApp.h b/src/Runtime/ogl-runtime/src/viewer/Qt3DSViewerApp.h index 975e3b12..7a9299f2 100644 --- a/src/Runtime/ogl-runtime/src/viewer/Qt3DSViewerApp.h +++ b/src/Runtime/ogl-runtime/src/viewer/Qt3DSViewerApp.h @@ -461,6 +461,7 @@ public: float dataInputMax(const QString &name) const; float dataInputMin(const QString &name) const; + QHash<QString, QString> dataInputMetadata(const QString &name) const; void createElements(const QString &parentElementPath, const QString &slideName, const QVector<QHash<QString, QVariant>> &properties); |