added support for meta-data editing improved element selection changed zooming fixed some issues with layer events fixed issue with 3D outline fixed loading issue for old maps some interface changes
322 lines
9.5 KiB
C++
322 lines
9.5 KiB
C++
#include "ElementParamWidget.h"
|
|
|
|
#include "../mapview/model/MapModelElement.h"
|
|
#include "../mapview/model/MMFloorObstacleLine.h"
|
|
#include "../mapview/model/MMFloorOutlinePolygon.h"
|
|
|
|
#include "../mapview/model/IHasParams.h"
|
|
#include "../mapview/model/IHasEditableMeta.h"
|
|
|
|
#include "MetaEditWidget.h"
|
|
|
|
#include <Indoor/floorplan/v2/Floorplan.h>
|
|
|
|
#include <QLabel>
|
|
#include <QComboBox>
|
|
#include <QGridLayout>
|
|
#include <QLineEdit>
|
|
#include <QPushButton>
|
|
#include <QFileDialog>
|
|
|
|
QComboBox* getMaterials() {
|
|
using namespace Floorplan;
|
|
QComboBox* cmbMaterial = new QComboBox();
|
|
for (int i = 0; i < (int)Material::_END; ++i) {
|
|
switch ((Material)i) {
|
|
case Material::CONCRETE: cmbMaterial->addItem("Concrete", i); break;
|
|
case Material::UNKNOWN: cmbMaterial->addItem("Unknown ", i); break;
|
|
case Material::DRYWALL: cmbMaterial->addItem("Drywall", i); break;
|
|
case Material::WOOD: cmbMaterial->addItem("Wood", i); break;
|
|
case Material::GLASS: cmbMaterial->addItem("Glass", i); break;
|
|
case Material::_END: throw 1;
|
|
}
|
|
}
|
|
return cmbMaterial;
|
|
}
|
|
|
|
QComboBox* getObstacleTypes() {
|
|
using namespace Floorplan;
|
|
QComboBox* cmb = new QComboBox();
|
|
for (int i = 0; i < (int)ObstacleType::_END; ++i) {
|
|
switch ((ObstacleType)i) {
|
|
case ObstacleType::UNKNOWN: cmb->addItem("Unknown ", i); break;
|
|
case ObstacleType::WALL: cmb->addItem("Wall", i); break;
|
|
case ObstacleType::WINDOW: cmb->addItem("Window", i); break;
|
|
case ObstacleType::HANDRAIL:cmb->addItem("Handrail", i); break;
|
|
case ObstacleType::PILLAR: cmb->addItem("Pillar", i); break;
|
|
case ObstacleType::_END: throw 1;
|
|
}
|
|
}
|
|
return cmb;
|
|
}
|
|
|
|
QComboBox* getOutlineMethods() {
|
|
using namespace Floorplan;
|
|
QComboBox* cmb = new QComboBox();
|
|
for (int i = 0; i < (int)OutlineMethod::_END; ++i) {
|
|
switch ((OutlineMethod)i) {
|
|
case OutlineMethod::ADD: cmb->addItem("add", i); break;
|
|
case OutlineMethod::REMOVE: cmb->addItem("remove ", i); break;
|
|
case OutlineMethod::_END: throw 1;
|
|
}
|
|
}
|
|
return cmb;
|
|
}
|
|
|
|
|
|
|
|
ElementParamWidget::ElementParamWidget(QWidget *parent) : QWidget(parent) {
|
|
|
|
this->lay = new QGridLayout(this);
|
|
|
|
//setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
|
|
//lay->setSizeConstraint(QLayout::SetMinAndMaxSize);
|
|
setMinimumSize(200, 25);
|
|
setMaximumSize(200, 9999);
|
|
//setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
|
|
|
|
//setTitle("MapElement Parameters");
|
|
lay = new QGridLayout();
|
|
|
|
// start empty
|
|
setElement(nullptr);
|
|
|
|
}
|
|
|
|
void ElementParamWidget::setElement(MapModelElement* el) {
|
|
|
|
this->curElement = el;
|
|
refresh();
|
|
|
|
}
|
|
|
|
void ElementParamWidget::refresh() {
|
|
|
|
while ( QWidget* w = this->findChild<QWidget*>() ) {delete w;}
|
|
delete this->layout();
|
|
this->lay = new QGridLayout();
|
|
this->setLayout(lay);
|
|
int r = 0;
|
|
|
|
MapModelElement* el = this->curElement;
|
|
|
|
// material? -> select in combo-box
|
|
{
|
|
IHasMaterial* elem = dynamic_cast<IHasMaterial*>(el);
|
|
if (elem) {
|
|
material.cmb = getMaterials();
|
|
material.lbl = new QLabel("material");
|
|
lay->addWidget(material.lbl,r,0);
|
|
lay->addWidget(material.cmb,r,1);
|
|
connect(material.cmb , SIGNAL(currentIndexChanged(int)), this, SLOT(onMaterialChange()));
|
|
material.cmb->setCurrentIndex((int)elem->getMaterial());
|
|
++r;
|
|
}
|
|
}
|
|
|
|
// obstacle-type? -> select in combo-box
|
|
{
|
|
IHasObstacleType* elem = dynamic_cast<IHasObstacleType*>(el);
|
|
if (elem) {
|
|
obstacleType.cmb = getObstacleTypes();
|
|
obstacleType.lbl = new QLabel("type");
|
|
lay->addWidget(obstacleType.lbl,r,0);
|
|
lay->addWidget(obstacleType.cmb,r,1);
|
|
connect(obstacleType.cmb, SIGNAL(currentIndexChanged(int)), this, SLOT(onObstacleTypeChange()));
|
|
obstacleType.cmb->setCurrentIndex((int)elem->getObatcleType());
|
|
++r;
|
|
}
|
|
}
|
|
|
|
|
|
// has outline method?
|
|
{
|
|
MMFloorOutlinePolygon* elem = dynamic_cast<MMFloorOutlinePolygon*>(el);
|
|
if (elem) {
|
|
QComboBox* cmb = getOutlineMethods();
|
|
QLabel* lbl = new QLabel("outline");
|
|
lay->addWidget(lbl,r,0);
|
|
lay->addWidget(cmb,r,1);
|
|
cmb->setCurrentIndex((int)elem->getMethod());
|
|
connect(cmb, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), [elem, cmb] (int idx) {
|
|
(void) idx;
|
|
elem->setMethod( (Floorplan::OutlineMethod) cmb->currentData().toInt() );
|
|
});
|
|
++r;
|
|
}
|
|
}
|
|
|
|
|
|
{ // does the element have "parameters" ?
|
|
IHasParams* elem = dynamic_cast<IHasParams*>(el);
|
|
if (elem) {
|
|
|
|
for(int i = 0; i < elem->getNumParams(); ++i) {
|
|
|
|
const Param param = elem->getParamDesc(i);
|
|
const ParamValue value = elem->getParamValue(i);
|
|
|
|
// skip Not-Available entries
|
|
if (param.type == ParamType::NOT_AVAILABLE) {continue;}
|
|
|
|
lay->addWidget(new QLabel(param.name.c_str()),r,0);
|
|
|
|
switch(param.type) {
|
|
|
|
case ParamType::NOT_AVAILABLE:
|
|
break;
|
|
|
|
case ParamType::BOOL: {
|
|
QCheckBox* chk = new QCheckBox( );
|
|
chk->setChecked(value.toBool());
|
|
if (param.readOnly) {
|
|
chk->setEnabled(false);
|
|
} else {
|
|
connect(chk, &QCheckBox::clicked, [i,elem] (const bool checked) {
|
|
elem->setParamValue(i, ParamValue(checked));
|
|
});
|
|
}
|
|
lay->addWidget(chk,r,1);
|
|
break;
|
|
}
|
|
|
|
case ParamType::FLOAT: {
|
|
const std::string str = std::to_string(value.toFloat());
|
|
if (param.readOnly) {
|
|
lay->addWidget(new QLabel(str.c_str()),r,1);
|
|
} else {
|
|
QLineEdit* le = new QLineEdit( str.c_str() );
|
|
connect(le, &QLineEdit::textChanged, [i,elem] (const QString& str) {
|
|
const float val = str.toFloat();
|
|
elem->setParamValue(i, ParamValue(val));
|
|
});
|
|
lay->addWidget(le,r,1);
|
|
}
|
|
break;
|
|
}
|
|
|
|
case ParamType::INT: {
|
|
const std::string str = std::to_string(value.toInt());
|
|
QLineEdit* le = new QLineEdit( str.c_str() );
|
|
connect(le, &QLineEdit::textChanged, [i,elem] (const QString& str) {
|
|
const int val = str.toInt();
|
|
elem->setParamValue(i, ParamValue(val));
|
|
});
|
|
lay->addWidget(le,r,1);
|
|
break;
|
|
}
|
|
|
|
case ParamType::STRING: {
|
|
const std::string str = value.toString();
|
|
QLineEdit* le = new QLineEdit( str.c_str() );
|
|
connect(le, &QLineEdit::textChanged, [i,elem] (const QString& str) {
|
|
elem->setParamValue(i, ParamValue(str.toStdString()));
|
|
});
|
|
lay->addWidget(le,r,1);
|
|
break;
|
|
}
|
|
|
|
case ParamType::FILE: {
|
|
const std::string str = value.toString();
|
|
QLabel* lblFile = new QLabel(str.c_str());
|
|
QPushButton* btn = new QPushButton("<");
|
|
btn->setMaximumSize(32,32);
|
|
connect(btn, &QPushButton::clicked, [i,elem,lblFile] (const bool checked) {
|
|
(void) checked;
|
|
QString res = QFileDialog::getOpenFileName();
|
|
elem->setParamValue(i, ParamValue(res.toStdString()));
|
|
lblFile->setText(res);
|
|
});
|
|
lay->addWidget(lblFile,r,1);
|
|
lay->addWidget(btn,r,2);
|
|
break;
|
|
}
|
|
|
|
case ParamType::POINT2: {
|
|
const Point2 p2 = value.toPoint2();
|
|
QWidget* subWidget = new QWidget();
|
|
QGridLayout* laySub = new QGridLayout(subWidget); laySub->setMargin(0);
|
|
QLineEdit* txtX = new QLineEdit(QString::number(p2.x));
|
|
QLineEdit* txtY = new QLineEdit(QString::number(p2.y));
|
|
laySub->addWidget(txtX,0,0);
|
|
laySub->addWidget(txtY,0,1);
|
|
lay->addWidget(subWidget,r,1);
|
|
auto onChange = [i,elem,txtX,txtY] (const QString& str) {
|
|
(void) str;
|
|
elem->setParamValue(i, ParamValue( Point2(txtX->text().toFloat(), txtY->text().toFloat()) ));
|
|
};
|
|
connect(txtX, &QLineEdit::textChanged, onChange);
|
|
connect(txtY, &QLineEdit::textChanged, onChange);
|
|
break;
|
|
}
|
|
|
|
case ParamType::POINT3: {
|
|
const Point3 p3 = value.toPoint3();
|
|
QWidget* subWidget = new QWidget();
|
|
QGridLayout* laySub = new QGridLayout(subWidget); laySub->setMargin(0);
|
|
QLineEdit* txtX = new QLineEdit(QString::number(p3.x));
|
|
QLineEdit* txtY = new QLineEdit(QString::number(p3.y));
|
|
QLineEdit* txtZ = new QLineEdit(QString::number(p3.z));
|
|
laySub->addWidget(txtX,0,0);
|
|
laySub->addWidget(txtY,0,1);
|
|
laySub->addWidget(txtZ,0,2);
|
|
lay->addWidget(subWidget,r,1);
|
|
auto onChange = [i,elem,txtX,txtY,txtZ] (const QString& str) {
|
|
(void) str;
|
|
elem->setParamValue(i, ParamValue( Point3(txtX->text().toFloat(), txtY->text().toFloat(), txtZ->text().toFloat()) ));
|
|
};
|
|
connect(txtX, &QLineEdit::textChanged, onChange);
|
|
connect(txtY, &QLineEdit::textChanged, onChange);
|
|
connect(txtZ, &QLineEdit::textChanged, onChange);
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
++r;
|
|
|
|
}
|
|
}
|
|
|
|
{ // does the element have editable metadata?
|
|
IHasEditableMeta* elem = dynamic_cast<IHasEditableMeta*>(el);
|
|
if (elem) {
|
|
|
|
QPushButton* btn = new QPushButton("edit");
|
|
connect(btn, &QPushButton::clicked, [elem] (const bool checked) {
|
|
(void) checked;
|
|
if (!elem->getMeta()) {elem->setMeta(new Floorplan::Meta());} // ensure meta-object is present
|
|
MetaEditWidget* mew = new MetaEditWidget(elem->getMeta()); // edit
|
|
mew->show();
|
|
});
|
|
lay->addWidget(new QLabel("Meta"),r,0);
|
|
lay->addWidget(btn,r,1);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
//setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
|
|
//lay->setSizeConstraint(QLayout::SetMinimumSize);
|
|
//setLayout(lay);
|
|
setMinimumSize(150, 30+r*24);
|
|
setMaximumSize(250, 30+r*24);
|
|
//resize(100, 20+r*22);
|
|
//emit update();
|
|
//setVisible(false);
|
|
//setVisible(true);
|
|
|
|
|
|
}
|
|
|
|
|
|
void ElementParamWidget::onMaterialChange() {
|
|
IHasMaterial* el = dynamic_cast<IHasMaterial*>(this->curElement);
|
|
if (el) {el->setMaterial( (Floorplan::Material) material.cmb->currentData().toInt() );}
|
|
}
|
|
|
|
void ElementParamWidget::onObstacleTypeChange() {
|
|
IHasObstacleType* el = dynamic_cast<IHasObstacleType*>(this->curElement);
|
|
if (el) {el->setObstacleType((Floorplan::ObstacleType) obstacleType.cmb->currentData().toInt() );}
|
|
}
|