diff options
-rw-r--r-- | src/Authoring/Client/Code/Core/Doc/Doc.h | 10 | ||||
-rw-r--r-- | src/Authoring/Studio/Application/DataInputDlg.cpp | 128 | ||||
-rw-r--r-- | src/Authoring/Studio/Application/DataInputDlg.h | 17 | ||||
-rw-r--r-- | src/Authoring/Studio/Application/DataInputDlg.ui | 254 | ||||
-rw-r--r-- | src/Authoring/Studio/Application/ProjectFile.cpp | 21 | ||||
-rw-r--r-- | src/Authoring/Studio/Application/StudioApp.cpp | 16 | ||||
-rw-r--r-- | src/Authoring/Studio/style.qss | 11 |
7 files changed, 281 insertions, 176 deletions
diff --git a/src/Authoring/Client/Code/Core/Doc/Doc.h b/src/Authoring/Client/Code/Core/Doc/Doc.h index c18b85fb..60f0c3e6 100644 --- a/src/Authoring/Client/Code/Core/Doc/Doc.h +++ b/src/Authoring/Client/Code/Core/Doc/Doc.h @@ -51,6 +51,7 @@ #include <QtCore/quuid.h> #include <QtCore/qsize.h> +#include <QtCore/qhash.h> //============================================================================== // Forwards @@ -184,11 +185,10 @@ public: QString name; int type; QVector<ControlledItem> ctrldElems; - // As per QT3DS-2992 we currently need only a single key-value pair per datainput. - // For efficiency we use separate QStrings for both, as there is no need for more - // elaborate containers. - QString metaDataKey; - QString metaData; + + // On editor side we use just QStrings as metadata will be squashed into strings + // anyway when storing into UIA file. (Runtime uses QVariants.) + QHash<QString, QString> metadata; // Bindings in other subpresentations, of QMap format // QMultiMap<subpresentation_id, QPair<datatype, strict>>. diff --git a/src/Authoring/Studio/Application/DataInputDlg.cpp b/src/Authoring/Studio/Application/DataInputDlg.cpp index 9bfec2a0..53b07d26 100644 --- a/src/Authoring/Studio/Application/DataInputDlg.cpp +++ b/src/Authoring/Studio/Application/DataInputDlg.cpp @@ -44,8 +44,7 @@ CDataInputDlg::CDataInputDlg(CDataInputDialogItem **datainput, QStandardItemMode , m_type(0) , m_min(0.0) , m_max(10.0) - , m_metadataKey(m_dataInput->metaDataKey) - , m_metadata(m_dataInput->metaData) + , m_metadata(m_dataInput->metadata) , m_acceptedTypes(acceptedTypes) { m_ui->setupUi(this); @@ -89,11 +88,15 @@ CDataInputDlg::CDataInputDlg(CDataInputDialogItem **datainput, QStandardItemMode static_cast<void(QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged), this, &CDataInputDlg::onMaxChanged); connect(m_ui->lineEditInputName, &QLineEdit::textChanged, this, &CDataInputDlg::onNameChanged); - connect(m_ui->lineEditEvaluation, &QLineEdit::textChanged, this, &CDataInputDlg::onTextChanged); - connect(m_ui->lineEditMetadata, &QLineEdit::textChanged, this, - &CDataInputDlg::onMetadataChanged); - connect(m_ui->lineEditMetadataKey, &QLineEdit::textChanged, this, - &CDataInputDlg::onMetadataKeyChanged); + connect(m_ui->pushButtonAddMeta, &QPushButton::clicked, this, &CDataInputDlg::onMetadataAdded); + connect(m_ui->tableEditMetadata, &QTableWidget::itemDoubleClicked, this, + [this](QTableWidgetItem *item) { + m_ui->lineEditMetadataKey->setText(m_ui->tableEditMetadata->item(item->row(), 0)->text()); + m_ui->lineEditMetadata->setText(m_ui->tableEditMetadata->item(item->row(), 1)->text()); + m_metadataEdit = true; + m_editMetadataKey = m_ui->tableEditMetadata->item(item->row(), 0)->text(); + m_ui->lineEditMetadataKey->setFocus(); + }); } CDataInputDlg::~CDataInputDlg() @@ -105,7 +108,10 @@ void CDataInputDlg::initDialog() { // Disallow special characters and whitespaces QRegExpValidator *rxp = new QRegExpValidator(QRegExp("[A-Za-z0-9_]+"), this); + QRegExpValidator *rxpWsOk = new QRegExpValidator(QRegExp("[A-Za-z0-9_ ]+"), this); m_ui->lineEditInputName->setValidator(rxp); + m_ui->lineEditMetadataKey->setValidator(rxp); + m_ui->lineEditMetadata->setValidator(rxpWsOk); if (!m_dataInput->name.isEmpty()) { m_name = m_dataInput->name; @@ -134,20 +140,23 @@ void CDataInputDlg::initDialog() m_ui->doubleSpinBoxMax->setValue(m_dataInput->maxValue); } - m_metadata = m_dataInput->metaData; - m_metadataKey = m_dataInput->metaDataKey; - m_ui->lineEditMetadata->setText(m_metadata); - m_ui->lineEditMetadataKey->setText(m_metadataKey); + m_metadata = m_dataInput->metadata; + // Removes focus dotted border, does not disable double-click + // to start editing an entry. + m_ui->tableEditMetadata->setFocusPolicy(Qt::NoFocus); + m_ui->tableEditMetadata->setRowCount(m_metadata.size()); + m_ui->tableEditMetadata->setColumnCount(3); + m_ui->tableEditMetadata->setColumnWidth(0, 150); + m_ui->tableEditMetadata->setColumnWidth(1, 280); + m_ui->tableEditMetadata->setColumnWidth(2, 30); + m_ui->tableEditMetadata->setEditTriggers(QAbstractItemView::NoEditTriggers); + + populateMetadata(); updateVisibility(m_dataInput->type); } void CDataInputDlg::accept() { - if (m_metadataKey.isEmpty() && !m_metadata.isEmpty()) { - Qt3DSMessageBox::Show(tr("Metadata Error"), tr("Metadata key cannot be empty."), - Qt3DSMessageBox::ICON_WARNING, false, this); - return; - } if (m_dataInput->name != m_name) m_dataInput->name = getUniqueId(m_name); @@ -161,8 +170,8 @@ void CDataInputDlg::accept() m_dataInput->valueString = m_text; } #endif - m_dataInput->metaData = m_metadata; - m_dataInput->metaDataKey = m_metadataKey; + m_dataInput->metadata = m_metadata; + QDialog::accept(); } @@ -194,25 +203,33 @@ void CDataInputDlg::onNameChanged(const QString &name) m_ui->lineEditInputName->setCursorPosition(cursorPos); } -void CDataInputDlg::onTextChanged(const QString &text) +void CDataInputDlg::onMetadataAdded() { - m_text = text; -} + auto key = m_ui->lineEditMetadataKey->text(); + auto metadata = m_ui->lineEditMetadata->text(); + // Let's allow empty metadata because it might have significance to + // metadata user + if (key.isEmpty()) { + Qt3DSMessageBox::Show(tr("Metadata Error"), tr("Metadata key cannot be empty."), + Qt3DSMessageBox::ICON_WARNING, false, this); + return; + } -void CDataInputDlg::onMetadataChanged(const QString &metadata) -{ - int cursorPos = m_ui->lineEditMetadata->cursorPosition(); - m_metadata = metadata; - m_ui->lineEditMetadata->setText(metadata); - m_ui->lineEditMetadata->setCursorPosition(cursorPos); -} + // We are editing an existing key - value, remove old entry + if (m_metadataEdit) { + m_metadata.remove(m_editMetadataKey); + m_metadataEdit = false; + m_editMetadataKey.clear(); + } -void CDataInputDlg::onMetadataKeyChanged(const QString &metadataKey) -{ - int cursorPos = m_ui->lineEditMetadataKey->cursorPosition(); - m_metadataKey = metadataKey; - m_ui->lineEditMetadataKey->setText(metadataKey); - m_ui->lineEditMetadataKey->setCursorPosition(cursorPos); + m_metadata.insert(key, metadata); + m_ui->tableEditMetadata->setRowCount(m_metadata.size()); + m_ui->lineEditMetadata->clear(); + m_ui->lineEditMetadataKey->clear(); + + // Let's update all entries since we do not know if QHash::insert() replaced an existing + // entry of just appended a new one. + populateMetadata(); } QString CDataInputDlg::getUniqueId(const QString &id) @@ -247,9 +264,6 @@ void CDataInputDlg::updateVisibility(int type) m_ui->lineEditEvaluation->setVisible(false); m_ui->labelEvaluation->setVisible(false); } -#else - m_ui->lineEditEvaluation->setVisible(false); - m_ui->labelEvaluation->setVisible(false); #endif // Adjust text label positioning according to the // visibility of info text warning about allowed datatypes. @@ -262,6 +276,23 @@ void CDataInputDlg::updateVisibility(int type) } } +void CDataInputDlg::keyPressEvent(QKeyEvent *e) +{ + // If we are editing metadata entry, grab ESC event and clear text fields. + // Also get out of editing existing metadata entry -mode without saving changes. + if (e->key() == Qt::Key_Escape) { + if (m_ui->lineEditMetadata->hasFocus() || m_ui->lineEditMetadataKey->hasFocus()) { + m_ui->lineEditMetadata->clear(); + m_ui->lineEditMetadataKey->clear(); + m_metadataEdit = false; + // Return focus to main dialog to allow it to receive ESC events. + this->setFocus(); + return; + } + } + QDialog::keyPressEvent(e); +} + const bool CDataInputDlg::isEquivalentDataType(int dlgType, qt3dsdm::DataModelDataType::Value dmType, bool strict) @@ -305,3 +336,26 @@ QVector<EDataType> CDataInputDlg::getAcceptedTypes(qt3dsdm::DataModelDataType::V } return acceptedTypes; } + +void CDataInputDlg::populateMetadata() +{ + static const QIcon trashIcon = QIcon(":/images/Action-Trash-Normal.png"); + m_ui->tableEditMetadata->clearContents(); + QHashIterator<QString, QString> i(m_metadata); + int currRow = 0; + while (i.hasNext()) { + i.next(); + QTableWidgetItem *key = new QTableWidgetItem(i.key()); + QTableWidgetItem *metadata = new QTableWidgetItem(i.value()); + m_ui->tableEditMetadata->setItem(currRow, 0, key); + m_ui->tableEditMetadata->setItem(currRow, 1, metadata); + QPushButton *delButton = new QPushButton(trashIcon, {}, nullptr); + + m_ui->tableEditMetadata->setCellWidget(currRow, 2, delButton); + connect(delButton, &QPushButton::clicked, this, [this, i]{ + m_metadata.remove(i.key()); + populateMetadata(); + }); + ++currRow; + } +} diff --git a/src/Authoring/Studio/Application/DataInputDlg.h b/src/Authoring/Studio/Application/DataInputDlg.h index 49593cd4..d9fb0fcf 100644 --- a/src/Authoring/Studio/Application/DataInputDlg.h +++ b/src/Authoring/Studio/Application/DataInputDlg.h @@ -30,6 +30,10 @@ #define DATAINPUTDLG_H #include <QtWidgets/qdialog.h> +#include <QtWidgets/QTableWidgetItem> +#include <QtWidgets/QTableWidget> +#include <QtCore/qhash.h> +#include <QKeyEvent> #include "Doc.h" #include "Qt3DSDMDataTypes.h" @@ -91,6 +95,7 @@ protected: void initDialog(); QString getUniqueId(const QString &id); void updateVisibility(int type); + void keyPressEvent(QKeyEvent *e) override; private Q_SLOTS: void accept() override; @@ -98,11 +103,11 @@ private Q_SLOTS: void onMinChanged(float min); void onMaxChanged(float max); void onNameChanged(const QString &name); - void onTextChanged(const QString &text); - void onMetadataChanged(const QString &metadata); - void onMetadataKeyChanged(const QString &metadataKey); + void onMetadataAdded(); private: + void populateMetadata(); + Ui::DataInputDlg *m_ui; CDataInputDialogItem *m_dataInput; QStandardItemModel *m_data; @@ -110,10 +115,10 @@ private: float m_max; float m_min; int m_type; - QString m_text; - QString m_metadataKey; - QString m_metadata; + QHash<QString, QString> m_metadata; QVector<EDataType> m_acceptedTypes; + bool m_metadataEdit = false; // are we editing existing metadata? + QString m_editMetadataKey; // original metadata key now being edited }; #endif diff --git a/src/Authoring/Studio/Application/DataInputDlg.ui b/src/Authoring/Studio/Application/DataInputDlg.ui index 982e2d4f..d75db475 100644 --- a/src/Authoring/Studio/Application/DataInputDlg.ui +++ b/src/Authoring/Studio/Application/DataInputDlg.ui @@ -7,7 +7,7 @@ <x>0</x> <y>0</y> <width>533</width> - <height>300</height> + <height>307</height> </rect> </property> <property name="windowTitle"> @@ -71,7 +71,7 @@ <item> <widget class="QLabel" name="labelNodeName"> <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> @@ -85,6 +85,9 @@ <property name="text"> <string>Name</string> </property> + <property name="alignment"> + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> + </property> </widget> </item> <item> @@ -93,22 +96,28 @@ <enum>Qt::Vertical</enum> </property> <property name="sizeType"> - <enum>QSizePolicy::Preferred</enum> + <enum>QSizePolicy::Expanding</enum> </property> <property name="sizeHint" stdset="0"> <size> <width>20</width> - <height>18</height> + <height>9</height> </size> </property> </spacer> </item> <item> <widget class="QLabel" name="labelNodeType"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> <property name="minimumSize"> <size> <width>90</width> - <height>24</height> + <height>20</height> </size> </property> <property name="text"> @@ -117,61 +126,6 @@ </widget> </item> <item> - <spacer name="verticalSpacer_2"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeType"> - <enum>QSizePolicy::Expanding</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>14</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QLabel" name="labelMetadataKey"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>24</height> - </size> - </property> - <property name="text"> - <string>Metadata Key</string> - </property> - </widget> - </item> - <item> - <widget class="QLabel" name="labelMetadata"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>24</height> - </size> - </property> - <property name="text"> - <string>Metadata</string> - </property> - </widget> - </item> - <item> - <widget class="QLabel" name="labelEvaluation"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>24</height> - </size> - </property> - <property name="text"> - <string>Evaluation</string> - </property> - </widget> - </item> - <item> <widget class="QLabel" name="labelMin"> <property name="minimumSize"> <size> @@ -206,19 +160,6 @@ </property> </widget> </item> - <item> - <spacer name="verticalSpacer_4"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>15</height> - </size> - </property> - </spacer> - </item> </layout> </widget> </item> @@ -274,40 +215,6 @@ </widget> </item> <item> - <spacer name="verticalSpacer"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>40</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QLineEdit" name="lineEditMetadataKey"> - <property name="toolTip"> - <string>Key for accessing the metadata for this Data Input</string> - </property> - </widget> - </item> - <item> - <widget class="QLineEdit" name="lineEditMetadata"> - <property name="toolTip"> - <string>Metadata associated with this Data Input</string> - </property> - </widget> - </item> - <item> - <widget class="QLineEdit" name="lineEditEvaluation"> - <property name="toolTip"> - <string/> - </property> - </widget> - </item> - <item> <widget class="QDoubleSpinBox" name="doubleSpinBoxMin"> <property name="toolTip"> <string>The minimum value for the number</string> @@ -336,19 +243,6 @@ </property> </widget> </item> - <item> - <spacer name="verticalSpacer_3"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>40</height> - </size> - </property> - </spacer> - </item> </layout> </widget> </item> @@ -356,6 +250,126 @@ </widget> </item> <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <layout class="QGridLayout" name="gridLayout"> + <property name="sizeConstraint"> + <enum>QLayout::SetMaximumSize</enum> + </property> + <item row="1" column="0"> + <widget class="QLineEdit" name="lineEditMetadata"> + <property name="text"> + <string/> + </property> + <property name="placeholderText"> + <string>Metadata value</string> + </property> + </widget> + </item> + <item row="0" column="0"> + <widget class="QLineEdit" name="lineEditMetadataKey"> + <property name="text"> + <string/> + </property> + <property name="placeholderText"> + <string>Metadata key</string> + </property> + </widget> + </item> + <item row="0" column="1" rowspan="2"> + <widget class="QPushButton" name="pushButtonAddMeta"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>1</verstretch> + </sizepolicy> + </property> + <property name="toolTip"> + <string>Enter metadata</string> + </property> + <property name="text"> + <string>OK</string> + </property> + </widget> + </item> + <item row="3" column="0" colspan="2"> + <widget class="QTableWidget" name="tableEditMetadata"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>5</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>78</height> + </size> + </property> + <property name="baseSize"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + <property name="toolTip"> + <string>Metadata key - value pairs. Double-click to edit.</string> + </property> + <property name="sizeAdjustPolicy"> + <enum>QAbstractScrollArea::AdjustIgnored</enum> + </property> + <property name="alternatingRowColors"> + <bool>false</bool> + </property> + <property name="selectionMode"> + <enum>QAbstractItemView::NoSelection</enum> + </property> + <property name="selectionBehavior"> + <enum>QAbstractItemView::SelectRows</enum> + </property> + <property name="showGrid"> + <bool>false</bool> + </property> + <attribute name="horizontalHeaderVisible"> + <bool>false</bool> + </attribute> + <attribute name="horizontalHeaderDefaultSectionSize"> + <number>75</number> + </attribute> + <attribute name="horizontalHeaderHighlightSections"> + <bool>false</bool> + </attribute> + <attribute name="horizontalHeaderStretchLastSection"> + <bool>true</bool> + </attribute> + <attribute name="verticalHeaderVisible"> + <bool>false</bool> + </attribute> + <attribute name="verticalHeaderHighlightSections"> + <bool>false</bool> + </attribute> + </widget> + </item> + </layout> + </item> + <item> <widget class="QWidget" name="widget_3" native="true"> <layout class="QHBoxLayout" name="horizontalLayout_2"> <property name="leftMargin"> diff --git a/src/Authoring/Studio/Application/ProjectFile.cpp b/src/Authoring/Studio/Application/ProjectFile.cpp index ebec8b53..953a0226 100644 --- a/src/Authoring/Studio/Application/ProjectFile.cpp +++ b/src/Authoring/Studio/Application/ProjectFile.cpp @@ -495,8 +495,25 @@ void ProjectFile::parseDataInputElem(const QDomElement &elem, item->valueString = elem.attribute(QStringLiteral("evaluator")); } #endif - item->metaDataKey = elem.attribute((QStringLiteral("metadatakey"))); - item->metaData = elem.attribute((QStringLiteral("metadata"))); + + auto metadata = elem.attribute(QStringLiteral("metadata")); + 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(item->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(item->name)); + break; + } + item->metadata.insert(metadataList[i], metadataList[i+1]); + } + } + } dataInputs.insert(item->name, item); } } diff --git a/src/Authoring/Studio/Application/StudioApp.cpp b/src/Authoring/Studio/Application/StudioApp.cpp index 8ce3d6c0..44127bdc 100644 --- a/src/Authoring/Studio/Application/StudioApp.cpp +++ b/src/Authoring/Studio/Application/StudioApp.cpp @@ -1791,13 +1791,17 @@ void CStudioApp::saveDataInputsToProjectFile() diNode.setAttribute(QStringLiteral("evaluator"), item->valueString); } #endif - // Let's allow storing key even if actual metadata is empty, as we - // do not know how the user code is going to interpret metadata contents. - if (!item->metaDataKey.isEmpty()) { - diNode.setAttribute(QStringLiteral("metadatakey"), item->metaDataKey); - if (!item->metaData.isEmpty()) - diNode.setAttribute(QStringLiteral("metadata"), item->metaData); + + QHashIterator<QString, QString> it(item->metadata); + QString metadataStr; + while (it.hasNext()) { + it.next(); + metadataStr.append(it.key() + QLatin1Char('$') + it.value() + QLatin1Char('$')); } + metadataStr.chop(1); + + diNode.setAttribute(QStringLiteral("metadata"), metadataStr.trimmed()); + assetsNode.appendChild(diNode); } StudioUtils::commitDomDocumentSave(file, doc); diff --git a/src/Authoring/Studio/style.qss b/src/Authoring/Studio/style.qss index 0636e49c..e26785c0 100644 --- a/src/Authoring/Studio/style.qss +++ b/src/Authoring/Studio/style.qss @@ -435,6 +435,17 @@ QDialog#DataInputDlg QComboBox QAbstractItemView::item:disabled { color: #727476; } +QDialog#DataInputDlg QTableView { + selection-background-color: #46a2da; + gridline-color: transparent; + border: 1px solid #808080; + background-color: transparent; +} + +QDialog#DataInputDlg QTableView::item:selected { + background-color: #46a2da; +} + /* QSlider horizontal */ QSlider { background: transparent; |