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
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -4,19 +4,44 @@
|
||||
#include <QObject>
|
||||
#include <QModelIndex>
|
||||
#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:
|
||||
|
||||
|
||||
@@ -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);}
|
||||
|
||||
0
mapview/2D/tools/ToolMeasure.cpp
Normal file
0
mapview/2D/tools/ToolMeasure.cpp
Normal file
132
mapview/2D/tools/ToolMeasure.h
Normal file
132
mapview/2D/tools/ToolMeasure.h
Normal file
@@ -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<Point2> 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
|
||||
@@ -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<MapModelElement*> 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)
|
||||
|
||||
21
mapview/model/IHasEditableMeta.h
Normal file
21
mapview/model/IHasEditableMeta.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#ifndef IHASEDITABLEMETA_H
|
||||
#define IHASEDITABLEMETA_H
|
||||
|
||||
#include <Indoor/floorplan/v2/Floorplan.h>
|
||||
|
||||
/**
|
||||
* 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
|
||||
@@ -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);
|
||||
|
||||
@@ -3,13 +3,14 @@
|
||||
|
||||
#include "MapModelElement.h"
|
||||
#include "IHasParams.h"
|
||||
#include "IHasEditableMeta.h"
|
||||
|
||||
#include "../2D/MV2DElementAccessPoint.h"
|
||||
#include "../3D/MV3DElementAccessPoint.h"
|
||||
|
||||
#include <Indoor/floorplan/v2/Floorplan.h>
|
||||
|
||||
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;}
|
||||
|
||||
|
||||
@@ -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));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -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));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -23,11 +23,11 @@ public:
|
||||
// the obstacles
|
||||
for (Floorplan::FloorObstacle* o : floor->obstacles) {
|
||||
if (dynamic_cast<Floorplan::FloorObstacleLine*>(o)) {
|
||||
elements.push_back(new MMFloorObstacleLine(this, floor, (Floorplan::FloorObstacleLine*)o));
|
||||
addElement(new MMFloorObstacleLine(this, floor, (Floorplan::FloorObstacleLine*)o));
|
||||
} else if (dynamic_cast<Floorplan::FloorObstacleCircle*>(o)) {
|
||||
elements.push_back(new MMFloorObstacleCircle(this, floor, (Floorplan::FloorObstacleCircle*)o));
|
||||
addElement(new MMFloorObstacleCircle(this, floor, (Floorplan::FloorObstacleCircle*)o));
|
||||
} else if (dynamic_cast<Floorplan::FloorObstacleDoor*>(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));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -3,37 +3,38 @@
|
||||
|
||||
#include "MapLayer.h"
|
||||
#include "MMFloorOutlinePolygon.h"
|
||||
#include "../3D/MV3DElementFloorOutline.h"
|
||||
#include "MMFloorOutlinePolygonCombined.h"
|
||||
|
||||
#include "../3D/MV3DElementFloorOutline.h"
|
||||
|
||||
#include <Indoor/floorplan/v2/Floorplan.h>
|
||||
|
||||
/**
|
||||
* 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));
|
||||
|
||||
}
|
||||
|
||||
|
||||
41
mapview/model/MMFloorOutlinePolygonCombined.h
Normal file
41
mapview/model/MMFloorOutlinePolygonCombined.h
Normal file
@@ -0,0 +1,41 @@
|
||||
#ifndef MMFLOOROUTLINEPOLYGONCOMBINED_H
|
||||
#define MMFLOOROUTLINEPOLYGONCOMBINED_H
|
||||
|
||||
#include "MapLayer.h"
|
||||
#include "MMFloorOutlinePolygon.h"
|
||||
#include "../3D/MV3DElementFloorOutline.h"
|
||||
|
||||
|
||||
#include <Indoor/floorplan/v2/Floorplan.h>
|
||||
|
||||
/**
|
||||
* 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
|
||||
@@ -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));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ public:
|
||||
// add all floors
|
||||
for (Floorplan::Stair* stair : floor->stairs) {
|
||||
if (dynamic_cast<Floorplan::StairFreeform*>(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));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
#include "MapLayerListener.h"
|
||||
|
||||
class MapModelElement;
|
||||
|
||||
|
||||
@@ -27,14 +29,17 @@ enum class MapLayerType {
|
||||
|
||||
class MapLayer {
|
||||
|
||||
/** this layer's elements */
|
||||
std::vector<MapModelElement*> elements;
|
||||
|
||||
/** attached listeners (if any) */
|
||||
std::vector<MapLayerListener*> listeners;
|
||||
|
||||
protected:
|
||||
|
||||
/** this layer's parent */
|
||||
MapLayer* parent;
|
||||
|
||||
/** this layer's elements */
|
||||
std::vector<MapModelElement*> elements;
|
||||
|
||||
/** this layer's sublayers */
|
||||
std::vector<MapLayer*> 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<MapModelElement*>& el) {
|
||||
if (isVisible()) {
|
||||
std::vector<MapModelElement*> local = getElements();
|
||||
const std::vector<MapModelElement*> 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:
|
||||
|
||||
25
mapview/model/MapLayerListener.h
Normal file
25
mapview/model/MapLayerListener.h
Normal file
@@ -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
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include "MapLayer.h"
|
||||
#include "MapModelElement.h"
|
||||
#include "MapModelListener.h"
|
||||
|
||||
#include "MMRoot.h"
|
||||
|
||||
@@ -13,7 +14,7 @@
|
||||
#include <Indoor/floorplan/v2/FloorplanReader.h>
|
||||
#include <Indoor/floorplan/v2/FloorplanWriter.h>
|
||||
|
||||
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<MapModelListener*> 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<MapModelElement*> getSelectedLayerElements() {
|
||||
//return selElements;
|
||||
//return (selLayer) ? (selLayer->getElementsRecursive()) : (std::vector<MapModelElement*>());
|
||||
std::vector<MapModelElement*> elements;
|
||||
root->getVisibleElementsRecursive(elements);
|
||||
return elements;
|
||||
}
|
||||
// /** get all elements within the currently selected layer */
|
||||
// std::vector<MapModelElement*> getSelectedLayerElements() {
|
||||
// //return selElements;
|
||||
// //return (selLayer) ? (selLayer->getElementsRecursive()) : (std::vector<MapModelElement*>());
|
||||
//// std::vector<MapModelElement*> elements;
|
||||
//// root->getVisibleElementsRecursive(elements);
|
||||
//// return elements;
|
||||
|
||||
// }
|
||||
|
||||
/** get all currently visible elements */
|
||||
std::vector<MapModelElement*> getVisibleElements() {
|
||||
return getSelectedLayerElements();
|
||||
std::vector<MapModelElement*> elements;
|
||||
root->getVisibleElementsRecursive(elements);
|
||||
return elements;
|
||||
}
|
||||
|
||||
/** set the currently selected layer */
|
||||
|
||||
13
mapview/model/MapModelListener.h
Normal file
13
mapview/model/MapModelListener.h
Normal file
@@ -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
|
||||
@@ -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 <Indoor/floorplan/v2/Floorplan.h>
|
||||
|
||||
@@ -138,13 +139,15 @@ void ElementParamWidget::refresh() {
|
||||
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) {
|
||||
|
||||
@@ -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<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);
|
||||
@@ -294,23 +319,3 @@ void ElementParamWidget::onObstacleTypeChange() {
|
||||
IHasObstacleType* el = dynamic_cast<IHasObstacleType*>(this->curElement);
|
||||
if (el) {el->setObstacleType((Floorplan::ObstacleType) obstacleType.cmb->currentData().toInt() );}
|
||||
}
|
||||
|
||||
//void ElementParamWidget::onNameChange() {
|
||||
// IHasName* el = dynamic_cast<IHasName*>(this->curElement);
|
||||
// if (el) {el->setName(name.txt->text().toStdString());}
|
||||
//}
|
||||
|
||||
//void ElementParamWidget::onOutlineMethodChange() {
|
||||
// MMFloorOutlinePolygon* el = dynamic_cast<MMFloorOutlinePolygon*>(this->curElement);
|
||||
// if (el) {el->setMethod( (Floorplan::OutlineMethod) outlineMethod.cmb->currentData().toInt() );}
|
||||
//}
|
||||
|
||||
//void ElementParamWidget::onMACChanged() {
|
||||
// dynamic_cast<IHasMAC*>(curElement)->setMAC(mac.txt->text().toStdString());
|
||||
//}
|
||||
|
||||
//void ElementParamWidget::onSelectFileName() {
|
||||
// QString res = QFileDialog::getOpenFileName(this);
|
||||
// dynamic_cast<IHasFile*>(curElement)->setFileName(res.toStdString());
|
||||
// fileName.txt->setText(res);
|
||||
//}
|
||||
|
||||
87
params/MetaEditModel.cpp
Normal file
87
params/MetaEditModel.cpp
Normal file
@@ -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();
|
||||
|
||||
}
|
||||
|
||||
41
params/MetaEditModel.h
Normal file
41
params/MetaEditModel.h
Normal file
@@ -0,0 +1,41 @@
|
||||
#ifndef METAEDITMODEL_H
|
||||
#define METAEDITMODEL_H
|
||||
|
||||
#include <Indoor/floorplan/v2/Floorplan.h>
|
||||
#include <QAbstractTableModel>
|
||||
|
||||
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
|
||||
67
params/MetaEditWidget.cpp
Normal file
67
params/MetaEditWidget.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
#include "MetaEditWidget.h"
|
||||
#include "MetaEditModel.h"
|
||||
|
||||
#include <QTableView>
|
||||
#include <QGridLayout>
|
||||
#include <QKeyEvent>
|
||||
#include <QPushButton>
|
||||
|
||||
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!
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
35
params/MetaEditWidget.h
Normal file
35
params/MetaEditWidget.h
Normal file
@@ -0,0 +1,35 @@
|
||||
#ifndef METAEDITWIDGET_H
|
||||
#define METAEDITWIDGET_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <Indoor/floorplan/v2/Floorplan.h>
|
||||
|
||||
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
|
||||
@@ -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() {
|
||||
|
||||
@@ -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();
|
||||
|
||||
1
res.qrc
1
res.qrc
@@ -16,5 +16,6 @@
|
||||
<file>res/icons/elevator.svg</file>
|
||||
<file>res/icons/add.svg</file>
|
||||
<file>res/icons/remove.svg</file>
|
||||
<file>res/icons/ruler.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
50
res/icons/ruler.svg
Normal file
50
res/icons/ruler.svg
Normal file
@@ -0,0 +1,50 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 496 496" style="enable-background:new 0 0 496 496;" xml:space="preserve">
|
||||
<g>
|
||||
<g>
|
||||
<path d="M420.08,422.424l6.6-13.208L378.776,137.76c4.768-7.448,7.568-16.28,7.568-25.76c0-17.72-9.68-33.192-24-41.504V0h-48
|
||||
v70.496c-14.32,8.312-24,23.784-24,41.504c0,9.48,2.8,18.312,7.568,25.76l-24.376,138.12L2.344,4.688V496h491.312L420.08,422.424z
|
||||
M410.008,406.776l-7.664,15.336L394,405.424l-46.192-246.376c6.264-1.256,12.088-3.736,17.216-7.176L410.008,406.776z
|
||||
M371.872,374.208l-56.464-56.464l22.936-122.336L371.872,374.208z M330.344,16h16v48.72c-2.608-0.44-5.272-0.72-8-0.72
|
||||
c-2.728,0-5.392,0.28-8,0.72V16z M338.344,80c17.648,0,32,14.352,32,32s-14.352,32-32,32s-32-14.352-32-32S320.696,80,338.344,80z
|
||||
M311.664,151.88c5.128,3.44,10.952,5.92,17.216,7.176l-46.192,246.376l-8.344,16.68l-7.664-15.328L311.664,151.88z M386.344,456
|
||||
v24h-32v-40h-16v40h-32v-24h-16v24h-32v-40h-16v40h-32v-24h-16v24h-32v-40h-16v40h-32v-24h-16v24h-32v-40h-16v40h-32v-40h24v-16
|
||||
h-24v-32h40v-16h-40v-32h24v-16h-24v-32h40v-16h-40v-32h24v-16h-24v-32h40v-16h-40v-32h24v-16h-24v-32h40V88h-40V43.312
|
||||
l251.8,251.8l-13.576,76.936L82.344,197.824V416h128v-16h-112V236.448L253.176,391.28l-1.544,8.72h-25.288v16H253.4l20.944,41.888
|
||||
L298,410.576l13.832-73.776l65.256,65.256l1.392,7.416L401.416,456H386.344z M402.344,457.888l10.192-20.384L455.032,480h-52.688
|
||||
V457.888z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
Reference in New Issue
Block a user