Sun, 13 Mar 2022 18:46:10 +0200
Handle properties in a generic manner in the object editor
CMakeLists.txt | file | annotate | diff | comparison | revisions | |
src/ui/objecteditor.cpp | file | annotate | diff | comparison | revisions | |
src/ui/objecteditor.h | file | annotate | diff | comparison | revisions | |
src/ui/polygonobjecteditor.cpp | file | annotate | diff | comparison | revisions | |
src/ui/polygonobjecteditor.h | file | annotate | diff | comparison | revisions |
--- a/CMakeLists.txt Sun Mar 13 14:53:14 2022 +0200 +++ b/CMakeLists.txt Sun Mar 13 18:46:10 2022 +0200 @@ -69,7 +69,6 @@ src/ui/canvas.cpp src/ui/multiplyfactordialog.cpp src/ui/objecteditor.cpp - src/ui/polygonobjecteditor.cpp src/widgets/colorbutton.cpp src/widgets/colorindexinput.cpp src/widgets/colorselectdialog.cpp @@ -129,7 +128,6 @@ src/ui/canvas.h src/ui/multiplyfactordialog.h src/ui/objecteditor.h - src/ui/polygonobjecteditor.h src/widgets/colorbutton.h src/widgets/colorindexinput.h src/widgets/colorselectdialog.h
--- a/src/ui/objecteditor.cpp Sun Mar 13 14:53:14 2022 +0200 +++ b/src/ui/objecteditor.cpp Sun Mar 13 18:46:10 2022 +0200 @@ -22,7 +22,6 @@ objectTypeNameLabel{new QLabel{this}}, objectTypeIconLabel{new QLabel{this}} { - this->polygonEditor.emplace(this->document, id); this->setLayout(new QVBoxLayout{this}); QWidget* objectTitleLayoutContainer = new QWidget{this}; QLayout* objectTitleLayout = new QHBoxLayout{objectTitleLayoutContainer}; @@ -31,31 +30,26 @@ objectTitleLayout->addWidget(this->objectTypeNameLabel); objectTitleLayout->addWidget(new QSplitter{Qt::Horizontal, this}); this->layout()->addWidget(objectTitleLayoutContainer); - this->layout()->addWidget(&*this->polygonEditor); this->layout()->addWidget(formContainer); this->setObjectId(id); - + QWidget* const parent = this->formContainer; QFormLayout* formLayout = new QFormLayout{parent}; this->formContainer->setLayout(formLayout); - QLabel* colorLabel = new QLabel{"Color", parent}; - ColorIndexInput* colorWidget = new ColorIndexInput{document, {0}, parent}; - formLayout->addRow(colorLabel, colorWidget); - connect(colorWidget, &ColorIndexInput::colorChanged, [this](ldraw::Color color) + + for (const ldraw::Property property : ldraw::ALL_PROPERTIES) { - const QModelIndex index = this->document->getModel().find(this->objectId); - if (index.isValid()) + QWidget* editorWidget = this->makeEditorWidgetForProperty(property); + if (editorWidget != nullptr) { - this->document->editModel()->modifyObjectAt<ldraw::ColoredObject>( - index.row(), - [color](ldraw::ColoredObject* object) - { - object->colorIndex = color; - } - ); + editorWidget->setProperty("_property_id", static_cast<int>(property)); + QLabel* propertyLabel = new QLabel{ldraw::traits(property).name.data()}; + formLayout->addRow(propertyLabel, editorWidget); + this->propertyWidgets[property] = {propertyLabel, editorWidget}; } - }); - this->propertyWidgets[ldraw::Property::Color] = {colorLabel, colorWidget}; + } + + this->setObjectId(ldraw::NULL_ID); } QString titleCase(const QString& string) @@ -63,34 +57,50 @@ return string.left(1).toUpper() + string.mid(1); } +void setValueToWidget(QWidget* widget, const QVariant& value) +{ + ColorIndexInput* colorIndexInput = qobject_cast<ColorIndexInput*>(widget); + if (colorIndexInput != nullptr) + { + colorIndexInput->setSelectedColor(value.value<ldraw::Color>()); + } + else + { + Vec3Editor* vec3Editor = qobject_cast<Vec3Editor*>(widget); + if (vec3Editor != nullptr) + { + vec3Editor->setValue(value.value<glm::vec3>()); + } + } +} + void ObjectEditor::setObjectId(const ldraw::id_t id) { this->objectId = id; const ldraw::Object* object = this->document->getModel().get(id); - this->clear(); if (object != nullptr) { this->objectTypeNameLabel->setText("<b>" + titleCase(object->typeName()) + "</b>"); this->objectTypeIconLabel->setPixmap(QPixmap{object->iconName()}.scaledToWidth(24)); - if (object->numPoints() > 0) - { - this->polygonEditor->setObjectId(id); - } - else + for (const ldraw::Property property : ldraw::ALL_PROPERTIES) { - this->polygonEditor->clear(); - } - constexpr ldraw::Property prop = ldraw::Property::Color; - QVariant color = object->getProperty(prop); - this->propertyWidgets[prop].first->setVisible(not color.isNull()); - this->propertyWidgets[prop].second->setVisible(not color.isNull()); - if (not color.isNull()) - { - static_cast<ColorIndexInput*>(this->propertyWidgets[prop].second)->setSelectedColor(color.value<ldraw::Color>()); + const QVariant value = object->getProperty(property); + const auto it = this->propertyWidgets.find(property); + if (it != this->propertyWidgets.end()) + { + it->first->setVisible(not value.isNull()); + it->second->setVisible(not value.isNull()); + if (not value.isNull()) + { + setValueToWidget(it->second, value); + } + } } } else { + this->objectTypeNameLabel->clear(); + this->objectTypeIconLabel->clear(); for (auto& pair : this->propertyWidgets) { pair.first->setVisible(false); @@ -99,10 +109,43 @@ } } -void ObjectEditor::clear() +void ObjectEditor::handleColorChange(ldraw::Color value) +{ + this->handlePropertyChange(this->sender(), QVariant::fromValue(value)); +} + +void ObjectEditor::handleVec3Change(const glm::vec3 &value) +{ + this->handlePropertyChange(this->sender(), QVariant::fromValue(value)); +} + +QWidget* ObjectEditor::makeEditorWidgetForProperty(ldraw::Property property) { - this->objectTypeNameLabel->clear(); - this->objectTypeIconLabel->clear(); - this->polygonEditor->clear(); - delete this->formContainer->layout(); + QWidget* const parent = qobject_cast<QWidget*>(this->parent()); + if (ldraw::traits(property).type == qMetaTypeId<ldraw::Color>()) + { + ColorIndexInput* colorWidget = new ColorIndexInput{this->document, {0}, parent}; + connect(colorWidget, &ColorIndexInput::colorChanged, this, &ObjectEditor::handleColorChange); + return colorWidget; + } + else if (ldraw::traits(property).type == qMetaTypeId<glm::vec3>()) + { + Vec3Editor* editor = new Vec3Editor{{}, parent}; + connect(editor, &Vec3Editor::valueChanged, this, &ObjectEditor::handleVec3Change); + return editor; + } + else + { + return nullptr; + } } + +void ObjectEditor::handlePropertyChange(QObject *caller, const QVariant &value) +{ + QVariant propertyVariant = caller->property("_property_id"); + if (not propertyVariant.isNull()) + { + ldraw::Property const property = static_cast<ldraw::Property>(propertyVariant.toInt()); + this->document->editModel()->setObjectProperty(this->objectId, property, value); + } +} \ No newline at end of file
--- a/src/ui/objecteditor.h Sun Mar 13 14:53:14 2022 +0200 +++ b/src/ui/objecteditor.h Sun Mar 13 18:46:10 2022 +0200 @@ -12,13 +12,15 @@ public: explicit ObjectEditor(Document* document, ldraw::id_t id = ldraw::NULL_ID); void setObjectId(ldraw::id_t id); - void clear(); private: + Q_SLOT void handleColorChange(ldraw::Color value); + Q_SLOT void handleVec3Change(const glm::vec3& value); Document* const document; ldraw::id_t objectId = ldraw::NULL_ID; - std::optional<PolygonObjectEditor> polygonEditor; QWidget* formContainer; class QLabel* objectTypeNameLabel; class QLabel* objectTypeIconLabel; QMap<ldraw::Property, QPair<QWidget*, QWidget*>> propertyWidgets; + QWidget* makeEditorWidgetForProperty(ldraw::Property property); + void handlePropertyChange(QObject* caller, const QVariant& value); };
--- a/src/ui/polygonobjecteditor.cpp Sun Mar 13 14:53:14 2022 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,96 +0,0 @@ -#include <QFormLayout> -#include <QSplitter> -#include "document.h" -#include "modeleditor.h" -#include "widgets/vec3editor.h" -#include "ui/polygonobjecteditor.h" - -static constexpr char INDEX_NAME[] = "_ldforge_index"; -static constexpr char LABEL_NAME[] = "_ldforge_label"; - -PolygonObjectEditor::PolygonObjectEditor(Document* document, ldraw::id_t id) : - QWidget{document}, - document{document}, - storedObjectId{ldraw::NULL_ID.value} -{ - this->splitter.emplace(Qt::Vertical, this); - this->buildWidgets(); - this->setObjectId(id); -} - -// destructor needed for std::unique_ptr -PolygonObjectEditor::~PolygonObjectEditor() -{ -} - -ldraw::id_t PolygonObjectEditor::objectId() const -{ - return this->storedObjectId; -} - -void PolygonObjectEditor::setObjectId(ldraw::id_t id) -{ - this->storedObjectId = id; - const QModelIndex index = this->document->getModel().find(this->objectId()); - if (index.isValid()) - { - for (int n : {0, 1, 2, 3}) - { - const ldraw::Object* const object = this->document->getModel()[index.row()]; - const ldraw::Property property = ldraw::pointProperty(n); - const QVariant value = object->getProperty(property); - this->widgets[n]->setVisible(value.isValid()); - this->formLayout->itemAt(n, QFormLayout::LabelRole)->widget()->setVisible(value.isValid()); - if (value.isValid()) - { - this->widgets[n]->setValue(value.value<glm::vec3>()); - } - } - } - else - { - for (int n : {0, 1, 2, 3}) - { - this->widgets[n]->setVisible(false); - this->formLayout->itemAt(n, QFormLayout::LabelRole)->widget()->setVisible(false); - } - } -} - -void PolygonObjectEditor::clear() -{ - this->setObjectId(ldraw::NULL_ID); -} - -void PolygonObjectEditor::buildWidgets() -{ - this->formLayout = new QFormLayout{this}; - this->setLayout(this->formLayout); - for (int n : {0, 1, 2, 3}) - { - this->setupPointWidget(n); - } - for (std::unique_ptr<Vec3Editor>& widget : this->widgets) - { - const QString label = widget->property(LABEL_NAME).toString(); - this->formLayout->addRow(label, widget.get()); - } - this->formLayout->addRow("", &*this->splitter); -} - -void PolygonObjectEditor::setupPointWidget(int n) -{ - std::unique_ptr<Vec3Editor> editor = std::make_unique<Vec3Editor>(glm::vec3{}, this); - QObject::connect(editor.get(), &Vec3Editor::valueChanged, this, &PolygonObjectEditor::pointChanged); - editor->setProperty(INDEX_NAME, QVariant::fromValue(n)); - editor->setProperty(LABEL_NAME, &ldraw::traits(ldraw::pointProperty(n)).name[0]); - this->widgets.push_back(std::move(editor)); -} - -void PolygonObjectEditor::pointChanged(const glm::vec3& value) -{ - std::unique_ptr<ModelEditor> modelEditor = this->document->editModel(); - const int n = this->sender()->property(INDEX_NAME).toInt(); - const ldraw::Property property = ldraw::pointProperty(n); - modelEditor->setObjectProperty(this->objectId(), property, QVariant::fromValue(value)); -}
--- a/src/ui/polygonobjecteditor.h Sun Mar 13 14:53:14 2022 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -#pragma once -#include <QWidget> -#include <QSplitter> -#include "main.h" -#include "../widgets/vec3editor.h" - -class Document; - -class PolygonObjectEditor : public QWidget -{ -public: - PolygonObjectEditor(Document* document, ldraw::id_t id); - ~PolygonObjectEditor(); - ldraw::id_t objectId() const; - void setObjectId(ldraw::id_t id); - void clear(); -private: - void buildWidgets(); - void setupPointWidget(int n); - Q_SLOT void pointChanged(const glm::vec3& value); - Document* document; - ldraw::id_t storedObjectId; - std::vector<std::unique_ptr<Vec3Editor>> widgets; - std::optional<QSplitter> splitter; - class QFormLayout* formLayout = nullptr; -};