Initial commit
This commit is contained in:
commit
b7d90b9afe
16245 files changed
+3396666
No files matched your search
@@ -0,0 +1,495 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Event Dispatcher for Qt5 to delegate mouse and keyboard event to another event dispatcher
|
||||
** $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 .........:
|
||||
**
|
||||
** 15.04.2015, JT : First edition
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "event_mouse_navigator.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <QtGui/QMouseEvent>
|
||||
#include <QtGui/QWheelEvent>
|
||||
|
||||
#include <QtWidgets/QApplication>
|
||||
#include <QtWidgets/QGesture>
|
||||
#include <QtWidgets/QGraphicsSceneMouseEvent>
|
||||
|
||||
#include <QtWidgets/QWidget>
|
||||
|
||||
#include <QtCore/QDebug> // for debugging only
|
||||
#include <QtCore/QCoreApplication>
|
||||
|
||||
#include <Map.h>
|
||||
#include <Layer.h>
|
||||
#include <FeatureLayer.h>
|
||||
#include <GraphicsLayer.h>
|
||||
#include <MessageGroupLayer.h>
|
||||
#include <Graphic.h>
|
||||
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
int EventMouseNavigator::_pickTolerance = 20;
|
||||
|
||||
EventMouseNavigator::EventMouseNavigator(QWidget * getEventsFrom, EsriRuntimeQt::Map * esriMap )
|
||||
: AbstractEventDispatcher(getEventsFrom)
|
||||
, _esriMap(esriMap)
|
||||
, _selectionMode()
|
||||
, _selectedIdList()
|
||||
, _idConnectionCount(0)
|
||||
, _mousePanningActive(false)
|
||||
{
|
||||
} /* EventMouseNavigator::EventMouseNavigator */
|
||||
|
||||
|
||||
bool EventMouseNavigator::eventFilter(QObject * watched, QEvent * e)
|
||||
{
|
||||
Q_UNUSED(watched);
|
||||
|
||||
QString debugString(QLatin1String("unhandled event"));
|
||||
|
||||
if (hasFinished()) return true; // don't accept new events if dispatcher is going to finish
|
||||
if (hasActiveEvent()) return true; // don't accept new events before last event has been handled completly
|
||||
|
||||
if (e)
|
||||
{
|
||||
bool handled( false );
|
||||
|
||||
setActiveEvent( true );
|
||||
|
||||
switch( e->type() )
|
||||
{
|
||||
|
||||
case QEvent::MouseButtonPress :
|
||||
{
|
||||
debugString = QLatin1String("mouse button press event");
|
||||
|
||||
QMouseEvent * mouseEvent = static_cast<QMouseEvent*>(e);
|
||||
|
||||
_mousePanningActive = false;
|
||||
|
||||
_mouseMoveRefPos = mouseEvent->pos();
|
||||
_restoreMouseCursor = getCursorFromWidget();
|
||||
|
||||
if (Qt::LeftButton == mouseEvent->button())
|
||||
{
|
||||
handled = false;
|
||||
|
||||
if (mouseEvent->modifiers() == Qt::KeyboardModifier::ControlModifier)
|
||||
{
|
||||
_selectionMode = SelectionMode::MultiSelection;
|
||||
setCursorToWidget( QCursor(Qt::CursorShape::PointingHandCursor) );
|
||||
}
|
||||
else if (mouseEvent->modifiers().testFlag( Qt::KeyboardModifier::ShiftModifier ))
|
||||
{
|
||||
_selectionMode = SelectionMode::FrameSelection;
|
||||
if (mouseEvent->modifiers().testFlag(Qt::KeyboardModifier::ControlModifier))
|
||||
{
|
||||
_selectionMode &= SelectionMode::MultiSelection;
|
||||
}
|
||||
else
|
||||
{
|
||||
_selectionMode &= SelectionMode::SingleSelection;
|
||||
}
|
||||
setCursorToWidget( QCursor(Qt::CursorShape::SizeAllCursor) );
|
||||
}
|
||||
else
|
||||
{
|
||||
setCursorToWidget( QCursor(Qt::CursorShape::ArrowCursor) );
|
||||
_selectionMode = SelectionMode::SingleSelection;
|
||||
}
|
||||
}
|
||||
|
||||
if (Qt::MidButton == mouseEvent->button())
|
||||
{
|
||||
handled = (Qt::MidButton == mouseEvent->button());
|
||||
|
||||
_mousePanningActive = true;
|
||||
setCursorToWidget( QCursor(Qt::CursorShape::ClosedHandCursor) );
|
||||
}
|
||||
} break;
|
||||
|
||||
case QEvent::MouseButtonRelease :
|
||||
{
|
||||
debugString = QLatin1String("mouse button release event");
|
||||
|
||||
QMouseEvent * mouseEvent = static_cast<QMouseEvent*>(e);
|
||||
|
||||
if (Qt::LeftButton == mouseEvent->button())
|
||||
{
|
||||
handled = false;
|
||||
|
||||
if (!_mousePanningActive)
|
||||
{
|
||||
setCursorToWidget( _restoreMouseCursor );
|
||||
|
||||
selectionRequested( mouseEvent->pos() );
|
||||
|
||||
_selectionMode = SelectionMode::NoSelection;
|
||||
// do not handled = true; because some buttons in GraphicsView needs to get the event later.
|
||||
}
|
||||
}
|
||||
|
||||
if (Qt::RightButton == mouseEvent->button())
|
||||
{
|
||||
handled = true;
|
||||
pickRequested( mouseEvent->pos() );
|
||||
}
|
||||
|
||||
if ((_mousePanningActive) || (Qt::MidButton == mouseEvent->button()))
|
||||
{
|
||||
handled = (Qt::MidButton == mouseEvent->button());
|
||||
setCursorToWidget( _restoreMouseCursor );
|
||||
}
|
||||
|
||||
_mousePanningActive = false;
|
||||
} break;
|
||||
|
||||
case QEvent::MouseMove :
|
||||
{
|
||||
debugString = QLatin1String("mouse button move event");
|
||||
QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(e);
|
||||
|
||||
if (mouseEvent->timestamp() != _ignoreMouseMoveTimestamp)
|
||||
{
|
||||
if (isSignalConnected(QMetaMethod::fromSignal(&EventMouseNavigator::mouseMovedEvent)))
|
||||
{
|
||||
mouseMovedEvent( mouseEvent->pos().x(), mouseEvent->pos().y() );
|
||||
}
|
||||
|
||||
if ((!_mousePanningActive) && mouseEvent->buttons().testFlag(Qt::LeftButton))
|
||||
{
|
||||
QPoint deltaMove = mouseEvent->pos()-_mouseMoveRefPos;
|
||||
if (deltaMove.manhattanLength() > 3)
|
||||
{
|
||||
_mousePanningActive = true;
|
||||
setCursorToWidget( QCursor(Qt::CursorShape::ClosedHandCursor) );
|
||||
}
|
||||
}
|
||||
|
||||
if ((_mousePanningActive) || mouseEvent->buttons().testFlag(Qt::MidButton))
|
||||
{
|
||||
handled = true;
|
||||
EsriRuntimeQt::AnimationMode mode = _esriMap->animationMode();
|
||||
|
||||
QPoint deltaMove = mouseEvent->pos()-_mouseMoveRefPos;
|
||||
QPoint winCenter = QPoint( _getEventsFrom->width() / 2, _getEventsFrom->height() / 2 );
|
||||
QPoint newCenter = winCenter-deltaMove;
|
||||
|
||||
const EsriRuntimeQt::Point & mapCenter = _esriMap->toMapPoint(newCenter.x(), newCenter.y());
|
||||
|
||||
_esriMap -> setAnimationMode( EsriRuntimeQt::AnimationMode::NoAnimation );
|
||||
_esriMap -> panTo( mapCenter );
|
||||
_esriMap -> setAnimationMode(mode);
|
||||
|
||||
_getEventsFrom -> update();
|
||||
|
||||
_mouseMoveRefPos = mouseEvent->pos();
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case QEvent::Wheel :
|
||||
{
|
||||
debugString = QLatin1String("mouse wheel event");
|
||||
// QWheelEvent * wheelEvent = static_cast<QWheelEvent*>(e);
|
||||
// handled = true;
|
||||
handled = false;
|
||||
} break;
|
||||
|
||||
case QEvent::Gesture:
|
||||
{
|
||||
QGestureEvent * gestureEvent = static_cast<QGestureEvent*>(e);
|
||||
|
||||
if (gestureEvent)
|
||||
{
|
||||
const QList<QGesture*> & gestureList = gestureEvent->gestures();
|
||||
for (auto gesture : gestureList)
|
||||
{
|
||||
Qt::GestureType gestureType = gesture->gestureType();
|
||||
Qt::GestureState gestureState = gesture->state();
|
||||
|
||||
QTapGesture * tapGesture = nullptr;
|
||||
QTapAndHoldGesture * tapAndHoldGesture = nullptr;
|
||||
QPanGesture * panGesture = nullptr;
|
||||
QPinchGesture * pinchGesture = nullptr;
|
||||
QSwipeGesture * swipeGesture = nullptr;
|
||||
QString typeName;
|
||||
QString stateName;
|
||||
|
||||
switch (gestureType)
|
||||
{
|
||||
case Qt::TapGesture : tapGesture = (QTapGesture *)gesture; typeName = QLatin1String("TapGesture"); break;
|
||||
case Qt::TapAndHoldGesture : tapAndHoldGesture = (QTapAndHoldGesture*)gesture; typeName = QLatin1String("TapAndHoldGesture"); break;
|
||||
case Qt::PanGesture : panGesture = (QPanGesture *)gesture; typeName = QLatin1String("PanGesture"); break;
|
||||
case Qt::PinchGesture : pinchGesture = (QPinchGesture *)gesture; typeName = QLatin1String("PinchGesture"); break;
|
||||
case Qt::SwipeGesture : swipeGesture = (QSwipeGesture *)gesture; typeName = QLatin1String("SwipeGesture"); break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
switch (gestureState)
|
||||
{
|
||||
case Qt::NoGesture : stateName = QLatin1String("NoGesture"); break;
|
||||
case Qt::GestureStarted : stateName = QLatin1String("GestureStarted"); break;
|
||||
case Qt::GestureUpdated : stateName = QLatin1String("GestureUpdated"); break;
|
||||
case Qt::GestureFinished : stateName = QLatin1String("GestureFinished"); break;
|
||||
case Qt::GestureCanceled : stateName = QLatin1String("GestureCanceled"); break;
|
||||
}
|
||||
|
||||
// tapGesture = nullptr;
|
||||
panGesture = nullptr;
|
||||
|
||||
if (panGesture)
|
||||
{
|
||||
EsriRuntimeQt::AnimationMode mode = _esriMap->animationMode();
|
||||
|
||||
QPointF deltaMove = panGesture->delta();
|
||||
QPoint winCenter = QPoint( _getEventsFrom->width() / 2, _getEventsFrom->height() / 2 );
|
||||
QPoint newCenter = winCenter-QPoint((int)deltaMove.x(),(int)deltaMove.y());
|
||||
|
||||
const EsriRuntimeQt::Point & mapCenter = _esriMap->toMapPoint(newCenter.x(), newCenter.y());
|
||||
|
||||
_esriMap -> setAnimationMode( EsriRuntimeQt::AnimationMode::NoAnimation );
|
||||
_esriMap -> panTo( mapCenter );
|
||||
_esriMap -> setAnimationMode(mode);
|
||||
|
||||
_getEventsFrom -> update();
|
||||
|
||||
if (gestureState == Qt::GestureStarted) gestureEvent -> setAccepted(panGesture, true);
|
||||
|
||||
}
|
||||
|
||||
if (pinchGesture)
|
||||
{
|
||||
EsriRuntimeQt::AnimationMode mode = _esriMap->animationMode();
|
||||
QPinchGesture::ChangeFlags changeFlags = pinchGesture->changeFlags();
|
||||
|
||||
_esriMap -> setAnimationMode( EsriRuntimeQt::AnimationMode::NoAnimation );
|
||||
|
||||
if (changeFlags & QPinchGesture::RotationAngleChanged)
|
||||
{
|
||||
qreal deltaPhi = pinchGesture->rotationAngle() - pinchGesture->lastRotationAngle();
|
||||
_esriMap -> setRotation( _esriMap->rotation()-deltaPhi );
|
||||
}
|
||||
if (changeFlags & QPinchGesture::ScaleFactorChanged) _esriMap -> zoom( 1.0/pinchGesture->scaleFactor() );
|
||||
|
||||
_esriMap -> setAnimationMode(mode);
|
||||
|
||||
_getEventsFrom -> update();
|
||||
|
||||
if (gestureState == Qt::GestureStarted) gestureEvent -> setAccepted(pinchGesture, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
default: break;
|
||||
|
||||
} /* switch */
|
||||
|
||||
if (!hasFinished()) setActiveEvent( false );
|
||||
|
||||
if (handled) e->accept();
|
||||
|
||||
if (handled) return true;
|
||||
}
|
||||
return AbstractEventDispatcher::eventFilter(watched,e);
|
||||
|
||||
} /* EventMouseNavigator::eventFilter */
|
||||
|
||||
|
||||
void EventMouseNavigator::selectionRequested( const QPoint & pos )
|
||||
{
|
||||
const bool appendSelection = _selectionMode.testFlag( SelectionMode::MultiSelection );
|
||||
|
||||
if (isSignalConnected( QMetaMethod::fromSignal(&EventMouseNavigator::selectionRequest) ))
|
||||
{
|
||||
// do the work only in case of slot connections are installed
|
||||
|
||||
if (0 != _idConnectionCount)
|
||||
{
|
||||
qWarning() << LOGFUNCTION << " graphic layer id list request is still pending!";
|
||||
return;
|
||||
}
|
||||
|
||||
pickObjects( pos, _selectedIdList, appendSelection, &EventMouseNavigator::selectionRequest );
|
||||
|
||||
}
|
||||
} /* EventMouseNavigator::selectionRequested */
|
||||
|
||||
|
||||
void EventMouseNavigator::pickRequested( const QPoint & pos )
|
||||
{
|
||||
if (isSignalConnected( QMetaMethod::fromSignal(&EventMouseNavigator::contextMenuRequest) ))
|
||||
{
|
||||
// do the work only in case of slot connections are installed
|
||||
|
||||
if (0 != _idConnectionCount)
|
||||
{
|
||||
qWarning() << LOGFUNCTION << " graphic layer id list request is still pending!";
|
||||
return;
|
||||
}
|
||||
|
||||
pickObjects( pos, _selectedIdList, false, &EventMouseNavigator::contextMenuRequest );
|
||||
|
||||
}
|
||||
} /* EventMouseNavigator::pickRequested */
|
||||
|
||||
|
||||
void EventMouseNavigator::pickObjects( const QPoint & pos
|
||||
, QList<uint> & pickIdList
|
||||
, bool append
|
||||
, void (EventMouseNavigator::*pickSignal)(const QList< uint>&,QPoint) )
|
||||
{
|
||||
#ifdef NEVER
|
||||
if (!append) _selectedIdList.clear();
|
||||
|
||||
QList<EsriRuntimeQt::Layer*> layerList = _esriMap->layers();
|
||||
QList<EsriRuntimeQt::Layer*> selectLayerList;
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~ first look for all layers in map ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
for (auto layer : layerList)
|
||||
{
|
||||
EsriRuntimeQt::MessageGroupLayer* msgGrpLayer = qobject_cast<EsriRuntimeQt::MessageGroupLayer*>(layer);
|
||||
if (msgGrpLayer)
|
||||
{
|
||||
selectLayerList.append( msgGrpLayer->getLayers() );
|
||||
}
|
||||
else selectLayerList.append(layer);
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~ loop over all layers in layer list ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
for (auto layer : selectLayerList)
|
||||
{
|
||||
EsriRuntimeQt::FeatureLayer* featureLayer = qobject_cast<EsriRuntimeQt::FeatureLayer*>(layer);
|
||||
if (featureLayer)
|
||||
{
|
||||
/*~~~~~~~~~~~~~~~~~~~~~~~ get selected features by direct function call ~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
QList<qint64> fidList = featureLayer -> featureIds( pos.x(), pos.y(), _pickTolerance );
|
||||
featureLayer->selectFeatures( fidList, append );
|
||||
|
||||
EsriRuntimeQt::FeatureTable* featureTable = featureLayer->featureTable();
|
||||
|
||||
for (auto featureId : fidList)
|
||||
{
|
||||
if (featureTable)
|
||||
{
|
||||
EsriRuntimeQt::Feature* feature = featureTable->feature( featureId );
|
||||
if (feature)
|
||||
{
|
||||
bool ok;
|
||||
SituationMap::UniqueMapId id;
|
||||
|
||||
id = feature->property( SituationMap::UniqueMapIdProperty ).toUInt( &ok );
|
||||
if (ok)
|
||||
{
|
||||
if (!pickIdList.contains(id))
|
||||
{
|
||||
pickIdList += id;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // for
|
||||
} // if (featureLayer)
|
||||
|
||||
EsriRuntimeQt::GraphicsLayer * graphicsLayer = qobject_cast<EsriRuntimeQt::GraphicsLayer*>(layer);
|
||||
if (graphicsLayer)
|
||||
{
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* In case of message symbols, in a graphic layer a slot method has to be used to get
|
||||
* the ids of selected symbols. The slot installed (connected) each time
|
||||
* EventMouseNavigator::selectionRequested() has been called and will be disconnect itself at
|
||||
* beginning of slot function. Because the slot methode will be called later, we have to store
|
||||
* some information like the _selectedIdList as member variable.
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* connect here, because the layer in MessageGroupLayer can change:
|
||||
* do not use QMetaObject:.Connection directly because disconnect will fail.
|
||||
* See also http://stackoverflow.com/questions/13847507/qt5-new-signal-to-lambda-connections-memory-leak
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
_idConnectionCount++;
|
||||
|
||||
auto conn = std::make_shared<QMetaObject::Connection>();
|
||||
*conn = connect( graphicsLayer, &EsriRuntimeQt::GraphicsLayer::graphicIdsComplete,
|
||||
this , [conn,pos,&pickIdList,graphicsLayer,pickSignal,this]( const QList<qint64>& gIdList )
|
||||
{
|
||||
disconnect( *conn );
|
||||
for (auto gId : gIdList)
|
||||
{
|
||||
QString objectName(QLatin1String(" - no graphic - "));
|
||||
|
||||
EsriRuntimeQt::Graphic * graphic = graphicsLayer->graphic(gId);
|
||||
if (graphic)
|
||||
objectName = graphic->objectName();
|
||||
|
||||
qDebug() << LOGFUNCTION
|
||||
<< " gId=" << gId
|
||||
<< " name= " << objectName;
|
||||
|
||||
if (graphic)
|
||||
{
|
||||
bool ok;
|
||||
SituationMap::UniqueMapId id;
|
||||
|
||||
id = graphic->property( SituationMap::UniqueMapIdProperty ).toUInt( &ok );
|
||||
if (ok)
|
||||
{
|
||||
if (!pickIdList.contains(id))
|
||||
{
|
||||
pickIdList += id;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Just emit selectionRequest only once
|
||||
if (_idConnectionCount <= 1)
|
||||
{
|
||||
(this->*pickSignal)( pickIdList, pos );
|
||||
_idConnectionCount = 0;
|
||||
}
|
||||
else _idConnectionCount--;
|
||||
|
||||
} ); // end of lambda methode
|
||||
|
||||
graphicsLayer->graphicIds( pos.x(), pos.y(), _pickTolerance, 100 );
|
||||
|
||||
}
|
||||
} // for layer
|
||||
if (_idConnectionCount == 0)
|
||||
{
|
||||
(this->*pickSignal)( pickIdList, pos );
|
||||
}
|
||||
#endif
|
||||
} // EventMouseNavigator::pickObjects
|
||||
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
Reference in new issue
Block a user