QGIS API Documentation 3.41.0-Master (fda2aa46e9a)
Loading...
Searching...
No Matches
qgslayoutviewtooladdnodeitem.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgslayoutviewtooladdnodeitem.cpp
3 ----------------------------
4 Date : July 2017
5 Copyright : (C) 2017 Nyall Dawson
6 Email : nyall dot dawson at gmail 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
17#include "moc_qgslayoutviewtooladdnodeitem.cpp"
18#include "qgsapplication.h"
19#include "qgslayoutview.h"
20#include "qgslayout.h"
23#include "qgslogger.h"
25#include "qgsgui.h"
28#include "qgssettings.h"
29#include "qgslayoututils.h"
31#include <QGraphicsRectItem>
32#include <QPen>
33#include <QBrush>
34#include <QMouseEvent>
35
42
44{
45 mItemMetadataId = metadataId;
46}
47
49{
50 if ( event->button() == Qt::LeftButton )
51 {
52 if ( !mRubberBand )
53 {
54 mPolygon.clear();
55 mRubberBand.reset( QgsGui::layoutItemGuiRegistry()->createNodeItemRubberBand( mItemMetadataId, view() ) );
56 if ( mRubberBand )
57 layout()->addItem( mRubberBand.get() );
58 }
59
60 if ( mRubberBand )
61 {
62 //add a new node
63 addNode( event->snappedPoint() );
64 }
65 }
66 else if ( event->button() == Qt::RightButton && mRubberBand )
67 {
68 // finish up
69
70 // last (temporary) point is removed
71 mPolygon.remove( mPolygon.count() - 1 );
72
73 std::unique_ptr< QgsLayoutItem > item( QgsGui::layoutItemGuiRegistry()->createItem( mItemMetadataId, layout() ) );
74 if ( !item )
75 return;
76
77 if ( QgsLayoutNodesItem *nodesItem = qobject_cast< QgsLayoutNodesItem * >( item.get() ) )
78 {
79 nodesItem->setNodes( mPolygon );
80 if ( !nodesItem->isValid() )
81 {
82 mRubberBand.reset();
83 return;
84 }
85 }
86 QgsLayoutItem *newItem = item.get();
87 layout()->addLayoutItem( item.release() );
88 layout()->setSelectedItem( newItem );
89 emit createdItem();
90 }
91 else
92 {
93 event->ignore();
94 mRubberBand.reset();
95 }
96
97}
98
100{
101 if ( mRubberBand )
102 {
103 moveTemporaryNode( event->snappedPoint(), event->modifiers() );
104 }
105 else
106 {
107 event->ignore();
108 }
109}
110
112{
113 if ( !mRubberBand )
114 {
115 event->ignore();
116 return;
117 }
118}
119
121{
122 if ( !mRubberBand || event->isAutoRepeat() )
123 {
124 event->ignore();
125 return;
126 }
127
128 if ( event->key() == Qt::Key_Delete || event->key() == Qt::Key_Backspace )
129 {
130 if ( mPolygon.size() > 2 )
131 {
132 //remove last added vertex
133 mPolygon.pop_back();
134 setRubberBandNodes();
135 }
136 else
137 {
138 // all deleted, cancel
139 mRubberBand.reset();
140 }
141 }
142 else if ( event->key() == Qt::Key_Escape )
143 {
144 mRubberBand.reset();
145 }
146 else
147 {
148 event->ignore();
149 }
150}
151
153{
154 if ( mRubberBand )
155 {
156 // canceled mid operation
157 mRubberBand.reset();
158 }
160}
161
162void QgsLayoutViewToolAddNodeItem::addNode( QPointF scenePoint )
163{
164 mPolygon.append( scenePoint );
165
166 if ( mPolygon.size() == 1 )
167 mPolygon.append( scenePoint );
168
169 setRubberBandNodes();
170}
171
172void QgsLayoutViewToolAddNodeItem::moveTemporaryNode( QPointF scenePoint, Qt::KeyboardModifiers modifiers )
173{
174 if ( mPolygon.isEmpty() )
175 return;
176
177 if ( mPolygon.size() > 1 && ( modifiers & Qt::ShiftModifier ) )
178 {
179 const QPointF start = mPolygon.at( mPolygon.size() - 2 );
180 QLineF newLine = QLineF( start, scenePoint );
181
182 //movement is constrained to 45 degree angles
183 const double angle = QgsLayoutUtils::snappedAngle( newLine.angle() );
184 newLine.setAngle( angle );
185 scenePoint = newLine.p2();
186 }
187
188 mPolygon.replace( mPolygon.size() - 1, scenePoint );
189 setRubberBandNodes();
190}
191
192void QgsLayoutViewToolAddNodeItem::setRubberBandNodes()
193{
194 if ( QGraphicsPolygonItem *polygonItem = dynamic_cast< QGraphicsPolygonItem *>( mRubberBand.get() ) )
195 {
196 polygonItem->setPolygon( mPolygon );
197 }
198 else if ( QGraphicsPathItem *polylineItem = dynamic_cast< QGraphicsPathItem *>( mRubberBand.get() ) )
199 {
200 // rebuild a new qpainter path
201 QPainterPath path;
202 path.addPolygon( mPolygon );
203 polylineItem->setPath( path );
204 }
205}
206
208{
209 return mItemMetadataId;
210}
static QgsLayoutItemGuiRegistry * layoutItemGuiRegistry()
Returns the global layout item GUI registry, used for registering the GUI behavior of layout items.
Definition qgsgui.cpp:139
Base class for graphical items within a QgsLayout.
An abstract layout item that provides generic methods for node based shapes such as polygon or polyli...
static double snappedAngle(double angle)
Snaps an angle (in degrees) to its closest 45 degree angle.
A QgsLayoutViewMouseEvent is the result of a user interaction with the mouse on a QgsLayoutView.
QPointF snappedPoint() const
Returns the snapped event point location in layout coordinates.
void layoutMoveEvent(QgsLayoutViewMouseEvent *event) override
Mouse move event for overriding.
int itemMetadataId() const
Returns the item metadata id for items created by the tool.
void createdItem()
Emitted when an item has been created using the tool.
void layoutReleaseEvent(QgsLayoutViewMouseEvent *event) override
Mouse release event for overriding.
QgsLayoutViewToolAddNodeItem(QgsLayoutView *view)
Constructs a QgsLayoutViewToolAddNodeItem for the given layout view.
void setItemMetadataId(int metadataId)
Sets the item metadata metadataId for items created by the tool.
void keyPressEvent(QKeyEvent *event) override
Key press event for overriding.
void layoutPressEvent(QgsLayoutViewMouseEvent *event) override
Mouse press event for overriding.
void deactivate() override
Called when tool is deactivated.
Abstract base class for all layout view tools.
void setCursor(const QCursor &cursor)
Sets a user defined cursor for use when the tool is active.
QgsLayoutView * view() const
Returns the view associated with the tool.
virtual void deactivate()
Called when tool is deactivated.
void setFlags(QgsLayoutViewTool::Flags flags)
Sets the combination of flags that will be used for the tool.
@ FlagSnaps
Tool utilizes snapped coordinates.
QgsLayout * layout() const
Returns the layout associated with the tool.
A graphical widget to display and interact with QgsLayouts.
void setSelectedItem(QgsLayoutItem *item)
Clears any selected items and sets item as the current selection.
void addLayoutItem(QgsLayoutItem *item)
Adds an item to the layout.
double ANALYSIS_EXPORT angle(QgsPoint *p1, QgsPoint *p2, QgsPoint *p3, QgsPoint *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)