mirror of
https://github.com/qgis/QGIS.git
synced 2025-07-03 00:03:10 -04:00
Compare commits
28 Commits
958b4c36e3
...
31787bb2e7
Author | SHA1 | Date | |
---|---|---|---|
|
31787bb2e7 | ||
|
b927df884f | ||
|
fe299930cd | ||
|
8c7edbeec2 | ||
|
ce2c8ac21f | ||
|
faf4afcba7 | ||
|
4bad76d876 | ||
|
1f6c1277dd | ||
|
ae463d8b75 | ||
|
fb0d20942d | ||
|
1680a6cd2e | ||
|
6fd32d92fd | ||
|
e5e3b9a44a | ||
|
88dd13a0ca | ||
|
e67201a2aa | ||
|
f2c61f819f | ||
|
55f2cbe674 | ||
|
9853fa2da1 | ||
|
d678daf1d5 | ||
|
13f020ef86 | ||
|
32b0327dbf | ||
|
7ccd8f0435 | ||
|
021467a178 | ||
|
88f59e4c37 | ||
|
a06f6ee8b1 | ||
|
ee23cf7c44 | ||
|
86f372948e | ||
|
ccdb476318 |
@ -11505,6 +11505,10 @@ Qgis.MouseHandlesAction.ResizeLeftUp.__doc__ = "Resize left up (Top left handle)
|
||||
Qgis.MouseHandlesAction.ResizeRightUp.__doc__ = "Resize right up (Top right handle)"
|
||||
Qgis.MouseHandlesAction.ResizeLeftDown.__doc__ = "Resize left down (Bottom left handle)"
|
||||
Qgis.MouseHandlesAction.ResizeRightDown.__doc__ = "Resize right down (Bottom right handle)"
|
||||
Qgis.MouseHandlesAction.RotateTopLeft.__doc__ = "Rotate from top left handle. \n.. versionadded:: 4.0"
|
||||
Qgis.MouseHandlesAction.RotateTopRight.__doc__ = "Rotate from top right handle. \n.. versionadded:: 4.0"
|
||||
Qgis.MouseHandlesAction.RotateBottomLeft.__doc__ = "Rotate from bottom left handle. \n.. versionadded:: 4.0"
|
||||
Qgis.MouseHandlesAction.RotateBottomRight.__doc__ = "Rotate right bottom right handle. \n.. versionadded:: 4.0"
|
||||
Qgis.MouseHandlesAction.SelectItem.__doc__ = "Select item"
|
||||
Qgis.MouseHandlesAction.NoAction.__doc__ = "No action"
|
||||
Qgis.MouseHandlesAction.__doc__ = """Action to be performed by the mouse handles
|
||||
@ -11520,6 +11524,22 @@ Qgis.MouseHandlesAction.__doc__ = """Action to be performed by the mouse handles
|
||||
* ``ResizeRightUp``: Resize right up (Top right handle)
|
||||
* ``ResizeLeftDown``: Resize left down (Bottom left handle)
|
||||
* ``ResizeRightDown``: Resize right down (Bottom right handle)
|
||||
* ``RotateTopLeft``: Rotate from top left handle.
|
||||
|
||||
.. versionadded:: 4.0
|
||||
|
||||
* ``RotateTopRight``: Rotate from top right handle.
|
||||
|
||||
.. versionadded:: 4.0
|
||||
|
||||
* ``RotateBottomLeft``: Rotate from bottom left handle.
|
||||
|
||||
.. versionadded:: 4.0
|
||||
|
||||
* ``RotateBottomRight``: Rotate right bottom right handle.
|
||||
|
||||
.. versionadded:: 4.0
|
||||
|
||||
* ``SelectItem``: Select item
|
||||
* ``NoAction``: No action
|
||||
|
||||
|
@ -3347,6 +3347,10 @@ The development version
|
||||
ResizeRightUp,
|
||||
ResizeLeftDown,
|
||||
ResizeRightDown,
|
||||
RotateTopLeft,
|
||||
RotateTopRight,
|
||||
RotateBottomLeft,
|
||||
RotateBottomRight,
|
||||
SelectItem,
|
||||
NoAction
|
||||
};
|
||||
|
@ -1,14 +1,14 @@
|
||||
Qgis.defaultProjectScales: src/core/qgis.h#L6068
|
||||
Qgis.defaultProjectScales: src/core/qgis.h#L6072
|
||||
Qgis.devVersion: src/core/qgis.h#L89
|
||||
Qgis.geoNone: src/core/qgis.h#L6113
|
||||
Qgis.geoProj4: src/core/qgis.h#L6143
|
||||
Qgis.geoWkt: src/core/qgis.h#L6134
|
||||
Qgis.geographicCrsAuthId: src/core/qgis.h#L6123
|
||||
Qgis.geosVersion: src/core/qgis.h#L6103
|
||||
Qgis.geosVersionInt: src/core/qgis.h#L6075
|
||||
Qgis.geosVersionMajor: src/core/qgis.h#L6082
|
||||
Qgis.geosVersionMinor: src/core/qgis.h#L6089
|
||||
Qgis.geosVersionPatch: src/core/qgis.h#L6096
|
||||
Qgis.geoNone: src/core/qgis.h#L6117
|
||||
Qgis.geoProj4: src/core/qgis.h#L6147
|
||||
Qgis.geoWkt: src/core/qgis.h#L6138
|
||||
Qgis.geographicCrsAuthId: src/core/qgis.h#L6127
|
||||
Qgis.geosVersion: src/core/qgis.h#L6107
|
||||
Qgis.geosVersionInt: src/core/qgis.h#L6079
|
||||
Qgis.geosVersionMajor: src/core/qgis.h#L6086
|
||||
Qgis.geosVersionMinor: src/core/qgis.h#L6093
|
||||
Qgis.geosVersionPatch: src/core/qgis.h#L6100
|
||||
Qgis.releaseName: src/core/qgis.h#L79
|
||||
Qgis.version: src/core/qgis.h#L65
|
||||
Qgis.versionInt: src/core/qgis.h#L72
|
||||
|
@ -173,6 +173,16 @@ full details (``longMessage``).
|
||||
%Docstring
|
||||
Requests a complete rebuild of a model by emitting the according signal
|
||||
|
||||
.. versionadded:: 3.44
|
||||
%End
|
||||
|
||||
void updateBounds();
|
||||
%Docstring
|
||||
Updates the scene rect based on the bounds of the model.
|
||||
|
||||
The bounding rectangle of the model is calculated off all components of
|
||||
the model, with an additional margin arounds items.
|
||||
|
||||
.. versionadded:: 3.44
|
||||
%End
|
||||
|
||||
|
@ -57,6 +57,15 @@ widget.
|
||||
void setModelScene( QgsModelGraphicsScene *scene );
|
||||
%Docstring
|
||||
Sets the related ``scene``.
|
||||
%End
|
||||
|
||||
void friendlySetSceneRect();
|
||||
%Docstring
|
||||
Sets the scene rect used for scrollbar without disturbing the user i.e:
|
||||
- We growth the scene rect as the model growth - We shrink only if the
|
||||
model scene rect is outside the current viewed viewport
|
||||
|
||||
Called each time the view viewport moved or the model scene changed
|
||||
%End
|
||||
|
||||
QgsModelGraphicsScene *modelScene() const;
|
||||
@ -134,12 +143,10 @@ Pastes items from clipboard, using the specified ``mode``.
|
||||
%End
|
||||
|
||||
public slots:
|
||||
|
||||
void snapSelected();
|
||||
%Docstring
|
||||
Snaps the selected items to the grid.
|
||||
%End
|
||||
|
||||
signals:
|
||||
|
||||
void algorithmDropped( const QString &algorithmId, const QPointF &pos );
|
||||
|
@ -11411,6 +11411,10 @@ Qgis.MouseHandlesAction.ResizeLeftUp.__doc__ = "Resize left up (Top left handle)
|
||||
Qgis.MouseHandlesAction.ResizeRightUp.__doc__ = "Resize right up (Top right handle)"
|
||||
Qgis.MouseHandlesAction.ResizeLeftDown.__doc__ = "Resize left down (Bottom left handle)"
|
||||
Qgis.MouseHandlesAction.ResizeRightDown.__doc__ = "Resize right down (Bottom right handle)"
|
||||
Qgis.MouseHandlesAction.RotateTopLeft.__doc__ = "Rotate from top left handle. \n.. versionadded:: 4.0"
|
||||
Qgis.MouseHandlesAction.RotateTopRight.__doc__ = "Rotate from top right handle. \n.. versionadded:: 4.0"
|
||||
Qgis.MouseHandlesAction.RotateBottomLeft.__doc__ = "Rotate from bottom left handle. \n.. versionadded:: 4.0"
|
||||
Qgis.MouseHandlesAction.RotateBottomRight.__doc__ = "Rotate right bottom right handle. \n.. versionadded:: 4.0"
|
||||
Qgis.MouseHandlesAction.SelectItem.__doc__ = "Select item"
|
||||
Qgis.MouseHandlesAction.NoAction.__doc__ = "No action"
|
||||
Qgis.MouseHandlesAction.__doc__ = """Action to be performed by the mouse handles
|
||||
@ -11426,6 +11430,22 @@ Qgis.MouseHandlesAction.__doc__ = """Action to be performed by the mouse handles
|
||||
* ``ResizeRightUp``: Resize right up (Top right handle)
|
||||
* ``ResizeLeftDown``: Resize left down (Bottom left handle)
|
||||
* ``ResizeRightDown``: Resize right down (Bottom right handle)
|
||||
* ``RotateTopLeft``: Rotate from top left handle.
|
||||
|
||||
.. versionadded:: 4.0
|
||||
|
||||
* ``RotateTopRight``: Rotate from top right handle.
|
||||
|
||||
.. versionadded:: 4.0
|
||||
|
||||
* ``RotateBottomLeft``: Rotate from bottom left handle.
|
||||
|
||||
.. versionadded:: 4.0
|
||||
|
||||
* ``RotateBottomRight``: Rotate right bottom right handle.
|
||||
|
||||
.. versionadded:: 4.0
|
||||
|
||||
* ``SelectItem``: Select item
|
||||
* ``NoAction``: No action
|
||||
|
||||
|
@ -3347,6 +3347,10 @@ The development version
|
||||
ResizeRightUp,
|
||||
ResizeLeftDown,
|
||||
ResizeRightDown,
|
||||
RotateTopLeft,
|
||||
RotateTopRight,
|
||||
RotateBottomLeft,
|
||||
RotateBottomRight,
|
||||
SelectItem,
|
||||
NoAction
|
||||
};
|
||||
|
@ -1,14 +1,14 @@
|
||||
Qgis.defaultProjectScales: src/core/qgis.h#L6068
|
||||
Qgis.defaultProjectScales: src/core/qgis.h#L6072
|
||||
Qgis.devVersion: src/core/qgis.h#L89
|
||||
Qgis.geoNone: src/core/qgis.h#L6113
|
||||
Qgis.geoProj4: src/core/qgis.h#L6143
|
||||
Qgis.geoWkt: src/core/qgis.h#L6134
|
||||
Qgis.geographicCrsAuthId: src/core/qgis.h#L6123
|
||||
Qgis.geosVersion: src/core/qgis.h#L6103
|
||||
Qgis.geosVersionInt: src/core/qgis.h#L6075
|
||||
Qgis.geosVersionMajor: src/core/qgis.h#L6082
|
||||
Qgis.geosVersionMinor: src/core/qgis.h#L6089
|
||||
Qgis.geosVersionPatch: src/core/qgis.h#L6096
|
||||
Qgis.geoNone: src/core/qgis.h#L6117
|
||||
Qgis.geoProj4: src/core/qgis.h#L6147
|
||||
Qgis.geoWkt: src/core/qgis.h#L6138
|
||||
Qgis.geographicCrsAuthId: src/core/qgis.h#L6127
|
||||
Qgis.geosVersion: src/core/qgis.h#L6107
|
||||
Qgis.geosVersionInt: src/core/qgis.h#L6079
|
||||
Qgis.geosVersionMajor: src/core/qgis.h#L6086
|
||||
Qgis.geosVersionMinor: src/core/qgis.h#L6093
|
||||
Qgis.geosVersionPatch: src/core/qgis.h#L6100
|
||||
Qgis.releaseName: src/core/qgis.h#L79
|
||||
Qgis.version: src/core/qgis.h#L65
|
||||
Qgis.versionInt: src/core/qgis.h#L72
|
||||
|
@ -173,6 +173,16 @@ full details (``longMessage``).
|
||||
%Docstring
|
||||
Requests a complete rebuild of a model by emitting the according signal
|
||||
|
||||
.. versionadded:: 3.44
|
||||
%End
|
||||
|
||||
void updateBounds();
|
||||
%Docstring
|
||||
Updates the scene rect based on the bounds of the model.
|
||||
|
||||
The bounding rectangle of the model is calculated off all components of
|
||||
the model, with an additional margin arounds items.
|
||||
|
||||
.. versionadded:: 3.44
|
||||
%End
|
||||
|
||||
|
@ -57,6 +57,15 @@ widget.
|
||||
void setModelScene( QgsModelGraphicsScene *scene );
|
||||
%Docstring
|
||||
Sets the related ``scene``.
|
||||
%End
|
||||
|
||||
void friendlySetSceneRect();
|
||||
%Docstring
|
||||
Sets the scene rect used for scrollbar without disturbing the user i.e:
|
||||
- We growth the scene rect as the model growth - We shrink only if the
|
||||
model scene rect is outside the current viewed viewport
|
||||
|
||||
Called each time the view viewport moved or the model scene changed
|
||||
%End
|
||||
|
||||
QgsModelGraphicsScene *modelScene() const;
|
||||
@ -134,12 +143,10 @@ Pastes items from clipboard, using the specified ``mode``.
|
||||
%End
|
||||
|
||||
public slots:
|
||||
|
||||
void snapSelected();
|
||||
%Docstring
|
||||
Snaps the selected items to the grid.
|
||||
%End
|
||||
|
||||
signals:
|
||||
|
||||
void algorithmDropped( const QString &algorithmId, const QPointF &pos );
|
||||
|
@ -71,7 +71,6 @@ pluginPath = os.path.split(os.path.dirname(__file__))[0]
|
||||
|
||||
|
||||
class ModelerDialog(QgsModelDesignerDialog):
|
||||
CANVAS_SIZE = 4000
|
||||
|
||||
update_model = pyqtSignal()
|
||||
|
||||
@ -97,7 +96,6 @@ class ModelerDialog(QgsModelDesignerDialog):
|
||||
self.setStyleSheet(iface.mainWindow().styleSheet())
|
||||
|
||||
scene = ModelerScene(self)
|
||||
scene.setSceneRect(QRectF(0, 0, self.CANVAS_SIZE, self.CANVAS_SIZE))
|
||||
self.setModelScene(scene)
|
||||
|
||||
self.view().ensureVisible(0, 0, 10, 10)
|
||||
@ -244,8 +242,6 @@ class ModelerDialog(QgsModelDesignerDialog):
|
||||
|
||||
def repaintModel(self, showControls=True):
|
||||
scene = ModelerScene(self)
|
||||
scene.setSceneRect(QRectF(0, 0, self.CANVAS_SIZE, self.CANVAS_SIZE))
|
||||
|
||||
if not showControls:
|
||||
scene.setFlag(QgsModelGraphicsScene.Flag.FlagHideControls)
|
||||
|
||||
@ -259,6 +255,7 @@ class ModelerDialog(QgsModelDesignerDialog):
|
||||
self.setModelScene(scene)
|
||||
# create items later that setModelScene to setup link to messageBar to the scene
|
||||
scene.createItems(self.model(), context)
|
||||
scene.updateBounds()
|
||||
|
||||
def create_widget_context(self):
|
||||
"""
|
||||
@ -347,7 +344,7 @@ class ModelerDialog(QgsModelDesignerDialog):
|
||||
for i in list(self.model().parameterComponents().values())
|
||||
]
|
||||
)
|
||||
newX = min(MARGIN + BOX_WIDTH + maxX, self.CANVAS_SIZE - BOX_WIDTH)
|
||||
newX = MARGIN + BOX_WIDTH + maxX
|
||||
else:
|
||||
newX = MARGIN + BOX_WIDTH / 2
|
||||
return QPointF(newX, MARGIN + BOX_HEIGHT / 2)
|
||||
@ -415,8 +412,8 @@ class ModelerDialog(QgsModelDesignerDialog):
|
||||
for alg in list(self.model().childAlgorithms().values())
|
||||
]
|
||||
)
|
||||
newX = min(MARGIN + BOX_WIDTH + maxX, self.CANVAS_SIZE - BOX_WIDTH)
|
||||
newY = min(MARGIN + BOX_HEIGHT + maxY, self.CANVAS_SIZE - BOX_HEIGHT)
|
||||
newX = MARGIN + BOX_WIDTH + maxX
|
||||
newY = MARGIN + BOX_HEIGHT + maxY
|
||||
else:
|
||||
newX = MARGIN + BOX_WIDTH / 2
|
||||
newY = MARGIN * 2 + BOX_HEIGHT + BOX_HEIGHT / 2
|
||||
|
@ -658,6 +658,9 @@ class Repositories(QObject):
|
||||
.text()
|
||||
.strip()
|
||||
)
|
||||
supports_qt6 = pluginNodes.item(i).firstChildElement(
|
||||
"supports_qt6"
|
||||
).text().strip().upper() in ["TRUE", "YES"]
|
||||
if not qgisMaximumVersion:
|
||||
if qgisMinimumVersion[0] == "3" and supports_qt6:
|
||||
qgisMaximumVersion = "4.99"
|
||||
|
@ -5897,6 +5897,10 @@ class CORE_EXPORT Qgis
|
||||
ResizeRightUp, //!< Resize right up (Top right handle)
|
||||
ResizeLeftDown, //!< Resize left down (Bottom left handle)
|
||||
ResizeRightDown, //!< Resize right down (Bottom right handle)
|
||||
RotateTopLeft, //!< Rotate from top left handle. \since QGIS 4.0
|
||||
RotateTopRight, //!< Rotate from top right handle. \since QGIS 4.0
|
||||
RotateBottomLeft, //!< Rotate from bottom left handle. \since QGIS 4.0
|
||||
RotateBottomRight, //!< Rotate right bottom right handle. \since QGIS 4.0
|
||||
SelectItem, //!< Select item
|
||||
NoAction //!< No action
|
||||
};
|
||||
|
@ -196,6 +196,10 @@ void QgsLayoutGuiUtils::registerGuiForKnownItemTypes( QgsMapCanvas *mapCanvas )
|
||||
case Qgis::MouseHandlesAction::MoveItem:
|
||||
case Qgis::MouseHandlesAction::NoAction:
|
||||
case Qgis::MouseHandlesAction::SelectItem:
|
||||
case Qgis::MouseHandlesAction::RotateTopLeft:
|
||||
case Qgis::MouseHandlesAction::RotateTopRight:
|
||||
case Qgis::MouseHandlesAction::RotateBottomLeft:
|
||||
case Qgis::MouseHandlesAction::RotateBottomRight:
|
||||
return;
|
||||
|
||||
case Qgis::MouseHandlesAction::ResizeUp:
|
||||
|
@ -44,6 +44,8 @@ QgsLayoutMouseHandles::QgsLayoutMouseHandles( QgsLayout *layout, QgsLayoutView *
|
||||
, mLayout( layout )
|
||||
, mView( view )
|
||||
{
|
||||
setRotationEnabled( true );
|
||||
|
||||
//listen for selection changes, and update handles accordingly
|
||||
connect( mLayout, &QGraphicsScene::selectionChanged, this, &QgsLayoutMouseHandles::selectionChanged );
|
||||
|
||||
@ -251,6 +253,16 @@ void QgsLayoutMouseHandles::moveItem( QGraphicsItem *item, double deltaX, double
|
||||
qgis::down_cast<QgsLayoutItem *>( item )->attemptMoveBy( deltaX, deltaY );
|
||||
}
|
||||
|
||||
void QgsLayoutMouseHandles::rotateItem( QGraphicsItem *item, double deltaDegree, double deltaCenterX, double deltaCenterY )
|
||||
{
|
||||
QgsLayoutItem *itm = qgis::down_cast<QgsLayoutItem *>( item );
|
||||
QgsLayoutItem::ReferencePoint previousReferencePoint = itm->referencePoint();
|
||||
itm->setReferencePoint( QgsLayoutItem::Middle );
|
||||
itm->attemptMoveBy( deltaCenterX, deltaCenterY );
|
||||
itm->setItemRotation( itm->itemRotation() + deltaDegree, true );
|
||||
itm->setReferencePoint( previousReferencePoint );
|
||||
}
|
||||
|
||||
void QgsLayoutMouseHandles::setItemRect( QGraphicsItem *item, QRectF rect )
|
||||
{
|
||||
QgsLayoutItem *layoutItem = dynamic_cast<QgsLayoutItem *>( item );
|
||||
|
@ -74,6 +74,7 @@ class GUI_EXPORT QgsLayoutMouseHandles : public QgsGraphicsViewMouseHandles
|
||||
void expandItemList( const QList<QGraphicsItem *> &items, QList<QGraphicsItem *> &collected ) const override;
|
||||
void expandItemList( const QList<QgsLayoutItem *> &items, QList<QGraphicsItem *> &collected ) const;
|
||||
void moveItem( QGraphicsItem *item, double deltaX, double deltaY ) override;
|
||||
void rotateItem( QGraphicsItem *item, double deltaDegree, double deltaCenterX, double deltaCenterY ) override;
|
||||
void setItemRect( QGraphicsItem *item, QRectF rect ) override;
|
||||
void showStatusMessage( const QString &message ) override;
|
||||
void hideAlignItems() override;
|
||||
|
@ -440,7 +440,7 @@ void QgsModelDesignerDialog::setModel( QgsProcessingModelAlgorithm *model )
|
||||
|
||||
mGroupEdit->setText( mModel->group() );
|
||||
mNameEdit->setText( mModel->displayName() );
|
||||
repaintModel();
|
||||
repaintModel( true );
|
||||
updateVariablesGui();
|
||||
|
||||
mView->centerOn( 0, 0 );
|
||||
@ -480,7 +480,6 @@ void QgsModelDesignerDialog::setModelScene( QgsModelGraphicsScene *scene )
|
||||
mScene->setModel( mModel.get() );
|
||||
mScene->setMessageBar( mMessageBar );
|
||||
|
||||
const QPointF center = mView->mapToScene( mView->viewport()->rect().center() );
|
||||
mView->setModelScene( mScene );
|
||||
|
||||
mSelectTool->resetCache();
|
||||
@ -499,8 +498,6 @@ void QgsModelDesignerDialog::setModelScene( QgsModelGraphicsScene *scene )
|
||||
connect( mScene, &QgsModelGraphicsScene::showChildAlgorithmOutputs, this, &QgsModelDesignerDialog::showChildAlgorithmOutputs );
|
||||
connect( mScene, &QgsModelGraphicsScene::showChildAlgorithmLog, this, &QgsModelDesignerDialog::showChildAlgorithmLog );
|
||||
|
||||
mView->centerOn( center );
|
||||
|
||||
if ( oldScene )
|
||||
oldScene->deleteLater();
|
||||
}
|
||||
|
@ -33,6 +33,8 @@ QgsModelGraphicsScene::QgsModelGraphicsScene( QObject *parent )
|
||||
: QGraphicsScene( parent )
|
||||
{
|
||||
setItemIndexMethod( QGraphicsScene::NoIndex );
|
||||
|
||||
connect( this, &QgsModelGraphicsScene::componentChanged, this, &QgsModelGraphicsScene::updateBounds );
|
||||
}
|
||||
|
||||
QgsProcessingModelAlgorithm *QgsModelGraphicsScene::model()
|
||||
@ -60,6 +62,28 @@ void QgsModelGraphicsScene::mousePressEvent( QGraphicsSceneMouseEvent *event )
|
||||
QGraphicsScene::mousePressEvent( event );
|
||||
}
|
||||
|
||||
void QgsModelGraphicsScene::updateBounds()
|
||||
{
|
||||
//start with an empty rectangle
|
||||
QRectF bounds;
|
||||
|
||||
//add all items
|
||||
const QList<QGraphicsItem *> constItems = items();
|
||||
for ( QGraphicsItem *item : constItems )
|
||||
{
|
||||
QgsModelComponentGraphicItem *componentItem = dynamic_cast<QgsModelComponentGraphicItem *>( item );
|
||||
if ( componentItem )
|
||||
bounds = bounds.united( componentItem->sceneBoundingRect() );
|
||||
}
|
||||
|
||||
if ( bounds.isValid() )
|
||||
{
|
||||
bounds.adjust( -SCENE_COMPONENT_MARGIN, -SCENE_COMPONENT_MARGIN, SCENE_COMPONENT_MARGIN, SCENE_COMPONENT_MARGIN );
|
||||
}
|
||||
|
||||
setSceneRect( bounds );
|
||||
}
|
||||
|
||||
QgsModelComponentGraphicItem *QgsModelGraphicsScene::createParameterGraphicItem( QgsProcessingModelAlgorithm *model, QgsProcessingModelParameter *param ) const
|
||||
{
|
||||
return new QgsModelParameterGraphicItem( param, model, nullptr );
|
||||
|
@ -181,6 +181,15 @@ class GUI_EXPORT QgsModelGraphicsScene : public QGraphicsScene
|
||||
*/
|
||||
void requestRebuildRequired();
|
||||
|
||||
/**
|
||||
* Updates the scene rect based on the bounds of the model.
|
||||
|
||||
* The bounding rectangle of the model is calculated off all components of the model, with an additional margin arounds items.
|
||||
*
|
||||
* \since QGIS 3.44
|
||||
*/
|
||||
void updateBounds();
|
||||
|
||||
signals:
|
||||
|
||||
/**
|
||||
@ -282,6 +291,8 @@ class GUI_EXPORT QgsModelGraphicsScene : public QGraphicsScene
|
||||
QMap<QString, QgsModelComponentGraphicItem *> mGroupBoxItems;
|
||||
QgsProcessingModelResult mLastResult;
|
||||
|
||||
static constexpr int SCENE_COMPONENT_MARGIN = 50;
|
||||
|
||||
QgsMessageBar *mMessageBar = nullptr;
|
||||
};
|
||||
|
||||
|
@ -52,6 +52,9 @@ QgsModelGraphicsView::QgsModelGraphicsView( QWidget *parent )
|
||||
mMidMouseButtonPanTool = new QgsModelViewToolTemporaryMousePan( this );
|
||||
mSpaceZoomTool = new QgsModelViewToolTemporaryKeyZoom( this );
|
||||
|
||||
connect( horizontalScrollBar(), &QScrollBar::sliderReleased, this, [=] { friendlySetSceneRect(); } );
|
||||
connect( verticalScrollBar(), &QScrollBar::sliderReleased, this, [=] { friendlySetSceneRect(); } );
|
||||
|
||||
mSnapper.setSnapToGrid( true );
|
||||
}
|
||||
|
||||
@ -397,6 +400,8 @@ void QgsModelGraphicsView::setModelScene( QgsModelGraphicsScene *scene )
|
||||
{
|
||||
setScene( scene );
|
||||
|
||||
connect( scene, &QgsModelGraphicsScene::sceneRectChanged, this, [=] { friendlySetSceneRect(); } );
|
||||
|
||||
// IMPORTANT!
|
||||
// previous snap markers, snap lines are owned by previous layout - so don't delete them here!
|
||||
mSnapMarker = new QgsModelViewSnapMarker();
|
||||
@ -468,7 +473,6 @@ void QgsModelGraphicsView::endCommand()
|
||||
emit commandEnded();
|
||||
}
|
||||
|
||||
|
||||
void QgsModelGraphicsView::snapSelected()
|
||||
{
|
||||
QgsModelGraphicsScene *s = modelScene();
|
||||
@ -492,6 +496,21 @@ void QgsModelGraphicsView::snapSelected()
|
||||
endMacroCommand();
|
||||
}
|
||||
|
||||
void QgsModelGraphicsView::friendlySetSceneRect()
|
||||
{
|
||||
QRectF modelSceneRect = modelScene()->sceneRect();
|
||||
QRectF viewSceneRect = sceneRect();
|
||||
|
||||
QRectF visibleRect = mapToScene( viewport()->rect() ).boundingRect();
|
||||
|
||||
viewSceneRect.setLeft( std::min( modelSceneRect.left(), visibleRect.left() ) );
|
||||
viewSceneRect.setRight( std::max( modelSceneRect.right(), visibleRect.right() ) );
|
||||
viewSceneRect.setTop( std::min( modelSceneRect.top(), visibleRect.top() ) );
|
||||
viewSceneRect.setBottom( std::max( modelSceneRect.bottom(), visibleRect.bottom() ) );
|
||||
|
||||
setSceneRect( viewSceneRect );
|
||||
}
|
||||
|
||||
void QgsModelGraphicsView::copySelectedItems( QgsModelGraphicsView::ClipboardOperation operation )
|
||||
{
|
||||
copyItems( modelScene()->selectedComponentItems(), operation );
|
||||
|
@ -66,6 +66,16 @@ class GUI_EXPORT QgsModelGraphicsView : public QGraphicsView
|
||||
*/
|
||||
void setModelScene( QgsModelGraphicsScene *scene );
|
||||
|
||||
/**
|
||||
* Sets the scene rect used for scrollbar without disturbing the user
|
||||
* i.e:
|
||||
* - We growth the scene rect as the model growth
|
||||
* - We shrink only if the model scene rect is outside the current viewed viewport
|
||||
*
|
||||
* Called each time the view viewport moved or the model scene changed
|
||||
*/
|
||||
void friendlySetSceneRect();
|
||||
|
||||
/**
|
||||
* Returns the scene associated with the tool.
|
||||
* \see view()
|
||||
@ -158,12 +168,10 @@ class GUI_EXPORT QgsModelGraphicsView : public QGraphicsView
|
||||
void pasteItems( PasteMode mode );
|
||||
|
||||
public slots:
|
||||
|
||||
/**
|
||||
* Snaps the selected items to the grid.
|
||||
*/
|
||||
void snapSelected();
|
||||
|
||||
signals:
|
||||
|
||||
/**
|
||||
|
@ -81,6 +81,7 @@ void QgsModelViewToolPan::modelReleaseEvent( QgsModelViewMouseEvent *event )
|
||||
|
||||
mIsPanning = false;
|
||||
view()->viewport()->setCursor( Qt::OpenHandCursor );
|
||||
view()->friendlySetSceneRect();
|
||||
}
|
||||
|
||||
void QgsModelViewToolPan::deactivate()
|
||||
|
@ -37,6 +37,7 @@ void QgsModelViewToolTemporaryKeyPan::keyReleaseEvent( QKeyEvent *event )
|
||||
if ( event->key() == Qt::Key_Space && !event->isAutoRepeat() )
|
||||
{
|
||||
view()->setTool( mPreviousViewTool );
|
||||
view()->friendlySetSceneRect();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,6 +37,7 @@ void QgsModelViewToolTemporaryMousePan::modelReleaseEvent( QgsModelViewMouseEven
|
||||
if ( event->button() == Qt::MiddleButton )
|
||||
{
|
||||
view()->setTool( mPreviousViewTool );
|
||||
view()->friendlySetSceneRect();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,10 +15,13 @@
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "qgsgraphicsviewmousehandles.h"
|
||||
#include "moc_qgsgraphicsviewmousehandles.cpp"
|
||||
#include "qgsrendercontext.h"
|
||||
|
||||
#include "qgis.h"
|
||||
#include "qgsgraphicsviewmousehandles.h"
|
||||
#include "qgslayoututils.h"
|
||||
#include "qgsrendercontext.h"
|
||||
|
||||
#include <QGraphicsView>
|
||||
#include <QGraphicsSceneHoverEvent>
|
||||
#include <QPainter>
|
||||
@ -34,6 +37,28 @@ QgsGraphicsViewMouseHandles::QgsGraphicsViewMouseHandles( QGraphicsView *view )
|
||||
{
|
||||
//accept hover events, required for changing cursor to resize cursors
|
||||
setAcceptHoverEvents( true );
|
||||
|
||||
//prepare rotation handle path
|
||||
mRotationHandlePath.moveTo( 0, 14 );
|
||||
mRotationHandlePath.lineTo( 6, 20 );
|
||||
mRotationHandlePath.lineTo( 12, 14 );
|
||||
mRotationHandlePath.arcTo( 8, 8, 12, 12, 180, -90 );
|
||||
mRotationHandlePath.lineTo( 14, 12 );
|
||||
mRotationHandlePath.lineTo( 20, 6 );
|
||||
mRotationHandlePath.lineTo( 14, 0 );
|
||||
mRotationHandlePath.arcTo( 4, 4, 20, 20, 90, 90 );
|
||||
mRotationHandlePath.lineTo( 0, 14 );
|
||||
}
|
||||
|
||||
void QgsGraphicsViewMouseHandles::setRotationEnabled( bool enable )
|
||||
{
|
||||
if ( mRotationEnabled == enable )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
mRotationEnabled = enable;
|
||||
update();
|
||||
}
|
||||
|
||||
void QgsGraphicsViewMouseHandles::paintInternal( QPainter *painter, bool showHandles, bool showStaticBoundingBoxes, bool showTemporaryBoundingBoxes, const QStyleOptionGraphicsItem *, QWidget * )
|
||||
@ -62,6 +87,11 @@ QRectF QgsGraphicsViewMouseHandles::storedItemRect( QGraphicsItem *item ) const
|
||||
return itemRect( item );
|
||||
}
|
||||
|
||||
void QgsGraphicsViewMouseHandles::rotateItem( QGraphicsItem *, double, double, double )
|
||||
{
|
||||
QgsDebugError( QStringLiteral( "Rotation is not implemented for this class" ) );
|
||||
}
|
||||
|
||||
void QgsGraphicsViewMouseHandles::previewItemMove( QGraphicsItem *, double, double )
|
||||
{
|
||||
}
|
||||
@ -108,7 +138,7 @@ void QgsGraphicsViewMouseHandles::drawHandles( QPainter *painter, double rectHan
|
||||
painter->setBrush( Qt::NoBrush );
|
||||
painter->drawRect( QRectF( 0, 0, rect().width(), rect().height() ) );
|
||||
|
||||
//draw resize handles, using a filled white box
|
||||
//draw resize handles, using filled white boxes
|
||||
painter->setBrush( QColor( 255, 255, 255, 255 ) );
|
||||
//top left
|
||||
painter->drawRect( QRectF( 0, 0, rectHandlerSize, rectHandlerSize ) );
|
||||
@ -126,6 +156,63 @@ void QgsGraphicsViewMouseHandles::drawHandles( QPainter *painter, double rectHan
|
||||
painter->drawRect( QRectF( ( rect().width() - rectHandlerSize ) / 2, rect().height() - rectHandlerSize, rectHandlerSize, rectHandlerSize ) );
|
||||
//bottom right
|
||||
painter->drawRect( QRectF( rect().width() - rectHandlerSize, rect().height() - rectHandlerSize, rectHandlerSize, rectHandlerSize ) );
|
||||
|
||||
if ( isRotationEnabled() )
|
||||
{
|
||||
//draw rotate handles
|
||||
const double scale = rectHandlerSize / mHandleSize;
|
||||
const bool drawBottomRotationHandles = ( rectHandlerSize * 2 ) + ( mRotationHandleSize * scale * 2 ) < rect().height();
|
||||
const bool drawRightRotationHandles = ( rectHandlerSize * 2 ) + ( mRotationHandleSize * scale * 2 ) < rect().width();
|
||||
QTransform transform;
|
||||
|
||||
//top left
|
||||
transform.reset();
|
||||
transform.translate( rectHandlerSize, rectHandlerSize );
|
||||
transform.scale( scale, scale );
|
||||
painter->save();
|
||||
painter->setTransform( transform, true );
|
||||
painter->drawPath( mRotationHandlePath );
|
||||
painter->restore();
|
||||
|
||||
//top right
|
||||
if ( drawRightRotationHandles )
|
||||
{
|
||||
transform.reset();
|
||||
transform.translate( rect().width() - rectHandlerSize, rectHandlerSize );
|
||||
transform.rotate( 90 );
|
||||
transform.scale( scale, scale );
|
||||
painter->save();
|
||||
painter->setTransform( transform, true );
|
||||
painter->drawPath( mRotationHandlePath );
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
if ( drawBottomRotationHandles )
|
||||
{
|
||||
//bottom left
|
||||
transform.reset();
|
||||
transform.translate( rectHandlerSize, rect().height() - rectHandlerSize );
|
||||
transform.rotate( 270 );
|
||||
transform.scale( scale, scale );
|
||||
painter->save();
|
||||
painter->setTransform( transform, true );
|
||||
painter->drawPath( mRotationHandlePath );
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
if ( drawBottomRotationHandles && drawRightRotationHandles )
|
||||
{
|
||||
//bottom right
|
||||
transform.reset();
|
||||
transform.translate( rect().width() - rectHandlerSize, rect().height() - rectHandlerSize );
|
||||
transform.rotate( 180 );
|
||||
transform.scale( scale, scale );
|
||||
painter->save();
|
||||
painter->setTransform( transform, true );
|
||||
painter->drawPath( mRotationHandlePath );
|
||||
painter->restore();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QgsGraphicsViewMouseHandles::drawSelectedItemBounds( QPainter *painter )
|
||||
@ -181,6 +268,17 @@ void QgsGraphicsViewMouseHandles::drawSelectedItemBounds( QPainter *painter )
|
||||
relativeResizeRect( thisItemRect, QRectF( -mResizeMoveX, -mResizeMoveY, mBeginHandleWidth, mBeginHandleHeight ), mResizeRect );
|
||||
itemBounds = QPolygonF( thisItemRect );
|
||||
}
|
||||
else if ( isRotating() && !itemIsLocked( item ) )
|
||||
{
|
||||
const QPolygonF itemSceneBounds = item->mapToScene( itemRect( item ) );
|
||||
const QPointF rotationCenter = sceneTransform().map( rect().center() );
|
||||
|
||||
QTransform transform;
|
||||
transform.translate( rotationCenter.x(), rotationCenter.y() );
|
||||
transform.rotate( mRotationDelta );
|
||||
transform.translate( -rotationCenter.x(), -rotationCenter.y() );
|
||||
itemBounds = mapFromScene( transform.map( itemSceneBounds ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
// not resizing or moving, so just map the item's bounds to the mouse handle item's coordinate system
|
||||
@ -195,7 +293,7 @@ void QgsGraphicsViewMouseHandles::drawSelectedItemBounds( QPainter *painter )
|
||||
}
|
||||
}
|
||||
|
||||
double QgsGraphicsViewMouseHandles::rectHandlerBorderTolerance()
|
||||
double QgsGraphicsViewMouseHandles::rectHandlerBorderTolerance() const
|
||||
{
|
||||
if ( !mView )
|
||||
return 0;
|
||||
@ -312,6 +410,12 @@ Qt::CursorShape QgsGraphicsViewMouseHandles::cursorForPosition( QPointF itemCoor
|
||||
}
|
||||
case Qgis::MouseHandlesAction::SelectItem:
|
||||
return Qt::ArrowCursor;
|
||||
|
||||
case Qgis::MouseHandlesAction::RotateTopLeft:
|
||||
case Qgis::MouseHandlesAction::RotateTopRight:
|
||||
case Qgis::MouseHandlesAction::RotateBottomLeft:
|
||||
case Qgis::MouseHandlesAction::RotateBottomRight:
|
||||
return Qt::PointingHandCursor;
|
||||
}
|
||||
|
||||
return Qt::ArrowCursor;
|
||||
@ -324,8 +428,14 @@ Qgis::MouseHandlesAction QgsGraphicsViewMouseHandles::mouseActionForPosition( QP
|
||||
bool nearLowerBorder = false;
|
||||
bool nearUpperBorder = false;
|
||||
|
||||
bool nearLeftInner = false;
|
||||
bool nearRightInner = false;
|
||||
bool nearLowerInner = false;
|
||||
bool nearUpperInner = false;
|
||||
|
||||
bool withinWidth = false;
|
||||
bool withinHeight = false;
|
||||
|
||||
if ( itemCoordPos.x() >= 0 && itemCoordPos.x() <= rect().width() )
|
||||
{
|
||||
withinWidth = true;
|
||||
@ -336,23 +446,40 @@ Qgis::MouseHandlesAction QgsGraphicsViewMouseHandles::mouseActionForPosition( QP
|
||||
}
|
||||
|
||||
double borderTolerance = rectHandlerBorderTolerance();
|
||||
double innerTolerance = mRotationHandleSize * borderTolerance / mHandleSize;
|
||||
|
||||
if ( itemCoordPos.x() >= 0 && itemCoordPos.x() < borderTolerance )
|
||||
{
|
||||
nearLeftBorder = true;
|
||||
}
|
||||
else if ( isRotationEnabled() && itemCoordPos.x() >= borderTolerance && itemCoordPos.x() < ( borderTolerance + innerTolerance ) )
|
||||
{
|
||||
nearLeftInner = true;
|
||||
}
|
||||
if ( itemCoordPos.y() >= 0 && itemCoordPos.y() < borderTolerance )
|
||||
{
|
||||
nearUpperBorder = true;
|
||||
}
|
||||
else if ( isRotationEnabled() && itemCoordPos.y() >= borderTolerance && itemCoordPos.y() < ( borderTolerance + innerTolerance ) )
|
||||
{
|
||||
nearUpperInner = true;
|
||||
}
|
||||
if ( itemCoordPos.x() <= rect().width() && itemCoordPos.x() > ( rect().width() - borderTolerance ) )
|
||||
{
|
||||
nearRightBorder = true;
|
||||
}
|
||||
else if ( isRotationEnabled() && itemCoordPos.x() <= ( rect().width() - borderTolerance ) && itemCoordPos.x() > ( rect().width() - borderTolerance - innerTolerance ) )
|
||||
{
|
||||
nearRightInner = true;
|
||||
}
|
||||
if ( itemCoordPos.y() <= rect().height() && itemCoordPos.y() > ( rect().height() - borderTolerance ) )
|
||||
{
|
||||
nearLowerBorder = true;
|
||||
}
|
||||
else if ( isRotationEnabled() && itemCoordPos.y() <= ( rect().height() - borderTolerance ) && itemCoordPos.y() > ( rect().height() - borderTolerance - innerTolerance ) )
|
||||
{
|
||||
nearLowerInner = true;
|
||||
}
|
||||
|
||||
if ( nearLeftBorder && nearUpperBorder )
|
||||
{
|
||||
@ -386,6 +513,22 @@ Qgis::MouseHandlesAction QgsGraphicsViewMouseHandles::mouseActionForPosition( QP
|
||||
{
|
||||
return Qgis::MouseHandlesAction::ResizeDown;
|
||||
}
|
||||
else if ( nearLeftInner && nearUpperInner )
|
||||
{
|
||||
return Qgis::MouseHandlesAction::RotateTopLeft;
|
||||
}
|
||||
else if ( nearRightInner && nearUpperInner )
|
||||
{
|
||||
return Qgis::MouseHandlesAction::RotateTopRight;
|
||||
}
|
||||
else if ( nearLeftInner && nearLowerInner )
|
||||
{
|
||||
return Qgis::MouseHandlesAction::RotateBottomLeft;
|
||||
}
|
||||
else if ( nearRightInner && nearLowerInner )
|
||||
{
|
||||
return Qgis::MouseHandlesAction::RotateBottomRight;
|
||||
}
|
||||
|
||||
//find out if cursor position is over a selected item
|
||||
QPointF scenePoint = mapToScene( itemCoordPos );
|
||||
@ -489,19 +632,42 @@ void QgsGraphicsViewMouseHandles::mousePressEvent( QGraphicsSceneMouseEvent *eve
|
||||
|
||||
hideAlignItems();
|
||||
|
||||
if ( mCurrentMouseMoveAction == Qgis::MouseHandlesAction::MoveItem )
|
||||
switch ( mCurrentMouseMoveAction )
|
||||
{
|
||||
//moving items
|
||||
mIsDragging = true;
|
||||
}
|
||||
else if ( mCurrentMouseMoveAction != Qgis::MouseHandlesAction::SelectItem && mCurrentMouseMoveAction != Qgis::MouseHandlesAction::NoAction )
|
||||
{
|
||||
//resizing items
|
||||
mIsResizing = true;
|
||||
mResizeRect = QRectF( 0, 0, mBeginHandleWidth, mBeginHandleHeight );
|
||||
mResizeMoveX = 0;
|
||||
mResizeMoveY = 0;
|
||||
mCursorOffset = calcCursorEdgeOffset( mMouseMoveStartPos );
|
||||
case Qgis::MouseHandlesAction::MoveItem:
|
||||
//moving items
|
||||
mIsDragging = true;
|
||||
break;
|
||||
|
||||
case Qgis::MouseHandlesAction::ResizeUp:
|
||||
case Qgis::MouseHandlesAction::ResizeDown:
|
||||
case Qgis::MouseHandlesAction::ResizeLeft:
|
||||
case Qgis::MouseHandlesAction::ResizeRight:
|
||||
case Qgis::MouseHandlesAction::ResizeLeftUp:
|
||||
case Qgis::MouseHandlesAction::ResizeRightUp:
|
||||
case Qgis::MouseHandlesAction::ResizeLeftDown:
|
||||
case Qgis::MouseHandlesAction::ResizeRightDown:
|
||||
//resizing items
|
||||
mIsResizing = true;
|
||||
mResizeRect = QRectF( 0, 0, mBeginHandleWidth, mBeginHandleHeight );
|
||||
mResizeMoveX = 0;
|
||||
mResizeMoveY = 0;
|
||||
mCursorOffset = calcCursorEdgeOffset( mMouseMoveStartPos );
|
||||
break;
|
||||
|
||||
case Qgis::MouseHandlesAction::RotateTopLeft:
|
||||
case Qgis::MouseHandlesAction::RotateTopRight:
|
||||
case Qgis::MouseHandlesAction::RotateBottomLeft:
|
||||
case Qgis::MouseHandlesAction::RotateBottomRight:
|
||||
mIsRotating = true;
|
||||
mRotationCenter = sceneTransform().map( rect().center() );
|
||||
mRotationBegin = std::atan2( mMouseMoveStartPos.y() - mRotationCenter.y(), mMouseMoveStartPos.x() - mRotationCenter.x() ) * 180 / M_PI;
|
||||
mRotationCurrent = 0.0;
|
||||
break;
|
||||
|
||||
case Qgis::MouseHandlesAction::SelectItem:
|
||||
case Qgis::MouseHandlesAction::NoAction:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -537,6 +703,12 @@ void QgsGraphicsViewMouseHandles::mouseMoveEvent( QGraphicsSceneMouseEvent *even
|
||||
//resize from center if alt depressed
|
||||
resizeMouseMove( event->lastScenePos(), event->modifiers() & Qt::ShiftModifier, event->modifiers() & Qt::AltModifier );
|
||||
}
|
||||
else if ( isRotating() )
|
||||
{
|
||||
//currently rotating a selection
|
||||
//snap to common angles if ctrl is pressed
|
||||
rotateMouseMove( event->lastScenePos(), event->modifiers() & Qt::ControlModifier );
|
||||
}
|
||||
}
|
||||
|
||||
void QgsGraphicsViewMouseHandles::mouseReleaseEvent( QGraphicsSceneMouseEvent *event )
|
||||
@ -567,12 +739,13 @@ void QgsGraphicsViewMouseHandles::mouseReleaseEvent( QGraphicsSceneMouseEvent *e
|
||||
{
|
||||
mIsDragging = false;
|
||||
mIsResizing = false;
|
||||
mIsRotating = false;
|
||||
update();
|
||||
hideAlignItems();
|
||||
return;
|
||||
}
|
||||
|
||||
if ( mCurrentMouseMoveAction == Qgis::MouseHandlesAction::MoveItem )
|
||||
if ( mIsDragging )
|
||||
{
|
||||
//move selected items
|
||||
startMacroCommand( tr( "Move Items" ) );
|
||||
@ -597,8 +770,10 @@ void QgsGraphicsViewMouseHandles::mouseReleaseEvent( QGraphicsSceneMouseEvent *e
|
||||
endItemCommand( item );
|
||||
}
|
||||
endMacroCommand();
|
||||
|
||||
mIsDragging = false;
|
||||
}
|
||||
else if ( mCurrentMouseMoveAction != Qgis::MouseHandlesAction::NoAction )
|
||||
else if ( mIsResizing )
|
||||
{
|
||||
//resize selected items
|
||||
startMacroCommand( tr( "Resize Items" ) );
|
||||
@ -635,17 +810,44 @@ void QgsGraphicsViewMouseHandles::mouseReleaseEvent( QGraphicsSceneMouseEvent *e
|
||||
endItemCommand( item );
|
||||
}
|
||||
endMacroCommand();
|
||||
|
||||
mIsResizing = false;
|
||||
}
|
||||
else if ( mIsRotating )
|
||||
{
|
||||
const QPointF itemRotationCenter = sceneTransform().map( rect().center() );
|
||||
|
||||
//move selected items
|
||||
startMacroCommand( tr( "Rotate Items" ) );
|
||||
|
||||
//move all selected items
|
||||
const QList<QGraphicsItem *> selectedItems = selectedSceneItems( false );
|
||||
for ( QGraphicsItem *item : selectedItems )
|
||||
{
|
||||
if ( itemIsLocked( item ) || ( item->flags() & QGraphicsItem::ItemIsSelectable ) == 0 || itemIsGroupMember( item ) )
|
||||
{
|
||||
//don't move locked items, or grouped items (group takes care of that)
|
||||
continue;
|
||||
}
|
||||
|
||||
const QPointF itemCenter = item->mapToScene( itemRect( item ) ).boundingRect().center();
|
||||
|
||||
QTransform transform;
|
||||
transform.translate( itemRotationCenter.x(), itemRotationCenter.y() );
|
||||
transform.rotate( mRotationDelta );
|
||||
transform.translate( -itemRotationCenter.x(), -itemRotationCenter.y() );
|
||||
const QPointF rotatedItemCenter = transform.map( itemCenter );
|
||||
|
||||
createItemCommand( item );
|
||||
rotateItem( item, mRotationDelta, rotatedItemCenter.x() - itemCenter.x(), rotatedItemCenter.y() - itemCenter.y() );
|
||||
endItemCommand( item );
|
||||
}
|
||||
endMacroCommand();
|
||||
|
||||
mIsRotating = false;
|
||||
}
|
||||
|
||||
hideAlignItems();
|
||||
if ( mIsDragging )
|
||||
{
|
||||
mIsDragging = false;
|
||||
}
|
||||
if ( mIsResizing )
|
||||
{
|
||||
mIsResizing = false;
|
||||
}
|
||||
|
||||
//reset default action
|
||||
mCurrentMouseMoveAction = Qgis::MouseHandlesAction::MoveItem;
|
||||
@ -721,6 +923,36 @@ void QgsGraphicsViewMouseHandles::updateHandles()
|
||||
update();
|
||||
}
|
||||
|
||||
void QgsGraphicsViewMouseHandles::rotateMouseMove( QPointF currentPosition, bool snapToCommonAngles )
|
||||
{
|
||||
if ( !scene() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
mRotationCurrent = std::atan2( currentPosition.y() - mRotationCenter.y(), currentPosition.x() - mRotationCenter.x() ) * 180 / M_PI;
|
||||
mRotationDelta = mRotationCurrent - mRotationBegin;
|
||||
if ( snapToCommonAngles )
|
||||
{
|
||||
mRotationDelta = QgsLayoutUtils::snappedAngle( mRotationDelta );
|
||||
}
|
||||
|
||||
const double itemRotationRadian = rotation() * M_PI / 180;
|
||||
const double deltaX = ( rect().width() / 2 ) * cos( itemRotationRadian ) - ( rect().height() / 2 ) * sin( itemRotationRadian );
|
||||
const double deltaY = ( rect().width() / 2 ) * sin( itemRotationRadian ) + ( rect().height() / 2 ) * cos( itemRotationRadian );
|
||||
|
||||
QTransform rotateTransform;
|
||||
rotateTransform.translate( deltaX, deltaY );
|
||||
rotateTransform.rotate( mRotationDelta );
|
||||
rotateTransform.translate( -deltaX, -deltaY );
|
||||
setTransform( rotateTransform );
|
||||
|
||||
//show current selection rotation in status bar
|
||||
showStatusMessage( tr( "rotation: %1°" ).arg( QString::number( mRotationDelta, 'f', 2 ) ) );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void QgsGraphicsViewMouseHandles::dragMouseMove( QPointF currentPosition, bool lockMovement, bool preventSnap )
|
||||
{
|
||||
if ( !scene() )
|
||||
@ -985,6 +1217,10 @@ void QgsGraphicsViewMouseHandles::resizeMouseMove( QPointF currentPosition, bool
|
||||
break;
|
||||
}
|
||||
|
||||
case Qgis::MouseHandlesAction::RotateTopLeft:
|
||||
case Qgis::MouseHandlesAction::RotateTopRight:
|
||||
case Qgis::MouseHandlesAction::RotateBottomLeft:
|
||||
case Qgis::MouseHandlesAction::RotateBottomRight:
|
||||
case Qgis::MouseHandlesAction::MoveItem:
|
||||
case Qgis::MouseHandlesAction::SelectItem:
|
||||
case Qgis::MouseHandlesAction::NoAction:
|
||||
@ -1099,6 +1335,10 @@ QSizeF QgsGraphicsViewMouseHandles::calcCursorEdgeOffset( QPointF cursorPos )
|
||||
case Qgis::MouseHandlesAction::ResizeLeftDown:
|
||||
return QSizeF( sceneMousePos.x(), sceneMousePos.y() - rect().height() );
|
||||
|
||||
case Qgis::MouseHandlesAction::RotateTopLeft:
|
||||
case Qgis::MouseHandlesAction::RotateTopRight:
|
||||
case Qgis::MouseHandlesAction::RotateBottomLeft:
|
||||
case Qgis::MouseHandlesAction::RotateBottomRight:
|
||||
case Qgis::MouseHandlesAction::MoveItem:
|
||||
case Qgis::MouseHandlesAction::SelectItem:
|
||||
case Qgis::MouseHandlesAction::NoAction:
|
||||
|
@ -77,11 +77,37 @@ class GUI_EXPORT QgsGraphicsViewMouseHandles : public QObject, public QGraphicsR
|
||||
//! Returns TRUE is user is currently resizing with the handles
|
||||
bool isResizing() const { return mIsResizing; }
|
||||
|
||||
/**
|
||||
* Returns TRUE is user is currently rotating with the handles.
|
||||
*
|
||||
* \since QGIS 4.0
|
||||
*/
|
||||
bool isRotating() const { return mIsRotating; }
|
||||
|
||||
bool shouldBlockEvent( QInputEvent *event ) const;
|
||||
|
||||
//! Initializes a drag operation \since QGIS 3.34
|
||||
void startMove( QPointF sceneCoordPos );
|
||||
|
||||
/**
|
||||
* Returns TRUE if rotation functionality is enabled.
|
||||
*
|
||||
* Rotation is not enabled by default.
|
||||
*
|
||||
* \since QGIS 4.0
|
||||
*/
|
||||
bool isRotationEnabled() const { return mRotationEnabled; }
|
||||
|
||||
/**
|
||||
* Sets whether rotation functionality is enabled.
|
||||
*
|
||||
* Rotation is not enabled by default. Subclasses must implement the
|
||||
* rotateItem() method in order to support rotation.
|
||||
*
|
||||
* \since QGIS 4.0
|
||||
*/
|
||||
void setRotationEnabled( bool enable );
|
||||
|
||||
public slots:
|
||||
|
||||
//! Redraws handles when selected item size changes
|
||||
@ -111,6 +137,7 @@ class GUI_EXPORT QgsGraphicsViewMouseHandles : public QObject, public QGraphicsR
|
||||
virtual QRectF itemRect( QGraphicsItem *item ) const = 0;
|
||||
virtual QRectF storedItemRect( QGraphicsItem *item ) const;
|
||||
virtual void moveItem( QGraphicsItem *item, double deltaX, double deltaY ) = 0;
|
||||
virtual void rotateItem( QGraphicsItem *item, double deltaDegree, double deltaCenterX, double deltaCenterY );
|
||||
virtual void previewItemMove( QGraphicsItem *item, double deltaX, double deltaY );
|
||||
virtual void setItemRect( QGraphicsItem *item, QRectF rect ) = 0;
|
||||
|
||||
@ -158,6 +185,9 @@ class GUI_EXPORT QgsGraphicsViewMouseHandles : public QObject, public QGraphicsR
|
||||
//! Handles resizing of items during mouse move
|
||||
void resizeMouseMove( QPointF currentPosition, bool lockAspect, bool fromCenter );
|
||||
|
||||
//! Handles rotating of tiems during mouse move
|
||||
void rotateMouseMove( QPointF currentPosition, bool snapToCommonAngles );
|
||||
|
||||
void setHandleSize( double size );
|
||||
|
||||
//! Finds out which mouse move action to choose depending on the cursor position inside the widget
|
||||
@ -194,6 +224,8 @@ class GUI_EXPORT QgsGraphicsViewMouseHandles : public QObject, public QGraphicsR
|
||||
QGraphicsView *mView = nullptr;
|
||||
|
||||
double mHandleSize = 10;
|
||||
double mRotationHandleSize = 20;
|
||||
QPainterPath mRotationHandlePath;
|
||||
|
||||
QSizeF mCursorOffset;
|
||||
double mResizeMoveX = 0;
|
||||
@ -205,6 +237,16 @@ class GUI_EXPORT QgsGraphicsViewMouseHandles : public QObject, public QGraphicsR
|
||||
|
||||
QRectF mResizeRect;
|
||||
|
||||
bool mRotationEnabled = false;
|
||||
//! Center point around which rotation occurs
|
||||
QPointF mRotationCenter;
|
||||
//! The starting rotation angle from center point
|
||||
double mRotationBegin = 0.0;
|
||||
//! The current rotation angle from center point
|
||||
double mRotationCurrent = 0.0;
|
||||
//! The rotation angle delta to be applied (can be snapped to common angle)
|
||||
double mRotationDelta = 0.0;
|
||||
|
||||
//! Start point of the last mouse move action (in scene coordinates)
|
||||
QPointF mMouseMoveStartPos;
|
||||
|
||||
@ -215,6 +257,8 @@ class GUI_EXPORT QgsGraphicsViewMouseHandles : public QObject, public QGraphicsR
|
||||
bool mIsDragging = false;
|
||||
//! True is user is currently resizing items
|
||||
bool mIsResizing = false;
|
||||
//! True is user is currently rotating items
|
||||
bool mIsRotating = false;
|
||||
|
||||
//! Position of the mouse at beginning of move/resize (in scene coordinates)
|
||||
QPointF mBeginMouseEventPos;
|
||||
@ -232,7 +276,7 @@ class GUI_EXPORT QgsGraphicsViewMouseHandles : public QObject, public QGraphicsR
|
||||
* Returns the current (zoom level dependent) tolerance to decide if mouse position is close enough to the
|
||||
* item border for resizing.
|
||||
*/
|
||||
double rectHandlerBorderTolerance();
|
||||
double rectHandlerBorderTolerance() const;
|
||||
|
||||
//! Finds out the appropriate cursor for the current mouse position in the widget (e.g. move in the middle, resize at border)
|
||||
Qt::CursorShape cursorForPosition( QPointF itemCoordPos );
|
||||
|
@ -11455,6 +11455,42 @@ void TestProcessingGui::testModelGraphicsView()
|
||||
// should not exist
|
||||
QVERIFY( !layerCommentItem );
|
||||
|
||||
//check model bounds
|
||||
scene2.updateBounds();
|
||||
QRectF modelRect = scene2.sceneRect();
|
||||
QGSCOMPARENEAR( modelRect.height(), 624.4, 3 ); // Sligtly higher threeshold because of various font size can marginally change the bounding rect
|
||||
QGSCOMPARENEAR( modelRect.width(), 655.00, 0.01 );
|
||||
QGSCOMPARENEAR( modelRect.left(), -252.0, 0.01 );
|
||||
QGSCOMPARENEAR( modelRect.top(), -232.0, 0.01 );
|
||||
|
||||
|
||||
// test model large modelRect
|
||||
QgsProcessingModelAlgorithm model2;
|
||||
|
||||
QgsProcessingModelChildAlgorithm algc2;
|
||||
algc2.setChildId( "buffer" );
|
||||
algc2.setAlgorithmId( "native:buffer" );
|
||||
algc2.setPosition( QPointF( 4250, 4250 ) );
|
||||
QgsProcessingModelParameter param1;
|
||||
param1.setParameterName( QStringLiteral( "LAYER" ) );
|
||||
param1.setSize( QSizeF( 500, 400 ) );
|
||||
param1.setPosition( QPointF( -250, -250 ) );
|
||||
model2.addModelParameter( new QgsProcessingParameterMapLayer( QStringLiteral( "LAYER" ) ), param );
|
||||
algc2.addParameterSources( QStringLiteral( "INPUT" ), QList<QgsProcessingModelChildParameterSource>() << QgsProcessingModelChildParameterSource::fromModelParameter( QStringLiteral( "LAYER" ) ) );
|
||||
|
||||
model2.addChildAlgorithm( algc2 );
|
||||
|
||||
QgsModelGraphicsScene scene3;
|
||||
scene3.setModel( &model2 );
|
||||
scene3.createItems( &model2, context );
|
||||
|
||||
scene3.updateBounds();
|
||||
QRectF modelRect2 = scene3.sceneRect();
|
||||
QGSCOMPARENEAR( modelRect2.height(), 4505.4, 3 ); // Sligtly higher threeshold because of various font size can marginally change the bounding rect
|
||||
QGSCOMPARENEAR( modelRect2.width(), 4603.0, 0.01 );
|
||||
QGSCOMPARENEAR( modelRect2.left(), -201.0, 0.01 );
|
||||
QGSCOMPARENEAR( modelRect2.top(), -150.0, 0.01 );
|
||||
|
||||
|
||||
QgsModelGraphicsScene scene;
|
||||
QVERIFY( !scene.model() );
|
||||
|
Loading…
x
Reference in New Issue
Block a user