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:
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user