src/ui/objecteditor.cpp

Sun, 13 Mar 2022 18:46:10 +0200

author
Teemu Piippo <teemu@hecknology.net>
date
Sun, 13 Mar 2022 18:46:10 +0200
changeset 180
5b7a8f2270ff
parent 178
a23024fc98e0
child 181
79de20dc6a1e
permissions
-rw-r--r--

Handle properties in a generic manner in the object editor

#include <QVBoxLayout>
#include <QFormLayout>
#include <QPushButton>
#include <QLabel>
#include <QSpinBox>
#include "objecteditor.h"
#include "document.h"
#include "modeleditor.h"
#include "widgets/colorbutton.h"
#include "widgets/colorindexinput.h"

template<ldraw::Property property>
static void makeColorEditor()
{
	QString propertyName = ldraw::PropertyTraits<property>::name;
}

ObjectEditor::ObjectEditor(Document* document, const ldraw::id_t id) :
	QWidget{document},
	document{document},
	formContainer{new QWidget{this}},
	objectTypeNameLabel{new QLabel{this}},
	objectTypeIconLabel{new QLabel{this}}
{
	this->setLayout(new QVBoxLayout{this});
	QWidget* objectTitleLayoutContainer = new QWidget{this};
	QLayout* objectTitleLayout = new QHBoxLayout{objectTitleLayoutContainer};
	objectTitleLayoutContainer->setLayout(objectTitleLayout);
	objectTitleLayout->addWidget(this->objectTypeIconLabel);
	objectTitleLayout->addWidget(this->objectTypeNameLabel);
	objectTitleLayout->addWidget(new QSplitter{Qt::Horizontal, this});
	this->layout()->addWidget(objectTitleLayoutContainer);
	this->layout()->addWidget(formContainer);
	this->setObjectId(id);

	QWidget* const parent = this->formContainer;
	QFormLayout* formLayout = new QFormLayout{parent};
	this->formContainer->setLayout(formLayout);

	for (const ldraw::Property property : ldraw::ALL_PROPERTIES)
	{
		QWidget* editorWidget = this->makeEditorWidgetForProperty(property);
		if (editorWidget != nullptr)
		{
			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->setObjectId(ldraw::NULL_ID);
}

QString titleCase(const QString& string)
{
	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);
	if (object != nullptr)
	{
		this->objectTypeNameLabel->setText("<b>" + titleCase(object->typeName()) + "</b>");
		this->objectTypeIconLabel->setPixmap(QPixmap{object->iconName()}.scaledToWidth(24));
		for (const ldraw::Property property : ldraw::ALL_PROPERTIES)
		{
			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);
			pair.second->setVisible(false);
		}
	}
}

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)
{
	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);
	}
}

mercurial