diff --git a/python/PyQt6/gui/auto_additions/qgsmodelgraphicsview.py b/python/PyQt6/gui/auto_additions/qgsmodelgraphicsview.py index 1b10abc856a..8bac1c15d58 100644 --- a/python/PyQt6/gui/auto_additions/qgsmodelgraphicsview.py +++ b/python/PyQt6/gui/auto_additions/qgsmodelgraphicsview.py @@ -5,7 +5,7 @@ QgsModelGraphicsView.PasteModeCursor = QgsModelGraphicsView.PasteMode.PasteModeC QgsModelGraphicsView.PasteModeCenter = QgsModelGraphicsView.PasteMode.PasteModeCenter QgsModelGraphicsView.PasteModeInPlace = QgsModelGraphicsView.PasteMode.PasteModeInPlace try: - QgsModelGraphicsView.__attribute_docs__ = {'algorithmDropped': 'Emitted when an algorithm is dropped onto the view.\n', 'inputDropped': 'Emitted when an input parameter is dropped onto the view.\n', 'itemFocused': 'Emitted when an ``item`` is "focused" in the view, i.e. it becomes the\nactive item and should have its properties displayed in any designer\nwindows.\n', 'willBeDeleted': 'Emitted in the destructor when the view is about to be deleted, but is\nstill in a perfectly valid state.\n', 'macroCommandStarted': 'Emitted when a macro command containing a group of interactions is\nstarted in the view.\n', 'macroCommandEnded': 'Emitted when a macro command containing a group of interactions in the\nview has ended.\n', 'commandBegun': 'Emitted when an undo command is started in the view.\n', 'commandEnded': 'Emitted when an undo command in the view has ended.\n', 'deleteSelectedItems': 'Emitted when the selected items should be deleted;\n'} + QgsModelGraphicsView.__attribute_docs__ = {'algorithmDropped': 'Emitted when an algorithm is dropped onto the view.\n', 'inputDropped': 'Emitted when an input parameter is dropped onto the view.\n', 'itemFocused': 'Emitted when an ``item`` is "focused" in the view, i.e. it becomes the\nactive item and should have its properties displayed in any designer\nwindows.\n', 'willBeDeleted': 'Emitted in the destructor when the view is about to be deleted, but is\nstill in a perfectly valid state.\n', 'macroCommandStarted': 'Emitted when a macro command containing a group of interactions is\nstarted in the view.\n', 'macroCommandEnded': 'Emitted when a macro command containing a group of interactions in the\nview has ended.\n', 'commandBegun': 'Emitted when an undo command is started in the view.\n', 'commandEnded': 'Emitted when an undo command in the view has ended.\n', 'commandAborted': 'Emitted when an undo command in the view was aborted.\n', 'deleteSelectedItems': 'Emitted when the selected items should be deleted;\n'} QgsModelGraphicsView.__overridden_methods__ = ['dragEnterEvent', 'dropEvent', 'dragMoveEvent', 'wheelEvent', 'mousePressEvent', 'mouseReleaseEvent', 'mouseMoveEvent', 'mouseDoubleClickEvent', 'keyPressEvent', 'keyReleaseEvent'] QgsModelGraphicsView.__signal_arguments__ = {'algorithmDropped': ['algorithmId: str', 'pos: QPointF'], 'inputDropped': ['inputId: str', 'pos: QPointF'], 'itemFocused': ['item: QgsModelComponentGraphicItem'], 'macroCommandStarted': ['text: str'], 'commandBegun': ['text: str']} QgsModelGraphicsView.__group__ = ['processing', 'models'] diff --git a/python/PyQt6/gui/auto_generated/processing/models/qgsmodeldesignerdialog.sip.in b/python/PyQt6/gui/auto_generated/processing/models/qgsmodeldesignerdialog.sip.in index 10a7f715e68..0fe057a6989 100644 --- a/python/PyQt6/gui/auto_generated/processing/models/qgsmodeldesignerdialog.sip.in +++ b/python/PyQt6/gui/auto_generated/processing/models/qgsmodeldesignerdialog.sip.in @@ -44,6 +44,12 @@ made to the model. %Docstring Ends the current undo command. This should be called after changes are made to the model. +%End + + void abortUndoCommand(); +%Docstring +Aborts pending undo command, tunring last call to beginUndoCommand +obsolete %End QgsProcessingModelAlgorithm *model(); diff --git a/python/PyQt6/gui/auto_generated/processing/models/qgsmodelgraphicsview.sip.in b/python/PyQt6/gui/auto_generated/processing/models/qgsmodelgraphicsview.sip.in index 1a8202ee82b..8b99f910860 100644 --- a/python/PyQt6/gui/auto_generated/processing/models/qgsmodelgraphicsview.sip.in +++ b/python/PyQt6/gui/auto_generated/processing/models/qgsmodelgraphicsview.sip.in @@ -90,6 +90,11 @@ Starts a single undo command Ends a single undo command %End + void abortCommand(); +%Docstring +Aborts pending undo command +%End + enum ClipboardOperation /BaseType=IntEnum/ { @@ -184,6 +189,11 @@ Emitted when an undo command is started in the view. void commandEnded(); %Docstring Emitted when an undo command in the view has ended. +%End + + void commandAborted(); +%Docstring +Emitted when an undo command in the view was aborted. %End void deleteSelectedItems(); diff --git a/python/gui/auto_additions/qgsmodelgraphicsview.py b/python/gui/auto_additions/qgsmodelgraphicsview.py index 4980ed820ce..670404ed85a 100644 --- a/python/gui/auto_additions/qgsmodelgraphicsview.py +++ b/python/gui/auto_additions/qgsmodelgraphicsview.py @@ -1,6 +1,6 @@ # The following has been generated automatically from src/gui/processing/models/qgsmodelgraphicsview.h try: - QgsModelGraphicsView.__attribute_docs__ = {'algorithmDropped': 'Emitted when an algorithm is dropped onto the view.\n', 'inputDropped': 'Emitted when an input parameter is dropped onto the view.\n', 'itemFocused': 'Emitted when an ``item`` is "focused" in the view, i.e. it becomes the\nactive item and should have its properties displayed in any designer\nwindows.\n', 'willBeDeleted': 'Emitted in the destructor when the view is about to be deleted, but is\nstill in a perfectly valid state.\n', 'macroCommandStarted': 'Emitted when a macro command containing a group of interactions is\nstarted in the view.\n', 'macroCommandEnded': 'Emitted when a macro command containing a group of interactions in the\nview has ended.\n', 'commandBegun': 'Emitted when an undo command is started in the view.\n', 'commandEnded': 'Emitted when an undo command in the view has ended.\n', 'deleteSelectedItems': 'Emitted when the selected items should be deleted;\n'} + QgsModelGraphicsView.__attribute_docs__ = {'algorithmDropped': 'Emitted when an algorithm is dropped onto the view.\n', 'inputDropped': 'Emitted when an input parameter is dropped onto the view.\n', 'itemFocused': 'Emitted when an ``item`` is "focused" in the view, i.e. it becomes the\nactive item and should have its properties displayed in any designer\nwindows.\n', 'willBeDeleted': 'Emitted in the destructor when the view is about to be deleted, but is\nstill in a perfectly valid state.\n', 'macroCommandStarted': 'Emitted when a macro command containing a group of interactions is\nstarted in the view.\n', 'macroCommandEnded': 'Emitted when a macro command containing a group of interactions in the\nview has ended.\n', 'commandBegun': 'Emitted when an undo command is started in the view.\n', 'commandEnded': 'Emitted when an undo command in the view has ended.\n', 'commandAborted': 'Emitted when an undo command in the view was aborted.\n', 'deleteSelectedItems': 'Emitted when the selected items should be deleted;\n'} QgsModelGraphicsView.__overridden_methods__ = ['dragEnterEvent', 'dropEvent', 'dragMoveEvent', 'wheelEvent', 'mousePressEvent', 'mouseReleaseEvent', 'mouseMoveEvent', 'mouseDoubleClickEvent', 'keyPressEvent', 'keyReleaseEvent'] QgsModelGraphicsView.__signal_arguments__ = {'algorithmDropped': ['algorithmId: str', 'pos: QPointF'], 'inputDropped': ['inputId: str', 'pos: QPointF'], 'itemFocused': ['item: QgsModelComponentGraphicItem'], 'macroCommandStarted': ['text: str'], 'commandBegun': ['text: str']} QgsModelGraphicsView.__group__ = ['processing', 'models'] diff --git a/python/gui/auto_generated/processing/models/qgsmodeldesignerdialog.sip.in b/python/gui/auto_generated/processing/models/qgsmodeldesignerdialog.sip.in index 10a7f715e68..0fe057a6989 100644 --- a/python/gui/auto_generated/processing/models/qgsmodeldesignerdialog.sip.in +++ b/python/gui/auto_generated/processing/models/qgsmodeldesignerdialog.sip.in @@ -44,6 +44,12 @@ made to the model. %Docstring Ends the current undo command. This should be called after changes are made to the model. +%End + + void abortUndoCommand(); +%Docstring +Aborts pending undo command, tunring last call to beginUndoCommand +obsolete %End QgsProcessingModelAlgorithm *model(); diff --git a/python/gui/auto_generated/processing/models/qgsmodelgraphicsview.sip.in b/python/gui/auto_generated/processing/models/qgsmodelgraphicsview.sip.in index fb899a9ff89..92b42499af6 100644 --- a/python/gui/auto_generated/processing/models/qgsmodelgraphicsview.sip.in +++ b/python/gui/auto_generated/processing/models/qgsmodelgraphicsview.sip.in @@ -90,6 +90,11 @@ Starts a single undo command Ends a single undo command %End + void abortCommand(); +%Docstring +Aborts pending undo command +%End + enum ClipboardOperation { @@ -184,6 +189,11 @@ Emitted when an undo command is started in the view. void commandEnded(); %Docstring Emitted when an undo command in the view has ended. +%End + + void commandAborted(); +%Docstring +Emitted when an undo command in the view was aborted. %End void deleteSelectedItems(); diff --git a/src/gui/processing/models/qgsmodeldesignerdialog.cpp b/src/gui/processing/models/qgsmodeldesignerdialog.cpp index 995401d525d..5bcb6aa86bf 100644 --- a/src/gui/processing/models/qgsmodeldesignerdialog.cpp +++ b/src/gui/processing/models/qgsmodeldesignerdialog.cpp @@ -345,6 +345,9 @@ QgsModelDesignerDialog::QgsModelDesignerDialog( QWidget *parent, Qt::WindowFlags connect( mView, &QgsModelGraphicsView::commandEnded, this, [this] { endUndoCommand(); } ); + connect( mView, &QgsModelGraphicsView::commandAborted, this, [this] { + abortUndoCommand(); + } ); connect( mView, &QgsModelGraphicsView::deleteSelectedItems, this, [this] { deleteSelected(); } ); @@ -429,6 +432,12 @@ void QgsModelDesignerDialog::endUndoCommand() setDirty( true ); } +void QgsModelDesignerDialog::abortUndoCommand() +{ + if ( mActiveCommand ) + mActiveCommand->setObsolete( true ); +} + QgsProcessingModelAlgorithm *QgsModelDesignerDialog::model() { return mModel.get(); diff --git a/src/gui/processing/models/qgsmodeldesignerdialog.h b/src/gui/processing/models/qgsmodeldesignerdialog.h index 275f1c28022..d4ad0291ffd 100644 --- a/src/gui/processing/models/qgsmodeldesignerdialog.h +++ b/src/gui/processing/models/qgsmodeldesignerdialog.h @@ -72,6 +72,11 @@ class GUI_EXPORT QgsModelDesignerDialog : public QMainWindow, public Ui::QgsMode */ void endUndoCommand(); + /** + * Aborts pending undo command, tunring last call to beginUndoCommand obsolete + */ + void abortUndoCommand(); + /** * Returns the model shown in the dialog. */ diff --git a/src/gui/processing/models/qgsmodelgraphicsview.cpp b/src/gui/processing/models/qgsmodelgraphicsview.cpp index 0f5b65810f4..f91bae2ecf2 100644 --- a/src/gui/processing/models/qgsmodelgraphicsview.cpp +++ b/src/gui/processing/models/qgsmodelgraphicsview.cpp @@ -473,6 +473,11 @@ void QgsModelGraphicsView::endCommand() emit commandEnded(); } +void QgsModelGraphicsView::abortCommand() +{ + emit commandAborted(); +} + void QgsModelGraphicsView::snapSelected() { QgsModelGraphicsScene *s = modelScene(); diff --git a/src/gui/processing/models/qgsmodelgraphicsview.h b/src/gui/processing/models/qgsmodelgraphicsview.h index 212823c18a5..d604ebda907 100644 --- a/src/gui/processing/models/qgsmodelgraphicsview.h +++ b/src/gui/processing/models/qgsmodelgraphicsview.h @@ -115,10 +115,15 @@ class GUI_EXPORT QgsModelGraphicsView : public QGraphicsView void beginCommand( const QString &text ); /** - * Ends a single undo command + * Ends a single undo command */ void endCommand(); + /** + * Aborts pending undo command + */ + void abortCommand(); + //! Clipboard operations enum ClipboardOperation @@ -212,6 +217,11 @@ class GUI_EXPORT QgsModelGraphicsView : public QGraphicsView */ void commandEnded(); + /** + * Emitted when an undo command in the view was aborted. + */ + void commandAborted(); + /** * Emitted when the selected items should be deleted; */ diff --git a/src/gui/processing/models/qgsmodelviewtoollink.cpp b/src/gui/processing/models/qgsmodelviewtoollink.cpp index f44e6b1a77e..d6abb9bc2fd 100644 --- a/src/gui/processing/models/qgsmodelviewtoollink.cpp +++ b/src/gui/processing/models/qgsmodelviewtoollink.cpp @@ -23,7 +23,9 @@ #include "qgsmodelviewmouseevent.h" #include "qgsmodelviewtoolselect.h" #include "qgsmodelgraphicsview.h" -#include +#include "qgsmodelviewrubberband.h" +#include "qgsmodelgraphicitem.h" + QgsModelViewToolLink::QgsModelViewToolLink( QgsModelGraphicsView *view ) : QgsModelViewTool( view, tr( "Link Tool" ) ) @@ -40,21 +42,20 @@ void QgsModelViewToolLink::modelMoveEvent( QgsModelViewMouseEvent *event ) mBezierRubberBand->update( event->modelPoint(), Qt::KeyboardModifiers() ); // we need to manually pass this event down to items we want it to go to -- QGraphicsScene doesn't propagate - QList items = scene()->items( event->modelPoint() ); + const QList items = scene()->items( event->modelPoint() ); QgsModelDesignerSocketGraphicItem *socket = nullptr; for ( QGraphicsItem *item : items ) { - if ( ( socket = dynamic_cast( item ) ) - && ( mFromSocket != socket && mFromSocket->edge() != socket->edge() ) ) - { - // snap - socket->modelHoverEnterEvent( event ); - QPointF rubberEndPos = socket->mapToScene( socket->position() ); - mBezierRubberBand->update( rubberEndPos, Qt::KeyboardModifiers() ); + socket = dynamic_cast( item ); + if ( !socket || mFromSocket == socket || mFromSocket->edge() == socket->edge() || mFromSocket->component() == socket->component() ) + continue; - break; - } + // snap + socket->modelHoverEnterEvent( event ); + const QPointF rubberEndPos = socket->mapToScene( socket->position() ); + mBezierRubberBand->update( rubberEndPos, Qt::KeyboardModifiers() ); + break; } if ( mLastHoveredSocket && socket != mLastHoveredSocket ) @@ -85,7 +86,7 @@ void QgsModelViewToolLink::modelReleaseEvent( QgsModelViewMouseEvent *event ) view()->setTool( mPreviousViewTool ); // we need to manually pass this event down to items we want it to go to -- QGraphicsScene doesn't propagate - QList items = scene()->items( event->modelPoint() ); + const QList items = scene()->items( event->modelPoint() ); mToSocket = nullptr; @@ -93,6 +94,10 @@ void QgsModelViewToolLink::modelReleaseEvent( QgsModelViewMouseEvent *event ) { if ( QgsModelDesignerSocketGraphicItem *socket = dynamic_cast( item ) ) { + // Skip if sockets are both input or both output or both from the same algorithm + if ( mFromSocket->edge() == socket->edge() || mFromSocket->component() == socket->component() ) + continue; + mToSocket = socket; break; } @@ -101,28 +106,19 @@ void QgsModelViewToolLink::modelReleaseEvent( QgsModelViewMouseEvent *event ) // Do nothing if cursor didn't land on another socket if ( !mToSocket ) { + // but it might have been an unlink, so we properly end the command + view()->endCommand(); return; } - - // Do nothing if from socket and to socket are both input or both output - if ( mFromSocket->edge() == mToSocket->edge() ) - { - return; - } - - view()->beginCommand( tr( "Edit link" ) ); - - QList sources; - - QgsProcessingModelComponent *componentFrom = nullptr; - QgsProcessingModelChildAlgorithm *childTo = nullptr; + // and we abort any pending unlink command to not litter the undo buffer + view()->abortCommand(); /** * Reorder input and output socket * whether the user dragged : * - From an input socket to an output socket * - From an output socket to an input socket - * + * * In the code, we always come back to the first case */ if ( !mToSocket->isInput() ) @@ -130,26 +126,32 @@ void QgsModelViewToolLink::modelReleaseEvent( QgsModelViewMouseEvent *event ) std::swap( mFromSocket, mToSocket ); } - componentFrom = mFromSocket->component(); - childTo = dynamic_cast( mToSocket->component() ); - - - const QgsProcessingParameterDefinition *toParam = childTo->algorithm()->parameterDefinitions().at( mToSocket->index() ); - - QgsProcessingModelChildParameterSource source; - if ( QgsProcessingModelChildAlgorithm *childFrom = dynamic_cast( componentFrom ) ) + QgsProcessingModelComponent *outputComponent = mFromSocket->component(); + QgsProcessingModelChildAlgorithm *inputChildAlgorithm = dynamic_cast( mToSocket->component() ); + if ( !inputChildAlgorithm ) { - QString outputName = childFrom->algorithm()->outputDefinitions().at( mFromSocket->index() )->name(); - source = QgsProcessingModelChildParameterSource::fromChildOutput( childFrom->childId(), outputName ); - } - else if ( QgsProcessingModelParameter *paramFrom = dynamic_cast( componentFrom ) ) - { - source = QgsProcessingModelChildParameterSource::fromModelParameter( paramFrom->parameterName() ); + // Should not happen, but checking is cheap! + QgsDebugError( QStringLiteral( "Input is not a QgsProcessingModelChildAlgorithm" ) ); + return; } - QList compatibleParamSources = scene()->model()->availableSourcesForChild( childTo->childId(), toParam ); + QgsProcessingModelChildParameterSource newInputParamSource; + QString outParamDescription; + if ( const QgsProcessingModelChildAlgorithm *outputChildAlgorithm = dynamic_cast( outputComponent ) ) + { + const QString outParamName = outputChildAlgorithm->algorithm()->outputDefinitions().at( mFromSocket->index() )->name(); + newInputParamSource = QgsProcessingModelChildParameterSource::fromChildOutput( outputChildAlgorithm->childId(), outParamName ); + outParamDescription = outputChildAlgorithm->algorithm()->outputDefinitions().at( mFromSocket->index() )->description(); + } + else if ( const QgsProcessingModelParameter *paramFrom = dynamic_cast( outputComponent ) ) + { + newInputParamSource = QgsProcessingModelChildParameterSource::fromModelParameter( paramFrom->parameterName() ); + outParamDescription = paramFrom->description(); + } - if ( !compatibleParamSources.contains( source ) ) + const QgsProcessingParameterDefinition *inputParam = inputChildAlgorithm->algorithm()->parameterDefinitions().at( mToSocket->index() ); + const QList compatibleInputParamSources = scene()->model()->availableSourcesForChild( inputChildAlgorithm->childId(), inputParam ); + if ( !compatibleInputParamSources.contains( newInputParamSource ) ) { //Type are incomatible const QString title = tr( "Sockets cannot be connected" ); @@ -158,12 +160,12 @@ void QgsModelViewToolLink::modelReleaseEvent( QgsModelViewMouseEvent *event ) return; } - sources << source; - childTo->addParameterSources( toParam->name(), sources ); + view()->beginCommand( tr( "Link %1: %2 to %3: %4" ).arg( outputComponent->description(), outParamDescription, inputChildAlgorithm->description(), inputParam->description() ) ); + inputChildAlgorithm->addParameterSources( inputParam->name(), { newInputParamSource } ); //We need to pass the update child algorithm to the model - scene()->model()->setChildAlgorithm( *childTo ); + scene()->model()->setChildAlgorithm( *inputChildAlgorithm ); view()->endCommand(); // Redraw @@ -184,7 +186,7 @@ void QgsModelViewToolLink::activate() mPreviousViewTool = tool; } - QPointF rubberStartPos = mFromSocket->mapToScene( mFromSocket->position() ); + const QPointF rubberStartPos = mFromSocket->mapToScene( mFromSocket->position() ); mBezierRubberBand->start( rubberStartPos, Qt::KeyboardModifiers() ); QgsModelViewTool::activate(); @@ -200,28 +202,37 @@ void QgsModelViewToolLink::setFromSocket( QgsModelDesignerSocketGraphicItem *soc { mFromSocket = socket; + // If it's an input socket and it's already connected, we want 'From' to be the output at the other end of the connection if ( mFromSocket->isInput() ) { QgsProcessingModelChildAlgorithm *childFrom = dynamic_cast( mFromSocket->component() ); const QgsProcessingParameterDefinition *param = childFrom->algorithm()->parameterDefinitions().at( mFromSocket->index() ); + const QList currentSources = childFrom->parameterSources().value( param->name() ); - auto currentSources = childFrom->parameterSources().value( param->name() ); - - QgsProcessingModelChildParameterSource oldSource; - for ( const QgsProcessingModelChildParameterSource &source : std::as_const( currentSources ) ) + for ( const QgsProcessingModelChildParameterSource &source : currentSources ) { + // Was not connected, nothing to do + if ( source.outputChildId().isEmpty() ) + break; + switch ( source.source() ) { case Qgis::ProcessingModelChildParameterSource::ModelParameter: case Qgis::ProcessingModelChildParameterSource::ChildOutput: { - oldSource = source; - view()->beginCommand( tr( "Edit link" ) ); + view()->beginCommand( tr( "Unlink %1: %2", "Unlink Algorithm: Input" ).arg( childFrom->description(), param->description() ) ); - //reset to default value + // reset to default value. Layers/feature sources default to an empty model parameter QList newSources; - newSources << QgsProcessingModelChildParameterSource::fromStaticValue( param->defaultValue() ); - + if ( param->type() == QgsProcessingParameterFeatureSource::typeName() || param->type() == QgsProcessingParameterMapLayer::typeName() || param->type() == QgsProcessingParameterMeshLayer::typeName() || param->type() == QgsProcessingParameterPointCloudLayer::typeName() || param->type() == QgsProcessingParameterRasterLayer::typeName() || param->type() == QgsProcessingParameterVectorLayer::typeName() ) + { + newSources << QgsProcessingModelChildParameterSource::fromModelParameter( QString() ); + } + else + { + // Other parameters default to static value + newSources << QgsProcessingModelChildParameterSource::fromStaticValue( param->defaultValue() ); + } childFrom->addParameterSources( param->name(), newSources ); //We need to pass the update child algorithm to the model @@ -232,9 +243,9 @@ void QgsModelViewToolLink::setFromSocket( QgsModelDesignerSocketGraphicItem *soc //Get socket from initial source alg / source parameter QgsModelComponentGraphicItem *item = nullptr; int socketIndex = -1; - if ( oldSource.source() == Qgis::ProcessingModelChildParameterSource::ChildOutput ) + if ( source.source() == Qgis::ProcessingModelChildParameterSource::ChildOutput ) { - item = scene()->childAlgorithmItem( oldSource.outputChildId() ); + item = scene()->childAlgorithmItem( source.outputChildId() ); auto algSource = dynamic_cast( item->component() ); if ( !algSource ) { @@ -243,7 +254,7 @@ void QgsModelViewToolLink::setFromSocket( QgsModelDesignerSocketGraphicItem *soc } socketIndex = QgsProcessingUtils::outputDefinitionIndex( algSource->algorithm(), source.outputName() ); } - else if ( oldSource.source() == Qgis::ProcessingModelChildParameterSource::ModelParameter ) + else if ( source.source() == Qgis::ProcessingModelChildParameterSource::ModelParameter ) { item = scene()->parameterItem( source.parameterName() ); socketIndex = 0; diff --git a/src/gui/processing/models/qgsmodelviewtoollink.h b/src/gui/processing/models/qgsmodelviewtoollink.h index ec2ff508e42..7033f0f5dc0 100644 --- a/src/gui/processing/models/qgsmodelviewtoollink.h +++ b/src/gui/processing/models/qgsmodelviewtoollink.h @@ -19,12 +19,14 @@ #include "qgis_sip.h" #include "qgis_gui.h" #include "qgsmodelviewtool.h" -#include "qgsmodelviewrubberband.h" -#include "qgsmodelgraphicitem.h" #include #define SIP_NO_FILE +class QgsModelViewBezierRubberBand; +class QgsModelDesignerSocketGraphicItem; +class QgsProcessingModelComponent; + /** * \ingroup gui * \brief Model designer view tool for linking socket together diff --git a/src/gui/processing/models/qgsmodelviewtoolselect.cpp b/src/gui/processing/models/qgsmodelviewtoolselect.cpp index 020fe62a505..24cae526bbc 100644 --- a/src/gui/processing/models/qgsmodelviewtoolselect.cpp +++ b/src/gui/processing/models/qgsmodelviewtoolselect.cpp @@ -124,7 +124,7 @@ void QgsModelViewToolSelect::modelPressEvent( QgsModelViewMouseEvent *event ) { // we need to manually pass this event down to items we want it to go to -- QGraphicsScene doesn't propagate events // to multiple items - QList items = scene()->items( event->modelPoint() ); + const QList items = scene()->items( event->modelPoint() ); for ( QGraphicsItem *item : items ) { if ( QgsModelDesignerSocketGraphicItem *socket = dynamic_cast( item ) )