QGIS API Documentation 4.1.0-Master (4aad578bf8d)
Loading...
Searching...
No Matches
qgsmaptoolextraitem.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsmaptoolextraitem.cpp
3 ---------------------
4 begin : 2026/01/22
5 copyright : (C) 2026 by Julien Cabieces
6 email : julien dot cabieces at oslandia dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
16#include "qgsmaptoolextraitem.h"
17
18#include "qgsauxiliarystorage.h"
19#include "qgslinesymbol.h"
20#include "qgslinesymbollayer.h"
21#include "qgsmapmouseevent.h"
22#include "qgsmarkersymbol.h"
24#include "qgsrubberband.h"
25#include "qgssnappingutils.h"
26#include "qgssymbollayerutils.h"
27#include "qgsvectorlayerutils.h"
28
29#include <qgraphicssceneevent.h>
30
31#include "moc_qgsmaptoolextraitem.cpp"
32
44{
45 public:
55
60
65 void setRotation( double rotation );
66
70 const QgsPointXY &position() const;
71
75 double rotation() const;
76
80 void update();
81
82 private:
83 QgsPointXY mPosition;
84 double mRotation;
85 QPointer<QgsVectorLayer> mLayer;
86 QgsTemplatedLineSymbolLayerBase *mSymbolLayer = nullptr;
87};
88
90
105
107{
108 if ( FID_IS_NULL( mFeatureId ) || !mLayer )
109 return;
110
111 QgsFeature feature = mLayer->getFeature( mFeatureId );
112 if ( !feature.isValid() )
113 return;
114
115 QString currentExtraItems = feature.attribute( mExtraItemsFieldIndex ).toString();
116
117 QString error;
118 QgsSymbolLayerUtils::ExtraItems extraItems = QgsSymbolLayerUtils::parseExtraItems( currentExtraItems, error );
119 if ( !error.isEmpty() )
120 {
121 emit messageEmitted( tr( "Error while parsing feature extra items: %1" ).arg( error ), Qgis::MessageLevel::Critical );
122 return;
123 }
124
125 mExtraItems.clear();
126
127 for ( std::pair<QPointF, double> extraItem : extraItems )
128 {
129 QgsExtraItemRubberBand *rubberBand = new QgsExtraItemRubberBand( extraItem.first, extraItem.second, mCanvas, mLayer, mSymbolLayer );
130 mExtraItems.push_back( rubberBand );
131 }
132}
133
135{
136 if ( !mLayer )
137 return;
138
139 QStringList strExtraItems;
141 {
142 QgsPointXY point = extraItem->position();
143 strExtraItems << qgsDoubleToString( point.x() ) + " " + qgsDoubleToString( point.y() ) + " " + qgsDoubleToString( extraItem->rotation() );
144 }
145
146 QString strNewExtraItems = strExtraItems.join( "," );
147
148 mLayer->beginEditCommand( tr( "Set extra item list" ) );
149 if ( mLayer->changeAttributeValue( mFeatureId, mExtraItemsFieldIndex, strNewExtraItems ) )
150 {
151 mLayer->endEditCommand();
152 mLayer->triggerRepaint();
153 }
154 else
155 {
156 mLayer->destroyEditCommand();
157 }
158}
159
161{
162 if ( !mLayer || !mSymbolLayer || !mPropertyButton || mPropertyButton->propertyKey() != static_cast<int>( QgsSymbolLayer::Property::ExtraItems ) )
163 return;
164
165 // find the closest feature to the pressed position
166 const QgsPointLocator::Match m = mCanvas->snappingUtils()->snapToCurrentLayer( event->pos(), QgsPointLocator::Edge );
167 if ( !m.isValid() )
168 {
169 emit
170 messageEmitted( tr( "No feature was detected at the clicked position. Please click closer to the feature or enhance the search tolerance under Settings->Options->Digitizing->Search radius for vertex edits" ), Qgis::MessageLevel::Critical );
171 return;
172 }
173
174 // initialize field index if not already done
175 if ( mExtraItemsFieldIndex < 0 )
176 {
178 }
179
180 // No data defined property, create one
181 if ( mExtraItemsFieldIndex < 0 )
182 {
183 if ( !mLayer->auxiliaryLayer() )
184 {
186 dlg.exec();
187 }
188
189 if ( !mLayer->auxiliaryLayer() )
190 return;
191
193 if ( mExtraItemsFieldIndex < 0 )
194 {
195 emit messageEmitted( tr( "Failed to create extra item auxiliary field for layer '%1'" ).arg( mLayer->name() ) );
196 return;
197 }
198
199 // update property override button from new property
200 QgsPropertyCollection c = mSymbolLayer->dataDefinedProperties();
201 QgsProperty property = c.property( static_cast<int>( QgsSymbolLayer::Property::ExtraItems ) );
202 mPropertyButton->updateFieldLists();
203 mPropertyButton->setToProperty( property );
204 emit mPropertyButton->changed(); // setToProperty doesn't fire the changed signal
205 }
206
207 // start editing
208
209 const bool usesAuxFields = mLayer->fields().fieldOrigin( mExtraItemsFieldIndex ) == Qgis::FieldOrigin::Join;
210 if ( !usesAuxFields && !mLayer->isEditable() )
211 {
212 if ( mLayer->startEditing() )
213 {
214 emit messageEmitted( tr( "Layer “%1” was made editable" ).arg( mLayer->name() ) );
215 }
216 else
217 {
218 emit messageEmitted( tr( "Cannot modify extra items — the layer “%1” could not be made editable" ).arg( mLayer->name() ) );
219 return;
220 }
221 }
222
223 mFeatureId = m.featureId();
226 event->ignore();
227}
228
230
232 : QgsMapToolExtraItemBase( canvas, layer, symbolLayer, propertyButton )
233{
234 mToolName = tr( "Extra item add tool" );
235}
236
238{
239 if ( !mLayer || e->button() != Qt::LeftButton )
240 return;
241
242 switch ( mState )
243 {
245 selectFeature( e );
246 break;
247
249 {
250 const QgsPointXY layerPoint = toLayerCoordinates( mLayer, e->mapPoint() );
251 QgsExtraItemRubberBand *newRubberBand = new QgsExtraItemRubberBand( layerPoint, 0, mCanvas, mLayer, mSymbolLayer );
252 mExtraItems.push_back( newRubberBand );
254 e->ignore();
255 break;
256 }
257 }
258}
259
261{
262 switch ( mState )
263 {
265 break;
266
268 if ( event->matches( QKeySequence::StandardKey::Cancel ) )
269 {
272 mExtraItems.clear();
273 event->ignore();
274 }
275 }
276}
277
279
280
281QgsMapToolModifyExtraItems::QgsMapToolModifyExtraItemMouseHandles::QgsMapToolModifyExtraItemMouseHandles( QgsMapToolModifyExtraItems *mapTool, QgsMapCanvas *canvas )
282 : QgsGraphicsViewMouseHandles( canvas )
283 , mMapTool( mapTool )
284 , mCanvas( canvas )
285{
286 setZValue( 100 );
287
288 connect( mMapTool, &QgsMapToolModifyExtraItems::selectedItemsChanged, this, [this] { updateHandles(); } );
289 mCanvas->scene()->addItem( this );
290
291 setRotationEnabled( true );
292 setResizeEnabled( false );
293};
294
295void QgsMapToolModifyExtraItems::QgsMapToolModifyExtraItemMouseHandles::paint( QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget )
296{
297 paintInternal( painter, true, true, true, option, widget );
298}
299
300void QgsMapToolModifyExtraItems::QgsMapToolModifyExtraItemMouseHandles::setViewportCursor( Qt::CursorShape cursor )
301{
302 if ( dynamic_cast<QgsMapToolModifyExtraItems *>( mCanvas->mapTool() ) )
303 {
304 mCanvas->viewport()->setCursor( cursor );
305 }
306}
307
308QList<QGraphicsItem *> QgsMapToolModifyExtraItems::QgsMapToolModifyExtraItemMouseHandles::sceneItemsAtPoint( QPointF scenePoint )
309{
310 QList<QGraphicsItem *> graphicsItems;
311 const QList<QGraphicsItem *> items = mMapTool->selectedItems();
312 for ( auto item : items )
313 {
314 if ( item->sceneBoundingRect().contains( scenePoint ) )
315 {
316 graphicsItems << item;
317 }
318 }
319 return graphicsItems;
320}
321
322QList<QGraphicsItem *> QgsMapToolModifyExtraItems::QgsMapToolModifyExtraItemMouseHandles::selectedSceneItems( bool ) const
323{
324 return mMapTool->selectedItems();
325}
326
327QRectF QgsMapToolModifyExtraItems::QgsMapToolModifyExtraItemMouseHandles::itemRect( QGraphicsItem *item ) const
328{
329 return item->boundingRect();
330}
331
332void QgsMapToolModifyExtraItems::QgsMapToolModifyExtraItemMouseHandles::moveItem( QGraphicsItem *item, double deltaX, double deltaY )
333{
334 mMapTool->attemptMoveBy( item, deltaX, deltaY );
335}
336
337void QgsMapToolModifyExtraItems::QgsMapToolModifyExtraItemMouseHandles::rotateItem( QGraphicsItem *item, double deltaDegree, double deltaCenterX, double deltaCenterY )
338{
339 mMapTool->attemptRotateBy( item, deltaDegree, deltaCenterX, deltaCenterY );
340}
341
342void QgsMapToolModifyExtraItems::QgsMapToolModifyExtraItemMouseHandles::setItemRect( QGraphicsItem *, QRectF )
343{
344 QgsDebugError( "Resize is not supported for extra item" );
345}
346
348
350 : QgsRubberBand( mapCanvas )
351 , mPosition( position )
352 , mRotation( rotation )
353 , mLayer( layer )
354 , mSymbolLayer( symbolLayer )
355{
356 setFlags( flags() | QGraphicsItem::ItemIsSelectable );
357
358 setWidth( mapCanvas->fontMetrics().xHeight() * .2 );
359 setStrokeColor( QColor( 255, 0, 0, 255 ) );
360 setFillColor( QColor( 0, 0, 0, 0 ) );
361 setZValue( 10 );
362
363 update();
364
366}
367
373
375{
376 mRotation = rotation;
377 update();
378}
379
381{
382 return mPosition;
383}
384
386{
387 return mRotation;
388}
389
390
392{
393 if ( !mLayer )
394 return;
395
396 QgsRenderContext renderContext = QgsRenderContext::fromMapSettings( mMapCanvas->mapSettings() );
397
398 QgsPointXY mapPoint = mMapCanvas->mapSettings().layerToMapCoordinates( mLayer, mPosition );
399 const QPointF canvasPoint = toCanvasCoordinates( mapPoint );
400
401 QRectF boundingRect;
402 if ( QgsMarkerSymbol *symbol = dynamic_cast<QgsMarkerSymbol *>( mSymbolLayer->subSymbol() ) )
403 {
404 boundingRect = symbol->bounds( canvasPoint, renderContext );
405 }
406 else if ( QgsHashedLineSymbolLayer *slHashedLine = dynamic_cast<QgsHashedLineSymbolLayer *>( mSymbolLayer ) )
407 {
408 QgsLineSymbol *symbol = static_cast<QgsLineSymbol *>( slHashedLine->subSymbol() );
409 const double length = renderContext.convertToPainterUnits( slHashedLine->hashLength(), slHashedLine->hashLengthUnit() );
410 const double width = symbol->width( renderContext );
411 boundingRect = QRectF( canvasPoint - QPointF( width / 2, length / 2 + width / 2 ), QSizeF( width, length + width ) );
412 }
413 else // Shall never happen, extra items are only supported for marker and hashed line symbol layer
414 {
415 Q_ASSERT( false );
416 return;
417 }
418
419 QTransform t = QTransform().translate( canvasPoint.x(), canvasPoint.y() ).rotate( mRotation ).translate( -canvasPoint.x(), -canvasPoint.y() );
420 QPolygonF bounds = t.map( boundingRect );
421
422 bool selected = isSelected();
424 const QgsMapToPixel *transform = mMapCanvas->getCoordinateTransform();
425 for ( int i = 0; i < bounds.count(); i++ )
426 {
427 QPointF canvasPt = bounds.at( i );
428 QgsPointXY mapPt = transform->toMapCoordinates( canvasPt.x(), canvasPt.y() );
429 addPoint( mapPt, i == bounds.count() - 1 ); // update only last one
430 }
431
432 // selected is reinitialized during reset, we need to restore it
433 setSelected( selected );
434}
435
436
438
440 : QgsMapToolExtraItemBase( canvas, layer, symbolLayer, propertyButton )
441{
442 mToolName = tr( "Extra item modify tool" );
443}
444
445
447{
448 connect( mCanvas, &QgsMapCanvas::extentsChanged, this, &QgsMapToolModifyExtraItems::onMapCanvasExtentsChanged );
450}
451
453{
455 disconnect( mCanvas, &QgsMapCanvas::extentsChanged, this, &QgsMapToolModifyExtraItems::onMapCanvasExtentsChanged );
456}
457
458
459QList<QGraphicsItem *> QgsMapToolModifyExtraItems::selectedItems() const
460{
461 return mSelectedItems;
462}
463
465{
466 if ( !mLayer || e->button() != Qt::LeftButton )
467 return;
468
469 switch ( mState )
470 {
472 selectFeature( e );
473 mMouseHandles.reset( new QgsMapToolModifyExtraItemMouseHandles( this, mCanvas ) );
474 break;
475
477 {
478 const bool toggleSelection = e->modifiers() & Qt::ShiftModifier;
479 QPointF scenePos = mCanvas->mapToScene( e->pos() );
480 if ( !toggleSelection && !mSelectedItems.empty() && mMouseHandles->sceneBoundingRect().contains( scenePos ) )
481 {
482 QGraphicsSceneMouseEvent forwardedEvent( QEvent::GraphicsSceneMousePress );
483 forwardedEvent.setPos( mMouseHandles->mapFromScene( scenePos ) );
484 forwardedEvent.setScenePos( scenePos );
485 forwardedEvent.setLastScenePos( mCanvas->mapToScene( mLastPos ) );
486 forwardedEvent.setButton( Qt::LeftButton );
487 mMouseHandles->mousePressEvent( &forwardedEvent );
488 }
489 else
490 {
491 mSelectionRect.setTopLeft( e->pos() );
492 mSelectionRect.setBottomRight( e->pos() );
493 }
494
495 mLastPos = e->pos();
496
497 break;
498 }
499 }
500}
501
503{
504 if ( !mLayer )
505 return;
506
507 switch ( mState )
508 {
510 break;
511
513 {
514 const QPointF scenePos = mCanvas->mapToScene( event->pos() );
515 if ( event->buttons() == Qt::NoButton )
516 {
517 if ( mMouseHandles->sceneBoundingRect().contains( scenePos ) )
518 {
519 QGraphicsSceneHoverEvent forwardedEvent( QEvent::GraphicsSceneHoverMove );
520 forwardedEvent.setPos( mMouseHandles->mapFromScene( scenePos ) );
521 forwardedEvent.setScenePos( scenePos );
522 mMouseHandles->hoverMoveEvent( &forwardedEvent );
523 mHoveringMouseHandles = true;
524 }
525 else if ( mHoveringMouseHandles )
526 {
527 QGraphicsSceneHoverEvent forwardedEvent( QEvent::GraphicsSceneHoverLeave );
528 forwardedEvent.setPos( mMouseHandles->mapFromScene( scenePos ) );
529 forwardedEvent.setScenePos( scenePos );
530 mMouseHandles->hoverMoveEvent( &forwardedEvent );
531 mHoveringMouseHandles = false;
532 }
533 }
534 else if ( event->buttons() == Qt::LeftButton )
535 {
536 if ( mMouseHandles->shouldBlockEvent( event ) )
537 {
538 QGraphicsSceneMouseEvent forwardedEvent( QEvent::GraphicsSceneMouseMove );
539 forwardedEvent.setPos( mMouseHandles->mapFromScene( scenePos ) );
540 forwardedEvent.setScenePos( scenePos );
541 forwardedEvent.setLastScenePos( mCanvas->mapToScene( mLastPos ) );
542 forwardedEvent.setButton( Qt::LeftButton );
543 mMouseHandles->mouseMoveEvent( &forwardedEvent );
544 }
545 else
546 {
547 if ( !mDragging )
548 {
549 mDragging = true;
550 mSelectionRubberBand.reset( new QgsRubberBand( mCanvas, Qgis::GeometryType::Polygon ) );
551 QColor color( Qt::blue );
552 color.setAlpha( 63 );
553 mSelectionRubberBand->setColor( color );
554 mSelectionRect.setTopLeft( event->pos() );
555 }
556
557 mSelectionRect.setBottomRight( event->pos() );
558 if ( mSelectionRubberBand )
559 {
560 mSelectionRubberBand->setToCanvasRectangle( mSelectionRect );
561 mSelectionRubberBand->show();
562 }
563 }
564 }
565 mLastPos = event->pos();
566 break;
567 }
568 }
569}
570
572{
573 if ( !mLayer || event->button() != Qt::LeftButton )
574 return;
575
576 switch ( mState )
577 {
579 break;
580
582 if ( mMouseHandles && mMouseHandles->shouldBlockEvent( event ) )
583 {
584 const QPointF scenePos = mCanvas->mapToScene( event->pos() );
585 QGraphicsSceneMouseEvent forwardedEvent( QEvent::GraphicsSceneMouseRelease );
586 forwardedEvent.setPos( event->pos() );
587 forwardedEvent.setScenePos( scenePos );
588 forwardedEvent.setLastScenePos( mCanvas->mapToScene( mLastPos ) );
589 forwardedEvent.setButton( Qt::LeftButton );
590 mMouseHandles->mouseReleaseEvent( &forwardedEvent );
591 }
592 else
593 {
594 if ( mCanceled )
595 {
596 mCanceled = false;
597 mDragging = false;
598 return;
599 }
600
601 if ( mDragging )
602 {
603 mDragging = false;
604 mSelectionRubberBand.reset();
605 }
606
607 bool selectedItemsHasChanged = false;
608 if ( !( event->modifiers() & Qt::ShiftModifier ) )
609 {
610 selectedItemsHasChanged = true;
611 mSelectedItems.clear();
613 {
614 extraItem->setSelected( false );
615 }
616 }
617
619 {
620 QRectF rect = extraItem->boundingRect();
621 rect.translate( extraItem->pos().x(), extraItem->pos().y() );
622 const bool isSelected = rect.intersects( mSelectionRect );
623 selectedItemsHasChanged |= ( isSelected != extraItem->isSelected() );
624 extraItem->setSelected( isSelected );
625
626 if ( isSelected )
627 {
628 mSelectedItems << extraItem;
629 }
630 }
631
632 if ( selectedItemsHasChanged )
634
635 mMouseHandles->setSelected( !mSelectedItems.empty() );
636 }
637 break;
638 }
639}
640
642{
643 switch ( mState )
644 {
646 break;
647
649 if ( event->matches( QKeySequence::StandardKey::Cancel ) )
650 {
651 if ( !mSelectedItems.empty() )
652 {
653 mSelectedItems.clear();
654 mMouseHandles->updateHandles();
655 event->ignore();
656 return;
657 }
658 else
659 {
662 mExtraItems.clear();
663 event->ignore();
664 return;
665 }
666 }
667
668 if ( event->key() == Qt::Key_V )
669 {
670 const QPointF delta = mLastPos - mCopiedItemsTopLeft;
671 mSelectedItems.clear();
672 for ( const std::tuple<double, double, double> &extraItem : std::as_const( mCopiedItems ) )
673 {
674 QgsExtraItemRubberBand *newRubberBand = new QgsExtraItemRubberBand( QgsPointXY( std::get<0>( extraItem ), std::get<1>( extraItem ) ), std::get<2>( extraItem ), mCanvas, mLayer, mSymbolLayer );
675 newRubberBand->setSelected( true );
676 attemptMoveBy( newRubberBand, delta.x(), delta.y() );
677 mSelectedItems << newRubberBand;
678 mExtraItems.push_back( newRubberBand );
679 }
681 mMouseHandles->updateHandles();
682 event->ignore();
683 return;
684 }
685
686 if ( mSelectedItems.empty() )
687 return;
688
689 if ( event->key() == Qt::Key_C || event->key() == Qt::Key_X )
690 {
691 mCopiedItems.clear();
692 for ( QGraphicsItem *extraItem : std::as_const( mSelectedItems ) )
693 {
694 QgsExtraItemRubberBand *rubberBand = qgis::down_cast<QgsExtraItemRubberBand *>( extraItem );
695 mCopiedItems.push_back( { rubberBand->position().x(), rubberBand->position().y(), rubberBand->rotation() } );
696 }
697 mCopiedItemsTopLeft = mMouseHandles->sceneBoundingRect().topLeft();
698 event->ignore();
699 }
700 else if ( event->key() == Qt::Key_Left || event->key() == Qt::Key_Right || event->key() == Qt::Key_Up || event->key() == Qt::Key_Down )
701 {
702 const int pixels = ( event->modifiers() & Qt::ShiftModifier ) ? 1 : 50;
703 int deltaX = 0;
704 int deltaY = 0;
705 if ( event->key() == Qt::Key_Up )
706 {
707 deltaY = -pixels;
708 }
709 else if ( event->key() == Qt::Key_Down )
710 {
711 deltaY = pixels;
712 }
713 else if ( event->key() == Qt::Key_Left )
714 {
715 deltaX = -pixels;
716 }
717 else if ( event->key() == Qt::Key_Right )
718 {
719 deltaX = pixels;
720 }
721
722 for ( QGraphicsItem *extraItem : mSelectedItems )
723 {
724 attemptMoveBy( extraItem, deltaX, deltaY );
725 }
726 mMouseHandles->updateHandles();
727
728 event->ignore();
729 }
730
731 if ( event->matches( QKeySequence::StandardKey::Delete ) || event->key() == Qt::Key_X )
732 {
733 for ( QGraphicsItem *extraItem : mSelectedItems )
734 {
735 auto it = std::find( mExtraItems.cbegin(), mExtraItems.cend(), extraItem );
736 mExtraItems.erase( it );
737 }
738
739 mSelectedItems.clear();
741 mMouseHandles->updateHandles();
742 event->ignore();
743 }
744 }
745}
746
747QgsPointXY QgsMapToolModifyExtraItems::movePosition( const QgsPointXY &position, double deltaX, double deltaY ) const
748{
749 const double mupp = canvas()->mapSettings().mapUnitsPerPixel();
750 QgsVector translation( deltaX * mupp, -deltaY * mupp );
751
752 QgsPointXY mapPoint = canvas()->mapSettings().layerToMapCoordinates( mLayer, position );
753 mapPoint += translation;
754 return canvas()->mapSettings().mapToLayerCoordinates( mLayer, mapPoint );
755}
756
757
758void QgsMapToolModifyExtraItems::attemptMoveBy( QGraphicsItem *item, double deltaX, double deltaY )
759{
760 QgsExtraItemRubberBand *rubberBand = qgis::down_cast<QgsExtraItemRubberBand *>( item );
761 rubberBand->setPosition( movePosition( rubberBand->position(), deltaX, deltaY ) );
763}
764
765void QgsMapToolModifyExtraItems::attemptRotateBy( QGraphicsItem *item, double deltaDegree, double deltaCenterX, double deltaCenterY )
766{
767 QgsExtraItemRubberBand *rubberBand = qgis::down_cast<QgsExtraItemRubberBand *>( item );
768 rubberBand->setPosition( movePosition( rubberBand->position(), deltaCenterX, deltaCenterY ) );
769 rubberBand->setRotation( std::fmod( rubberBand->rotation() + deltaDegree + 360., 360.0 ) );
771}
772
773void QgsMapToolModifyExtraItems::onMapCanvasExtentsChanged()
774{
776 {
777 extraItem->update();
778 }
779
780 if ( mMouseHandles )
781 mMouseHandles->updateHandles();
782}
Keeps a pointer to a QObject and deletes it whenever this object is deleted.
@ Critical
Critical/error message.
Definition qgis.h:163
@ Polygon
Polygons.
Definition qgis.h:382
@ Join
Field originates from a joined layer.
Definition qgis.h:1827
static int createProperty(QgsPalLayerSettings::Property property, QgsVectorLayer *vlayer, bool overwriteExisting=true)
Creates if necessary a new auxiliary field for a PAL property and activates this property in settings...
Rubber band for one extra item.
double rotation() const
Returns rotation angle in degree between 0 and 360.
void setPosition(QgsPointXY position)
Set extra item position in layer coordinates.
const QgsPointXY & position() const
Returns position in layer CRS.
void setRotation(double rotation)
Set extra item rotation around its center.
QgsExtraItemRubberBand(QgsPointXY position, double rotation, QgsMapCanvas *mapCanvas, QgsVectorLayer *layer, QgsTemplatedLineSymbolLayerBase *symbolLayer)
Constructor.
void update()
Update item according to its current rotation angle and position.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition qgsfeature.h:60
bool isValid() const
Returns the validity of this feature.
Q_INVOKABLE QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
Line symbol layer type which draws repeating line sections along a line feature.
A line symbol type, for rendering LineString and MultiLineString geometries.
QRectF boundingRect() const override
QPointF toCanvasCoordinates(const QgsPointXY &point) const
transformation from map coordinates to screen coordinates
QgsMapCanvas * mMapCanvas
pointer to map canvas
Map canvas is a class for displaying all GIS data types on a canvas.
void extentsChanged()
Emitted when the extents of the map change.
void mapCanvasRefreshed()
Emitted when canvas finished a refresh request.
const QgsMapSettings & mapSettings() const
Gets access to properties used for map rendering.
A mouse event which is the result of a user interaction with a QgsMapCanvas.
QgsPointXY mapPoint() const
mapPoint returns the point in coordinates
QgsPointXY layerToMapCoordinates(const QgsMapLayer *layer, QgsPointXY point) const
transform point coordinates from layer's CRS to output CRS
double mapUnitsPerPixel() const
Returns the distance in geographical coordinates that equals to one pixel in the map.
QgsPointXY mapToLayerCoordinates(const QgsMapLayer *layer, QgsPointXY point) const
transform point coordinates from output CRS to layer's CRS
Perform transforms between map coordinates and device coordinates.
QgsPointXY toMapCoordinates(int x, int y) const
Transforms device coordinates to map (world) coordinates.
void canvasPressEvent(QgsMapMouseEvent *e) override
Mouse press event for overriding. Default implementation does nothing.
void keyPressEvent(QKeyEvent *event) override
Key event for overriding. Default implementation does nothing.
QgsMapToolAddExtraItem(QgsMapCanvas *canvas, QgsVectorLayer *layer, QgsTemplatedLineSymbolLayerBase *symbolLayer, QgsPropertyOverrideButton *propertyButton)
Constructor.
@ SelectFeature
User needs to select a feature.
@ FeatureSelected
User has selected a feature.
void updateAttribute()
Update feature attribute extra item field regarding with the currently digitized extra items.
QPointer< QgsVectorLayer > mLayer
QgsTemplatedLineSymbolLayerBase * mSymbolLayer
void selectFeature(QgsMapMouseEvent *event)
Process event in order to select the current feature at the event mouse position.
QgsMapToolExtraItemBase(QgsMapCanvas *canvas, QgsVectorLayer *layer, QgsTemplatedLineSymbolLayerBase *symbolLayer, QgsPropertyOverrideButton *propertyButton)
Constructor.
std::vector< QObjectUniquePtr< QgsExtraItemRubberBand > > mExtraItems
QgsPropertyOverrideButton * mPropertyButton
void loadFeatureExtraItems()
Load current feature existing extra items.
Map tool to select and modify extra items for a giving vector layer and symbol layer.
QgsMapToolModifyExtraItems(QgsMapCanvas *canvas, QgsVectorLayer *layer, QgsTemplatedLineSymbolLayerBase *symbolLayer, QgsPropertyOverrideButton *propertyButton)
Constructor.
void attemptRotateBy(QGraphicsItem *item, double deltaDegree, double deltaCenterX, double deltaCenterY)
Attempt to rotate item by deltaDegree around its center.
void canvasPressEvent(QgsMapMouseEvent *event) override
Mouse press event for overriding. Default implementation does nothing.
void keyPressEvent(QKeyEvent *event) override
Key event for overriding. Default implementation does nothing.
void attemptMoveBy(QGraphicsItem *item, double deltaX, double deltaY)
Attempt to move item by deltaX horizontally and deltaY vertically.
void canvasReleaseEvent(QgsMapMouseEvent *event) override
Mouse release event for overriding. Default implementation does nothing.
void canvasMoveEvent(QgsMapMouseEvent *event) override
Mouse move event for overriding. Default implementation does nothing.
void deactivate() override
called when map tool is being deactivated
QList< QGraphicsItem * > selectedItems() const
Returns currently selected items.
void activate() override
called when set as currently active map tool
void selectedItemsChanged()
Emitted whenever selected items has changed.
QgsPoint toLayerCoordinates(const QgsMapLayer *layer, const QgsPoint &point)
Transforms a point from map coordinates to layer coordinates.
QgsMapLayer * layer(const QString &id)
Returns the map layer with the matching ID, or nullptr if no layers could be found.
QgsMapCanvas * canvas() const
returns pointer to the tool's map canvas
QgsMapTool(QgsMapCanvas *canvas)
Constructor takes a map canvas as a parameter.
QPointer< QgsMapCanvas > mCanvas
The pointer to the map canvas.
Definition qgsmaptool.h:403
QString mToolName
The translated name of the map tool.
Definition qgsmaptool.h:421
friend class QgsMapCanvas
Definition qgsmaptool.h:423
void messageEmitted(const QString &message, Qgis::MessageLevel level=Qgis::MessageLevel::Info)
Emitted when a message should be shown to the user in the application message bar.
virtual void activate()
called when set as currently active map tool
int dataDefinedColumnIndex(int propertyKey, const QgsPropertyCollection &properties, const QgsVectorLayer *vlayer) const
Returns data defined property column index for the propertyKey from properties associated to the laye...
virtual void deactivate()
called when map tool is being deactivated
A marker symbol type, for rendering Point and MultiPoint geometries.
A dialog to create a new auxiliary layer.
@ Edge
Snapped to an edge.
Represents a 2D point.
Definition qgspointxy.h:62
double y
Definition qgspointxy.h:66
double x
Definition qgspointxy.h:65
A grouped map of multiple QgsProperty objects, each referenced by an integer key value.
A button for controlling property overrides which may apply to a widget.
void changed()
Emitted when property definition changes.
A store for object properties.
Contains information about the context of a rendering operation.
double convertToPainterUnits(double size, Qgis::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::RenderSubcomponentProperty property=Qgis::RenderSubcomponentProperty::Generic) const
Converts a size from the specified units to painter units (pixels).
static QgsRenderContext fromMapSettings(const QgsMapSettings &mapSettings)
create initialized QgsRenderContext instance from given QgsMapSettings
Responsible for drawing transient features (e.g.
QgsRubberBand(QgsMapCanvas *mapCanvas, Qgis::GeometryType geometryType=Qgis::GeometryType::Line)
Creates a new RubberBand.
void setWidth(double width)
Sets the width of the line.
void reset(Qgis::GeometryType geometryType=Qgis::GeometryType::Line)
Clears all the geometries in this rubberband.
void setStrokeColor(const QColor &color)
Sets the stroke color for the rubberband.
QgsSymbol * symbol() const
Returns the symbol used for rendering the rubberband, if set.
void setFillColor(const QColor &color)
Sets the fill color for the rubberband.
void addPoint(const QgsPointXY &p, bool doUpdate=true, int geometryIndex=0, int ringIndex=0)
Adds a vertex to the rubberband and update canvas.
@ ExtraItems
String list of tuple (x, y and rotation angle) to define extra items to be rendered for templated lin...
Base class for templated line symbols, e.g.
Represents a vector layer which manages a vector based dataset.
Represent a 2-dimensional vector.
Definition qgsvector.h:34
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
Definition qgis.h:7109
#define FID_NULL
#define FID_IS_NULL(fid)
#define QgsDebugError(str)
Definition qgslogger.h:59
QgsFeatureId featureId() const
The id of the feature to which the snapped geometry belongs.