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

310 lines
10 KiB
C++
Executable File

/**
**
** @RDE_HEADER@
** Implementation of base class for 2D rubberbands
** $Id$
** $HeadURL$
** $Author$
**
** -----------------------------------------------------------------------------------------------
**
** Hardware-Environment: Intel-PC
** Software-Environment: Windows 7, Qt 5.4. ArcGIS 10.2.5
**
** Language ........: C++ 11
**
** -----------------------------------------------------------------------------------------------
**
** Author ...........: Jörg Turla, SPD G, Tel. 3132
**
** -----------------------------------------------------------------------------------------------
**
** Notes .........:
**
** 27.03.2015, JT : First edition for use with Qt5
**
** -----------------------------------------------------------------------------------------------
*/
#include "rubberband.h"
#include "rubberband_drawable.h"
#include "rubberband_handle.h"
#include "rubberband_handle_proxy.h"
#include "rubberband_point_handle.h"
#include "rubberband_internal.h"
#include "rubberband_base_internal.h"
#include "rubberband_factory.h"
#include <arcgis/MapGraphicsView.h>
// Qt
#include <QtCore/QMetaMethod>
#include <QtWidgets/QGraphicsPixmapItem>
namespace SituationMap { namespace RB
{
Rubberband::Rubberband( SituationMap::Map * map, QObject * parent, bool isActive )
: RubberbandBase(map,parent,isActive)
, _internal( new Rubberband::InternalData(map) )
, _state( RubberbandState::ConstructionState )
, _previewSidc()
, _previewCursorOffset(32,32)
, _previewSize(32)
{
_fillColor.setAlpha(100);
connect( &_previewSymbolResultWatcher
, &AdvancedSymbology::SymbolResultWatcher::resultReady
, this
, &Rubberband::onPreviewSymbolResultReady );
} /* Rubberband::Rubberband */
Rubberband::~Rubberband()
{
delete _internal;
_internal = nullptr;
} /* Rubberband::~Rubberband */
void Rubberband::connectPreviewPixmap( const QPixmap & symbolPixmap )
{
if (nullptr == _internal->_connectedPreviewPixmap)
{
_internal->_connectedPreviewPixmap = new QGraphicsPixmapItem( symbolPixmap );
_internal->_connectedPreviewPixmap -> setOffset(-qreal(symbolPixmap.width())/2,-qreal(symbolPixmap.height())/2);
_internal->_mapScene -> addItem( _internal->_connectedPreviewPixmap );
}
} /* RubberbandPointFeature::connectPreviewPixmap */
unsigned int Rubberband::coordinateCount() const { return static_cast<unsigned int>(_internal->_handleList.size()); }
void Rubberband::resetAction(AbstractEventDispatcher*, int, int)
{
disenableSelectedState();
disenableMultiSelectedState();
update();
} /* Rubberband::resetAction */
bool Rubberband::selectAction( AbstractEventDispatcher*, int x, int y )
{
if (rubberbandIsAlive())
{
QPointF scenePos = pixel2ScenePosition(x,y);
if (_baseInternal->buttonProxyActive(scenePos)) return false;
_baseInternal->_lastClickPosition = scenePos;
return true;
}
return false;
} /* Rubberband::selectAction */
bool Rubberband::multiSelectActionPress( AbstractEventDispatcher * causer, int x, int y )
{
if (rubberbandIsAlive())
{
if (isEnabledModificationState())
{
_baseInternal->_lastClickPosition = pixel2ScenePosition(x,y);
enableMultiSelectedState();
}
return selectAction( causer, x, y);
}
return false;
} /* RubberbandPointFeature::multiSelectActionPress */
bool Rubberband::multiSelectActionRelease( AbstractEventDispatcher * causer, int x, int y )
{
if (rubberbandIsAlive())
{
if (isEnabledModificationState())
{
updateButtonPosition();
activateButtons();
}
else return setCoordinateAction(causer,x,y);
}
return false;
} /* RubberbandPointFeature::multiSelectActionRelease */
void Rubberband::adjustConnectedPreviewPixmap( int x, int y )
{
if (_internal->_connectedPreviewPixmap)
{
_internal->_connectedPreviewPixmap -> setPos(pixel2ScenePosition( x+_previewCursorOffset.x(), y+_previewCursorOffset.y() ));
}
} /* Rubberband::adjustConnectedPreviewPixmap */
bool Rubberband::moveAction( AbstractEventDispatcher*, int x, int y )
{
adjustConnectedPreviewPixmap(x,y);
return rubberbandIsAlive();
} /* moveAction */
bool Rubberband::setCoordinateAction( AbstractEventDispatcher*, int x, int y )
{
if (rubberbandIsAlive())
{
QPointF scenePos = pixel2ScenePosition(x,y);
if (_baseInternal->buttonProxyActive(scenePos)) return false;
_internal->_lastClickPosition = scenePos;
return true;
}
return false;
} /* Rubberband::setCoordinateAction */
bool Rubberband::movePickedAction ( AbstractEventDispatcher*, int x, int y ) { adjustConnectedPreviewPixmap(x,y); return false; }
bool Rubberband::contextMenuAction ( AbstractEventDispatcher*, int x, int y ) { Q_UNUSED(x); Q_UNUSED(y); return rubberbandIsAlive(); }
bool Rubberband::completeStateAction ( AbstractEventDispatcher*, int x, int y ) { Q_UNUSED(x); Q_UNUSED(y); return rubberbandIsAlive(); }
bool Rubberband::deleteAction ( AbstractEventDispatcher*, int x, int y ) { Q_UNUSED(x); Q_UNUSED(y); return rubberbandIsAlive(); }
bool Rubberband::undoAction ( AbstractEventDispatcher*, int x, int y ) { Q_UNUSED(x); Q_UNUSED(y); return rubberbandIsAlive(); }
RubberbandHandle * Rubberband::pickHandle( int x, int y ) const
{
if (_internal->_mapView != nullptr)
{
QPointF scenePosition = pixel2ScenePosition(x,y);
for (auto handle : qAsConst(_internal->_handleList))
{
if (handle->isPositionInside(scenePosition))
return handle.get();
}
}
return nullptr;
} /* Rubberband::pickHandle */
void Rubberband::deSelectHandles()
{
for (auto handle : qAsConst(_internal->_handleList))
{
RubberbandHandle * handlePtr = handle.get();
if (handlePtr)
{
handlePtr->setSelection(false);
}
}
} /* Rubberband::deSelectHandles */
QRectF Rubberband::sceneBbox() const
{
DEBUG_LOG(_internal->_logger) << LOGFUNCTION;
QPointF topLeft( std::numeric_limits<double>::max(), std::numeric_limits<double>::max() );
QPointF bottomRight( std::numeric_limits<double>::min(), std::numeric_limits<double>::min() );
for (auto handle : qAsConst(_internal->_handleList))
{
RubberbandPointHandle * pointHandlePtr = dynamic_cast<RubberbandPointHandle*>(handle.get());
if (pointHandlePtr)
{
const QPointF & p = pointHandlePtr->getCoordinate()._sceneCoordinate;
if (topLeft.x() > p.x()) topLeft.setX(p.x());
if (topLeft.y() > p.y()) topLeft.setY(p.y());
if (bottomRight.x() < p.x()) bottomRight.setX(p.x());
if (bottomRight.y() < p.y()) bottomRight.setY(p.y());
}
}
return QRectF( topLeft, bottomRight );
} /* Rubberband::sceneBbox */
void Rubberband::update()
{
// Check Quartz
// if (isSignalConnected(QMetaMethod::fromSignal(&Rubberband::updatePreview)))
// {
// emit updatePreview( this );
// }
// if (_internal->_map->symbolDictionary().contains(_previewSidc))
// {
// const QImage& symbolImage = _internal->_map->symbolDictionary().symbolImageBySidc( _previewSidc, _previewSize );
// connectPreviewPixmap( QPixmap::fromImage(symbolImage) );
// }
if ((!_previewSidc.isEmpty()) && (nullptr == _internal->_connectedPreviewPixmap) && (!_previewSymbolResultWatcher.resultIsValid()))
{
_previewSymbolResultWatcher.setSymbolResult(_baseInternal->_map->symbolDictionary().findBaseSymbol(_previewSidc));
}
for (auto handle : qAsConst(_internal->_handleList))
{
handle -> setDrawColor(_handleDrawColor);
handle -> setFillColor(_handleFillColor);
handle -> setSelectionColor(_handleSelectionColor);
handle -> setPickingRatio( _pickingRatio );
}
updateButtonPosition();
if (_internal->_constructionObjectDraw != nullptr)
{
// _constructionObjectDraw -> setColors
}
externalUpdate();
} /* Rubberband::update */
void Rubberband::onPreviewSymbolResultReady()
{
QSharedPointer<AdvancedSymbology::SymbolResult> symResult = _previewSymbolResultWatcher.symbolResult();
if (!symResult) return; // should NEVER happen! (Which object should have triggered the signal???)
const QPixmap & symbolPixmap = QPixmap::fromImage(symResult->symbolImage().image()).scaled(_previewSize,_previewSize,Qt::KeepAspectRatio);
if (symbolPixmap.isNull())
{
DEBUG_LOG(_internal->_logger) << LOGFUNCTION << "Preview symbol image is empty.";
}
connectPreviewPixmap( symbolPixmap );
} /* Rubberband::onPreviewSymbolResultReady */
#include "./constrainsMarker.xpm"
void Rubberband::markFailedConstrains( const QPointF & scenePos, bool on )
{
if (on)
{
QPixmap markerPixmap(constrainsMarker_xpm);
if (nullptr == _internal->_constrainFailedMarker)
{
_internal->_constrainFailedMarker = new QGraphicsPixmapItem( markerPixmap );
_internal->_mapScene -> addItem( _internal->_constrainFailedMarker );
}
_internal->_constrainFailedMarker -> setOffset(-qreal(markerPixmap.width())/2,-qreal(markerPixmap.height())/2);
_internal->_constrainFailedMarker -> setPos(scenePos-QPointF(_previewCursorOffset));
_internal->_constrainFailedMarker->setVisible(true);
}
else if (_internal->_constrainFailedMarker) _internal->_constrainFailedMarker->setVisible(false);
} /* Rubberband::markFailedConstrains */
} } /* namespace SituationMap::RB */