From 535e410ae9cc3aa5bcdf360b624781ca053ca14b Mon Sep 17 00:00:00 2001 From: kazu Date: Tue, 29 Nov 2016 21:31:20 +0100 Subject: [PATCH] added new param-editing to APs and Beacons changed drawing for better debuging changed layer editing option to add and delete layers some minor changes --- IndoorMap.pro | 7 +- MainController.cpp | 15 +- MainWindow.cpp | 6 +- MainWindow.h | 7 +- main.cpp | 20 +++ mapview/2D/MV2DElementFloorObstacleLine.h | 4 + mapview/2D/tools/ToolRuler.h | 12 ++ mapview/3D/MV3DElementFloorOutlinePolygon.h | 2 +- mapview/3D/MapView3D.cpp | 5 +- mapview/model/MMFloor.h | 19 ++- mapview/model/MMFloorAccessPoint.h | 11 +- mapview/model/MMFloorBeacon.h | 32 ++++- mapview/model/MMFloorObstacleLine.h | 28 +++- mapview/model/MMFloors.h | 18 ++- mapview/model/MapLayer.h | 4 +- mapview/model/MapModel.h | 7 + params/EditFields.h | 143 ++++++++++++++++++++ params/ElementParamWidget.cpp | 22 ++- params/ElementParamWidget.h | 1 + params/LayerParamWidget.cpp | 69 ++++++---- params/LayerParamWidget.h | 5 + params/LayerTree.cpp | 92 +++++++++++++ params/LayerTree.h | 49 +++++++ res.qrc | 2 + res/icons/add.svg | 42 ++++++ res/icons/remove.svg | 42 ++++++ res/icons/sources.txt | 8 ++ tree/MapTreeModel.h | 4 + 28 files changed, 614 insertions(+), 62 deletions(-) create mode 100644 params/EditFields.h create mode 100644 params/LayerTree.cpp create mode 100644 params/LayerTree.h create mode 100644 res/icons/add.svg create mode 100644 res/icons/remove.svg create mode 100644 res/icons/sources.txt diff --git a/IndoorMap.pro b/IndoorMap.pro index 2f5936e..3db9253 100644 --- a/IndoorMap.pro +++ b/IndoorMap.pro @@ -37,7 +37,8 @@ SOURCES += \ tree/MapTreeModel.cpp \ mapview/3D/MapView3D.cpp \ params/StairBuilder.cpp \ - mapview/2D/tools/Tools.cpp + mapview/2D/tools/Tools.cpp \ + params/LayerTree.cpp HEADERS += MainWindow.h \ @@ -125,7 +126,9 @@ HEADERS += MainWindow.h \ mapview/2D/Scaler.h \ mapview/2D/MV2DElementElevator.h \ mapview/model/MMFloorElevators.h \ - mapview/model/MMFloorElevator.h + mapview/model/MMFloorElevator.h \ + params/LayerTree.h \ + params/EditFields.h FORMS += MainWindow.ui diff --git a/MainController.cpp b/MainController.cpp index 03dd1ae..ecea8f7 100644 --- a/MainController.cpp +++ b/MainController.cpp @@ -15,6 +15,7 @@ #include "params/LayerParamWidget.h" #include "params/ToolBoxWidget.h" #include "params/ActionWidget.h" +#include "params/LayerTree.h" #include "tree/MapTreeModel.h" @@ -32,7 +33,7 @@ MainController::MainController() { MapView2D* mapView2D = mw->getMapView2D(); MapView3D* mapView3D = mw->getMapView3D(); - QTreeView* layerTree = mw->getTree(); + LayerTree* layerTree = mw->getTree(); // model setup @@ -58,7 +59,8 @@ MainController::MainController() { //connect(layerTree, SIGNAL(activated(QModelIndex)), this, SLOT(layerSelected(QModelIndex))); - connect(layerTree->selectionModel(), SIGNAL(currentChanged(QModelIndex, QModelIndex)), this, SLOT(layerSelected(QModelIndex))); + //connect(layerTree->getTree()->selectionModel(), SIGNAL(currentChanged(QModelIndex, QModelIndex)), this, SLOT(layerSelected(QModelIndex))); + connect(layerTree, SIGNAL(layerSelected(QModelIndex)), this, SLOT(layerSelected(QModelIndex))); connect(mapSelector, SIGNAL(onMapElementSelected(MapModelElement*)), this, SLOT(mapElementSelected(MapModelElement*))); connect(mw->getMapView2D(), SIGNAL(onElementChange(MV2DElement*)), this, SLOT(curMapElementChanged())); @@ -81,17 +83,20 @@ MainController::MainController() { connect(mw, &MainWindow::onGridShowEdges, [&] (const bool show) {mw->getMapView3D()->getGridRenderer()->setShowEdges(show);} ); - //mapModel->load("../IndoorMap/maps/SHL21.xml"); + //mapModel->load("../IndoorMap/maps/SHL25.xml"); //mapModel->load("../IndoorMap/maps/test.xml"); + //mapModel->load("../IndoorMap/maps/APs.xml"); //mapModel->load("/mnt/data/workspaces/IPIN2016/IPIN2016/competition/maps/CAR/CAR9.xml"); - mapModel->load("/mnt/data/workspaces/IPIN2016/IPIN2016/competition/maps/UAH/UAH9.xml"); + //mapModel->load("/mnt/data/workspaces/IPIN2016/IPIN2016/competition/maps/UAH/UAH9.xml"); //mapModel->load("/mnt/data/workspaces/IPIN2016/IPIN2016/competition/maps/UJI-TI/UJI-TI4.xml"); //mapModel->load("/mnt/data/workspaces/IPIN2016/IPIN2016/competition/maps/UJI-UB/UJI-UB4.xml"); //mapModel->load("/mnt/data/workspaces/Indoor/tests/data/WalkHeadingMap.xml"); //mapModel->load("/mnt/data/workspaces/IPIN2016/IPIN2016/competition/maps/test.xml"); + //mapModel->load("/mnt/vm/workspace/IRGame/IndoorServer/maps/map6.xml"); + //mapModel->load("/mnt/vm/workspace/IRGame/IndoorServer/maps/keller.xml"); - + //mapModel->startEmpty(); } diff --git a/MainWindow.cpp b/MainWindow.cpp index c77199b..6a6ce45 100644 --- a/MainWindow.cpp +++ b/MainWindow.cpp @@ -20,6 +20,7 @@ #include "params/LayerParamWidget.h" #include "params/ActionWidget.h" #include "params/ToolBoxWidget.h" +#include "params/LayerTree.h" #include "tree/MapTreeModel.h" @@ -39,7 +40,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi this->setStyleSheet(css); { - layerTree = new QTreeView(); + layerTree = new LayerTree(); QString css; //css += "QTreeView::item:selected:active {background-color: #888888;}"; //css += "QTreeView::item:selected:!active {background-color: #888888;}"; @@ -140,6 +141,3 @@ MainWindow::~MainWindow() { } -QTreeView* MainWindow::getTree() { - return layerTree; -} diff --git a/MainWindow.h b/MainWindow.h index 25ba600..6800b19 100644 --- a/MainWindow.h +++ b/MainWindow.h @@ -12,6 +12,7 @@ class ElementParamWidget; class LayerParamWidget; class ActionWidget; class ToolBoxWidget; +class LayerTree; namespace Ui { class MainWindow; @@ -32,9 +33,7 @@ public: LayerParamWidget* getLayerParamWidget() {return layerParamWidget;} ToolBoxWidget* getToolBoxWidget() {return toolBoxWidget;} ActionWidget* getActionWidget() {return actionWidget;} - - - QTreeView* getTree(); + LayerTree* getTree() {return layerTree;} signals: @@ -47,7 +46,7 @@ signals: private: Ui::MainWindow *ui; - QTreeView* layerTree; + LayerTree* layerTree; MapView2D* mapView2D; MapView3D* mapView3D; ElementParamWidget* elementParamWidget; diff --git a/main.cpp b/main.cpp index 8ded81e..2dc80b9 100644 --- a/main.cpp +++ b/main.cpp @@ -11,6 +11,26 @@ int main(int argc, char *argv[]) { QApplication a(argc, argv); + QString str = R"( + + QDockWidget { + border: 1px solid #000; + } + + QDockWidget::title { + text-align: left; /* align the text to the left */ + background: #ccc; + padding: 1px; + } + + QDockWidget::title:hover { + background: #bbb; + } + + )"; + + a.setStyleSheet(str); + MainController mc; mc.show(); diff --git a/mapview/2D/MV2DElementFloorObstacleLine.h b/mapview/2D/MV2DElementFloorObstacleLine.h index f415afd..4aab07c 100644 --- a/mapview/2D/MV2DElementFloorObstacleLine.h +++ b/mapview/2D/MV2DElementFloorObstacleLine.h @@ -60,6 +60,10 @@ public: p.setPenBrush(Qt::black, Qt::NoBrush); p.drawCircle(fo->from); p.drawCircle(fo->to); + } else { + //p.setPenBrush(Qt::NoPen, Qt::black); + p.drawCircle(fo->from, 0.1); + p.drawCircle(fo->to, 0.1); } } diff --git a/mapview/2D/tools/ToolRuler.h b/mapview/2D/tools/ToolRuler.h index 2adbaf1..ce1ee7d 100644 --- a/mapview/2D/tools/ToolRuler.h +++ b/mapview/2D/tools/ToolRuler.h @@ -96,9 +96,19 @@ public: p.p->drawLine(mouseX, 0, mouseX, rs); + + p.setPenBrush(Qt::black, Qt::NoBrush); char buf[128]; + // coordinates + QRect ru(0,0,rs-1,rs-1); + p.p->fillRect(ru, Qt::white); + std::sprintf(buf, "%.1f", p.getScaler().xsm(this->mouseX)); + p.p->drawText(5,15, buf); + std::sprintf(buf, "%.1f", p.getScaler().ysm(this->mouseY)); + p.p->drawText(5,30, buf); + // y-axis p.p->setClipRect(ry); for (float y = r.y0; y <= r.y1; y += step) { @@ -141,6 +151,8 @@ public: p.p->setClipping(false); + + // snapped dot const Point2 mouseOnScreen(mouseX, mouseY); const Point2 mouseInMap = p.s.sm(mouseOnScreen); diff --git a/mapview/3D/MV3DElementFloorOutlinePolygon.h b/mapview/3D/MV3DElementFloorOutlinePolygon.h index 5b63c6e..00ad604 100644 --- a/mapview/3D/MV3DElementFloorOutlinePolygon.h +++ b/mapview/3D/MV3DElementFloorOutlinePolygon.h @@ -31,7 +31,7 @@ protected: glColor3f(1,1,1); break; case Floorplan::OutlineMethod::REMOVE: - glColor3f(0.2, 0.2, 0.2); + glColor3f(0.3, 0.3, 0.3); break; } diff --git a/mapview/3D/MapView3D.cpp b/mapview/3D/MapView3D.cpp index 8c762bd..454da88 100644 --- a/mapview/3D/MapView3D.cpp +++ b/mapview/3D/MapView3D.cpp @@ -32,11 +32,12 @@ void MapView3D::initializeGL() { QGLWidget::initializeGL(); - //glCullFace(GL_FRONT); + glCullFace(GL_FRONT); + //glDisable(GL_CULL_FACE); + glEnable(GL_CULL_FACE); // culling, lighting, depth-test, ... glEnable(GL_DEPTH_TEST); - glEnable(GL_CULL_FACE); glShadeModel(GL_SMOOTH); glEnable(GL_MULTISAMPLE); diff --git a/mapview/model/MMFloor.h b/mapview/model/MMFloor.h index 010e35b..87e966d 100644 --- a/mapview/model/MMFloor.h +++ b/mapview/model/MMFloor.h @@ -25,13 +25,15 @@ class MMFloor : public MapLayer, public IHasParams { private: + Floorplan::IndoorMap* map; + /** the underlying data-structure */ Floorplan::Floor* floor; public: /** ctor. existing floor */ - MMFloor(MapLayer* parent, Floorplan::Floor* floor) : MapLayer(parent, MapLayerType::FLOOR), floor(floor) { + MMFloor(MapLayer* parent, Floorplan::IndoorMap* map, Floorplan::Floor* floor) : MapLayer(parent, MapLayerType::FLOOR), map(map), floor(floor) { new MMFloorUnderlays(this, floor); elements.push_back(new MMFloorOutline(this, floor)); @@ -56,12 +58,14 @@ public: std::string getLayerName() const override {return floor->name;} virtual int getNumParams() const override { - return 1; + return 3; } virtual Param getParamDesc(const int idx) const override { switch(idx) { - case 0: return Param("anem", ParamType::STRING); + case 0: return Param("name", ParamType::STRING); + case 1: return Param("height", ParamType::FLOAT); + case 2: return Param("at height", ParamType::FLOAT); } throw 1; } @@ -69,6 +73,8 @@ public: virtual ParamValue getParamValue(const int idx) const override { switch(idx) { case 0: return floor->name; + case 1: return floor->height; + case 2: return floor->atHeight; } throw 1; } @@ -76,9 +82,16 @@ public: virtual void setParamValue(const int idx, const ParamValue& val) const override { switch(idx) { case 0: floor->name = val.toString(); break; + case 1: floor->height = val.toFloat(); break; + case 2: floor->atHeight = val.toFloat(); break; } } + void deleteMe() { + parent->removeSublayer(this); + map->floors.erase(std::remove(map->floors.begin(), map->floors.end(), floor), map->floors.end()); + } + }; #endif // MMFLOOR_H diff --git a/mapview/model/MMFloorAccessPoint.h b/mapview/model/MMFloorAccessPoint.h index b364956..66e3f18 100644 --- a/mapview/model/MMFloorAccessPoint.h +++ b/mapview/model/MMFloorAccessPoint.h @@ -26,7 +26,7 @@ public: } virtual int getNumParams() const override { - return 3; + return 6; } virtual Param getParamDesc(const int idx) const override { @@ -34,6 +34,9 @@ public: case 0: return Param("name", ParamType::STRING); case 1: return Param("MAC", ParamType::STRING); case 2: return Param("Position", ParamType::POINT3); + case 3: return Param("TXP", ParamType::FLOAT); + case 4: return Param("EXP", ParamType::FLOAT); + case 5: return Param("WAF", ParamType::FLOAT); } throw 1; } @@ -43,6 +46,9 @@ public: case 0: return ap->name; case 1: return ap->mac; case 2: return ap->pos; + case 3: return ap->model.txp; + case 4: return ap->model.exp; + case 5: return ap->model.waf; } throw 1; } @@ -52,6 +58,9 @@ public: case 0: ap->name = val.toString(); break; case 1: ap->mac = val.toString(); break; case 2: ap->pos = val.toPoint3(); break; + case 3: ap->model.txp = val.toFloat(); break; + case 4: ap->model.exp = val.toFloat(); break; + case 5: ap->model.waf = val.toFloat(); break; } } diff --git a/mapview/model/MMFloorBeacon.h b/mapview/model/MMFloorBeacon.h index eb6f078..fffe8a8 100644 --- a/mapview/model/MMFloorBeacon.h +++ b/mapview/model/MMFloorBeacon.h @@ -23,14 +23,20 @@ public: } virtual int getNumParams() const override { - return 3; + return 9; } virtual Param getParamDesc(const int idx) const override { switch(idx) { case 0: return Param("name", ParamType::STRING); - case 1: return Param("MAC", ParamType::STRING); - case 2: return Param("Position", ParamType::POINT3); + case 1: return Param("Position", ParamType::POINT3); + case 2: return Param("MAC", ParamType::STRING); + case 3: return Param("major", ParamType::STRING); + case 4: return Param("minor", ParamType::STRING); + case 5: return Param("UUDI", ParamType::STRING); + case 6: return Param("TXP", ParamType::FLOAT); + case 7: return Param("EXP", ParamType::FLOAT); + case 8: return Param("WAF", ParamType::FLOAT); } throw 1; } @@ -38,8 +44,14 @@ public: virtual ParamValue getParamValue(const int idx) const override { switch(idx) { case 0: return b->name; - case 1: return b->mac; - case 2: return b->pos; + case 1: return b->pos; + case 2: return b->mac; + case 3: return b->major; + case 4: return b->minor; + case 5: return b->uuid; + case 6: return b->model.txp; + case 7: return b->model.exp; + case 8: return b->model.waf; } throw 1; } @@ -47,8 +59,14 @@ public: virtual void setParamValue(const int idx, const ParamValue& val) const override { switch(idx) { case 0: b->name = val.toString(); break; - case 1: b->mac = val.toString(); break; - case 2: b->pos = val.toPoint3(); break; + case 1: b->pos = val.toPoint3(); break; + case 2: b->mac = val.toString(); break; + case 3: b->major = val.toString(); break; + case 4: b->minor = val.toString(); break; + case 5: b->uuid = val.toString(); break; + case 6: b->uuid = val.toFloat(); break; + case 7: b->uuid = val.toFloat(); break; + case 8: b->uuid = val.toFloat(); break; } } diff --git a/mapview/model/MMFloorObstacleLine.h b/mapview/model/MMFloorObstacleLine.h index e36773a..31c165e 100644 --- a/mapview/model/MMFloorObstacleLine.h +++ b/mapview/model/MMFloorObstacleLine.h @@ -6,6 +6,7 @@ #include "IHasMaterial.h" #include "IHasObstacleType.h" +#include "IHasParams.h" #include "../2D/MV2DElementFloorObstacleLine.h" #include "../3D/MV3DElementFloorObstacleWall.h" @@ -13,7 +14,7 @@ #include -class MMFloorObstacleLine : public MapModelElement, public IHasMaterial, public IHasObstacleType { +class MMFloorObstacleLine : public MapModelElement, public IHasMaterial, public IHasObstacleType, public IHasParams { public: @@ -43,6 +44,31 @@ public: mf->obstacles.erase(std::remove(mf->obstacles.begin(), mf->obstacles.end(), fo), mf->obstacles.end()); } + + virtual int getNumParams() const override { + return 1; + } + + virtual Param getParamDesc(const int idx) const override { + switch(idx) { + case 0: return Param("length", ParamType::FLOAT, true); + } + throw 1; + } + + virtual ParamValue getParamValue(const int idx) const override { + switch(idx) { + case 0: return fo->from.getDistance(fo->to); + } + throw 1; + } + + virtual void setParamValue(const int idx, const ParamValue& val) const override { + switch(idx) { + case 0: break; + } + } + }; #endif // MAPELEMENTOBSTACLE_H diff --git a/mapview/model/MMFloors.h b/mapview/model/MMFloors.h index ec40cad..3a84f06 100644 --- a/mapview/model/MMFloors.h +++ b/mapview/model/MMFloors.h @@ -22,7 +22,7 @@ public: // add all floors for (Floorplan::Floor* floor : map->floors) { - new MMFloor(this, floor); + new MMFloor(this, map, floor); } } @@ -32,6 +32,22 @@ public: /** get the underlying model */ Floorplan::IndoorMap* getMap() {return map;} + MMFloor* createFloor() { + + // add to underlying model + Floorplan::Floor* floor = new Floorplan::Floor(); + floor->name = "floor"; + map->floors.push_back(floor); + + // add to UI model + MMFloor* mmfloor = new MMFloor(this, map, floor); + //elements.push_back(mmfloor); + + return mmfloor; + + } + + }; #endif // MMFLOORS_H diff --git a/mapview/model/MapLayer.h b/mapview/model/MapLayer.h index b5be0dc..506a016 100644 --- a/mapview/model/MapLayer.h +++ b/mapview/model/MapLayer.h @@ -78,6 +78,8 @@ public: /** remove the given element from the elements list */ void removeElement(const MapModelElement* elem) { elements.erase(std::remove(elements.begin(), elements.end(), elem), elements.end()); } + /** remove the given sublayer from this layer */ + void removeSublayer(const MapLayer* layer) { sublayers.erase(std::remove(sublayers.begin(), sublayers.end(), layer), sublayers.end()); } /** is this layer currently visible? */ bool isVisible() const {return visible;} @@ -101,7 +103,7 @@ public: } } -protected: +public: diff --git a/mapview/model/MapModel.h b/mapview/model/MapModel.h index 4d2da38..b92c35a 100644 --- a/mapview/model/MapModel.h +++ b/mapview/model/MapModel.h @@ -42,6 +42,13 @@ public: cleanup(); } + /** create a new, empty root node */ + void startEmpty() { + im = new Floorplan::IndoorMap(); + root = new MMRoot(nullptr, im); + //root->addSublayer(new MMFloors(root, im)); + } + void cleanup() { selLayer = nullptr; //selElements.clear(); diff --git a/params/EditFields.h b/params/EditFields.h new file mode 100644 index 0000000..3c6b42e --- /dev/null +++ b/params/EditFields.h @@ -0,0 +1,143 @@ +#ifndef EDITFIELDS_H +#define EDITFIELDS_H + +#include +#include +#include +#include +#include "../mapview/model/IHasParams.h" + +class EditFields { + +public: + + static void get(QGridLayout* lay, IHasParams* elem) { + + int r = 0; + + 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::BOOL: { + QCheckBox* chk = new QCheckBox( ); + chk->setChecked(value.toBool()); + if (param.readOnly) { + chk->setEnabled(false); + } else { + chk->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() ); + le->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() ); + le->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() ); + le->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); + btn->connect(btn, &QPushButton::clicked, [i,elem,lblFile] (const bool 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) { + elem->setParamValue(i, ParamValue( Point2(txtX->text().toFloat(), txtY->text().toFloat()) )); + }; + txtX->connect(txtX, &QLineEdit::textChanged, onChange); + txtY->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()) )); + }; + txtX->connect(txtX, &QLineEdit::textChanged, onChange); + txtY->connect(txtY, &QLineEdit::textChanged, onChange); + txtZ->connect(txtZ, &QLineEdit::textChanged, onChange); + break; + } + + } + + ++r; + + } + + } + +}; + +#endif // EDITFIELDS_H diff --git a/params/ElementParamWidget.cpp b/params/ElementParamWidget.cpp index af0279e..da6b42c 100644 --- a/params/ElementParamWidget.cpp +++ b/params/ElementParamWidget.cpp @@ -68,11 +68,14 @@ ElementParamWidget::ElementParamWidget(QWidget *parent) : QWidget(parent) { this->lay = new QGridLayout(this); - setMinimumSize(100, 100); - setMaximumWidth(250); + //setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred); + //lay->setSizeConstraint(QLayout::SetMinAndMaxSize); + setMinimumSize(200, 25); + setMaximumSize(200, 9999); + //setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding); //setTitle("MapElement Parameters"); - QGridLayout* lay = new QGridLayout(); + lay = new QGridLayout(); // start empty setElement(nullptr); @@ -90,7 +93,6 @@ void ElementParamWidget::refresh() { while ( QWidget* w = this->findChild() ) {delete w;} delete this->layout(); - this->lay = new QGridLayout(); this->setLayout(lay); int r = 0; @@ -269,8 +271,20 @@ void ElementParamWidget::refresh() { } } + //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(this->curElement); if (el) {el->setMaterial( (Floorplan::Material) material.cmb->currentData().toInt() );} diff --git a/params/ElementParamWidget.h b/params/ElementParamWidget.h index 8d756f6..aa8fe4b 100644 --- a/params/ElementParamWidget.h +++ b/params/ElementParamWidget.h @@ -21,6 +21,7 @@ public: /** refresh the currently selected element */ void refresh(); + private: QGridLayout* lay; diff --git a/params/LayerParamWidget.cpp b/params/LayerParamWidget.cpp index 9cdffab..42354b6 100644 --- a/params/LayerParamWidget.cpp +++ b/params/LayerParamWidget.cpp @@ -7,13 +7,15 @@ #include "mapview/model/IHasName.h" #include "mapview/model/MMFloor.h" +#include "EditFields.h" + LayerParamWidget::LayerParamWidget(QWidget *parent) : QWidget(parent) { - setMinimumSize(100, 100); + setMinimumSize(100, 50); setMaximumWidth(250); //setTitle("MapLayer Parameters"); - QGridLayout* lay = new QGridLayout(this); + lay = new QGridLayout(this); int r = 0; @@ -53,35 +55,50 @@ void LayerParamWidget::setElement(MapLayer* l) { this->curElement = l; - if (l) { - std::string info = l->getLayerName() + " (" + std::to_string(l->getNumElements()) + " elements)"; - selected.info->setText(info.c_str()); - } else { - selected.info->setText("-"); - } +// if (l) { +// std::string info = l->getLayerName() + " (" + std::to_string(l->getNumElements()) + " elements)"; +// selected.info->setText(info.c_str()); +// } else { +// selected.info->setText("-"); +// } + + while ( QWidget* w = this->findChild() ) {delete w;} + delete this->layout(); + this->lay = new QGridLayout(); + this->setLayout(lay); + int r = 0; + + +// { +// MMFloor* floor = dynamic_cast(l); +// atHeight.lbl->setVisible(floor); +// atHeight.txt->setVisible(floor); +// height.lbl->setVisible(floor); +// height.txt->setVisible(floor); +// if (floor) { +// std::string _atHeight = std::to_string(floor->getFloor().atHeight); +// atHeight.txt->setText( _atHeight.c_str() ); +// std::string _height = std::to_string(floor->getFloor().height); +// height.txt->setText( _height.c_str() ); +// } +// } + +// // has name +// { +// IHasName* elem = dynamic_cast(l); +// name.lbl->setVisible(elem); +// name.txt->setVisible(elem); +// if (elem) {name.txt->setText(elem->getName().c_str());} +// } + { - MMFloor* floor = dynamic_cast(l); - atHeight.lbl->setVisible(floor); - atHeight.txt->setVisible(floor); - height.lbl->setVisible(floor); - height.txt->setVisible(floor); - if (floor) { - std::string _atHeight = std::to_string(floor->getFloor().atHeight); - atHeight.txt->setText( _atHeight.c_str() ); - std::string _height = std::to_string(floor->getFloor().height); - height.txt->setText( _height.c_str() ); + IHasParams* elem = dynamic_cast(l); + if (elem) { + EditFields::get(lay, elem); } } - // has name - { - IHasName* elem = dynamic_cast(l); - name.lbl->setVisible(elem); - name.txt->setVisible(elem); - if (elem) {name.txt->setText(elem->getName().c_str());} - } - } diff --git a/params/LayerParamWidget.h b/params/LayerParamWidget.h index a445299..214bb00 100644 --- a/params/LayerParamWidget.h +++ b/params/LayerParamWidget.h @@ -8,11 +8,16 @@ class MapLayer; class QLabel; class QLineEdit; class QComboBox; +class QGridLayout; class LayerParamWidget : public QWidget { Q_OBJECT +private: + + QGridLayout* lay; + public: explicit LayerParamWidget(QWidget *parent = 0); diff --git a/params/LayerTree.cpp b/params/LayerTree.cpp new file mode 100644 index 0000000..df6ede8 --- /dev/null +++ b/params/LayerTree.cpp @@ -0,0 +1,92 @@ +#include "LayerTree.h" + +#include +#include +#include +#include + +#include "../tree/MapTreeModel.h" +#include "../UIHelper.h" + +LayerTree::LayerTree(QWidget *parent) : QWidget(parent) { + + QGridLayout* layGrid = new QGridLayout(this); + + tree = new QTreeView(this); + tree->setMinimumSize(150, 200); + + QWidget* wButtons = new QWidget(); + QHBoxLayout* layButtons = new QHBoxLayout(wButtons); + + btnNew = new QPushButton(this); + btnNew->setIcon(UIHelper::getIcon("add")); + btnNew->setMaximumSize(32,32); + btnNew->setMinimumSize(32,32); + btnNew->setEnabled(false); + layButtons->addWidget(btnNew); + + + btnDelete = new QPushButton(this); + btnDelete->setIcon(UIHelper::getIcon("remove")); + btnDelete->setMaximumSize(32,32); + btnDelete->setMinimumSize(32,32); + btnDelete->setEnabled(false); + layButtons->addWidget(btnDelete); + + layGrid->addWidget(tree, 0,0,1,1); + layGrid->addWidget(wButtons, 1, 0, 1, 1); + + connect(btnNew, SIGNAL(clicked(bool)), this, SLOT(onBtnNew())); + connect(btnDelete, SIGNAL(clicked(bool)), this, SLOT(onBtnDelete())); + + +} + +void LayerTree::expandAll() { + tree->expandAll(); +} + +void LayerTree::setModel(MapTreeModel* model) { + + this->model = model; + this->tree->setModel(model); + + // tree model selection events + if (!connect(tree->selectionModel(), SIGNAL(currentChanged(QModelIndex, QModelIndex)), this, SLOT(onLayerSelected(QModelIndex)))) {throw "error";} + +} + +void LayerTree::onLayerSelected(QModelIndex idx) { + + MapLayer* ml = static_cast(idx.internalPointer()); + + MMFloors* floors = dynamic_cast(ml); + btnNew->setEnabled( floors != nullptr ); + + MMFloor* floor = dynamic_cast(ml); + btnDelete->setEnabled( floor != nullptr ); + + emit layerSelected(idx); + +} + + +void LayerTree::onBtnNew() { + QModelIndex idx = tree->selectionModel()->selectedIndexes().first(); + MapLayer* ml = static_cast(idx.internalPointer()); + MMFloors* floors = dynamic_cast(ml); + if (floors) { + floors->createFloor(); + model->getMapModel()->reset(); + } +} + +void LayerTree::onBtnDelete() { + QModelIndex idx = tree->selectionModel()->selectedIndexes().first(); + MapLayer* ml = static_cast(idx.internalPointer()); + MMFloor* floor= dynamic_cast(ml); + if (floor) { + floor->deleteMe(); + model->getMapModel()->reset(); + } +} diff --git a/params/LayerTree.h b/params/LayerTree.h new file mode 100644 index 0000000..0044940 --- /dev/null +++ b/params/LayerTree.h @@ -0,0 +1,49 @@ +#ifndef LAYERTREE_H +#define LAYERTREE_H + +#include + +class QTreeView; +class QPushButton; +class MapTreeModel; + +#include + +class LayerTree : public QWidget { + + Q_OBJECT + +public: + + explicit LayerTree(QWidget *parent = 0); + + //QTreeView* getTree() const {return tree;} + + void setModel(MapTreeModel* model); + + void expandAll(); + +signals: + + void layerSelected(QModelIndex); + +private slots: + + void onLayerSelected(QModelIndex); + + void onBtnNew(); + + void onBtnDelete(); + +private: + + QTreeView* tree; + QPushButton* btnNew; + QPushButton* btnDelete; + MapTreeModel* model; + +public slots: + +}; + +#endif // LAYERTREE_H diff --git a/res.qrc b/res.qrc index 73ca53d..2c3bc59 100644 --- a/res.qrc +++ b/res.qrc @@ -14,5 +14,7 @@ res/icons/door.svg res/icons/cursor.svg res/icons/elevator.svg + res/icons/add.svg + res/icons/remove.svg diff --git a/res/icons/add.svg b/res/icons/add.svg new file mode 100644 index 0000000..5d43b92 --- /dev/null +++ b/res/icons/add.svg @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/icons/remove.svg b/res/icons/remove.svg new file mode 100644 index 0000000..97830d3 --- /dev/null +++ b/res/icons/remove.svg @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/icons/sources.txt b/res/icons/sources.txt new file mode 100644 index 0000000..b4be463 --- /dev/null +++ b/res/icons/sources.txt @@ -0,0 +1,8 @@ +www.flaticon.com +https://icons8.com/web-app/for/all/Ibeacon + + +# add +http://www.flaticon.com/free-icon/add-button-inside-black-circle_60740 +# remove +http://www.flaticon.com/free-icon/rounded-remove-button_60951#term=remove%20button&page=1&position=6 diff --git a/tree/MapTreeModel.h b/tree/MapTreeModel.h index e9fcae3..9ff442a 100644 --- a/tree/MapTreeModel.h +++ b/tree/MapTreeModel.h @@ -25,6 +25,10 @@ public: virtual ~MapTreeModel() {;} + MapModel* getMapModel() { + return mdl; + } + virtual QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override { MapLayer* _parent = nullptr;