/** ** ** @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 // Qt #include #include 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(_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::max(), std::numeric_limits::max() ); QPointF bottomRight( std::numeric_limits::min(), std::numeric_limits::min() ); for (auto handle : qAsConst(_internal->_handleList)) { RubberbandPointHandle * pointHandlePtr = dynamic_cast(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 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 */