From 47667dbd552d203a02a6284efaf3a4496545b84c Mon Sep 17 00:00:00 2001 From: Marco Hugentobler Date: Sat, 18 Feb 2012 14:14:45 +0100 Subject: [PATCH] Add moving spin box to enter numeric value for curve offset --- src/app/CMakeLists.txt | 1 + src/app/qgsmaptooloffsetcurve.cpp | 111 ++++++++++++++++++++++++------ src/app/qgsmaptooloffsetcurve.h | 14 +++- src/gui/qgsmapcanvas.cpp | 2 +- 4 files changed, 104 insertions(+), 24 deletions(-) diff --git a/src/app/CMakeLists.txt b/src/app/CMakeLists.txt index 58a86933454..bd4e0428c49 100644 --- a/src/app/CMakeLists.txt +++ b/src/app/CMakeLists.txt @@ -202,6 +202,7 @@ SET (QGIS_APP_MOC_HDRS qgsmaptoolmovefeature.h qgsmaptoolmovelabel.h qgsmaptoolmovevertex.h + qgsmaptooloffsetcurve.h qgsmaptoolreshape.h qgsmaptoolrotatelabel.h qgsmaptoolrotatepointsymbols.h diff --git a/src/app/qgsmaptooloffsetcurve.cpp b/src/app/qgsmaptooloffsetcurve.cpp index f824fda10d9..35d71239c53 100644 --- a/src/app/qgsmaptooloffsetcurve.cpp +++ b/src/app/qgsmaptooloffsetcurve.cpp @@ -18,15 +18,19 @@ #include "qgsmaplayerregistry.h" #include "qgsrubberband.h" #include "qgsvectorlayer.h" +#include +#include #include -QgsMapToolOffsetCurve::QgsMapToolOffsetCurve( QgsMapCanvas* canvas ): QgsMapToolEdit( canvas ), mRubberBand( 0 ), mOriginalGeometry( 0 ), mGeometryModified( false ), mDistanceItem( 0 ) +QgsMapToolOffsetCurve::QgsMapToolOffsetCurve( QgsMapCanvas* canvas ): QgsMapToolEdit( canvas ), mRubberBand( 0 ), + mOriginalGeometry( 0 ), mGeometryModified( false ), mDistanceItem( 0 ), mDistanceSpinBox( 0 ) { } QgsMapToolOffsetCurve::~QgsMapToolOffsetCurve() { deleteRubberBandAndGeometry(); + deleteDistanceItem(); } void QgsMapToolOffsetCurve::canvasPressEvent( QMouseEvent * e ) @@ -57,8 +61,12 @@ void QgsMapToolOffsetCurve::canvasPressEvent( QMouseEvent * e ) { mOriginalGeometry = createOriginGeometry( vl, snapResult, fet ); mRubberBand = createRubberBand(); - mRubberBand->setToGeometry( mOriginalGeometry, layer ); + if ( mRubberBand ) + { + mRubberBand->setToGeometry( mOriginalGeometry, layer ); + } mModifiedFeature = fet.id(); + createDistanceItem(); } } } @@ -66,6 +74,7 @@ void QgsMapToolOffsetCurve::canvasPressEvent( QMouseEvent * e ) void QgsMapToolOffsetCurve::canvasReleaseEvent( QMouseEvent * e ) { + Q_UNUSED( e ); QgsVectorLayer* vlayer = currentVectorLayer(); if ( !vlayer || !mGeometryModified ) { @@ -96,11 +105,28 @@ void QgsMapToolOffsetCurve::canvasReleaseEvent( QMouseEvent * e ) vlayer->destroyEditCommand(); } - delete mRubberBand; - mRubberBand = 0; + deleteRubberBandAndGeometry(); + deleteDistanceItem(); mCanvas->refresh(); } +void QgsMapToolOffsetCurve::placeOffsetCurveToValue() +{ + if ( mOriginalGeometry && mRubberBand && mRubberBand->numberOfVertices() > 0 ) + { + //is rubber band left or right of original geometry + double leftOf = 0; + const QgsPoint* firstPoint = mRubberBand->getPoint( 0 ); + if ( firstPoint ) + { + QgsPoint minDistPoint; + int beforeVertex; + mOriginalGeometry->closestSegmentWithContext( *firstPoint, minDistPoint, beforeVertex, &leftOf ); + } + setOffsetForRubberBand( mDistanceSpinBox->value(), leftOf < 0 ); + } +} + void QgsMapToolOffsetCurve::canvasMoveEvent( QMouseEvent * e ) { if ( !mOriginalGeometry || !mRubberBand ) @@ -114,6 +140,12 @@ void QgsMapToolOffsetCurve::canvasMoveEvent( QMouseEvent * e ) return; } + if ( mDistanceItem ) + { + mDistanceItem->show(); + mDistanceItem->setPos( e->posF() + QPointF( 10, 10 ) ); + } + mGeometryModified = true; //get offset from current position rectangular to feature @@ -122,19 +154,13 @@ void QgsMapToolOffsetCurve::canvasMoveEvent( QMouseEvent * e ) int beforeVertex; double leftOf; double offset = sqrt( mOriginalGeometry->closestSegmentWithContext( layerCoords, minDistPoint, beforeVertex, &leftOf ) ); - //qWarning( QString::number( offset ).toLocal8Bit().data() ); //create offset geometry using geos - QgsGeometry geomCopy( *mOriginalGeometry ); - GEOSGeometry* geosGeom = geomCopy.asGeos(); - if ( geosGeom ) + setOffsetForRubberBand( offset, leftOf < 0 ); + + if ( mDistanceSpinBox ) { - GEOSGeometry* offsetGeom = GEOSSingleSidedBuffer( geosGeom, offset, 8, 1, 1, ( leftOf < 0 ) ? 1 : 0 ); - if ( offsetGeom ) - { - mModifiedGeometry.fromGeos( offsetGeom ); - mRubberBand->setToGeometry( &mModifiedGeometry, layer ); - } + mDistanceSpinBox->setValue( offset ); } } @@ -182,19 +208,35 @@ QgsGeometry* QgsMapToolOffsetCurve::createOriginGeometry( QgsVectorLayer* vl, co } } -QGraphicsProxyWidget* QgsMapToolOffsetCurve::createDistanceItem() +void QgsMapToolOffsetCurve::createDistanceItem() { if ( !mCanvas ) { - return 0; + return; } - QGraphicsProxyWidget* pw = new QGraphicsProxyWidget(); - //Embed double spin box - QDoubleSpinBox* sb = new QDoubleSpinBox(); - pw->setWidget( sb ); + deleteDistanceItem(); - return pw; + mDistanceItem = new QGraphicsProxyWidget(); + mDistanceSpinBox = new QDoubleSpinBox(); + mDistanceSpinBox->setMaximum( 99999999 ); + mDistanceSpinBox->setDecimals( 2 ); + mDistanceItem->setWidget( mDistanceSpinBox ); + mCanvas->scene()->addItem( mDistanceItem ); + mDistanceSpinBox->grabKeyboard(); + mDistanceItem->hide(); + QObject::connect( mDistanceSpinBox, SIGNAL( editingFinished() ), this, SLOT( placeOffsetCurveToValue() ) ); +} + +void QgsMapToolOffsetCurve::deleteDistanceItem() +{ + if ( mDistanceSpinBox ) + { + mDistanceSpinBox->releaseKeyboard(); + } + delete mDistanceItem; + mDistanceItem = 0; + mDistanceSpinBox = 0; } void QgsMapToolOffsetCurve::deleteRubberBandAndGeometry() @@ -204,3 +246,30 @@ void QgsMapToolOffsetCurve::deleteRubberBandAndGeometry() delete mOriginalGeometry; mOriginalGeometry = 0; } + +void QgsMapToolOffsetCurve::setOffsetForRubberBand( double offset, bool leftSide ) +{ + if ( !mRubberBand || !mOriginalGeometry ) + { + return; + } + + QgsVectorLayer* sourceLayer = dynamic_cast( QgsMapLayerRegistry::instance()->mapLayer( mSourceLayerId ) ); + if ( !sourceLayer ) + { + return; + } + + + QgsGeometry geomCopy( *mOriginalGeometry ); + GEOSGeometry* geosGeom = geomCopy.asGeos(); + if ( geosGeom ) + { + GEOSGeometry* offsetGeom = GEOSSingleSidedBuffer( geosGeom, offset, 8, 1, 1, leftSide ? 1 : 0 ); + if ( offsetGeom ) + { + mModifiedGeometry.fromGeos( offsetGeom ); + mRubberBand->setToGeometry( &mModifiedGeometry, sourceLayer ); + } + } +} diff --git a/src/app/qgsmaptooloffsetcurve.h b/src/app/qgsmaptooloffsetcurve.h index ba1e7bf5908..76003815501 100644 --- a/src/app/qgsmaptooloffsetcurve.h +++ b/src/app/qgsmaptooloffsetcurve.h @@ -20,10 +20,12 @@ #include "qgsgeometry.h" #include "qgssnapper.h" +class QDoubleSpinBox; class QGraphicsProxyWidget; class QgsMapToolOffsetCurve: public QgsMapToolEdit { + Q_OBJECT public: QgsMapToolOffsetCurve( QgsMapCanvas* canvas ); ~QgsMapToolOffsetCurve(); @@ -32,6 +34,10 @@ class QgsMapToolOffsetCurve: public QgsMapToolEdit void canvasReleaseEvent( QMouseEvent * e ); void canvasMoveEvent( QMouseEvent * e ); + private slots: + /**Places curve offset to value entered in the spin box*/ + void placeOffsetCurveToValue(); + private: /**Rubberband that shows the position of the offset curve*/ @@ -46,13 +52,17 @@ class QgsMapToolOffsetCurve: public QgsMapToolEdit QString mSourceLayerId; /**Internal flag to distinguish move from click*/ bool mGeometryModified; - /**Shows current distance value and allows numerical editing*/ + /**Embedded item widget for distance spinbox*/ QGraphicsProxyWidget* mDistanceItem; + /**Shows current distance value and allows numerical editing*/ + QDoubleSpinBox* mDistanceSpinBox; void deleteRubberBandAndGeometry(); QgsGeometry* createOriginGeometry( QgsVectorLayer* vl, const QgsSnappingResult& sr, QgsFeature& snappedFeature ); - QGraphicsProxyWidget* createDistanceItem(); + void createDistanceItem(); + void deleteDistanceItem(); + void setOffsetForRubberBand( double offset, bool leftSide ); }; #endif // QGSMAPTOOLOFFSETCURVE_H diff --git a/src/gui/qgsmapcanvas.cpp b/src/gui/qgsmapcanvas.cpp index 6e367689627..ab9c7c83cf6 100644 --- a/src/gui/qgsmapcanvas.cpp +++ b/src/gui/qgsmapcanvas.cpp @@ -88,7 +88,7 @@ QgsMapCanvas::QgsMapCanvas( QWidget * parent, const char *name ) if ( viewport() ) { #ifndef ANDROID - viewport()->setAttribute( Qt::WA_PaintOnScreen, true ); + //viewport()->setAttribute( Qt::WA_PaintOnScreen, true ); #endif //ANDROID }