655 lines
22 KiB
C++
Executable File
655 lines
22 KiB
C++
Executable File
|
|
/**
|
|
**
|
|
** @RDE_HEADER@
|
|
** Implementation of base class for 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_base.h"
|
|
#include "rubberband_base_internal.h"
|
|
#include "rubberband_handle_proxy.h"
|
|
|
|
#include "rubberband_factory.h"
|
|
|
|
#include <Common/exception.h>
|
|
|
|
#include <Map/coord_translation_functor.h>
|
|
#include <MapImpl/map_impl.h>
|
|
|
|
// Qt
|
|
#include <QtCore/QCoreApplication>
|
|
#include <QtCore/QMetaMethod>
|
|
|
|
#include <QtWidgets/QGraphicsView>
|
|
#include <QtWidgets/QWidget>
|
|
#include <QtWidgets/QHBoxLayout>
|
|
#include <QtWidgets/QPushButton>
|
|
#include <QtGui/QPixmap>
|
|
|
|
#include "apply.xpm"
|
|
#include "abort.xpm"
|
|
#include "undo.xpm"
|
|
|
|
static SituationMap::Map * currentFactoryMap = nullptr;
|
|
static bool allowMultipleRubberbands = false;
|
|
|
|
|
|
namespace SituationMap { namespace RB
|
|
{
|
|
QPixmap * RubberbandBase::BaseInternalData::_applyIcon = nullptr;
|
|
QPixmap * RubberbandBase::BaseInternalData::_abortIcon = nullptr;
|
|
QPixmap * RubberbandBase::BaseInternalData::_undoIcon = nullptr;
|
|
|
|
RubberbandBase::BaseInternalData::BaseInternalData( SituationMap::Map * map, RubberbandBase * me )
|
|
: _map(map)
|
|
, _mapCtFunctor(map->coordTranslationFunctor())
|
|
, _isActive(false)
|
|
, _applyIsPossible(false)
|
|
, _undoIsPossible(false)
|
|
, _hasUndoButton(false)
|
|
, _lastClickPosition(-1,-1)
|
|
, _buttonBoxSceneAnchor()
|
|
, _buttonBoxFixPosition(-1,-1)
|
|
, _buttonProxy()
|
|
, _updateFunctorList()
|
|
, _logger(getLogger("RubberbandBase"))
|
|
{
|
|
QGraphicsView * view = map->getQGraphicsView();
|
|
|
|
if (view)
|
|
{
|
|
_restoreCursor = view->viewport()->cursor(); // workaround Qt bug. remove when fixed
|
|
}
|
|
|
|
_buttonBox = new QWidget();
|
|
_buttonBox->setObjectName(QLatin1String("RBButtonBoxWidget"));
|
|
_buttonBox->hide();
|
|
_buttonBox->setAttribute( Qt::WidgetAttribute::WA_NoSystemBackground, true );
|
|
|
|
_applyButton = new QPushButton( (_applyIcon) ? *_applyIcon : QPixmap(apply_xpm), QString(), _buttonBox );
|
|
_applyButton -> setAttribute( Qt::WidgetAttribute::WA_NoSystemBackground, true );
|
|
_applyButton -> setObjectName(QLatin1String("RBApply"));
|
|
_applyButton -> setAttribute(Qt::WA_AcceptTouchEvents);
|
|
_applyButton -> grabGesture( Qt::GestureType::TapGesture );
|
|
me->connect( _applyButton, &QPushButton::clicked, me, &RubberbandBase::onDo_applyButtonClicked );
|
|
|
|
_cancelButton = new QPushButton( (_abortIcon) ? *_abortIcon : QPixmap(abort_xpm), QString(), _buttonBox );
|
|
_cancelButton -> setAttribute( Qt::WidgetAttribute::WA_NoSystemBackground, true );
|
|
_cancelButton -> setObjectName(QLatin1String("RBCancel"));
|
|
_cancelButton -> setAttribute(Qt::WA_AcceptTouchEvents);
|
|
_cancelButton -> grabGesture( Qt::GestureType::TapGesture );
|
|
me->connect( _cancelButton, &QPushButton::clicked, me, &RubberbandBase::onDo_cancelButtonClicked );
|
|
|
|
_undoButton = new QPushButton( (_undoIcon) ? *_undoIcon : QPixmap(undo_xpm), QString(), _buttonBox );
|
|
_undoButton -> setAttribute( Qt::WidgetAttribute::WA_NoSystemBackground, true );
|
|
_undoButton -> setObjectName(QLatin1String("RBUndo"));
|
|
_undoButton -> setAttribute(Qt::WA_AcceptTouchEvents);
|
|
_undoButton -> grabGesture( Qt::GestureType::TapGesture );
|
|
_undoButton -> hide();
|
|
me->connect( _undoButton, &QPushButton::clicked, me, &RubberbandBase::onDo_undoButtonClicked );
|
|
|
|
_buttonLayout = new QHBoxLayout( _buttonBox );
|
|
_buttonLayout->setObjectName(QLatin1String("RBButtonBoxLayoutHBox"));
|
|
|
|
_buttonLayout -> addWidget( _undoButton );
|
|
_buttonLayout -> addWidget( _cancelButton );
|
|
_buttonLayout -> addWidget( _applyButton );
|
|
|
|
} /* InternalData */
|
|
|
|
|
|
Rubberband::BaseInternalData::~BaseInternalData()
|
|
{
|
|
_map = nullptr;
|
|
_mapCtFunctor = nullptr;
|
|
|
|
_buttonProxy = nullptr; // delete RefPointer
|
|
if (_buttonBox) _buttonBox -> deleteLater(); // delete all widgets of button box
|
|
|
|
_buttonBox = nullptr;
|
|
_buttonLayout = nullptr;
|
|
_applyButton = nullptr;
|
|
_cancelButton = nullptr;
|
|
_undoButton = nullptr;
|
|
|
|
} /* ~InternalData */
|
|
|
|
|
|
bool RubberbandBase::BaseInternalData::buttonProxyActive( const QPointF & pos ) const
|
|
{
|
|
if (_buttonProxy)
|
|
{
|
|
return ((_buttonProxy->isVisible()) && (_buttonProxy->isPositionInside(pos)));
|
|
}
|
|
return false;
|
|
} /* bool RubberbandBase::BaseInternalData::buttonProxyActive( const QPointF & pos ) const*/
|
|
|
|
|
|
void RubberbandBase::BaseInternalData::enableAndShowOnlyPossibleButtons()
|
|
{
|
|
_applyButton->setEnabled(_applyIsPossible);
|
|
|
|
if (_undoButton)
|
|
{
|
|
if (_hasUndoButton)
|
|
{
|
|
_undoButton -> show();
|
|
}
|
|
_undoButton -> setEnabled(_undoIsPossible);
|
|
}
|
|
} /* void RubberbandBase::InternalData::showOnlyPossibleButtons() */
|
|
|
|
|
|
static QHash<SituationMap::Map*, QList<RubberbandBase*>> &activeRubberbands()
|
|
{
|
|
static QHash<SituationMap::Map*, QList<RubberbandBase*>> hashTable;
|
|
return hashTable;
|
|
} // activeRubberbands()
|
|
|
|
|
|
void RubberbandBase::currentFactoryMap(SituationMap::Map * map) { ::currentFactoryMap = map; }
|
|
void RubberbandBase::allowMultipleRubberbands( bool ok ) { ::allowMultipleRubberbands = ok; }
|
|
|
|
|
|
void * RubberbandBase::operator new(size_t bytes)
|
|
{
|
|
QString exceptionMsg;
|
|
|
|
// be careful it is not thread safe here
|
|
if (::currentFactoryMap)
|
|
{
|
|
bool doNew( ::allowMultipleRubberbands );
|
|
|
|
if (!doNew)
|
|
{
|
|
doNew = true;
|
|
const auto rubberbands = SituationMap::RB::activeRubberbands().value(::currentFactoryMap);
|
|
for (const auto rbnd : rubberbands)
|
|
{
|
|
if (rbnd->rubberbandIsAlive())
|
|
{
|
|
doNew = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (doNew)
|
|
{
|
|
RubberbandBase::currentFactoryMap( nullptr );
|
|
RubberbandBase::allowMultipleRubberbands( false );
|
|
return ::operator new(bytes);
|
|
}
|
|
else exceptionMsg = QLatin1String("Another rubberband is already alive at moment");
|
|
RubberbandBase::currentFactoryMap( nullptr );
|
|
}
|
|
else exceptionMsg = QLatin1String("Use rubberband factory to create rubberbands. Calling new directly is forbidden!");
|
|
|
|
RubberbandBase::currentFactoryMap( nullptr );
|
|
RubberbandBase::allowMultipleRubberbands( false );
|
|
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
* because "return nullptr;" is not compliante with the c++ standard
|
|
* throw exception instead
|
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
throw Exception( __FILE__, __LINE__, exceptionMsg );
|
|
|
|
} /* RubberbandBase::operator new */
|
|
|
|
|
|
QList<RubberbandBase*> RubberbandBase::activeRubberbands( SituationMap::Map * map )
|
|
{
|
|
QList<RubberbandBase*> ret;
|
|
const auto rubberbands = SituationMap::RB::activeRubberbands().value(map);
|
|
for (const auto rbnd : rubberbands)
|
|
{
|
|
if (rbnd && rbnd->rubberbandIsAlive())
|
|
ret += rbnd;
|
|
}
|
|
return ret;
|
|
} /* RubberbandBase::activeRubberbands */
|
|
|
|
void RubberbandBase::deleteAllActiveRubberbands(Map *map)
|
|
{
|
|
const QList<SituationMap::RB::RubberbandBase*> &rbCont = RubberbandBase::activeRubberbands(map);
|
|
qDeleteAll(rbCont);
|
|
} /* RubberbandBase::deleteAllActiveRubberbands */
|
|
|
|
|
|
bool RubberbandBase::isRubberbandActive(SituationMap::Map * map)
|
|
{
|
|
return (activeRubberbands(map).size() > 0);
|
|
} /* RubberbandBase::isRubberbandActive */
|
|
|
|
|
|
void RubberbandBase::abortActiveRubberbands( SituationMap::Map * map )
|
|
{
|
|
const QList<RubberbandBase*> & rbList = activeRubberbands(map);
|
|
for (auto rb : rbList)
|
|
{
|
|
emit rb->abort(rb);
|
|
rb->doAutoDelete();
|
|
}
|
|
} /* RubberbandBase::abortActiveRubberbands */
|
|
|
|
|
|
void RubberbandBase::deleteMySelf()
|
|
{
|
|
if (_viewPortEventDispatcher) _viewPortEventDispatcher -> onDo_kickTheBucket();
|
|
if (_viewPortEventDispatcher) _viewPortEventDispatcher -> onDo_delete();
|
|
if (_windowEventDispatcher) _windowEventDispatcher -> onDo_delete();
|
|
|
|
_viewPortEventDispatcher = nullptr;
|
|
_windowEventDispatcher = nullptr;
|
|
_baseInternal->_isActive = false;
|
|
|
|
deleteLater();
|
|
} /* RubberbandBase::deleteMySelf */
|
|
|
|
|
|
RubberbandBase::RubberbandBase( SituationMap::Map * map, QObject * parent, bool isActive )
|
|
: QObject( parent )
|
|
, EventActionInterface()
|
|
, _baseInternal( new RubberbandBase::BaseInternalData(map,this) )
|
|
, _drawColor(QColor("black"))
|
|
, _fillColor(QColor("black"))
|
|
, _handleDrawColor(QColor("black"))
|
|
, _handleFillColor(QColor("yellow"))
|
|
, _handleSelectionColor(QColor("red"))
|
|
, _frameColor(QColor("black"))
|
|
, _frameFillColor(QColor(150,150,0,50))
|
|
, _frameSelectionColor(QColor(255,0,0,50))
|
|
, _frameHandleMargin(10)
|
|
, _pickingRatio(0)
|
|
, _finishAfterConstruction(true)
|
|
, _autoDelete(false)
|
|
, _viewPortEventDispatcher(nullptr)
|
|
, _windowEventDispatcher (nullptr)
|
|
, _userData(nullptr)
|
|
{
|
|
_fillColor.setAlpha(100);
|
|
|
|
if (isActive) activate();
|
|
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
* In case of multiple rubberbands can be active, it is forbidden to
|
|
* create a rubberband of the same type twice anyway.
|
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
bool rubberbandOfSameTypeIsActive = false;
|
|
const auto rubberbands = SituationMap::RB::activeRubberbands().value(map);
|
|
for (auto rbnd : rubberbands)
|
|
{
|
|
// Just to check the class names with debugger
|
|
// const char * rbndName = typeid(*rbnd).name();
|
|
// const char * thisName = typeid(*this).name();
|
|
|
|
if (( typeid(*rbnd) == typeid(*this)) && rbnd->rubberbandIsAlive())
|
|
{
|
|
rubberbandOfSameTypeIsActive = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (rubberbandOfSameTypeIsActive)
|
|
{
|
|
// disable dispatcher, so the rubberband is not alive yet.
|
|
if (_viewPortEventDispatcher)
|
|
{
|
|
_viewPortEventDispatcher -> onDo_kickTheBucket();
|
|
_viewPortEventDispatcher -> onDo_delete();
|
|
}
|
|
if (_windowEventDispatcher) _windowEventDispatcher->onDo_delete();
|
|
_viewPortEventDispatcher = nullptr;
|
|
_windowEventDispatcher = nullptr;
|
|
}
|
|
else
|
|
{
|
|
SituationMap::RB::activeRubberbands()[map].append( this );
|
|
if (_windowEventDispatcher)
|
|
{
|
|
_windowEventDispatcher->setCursor(QCursor(Qt::CrossCursor));
|
|
_windowEventDispatcher->grab();
|
|
}
|
|
if (_viewPortEventDispatcher)
|
|
{
|
|
_viewPortEventDispatcher->setCursor(QCursor(Qt::CrossCursor));
|
|
_viewPortEventDispatcher->grab();
|
|
}
|
|
}
|
|
|
|
if (map)
|
|
{
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
*
|
|
* Sending signals of RubberbandFactory to inform about rubberband creation and destroy would be
|
|
* better placed in RubberbandFactory source (rubberband_factory.cpp) but there it's a lot of
|
|
* more writing stuff ...
|
|
*
|
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
SituationMap::RB::RubberbandFactory & rbndFactory = map -> rubberbandFactory();
|
|
emit rbndFactory.rubberbandCreated();
|
|
|
|
connect( this, &QObject::destroyed, &rbndFactory, &SituationMap::RB::RubberbandFactory::rubberbandDestroyed );
|
|
}
|
|
|
|
} /* RubberbandBase::RubberbandBase */
|
|
|
|
|
|
RubberbandBase::~RubberbandBase()
|
|
{
|
|
if (_viewPortEventDispatcher) _viewPortEventDispatcher -> onDo_kickTheBucket();
|
|
if (_viewPortEventDispatcher) _viewPortEventDispatcher -> onDo_delete();
|
|
if (_windowEventDispatcher) _windowEventDispatcher -> onDo_delete();
|
|
|
|
_viewPortEventDispatcher = nullptr;
|
|
_windowEventDispatcher = nullptr;
|
|
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
* Test if map has been already destroyed. If map exists all is nice ...
|
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
if (_baseInternal->_map)
|
|
{
|
|
SituationMap::RB::activeRubberbands()[_baseInternal->_map].removeOne( this );
|
|
emit finished( this );
|
|
}
|
|
else
|
|
{
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
* ... otherwise we have to search the rubberband
|
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
const auto rubberbands = SituationMap::RB::activeRubberbands();
|
|
for (auto rubberList : rubberbands)
|
|
rubberList.removeOne(this);
|
|
}
|
|
|
|
delete _baseInternal;
|
|
_baseInternal = nullptr;
|
|
|
|
} /* RubberbandBase::~RubberbandBase */
|
|
|
|
|
|
QPointF RubberbandBase::projectCoordinateToMap( CoordinateSystem cs, const QPointF & loc ) const
|
|
{
|
|
return (cs != CoordinateSystem::Geo || !_baseInternal->_mapCtFunctor) ? loc : _baseInternal->_mapCtFunctor->geographicToMap( loc );
|
|
} /* RubberbandBase::projectCoordinateToMap */
|
|
|
|
|
|
QPointF RubberbandBase::projectCoordinateFromMap( CoordinateSystem cs, const QPointF & loc ) const
|
|
{
|
|
return (cs != CoordinateSystem::Geo || !_baseInternal->_mapCtFunctor) ? loc : _baseInternal->_mapCtFunctor->mapToGeographic( loc );
|
|
} /* RubberbandBase::projectCoordinateFromMap */
|
|
|
|
|
|
QPointF RubberbandBase::projectCoordinateFromMap( CoordinateSystem cs, const Esri::ArcGISRuntime::Point & loc ) const
|
|
{
|
|
return (cs != CoordinateSystem::Geo || !_baseInternal->_mapCtFunctor) ? QPointF(loc.x(), loc.y()) : _baseInternal->_mapCtFunctor->mapToGeographic( loc );
|
|
} /* RubberbandBase::projectCoordinateFromMap */
|
|
|
|
|
|
|
|
void RubberbandBase::activate()
|
|
{
|
|
if (!_baseInternal->_map) return;
|
|
|
|
if (!_baseInternal->_isActive)
|
|
{
|
|
QGraphicsView * view = _baseInternal->_map->getQGraphicsView();
|
|
if (view)
|
|
{
|
|
_viewPortEventDispatcher = new EventDispatcher(view->viewport(), this);
|
|
_windowEventDispatcher = new EventDelegater(view, _viewPortEventDispatcher);
|
|
_baseInternal->_isActive = true;
|
|
|
|
MapImpl *mapImpl = static_cast<MapImpl*>(_baseInternal->_map.data());
|
|
|
|
connect(_viewPortEventDispatcher.data(), &EventDispatcher::mouseMovedEvent,
|
|
mapImpl, &MapImpl::onHandleMouseMove);
|
|
}
|
|
}
|
|
} /* RubberbandBase::activate */
|
|
|
|
|
|
bool RubberbandBase::autoSelectAction(int x, int y)
|
|
{
|
|
_viewPortEventDispatcher->_leftPressHandled = true;
|
|
return selectAction(nullptr,x,y);
|
|
} /* RubberbandBase::autoSelectAction */
|
|
|
|
|
|
void RubberbandBase::installExternalUpdate(const std::function<bool(RubberbandBase*)> & updateFunctor)
|
|
{
|
|
_baseInternal->_updateFunctorList << updateFunctor;
|
|
} // void RubberbandBase::installExternalUpdate( const std::function<bool(RubberbandBase*)> & updateFunctor)
|
|
|
|
|
|
void RubberbandBase::externalUpdate()
|
|
{
|
|
for (const auto &update : qAsConst(_baseInternal->_updateFunctorList))
|
|
{
|
|
if (!update(this))
|
|
break;
|
|
}
|
|
} // void RubberbandBase::externalUpdate()
|
|
|
|
|
|
|
|
void RubberbandBase::updateButtonPosition()
|
|
{
|
|
if ((_baseInternal->_lastClickPosition.x() < 0) || (_baseInternal->_lastClickPosition.y() < 0))
|
|
_baseInternal->_buttonBoxSceneAnchor = sceneBbox().bottomRight();
|
|
else
|
|
_baseInternal->_buttonBoxSceneAnchor = _baseInternal->_lastClickPosition;
|
|
|
|
// _internal->_mapView->update();
|
|
} /* RubberbandBase::updateButtonPosition */
|
|
|
|
|
|
void RubberbandBase::setFixedButtonBoxPosition( QPoint widgetPos )
|
|
{
|
|
_baseInternal->_buttonBoxFixPosition = widgetPos;
|
|
activateButtons();
|
|
} /* RubberbandBase::setFixedButtonBoxPosition */
|
|
|
|
|
|
void RubberbandBase::unsetFixedButtonBoxPosition()
|
|
{
|
|
_baseInternal->_buttonBoxFixPosition = QPoint(-1,-1);
|
|
|
|
if (_baseInternal->_buttonProxy)
|
|
{
|
|
_baseInternal->_buttonProxy->setPos( _baseInternal->_buttonBoxSceneAnchor );
|
|
}
|
|
} /* RubberbandBase::unsetFixedButtonBoxPosition */
|
|
|
|
|
|
bool RubberbandBase::isButtonBoxPositionFixed() { return ((_baseInternal->_buttonBoxFixPosition.x() >= 0) && (_baseInternal->_buttonBoxFixPosition.y() >= 0)); }
|
|
|
|
|
|
void RubberbandBase::onDo_updateButtonFixCoordinates()
|
|
{
|
|
if (!_baseInternal->_buttonProxy) return;
|
|
|
|
if (isButtonBoxPositionFixed())
|
|
{
|
|
// Don't use bottom right corner of rubberband bbox to place the buttons,
|
|
// rather than use fixed window position.
|
|
|
|
const QPoint & pos = _baseInternal->_buttonBoxFixPosition;
|
|
_baseInternal->_buttonProxy->setPos( pixel2ScenePosition(pos.x(),pos.y()) );
|
|
}
|
|
} /* RubberbandStateSelect::onDo_updateButtonFixCoordinates */
|
|
|
|
|
|
void RubberbandBase::activateButtons()
|
|
{
|
|
DEBUG_LOG(_baseInternal->_logger) << LOGFUNCTION;
|
|
if (!_baseInternal->_buttonProxy)
|
|
{
|
|
_baseInternal->_buttonProxy = new RubberbandHandleProxy( _baseInternal->_map->getQGraphicsView(), _baseInternal->_buttonBox );
|
|
_baseInternal->_buttonProxy->setRestoreCursor( _baseInternal->_restoreCursor ); // workaround Qt bug. remove when fixed
|
|
|
|
connect( _baseInternal->_buttonProxy.get(), &RubberbandHandleProxy::adjusted, this, [this]()
|
|
{
|
|
this->_baseInternal->_buttonBoxSceneAnchor = this->_baseInternal->_buttonProxy->getCoordinate()._sceneCoordinate;
|
|
} );
|
|
}
|
|
|
|
_baseInternal->enableAndShowOnlyPossibleButtons();
|
|
|
|
if (isButtonBoxPositionFixed())
|
|
{
|
|
const QPoint & pos = _baseInternal->_buttonBoxFixPosition;
|
|
_baseInternal->_buttonProxy->setPos( pixel2ScenePosition(pos.x(),pos.y()) );
|
|
_baseInternal->_buttonProxy->setSceneOffset( QPointF(0,0) );
|
|
|
|
}
|
|
else
|
|
{
|
|
_baseInternal->_buttonProxy->setPos( _baseInternal->_buttonBoxSceneAnchor );
|
|
_baseInternal->_buttonProxy->setSceneOffset( QPointF(_frameHandleMargin+5,_frameHandleMargin+5) );
|
|
}
|
|
|
|
_baseInternal->_buttonProxy->show();
|
|
|
|
} /* Rubberband::activateButtons */
|
|
|
|
|
|
void RubberbandBase::deactivateButtons()
|
|
{
|
|
DEBUG_LOG(_baseInternal->_logger) << LOGFUNCTION;
|
|
if (isButtonBoxPositionFixed()) return;
|
|
if (_baseInternal->_buttonProxy) _baseInternal->_buttonProxy->hide();
|
|
} /* RubberbandBase::deactivateButtons() */
|
|
|
|
|
|
void RubberbandBase::adjustButtons()
|
|
{
|
|
if (_baseInternal->_buttonProxy)
|
|
{
|
|
activateButtons();
|
|
}
|
|
} /* RubberbandBase::adjustButtons */
|
|
|
|
|
|
void RubberbandBase::applyButtonClicked()
|
|
{
|
|
completeStateAction( _viewPortEventDispatcher, 0.0, 0.0 );
|
|
} /* RubberbandBase::applyButtonClicked */
|
|
|
|
|
|
void RubberbandBase::cancelButtonClicked()
|
|
{
|
|
abortAction( _viewPortEventDispatcher, 0.0, 0.0 );
|
|
} /* RubberbandBase::cancelButtonClicked */
|
|
|
|
|
|
void RubberbandBase::undoButtonClicked()
|
|
{
|
|
undoAction( _viewPortEventDispatcher, 0.0, 0.0 );
|
|
} /* RubberbandBase::undoButtonClicked */
|
|
|
|
|
|
void RubberbandBase::resetIconsToDefault()
|
|
{
|
|
if (BaseInternalData::_applyIcon) { delete BaseInternalData::_applyIcon; BaseInternalData::_applyIcon = nullptr; }
|
|
if (BaseInternalData::_abortIcon) { delete BaseInternalData::_abortIcon; BaseInternalData::_abortIcon = nullptr; }
|
|
if (BaseInternalData::_undoIcon ) { delete BaseInternalData::_undoIcon; BaseInternalData::_undoIcon = nullptr; }
|
|
} /* RubberbandBase::resetIconsToDefault */
|
|
|
|
|
|
void RubberbandBase::setIconApply(const QPixmap & icon)
|
|
{
|
|
if (BaseInternalData::_applyIcon == nullptr) BaseInternalData::_applyIcon = new QPixmap(icon);
|
|
else *BaseInternalData::_applyIcon = icon;
|
|
} /* RubberbandBase::setIconApply */
|
|
|
|
|
|
void RubberbandBase::setIconAbort(const QPixmap & icon)
|
|
{
|
|
if (BaseInternalData::_abortIcon == nullptr) BaseInternalData::_abortIcon = new QPixmap(icon);
|
|
else *BaseInternalData::_abortIcon = icon;
|
|
} /* RubberbandBase::setIconAbort */
|
|
|
|
|
|
void RubberbandBase::setIconUndo(const QPixmap & icon)
|
|
{
|
|
if (BaseInternalData::_undoIcon == nullptr) BaseInternalData::_undoIcon = new QPixmap(icon);
|
|
else *BaseInternalData::_undoIcon = icon;
|
|
} /* RubberbandBase::setIconUndo */
|
|
|
|
|
|
QPointF RubberbandBase::pixel2ScenePosition( int x, int y ) const
|
|
{
|
|
QGraphicsView * view = _baseInternal->_map->getQGraphicsView();
|
|
return (view) ? view->mapToScene(x, y) : QPointF(x,y);
|
|
} /* RubberbandBase::pixel2ScenePosition */
|
|
|
|
|
|
bool RubberbandBase::buttonPositionAction(AbstractEventDispatcher *, int x, int y)
|
|
{
|
|
QPointF scenePos(pixel2ScenePosition(x,y));
|
|
|
|
if (!_baseInternal->buttonProxyActive(scenePos))
|
|
{
|
|
_baseInternal->_buttonBoxSceneAnchor = scenePos;
|
|
adjustButtons();
|
|
}
|
|
return false;
|
|
} /* bool RubberbandBase::buttonPositionAction(AbstractEventDispatcher * causer, int x, int y) */
|
|
|
|
|
|
void RubberbandBase::unlinkEventDispatcher( AbstractEventDispatcher* )
|
|
{
|
|
_viewPortEventDispatcher = nullptr;
|
|
_windowEventDispatcher = nullptr;
|
|
|
|
} /* RubberbandBase::unlinkEventDispatcher */
|
|
|
|
|
|
bool RubberbandBase::abortAction( AbstractEventDispatcher * causer, int, int )
|
|
{
|
|
_baseInternal->_buttonBox->hide();
|
|
|
|
if (causer) causer->onDo_kickTheBucket();
|
|
|
|
emit abort( this );
|
|
doAutoDelete();
|
|
return true;
|
|
} /* RubberbandBase::abortAction */
|
|
|
|
|
|
bool RubberbandBase::applyAndEndAction( AbstractEventDispatcher * causer, int,int )
|
|
{
|
|
_baseInternal->_buttonBox->hide();
|
|
|
|
if (causer) causer->onDo_kickTheBucket();
|
|
|
|
emit apply( this );
|
|
doAutoDelete();
|
|
return true;
|
|
} /* RubberbandBase::applyAndEndAction */
|
|
|
|
} } /* namespace SituationMap::RB */
|