Initial commit

This commit is contained in:
torsten committed 2026-08-13 18:33:10 +02:00
commit b7d90b9afe
16245 files changed
+3396666

No files matched your search

+445
View File
@@ -0,0 +1,445 @@
/**
* @RDE_HEADER@
* Interface for JumpPointWidget
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "jump_point_widget.h"
#include "jump_point_custom_view.h"
#include <Map/map.h>
#include <Map/object_factory.h>
#include <Map/situation_map_utils.h>
#include <MapImpl/layer_factory_impl.h>
#include <MapImpl/jump_point_namer.h>
#include <MapImpl/coord_translation_functor_impl.h>
#include <GraphicalObjects/graphical_object_picture_marker.h>
#include <Rubberbands/rubberband_factory.h>
#include <MapObjects/geo_image.h>
#include <LtsDataView/lts_data_view.h>
// Qt
#include <QCoreApplication>
#include <QHBoxLayout>
#include <QPushButton>
#include <QMenu>
#include <QAction>
#include <QFocusEvent>
namespace SituationMap
{
//-----------------------------------------------------------------------------
// class JumpPointWidget::Private
//-----------------------------------------------------------------------------
class JumpPointWidget::Private
{
public:
Private() = default;
// OWN data:
SituationMap::Map *m_map = nullptr; // Use INTERFACE
QString m_layername;
QString m_debugInfo;
RefPointer<GeoImage> m_uniqueMarker;
QGridLayout *m_layout = nullptr;
JumpPointModel *m_jumpPointModel = nullptr;
LtsDataView::LtsDataView *m_jumpPointView = nullptr;
QMenu *m_actionMenu = nullptr;
QAction *m_removeAction = nullptr;
QModelIndex m_contextModelIndex;
}; // class JumpPointWidget::Private
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// class JumpPointWidget
//-----------------------------------------------------------------------------
JumpPointWidget::JumpPointWidget(const QString &layername,
Map *map,
const QString &debugInfo)
: BaseClass()
, d(new Private)
, m_logger(getLogger("JumpPointWidget"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " debugInfo='" << debugInfo << "'";
d->m_jumpPointModel = new JumpPointModel(this);
if (map)
{
d->m_map = map;
d->m_layername = layername;
d->m_debugInfo = debugInfo;
connect(d->m_map, &Map::beginDestroy, this, &JumpPointWidget::cleanup);
d->m_jumpPointModel->setMap(d->m_map);
QVBoxLayout *vBox = new QVBoxLayout();
this->setLayout(vBox);
QHBoxLayout *hBox = new QHBoxLayout();
vBox->addLayout(hBox);
hBox->addWidget(new QLabel(tr("Jump Points:")));
QPushButton *pbPosition = new QPushButton(QIcon(QLatin1String("icon:position.svg")), tr("Position"));
hBox->addWidget(pbPosition);
connect(pbPosition, &QPushButton::clicked, this, &JumpPointWidget::onGetPosition);
pbPosition->setEnabled(d->m_map->mode() == Mode::Mode_2D);
d->m_jumpPointView = new LtsDataView::LtsDataView(this);
vBox->addWidget(d->m_jumpPointView);
d->m_jumpPointView->setSelectionMode(QAbstractItemView::SelectionMode::SingleSelection);
d->m_jumpPointView->selectCustomView();
d->m_jumpPointView->seamless();
d->m_jumpPointView->setModel(d->m_jumpPointModel, [this]()
{
return new JumpPointCustomView(this);
});
// connect signals of TableView:
connect(d->m_jumpPointView, &LtsDataView::LtsDataView::signalEntered, this, &JumpPointWidget::onTableViewClicked);
connect(d->m_jumpPointView, &LtsDataView::LtsDataView::clicked, this, &JumpPointWidget::onTableViewSelectionChanged);
d->m_jumpPointView->hideColumn(JumpPointModel::Columns::ORIGIN_GEO); // do not "print"
d->m_jumpPointView->hideColumn(JumpPointModel::Columns::ICON); // do not "print"
}
else
ERROR_LOG(m_logger) << LOGFUNCTION << " no map";
// context menue:
d->m_jumpPointView->setContextMenuPolicyPerView(LtsDataView::LtsDataView::CUSTOM, Qt::CustomContextMenu);
connect(d->m_jumpPointView, &LtsDataView::LtsDataView::signalContextMenuRequested,
this, &JumpPointWidget::onCustomContextMenuRequested);
d->m_actionMenu = new QMenu(this);
d->m_removeAction = new QAction(tr("Remove Jump Point"), this);
d->m_actionMenu->addAction(d->m_removeAction);
connect(d->m_removeAction, &QAction::triggered, this, &JumpPointWidget::onRemoveAction);
TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " END";
}
JumpPointWidget::~JumpPointWidget()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " START";
this->cleanup();
TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " END";
delete d;
}
QStringList JumpPointWidget::names()
{
if (!d->m_jumpPointModel)
return QStringList();
return d->m_jumpPointModel->names();
}
QVector<JPData> JumpPointWidget::jumpPoints()
{
if (!d->m_jumpPointModel)
return QVector<JPData>();
return d->m_jumpPointModel->jumpPoints();
}
int JumpPointWidget::count() const
{
if (!d->m_jumpPointModel)
return 0;
return d->m_jumpPointModel->rowCount();
}
bool JumpPointWidget::contains(const QString &name)
{
if (!d->m_jumpPointModel)
return false;
return d->m_jumpPointModel->contains(name);
}
bool JumpPointWidget::removeJumpPoint(const QString &name)
{
return d->m_jumpPointModel->removeItem(name);
}
void JumpPointWidget::onGetPosition()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " START";
if (!d->m_map)
return;
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Workaround to make sure that cursor setting of rubberband will work. Don't know why this
* is necessary. ToDo find the reason why changing cursor failed and fix the underlying cause.
*
* JT 2017/05/04
*/
d->m_map->sideBar()->hide();
// QCoreApplication::process Events(); // 2017.11.03, N.Thoden, not necessary
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
// remove any pending/active rubberbands of our map:
SituationMap::RB::Rubberband::deleteAllActiveRubberbands(d->m_map);
// create rb
RB::RubberbandPointFeature *rb = d->m_map->rubberbandFactory().create<RB::RubberbandPointFeature>(this);
if (!rb || !rb->rubberbandIsAlive())
{
if (rb)
rb->deleteMySelf();
FATAL_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " create Rubberband failed!";
return;
}
rb->setAutoDelete(true);
connect(rb, &RB::Rubberband::apply, this, &JumpPointWidget::onRubberbandApply);
}
void JumpPointWidget::onRubberbandApply(RB::RubberbandBase *rb)
{
QPolygonF coordGeo = rb->coordinateVector();
if (coordGeo.size() != 1)
return;
connect(this, &JumpPointWidget::newName, this, &JumpPointWidget::onName);
askUserForName(coordGeo.front());
}
void JumpPointWidget::askUserForName(const QPointF &coordGeo)
{
JumpPointNamer *namer = new JumpPointNamer(this->count(), coordGeo, this);
namer->setAttribute(Qt::WA_DeleteOnClose);
namer->connect(namer, &JumpPointNamer::newName, this, &JumpPointWidget::newName);
namer->show();
}
void JumpPointWidget::onName(const QString &name, const QPointF & coordGeo)
{
disconnect(this, &JumpPointWidget::newName, this, &JumpPointWidget::onName);
const double scale = d->m_map->scale();
addJumpPoint(name, coordGeo, scale);
}
void JumpPointWidget::onJumpPointHovered(const QString &name, bool enter)
{
setJumpPointSelected(name, enter);
}
void JumpPointWidget::onTableViewClicked(const QModelIndex &index)
{
if (!d->m_jumpPointModel)
return;
JPData *jumpPoint = d->m_jumpPointModel->getItemPtr(index);
if (!jumpPoint)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " not found";
return;
}
removeJumpPointSelections();
onJumpPointHovered(jumpPoint->m_name, true);
}
void JumpPointWidget::onTableViewSelectionChanged(const QModelIndex &index)
{
if (!d->m_jumpPointModel)
return;
JPData *jumpPoint = d->m_jumpPointModel->getItemPtr(index);
if (!jumpPoint)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " not found";
return;
}
centerMapToJumpPoint(jumpPoint->m_name);
}
bool JumpPointWidget::addJumpPoint(const QString &name, const QPointF &originGeo, double mapScale)
{
return addJumpPoint(name, Point3D::fromQPointF(originGeo), mapScale);
}
bool JumpPointWidget::addJumpPoint(const QString &name, const Point3D &originGeo, double mapScale)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " START"
<< " name='" << name << "'"
<< " originGeo=" << originGeo
<< " mapScale=" << mapScale;
if (d->m_layername.isEmpty())
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no layername";
return false;
}
{
JPData jpData(name, originGeo, mapScale);
jpData.m_image = QImage(QLatin1String(":/situationMap/pushPinRedClipArt.png")).scaled(30, 30, Qt::KeepAspectRatio, Qt::SmoothTransformation);
d->m_jumpPointModel->addUpdateItem(jpData);
}
JPData *jumpPoint = d->m_jumpPointModel->getItemPtr(name);
if (!jumpPoint)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " not found";
return false;
}
if (! jumpPoint->hasMarker())
{
QString debugInfo = QStringLiteral("%1_JumpPoint(%2)").arg(d->m_debugInfo, name);
jumpPoint->m_marker = d->m_map->objectFactory().create<SituationMap::GeoImage>(d->m_layername, debugInfo);
if (! jumpPoint->m_marker.valid())
{
ERROR_LOG(m_logger) << LOGFUNCTION << " create GeoImage failed, debugInfo='" << d->m_debugInfo << "'";
return false;
}
jumpPoint->m_marker->setProxyMarker(MarkerSymbolType::PushPin2D);
jumpPoint->m_marker->setPickable(false);
}
jumpPoint->m_mapScale = mapScale;
jumpPoint->m_originGeo = originGeo;
jumpPoint->m_marker->setOrigin(originGeo);
jumpPoint->m_marker->setIdentifier(name);
this->setJumpPointSelected(name, false);
bool success = jumpPoint->m_marker->updateView();
if (! success)
ERROR_LOG(m_logger) << LOGFUNCTION << " updateView failed, debugInfo='" << d->m_debugInfo << "'";
TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'"
<< " END"
<< " name='" << name << "'"
<< " originGeo=" << originGeo
<< " mapScale=" << mapScale;
return success;
}
bool JumpPointWidget::centerMapToJumpPoint(const QString &name)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " START"
<< " name='" << name << "'";
JPData *jumpPoint = d->m_jumpPointModel->getItemPtr(name);
if (!jumpPoint)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " not found";
return false;
}
const Point3D &originGeo = jumpPoint->m_originGeo;
const double mapScale = jumpPoint->m_mapScale;
d->m_map->setCenterPoint(originGeo.toPointF(), mapScale);
TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " END";
return true;
}
void JumpPointWidget::removeJumpPointSelections()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " START";
if (!d->m_jumpPointModel)
return;
const QStringList &sl = d->m_jumpPointModel->names();
for (const auto &name : sl)
setJumpPointSelected(name, false);
TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " END";
}
bool JumpPointWidget::setJumpPointSelected(const QString &name, bool selected)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " START"
<< " name='" << name << "'"
<< " selected='" << selected;
JPData *jumpPoint = d->m_jumpPointModel->getItemPtr(name);
if (!jumpPoint)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " not found";
return false;
}
if (! jumpPoint->hasMarker())
return false;
// jumpPoint->m_marker->setSelected(selected);
// jumpPoint->m_marker->setScale((selected) ? 1.5 : 1.0);
jumpPoint->m_marker->setProxyMarkerSize((selected) ? 30 : 20);
jumpPoint->m_marker->setDrawOrder((selected) ? 2 : 1); // selected should be above the other
jumpPoint->m_marker->rTextStyle().setSize((selected) ? 20 : 10);
bool success = jumpPoint->m_marker->updateView();
if (! success)
ERROR_LOG(m_logger) << LOGFUNCTION << " updateView failed, debugInfo='" << d->m_debugInfo << "'";
TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " END"
<< " name='" << name << "'"
<< " selected='" << selected;
return success;
}
void JumpPointWidget::onCustomContextMenuRequested(const QPoint &globalPos, const QModelIndex &indexSrc)
{
d->m_contextModelIndex = indexSrc;
if (!d->m_contextModelIndex.isValid())
return;
d->m_actionMenu->exec(globalPos);
}
void JumpPointWidget::onRemoveAction()
{
if (!d->m_contextModelIndex.isValid())
return;
d->m_jumpPointModel->removeRow(d->m_contextModelIndex.row());
}
void JumpPointWidget::cleanup()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " START";
d->m_jumpPointModel->clear();
TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " END";
}
bool JumpPointWidget::event(QEvent *event)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " START"
<< " type " << event->type();
if (event->type() == QEvent::Type::Hide)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'"
<< " hide Event -> removeJumpPointSelections...";
this->removeJumpPointSelections();
}
return BaseClass::event(event);
}
} // namespace SituationMap