From f40fc9a8237cbea56eb58b56eb3b741dd60c72d4 Mon Sep 17 00:00:00 2001 From: kazu Date: Fri, 10 Mar 2017 13:44:17 +0100 Subject: [PATCH] added a ruler for measuring 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 --- IndoorMap.pro | 14 +- MainController.cpp | 50 +++++- MainController.h | 28 +++- mapview/2D/tools/ToolMapZoom.h | 4 +- mapview/2D/tools/ToolMeasure.cpp | 0 mapview/2D/tools/ToolMeasure.h | 132 ++++++++++++++++ mapview/2D/tools/ToolSelector.h | 13 +- mapview/model/IHasEditableMeta.h | 21 +++ mapview/model/MMFloor.h | 2 +- mapview/model/MMFloorAccessPoint.h | 11 +- mapview/model/MMFloorAccessPoints.h | 4 +- mapview/model/MMFloorBeacons.h | 4 +- mapview/model/MMFloorElevators.h | 4 +- mapview/model/MMFloorObstacles.h | 12 +- mapview/model/MMFloorOutline.h | 19 +-- mapview/model/MMFloorOutlinePolygonCombined.h | 41 +++++ mapview/model/MMFloorPOIs.h | 4 +- mapview/model/MMFloorStairs.h | 4 +- mapview/model/MMFloorUnderlays.h | 4 +- mapview/model/MapLayer.h | 63 +++++++- mapview/model/MapLayerListener.h | 25 +++ mapview/model/MapModel.h | 50 ++++-- mapview/model/MapModelListener.h | 13 ++ params/ElementParamWidget.cpp | 51 +++--- params/MetaEditModel.cpp | 87 +++++++++++ params/MetaEditModel.h | 41 +++++ params/MetaEditWidget.cpp | 67 ++++++++ params/MetaEditWidget.h | 35 +++++ params/ToolBox.cpp | 147 ++++-------------- params/ToolBoxWidget.h | 6 +- res.qrc | 1 + res/icons/ruler.svg | 50 ++++++ 32 files changed, 809 insertions(+), 198 deletions(-) create mode 100644 mapview/2D/tools/ToolMeasure.cpp create mode 100644 mapview/2D/tools/ToolMeasure.h create mode 100644 mapview/model/IHasEditableMeta.h create mode 100644 mapview/model/MMFloorOutlinePolygonCombined.h create mode 100644 mapview/model/MapLayerListener.h create mode 100644 mapview/model/MapModelListener.h create mode 100644 params/MetaEditModel.cpp create mode 100644 params/MetaEditModel.h create mode 100644 params/MetaEditWidget.cpp create mode 100644 params/MetaEditWidget.h create mode 100644 res/icons/ruler.svg diff --git a/IndoorMap.pro b/IndoorMap.pro index 894d672..5f17cf7 100644 --- a/IndoorMap.pro +++ b/IndoorMap.pro @@ -38,7 +38,10 @@ SOURCES += \ mapview/3D/MapView3D.cpp \ params/StairBuilder.cpp \ mapview/2D/tools/Tools.cpp \ - params/LayerTree.cpp + params/LayerTree.cpp \ + mapview/2D/tools/ToolMeasure.cpp \ + params/MetaEditWidget.cpp \ + params/MetaEditModel.cpp HEADERS += MainWindow.h \ @@ -130,7 +133,14 @@ HEADERS += MainWindow.h \ mapview/model/MMFloorElevator.h \ params/LayerTree.h \ params/EditFields.h \ - mapview/2D/ClickDist.h + mapview/2D/ClickDist.h \ + mapview/2D/tools/ToolMeasure.h \ + mapview/model/IHasEditableMeta.h \ + params/MetaEditWidget.h \ + params/MetaEditModel.h \ + mapview/model/MapLayerListener.h \ + mapview/model/MapModelListener.h \ + mapview/model/MMFloorOutlinePolygonCombined.h FORMS += MainWindow.ui diff --git a/MainController.cpp b/MainController.cpp index e4ec417..b83a518 100644 --- a/MainController.cpp +++ b/MainController.cpp @@ -16,6 +16,7 @@ #include "params/ToolBoxWidget.h" #include "params/ActionWidget.h" #include "params/LayerTree.h" +#include "params/MetaEditWidget.h" #include "tree/MapTreeModel.h" @@ -28,6 +29,14 @@ MainController::MainController() { +// Floorplan::Meta* meta = new Floorplan::Meta(); +// meta->setVal("a", "b"); +// meta->setVal("c", "d"); +// MetaEditWidget* mew = new MetaEditWidget(meta); +// mew->resize(300,300); +// mew->show(); + + mw = new MainWindow(); mw->resize(1000, 700); @@ -44,11 +53,11 @@ MainController::MainController() { mapTreeModel = new MapTreeModel(mapModel); layerTree->setModel(mapTreeModel); - ToolMoveMap* moveMap = new ToolMoveMap(); - ToolRuler* ruler = new ToolRuler(); - ToolMapZoom* mapZoom = new ToolMapZoom(); - ToolMapGrid* mapGrid = new ToolMapGrid(); - ToolSelector* mapSelector = new ToolSelector(); + moveMap = new ToolMoveMap(); + ruler = new ToolRuler(); + mapZoom = new ToolMapZoom(); + mapGrid = new ToolMapGrid(); + mapSelector = new ToolSelector(); mapView2D->getTools().addBackground(mapGrid); mapView2D->getTools().addBackground(moveMap); @@ -68,6 +77,7 @@ MainController::MainController() { // model events connect(mapModel, SIGNAL(aboutToReset()), this, SLOT(onMapModelAboutToReset())); connect(mapModel, SIGNAL(reset()), this, SLOT(onMapModelReset())); + mapModel->addListener(this); // load/save connect(mw->getActionWidget(), SIGNAL(onLoad()), this, SLOT(onLoad())); @@ -83,7 +93,7 @@ MainController::MainController() { connect(mw, &MainWindow::onGridShowEdges, [&] (const bool show) {mw->getMapView3D()->getGridRenderer()->setShowEdges(show);} ); - //mapModel->load("../IndoorMap/maps/SHL25.xml"); + mapModel->load("../IndoorMap/maps/SHL26.xml"); //mapModel->load("../IndoorMap/maps/test.xml"); //mapModel->load("../IndoorMap/maps/APs.xml"); @@ -95,12 +105,34 @@ MainController::MainController() { //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/keller1.xml"); - mapModel->load("/mnt/vm/workspace/IRGame/IndoorServer/maps/wohnung3.xml"); + //mapModel->load("/mnt/vm/workspace/IRGame/IndoorServer/maps/wohnung4.xml"); //mapModel->startEmpty(); } + +void MainController::onLayerChanged(MapLayer* layer) { + (void) layer; + mw->getMapView2D()->update(); + mw->getMapView3D()->update(); +} + +void MainController::onLayerElementAdded(MapLayer* layer, MapModelElement* elem) { + (void) layer; + mapSelector->focus(mw->getMapView2D(), elem); +} + +void MainController::onLayerElementRemoved(MapLayer* layer, const MapModelElement* elem) { + (void) layer; + (void) elem; +} + +void MainController::onLayerVisibilityChanged(MapLayer *layer, const bool visible) { + (void) layer; + (void) visible; +} + void MainController::onShow3DFloorplan() { mw->getMapView3D()->showFloorplan(); } @@ -133,6 +165,10 @@ void MainController::onMapModelAboutToReset() { mw->getMapView2D()->update(); } +void MainController::onMapModelNeedsRepaint() { + mw->getMapView2D()->update(); +} + void MainController::onMapModelReset() { mw->getTree()->expandAll(); } diff --git a/MainController.h b/MainController.h index 6d39d0c..77a2dca 100644 --- a/MainController.h +++ b/MainController.h @@ -4,19 +4,44 @@ #include #include #include "MainWindow.h" +#include "mapview/model/MapModelListener.h" class MapTreeModel; class MapModelElement; class MapModel; -class MainController : public QObject { +class ToolMoveMap; +class ToolRuler; +class ToolMapZoom; +class ToolMapGrid; +class ToolSelector; + +class MainController : public QObject, public MapModelListener { + Q_OBJECT + ToolMoveMap* moveMap; + ToolRuler* ruler; + ToolMapZoom* mapZoom; + ToolMapGrid* mapGrid; + ToolSelector* mapSelector; + + public: explicit MainController(); void show() {mw->show();} +public: + + void onLayerChanged(MapLayer* layer) override; + + void onLayerElementAdded(MapLayer* layer, MapModelElement* elem) override; + + void onLayerElementRemoved(MapLayer* layer, const MapModelElement* elem) override; + + void onLayerVisibilityChanged(MapLayer *layer, const bool visible) override; + signals: public slots: @@ -37,6 +62,7 @@ public slots: void onMapModelAboutToReset(); void onMapModelReset(); + void onMapModelNeedsRepaint(); private slots: diff --git a/mapview/2D/tools/ToolMapZoom.h b/mapview/2D/tools/ToolMapZoom.h index d8468c5..f5fb4c5 100644 --- a/mapview/2D/tools/ToolMapZoom.h +++ b/mapview/2D/tools/ToolMapZoom.h @@ -20,9 +20,9 @@ public: Scaler& s = m->getScaler(); if (e->delta() < 0) { - s.setScale(s.getScale() * 0.5); + s.setScale(s.getScale() * 0.75); } else { - s.setScale(s.getScale() / 0.5); + s.setScale(s.getScale() / 0.75); } if (s.getScale() > 1000) {s.setScale(1000);} diff --git a/mapview/2D/tools/ToolMeasure.cpp b/mapview/2D/tools/ToolMeasure.cpp new file mode 100644 index 0000000..e69de29 diff --git a/mapview/2D/tools/ToolMeasure.h b/mapview/2D/tools/ToolMeasure.h new file mode 100644 index 0000000..1806c7f --- /dev/null +++ b/mapview/2D/tools/ToolMeasure.h @@ -0,0 +1,132 @@ +#ifndef TOOLMEASURE_H +#define TOOLMEASURE_H + + +#include "Tool.h" +#include "../MapView2D.h" + +#include "../../model/MapModelElement.h" +#include "../../model/MapModel.h" +#include "../MapViewElementHelper.h" + + +/** + * this tool allows: + * - selecting elements within the 2D view (focus/unfocus) + * - selecting and moving nodes of elements inheriting from HasMoveableNodes + * + */ +class ToolMeasure : public Tool { + + Q_OBJECT + + +protected: + + /** register this tool into the given tools-queue */ + Tools& tools; + Tool* oldMainTool; + + std::vector pts_m; + +public: + + /** ctor */ + ToolMeasure(Tools& tools) : tools(tools) { + + oldMainTool = tools.getMain(); // keep the current tool to reset it later + tools.setMain(this); + + resetMe(); + + } + + /** dtor */ + virtual ~ToolMeasure() { + tools.setMain(oldMainTool); // reset to the previous tool + } + + const std::string getName() const { + return "Measure"; + } + + virtual bool mousePressEvent(MapView2D*, QMouseEvent* e) override { + if (e->button() == Qt::MouseButton::LeftButton) { + pts_m.push_back(pts_m.back()); + return true; + } else { + return false; + } + } + + virtual bool mouseMoveEvent(MapView2D* m, QMouseEvent* e) override { + const Point2 onScreen(e->x(), e->y()); + Point2 onMap = m->getScaler().sm(onScreen); + onMap = m->getScaler().snap(onMap); + pts_m.back() = onMap; + return true; + } + + virtual bool mouseReleaseEvent(MapView2D*, QMouseEvent* e) override { + if (e->button() == Qt::MouseButton::LeftButton) { + return true; + } else if (e->button() == Qt::MouseButton::RightButton) { + resetMe(); + return true; + } else { + return false; + } + } + + virtual bool keyPressEvent(MapView2D* m, QKeyEvent* e) override { + (void) m; + if (e->key() == Qt::Key_Escape) { + disableMe(); + return true; + } + return false; + } + + virtual void paintAfter(MapView2D*, Painter& p) override { + + if (pts_m.size() < 1) {return;} + + p.setPen(Qt::black); + + for (const Point2 p_m : pts_m) { + p.drawCircle(p_m); + } + + float totalLen_m = 0; + for (size_t i = 0; i < pts_m.size() - 1; ++i) { + const Point2 p1 = pts_m[i]; + const Point2 p2 = pts_m[i+1]; + const float len_m = p1.getDistance(p2); + p.drawLine(p1, p2); + p.drawLength(p1, p2, len_m); + totalLen_m += len_m; + } + + if (pts_m.size() > 1) { + emit onHelpTextChange("total length is: " + QString::number(totalLen_m) + "m | right-click to restart"); + } + + } + +protected: + + + void resetMe() { + pts_m.resize(1); + emit onHelpTextChange("select the starting point for measuring"); + } + + /** finish creating new elements */ + void disableMe() { + delete this; // see dtor! + } + +}; + + +#endif // TOOLMEASURE_H diff --git a/mapview/2D/tools/ToolSelector.h b/mapview/2D/tools/ToolSelector.h index 054f022..07d09b1 100644 --- a/mapview/2D/tools/ToolSelector.h +++ b/mapview/2D/tools/ToolSelector.h @@ -46,6 +46,15 @@ public: setFocused(m, nullptr); } + /** + * @brief change the currently focused element. throws an event. + * @param el the to-be-focused element or null + * @return true if the focused element has changed. false otherwise + */ + bool focus(MapView2D* v, MapModelElement* el) { + setFocused(v, el); + } + private: void processUnfocus(MapView2D* m, MapModelElement* elem) { @@ -202,9 +211,11 @@ private: const float g = m->getScaler().sm(15); // increase each BBox by 15 px (needed mainly for hor/ver lines) +#warning "which elements to select? among all currently visible? or only among the selected layer?" // get all elements with bounding-box matchings std::vector possible; - for (MapModelElement* el : m->getModel()->getSelectedLayerElements()) { +// for (MapModelElement* el : m->getModel()->getSelectedLayerElements()) { + for (MapModelElement* el : m->getModel()->getVisibleElements()) { if (!el->getMV2D()) {continue;} BBox2 bbox = el->getMV2D()->getBoundingBox(); // elements 2D bbox bbox.grow(Point2(g, g)); // grow a little (needed for straight lines) diff --git a/mapview/model/IHasEditableMeta.h b/mapview/model/IHasEditableMeta.h new file mode 100644 index 0000000..e5a6d83 --- /dev/null +++ b/mapview/model/IHasEditableMeta.h @@ -0,0 +1,21 @@ +#ifndef IHASEDITABLEMETA_H +#define IHASEDITABLEMETA_H + +#include + +/** + * interface for all classes that provide editable meta information + */ +class IHasEditableMeta { + +public: + + /** get the meta-information object [if any] */ + virtual Floorplan::Meta* getMeta() = 0; + + /** set/overwrite the meta-information object */ + virtual void setMeta(Floorplan::Meta* meta) = 0; + +}; + +#endif // IHASEDITABLEMETA_H diff --git a/mapview/model/MMFloor.h b/mapview/model/MMFloor.h index 87e966d..8551ebe 100644 --- a/mapview/model/MMFloor.h +++ b/mapview/model/MMFloor.h @@ -36,7 +36,7 @@ public: 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)); + new MMFloorOutline(this, floor); new MMFloorObstacles(this, floor); new MMFloorAccessPoints(this, floor); new MMFloorBeacons(this, floor); diff --git a/mapview/model/MMFloorAccessPoint.h b/mapview/model/MMFloorAccessPoint.h index 66e3f18..f71ab5c 100644 --- a/mapview/model/MMFloorAccessPoint.h +++ b/mapview/model/MMFloorAccessPoint.h @@ -3,13 +3,14 @@ #include "MapModelElement.h" #include "IHasParams.h" +#include "IHasEditableMeta.h" #include "../2D/MV2DElementAccessPoint.h" #include "../3D/MV3DElementAccessPoint.h" #include -class MMFloorAccessPoint : public MapModelElement, public IHasParams { +class MMFloorAccessPoint : public MapModelElement, public IHasParams, public IHasEditableMeta { private: @@ -64,6 +65,14 @@ public: } } + virtual Floorplan::Meta* getMeta() override { + return ap->getMeta(); + } + + virtual void setMeta(Floorplan::Meta* meta) override { + ap->setMeta(meta); + } + MV2DElement* getMV2D() const override {return (MV2DElement*) &mv2d;} MV3DElement* getMV3D() const override {return (MV3DElement*) &mv3d;} diff --git a/mapview/model/MMFloorAccessPoints.h b/mapview/model/MMFloorAccessPoints.h index be64440..fb4c89c 100644 --- a/mapview/model/MMFloorAccessPoints.h +++ b/mapview/model/MMFloorAccessPoints.h @@ -22,7 +22,7 @@ public: // add all APs for (Floorplan::AccessPoint* ap : floor->accesspoints) { - elements.push_back(new MMFloorAccessPoint(this, floor, ap)); + addElement(new MMFloorAccessPoint(this, floor, ap)); } } @@ -36,7 +36,7 @@ public: floor->accesspoints.push_back(ap); // add to myself as element - elements.push_back(new MMFloorAccessPoint(this, floor, ap)); + addElement(new MMFloorAccessPoint(this, floor, ap)); } diff --git a/mapview/model/MMFloorBeacons.h b/mapview/model/MMFloorBeacons.h index 6c45b4f..af2079d 100644 --- a/mapview/model/MMFloorBeacons.h +++ b/mapview/model/MMFloorBeacons.h @@ -22,7 +22,7 @@ public: // add all Beacons for (Floorplan::Beacon* b : floor->beacons) { - elements.push_back(new MMFloorBeacon(this, floor, b)); + addElement(new MMFloorBeacon(this, floor, b)); } } @@ -36,7 +36,7 @@ public: floor->beacons.push_back(b); // add to myself as element - elements.push_back(new MMFloorBeacon(this, floor, b)); + addElement(new MMFloorBeacon(this, floor, b)); } }; diff --git a/mapview/model/MMFloorElevators.h b/mapview/model/MMFloorElevators.h index 7212d54..9b40b26 100644 --- a/mapview/model/MMFloorElevators.h +++ b/mapview/model/MMFloorElevators.h @@ -23,7 +23,7 @@ public: // add all elevators for (Floorplan::Elevator* elevator : floor->elevators) { - elements.push_back(new MMFloorElevator(this, floor, elevator)); + addElement(new MMFloorElevator(this, floor, elevator)); } } @@ -37,7 +37,7 @@ public: floor->elevators.push_back(elevator); // add to myself as element - elements.push_back(new MMFloorElevator(this, floor, elevator)); + addElement(new MMFloorElevator(this, floor, elevator)); } diff --git a/mapview/model/MMFloorObstacles.h b/mapview/model/MMFloorObstacles.h index c03c32a..02dac5e 100644 --- a/mapview/model/MMFloorObstacles.h +++ b/mapview/model/MMFloorObstacles.h @@ -23,11 +23,11 @@ public: // the obstacles for (Floorplan::FloorObstacle* o : floor->obstacles) { if (dynamic_cast(o)) { - elements.push_back(new MMFloorObstacleLine(this, floor, (Floorplan::FloorObstacleLine*)o)); + addElement(new MMFloorObstacleLine(this, floor, (Floorplan::FloorObstacleLine*)o)); } else if (dynamic_cast(o)) { - elements.push_back(new MMFloorObstacleCircle(this, floor, (Floorplan::FloorObstacleCircle*)o)); + addElement(new MMFloorObstacleCircle(this, floor, (Floorplan::FloorObstacleCircle*)o)); } else if (dynamic_cast(o)) { - elements.push_back(new MMFloorObstacleDoor(this, floor, (Floorplan::FloorObstacleDoor*)o)); + addElement(new MMFloorObstacleDoor(this, floor, (Floorplan::FloorObstacleDoor*)o)); } else { throw new Exception("todo: not yet implemented obstacle type"); } @@ -46,7 +46,7 @@ public: // add to myself as element MMFloorObstacleDoor* mm = new MMFloorObstacleDoor(this, floor, obs); - elements.push_back(mm); + addElement(mm); return mm; } @@ -59,7 +59,7 @@ public: // add to myself as element MMFloorObstacleLine* mm = new MMFloorObstacleLine(this, floor, obs); - elements.push_back(mm); + addElement(mm); return mm; } @@ -71,7 +71,7 @@ public: floor->obstacles.push_back(obs); // add to myself as element - elements.push_back(new MMFloorObstacleCircle(this, floor, obs)); + addElement(new MMFloorObstacleCircle(this, floor, obs)); } diff --git a/mapview/model/MMFloorOutline.h b/mapview/model/MMFloorOutline.h index e74d1a4..c66ee58 100644 --- a/mapview/model/MMFloorOutline.h +++ b/mapview/model/MMFloorOutline.h @@ -3,37 +3,38 @@ #include "MapLayer.h" #include "MMFloorOutlinePolygon.h" -#include "../3D/MV3DElementFloorOutline.h" +#include "MMFloorOutlinePolygonCombined.h" +#include "../3D/MV3DElementFloorOutline.h" #include /** * layer containing all elements describing a floor's outline */ -class MMFloorOutline : public MapLayer, public MapModelElement { +class MMFloorOutline : public MapLayer { private: /** the underlying model */ Floorplan::Floor* floor; - MV3DElementFloorOutline mv3d; public: /** ctor with the underlying model */ MMFloorOutline(MapLayer* parent, Floorplan::Floor* floor) : - MapLayer(parent, MapLayerType::FLOOR_GROUND), MapModelElement(parent), floor(floor), mv3d(floor, &floor->outline) { + MapLayer(parent, MapLayerType::FLOOR_GROUND), floor(floor) { - // the outline + // each polygon that is part of the outline for (Floorplan::FloorOutlinePolygon* poly : floor->outline) { - elements.push_back(new MMFloorOutlinePolygon(this, floor, poly)); + addElement(new MMFloorOutlinePolygon(this, floor, poly)); } - } + // for 3D, alle polygons [add/remove] are combined into one renderable polygons + addElement(new MMFloorOutlinePolygonCombined(this, floor)); - MV3DElement* getMV3D() const override {return (MV3DElement*) &mv3d;} + } /** get the corresponding floor from the underlying model */ @@ -46,7 +47,7 @@ public: floor->outline.push_back(poly); // add to myself as element - elements.push_back(new MMFloorOutlinePolygon(this, floor, poly)); + addElement(new MMFloorOutlinePolygon(this, floor, poly)); } diff --git a/mapview/model/MMFloorOutlinePolygonCombined.h b/mapview/model/MMFloorOutlinePolygonCombined.h new file mode 100644 index 0000000..7fa59a7 --- /dev/null +++ b/mapview/model/MMFloorOutlinePolygonCombined.h @@ -0,0 +1,41 @@ +#ifndef MMFLOOROUTLINEPOLYGONCOMBINED_H +#define MMFLOOROUTLINEPOLYGONCOMBINED_H + +#include "MapLayer.h" +#include "MMFloorOutlinePolygon.h" +#include "../3D/MV3DElementFloorOutline.h" + + +#include + +/** + * this element combines all polygons of one layer + * into one large, 3D renderable polygon + */ +class MMFloorOutlinePolygonCombined : public MapModelElement { + +private: + + /** the underlying model */ + Floorplan::Floor* floor; + + MV3DElementFloorOutline mv3d; + +public: + + /** ctor with the underlying model */ + MMFloorOutlinePolygonCombined(MapLayer* parent, Floorplan::Floor* floor) : + MapModelElement(parent), floor(floor), mv3d(floor, &floor->outline) { + + ; + + } + + MV3DElement* getMV3D() const override {return (MV3DElement*) &mv3d;} + + /** get the corresponding floor from the underlying model */ + Floorplan::Floor* getFloor() {return floor;} + +}; + +#endif // MMFLOOROUTLINEPOLYGONCOMBINED_H diff --git a/mapview/model/MMFloorPOIs.h b/mapview/model/MMFloorPOIs.h index efaa8d7..7b06945 100644 --- a/mapview/model/MMFloorPOIs.h +++ b/mapview/model/MMFloorPOIs.h @@ -20,7 +20,7 @@ public: // the POIs for (Floorplan::POI* poi : floor->pois) { - elements.push_back(new MMFloorPOI(this, floor, poi)); + addElement(new MMFloorPOI(this, floor, poi)); } } @@ -35,7 +35,7 @@ public: floor->pois.push_back(poi); // add to myself as element - elements.push_back(new MMFloorPOI(this, floor, poi)); + addElement(new MMFloorPOI(this, floor, poi)); } diff --git a/mapview/model/MMFloorStairs.h b/mapview/model/MMFloorStairs.h index ace1fce..1d81c7a 100644 --- a/mapview/model/MMFloorStairs.h +++ b/mapview/model/MMFloorStairs.h @@ -23,7 +23,7 @@ public: // add all floors for (Floorplan::Stair* stair : floor->stairs) { if (dynamic_cast(stair)) { - elements.push_back( new MMFloorStair(this, floor, (Floorplan::StairFreeform*)stair) ); + addElement( new MMFloorStair(this, floor, (Floorplan::StairFreeform*)stair) ); } } @@ -35,7 +35,7 @@ public: floor->stairs.push_back(stair); // add to myself as element - elements.push_back(new MMFloorStair(this, floor, stair)); + addElement(new MMFloorStair(this, floor, stair)); } diff --git a/mapview/model/MMFloorUnderlays.h b/mapview/model/MMFloorUnderlays.h index da25db0..e50260d 100644 --- a/mapview/model/MMFloorUnderlays.h +++ b/mapview/model/MMFloorUnderlays.h @@ -23,7 +23,7 @@ public: // the underlays for (Floorplan::UnderlayImage* img : floor->underlays) { - elements.push_back(new MMFloorUnderlayImage(this, floor, img)); + addElement(new MMFloorUnderlayImage(this, floor, img)); } } @@ -38,7 +38,7 @@ public: // add to myself as element MMFloorUnderlayImage* img = new MMFloorUnderlayImage(this, floor, elem); - elements.push_back(img); + addElement(img); img->setAnchor(center); img->setScale(0.1, 0.1); diff --git a/mapview/model/MapLayer.h b/mapview/model/MapLayer.h index 506a016..832502e 100644 --- a/mapview/model/MapLayer.h +++ b/mapview/model/MapLayer.h @@ -5,6 +5,8 @@ #include #include +#include "MapLayerListener.h" + class MapModelElement; @@ -27,14 +29,17 @@ enum class MapLayerType { class MapLayer { + /** this layer's elements */ + std::vector elements; + + /** attached listeners (if any) */ + std::vector listeners; + protected: /** this layer's parent */ MapLayer* parent; - /** this layer's elements */ - std::vector elements; - /** this layer's sublayers */ std::vector sublayers; @@ -59,6 +64,11 @@ public: /** dtor */ virtual ~MapLayer() {;} + /** attach a listener to this layer [usually only added to the root layer] */ + void addListener(MapLayerListener* listener) { + listeners.push_back(listener); + } + /** get the layer's parent */ MapLayer* getParent() const {return parent;} @@ -76,7 +86,16 @@ public: size_t getNumElements() const {return elements.size();} /** remove the given element from the elements list */ - void removeElement(const MapModelElement* elem) { elements.erase(std::remove(elements.begin(), elements.end(), elem), elements.end()); } + void removeElement(const MapModelElement* elem) { + elements.erase(std::remove(elements.begin(), elements.end(), elem), elements.end()); + onElemRemoved(elem); + } + + /** add a new element to this layer */ + void addElement(MapModelElement* el) { + elements.push_back(el); + onElemAdded(el); + } /** remove the given sublayer from this layer */ void removeSublayer(const MapLayer* layer) { sublayers.erase(std::remove(sublayers.begin(), sublayers.end(), layer), sublayers.end()); } @@ -85,7 +104,10 @@ public: bool isVisible() const {return visible;} /** make this layer visible */ - void setVisible(const bool visible) {this->visible = visible;} + void setVisible(const bool visible) { + this->visible = visible; + onVisibilityChanged(visible); + } /** get all sub-layers within this layer */ @@ -95,7 +117,7 @@ public: /** helper method to get all elements and those of all sub-layers */ void getVisibleElementsRecursive(std::vector& el) { if (isVisible()) { - std::vector local = getElements(); + const std::vector local = getElements(); el.insert(el.end(), local.begin(), local.end()); for (MapLayer* sub : getSubLayers()) { sub->getVisibleElementsRecursive(el); @@ -105,8 +127,6 @@ public: public: - - /** add a new sublayer to this layer */ void addSublayer(MapLayer* ml) { @@ -116,8 +136,35 @@ public: } +private: + + void onElemAdded(MapModelElement* e) { + if (parent) {parent->onElemAdded(e);} + for (MapLayerListener* listener : listeners) { + listener->onLayerChanged(this); + listener->onLayerElementAdded(this, e); + } + } + + void onElemRemoved(const MapModelElement* e) { + if (parent) {parent->onElemRemoved(e);} + for (MapLayerListener* listener : listeners) { + listener->onLayerChanged(this); + listener->onLayerElementRemoved(this, e); + } + } + + void onVisibilityChanged(const bool visibile) { + if (parent) {parent->onVisibilityChanged(visibile);} + for (MapLayerListener* listener : listeners) { + listener->onLayerChanged(this); + listener->onLayerVisibilityChanged(this, visibile); + } + } + }; + class MapLayerRoot : public MapLayer { public: diff --git a/mapview/model/MapLayerListener.h b/mapview/model/MapLayerListener.h new file mode 100644 index 0000000..72e29cd --- /dev/null +++ b/mapview/model/MapLayerListener.h @@ -0,0 +1,25 @@ +#ifndef MAPLAYERLISTENER_H +#define MAPLAYERLISTENER_H + +class MapLayer; +class MapModelElement; + +class MapLayerListener { + +public: + + /** the map layer has changed. e.g. new elements were added */ + virtual void onLayerChanged(MapLayer* layer) = 0; + + /** a new element was added to a layer */ + virtual void onLayerElementAdded(MapLayer* layer, MapModelElement* elem) = 0; + + /** an element was removed from the layer */ + virtual void onLayerElementRemoved(MapLayer* layer, const MapModelElement* elem) = 0; + + /** the layer's visibility has changed */ + virtual void onLayerVisibilityChanged(MapLayer* layer, const bool visible) = 0; + +}; + +#endif // MAPLAYERLISTENER_H diff --git a/mapview/model/MapModel.h b/mapview/model/MapModel.h index b92c35a..19a9be2 100644 --- a/mapview/model/MapModel.h +++ b/mapview/model/MapModel.h @@ -5,6 +5,7 @@ #include "MapLayer.h" #include "MapModelElement.h" +#include "MapModelListener.h" #include "MMRoot.h" @@ -13,7 +14,7 @@ #include #include -class MapModel : public QObject { +class MapModel : public QObject, public MapLayerListener { Q_OBJECT @@ -31,6 +32,9 @@ private: /** the loaded floorplan */ Floorplan::IndoorMap* im; + /** listener */ + std::vector listeners; + public: /** ctor */ @@ -42,10 +46,16 @@ public: cleanup(); } + /** attach a listener */ + void addListener(MapModelListener* l) { + listeners.push_back(l); + } + /** create a new, empty root node */ void startEmpty() { im = new Floorplan::IndoorMap(); root = new MMRoot(nullptr, im); + root->addListener(this); //root->addSublayer(new MMFloors(root, im)); } @@ -64,6 +74,7 @@ public: // load the indoor-map using the given XML-file im = Floorplan::Reader::readFromFile(file); root = new MMRoot(nullptr, im); + root->addListener(this); emit reset(); @@ -75,6 +86,22 @@ public: } + void onLayerChanged(MapLayer* layer) override { + for (MapModelListener* l : listeners) {l->onLayerChanged(layer);} + } + + void onLayerElementAdded(MapLayer* layer, MapModelElement* elem) override { + for (MapModelListener* l : listeners) {l->onLayerElementAdded(layer, elem);} + } + + void onLayerElementRemoved(MapLayer* layer, const MapModelElement* elem) override { + for (MapModelListener* l : listeners) {l->onLayerElementRemoved(layer, elem);} + } + + void onLayerVisibilityChanged(MapLayer* layer, const bool visible) override { + for (MapModelListener* l : listeners) {l->onLayerVisibilityChanged(layer, visible);} + } + /** get the constructed map */ Floorplan::IndoorMap* getMap() const { return im; @@ -83,18 +110,21 @@ public: /** get the map's root-layer containing all other layers */ MapLayer* getRootLayer() { return root; } - /** get all elements within the currently selected layer */ - std::vector getSelectedLayerElements() { - //return selElements; - //return (selLayer) ? (selLayer->getElementsRecursive()) : (std::vector()); - std::vector elements; - root->getVisibleElementsRecursive(elements); - return elements; - } +// /** get all elements within the currently selected layer */ +// std::vector getSelectedLayerElements() { +// //return selElements; +// //return (selLayer) ? (selLayer->getElementsRecursive()) : (std::vector()); +//// std::vector elements; +//// root->getVisibleElementsRecursive(elements); +//// return elements; + +// } /** get all currently visible elements */ std::vector getVisibleElements() { - return getSelectedLayerElements(); + std::vector elements; + root->getVisibleElementsRecursive(elements); + return elements; } /** set the currently selected layer */ diff --git a/mapview/model/MapModelListener.h b/mapview/model/MapModelListener.h new file mode 100644 index 0000000..fca2878 --- /dev/null +++ b/mapview/model/MapModelListener.h @@ -0,0 +1,13 @@ +#ifndef MAPMODELLISTENER_H +#define MAPMODELLISTENER_H + +#include "MapLayerListener.h" + +/** + * listen for changes to the map model + */ +class MapModelListener : public MapLayerListener { + +}; + +#endif // MAPMODELLISTENER_H diff --git a/params/ElementParamWidget.cpp b/params/ElementParamWidget.cpp index da6b42c..a6cff09 100644 --- a/params/ElementParamWidget.cpp +++ b/params/ElementParamWidget.cpp @@ -4,9 +4,10 @@ #include "../mapview/model/MMFloorObstacleLine.h" #include "../mapview/model/MMFloorOutlinePolygon.h" -#include "../mapview/model/IHasMAC.h" -#include "../mapview/model/IHasFile.h" #include "../mapview/model/IHasParams.h" +#include "../mapview/model/IHasEditableMeta.h" + +#include "MetaEditWidget.h" #include @@ -138,13 +139,15 @@ void ElementParamWidget::refresh() { lay->addWidget(cmb,r,1); cmb->setCurrentIndex((int)elem->getMethod()); connect(cmb, static_cast(&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(el); if (elem) { @@ -160,6 +163,9 @@ void ElementParamWidget::refresh() { switch(param.type) { + case ParamType::NOT_AVAILABLE: + break; + case ParamType::BOOL: { QCheckBox* chk = new QCheckBox( ); chk->setChecked(value.toBool()); @@ -216,6 +222,7 @@ void ElementParamWidget::refresh() { 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); @@ -235,6 +242,7 @@ void ElementParamWidget::refresh() { 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); @@ -269,6 +277,23 @@ void ElementParamWidget::refresh() { } } + + { // does the element have editable metadata? + IHasEditableMeta* elem = dynamic_cast(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); @@ -294,23 +319,3 @@ void ElementParamWidget::onObstacleTypeChange() { IHasObstacleType* el = dynamic_cast(this->curElement); if (el) {el->setObstacleType((Floorplan::ObstacleType) obstacleType.cmb->currentData().toInt() );} } - -//void ElementParamWidget::onNameChange() { -// IHasName* el = dynamic_cast(this->curElement); -// if (el) {el->setName(name.txt->text().toStdString());} -//} - -//void ElementParamWidget::onOutlineMethodChange() { -// MMFloorOutlinePolygon* el = dynamic_cast(this->curElement); -// if (el) {el->setMethod( (Floorplan::OutlineMethod) outlineMethod.cmb->currentData().toInt() );} -//} - -//void ElementParamWidget::onMACChanged() { -// dynamic_cast(curElement)->setMAC(mac.txt->text().toStdString()); -//} - -//void ElementParamWidget::onSelectFileName() { -// QString res = QFileDialog::getOpenFileName(this); -// dynamic_cast(curElement)->setFileName(res.toStdString()); -// fileName.txt->setText(res); -//} diff --git a/params/MetaEditModel.cpp b/params/MetaEditModel.cpp new file mode 100644 index 0000000..0667c9c --- /dev/null +++ b/params/MetaEditModel.cpp @@ -0,0 +1,87 @@ +#include "MetaEditModel.h" + + +MetaEditModel::MetaEditModel(QObject* parent) : QAbstractTableModel(parent) { + + setHeaderData(0, Qt::Horizontal, QObject::tr("ID")); + setHeaderData(1, Qt::Horizontal, QObject::tr("Name")); +} + +void MetaEditModel::setSource(Floorplan::Meta* meta) { + beginResetModel(); + this->meta = meta; + endResetModel(); +} + +int MetaEditModel::rowCount(const QModelIndex &parent) const { + return (meta) ? (meta->size()) : (0); +} + +int MetaEditModel::columnCount(const QModelIndex &parent) const { + return 2; +} + +QVariant MetaEditModel::data(const QModelIndex &index, int role) const { + + if (role == Qt::DisplayRole) { + switch(index.column()) { + case 0: return meta->getKey(index.row()).c_str(); + case 1: return meta->getVal(index.row()).c_str(); + } + } + + return QVariant(); + +} + +bool MetaEditModel::setData(const QModelIndex & index, const QVariant &value, int role) { + + if (role == Qt::EditRole) { + switch(index.column()) { + case 0: meta->setKey(index.row(), value.toString().toStdString()); return true; + case 1: meta->setVal(index.row(), value.toString().toStdString()); return true; + } + } + + return false; + +} + +void MetaEditModel::deleteEntry(const int idx) { + beginResetModel(); + meta->deleteEntry(idx); + endResetModel(); +} + +void MetaEditModel::addEntry() { + beginResetModel(); + meta->add("key", "val"); + endResetModel(); +} + +Qt::ItemFlags MetaEditModel::flags(const QModelIndex &index) const { + + if (!index.isValid()) {return Qt::ItemIsEnabled;} + + return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable; + +} + + + + +QVariant MetaEditModel::headerData(int section, Qt::Orientation orientation, int role) const { + + if (role == Qt::DisplayRole) { + if(orientation == Qt::Horizontal) { + if (section == 0) {return "key";} + if (section == 1) {return "value";} + } else { + return QString::number(section); + } + } + + return QVariant(); + +} + diff --git a/params/MetaEditModel.h b/params/MetaEditModel.h new file mode 100644 index 0000000..22f9fb1 --- /dev/null +++ b/params/MetaEditModel.h @@ -0,0 +1,41 @@ +#ifndef METAEDITMODEL_H +#define METAEDITMODEL_H + +#include +#include + +class MetaEditModel : public QAbstractTableModel { + + Q_OBJECT + +private: + + Floorplan::Meta* meta = nullptr; + +public: + + MetaEditModel(QObject* parent = nullptr); + + /** delete the idx-th entry */ + void deleteEntry(const int idx); + + /** add a new entry at the end */ + void addEntry(); + + void setSource(Floorplan::Meta* meta); + + int rowCount(const QModelIndex& parent) const override; + + int columnCount(const QModelIndex& parent) const override; + + Qt::ItemFlags flags(const QModelIndex &index) const override; + + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; + + QVariant headerData(int section, Qt::Orientation orientation, int role) const override; + + bool setData(const QModelIndex & index, const QVariant &value, int role = Qt::EditRole) override; + +}; + +#endif // METAEDITMODEL_H diff --git a/params/MetaEditWidget.cpp b/params/MetaEditWidget.cpp new file mode 100644 index 0000000..a574113 --- /dev/null +++ b/params/MetaEditWidget.cpp @@ -0,0 +1,67 @@ +#include "MetaEditWidget.h" +#include "MetaEditModel.h" + +#include +#include +#include +#include + +MetaEditWidget::MetaEditWidget(Floorplan::Meta* meta) : QWidget(nullptr), metaOrig(meta) { + + // local copy. for the abort button [orig is unchanged] + metaCopy.params = metaOrig->params; + + QGridLayout* lay = new QGridLayout(this); + + tbl = new QTableView(); + lay->addWidget(tbl, 0, 0, 1, 3); + + model = new MetaEditModel(); + model->setSource(&metaCopy); // we edit the copy + + tbl->setModel(model); + tbl->setSelectionBehavior(QAbstractItemView::SelectRows); + tbl->setSelectionMode(QAbstractItemView::SingleSelection); + + + // events + QPushButton* btnAdd = new QPushButton("add entry"); + lay->addWidget(btnAdd, 1, 0); + btnAdd->connect(btnAdd, &QPushButton::clicked, [this] (const bool) { + model->addEntry(); + }); + btnAdd->setToolTip("add a new, empty entry. delete an entry using the keyboard"); + + QPushButton* btnCancel = new QPushButton("abort"); + lay->addWidget(btnCancel, 1, 1); + btnCancel->connect(btnCancel, &QPushButton::clicked, [this] (const bool) { + // do not apply changes. juts close + close(); + }); + btnCancel->setToolTip("close the dialog without committing the changes"); + + QPushButton* btnOK = new QPushButton("OK"); + lay->addWidget(btnOK, 1, 2); + btnOK->connect(btnOK, &QPushButton::clicked, [this] (const bool) { + metaOrig->params = metaCopy.params; // apply changed + close(); + }); + btnOK->setToolTip("commit the changes and close the dialog"); + + + // sizing + resize(500,400); + +} + +void MetaEditWidget::keyPressEvent(QKeyEvent* e) { + + if (e->key() == Qt::Key_Delete) { + QModelIndexList indices = tbl->selectionModel()->selectedIndexes(); + for (const QModelIndex& idx : indices) { + model->deleteEntry(idx.row()); + break; // the list contains one entry per column! + } + } + +} diff --git a/params/MetaEditWidget.h b/params/MetaEditWidget.h new file mode 100644 index 0000000..6e4d6ec --- /dev/null +++ b/params/MetaEditWidget.h @@ -0,0 +1,35 @@ +#ifndef METAEDITWIDGET_H +#define METAEDITWIDGET_H + +#include +#include + +class MetaEditModel; +class QTableView; + +/** + * helper class to edit the Floorplan::Meta + * key value attribute + */ +class MetaEditWidget : public QWidget { + + Q_OBJECT + +private: + + Floorplan::Meta* metaOrig; + Floorplan::Meta metaCopy; // used for the abort button + + MetaEditModel* model; + + QTableView* tbl; + +public: + + MetaEditWidget(Floorplan::Meta* meta); + + void keyPressEvent(QKeyEvent* e); + +}; + +#endif // METAEDITWIDGET_H diff --git a/params/ToolBox.cpp b/params/ToolBox.cpp index 080375c..9266281 100644 --- a/params/ToolBox.cpp +++ b/params/ToolBox.cpp @@ -13,8 +13,19 @@ #include "../mapview/model/MMFloorAccessPoint.h" #include "../mapview/model/MMFloorBeacon.h" +#include "../mapview/2D/tools/ToolMeasure.h" + #include "../UIHelper.h" +QSplitter* getSplitter() { + + QSplitter* splt = new QSplitter(); + splt->setStyleSheet("background-color:black;"); + splt->setMinimumHeight(1); + return splt; + +} + ToolBoxWidget::ToolBoxWidget(MapView2D* view, QWidget *parent) : QWidget(parent), view(view) { const int s = 32; @@ -30,6 +41,16 @@ ToolBoxWidget::ToolBoxWidget(MapView2D* view, QWidget *parent) : QWidget(parent) connect(btnSelect, SIGNAL(clicked(bool)), this, SLOT(onSelect())); + // MEASURE + btnMeasure = new QPushButton(UIHelper::getIcon("ruler"), ""); + btnMeasure->setMinimumSize(s,s); + lay->addWidget(btnMeasure, r++, 0, 1,1,Qt::AlignTop); + connect(btnMeasure, SIGNAL(clicked(bool)), this, SLOT(onMeasure())); + + + // splitter + lay->addWidget(getSplitter(), r++, 0, 1,1,Qt::AlignTop); + // OBSTACLES btnGround = new QPushButton(UIHelper::getIcon("floor"), ""); @@ -63,6 +84,10 @@ ToolBoxWidget::ToolBoxWidget(MapView2D* view, QWidget *parent) : QWidget(parent) connect(btnElevator, SIGNAL(clicked(bool)), this, SLOT(onNewElevator())); + // splitter + lay->addWidget(getSplitter(), r++, 0, 1,1,Qt::AlignTop); + + // TRANSMITTERS btnWifi = new QPushButton(UIHelper::getIcon("wifi"), ""); btnWifi->setMinimumSize(s,s); @@ -342,116 +367,25 @@ public: }; -//struct NewLineTool : public Tool { - -// /** add another line after this one? */ -// bool multiple = true; - -// /** register this tool into the given tools-queue */ -// Tools& tools; - -// /** the layer to add the new line to */ -// MapLayer* layer; - -// /** currently edited line */ -// Floorplan::FloorObstacleLine* foLine; -// MMFloorObstacleLine* mmLine; - -// /** new line type */ -// Floorplan::ObstacleType type; - -// /** new line material */ -// Floorplan::Material mat; - -// /** currently edited line node (has 2) */ -// int idx = 0; - - -// NewLineTool(Tools& tools, MapLayer* layer, Floorplan::ObstacleType type, Floorplan::Material mat) : tools(tools), layer(layer), type(type), mat(mat) { -// createEmptyLine(); -// tools.addFront(this); -// } - -// virtual bool mousePressEvent(MapView2D* m, QMouseEvent* e) override { -// (void) m; (void) e; -// return true; -// } - -// virtual bool mouseMoveEvent(MapView2D* m, QMouseEvent* e) override { -// const Point2 onScreen(e->x(), e->y()); -// Point2 onMap = m->getScaler().sm(onScreen); -// onMap = m->getScaler().snap(onMap); -// if (idx == 0) { foLine->from = onMap; foLine->to = onMap; } -// if (idx == 1) { foLine->to = onMap; } -// return true; -// } - -// virtual bool mouseReleaseEvent(MapView2D* m, QMouseEvent* e) override { -// (void) m; (void) e; -// ++idx; -// if (idx == 2) { - -// finalizeLine(); - -// if (multiple) { -// idx = 0; -// createEmptyLine(); -// } else { -// disableMe(); -// } -// } -// return true; -// } - -// virtual bool keyPressEvent(MapView2D* m, QKeyEvent* e) override { -// (void) m; -// if (e->key() == Qt::Key_Escape) { -// if (mmLine) {mmLine->deleteMe();} -// disableMe(); return true; -// } -// return false; -// } - -//private: - -// /** finalize the current line */ -// void finalizeLine() { -// if (!mmLine) {return;} -// mmLine->getMV2D()->unfocus(); -// mmLine = nullptr; -// } - -// /** stop creating new lines */ -// void disableMe() { -// finalizeLine(); -// tools.remove(this); -// delete this; -// } - -// /** create a new, empty line */ -// void createEmptyLine() { -// foLine = new Floorplan::FloorObstacleLine(type, mat, Point2(0, 0), Point2(0, 0)); -// MMFloorObstacles* obs = (MMFloorObstacles*)layer; -// mmLine = obs->createLine(foLine); -// mmLine->getMV2D()->focus(); -// } - -//}; - - - - void ToolBoxWidget::onSelect() { +} + +void ToolBoxWidget::onMeasure() { + + new ToolMeasure(view->getTools()); } + void ToolBoxWidget::onNewWall() { + new NewWallTool(view->getTools(), curLayer); //view->getModel()->reselect(); + } void ToolBoxWidget::onNewPillar() { @@ -476,21 +410,6 @@ void ToolBoxWidget::onNewDoor() { new NewDoorTool(view->getTools(), curLayer); -// const Point2 center = view->getScaler().getCenter(); -// float s = view->getScaler().sm(50); - -// Floorplan::FloorObstacleDoor* door = new Floorplan::FloorObstacleDoor( -// Floorplan::DoorType::SWING, -// Floorplan::Material::WOOD, -// Point2(center.x-s, center.y), -// Point2(center.x+s, center.y) -// ); - -// MMFloorObstacles* obs = (MMFloorObstacles*)curLayer; -// obs->createDoor(door); - - //view->getModel()->reselect(); - } void ToolBoxWidget::onNewStair() { diff --git a/params/ToolBoxWidget.h b/params/ToolBoxWidget.h index be020a9..4814f1b 100644 --- a/params/ToolBoxWidget.h +++ b/params/ToolBoxWidget.h @@ -8,7 +8,9 @@ class QPushButton; class MapView2D; /** - * gui element with actions to perform + * the toolbox on the left of the map. + * gui element with actions to perform. + * add new elements, etc. */ class ToolBoxWidget : public QWidget { @@ -32,6 +34,7 @@ private: int r = 0; QPushButton* btnSelect; + QPushButton* btnMeasure; QPushButton* btnGround; QPushButton* btnWall; @@ -49,6 +52,7 @@ private: private slots: void onSelect(); + void onMeasure(); void onNewGround(); void onNewWall(); diff --git a/res.qrc b/res.qrc index 2c3bc59..e7ab3e0 100644 --- a/res.qrc +++ b/res.qrc @@ -16,5 +16,6 @@ res/icons/elevator.svg res/icons/add.svg res/icons/remove.svg + res/icons/ruler.svg diff --git a/res/icons/ruler.svg b/res/icons/ruler.svg new file mode 100644 index 0000000..e1b6e7c --- /dev/null +++ b/res/icons/ruler.svg @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +