Temporary rubberband

This commit is contained in:
Yoann Quenach de Quivillic 2024-12-07 15:13:38 +01:00 committed by Nyall Dawson
parent 7141c2e368
commit 6c3dc5d069
7 changed files with 87 additions and 26 deletions

View File

@ -90,7 +90,7 @@ should be created. The default behavior is to create a rectangular rubber band.
.. seealso:: :py:func:`createNodeRubberBand`
%End
virtual QAbstractGraphicsShapeItem *createNodeRubberBand( QgsLayoutView *view ) /TransferBack/;
virtual QGraphicsItem *createNodeRubberBand( QgsLayoutView *view ) /TransferBack/;
%Docstring
Creates a rubber band for use when creating layout node based items of this type. Can return ``None`` if no rubber band
should be created. The default behavior is to return ``None``.

View File

@ -90,7 +90,7 @@ should be created. The default behavior is to create a rectangular rubber band.
.. seealso:: :py:func:`createNodeRubberBand`
%End
virtual QAbstractGraphicsShapeItem *createNodeRubberBand( QgsLayoutView *view ) /TransferBack/;
virtual QGraphicsItem *createNodeRubberBand( QgsLayoutView *view ) /TransferBack/;
%Docstring
Creates a rubber band for use when creating layout node based items of this type. Can return ``None`` if no rubber band
should be created. The default behavior is to return ``None``.

View File

@ -387,9 +387,14 @@ void QgsLayoutGuiUtils::registerGuiForKnownItemTypes( QgsMapCanvas *mapCanvas )
arrow->setEndMarker( QgsLayoutItemPolyline::ArrowHead );
return arrow.release();
} );
arrowMetadata->setNodeRubberBandCreationFunction( []( QgsLayoutView * ) -> QGraphicsPathItem * {
std::unique_ptr<QGraphicsPathItem> band = std::make_unique<QGraphicsPathItem>();
band->setPen( QPen( QBrush( QColor( 227, 22, 22, 200 ) ), 0 ) );
arrowMetadata->setNodeRubberBandCreationFunction( []( QgsLayoutView * ) -> QGraphicsItemGroup * {
std::unique_ptr<QGraphicsItemGroup> band = std::make_unique<QGraphicsItemGroup>();
QGraphicsPathItem *poly = new QGraphicsPathItem( band.get() );
poly->setPen( QPen( QBrush( QColor( 227, 22, 22, 200 ) ), 0 ) );
QGraphicsPathItem *tempPoly = new QGraphicsPathItem( band.get() );
tempPoly->setPen( QPen( QBrush( QColor( 227, 22, 22, 200 ) ), 0, Qt::DotLine ) );
band->setZValue( QgsLayout::ZViewTool );
return band.release();
} );
@ -404,10 +409,16 @@ void QgsLayoutGuiUtils::registerGuiForKnownItemTypes( QgsMapCanvas *mapCanvas )
},
createRubberBand, QStringLiteral( "nodes" ), true
);
polygonMetadata->setNodeRubberBandCreationFunction( []( QgsLayoutView * ) -> QGraphicsPolygonItem * {
std::unique_ptr<QGraphicsPolygonItem> band = std::make_unique<QGraphicsPolygonItem>();
band->setBrush( Qt::NoBrush );
band->setPen( QPen( QBrush( QColor( 227, 22, 22, 200 ) ), 0 ) );
polygonMetadata->setNodeRubberBandCreationFunction( []( QgsLayoutView * ) -> QGraphicsItemGroup * {
std::unique_ptr<QGraphicsItemGroup> band = std::make_unique<QGraphicsItemGroup>();
QGraphicsPolygonItem *poly = new QGraphicsPolygonItem( band.get() );
poly->setBrush( QBrush( QColor( 227, 22, 22, 20 ) ) );
poly->setPen( QPen( QBrush( QColor( 227, 22, 22, 200 ) ), 0 ) );
QGraphicsPolygonItem *tempPoly = new QGraphicsPolygonItem( band.get() );
tempPoly->setBrush( Qt::NoBrush );
tempPoly->setPen( QPen( QBrush( QColor( 227, 22, 22, 200 ) ), 0, Qt::DotLine ) );
band->setZValue( QgsLayout::ZViewTool );
return band.release();
} );
@ -420,9 +431,14 @@ void QgsLayoutGuiUtils::registerGuiForKnownItemTypes( QgsMapCanvas *mapCanvas )
},
createRubberBand, QStringLiteral( "nodes" ), true
);
polylineMetadata->setNodeRubberBandCreationFunction( []( QgsLayoutView * ) -> QGraphicsPathItem * {
std::unique_ptr<QGraphicsPathItem> band = std::make_unique<QGraphicsPathItem>();
band->setPen( QPen( QBrush( QColor( 227, 22, 22, 200 ) ), 0 ) );
polylineMetadata->setNodeRubberBandCreationFunction( []( QgsLayoutView * ) -> QGraphicsItemGroup * {
std::unique_ptr<QGraphicsItemGroup> band = std::make_unique<QGraphicsItemGroup>();
QGraphicsPathItem *poly = new QGraphicsPathItem( band.get() );
poly->setPen( QPen( QBrush( QColor( 227, 22, 22, 200 ) ), 0 ) );
QGraphicsPathItem *tempPoly = new QGraphicsPathItem( band.get() );
tempPoly->setPen( QPen( QBrush( QColor( 227, 22, 22, 200 ) ), 0, Qt::DotLine ) );
band->setZValue( QgsLayout::ZViewTool );
return band.release();
} );

View File

@ -28,7 +28,7 @@ QgsLayoutViewRubberBand *QgsLayoutItemAbstractGuiMetadata::createRubberBand( Qgs
return new QgsLayoutViewRectangularRubberBand( view );
}
QAbstractGraphicsShapeItem *QgsLayoutItemAbstractGuiMetadata::createNodeRubberBand( QgsLayoutView * )
QGraphicsItem *QgsLayoutItemAbstractGuiMetadata::createNodeRubberBand( QgsLayoutView * )
{
return nullptr;
}
@ -160,7 +160,7 @@ QgsLayoutViewRubberBand *QgsLayoutItemGuiRegistry::createItemRubberBand( int met
return mMetadata[metadataId]->createRubberBand( view );
}
QAbstractGraphicsShapeItem *QgsLayoutItemGuiRegistry::createNodeItemRubberBand( int metadataId, QgsLayoutView *view )
QGraphicsItem *QgsLayoutItemGuiRegistry::createNodeItemRubberBand( int metadataId, QgsLayoutView *view )
{
if ( !mMetadata.contains( metadataId ) )
return nullptr;

View File

@ -137,7 +137,7 @@ class GUI_EXPORT QgsLayoutItemAbstractGuiMetadata
* should be created. The default behavior is to return NULLPTR.
* \see createRubberBand()
*/
virtual QAbstractGraphicsShapeItem *createNodeRubberBand( QgsLayoutView *view ) SIP_TRANSFERBACK;
virtual QGraphicsItem *createNodeRubberBand( QgsLayoutView *view ) SIP_TRANSFERBACK;
/**
* Creates an instance of the corresponding item type.
@ -176,7 +176,7 @@ typedef std::function<QgsLayoutItemBaseWidget *( QgsLayoutItem * )> QgsLayoutIte
typedef std::function<QgsLayoutViewRubberBand *( QgsLayoutView * )> QgsLayoutItemRubberBandFunc SIP_SKIP;
//! Layout node based rubber band creation function
typedef std::function<QAbstractGraphicsShapeItem *( QgsLayoutView * )> QgsLayoutNodeItemRubberBandFunc SIP_SKIP;
typedef std::function<QGraphicsItem *( QgsLayoutView * )> QgsLayoutNodeItemRubberBandFunc SIP_SKIP;
//! Layout item added to layout callback
typedef std::function<void( QgsLayoutItem *, const QVariantMap & )> QgsLayoutItemAddedToLayoutFunc SIP_SKIP;
@ -290,7 +290,7 @@ class GUI_EXPORT QgsLayoutItemGuiMetadata : public QgsLayoutItemAbstractGuiMetad
QIcon creationIcon() const override { return mIcon.isNull() ? QgsLayoutItemAbstractGuiMetadata::creationIcon() : mIcon; }
QgsLayoutItemBaseWidget *createItemWidget( QgsLayoutItem *item ) override { return mWidgetFunc ? mWidgetFunc( item ) : nullptr; }
QgsLayoutViewRubberBand *createRubberBand( QgsLayoutView *view ) override { return mRubberBandFunc ? mRubberBandFunc( view ) : nullptr; }
QAbstractGraphicsShapeItem *createNodeRubberBand( QgsLayoutView *view ) override { return mNodeRubberBandFunc ? mNodeRubberBandFunc( view ) : nullptr; }
QGraphicsItem *createNodeRubberBand( QgsLayoutView *view ) override { return mNodeRubberBandFunc ? mNodeRubberBandFunc( view ) : nullptr; }
QgsLayoutItem *createItem( QgsLayout *layout ) override;
void newItemAddedToLayout( QgsLayoutItem *item ) override;
@ -494,7 +494,7 @@ class GUI_EXPORT QgsLayoutItemGuiRegistry : public QObject
* \see createItemRubberBand()
* \note not available from Python bindings
*/
QAbstractGraphicsShapeItem *createNodeItemRubberBand( int metadataId, QgsLayoutView *view ) SIP_SKIP;
QGraphicsItem *createNodeItemRubberBand( int metadataId, QgsLayoutView *view ) SIP_SKIP;
/**
* Returns a list of available item metadata ids handled by the registry.

View File

@ -191,16 +191,61 @@ void QgsLayoutViewToolAddNodeItem::moveTemporaryNode( QPointF scenePoint, Qt::Ke
void QgsLayoutViewToolAddNodeItem::setRubberBandNodes()
{
if ( QGraphicsPolygonItem *polygonItem = dynamic_cast<QGraphicsPolygonItem *>( mRubberBand.get() ) )
QList<QGraphicsItem *> items = mRubberBand->childItems();
if ( items.isEmpty() )
return;
if ( QGraphicsPolygonItem *polygonItem = dynamic_cast<QGraphicsPolygonItem *>( items[0] ) )
{
polygonItem->setPolygon( mPolygon );
// The group contains two polygons
if ( items.size() == 2 && dynamic_cast<QGraphicsPolygonItem *>( items[1] ) != nullptr )
{
if ( mPolygon.size() > 3 )
{
polygonItem->setPolygon( QPolygonF( mPolygon.mid( 0, mPolygon.size() - 1 ) ) );
}
else
{
polygonItem->setPolygon( QPolygonF() );
}
dynamic_cast<QGraphicsPolygonItem *>( items[1] )->setPolygon( mPolygon );
}
// The group contains a single QGraphicsPolygonItem as rubberband
else
{
polygonItem->setPolygon( mPolygon );
}
}
else if ( QGraphicsPathItem *polylineItem = dynamic_cast<QGraphicsPathItem *>( mRubberBand.get() ) )
else if ( QGraphicsPathItem *polylineItem = dynamic_cast<QGraphicsPathItem *>( items[0] ) )
{
// rebuild a new qpainter path
QPainterPath path;
path.addPolygon( mPolygon );
polylineItem->setPath( path );
// The group contains two polylines
if ( items.size() == 2 && dynamic_cast<QGraphicsPathItem *>( items[1] ) != nullptr )
{
if ( mPolygon.size() > 2 )
{
QPainterPath path;
path.addPolygon( QPolygonF( mPolygon.mid( 0, mPolygon.size() - 1 ) ) );
polylineItem->setPath( path );
}
else
{
polylineItem->setPath( QPainterPath() );
}
if ( mPolygon.size() > 1 )
{
QPainterPath path;
path.addPolygon( mPolygon.mid( mPolygon.size() - 2 ) );
dynamic_cast<QGraphicsPathItem *>( items[1] )->setPath( path );
}
}
// The group contains a single QGraphicsPathItem as rubberband
else
{
// rebuild a new qpainter path
QPainterPath path;
path.addPolygon( mPolygon );
polylineItem->setPath( path );
}
}
}

View File

@ -67,7 +67,7 @@ class GUI_EXPORT QgsLayoutViewToolAddNodeItem : public QgsLayoutViewTool
int mItemMetadataId = -1;
//! Rubber band item
std::unique_ptr<QAbstractGraphicsShapeItem> mRubberBand;
std::unique_ptr<QGraphicsItem> mRubberBand;
QPolygonF mPolygon;