Initial commit
This commit is contained in:
commit
b7d90b9afe
16245 files changed
+3396666
No files matched your search
@@ -0,0 +1,572 @@
|
||||
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Implementation of rubberband class to edit states of point objects
|
||||
** $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 .........:
|
||||
**
|
||||
** 19.10.2015, JT : First edition for use with Qt5
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "rubberband_state_select.h"
|
||||
#include "rubberband_point_handle.h"
|
||||
#include "rubberband_drawable.h"
|
||||
#include "rubberband_handle_proxy.h"
|
||||
#include "rubberband_factory.h"
|
||||
|
||||
#include "rubberband_internal.h"
|
||||
#include "rubberband_base_internal.h"
|
||||
|
||||
|
||||
#include <arcgis/Map.h>
|
||||
#include <arcgis/MapGraphicsView.h>
|
||||
|
||||
#include <QtGui/QCursor>
|
||||
#include <QtWidgets/QPushButton>
|
||||
#include <QtWidgets/QHBoxLayout>
|
||||
#include <QtWidgets/QMenu>
|
||||
|
||||
#include "polygon.xpm"
|
||||
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
struct RubberbandStateSelect::InternalData
|
||||
{
|
||||
Q_DISABLE_COPY(InternalData)
|
||||
|
||||
InternalData() : _logger(getLogger("RubberbandStateSelect"))
|
||||
{}
|
||||
|
||||
~InternalData()
|
||||
{
|
||||
delete _stateMenu;
|
||||
}
|
||||
|
||||
QVector<State> _states;
|
||||
QVector<StateItem> _items;
|
||||
QList<SituationMap::RefPointer<RubberbandHandle>> _stateMenuSelectedHandleList;
|
||||
LOGGER_T _logger;
|
||||
|
||||
const State * getStateFromValue( int stateValue ) const
|
||||
{
|
||||
for (const State &state : _states)
|
||||
{
|
||||
if (state.value() == stateValue) return &state;
|
||||
}
|
||||
return nullptr;
|
||||
} /* getStateFromValue */
|
||||
|
||||
const State * getStateFromItem( const StateItem & item ) const { return getStateFromValue(item.stateValue()); }
|
||||
|
||||
static QPixmap * _polygonIcon;
|
||||
|
||||
QPushButton * _polygonButton = nullptr;
|
||||
QMenu * _stateMenu = nullptr;
|
||||
bool _stateMenuIsActive = false;
|
||||
|
||||
}; /* RubberbandMultiPointFeature::InternalData */
|
||||
|
||||
|
||||
QPixmap * RubberbandStateSelect::InternalData::_polygonIcon = nullptr;
|
||||
|
||||
void RubberbandStateSelect::setIconPolygon(const QPixmap & icon)
|
||||
{
|
||||
if (InternalData::_polygonIcon == nullptr) InternalData::_polygonIcon = new QPixmap(icon);
|
||||
else *InternalData::_polygonIcon = icon;
|
||||
} /* RubberbandStateSelect::setIconPolygon */
|
||||
|
||||
|
||||
RubberbandStateSelect::RubberbandStateSelect( SituationMap::Map * map, QObject * parent )
|
||||
: Rubberband(map,parent), _internal(new InternalData())
|
||||
{
|
||||
delete RubberbandBase::_baseInternal->_undoButton;
|
||||
RubberbandBase::_baseInternal->_undoButton = nullptr;
|
||||
|
||||
_internal->_polygonButton = new QPushButton( (InternalData::_polygonIcon) ? *InternalData::_polygonIcon : QPixmap(polygon_xpm), QString(), RubberbandBase::_baseInternal->_buttonBox );
|
||||
|
||||
RubberbandBase::_baseInternal->_buttonLayout->insertWidget( 0, _internal->_polygonButton );
|
||||
|
||||
connect( _internal->_polygonButton, &QPushButton::clicked, this, &RubberbandStateSelect::onDo_areaSelectionBegin );
|
||||
|
||||
// Check Quartz
|
||||
connect( Rubberband::_internal->_mapView.data(), &Esri::ArcGISRuntime::MapGraphicsView::viewpointChanged,
|
||||
this, &RubberbandStateSelect::onDo_updateButtonFixCoordinates );
|
||||
connect( Rubberband::_internal->_mapView.data(), &Esri::ArcGISRuntime::MapGraphicsView::rectChanged ,
|
||||
this, &RubberbandStateSelect::onDo_updateButtonFixCoordinates );
|
||||
|
||||
|
||||
setFixedButtonBoxPosition(QPoint(5,5));
|
||||
|
||||
} /* RubberbandStateSelect::RubberbandStateSelect */
|
||||
|
||||
|
||||
bool RubberbandStateSelect::setStateItems( const QVector<State> & stateVector
|
||||
, const QVector<StateItem> & itemVector
|
||||
, CoordinateSystem cs )
|
||||
{
|
||||
if (stateVector.size() < 2) return false;
|
||||
if (itemVector.isEmpty()) return false;
|
||||
|
||||
// check for all states are valid
|
||||
for (const State & state : qAsConst(_internal->_states))
|
||||
{
|
||||
if (!state.isValid())
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ok = true;
|
||||
|
||||
_internal -> _states = stateVector;
|
||||
_internal -> _items = itemVector;
|
||||
|
||||
for (QVector<StateItem>::iterator it = _internal->_items.begin(); it != _internal->_items.end(); ++it)
|
||||
{
|
||||
if (it->isValid())
|
||||
{
|
||||
const State * statePtr = _internal->getStateFromItem( *it );
|
||||
|
||||
if (statePtr == nullptr)
|
||||
{
|
||||
ok = false;
|
||||
statePtr = & _internal->_states.first();
|
||||
}
|
||||
|
||||
const QPointF &mapPos = projectCoordinateToMap( cs, it->coordinate() );
|
||||
|
||||
Esri::ArcGISRuntime::Point mapCoordinate( mapPos.x(), mapPos.y(), Rubberband::_internal->_mapView->map()->spatialReference() );
|
||||
RubberbandPointHandle * handlePtr = new RubberbandPointHandle( Rubberband::_internal->_mapView
|
||||
, Rubberband::_internal->_mapScene
|
||||
, mapCoordinate
|
||||
, statePtr->icon() );
|
||||
if (handlePtr)
|
||||
{
|
||||
handlePtr->setSelection(false);
|
||||
handlePtr->setUserData( &(*it) );
|
||||
Rubberband::_internal->_handleList.append( SituationMap::RefPointer<RubberbandHandle>(handlePtr) );
|
||||
}
|
||||
}
|
||||
else ok = false;
|
||||
}
|
||||
update();
|
||||
activateButtons();
|
||||
buildStateMenu();
|
||||
return ok;
|
||||
} /* RubberbandStateSelect::setStateItems */
|
||||
|
||||
|
||||
const QVector<RubberbandStateSelect::StateItem> & RubberbandStateSelect::stateItems() const
|
||||
{
|
||||
return _internal->_items;
|
||||
} /* RubberbandStateSelect::stateItems */
|
||||
|
||||
|
||||
void RubberbandStateSelect::activateButtons()
|
||||
{
|
||||
_baseInternal->_hasUndoButton = false;
|
||||
_baseInternal->_applyIsPossible = (!Rubberband::_internal->_handleList.isEmpty());
|
||||
_baseInternal->_undoIsPossible = false;
|
||||
Rubberband::activateButtons();
|
||||
} /* RubberbandStateSelect::activateButton */
|
||||
|
||||
|
||||
void RubberbandStateSelect::toggleState( RubberbandPointHandle * handlePtr )
|
||||
{
|
||||
if (_internal->_states.size() < 2) return;
|
||||
if (handlePtr == nullptr) return;
|
||||
|
||||
StateItem * itemPtr = static_cast<StateItem*>(handlePtr->userData());
|
||||
|
||||
if (itemPtr == nullptr) return;
|
||||
|
||||
if (_internal->_states.size() == 2)
|
||||
{
|
||||
const State * statePtr = _internal -> getStateFromItem( *itemPtr );
|
||||
|
||||
if (statePtr != nullptr)
|
||||
{
|
||||
if (statePtr == &_internal->_states.first()) statePtr = &_internal->_states.last();
|
||||
else statePtr = &_internal->_states.first();
|
||||
}
|
||||
else statePtr = &_internal->_states.first();
|
||||
|
||||
itemPtr->_stateValue = statePtr->value();
|
||||
handlePtr->setIcon( statePtr->icon() );
|
||||
}
|
||||
|
||||
} /* RubberbandStateSelect::toggleState */
|
||||
|
||||
|
||||
void RubberbandStateSelect::setState( RubberbandPointHandle * handlePtr, int stateValue )
|
||||
{
|
||||
if (handlePtr == nullptr) return;
|
||||
|
||||
const State * statePtr = _internal -> getStateFromValue(stateValue);
|
||||
StateItem * itemPtr = static_cast<StateItem*>(handlePtr->userData());
|
||||
|
||||
if (itemPtr == nullptr) return;
|
||||
if (statePtr == nullptr) return;
|
||||
|
||||
itemPtr->_stateValue = stateValue;
|
||||
handlePtr->setIcon( statePtr->icon() );
|
||||
|
||||
} /* RubberbandStateSelect::setState */
|
||||
|
||||
|
||||
void RubberbandStateSelect::buildStateMenu()
|
||||
{
|
||||
if (_internal->_states.isEmpty()) return;
|
||||
|
||||
_internal->_stateMenu = new QMenu();
|
||||
|
||||
for (const State & state : qAsConst(_internal->_states))
|
||||
{
|
||||
QAction * action = _internal->_stateMenu->addAction( state.icon(), state.description() );
|
||||
action -> setData( state.value() );
|
||||
|
||||
connect( action, &QAction::triggered, this, &RubberbandStateSelect::onDo_setState );
|
||||
}
|
||||
|
||||
connect( _internal->_stateMenu, &QMenu::aboutToShow, this, [this]()
|
||||
{
|
||||
this->_internal->_stateMenuSelectedHandleList.clear();
|
||||
|
||||
_baseInternal->_buttonBox->setDisabled(true);
|
||||
for (auto handle : qAsConst(Rubberband::_internal->_handleList))
|
||||
{
|
||||
if (handle->isSelected())
|
||||
{
|
||||
this->_internal->_stateMenuSelectedHandleList << handle;
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
connect( _internal->_stateMenu, &QMenu::aboutToHide, this, [this]()
|
||||
{
|
||||
_baseInternal->_buttonBox->setEnabled(true);
|
||||
deSelectHandles();
|
||||
} );
|
||||
|
||||
} /* RubberbandStateSelect::buildStateMenu */
|
||||
|
||||
|
||||
void RubberbandStateSelect::onDo_setState(bool)
|
||||
{
|
||||
QAction * action = (QAction*) sender();
|
||||
|
||||
if (action == nullptr) return;
|
||||
|
||||
int stateValue = action->data().toInt();
|
||||
|
||||
for (auto handle : qAsConst(_internal->_stateMenuSelectedHandleList))
|
||||
setState( dynamic_cast<RubberbandPointHandle*>(handle.get()), stateValue );
|
||||
|
||||
_internal -> _stateMenuSelectedHandleList.clear();
|
||||
_internal -> _stateMenuIsActive = false;
|
||||
|
||||
update();
|
||||
|
||||
} /* RubberbandStateSelect::onDo_setState */
|
||||
|
||||
|
||||
void RubberbandStateSelect::chooseStateMenu()
|
||||
{
|
||||
// popup a window with states the user can choose
|
||||
_internal->_stateMenu->popup( QCursor::pos() );
|
||||
_internal -> _stateMenuIsActive = true;
|
||||
} /* RubberbandStateSelect::chooseStateMenu */
|
||||
|
||||
|
||||
bool RubberbandStateSelect::selectAction( AbstractEventDispatcher*, int x, int y )
|
||||
{
|
||||
DEBUG_LOG(_internal->_logger) << LOGFUNCTION << x << " ; " << y;
|
||||
|
||||
_internal->_stateMenuSelectedHandleList.clear();
|
||||
|
||||
if (rubberbandIsAlive())
|
||||
{
|
||||
if (_internal->_stateMenuIsActive) return true;
|
||||
|
||||
QPointF scenePos(pixel2ScenePosition(x,y));
|
||||
|
||||
if (_baseInternal->buttonProxyActive(scenePos)) return false;
|
||||
|
||||
RubberbandHandle * handlePtr = pickHandle(x,y);
|
||||
|
||||
if (handlePtr)
|
||||
{
|
||||
handlePtr->setSelection();
|
||||
enableSelectedState();
|
||||
|
||||
update();
|
||||
deactivateButtons();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} /* RubberbandStateSelect::selectAction */
|
||||
|
||||
|
||||
bool RubberbandStateSelect::multiSelectActionPress(AbstractEventDispatcher*, int x, int y)
|
||||
{
|
||||
DEBUG_LOG(_internal->_logger) << LOGFUNCTION << x << " ; " << y;
|
||||
|
||||
if (rubberbandIsAlive())
|
||||
{
|
||||
if (_internal -> _stateMenuIsActive) return true;
|
||||
|
||||
RubberbandHandle * handlePtr = pickHandle(x,y);
|
||||
|
||||
if (handlePtr)
|
||||
{
|
||||
handlePtr->setSelection();
|
||||
enableSelectedState();
|
||||
enableMultiSelectedState();
|
||||
|
||||
update();
|
||||
deactivateButtons();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} /* RubberbandStateSelect::multiSelectActionPress */
|
||||
|
||||
|
||||
bool RubberbandStateSelect::multiSelectActionRelease( AbstractEventDispatcher*, int, int )
|
||||
{
|
||||
return false;
|
||||
} /* RubberbandStateSelect::multiSelectActionRelease */
|
||||
|
||||
|
||||
bool RubberbandStateSelect::setCoordinateAction( AbstractEventDispatcher * causer, int x, int y )
|
||||
{
|
||||
DEBUG_LOG(_internal->_logger) << LOGFUNCTION << x << " ; " << y;
|
||||
|
||||
if (rubberbandIsAlive())
|
||||
{
|
||||
Rubberband::_internal->_lastClickPosition = pixel2ScenePosition(x,y);
|
||||
|
||||
if (_internal->_stateMenuIsActive)
|
||||
{
|
||||
_internal -> _stateMenuIsActive = false;
|
||||
disenableSelectedState();
|
||||
disenableMultiSelectedState();
|
||||
activateButtons();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isEnabledSelectedState())
|
||||
{
|
||||
bool handlePicked = (pickHandle(x,y) != nullptr);
|
||||
bool toggleMode = (_internal->_states.size() == 2);
|
||||
bool eventHandled = false;
|
||||
|
||||
if (!toggleMode)
|
||||
{
|
||||
disenableSelectedState();
|
||||
disenableMultiSelectedState();
|
||||
|
||||
chooseStateMenu();
|
||||
return true;
|
||||
}
|
||||
for (auto handle : qAsConst(Rubberband::_internal->_handleList))
|
||||
{
|
||||
RubberbandPointHandle * handlePointPtr = dynamic_cast<RubberbandPointHandle*>(handle.get());
|
||||
if ((handlePointPtr) && (handlePointPtr->isSelected()))
|
||||
{
|
||||
handlePointPtr->setSelection(false);
|
||||
if ((handlePicked) && (toggleMode)) toggleState( handlePointPtr );
|
||||
eventHandled = true;
|
||||
}
|
||||
}
|
||||
|
||||
disenableSelectedState();
|
||||
disenableMultiSelectedState();
|
||||
activateButtons();
|
||||
return eventHandled;
|
||||
}
|
||||
else Rubberband::setCoordinateAction(causer,x,y);
|
||||
}
|
||||
return false;
|
||||
} /* RubberbandStateSelect::setCoordinateAction */
|
||||
|
||||
|
||||
bool RubberbandStateSelect::moveAction(AbstractEventDispatcher*, int x, int y)
|
||||
{
|
||||
DEBUG_LOG(_internal->_logger) << LOGFUNCTION << x << " ; " << y;
|
||||
|
||||
if (rubberbandIsAlive())
|
||||
{
|
||||
if (_internal -> _stateMenuIsActive) return false;
|
||||
|
||||
bool eventHandled = false;
|
||||
|
||||
QPointF scenePosition(pixel2ScenePosition(x,y));
|
||||
|
||||
if (_baseInternal->buttonProxyActive(scenePosition)) return false;
|
||||
|
||||
if (Rubberband::_internal->_mapView != nullptr)
|
||||
{
|
||||
if (!isEnabledMultiSelectedState()) deSelectHandles();
|
||||
|
||||
RubberbandHandle * handlePtr = pickHandle(x,y);
|
||||
if (handlePtr != nullptr)
|
||||
{
|
||||
handlePtr->setSelection();
|
||||
eventHandled = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (eventHandled) update();
|
||||
}
|
||||
return false;
|
||||
} /* RubberbandStateSelect::moveAction */
|
||||
|
||||
|
||||
bool RubberbandStateSelect::movePickedAction(AbstractEventDispatcher * causer, int x, int y )
|
||||
{
|
||||
DEBUG_LOG(_internal->_logger) << LOGFUNCTION << x << " ; " << y;
|
||||
|
||||
Rubberband::movePickedAction(causer,x,y);
|
||||
return false; // isEnabledSelectedState() || _internal->_stateMenuIsActive;
|
||||
} /* RubberbandStateSelect::movePickedAction */
|
||||
|
||||
|
||||
bool RubberbandStateSelect::contextMenuAction( AbstractEventDispatcher*, int, int )
|
||||
{
|
||||
if (!_internal -> _stateMenuIsActive) chooseStateMenu();
|
||||
return true;
|
||||
} /* RubberbandStateSelect::contextMenuAction */
|
||||
|
||||
|
||||
void RubberbandStateSelect::onDo_areaSelectionBegin()
|
||||
{
|
||||
bool mRbands = _baseInternal->_map->rubberbandFactory().allowMultipleRubberbands();
|
||||
_baseInternal->_map->rubberbandFactory().allowMultipleRubberbands(true);
|
||||
{
|
||||
RB::RubberbandMultiPointFeature * selectionRB = _baseInternal->_map->rubberbandFactory().create<RB::RubberbandMultiPointFeature>(this);
|
||||
|
||||
if (selectionRB == nullptr)
|
||||
{
|
||||
qWarning() << LOGFUNCTION << "Creating rubberband multi points feature failed";
|
||||
}
|
||||
else
|
||||
{
|
||||
selectionRB->setAutoDelete(true); // when finished rubberband will commit suicide
|
||||
selectionRB->setDrawColor( QColor(255,0,0,255) );
|
||||
selectionRB->setFillColor( QColor( 0,0,0,100) );
|
||||
|
||||
selectionRB -> enableClosed( true );
|
||||
selectionRB -> enableFinishAfterConstruction( true );
|
||||
|
||||
selectionRB -> setFixedButtonBoxPosition(QPoint(15,15));
|
||||
|
||||
QObject::connect( selectionRB, &RB::Rubberband::apply, this, &RubberbandStateSelect::onDo_areaSelectionApply );
|
||||
QObject::connect( selectionRB, &RB::Rubberband::abort, this, &RubberbandStateSelect::onDo_areaSelectionAbort );
|
||||
|
||||
RubberbandBase::_baseInternal->_buttonBox->setDisabled(true);
|
||||
}
|
||||
}
|
||||
_baseInternal->_map->rubberbandFactory().allowMultipleRubberbands( mRbands );
|
||||
} /* RubberbandStateSelect::onDo_areaSelectionBegin */
|
||||
|
||||
|
||||
void RubberbandStateSelect::onDo_areaSelectionApply( RubberbandBase * selectionRB )
|
||||
{
|
||||
RubberbandBase::_baseInternal->_buttonBox->setEnabled(true);
|
||||
if (selectionRB)
|
||||
{
|
||||
QVector<QPointF> polygonVertexList = selectionRB->coordinateVector( CoordinateSystem::Map );
|
||||
|
||||
// Looking for all handle which are inside polygon and select
|
||||
|
||||
unsigned int hitCounter = 0;
|
||||
|
||||
for (auto handle : qAsConst(Rubberband::_internal->_handleList))
|
||||
{
|
||||
RubberbandPointHandle * handlePointPtr = dynamic_cast<RubberbandPointHandle*>(handle.get());
|
||||
if (handlePointPtr)
|
||||
{
|
||||
const Esri::ArcGISRuntime::Point &v = handlePointPtr->getCoordinate()._mapCoordinate;
|
||||
bool inside = false;
|
||||
int nvert = polygonVertexList.size();
|
||||
|
||||
for (int i = 0, j = nvert-1; i < nvert; j = i++)
|
||||
{
|
||||
const QPointF & vertex_i = polygonVertexList[i];
|
||||
const QPointF & vertex_j = polygonVertexList[j];
|
||||
|
||||
if ((vertex_i.y()>v.y()) != (vertex_j.y()>v.y()))
|
||||
{
|
||||
if (v.x() < (vertex_j.x() - vertex_i.x()) * (v.y() - vertex_i.y()) / (vertex_j.y() - vertex_i.y()) + vertex_i.x())
|
||||
{
|
||||
inside = !inside;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (inside)
|
||||
{
|
||||
hitCounter++;
|
||||
handlePointPtr->setSelection();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (hitCounter > 0)
|
||||
{
|
||||
if (_internal->_states.size() == 2)
|
||||
{
|
||||
for (auto handle : qAsConst(Rubberband::_internal->_handleList))
|
||||
{
|
||||
if (!handle->isSelected()) continue;
|
||||
handle->setSelection(false);
|
||||
toggleState( dynamic_cast<RubberbandPointHandle*>(handle.get()) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
chooseStateMenu();
|
||||
// ????? enableMultiSelectedState();
|
||||
}
|
||||
}
|
||||
}
|
||||
} /* RubberbandStateSelect::onDo_areaSelectionApply */
|
||||
|
||||
|
||||
void RubberbandStateSelect::onDo_areaSelectionAbort( RubberbandBase * )
|
||||
{
|
||||
_baseInternal->_buttonBox->setEnabled(true);
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Really nothing else to do here?
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
} /* RubberbandStateSelect::onDo_areaSelectionAbort */
|
||||
|
||||
|
||||
void RubberbandStateSelect::update()
|
||||
{
|
||||
Rubberband::update();
|
||||
|
||||
onDo_updateButtonFixCoordinates();
|
||||
|
||||
} /* RubberbandPointCluster::update */
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
Reference in new issue
Block a user