QGIS API Documentation 3.28.0-Firenze (ed3ad0430f)
qgslayoutviewtooleditnodes.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgslayoutviewtooleditnodes.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
18#include "qgslayoutview.h"
19#include "qgslayout.h"
21#include "qgslayoutundostack.h"
22
24 : QgsLayoutViewTool( view, tr( "Select" ) )
25{
26 setCursor( Qt::CrossCursor );
28}
29
31{
32 if ( mNodesItem && mNodesItemIndex != -1 )
33 {
34 layout()->undoStack()->beginCommand( mNodesItem, tr( "Remove Item Node" ) );
35 if ( mNodesItem->removeNode( mNodesItemIndex ) )
36 {
38 if ( mNodesItem->nodesSize() > 0 )
39 {
40 mNodesItemIndex = mNodesItem->selectedNode();
41 // setSelectedNode( mNodesItem, mNodesItemIndex );
42 }
43 else
44 {
45 mNodesItemIndex = -1;
46 mNodesItem = nullptr;
47 }
48 if ( mNodesItem )
49 mNodesItem->update();
50 }
51 else
52 {
54 }
55 }
56}
57
59{
60 displayNodes( true );
62}
63
65{
66 if ( event->button() != Qt::LeftButton )
67 {
68 event->ignore();
69 return;
70 }
71
72 const QList<QGraphicsItem *> itemsAtCursorPos = view()->items( event->pos().x(), event->pos().y(),
73 mMoveContentSearchRadius,
74 mMoveContentSearchRadius );
75 if ( itemsAtCursorPos.isEmpty() )
76 return;
77
78 mNodesItemIndex = -1;
79 mNodesItem = nullptr;
80 isMoving = false;
81
82 for ( QGraphicsItem *graphicsItem : itemsAtCursorPos )
83 {
84 QgsLayoutNodesItem *item = dynamic_cast<QgsLayoutNodesItem *>( graphicsItem );
85
86 if ( item && !item->isLocked() )
87 {
88 int index = item->nodeAtPosition( event->layoutPoint() );
89 if ( index != -1 )
90 {
91 mNodesItemIndex = index;
92 mNodesItem = item;
93 mMoveContentStartPos = event->layoutPoint();
94 }
95 }
96
97 if ( mNodesItem && mNodesItemIndex != -1 )
98 {
99 layout()->undoStack()->beginCommand( mNodesItem, tr( "Move Item Node" ) );
100 setSelectedNode( mNodesItem, mNodesItemIndex );
101 isMoving = true;
102 break;
103 }
104 }
105}
106
108{
109 if ( !isMoving )
110 {
111 event->ignore();
112 return;
113 }
114
115 if ( mNodesItem && mNodesItemIndex != -1 && event->layoutPoint() != mMoveContentStartPos )
116 {
117 mNodesItem->moveNode( mNodesItemIndex, event->snappedPoint() );
118 }
119}
120
122{
123 if ( event->button() != Qt::LeftButton || !isMoving )
124 {
125 event->ignore();
126 return;
127 }
128
129 isMoving = false;
130 if ( mNodesItemIndex != -1 )
131 {
132 if ( event->layoutPoint() != mMoveContentStartPos )
133 {
135 }
136 else
137 {
139 }
140 }
141}
142
144{
145 if ( event->button() != Qt::LeftButton )
146 {
147 event->ignore();
148 return;
149 }
150
151 // erase status previously set by the mousePressEvent method
152 if ( mNodesItemIndex != -1 )
153 {
154 mNodesItem = nullptr;
155 mNodesItemIndex = -1;
156 deselectNodes();
157 }
158
159 // search items in layout
160 const QList<QGraphicsItem *> itemsAtCursorPos = view()->items( event->pos().x(), event->pos().y(),
161 mMoveContentSearchRadius,
162 mMoveContentSearchRadius );
163
164 if ( itemsAtCursorPos.isEmpty() )
165 return;
166
167 bool rc = false;
168 for ( QGraphicsItem *graphicsItem : itemsAtCursorPos )
169 {
170 QgsLayoutNodesItem *item = dynamic_cast<QgsLayoutNodesItem *>( graphicsItem );
171
172 if ( item && !item->isLocked() )
173 {
174 layout()->undoStack()->beginCommand( item, tr( "Add Item Node" ) );
175 rc = item->addNode( event->layoutPoint() );
176
177 if ( rc )
178 {
180 mNodesItem = item;
181 mNodesItemIndex = mNodesItem->nodeAtPosition( event->layoutPoint() );
182 }
183 else
185 }
186
187 if ( rc )
188 break;
189 }
190
191 if ( rc )
192 {
193 setSelectedNode( mNodesItem, mNodesItemIndex );
194 mNodesItem->update();
195 }
196}
197
199{
200 if ( mNodesItem && mNodesItemIndex != -1 && ( event->key() == Qt::Key_Left
201 || event->key() == Qt::Key_Right
202 || event->key() == Qt::Key_Up
203 || event->key() == Qt::Key_Down ) )
204 {
205 QPointF currentPos;
206
207 if ( mNodesItem->nodePosition( mNodesItemIndex, currentPos ) )
208 {
209 QPointF delta = view()->deltaForKeyEvent( event );
210
211 currentPos.setX( currentPos.x() + delta.x() );
212 currentPos.setY( currentPos.y() + delta.y() );
213
214 layout()->undoStack()->beginCommand( mNodesItem, tr( "Move Item Node" ), QgsLayoutItem::UndoNodeMove );
215 mNodesItem->moveNode( mNodesItemIndex, currentPos );
217 layout()->update();
218 }
219 }
220 else
221 {
222 event->ignore();
223 }
224}
225
227{
228 displayNodes( false );
229 deselectNodes();
231}
232
234{
235 QList< QgsLayoutItem * > items;
236 if ( mNodesItem )
237 items << mNodesItem;
238 return items;
239}
240
241void QgsLayoutViewToolEditNodes::displayNodes( bool display )
242{
243 QList<QgsLayoutNodesItem *> nodesShapes;
244 layout()->layoutItems( nodesShapes );
245
246 for ( QgsLayoutNodesItem *item : std::as_const( nodesShapes ) )
247 {
248 item->setDisplayNodes( display );
249 item->update();
250 }
251}
252
253void QgsLayoutViewToolEditNodes::deselectNodes()
254{
255 QList<QgsLayoutNodesItem *> nodesShapes;
256 layout()->layoutItems( nodesShapes );
257
258 for ( QgsLayoutNodesItem *item : std::as_const( nodesShapes ) )
259 {
260 item->deselectNode();
261 item->update();
262 }
263}
264
265void QgsLayoutViewToolEditNodes::setSelectedNode( QgsLayoutNodesItem *shape, int index )
266{
267 QList<QgsLayoutNodesItem *> nodesShapes;
268 layout()->layoutItems( nodesShapes );
269
270 for ( QgsLayoutNodesItem *item : std::as_const( nodesShapes ) )
271 {
272 if ( item == shape )
273 {
274 item->setSelectedNode( index );
275 layout()->setSelectedItem( item );
276 item->update();
277 }
278 else
279 {
280 item->deselectNode();
281 item->update();
282 }
283 }
284
285}
286
@ UndoNodeMove
Node move.
bool isLocked() const
Returns true if the item is locked, and cannot be interacted with using the mouse.
An abstract layout item that provides generic methods for node based shapes such as polygon or polyli...
bool addNode(QPointF point, bool checkArea=true, double radius=10)
Add a node in current shape.
int nodeAtPosition(QPointF point, bool searchInRadius=true, double radius=10) const
Search for the nearest node in the shape within a maximal area.
void endCommand()
Saves final state of an object and pushes the active command to the undo history.
void cancelCommand()
Cancels the active command, discarding it without pushing to the undo history.
void beginCommand(QgsLayoutUndoObjectInterface *object, const QString &commandText, int id=0)
Begins a new undo command for the specified object.
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.
QPointF layoutPoint() const
Returns the event point location in layout coordinates.
void layoutMoveEvent(QgsLayoutViewMouseEvent *event) override
Mouse move event for overriding.
void layoutDoubleClickEvent(QgsLayoutViewMouseEvent *event) override
Mouse double-click event for overriding.
void activate() override
Called when tool is set as the currently active layout tool.
QList< QgsLayoutItem * > ignoredSnapItems() const override
Returns a list of items which should be ignored while snapping events for this tool.
void layoutPressEvent(QgsLayoutViewMouseEvent *event) override
Mouse press event for overriding.
QgsLayoutViewToolEditNodes(QgsLayoutView *view)
Constructor for QgsLayoutViewToolEditNodes.
void keyPressEvent(QKeyEvent *event) override
Key press event for overriding.
void layoutReleaseEvent(QgsLayoutViewMouseEvent *event) override
Mouse release event for overriding.
void deactivate() override
Called when tool is deactivated.
void deleteSelectedNode()
Deletes the selected node from the item.
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.
virtual void activate()
Called when tool is set as the currently active layout tool.
QgsLayout * layout() const
Returns the layout associated with the tool.
A graphical widget to display and interact with QgsLayouts.
Definition: qgslayoutview.h:51
QPointF deltaForKeyEvent(QKeyEvent *event)
Returns the delta (in layout coordinates) by which to move items for the given key event.
void layoutItems(QList< T * > &itemList) const
Returns a list of layout items of a specific type.
Definition: qgslayout.h:122
void setSelectedItem(QgsLayoutItem *item)
Clears any selected items and sets item as the current selection.
Definition: qgslayout.cpp:159
QgsLayoutUndoStack * undoStack()
Returns a pointer to the layout's undo stack, which manages undo/redo states for the layout and it's ...
Definition: qgslayout.cpp:686