diff options
Diffstat (limited to 'src/Authoring/Studio/Palettes')
12 files changed, 956 insertions, 6 deletions
diff --git a/src/Authoring/Studio/Palettes/Inspector/InspectorControlModel.cpp b/src/Authoring/Studio/Palettes/Inspector/InspectorControlModel.cpp index d4fdc306..1232939c 100644 --- a/src/Authoring/Studio/Palettes/Inspector/InspectorControlModel.cpp +++ b/src/Authoring/Studio/Palettes/Inspector/InspectorControlModel.cpp @@ -62,6 +62,7 @@ #include "foundation/Qt3DSLogging.h" #include "Dialogs.h" #include "Dispatch.h" +#include "VariantsGroupModel.h" static QStringList renderableItems() { @@ -107,8 +108,9 @@ static std::pair<bool, bool> getSlideCharacteristics(qt3dsdm::Qt3DSDMInstanceHan return std::make_pair(hasNextSlide, hasPreviousSlide); } -InspectorControlModel::InspectorControlModel(QObject *parent) - : QAbstractListModel(parent) +InspectorControlModel::InspectorControlModel(VariantsGroupModel *variantsModel, QObject *parent) + : m_variantsModel(variantsModel) + , QAbstractListModel(parent) , m_UpdatableEditor(*g_StudioApp.GetCore()->GetDoc()) { m_modifiedProperty.first = 0; @@ -1229,7 +1231,6 @@ void InspectorControlModel::updatePropertyValue(InspectorControlBase *element) c metaDataProvider->GetMetaDataProperty(instance, element->m_property)); } - bool skipEmits = false; switch (element->m_dataType) { case qt3dsdm::DataModelDataType::String: { @@ -1239,6 +1240,10 @@ void InspectorControlModel::updatePropertyValue(InspectorControlBase *element) c if (index != -1) stringValue = stringValue.mid(index + 1); } + + if (bridge->IsLayerInstance(instance)) + m_variantsModel->refresh(); + element->m_value = stringValue; } // intentional fall-through for other String-derived datatypes case qt3dsdm::DataModelDataType::StringOrInt: diff --git a/src/Authoring/Studio/Palettes/Inspector/InspectorControlModel.h b/src/Authoring/Studio/Palettes/Inspector/InspectorControlModel.h index e329dba1..21e6b3a7 100644 --- a/src/Authoring/Studio/Palettes/Inspector/InspectorControlModel.h +++ b/src/Authoring/Studio/Palettes/Inspector/InspectorControlModel.h @@ -42,6 +42,7 @@ class CInspectableBase; class Qt3DSDMInspectable; class SGuideInspectableImpl; +class VariantsGroupModel; namespace qt3dsdm { class ISignalConnection; @@ -107,7 +108,7 @@ class InspectorControlModel : public QAbstractListModel { Q_OBJECT public: - explicit InspectorControlModel(QObject *parent); + explicit InspectorControlModel(VariantsGroupModel *variantsModel, QObject *parent); ~InspectorControlModel() = default; enum Roles { @@ -247,6 +248,8 @@ private: bool isGroupRebuildRequired(CInspectableBase *inspectable, int theIndex) const; static int handleToGuidePropIndex(int handle) { return handle - 1; } + + VariantsGroupModel *m_variantsModel = nullptr; }; #endif // INSPECTORCONTROLMODEL_H diff --git a/src/Authoring/Studio/Palettes/Inspector/InspectorControlView.cpp b/src/Authoring/Studio/Palettes/Inspector/InspectorControlView.cpp index 69543a12..6252c0ea 100644 --- a/src/Authoring/Studio/Palettes/Inspector/InspectorControlView.cpp +++ b/src/Authoring/Studio/Palettes/Inspector/InspectorControlView.cpp @@ -58,6 +58,8 @@ #include "MaterialRefView.h" #include "BasicObjectsModel.h" #include "Qt3DSDMSlides.h" +#include "VariantsGroupModel.h" +#include "VariantTagDialog.h" #include <QtCore/qtimer.h> #include <QtQml/qqmlcontext.h> @@ -69,7 +71,8 @@ InspectorControlView::InspectorControlView(const QSize &preferredSize, QWidget *parent) : QQuickWidget(parent), TabNavigable(), - m_inspectorControlModel(new InspectorControlModel(this)), + m_variantsGroupModel(new VariantsGroupModel(this)), + m_inspectorControlModel(new InspectorControlModel(m_variantsGroupModel, this)), m_meshChooserView(new MeshChooserView(this)), m_instance(0), m_handle(0), @@ -241,6 +244,7 @@ void InspectorControlView::initialize() CStudioPreferences::setQmlContextProperties(rootContext()); rootContext()->setContextProperty(QStringLiteral("_parentView"), this); rootContext()->setContextProperty(QStringLiteral("_inspectorModel"), m_inspectorControlModel); + rootContext()->setContextProperty(QStringLiteral("_variantsGroupModel"), m_variantsGroupModel); rootContext()->setContextProperty(QStringLiteral("_resDir"), StudioUtils::resourceImageUrl()); rootContext()->setContextProperty(QStringLiteral("_tabOrderHandler"), tabOrderHandler()); rootContext()->setContextProperty(QStringLiteral("_mouseHelper"), &m_mouseHelper); @@ -412,6 +416,8 @@ void InspectorControlView::setInspectable(CInspectableBase *inInspectable) m_inspectorControlModel->setInspectable(inInspectable); Q_EMIT titleChanged(); + + m_variantsGroupModel->refresh(); } } @@ -452,6 +458,62 @@ void InspectorControlView::showContextMenu(int x, int y, int handle, int instanc m_handle = 0; } +void InspectorControlView::showTagContextMenu(int x, int y, const QString &group, + const QString &tag) +{ + QMenu theContextMenu; + + auto actionRename = theContextMenu.addAction(QObject::tr("Rename Tag")); + connect(actionRename, &QAction::triggered, this, [&]() { + VariantTagDialog dlg(VariantTagDialog::RenameTag, group, tag); + if (dlg.exec() == QDialog::Accepted) { + g_StudioApp.GetCore()->getProjectFile().renameVariantTag(group, dlg.getNames().first, + dlg.getNames().second); + } + }); + + auto actionDelete = theContextMenu.addAction(QObject::tr("Delete Tag")); + connect(actionDelete, &QAction::triggered, this, [&]() { + g_StudioApp.GetCore()->getProjectFile().deleteVariantTag(group, tag); + }); + + theContextMenu.exec(mapToGlobal({x, y})); +} + +void InspectorControlView::showGroupContextMenu(int x, int y, const QString &group) +{ + QMenu theContextMenu; + + ProjectFile &projectFile = g_StudioApp.GetCore()->getProjectFile(); + + auto actionRename = theContextMenu.addAction(QObject::tr("Rename Group")); + connect(actionRename, &QAction::triggered, this, [&]() { + VariantTagDialog dlg(VariantTagDialog::RenameGroup, {}, group); + if (dlg.exec() == QDialog::Accepted) { + projectFile.renameVariantGroup(dlg.getNames().first, dlg.getNames().second); + } + }); + + auto actionColor = theContextMenu.addAction(QObject::tr("Change Group Color")); + connect(actionColor, &QAction::triggered, this, [&]() { + const auto variantsDef = g_StudioApp.GetCore()->getProjectFile().variantsDef(); + for (auto &g : variantsDef) { + if (g.m_title == group) { + QColor newColor = this->showColorDialog(g.m_color); + projectFile.changeVariantGroupColor(group, newColor.name()); + break; + } + } + }); + + auto actionDelete = theContextMenu.addAction(QObject::tr("Delete Group")); + connect(actionDelete, &QAction::triggered, this, [&]() { + projectFile.deleteVariantGroup(group); + }); + + theContextMenu.exec(mapToGlobal({x, y})); +} + void InspectorControlView::toggleMasterLink() { Q3DStudio::ScopedDocumentEditor editor(*g_StudioApp.GetCore()->GetDoc(), diff --git a/src/Authoring/Studio/Palettes/Inspector/InspectorControlView.h b/src/Authoring/Studio/Palettes/Inspector/InspectorControlView.h index 98d67f41..14936b57 100644 --- a/src/Authoring/Studio/Palettes/Inspector/InspectorControlView.h +++ b/src/Authoring/Studio/Palettes/Inspector/InspectorControlView.h @@ -39,6 +39,7 @@ #include "DataInputSelectView.h" class InspectorControlModel; +class VariantsGroupModel; class CInspectableBase; class ImageChooserView; class DataInputSelectView; @@ -72,6 +73,8 @@ public: QString titleIcon() const; Q_INVOKABLE void showContextMenu(int x, int y, int handle, int instance); + Q_INVOKABLE void showTagContextMenu(int x, int y, const QString &group, const QString &tag); + Q_INVOKABLE void showGroupContextMenu(int x, int y, const QString &group); Q_INVOKABLE QObject *showImageChooser(int handle, int instance, const QPoint &point); Q_INVOKABLE QObject *showFilesChooser(int handle, int instance, const QPoint &point); Q_INVOKABLE QObject *showMeshChooser(int handle, int instance, const QPoint &point); @@ -126,6 +129,7 @@ private: std::vector<std::shared_ptr<qt3dsdm::ISignalConnection>> m_connections; QColor m_backgroundColor; + VariantsGroupModel *m_variantsGroupModel = nullptr; InspectorControlModel *m_inspectorControlModel = nullptr; CInspectableBase *m_inspectableBase = nullptr; QPointer<ImageChooserView> m_imageChooserView; diff --git a/src/Authoring/Studio/Palettes/Inspector/InspectorControlView.qml b/src/Authoring/Studio/Palettes/Inspector/InspectorControlView.qml index b2e8b286..833bbd65 100644 --- a/src/Authoring/Studio/Palettes/Inspector/InspectorControlView.qml +++ b/src/Authoring/Studio/Palettes/Inspector/InspectorControlView.qml @@ -28,6 +28,8 @@ import QtQuick 2.8 import QtQuick.Layouts 1.1 import QtQuick.Controls 2.2 +import QtQuick.Controls.Styles 1.4 +import QtQuick.Extras 1.4 import Qt3DStudio 1.0 import "../controls" @@ -286,6 +288,7 @@ Rectangle { ColumnLayout { // Property row and datainput control Layout.alignment: Qt.AlignTop + visible: modelData.title !== "variants" spacing: 0 RowLayout { // Property row Layout.alignment: Qt.AlignLeft @@ -315,7 +318,7 @@ Rectangle { anchors.fill: parent acceptedButtons: Qt.RightButton | Qt.LeftButton hoverEnabled: true - onClicked: { + onClicked: { if (mouse.button === Qt.LeftButton) { _inspectorModel.setPropertyAnimated( model.modelData.instance, @@ -423,6 +426,9 @@ Rectangle { opacity: enabled ? 1 : .5 Layout.alignment: Qt.AlignTop sourceComponent: { + if (modelData.title === "variants") + return variantTagsComponent; + const dataType = modelData.dataType; switch (dataType) { case DataModelDataType.Long: @@ -1098,4 +1104,154 @@ Rectangle { } } } + + Component { + id: variantTagsComponent + + Column { + width: root.width - 10 + spacing: 10 + + Row { + anchors.right: parent.right + anchors.rightMargin: 5 + spacing: 5 + + ToolButton { + id: importButton + text: qsTr("Import...") + width: 70 + height: 20 + + onClicked: { + // TODO: implement + } + } + + ToolButton { + id: exportButton + text: qsTr("Export...") + width: 70 + height: 20 + + onClicked: { + // TODO: implement + } + } + } + + Text { + text: qsTr("There are no variant tags yet. Click [+ Group] to add a new tag group and start adding tags.") + color: "#ffffff" + visible: _variantsGroupModel.rowCount() === 0 + } + + Repeater { + id: tagsReeater + model: _variantsGroupModel + + Row { + id: variantTagsRow + + readonly property var tagsModel: model.tags + readonly property var groupModel: model + + Text { + text: model.group + color: model.color + width: 50 + anchors.top: parent.top + anchors.topMargin: 5 + + MouseArea { + anchors.fill: parent; + acceptedButtons: Qt.RightButton + onClicked: { + if (mouse.button === Qt.RightButton) { + const coords = mapToItem(root, mouse.x, mouse.y); + _parentView.showGroupContextMenu(coords.x, coords.y, model.group); + } + } + } + } + + Flow { + width: root.width - 110 + spacing: 5 + + Repeater { + model: tagsModel + + Loader { + readonly property var tagsModel: model + readonly property var grpModel: groupModel + sourceComponent: tagComponent + } + } + + ToolButton { + id: addTagButton + text: qsTr("+ Tag") + height: 25 + + onClicked: { + _variantsGroupModel.addNewTag(groupModel.group) + } + + } + } + } + } + + Item { width: 1; height: 5 } // vertical spacer + + ToolButton { + id: addGroupButton + text: qsTr("+ Group") + width: 60 + height: 25 + onClicked: { + _variantsGroupModel.addNewGroup() + } + } + + Item { width: 1; height: 5 } // vertical spacer + } + } + + Component { + id: tagComponent + + Rectangle { + property bool toggled: tagsModel.selected + property string grpColor: grpModel ? grpModel.color : "" + + width: Math.max(tLabel.width + 10, 60) + height: 25 + color: toggled ? grpColor : "#2e2f30" + border.color: "#959596" + + Text { + id: tLabel + anchors.centerIn: parent + text: tagsModel.tag + color: toggled ? "#ffffff" : "#959596" + } + + MouseArea { + anchors.fill: parent; + acceptedButtons: Qt.RightButton | Qt.LeftButton + onClicked: { + if (mouse.button === Qt.LeftButton) { + toggled = !toggled; + _variantsGroupModel.setTagState(grpModel.group, tagsModel.tag, toggled); + } else if (mouse.button === Qt.RightButton) { + const coords = mapToItem(root, mouse.x, mouse.y); + _parentView.showTagContextMenu(coords.x, coords.y, grpModel.group, + tagsModel.tag); + } + } + } + } + } } diff --git a/src/Authoring/Studio/Palettes/Inspector/VariantTagDialog.cpp b/src/Authoring/Studio/Palettes/Inspector/VariantTagDialog.cpp new file mode 100644 index 00000000..83e72e7b --- /dev/null +++ b/src/Authoring/Studio/Palettes/Inspector/VariantTagDialog.cpp @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "VariantTagDialog.h" +#include "ui_VariantTagDialog.h" +#include "Dialogs.h" +#include "StudioApp.h" +#include "Core.h" +#include "ProjectFile.h" + +VariantTagDialog::VariantTagDialog(DialogType type, const QString &group, const QString &name, + QWidget *parent) + : QDialog(parent) + , m_type(type) + , m_group(group) + , m_ui(new Ui::VariantTagDialog) +{ + m_ui->setupUi(this); + + m_names.first = name; + + if (type == AddGroup) { + setWindowTitle(tr("Add new Group")); + m_ui->label->setText(tr("Group name")); + } else if (type == RenameGroup) { + setWindowTitle(tr("Rename Group")); + m_ui->label->setText(tr("Group name")); + m_ui->lineEditTagName->setText(name); + m_ui->lineEditTagName->selectAll(); + } else if (type == RenameTag) { + m_ui->lineEditTagName->setText(name); + m_ui->lineEditTagName->selectAll(); + } +} + +void VariantTagDialog::accept() +{ + QString name = m_ui->lineEditTagName->text(); + + if (name.isEmpty()) { + displayWarning(EmptyWarning); + } else if (name == m_names.first) { // no change + QDialog::reject(); + } else if (((m_type == AddGroup || m_type == RenameGroup) + && !g_StudioApp.GetCore()->getProjectFile().isVariantGroupUnique(name)) + || (!g_StudioApp.GetCore()->getProjectFile().isVariantTagUnique(m_group, name))) { + displayWarning(UniqueWarning); + } else { + m_names.second = name; + QDialog::accept(); + } +} + +std::pair<QString, QString> VariantTagDialog::getNames() const +{ + return m_names; +} + +void VariantTagDialog::displayWarning(WarningType warningType) +{ + QString warning; + if (warningType == EmptyWarning) { + if (m_type == AddGroup || m_type == RenameGroup) + warning = tr("The group name must not be empty."); + else + warning = tr("The tag name must not be empty."); + } else if (warningType == UniqueWarning) { + if (m_type == AddGroup || m_type == RenameGroup) + warning = tr("The group name must be unique."); + else + warning = tr("The tag name must be unique within the tag group."); + } + + g_StudioApp.GetDialogs()->DisplayMessageBox(tr("Warning"), warning, + Qt3DSMessageBox::ICON_WARNING, false); +} + +VariantTagDialog::~VariantTagDialog() +{ + delete m_ui; +} diff --git a/src/Authoring/Studio/Palettes/Inspector/VariantTagDialog.h b/src/Authoring/Studio/Palettes/Inspector/VariantTagDialog.h new file mode 100644 index 00000000..b5e3989f --- /dev/null +++ b/src/Authoring/Studio/Palettes/Inspector/VariantTagDialog.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef VARIANTTAGDIALOG_H +#define VARIANTTAGDIALOG_H + +#include <QtWidgets/qdialog.h> + +#ifdef QT_NAMESPACE +using namespace QT_NAMESPACE; +#endif + +QT_BEGIN_NAMESPACE +namespace Ui { +class VariantTagDialog; +} +QT_END_NAMESPACE + +class VariantTagDialog : public QDialog +{ + Q_OBJECT + +public: + enum DialogType { AddTag, RenameTag, AddGroup, RenameGroup }; + + explicit VariantTagDialog(DialogType type, const QString &group = {}, const QString &name = {}, + QWidget *parent = nullptr); + ~VariantTagDialog() override; + +public Q_SLOTS: + void accept() override; + std::pair<QString, QString> getNames() const; + +private: + enum WarningType { + EmptyWarning, + UniqueWarning + }; + + void displayWarning(WarningType warningType); + + DialogType m_type; + QString m_group; + Ui::VariantTagDialog *m_ui; + std::pair<QString, QString> m_names; // holds the tags values before and after rename +}; + +#endif // VARIANTTAGDIALOG_H diff --git a/src/Authoring/Studio/Palettes/Inspector/VariantTagDialog.ui b/src/Authoring/Studio/Palettes/Inspector/VariantTagDialog.ui new file mode 100644 index 00000000..aa5d24ef --- /dev/null +++ b/src/Authoring/Studio/Palettes/Inspector/VariantTagDialog.ui @@ -0,0 +1,113 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>VariantTagDialog</class> + <widget class="QDialog" name="VariantTagDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>241</width> + <height>89</height> + </rect> + </property> + <property name="windowTitle"> + <string>Add new Tag</string> + </property> + <property name="sizeGripEnabled"> + <bool>false</bool> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QWidget" name="widget" native="true"> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="QWidget" name="labelEditLayout" native="true"> + <layout class="QHBoxLayout" name="horizontalLayout" stretch="0"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Tag name</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QLineEdit" name="lineEditTagName"/> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>VariantTagDialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>VariantTagDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/src/Authoring/Studio/Palettes/Inspector/VariantsGroupModel.cpp b/src/Authoring/Studio/Palettes/Inspector/VariantsGroupModel.cpp new file mode 100644 index 00000000..3a2a2a45 --- /dev/null +++ b/src/Authoring/Studio/Palettes/Inspector/VariantsGroupModel.cpp @@ -0,0 +1,181 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "VariantsGroupModel.h" +#include "VariantsTagModel.h" +#include "StudioApp.h" +#include "Core.h" +#include "QDebug" // TODO: remove +#include "Qt3DSDMStudioSystem.h" +#include "ClientDataModelBridge.h" +#include "IDocumentEditor.h" +#include "VariantTagDialog.h" + +VariantsGroupModel::VariantsGroupModel(QObject *parent) + : QAbstractListModel(parent) +{ + +} + +void VariantsGroupModel::refresh() +{ + int instance = g_StudioApp.GetCore()->GetDoc()->GetSelectedInstance(); + auto bridge = g_StudioApp.GetCore()->GetDoc()->GetStudioSystem()->GetClientDataModelBridge(); + + if (instance == 0 || !bridge->IsLayerInstance(instance)) { + m_instance = 0; + m_property = 0; + return; + } + + auto propertySystem = g_StudioApp.GetCore()->GetDoc()->GetStudioSystem()->GetPropertySystem(); + m_instance = instance; + m_property = propertySystem->GetAggregateInstancePropertyByName(instance, L"variants"); + + qt3dsdm::SValue sValue; + if (propertySystem->GetInstancePropertyValue(m_instance, m_property, sValue)) { + beginResetModel(); + m_data.clear(); + + QString val = QString::fromWCharArray( + qt3dsdm::get<qt3dsdm::TDataStrPtr>(sValue)->GetData()); + // TODO: remove qDebug when the variants work is fully done. + qDebug() << "\x1b[42m \x1b[1m" << __FUNCTION__ + << ", val=" << val + << "\x1b[m"; + QHash<QString, QStringList> propTags; + if (!val.isEmpty()) { + const QStringList propTagsList = val.split(QChar(',')); + for (auto &propTag : propTagsList) { + const QStringList propTagPair = propTag.split(QChar(':')); + propTags[propTagPair[0]].append(propTagPair[1]); + } + } + + // build the variants data model + const auto variantsDef = g_StudioApp.GetCore()->getProjectFile().variantsDef(); + for (auto &group : variantsDef) { + TagGroupData g; + g.m_title = group.m_title; + g.m_color = group.m_color; + + VariantsTagModel *m = new VariantsTagModel(this); + QVector<std::pair<QString, bool> > tags; + for (int i = 0; i < group.m_tags.length(); ++i) + tags.append({group.m_tags[i], propTags[group.m_title].contains(group.m_tags[i])}); + + m->init(tags); + g.m_tagsModel = m; + + m_data.push_back(g); + } + + endResetModel(); + } +} + +int VariantsGroupModel::rowCount(const QModelIndex &parent) const +{ + // For list models only the root node (an invalid parent) should return the list's size. For all + // other (valid) parents, rowCount() should return 0 so that it does not become a tree model. + if (parent.isValid()) + return 0; + + return m_data.size(); +} + +QVariant VariantsGroupModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + if (role == GroupTitleRole) + return m_data.at(index.row()).m_title; + else if (role == GroupColorRole) + return m_data.at(index.row()).m_color; + else if (role == TagRole) + return QVariant::fromValue(m_data.at(index.row()).m_tagsModel); + + return QVariant(); +} + +void VariantsGroupModel::setTagState(const QString &group, const QString &tag, bool selected) +{ + QString val; + QString tagsStr; + bool skipFirst = false; + for (auto &g : qAsConst(m_data)) { + if (g.m_title == group) + g.m_tagsModel->updateTagState(tag, selected); + + tagsStr = g.m_tagsModel->serialize(g.m_title); + if (!tagsStr.isEmpty()) { + if (skipFirst) + val.append(QChar(',')); + val.append(tagsStr); + skipFirst = true; + } + } + + auto sVal = std::make_shared<qt3dsdm::CDataStr>(Q3DStudio::CString::fromQString(val)); + Q3DStudio::SCOPED_DOCUMENT_EDITOR(*g_StudioApp.GetCore()->GetDoc(), QObject::tr("Set Property")) + ->SetInstancePropertyValue(m_instance, m_property, sVal); +} + +void VariantsGroupModel::addNewTag(const QString &group) +{ + VariantTagDialog dlg(VariantTagDialog::AddTag, group); + + if (dlg.exec() == QDialog::Accepted) + g_StudioApp.GetCore()->getProjectFile().addVariantTag(group, dlg.getNames().second); +} + +void VariantsGroupModel::addNewGroup() +{ + VariantTagDialog dlg(VariantTagDialog::AddGroup); + + if (dlg.exec() == QDialog::Accepted) + g_StudioApp.GetCore()->getProjectFile().addVariantGroup(dlg.getNames().second); +} + +QHash<int, QByteArray> VariantsGroupModel::roleNames() const +{ + auto names = QAbstractListModel::roleNames(); + names.insert(GroupTitleRole, "group"); + names.insert(GroupColorRole, "color"); + names.insert(TagRole, "tags"); + return names; +} + +Qt::ItemFlags VariantsGroupModel::flags(const QModelIndex &index) const +{ + if (!index.isValid()) + return Qt::NoItemFlags; + + return Qt::ItemIsEditable; +} diff --git a/src/Authoring/Studio/Palettes/Inspector/VariantsGroupModel.h b/src/Authoring/Studio/Palettes/Inspector/VariantsGroupModel.h new file mode 100644 index 00000000..695e3fb0 --- /dev/null +++ b/src/Authoring/Studio/Palettes/Inspector/VariantsGroupModel.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef VARIANTSGROUPMODEL_H +#define VARIANTSGROUPMODEL_H + +#include <QtCore/qabstractitemmodel.h> + +class VariantsTagModel; + +class VariantsGroupModel : public QAbstractListModel +{ + Q_OBJECT + +public: + explicit VariantsGroupModel(QObject *parent = nullptr); + + enum Roles { + GroupTitleRole = Qt::UserRole + 1, + GroupColorRole, + TagRole + }; + + struct TagGroupData + { + QString m_title; + QString m_color; + VariantsTagModel *m_tagsModel = nullptr; + }; + + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role = GroupTitleRole) const override; + + Qt::ItemFlags flags(const QModelIndex& index) const override; + + void refresh(); + + Q_INVOKABLE void setTagState(const QString &group, const QString &tag, bool selected); + Q_INVOKABLE void addNewTag(const QString &group); + Q_INVOKABLE void addNewGroup(); + + +protected: + QHash<int, QByteArray> roleNames() const override; + +private: + QVector<TagGroupData> m_data; + int m_instance = 0; // selected layer instance + int m_property = 0; // variant tags property handler +}; + +#endif // VARIANTSGROUPMODEL_H diff --git a/src/Authoring/Studio/Palettes/Inspector/VariantsTagModel.cpp b/src/Authoring/Studio/Palettes/Inspector/VariantsTagModel.cpp new file mode 100644 index 00000000..910b4f09 --- /dev/null +++ b/src/Authoring/Studio/Palettes/Inspector/VariantsTagModel.cpp @@ -0,0 +1,108 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "VariantsTagModel.h" + +VariantsTagModel::VariantsTagModel(QObject *parent) + : QAbstractListModel(parent) +{ + +} + +void VariantsTagModel::init(const QVector<std::pair<QString, bool> > &data) +{ + m_data = data; +} + +void VariantsTagModel::updateTagState(const QString &tag, bool selected) +{ + for (auto &t : m_data) { + if (t.first == tag) { + t.second = selected; + break; + } + } +} + +// return the tags in a formatted string to be saved to the property +QString VariantsTagModel::serialize(const QString &groupName) const +{ + QString ret; + bool skipFirst = false; + for (auto &t : qAsConst(m_data)) { + if (t.second) { + if (skipFirst) + ret.append(QLatin1Char(',')); + + ret.append(groupName + QLatin1Char(':') + t.first); + + skipFirst = true; + } + } + + return ret; +} + +int VariantsTagModel::rowCount(const QModelIndex &parent) const +{ + // For list models only the root node (an invalid parent) should return the list's size. For all + // other (valid) parents, rowCount() should return 0 so that it does not become a tree model. + if (parent.isValid()) + return 0; + + return m_data.size(); +} + +QVariant VariantsTagModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + if (role == TagRole) + return m_data.at(index.row()).first; + else if (role == SelectedRole) + return m_data.at(index.row()).second; + + return QVariant(); +} + +QHash<int, QByteArray> VariantsTagModel::roleNames() const +{ + auto names = QAbstractListModel::roleNames(); + names.insert(TagRole, "tag"); + names.insert(SelectedRole, "selected"); + return names; +} + +Qt::ItemFlags VariantsTagModel::flags(const QModelIndex &index) const +{ + if (!index.isValid()) + return Qt::NoItemFlags; + + return Qt::ItemIsEditable; // FIXME: Implement me! +} diff --git a/src/Authoring/Studio/Palettes/Inspector/VariantsTagModel.h b/src/Authoring/Studio/Palettes/Inspector/VariantsTagModel.h new file mode 100644 index 00000000..01bb4e73 --- /dev/null +++ b/src/Authoring/Studio/Palettes/Inspector/VariantsTagModel.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef VARIANTSTAGMODEL_H +#define VARIANTSTAGMODEL_H + +#include <QtCore/qabstractitemmodel.h> + +class VariantsTagModel : public QAbstractListModel +{ + Q_OBJECT + +public: + explicit VariantsTagModel(QObject *parent = nullptr); + + enum Roles { + TagRole = Qt::UserRole + 1, + SelectedRole, + }; + + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role = TagRole) const override; + + Qt::ItemFlags flags(const QModelIndex& index) const override; + + void init(const QVector<std::pair<QString, bool> > &data); + void updateTagState(const QString &tag, bool selected); + QString serialize(const QString &groupName) const; + +protected: + QHash<int, QByteArray> roleNames() const override; + +private: + QVector<std::pair<QString, bool> > m_data; // [{tagName, selectedState}, ...] +}; + +#endif // VARIANTSTAGMODEL_H |