diff --git a/src/3d/qgs3dmapcanvas.cpp b/src/3d/qgs3dmapcanvas.cpp index dc920edafab2..c45b00aef7e5 100644 --- a/src/3d/qgs3dmapcanvas.cpp +++ b/src/3d/qgs3dmapcanvas.cpp @@ -300,6 +300,9 @@ bool Qgs3DMapCanvas::eventFilter( QObject *watched, QEvent *event ) case QEvent::KeyPress: mMapTool->keyPressEvent( static_cast( event ) ); break; + case QEvent::KeyRelease: + mMapTool->keyReleaseEvent( static_cast( event ) ); + break; case QEvent::Wheel: mMapTool->mouseWheelEvent( static_cast( event ) ); break; diff --git a/src/3d/qgs3dmaptool.cpp b/src/3d/qgs3dmaptool.cpp index 1a68a553a4b3..f82a45af3797 100644 --- a/src/3d/qgs3dmaptool.cpp +++ b/src/3d/qgs3dmaptool.cpp @@ -44,6 +44,11 @@ void Qgs3DMapTool::keyPressEvent( QKeyEvent *event ) Q_UNUSED( event ) } +void Qgs3DMapTool::keyReleaseEvent( QKeyEvent *event ) +{ + Q_UNUSED( event ) +} + void Qgs3DMapTool::mouseWheelEvent( QWheelEvent *event ) { Q_UNUSED( event ) diff --git a/src/3d/qgs3dmaptool.h b/src/3d/qgs3dmaptool.h index cc9713caba3a..b15c51ff04b4 100644 --- a/src/3d/qgs3dmaptool.h +++ b/src/3d/qgs3dmaptool.h @@ -50,6 +50,8 @@ class _3D_EXPORT Qgs3DMapTool : public QObject virtual void mouseMoveEvent( QMouseEvent *event ); //! Reimplement to handle key press \a event forwarded by the parent Qgs3DMapCanvas virtual void keyPressEvent( QKeyEvent *event ); + //! Reimplement to handle key release \a event forwarded by the parent Qgs3DMapCanvas + virtual void keyReleaseEvent( QKeyEvent *event ); //! Reimplement to handle mouse wheel \a event forwarded by the parent Qgs3DMapCanvas virtual void mouseWheelEvent( QWheelEvent *event ); diff --git a/src/3d/qgsrubberband3d.cpp b/src/3d/qgsrubberband3d.cpp index 8b28fa23cfba..85d76b799a9a 100644 --- a/src/3d/qgsrubberband3d.cpp +++ b/src/3d/qgsrubberband3d.cpp @@ -140,15 +140,8 @@ void QgsRubberBand3D::setupPolygon( Qt3DCore::QEntity *parentEntity ) mPolygonEntity->addComponent( mPolygonMaterial ); } -QgsRubberBand3D::~QgsRubberBand3D() -{ - if ( mPolygonEntity ) - mPolygonEntity->deleteLater(); - if ( mLineEntity ) - mLineEntity->deleteLater(); - if ( mMarkerEntity ) - mMarkerEntity->deleteLater(); -} +QgsRubberBand3D::~QgsRubberBand3D() = default; + float QgsRubberBand3D::width() const { diff --git a/src/app/3d/qgs3dmapcanvaswidget.cpp b/src/app/3d/qgs3dmapcanvaswidget.cpp index 09dcc5368079..90d5c982d7b4 100644 --- a/src/app/3d/qgs3dmapcanvaswidget.cpp +++ b/src/app/3d/qgs3dmapcanvaswidget.cpp @@ -80,14 +80,16 @@ Qgs3DMapCanvasWidget::Qgs3DMapCanvasWidget( const QString &name, bool isDocked ) // Editing toolbar mEditingToolBar = new QToolBar( this ); mEditingToolBar->setWindowTitle( tr( "Editing Toolbar" ) ); - mEditingToolBar->setVisible( false ); mEditingToolsMenu = new QMenu( this ); mPointCloudEditingToolbar = new QToolBar( this ); mActionToggleEditing = new QAction( QgsApplication::getThemeIcon( QStringLiteral( "/mActionToggleEditing.svg" ) ), tr( "Toggle editing" ), this ); mActionToggleEditing->setCheckable( true ); - connect( mActionToggleEditing, &QAction::triggered, this, [] { QgisApp::instance()->toggleEditing( QgisApp::instance()->activeLayer() ); } ); + connect( mActionToggleEditing, &QAction::triggered, this, [this] { + QgisApp::instance()->toggleEditing( QgisApp::instance()->activeLayer() ); + mCanvas->setMapTool( nullptr ); + } ); mActionUndo = new QAction( QgsApplication::getThemeIcon( QStringLiteral( "/mActionUndo.svg" ) ), tr( "Undo" ), this ); mActionRedo = new QAction( QgsApplication::getThemeIcon( QStringLiteral( "/mActionRedo.svg" ) ), tr( "Redo" ), this ); @@ -120,8 +122,12 @@ Qgs3DMapCanvasWidget::Qgs3DMapCanvasWidget( const QString &name, bool isDocked ) mClassValidator = new ClassValidator( this ); mCboChangeAttributeValueAction = mPointCloudEditingToolbar->addWidget( mCboChangeAttributeValue ); - QAction *actionEditingToolbar = toolBar->addAction( QIcon( QgsApplication::iconPath( "mIconPointCloudLayer.svg" ) ), tr( "Show Editing Toolbar" ), this, [this] { mEditingToolBar->setVisible( !mEditingToolBar->isVisible() ); } ); + QAction *actionEditingToolbar = toolBar->addAction( QIcon( QgsApplication::iconPath( "mIconPointCloudLayer.svg" ) ), tr( "Show Editing Toolbar" ) ); actionEditingToolbar->setCheckable( true ); + actionEditingToolbar->setChecked( + setting.value( QStringLiteral( "/3D/editingToolbar/visibility" ), false, QgsSettings::Gui ).toBool() + ); + connect( actionEditingToolbar, &QAction::toggled, this, &Qgs3DMapCanvasWidget::toggleEditingToolbar ); connect( mCboChangeAttribute, qOverload( &QComboBox::currentIndexChanged ), this, [this]( int ) { onPointCloudChangeAttributeSettingsChanged(); } ); connect( mCboChangeAttributeValue, qOverload( &QComboBox::currentTextChanged ), this, [this]( const QString &text ) { double newValue = 0; @@ -306,7 +312,7 @@ Qgs3DMapCanvasWidget::Qgs3DMapCanvasWidget( const QString &name, bool isDocked ) mMapToolMeasureLine = new Qgs3DMapToolMeasureLine( mCanvas ); - mMapToolChangeAttribute.reset( new Qgs3DMapToolPointCloudChangeAttribute( mCanvas ) ); + mMapToolChangeAttribute = new Qgs3DMapToolPointCloudChangeAttribute( mCanvas ); mLabelPendingJobs = new QLabel( this ); mProgressPendingJobs = new QProgressBar( this ); @@ -392,6 +398,7 @@ Qgs3DMapCanvasWidget::Qgs3DMapCanvasWidget( const QString &name, bool isDocked ) } ); updateLayerRelatedActions( QgisApp::instance()->activeLayer() ); + mEditingToolBar->setVisible( setting.value( QStringLiteral( "/3D/editingToolbar/visibility" ), false, QgsSettings::Gui ).toBool() ); QList toolbarMenuActions; // Set action names so that they can be used in customization @@ -415,11 +422,6 @@ Qgs3DMapCanvasWidget::Qgs3DMapCanvasWidget( const QString &name, bool isDocked ) Qgs3DMapCanvasWidget::~Qgs3DMapCanvasWidget() { delete mDockableWidgetHelper; - // we don't want canvas to reset the map tool as it is managed by unique_ptr - if ( mMapToolChangeAttribute.get() == mCanvas->mapTool() ) - { - mCanvas->setMapTool( nullptr ); - } } void Qgs3DMapCanvasWidget::saveAsImage() @@ -481,10 +483,11 @@ void Qgs3DMapCanvasWidget::changePointCloudAttributeByPaintbrush() if ( !action ) return; - mCanvas->setMapTool( nullptr ); - mMapToolChangeAttribute.reset( new Qgs3DMapToolPointCloudChangeAttributePaintbrush( mCanvas ) ); + mCanvas->requestActivate(); + mMapToolChangeAttribute->deleteLater(); + mMapToolChangeAttribute = new Qgs3DMapToolPointCloudChangeAttributePaintbrush( mCanvas ); onPointCloudChangeAttributeSettingsChanged(); - mCanvas->setMapTool( mMapToolChangeAttribute.get() ); + mCanvas->setMapTool( mMapToolChangeAttribute ); mEditingToolsAction->setIcon( action->icon() ); } @@ -494,10 +497,10 @@ void Qgs3DMapCanvasWidget::changePointCloudAttributeByPolygon() if ( !action ) return; - mCanvas->setMapTool( nullptr ); - mMapToolChangeAttribute.reset( new Qgs3DMapToolPointCloudChangeAttributePolygon( mCanvas, Qgs3DMapToolPointCloudChangeAttributePolygon::Polygon ) ); + mMapToolChangeAttribute->deleteLater(); + mMapToolChangeAttribute = new Qgs3DMapToolPointCloudChangeAttributePolygon( mCanvas, Qgs3DMapToolPointCloudChangeAttributePolygon::Polygon ); onPointCloudChangeAttributeSettingsChanged(); - mCanvas->setMapTool( mMapToolChangeAttribute.get() ); + mCanvas->setMapTool( mMapToolChangeAttribute ); mEditingToolsAction->setIcon( action->icon() ); } @@ -507,10 +510,10 @@ void Qgs3DMapCanvasWidget::changePointCloudAttributeByAboveLine() if ( !action ) return; - mCanvas->setMapTool( nullptr ); - mMapToolChangeAttribute.reset( new Qgs3DMapToolPointCloudChangeAttributePolygon( mCanvas, Qgs3DMapToolPointCloudChangeAttributePolygon::AboveLine ) ); + mMapToolChangeAttribute->deleteLater(); + mMapToolChangeAttribute = new Qgs3DMapToolPointCloudChangeAttributePolygon( mCanvas, Qgs3DMapToolPointCloudChangeAttributePolygon::AboveLine ); onPointCloudChangeAttributeSettingsChanged(); - mCanvas->setMapTool( mMapToolChangeAttribute.get() ); + mCanvas->setMapTool( mMapToolChangeAttribute ); mEditingToolsAction->setIcon( action->icon() ); } @@ -520,10 +523,10 @@ void Qgs3DMapCanvasWidget::changePointCloudAttributeByBelowLine() if ( !action ) return; - mCanvas->setMapTool( nullptr ); - mMapToolChangeAttribute.reset( new Qgs3DMapToolPointCloudChangeAttributePolygon( mCanvas, Qgs3DMapToolPointCloudChangeAttributePolygon::BelowLine ) ); + mMapToolChangeAttribute->deleteLater(); + mMapToolChangeAttribute = new Qgs3DMapToolPointCloudChangeAttributePolygon( mCanvas, Qgs3DMapToolPointCloudChangeAttributePolygon::BelowLine ); onPointCloudChangeAttributeSettingsChanged(); - mCanvas->setMapTool( mMapToolChangeAttribute.get() ); + mCanvas->setMapTool( mMapToolChangeAttribute ); mEditingToolsAction->setIcon( action->icon() ); } @@ -612,6 +615,13 @@ void Qgs3DMapCanvasWidget::toggleNavigationWidget( const bool visibility ) setting.setValue( QStringLiteral( "/3D/navigationWidget/visibility" ), visibility, QgsSettings::Gui ); } +void Qgs3DMapCanvasWidget::toggleEditingToolbar( const bool visibility ) +{ + mEditingToolBar->setVisible( visibility ); + QgsSettings setting; + setting.setValue( QStringLiteral( "/3D/editingToolbar/visibility" ), visibility, QgsSettings::Gui ); +} + void Qgs3DMapCanvasWidget::toggleFpsCounter( const bool visibility ) { mLabelFpsCounter->setVisible( visibility ); diff --git a/src/app/3d/qgs3dmapcanvaswidget.h b/src/app/3d/qgs3dmapcanvaswidget.h index d73c3238350e..37e4d6fe24d6 100644 --- a/src/app/3d/qgs3dmapcanvaswidget.h +++ b/src/app/3d/qgs3dmapcanvaswidget.h @@ -108,6 +108,7 @@ class APP_EXPORT Qgs3DMapCanvasWidget : public QWidget void changePointCloudAttributeByBelowLine(); void exportScene(); void toggleNavigationWidget( bool visibility ); + void toggleEditingToolbar( bool visibility ); void toggleFpsCounter( bool visibility ); void toggleDebugWidget( bool visibility ) const; void toggleDebugWidget() const; @@ -143,7 +144,7 @@ class APP_EXPORT Qgs3DMapCanvasWidget : public QWidget QTimer *mLabelNavSpeedHideTimeout = nullptr; Qgs3DMapToolIdentify *mMapToolIdentify = nullptr; Qgs3DMapToolMeasureLine *mMapToolMeasureLine = nullptr; - QObjectUniquePtr mMapToolChangeAttribute; + Qgs3DMapToolPointCloudChangeAttribute *mMapToolChangeAttribute = nullptr; std::unique_ptr mMapToolExtent; QgsMapTool *mMapToolPrevious = nullptr; QMenu *mExportMenu = nullptr; diff --git a/src/app/3d/qgs3dmaptoolpointcloudchangeattributepaintbrush.cpp b/src/app/3d/qgs3dmaptoolpointcloudchangeattributepaintbrush.cpp index dd02d64671e2..9b1262534f1e 100644 --- a/src/app/3d/qgs3dmaptoolpointcloudchangeattributepaintbrush.cpp +++ b/src/app/3d/qgs3dmaptoolpointcloudchangeattributepaintbrush.cpp @@ -62,6 +62,8 @@ void Qgs3DMapToolPointCloudChangeAttributePaintbrush::activate() void Qgs3DMapToolPointCloudChangeAttributePaintbrush::deactivate() { restart(); + // this makes sure there are no leftover artifacts when switching from paintbrush tool to another + mSelectionRubberBand->setMarkersEnabled( false ); mSelectionRubberBand.reset(); mIsActive = false; mCanvas->cameraController()->setInputHandlersEnabled( true ); @@ -143,9 +145,12 @@ void Qgs3DMapToolPointCloudChangeAttributePaintbrush::mouseWheelEvent( QWheelEve const QgsSettings settings; const bool reverseZoom = settings.value( QStringLiteral( "qgis/reverse_wheel_zoom" ), false ).toBool(); const bool shrink = reverseZoom ? event->angleDelta().y() < 0 : event->angleDelta().y() > 0; + if ( shrink && mSelectionRubberBand->width() <= 5 ) + return; // "Normal" mouse have an angle delta of 120, precision mouses provide data faster, in smaller steps const double zoomFactor = ( shrink ? 0.8 : 1.25 ) / 120.0 * std::fabs( event->angleDelta().y() ); - mSelectionRubberBand->setWidth( mSelectionRubberBand->width() * zoomFactor ); + const float newWidth = mSelectionRubberBand->width() * zoomFactor < 5 ? 5 : mSelectionRubberBand->width() * static_cast( zoomFactor ); + mSelectionRubberBand->setWidth( newWidth ); } void Qgs3DMapToolPointCloudChangeAttributePaintbrush::keyPressEvent( QKeyEvent *event ) @@ -155,10 +160,18 @@ void Qgs3DMapToolPointCloudChangeAttributePaintbrush::keyPressEvent( QKeyEvent * restart(); } - if ( !mIsClicked && event->key() == Qt::Key_Space ) + if ( event->key() == Qt::Key_Space && !event->isAutoRepeat() ) + { + mCanvas->cameraController()->setInputHandlersEnabled( true ); + mIsMoving = true; + } +} + +void Qgs3DMapToolPointCloudChangeAttributePaintbrush::keyReleaseEvent( QKeyEvent *event ) +{ + if ( event->key() == Qt::Key_Space && !event->isAutoRepeat() ) { - const bool newState = !mCanvas->cameraController()->hasInputHandlersEnabled(); - mCanvas->cameraController()->setInputHandlersEnabled( newState ); - mIsMoving = newState; + mCanvas->cameraController()->setInputHandlersEnabled( false ); + mIsMoving = false; } } diff --git a/src/app/3d/qgs3dmaptoolpointcloudchangeattributepaintbrush.h b/src/app/3d/qgs3dmaptoolpointcloudchangeattributepaintbrush.h index d7b6ab479daf..a42fd11d142f 100644 --- a/src/app/3d/qgs3dmaptoolpointcloudchangeattributepaintbrush.h +++ b/src/app/3d/qgs3dmaptoolpointcloudchangeattributepaintbrush.h @@ -42,6 +42,7 @@ class Qgs3DMapToolPointCloudChangeAttributePaintbrush : public Qgs3DMapToolPoint void mouseMoveEvent( QMouseEvent *event ) override; void mouseWheelEvent( QWheelEvent *event ) override; void keyPressEvent( QKeyEvent *event ) override; + void keyReleaseEvent( QKeyEvent *event ) override; private: void run() override; diff --git a/src/app/3d/qgs3dmaptoolpointcloudchangeattributepolygon.cpp b/src/app/3d/qgs3dmaptoolpointcloudchangeattributepolygon.cpp index ef46f567ad80..e062d02f3842 100644 --- a/src/app/3d/qgs3dmaptoolpointcloudchangeattributepolygon.cpp +++ b/src/app/3d/qgs3dmaptoolpointcloudchangeattributepolygon.cpp @@ -126,6 +126,11 @@ void Qgs3DMapToolPointCloudChangeAttributePolygon::mouseReleaseEvent( QMouseEven mPolygonRubberBand->addPoint( screenEdgePoint ); mPolygonRubberBand->addPoint( newPoint ); } + else if ( mScreenPoints.size() == 2 ) + { + run(); + restart(); + } } } else if ( event->button() == Qt::RightButton ) @@ -169,6 +174,8 @@ void Qgs3DMapToolPointCloudChangeAttributePolygon::run() if ( mToolType == AboveLine || mToolType == BelowLine ) { + if ( mScreenPoints.size() != 2 ) + return; const double y = mToolType == AboveLine ? 0 : mCanvas->height(); mScreenPoints.append( { QgsPointXY( mScreenPoints[1].x(), y ), QgsPointXY( mScreenPoints[0].x(), y ) } ); }