Files
qt5-legatus-legacy/Lts/Viewer/SituationMap/MapImpl/overview_map_handler_impl.cpp
T
2026-08-13 18:33:10 +02:00

345 lines
10 KiB
C++
Executable File

/**
* @RDE_HEADER@
* Implementation of AbstractMapObject
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "overview_map_handler_impl.h"
#include <Common/resource_path.h>
#include <MapImpl/map_impl.h>
#include <SymbologyImpl/symbol_dictionary_impl.h>
#include <Rubberbands/rubberband_factory.h>
#include <Map/situation_map_utils.h>
#include <MapImpl/layer_factory_impl.h>
// ESRI
#include <arcgis/Map.h>
#include <arcgis/MapGraphicsView.h>
#include <arcgis/TileCache.h>
#include <arcgis/ArcGISTiledLayer.h>
#include <arcgis/Basemap.h>
#include <arcgis/SimpleRenderer.h>
#include <arcgis/GraphicsOverlayListModel.h>
#include <arcgis/SimpleLineSymbol.h>
#include <arcgis/SimpleFillSymbol.h>
//----------------------------------------------------------------------------
namespace SituationMap
{
//-----------------------------------------------------------------------------
class OverviewMapHandlerImpl::Private
{
public:
Private() = default;
~Private() = default;
// ESRI data:
// Own data:
QPointer<OverviewMap> m_builtInOverviewMap;
MapImpl *m_mainMap = nullptr;
QColor m_color = Qt::red;
}; // class OverviewMapHandlerImpl::Private
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
OverviewMapHandlerImpl::OverviewMapHandlerImpl(Map *map)
: BaseClass(map)
, m_logger(getLogger("OverviewMapHandlerImpl"))
, d(new Private)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
d->m_mainMap = static_cast<MapImpl *>(map);
if (d->m_mainMap)
{
// d->m_color = d->m_mainMap->palette().color(QPalette::WindowText); // RDE_DARK_BLUE
// REGG-4125 - Karte: Bereichsauswahl verdrängt Übersichtskarte
// EventDispatcher und EventDelegater scheinen die OverviewMap zu verdrängen.
// OverviewMap per QGraphicsProxyWidget (QGraphicsView()->scene()->addWidget) schlägt auch fehl
// Daher dieser einfacher workaround:
// Raise nach dem Zerstören eines Rubberbands (und damit Entfernen von EventDispatcher und EventDelegater):
connect(&d->m_mainMap->rubberbandFactory(), &RB::RubberbandFactory::rubberbandDestroyed,
this, &OverviewMapHandlerImpl::onMainMapRectChanged);
}
else
ERROR_LOG(m_logger) << LOGFUNCTION << " error no mainMap ";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
OverviewMapHandlerImpl::~OverviewMapHandlerImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
delete d;
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
void OverviewMapHandlerImpl::createBuiltInOverviewMap()
{
if (d->m_builtInOverviewMap)
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " already exists";
return;
}
d->m_builtInOverviewMap = QPointer<OverviewMap>(new OverviewMap(this));
d->m_builtInOverviewMap->init(d->m_mainMap, d->m_color);
if (! d->m_builtInOverviewMap->createBasicOverviewMap())
ERROR_LOG(m_logger) << LOGFUNCTION << " createBasicOverviewMap failed";
if (! d->m_builtInOverviewMap->widget())
{
ERROR_LOG(m_logger) << LOGFUNCTION << " d->m_builtInOverviewMap->widget() failed";
return;
}
// confgure widget:
// disable mouse:
d->m_builtInOverviewMap->widget()->setAttribute(Qt::WA_TransparentForMouseEvents);
d->m_builtInOverviewMap->widget()->setFocusPolicy(Qt::NoFocus);
d->m_builtInOverviewMap->widget()->setMinimumSize(QSize(100, 100));
d->m_builtInOverviewMap->widget()->setStyleSheet(QLatin1String("border: 1px solid gray"));
d->m_builtInOverviewMap->widget()->show();
// take care of position:
connect(d->m_mainMap, &MapImpl::rectChanged,
this, &OverviewMapHandlerImpl::onMainMapRectChanged);
onMainMapRectChanged();
d->m_mainMap->emitVisualComponentChanged(VisualComponent::OverviewMap); // to update onOffCheckbox
}
void OverviewMapHandlerImpl::removeBuiltInOverviewMap()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (d->m_builtInOverviewMap)
{
QPointer<OverviewMap> localPtr = d->m_builtInOverviewMap;
d->m_builtInOverviewMap.clear();
localPtr->deleteLater();
d->m_mainMap->emitVisualComponentChanged(VisualComponent::OverviewMap);
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
QWidget *OverviewMapHandlerImpl::builtInOverviewMapWidget()
{
if (! d->m_builtInOverviewMap)
return nullptr;
return d->m_builtInOverviewMap->widget();
}
void OverviewMapHandlerImpl::removeAll()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
removeBuiltInOverviewMap();
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
void OverviewMapHandlerImpl::onMainMapRectChanged()
{
if (! d->m_builtInOverviewMap)
return;
if (! d->m_builtInOverviewMap->widget())
return;
const QSize &mainSize = d->m_mainMap->size();
const QSize &overviewSize = d->m_builtInOverviewMap->widget()->size();
QSize diff = mainSize - overviewSize - QSize(10, 10); // additional border
d->m_builtInOverviewMap->widget()->move(diff.width(), diff.height());
d->m_builtInOverviewMap->widget()->raise();
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
OverviewMap::OverviewMap(QObject *parent)
: BaseClass(parent)
, m_logger(getLogger("OverviewMap"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
OverviewMap::~OverviewMap()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (m_graphicsView)
m_graphicsView->deleteLater();
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
void OverviewMap::init(MapImpl *mainMap, const QColor &color)
{
m_mainMap = mainMap;
m_color = color;
}
QWidget *OverviewMap::widget()
{
return m_graphicsView.data();
}
bool OverviewMap::createBasicOverviewMap()
{
if (m_graphicsView)
return true;
// create required objects:
m_graphicsView = QPointer<Esri::ArcGISRuntime::MapGraphicsView>(new Esri::ArcGISRuntime::MapGraphicsView(m_mainMap));
m_graphicsView->setAttributionTextVisible(false);
QObject *parent = this;
QString tiledBaseMapLayer = SituationMap::getResourcePath() + QLatin1String("Topographic.tpk");
QFile f(tiledBaseMapLayer);
if (!f.exists())
{
ERROR_LOG(m_logger) << LOGFUNCTION << " file does not exist: tiledBaseMapLayer='" << tiledBaseMapLayer << "'";
return false;
}
INFO_LOG(m_logger) << LOGFUNCTION << " tiledBaseMapLayer='" << tiledBaseMapLayer << "'";
Esri::ArcGISRuntime::TileCache *tpkCache = new Esri::ArcGISRuntime::TileCache(tiledBaseMapLayer, parent);
tpkCache->setObjectName(QLatin1String("OverviewMap-TPK-tpkCache"));
Esri::ArcGISRuntime::ArcGISTiledLayer *tiledLayer = new Esri::ArcGISRuntime::ArcGISTiledLayer(tpkCache, parent);
tiledLayer->setName(QLatin1String("OverviewMap-TPK-tiledLayer"));
Esri::ArcGISRuntime::Basemap *basemap = new Esri::ArcGISRuntime::Basemap(tiledLayer, parent);
basemap->setName(QLatin1String("TPK-Basemap"));
// connect signals
// loadStatusChanged ->
connect(tpkCache, &Esri::ArcGISRuntime::TileCache::loadStatusChanged, this, [this](Esri::ArcGISRuntime::LoadStatus loadStatus)
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " OverviewMap-TileCache: " << "loadStatus changed to: " << loadStatus;
});
connect(tiledLayer, &Esri::ArcGISRuntime::ArcGISTiledLayer::loadStatusChanged, this, [this](Esri::ArcGISRuntime::LoadStatus loadStatus)
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " OverviewMap-ArcGISTiledLayer: " << "loadStatus changed to: " << loadStatus;
if (loadStatus == Esri::ArcGISRuntime::LoadStatus::Loaded)
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " loaded -> setToFullExtent";
setToFullExtent();
}
});
connect(basemap, &Esri::ArcGISRuntime::Basemap::loadStatusChanged, this, [this](Esri::ArcGISRuntime::LoadStatus loadStatus)
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " OverviewMap-Basemap: " << "loadStatus changed to: " << loadStatus;
});
// Map:
Esri::ArcGISRuntime::Map *overviewMap = new Esri::ArcGISRuntime::Map(basemap, parent);
overviewMap->setObjectName(QLatin1String("OverviewMap-EsriMap"));
// will start esris cascading load dependecies...
m_graphicsView->setMap(overviewMap);
// GraphicsOverlay:
Esri::ArcGISRuntime::GraphicsOverlay *graphicalOverlay = new Esri::ArcGISRuntime::GraphicsOverlay(parent);
m_graphicsView->graphicsOverlays()->append(graphicalOverlay);
QColor color = m_color;
// create symbol
Esri::ArcGISRuntime::SimpleLineSymbol *sls =
new Esri::ArcGISRuntime::SimpleLineSymbol(Esri::ArcGISRuntime::SimpleLineSymbolStyle::Solid,
color, 1, parent);
color.setAlpha(100);
Esri::ArcGISRuntime::SimpleFillSymbol *sfs =
new Esri::ArcGISRuntime::SimpleFillSymbol(Esri::ArcGISRuntime::SimpleFillSymbolStyle::Solid,
color, sls, parent);
// create renderer
Esri::ArcGISRuntime::SimpleRenderer *renderer =
new Esri::ArcGISRuntime::SimpleRenderer(sfs, parent);
// Handle errors of renderer:
connect(renderer, &Esri::ArcGISRuntime::SimpleRenderer::errorOccurred, this, [this](const Esri::ArcGISRuntime::Error & error)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " EsriError occured: " << error;
});
// set Renderer to layer:
graphicalOverlay->setRenderer(renderer);
// prepare graphic
m_graphic = new Esri::ArcGISRuntime::Graphic(graphicalOverlay);
graphicalOverlay->graphics()->append(m_graphic);
// update first time
onMainMapExtentChanged();
// execute on extentChanged
connect(m_mainMap, &MapImpl::extentChangedDelayed, this, &OverviewMap::onMainMapExtentChanged);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
void OverviewMap::onMainMapExtentChanged()
{
if (! m_graphic)
return;
Esri::ArcGISRuntime::GeoView *geoView = m_mainMap->getEsriGeoView();
if (! geoView)
return;
setToFullExtent();
const Esri::ArcGISRuntime::Viewpoint curVp =
geoView->currentViewpoint(Esri::ArcGISRuntime::ViewpointType::BoundingGeometry);
m_graphic->setGeometry(curVp.targetGeometry()); // curVp.targetGeometry() should be a rectangle
}
void OverviewMap::setToFullExtent()
{
if (!m_graphicsView || !m_mainMap)
return;
// zoom to fullExtent:
Esri::ArcGISRuntime::Envelope fullExtent = m_mainMap->layerFactoryImpl().fullExtentOfBasemaps(0.2); // add margin
Esri::ArcGISRuntime::Viewpoint vp(fullExtent);
m_graphicsView->setViewpointAndWait(vp);
}
} // namespace SituationMap