Skip to content

Commit e0089fb

Browse files
committed
Move mouse handles to select tool
1 parent bfa9c1d commit e0089fb

7 files changed

+168
-60
lines changed

python/gui/layout/qgslayoutview.sip

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,6 @@ class QgsLayoutView: QGraphicsView
127127
:rtype: list of int
128128
%End
129129

130-
131-
132130
public slots:
133131

134132
void zoomFull();

python/gui/layout/qgslayoutviewtoolselect.sip

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99

1010

11+
1112
class QgsLayoutViewToolSelect : QgsLayoutViewTool
1213
{
1314
%Docstring
@@ -31,9 +32,17 @@ class QgsLayoutViewToolSelect : QgsLayoutViewTool
3132

3233
virtual void layoutReleaseEvent( QgsLayoutViewMouseEvent *event );
3334

35+
virtual void wheelEvent( QWheelEvent *event );
36+
37+
virtual void keyPressEvent( QKeyEvent *event );
38+
3439
virtual void deactivate();
3540

3641

42+
43+
44+
void setLayout( QgsLayout *layout );
45+
3746
};
3847

3948
/************************************************************************

src/app/layout/qgslayoutdesignerdialog.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,8 @@ void QgsLayoutDesignerDialog::setCurrentLayout( QgsLayout *layout )
352352
connect( mActionRedo, &QAction::triggered, mLayout->undoStack()->stack(), &QUndoStack::redo );
353353
mUndoView->setStack( mLayout->undoStack()->stack() );
354354

355+
mSelectTool->setLayout( layout );
356+
355357
createLayoutPropertiesWidget();
356358
}
357359

@@ -440,7 +442,7 @@ void QgsLayoutDesignerDialog::showGrid( bool visible )
440442
void QgsLayoutDesignerDialog::showBoxes( bool visible )
441443
{
442444
mLayout->context().setBoundingBoxesVisible( visible );
443-
mView->mouseHandles()->update();
445+
mSelectTool->mouseHandles()->update();
444446
}
445447

446448
void QgsLayoutDesignerDialog::snapToGrid( bool enabled )

src/gui/layout/qgslayoutview.cpp

Lines changed: 0 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -89,12 +89,6 @@ void QgsLayoutView::setCurrentLayout( QgsLayout *layout )
8989
connect( &layout->guides(), &QAbstractItemModel::modelReset, mVerticalRuler, [ = ] { mVerticalRuler->update(); } );
9090
}
9191

92-
//add mouse selection handles to layout, and initially hide
93-
mMouseHandles = new QgsLayoutMouseHandles( layout, this );
94-
mMouseHandles->hide();
95-
mMouseHandles->setZValue( QgsLayout::ZMouseHandles );
96-
layout->addItem( mMouseHandles );
97-
9892
//emit layoutSet, so that designer dialogs can update for the new layout
9993
emit layoutSet( layout );
10094
}
@@ -220,13 +214,6 @@ QList<int> QgsLayoutView::visiblePageNumbers() const
220214
return currentLayout()->pageCollection()->visiblePageNumbers( visibleRect );
221215
}
222216

223-
///@cond PRIVATE
224-
QgsLayoutMouseHandles *QgsLayoutView::mouseHandles()
225-
{
226-
return mMouseHandles;
227-
}
228-
///@endcond
229-
230217
void QgsLayoutView::zoomFull()
231218
{
232219
fitInView( scene()->sceneRect(), Qt::KeepAspectRatio );
@@ -280,17 +267,6 @@ void QgsLayoutView::mousePressEvent( QMouseEvent *event )
280267
{
281268
mSnapMarker->setVisible( false );
282269

283-
if ( mMouseHandles->shouldBlockEvent( event ) )
284-
{
285-
//ignore clicks while dragging/resizing items
286-
return;
287-
}
288-
else if ( mMouseHandles->isVisible() )
289-
{
290-
QGraphicsView::mousePressEvent( event );
291-
return;
292-
}
293-
294270
if ( mTool )
295271
{
296272
std::unique_ptr<QgsLayoutViewMouseEvent> me( new QgsLayoutViewMouseEvent( this, event, mTool->flags() & QgsLayoutViewTool::FlagSnaps ) );
@@ -324,13 +300,6 @@ void QgsLayoutView::mousePressEvent( QMouseEvent *event )
324300

325301
void QgsLayoutView::mouseReleaseEvent( QMouseEvent *event )
326302
{
327-
if ( event->button() != Qt::LeftButton &&
328-
mMouseHandles->shouldBlockEvent( event ) )
329-
{
330-
//ignore clicks while dragging/resizing items
331-
return;
332-
}
333-
334303
if ( mTool )
335304
{
336305
std::unique_ptr<QgsLayoutViewMouseEvent> me( new QgsLayoutViewMouseEvent( this, event, mTool->flags() & QgsLayoutViewTool::FlagSnaps ) );
@@ -388,12 +357,6 @@ void QgsLayoutView::mouseDoubleClickEvent( QMouseEvent *event )
388357

389358
void QgsLayoutView::wheelEvent( QWheelEvent *event )
390359
{
391-
if ( mMouseHandles->shouldBlockEvent( event ) )
392-
{
393-
//ignore wheel events while dragging/resizing items
394-
return;
395-
}
396-
397360
if ( mTool )
398361
{
399362
mTool->wheelEvent( event );
@@ -408,11 +371,6 @@ void QgsLayoutView::wheelEvent( QWheelEvent *event )
408371

409372
void QgsLayoutView::keyPressEvent( QKeyEvent *event )
410373
{
411-
if ( mMouseHandles->isDragging() || mMouseHandles->isResizing() )
412-
{
413-
return;
414-
}
415-
416374
if ( mTool )
417375
{
418376
mTool->keyPressEvent( event );

src/gui/layout/qgslayoutview.h

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ class QgsLayoutViewToolTemporaryMousePan;
3535
class QgsLayoutRuler;
3636
class QgsLayoutViewMenuProvider;
3737
class QgsLayoutViewSnapMarker;
38-
class QgsLayoutMouseHandles;
3938

4039
/**
4140
* \ingroup gui
@@ -158,15 +157,6 @@ class GUI_EXPORT QgsLayoutView: public QGraphicsView
158157
*/
159158
QList< int > visiblePageNumbers() const;
160159

161-
///@cond PRIVATE
162-
163-
/**
164-
* Returns the view's mouse handles.
165-
* \note Not available in Python bindings.
166-
*/
167-
SIP_SKIP QgsLayoutMouseHandles *mouseHandles();
168-
///@endcond
169-
170160
public slots:
171161

172162
/**
@@ -310,8 +300,6 @@ class GUI_EXPORT QgsLayoutView: public QGraphicsView
310300

311301
std::unique_ptr< QgsLayoutViewSnapMarker > mSnapMarker;
312302

313-
QgsLayoutMouseHandles *mMouseHandles = nullptr; //owned by scene
314-
315303
int mCurrentPage = 0;
316304

317305
friend class TestQgsLayoutView;

src/gui/layout/qgslayoutviewtoolselect.cpp

Lines changed: 140 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "qgslayoutview.h"
1919
#include "qgslayout.h"
2020
#include "qgslayoutitempage.h"
21+
#include "qgslayoutmousehandles.h"
2122

2223
QgsLayoutViewToolSelect::QgsLayoutViewToolSelect( QgsLayoutView *view )
2324
: QgsLayoutViewTool( view, tr( "Select" ) )
@@ -31,15 +32,102 @@ QgsLayoutViewToolSelect::QgsLayoutViewToolSelect( QgsLayoutView *view )
3132

3233
void QgsLayoutViewToolSelect::layoutPressEvent( QgsLayoutViewMouseEvent *event )
3334
{
35+
if ( mMouseHandles->shouldBlockEvent( event ) )
36+
{
37+
//swallow clicks while dragging/resizing items
38+
return;
39+
}
40+
41+
if ( mMouseHandles->isVisible() )
42+
{
43+
//selection handles are being shown, get mouse action for current cursor position
44+
QgsLayoutMouseHandles::MouseAction mouseAction = mMouseHandles->mouseActionForScenePos( event->layoutPoint() );
45+
46+
if ( mouseAction != QgsLayoutMouseHandles::MoveItem
47+
&& mouseAction != QgsLayoutMouseHandles::NoAction
48+
&& mouseAction != QgsLayoutMouseHandles::SelectItem )
49+
{
50+
//mouse is over a resize handle, so propagate event onward
51+
event->ignore();
52+
return;
53+
}
54+
}
55+
3456
if ( event->button() != Qt::LeftButton )
3557
{
3658
event->ignore();
3759
return;
3860
}
3961

40-
mIsSelecting = true;
41-
mMousePressStartPos = event->pos();
42-
mRubberBand->start( event->layoutPoint(), 0 );
62+
QgsLayoutItem *selectedItem = nullptr;
63+
QgsLayoutItem *previousSelectedItem = nullptr;
64+
65+
if ( event->modifiers() & Qt::ControlModifier )
66+
{
67+
//CTRL modifier, so we are trying to select the next item below the current one
68+
//first, find currently selected item
69+
QList<QgsLayoutItem *> selectedItems = layout()->selectedLayoutItems();
70+
if ( !selectedItems.isEmpty() )
71+
{
72+
previousSelectedItem = selectedItems.at( 0 );
73+
}
74+
}
75+
76+
if ( previousSelectedItem )
77+
{
78+
//select highest item just below previously selected item at position of event
79+
selectedItem = layout()->layoutItemAt( event->layoutPoint(), previousSelectedItem, true );
80+
81+
//if we didn't find a lower item we'll use the top-most as fall-back
82+
//this duplicates mapinfo/illustrator/etc behavior where ctrl-clicks are "cyclic"
83+
if ( !selectedItem )
84+
{
85+
selectedItem = layout()->layoutItemAt( event->layoutPoint(), true );
86+
}
87+
}
88+
else
89+
{
90+
//select topmost item at position of event
91+
selectedItem = layout()->layoutItemAt( event->layoutPoint(), true );
92+
}
93+
94+
if ( !selectedItem )
95+
{
96+
//not clicking over an item, so start marquee selection
97+
mIsSelecting = true;
98+
mMousePressStartPos = event->pos();
99+
mRubberBand->start( event->layoutPoint(), 0 );
100+
return;
101+
}
102+
103+
if ( ( !selectedItem->isSelected() ) && //keep selection if an already selected item pressed
104+
!( event->modifiers() & Qt::ShiftModifier ) ) //keep selection if shift key pressed
105+
{
106+
layout()->deselectAll();
107+
}
108+
109+
if ( ( event->modifiers() & Qt::ShiftModifier ) && ( selectedItem->isSelected() ) )
110+
{
111+
//SHIFT-clicking a selected item deselects it
112+
selectedItem->setSelected( false );
113+
114+
//Check if we have any remaining selected items, and if so, update the item panel
115+
QList<QgsLayoutItem *> selectedItems = layout()->selectedLayoutItems();
116+
if ( !selectedItems.isEmpty() )
117+
{
118+
#if 0 //TODO
119+
emit selectedItemChanged( selectedItems.at( 0 ) );
120+
#endif
121+
}
122+
}
123+
else
124+
{
125+
selectedItem->setSelected( true );
126+
event->ignore();
127+
#if 0 //TODO
128+
emit selectedItemChanged( selectedItem );
129+
#endif
130+
}
43131
}
44132

45133
void QgsLayoutViewToolSelect::layoutMoveEvent( QgsLayoutViewMouseEvent *event )
@@ -56,6 +144,12 @@ void QgsLayoutViewToolSelect::layoutMoveEvent( QgsLayoutViewMouseEvent *event )
56144

57145
void QgsLayoutViewToolSelect::layoutReleaseEvent( QgsLayoutViewMouseEvent *event )
58146
{
147+
if ( event->button() != Qt::LeftButton && mMouseHandles->shouldBlockEvent( event ) )
148+
{
149+
//swallow clicks while dragging/resizing items
150+
return;
151+
}
152+
59153
if ( !mIsSelecting || event->button() != Qt::LeftButton )
60154
{
61155
event->ignore();
@@ -132,6 +226,31 @@ void QgsLayoutViewToolSelect::layoutReleaseEvent( QgsLayoutViewMouseEvent *event
132226
#endif
133227
}
134228

229+
void QgsLayoutViewToolSelect::wheelEvent( QWheelEvent *event )
230+
{
231+
if ( mMouseHandles->shouldBlockEvent( event ) )
232+
{
233+
//ignore wheel events while dragging/resizing items
234+
return;
235+
}
236+
else
237+
{
238+
event->ignore();
239+
}
240+
}
241+
242+
void QgsLayoutViewToolSelect::keyPressEvent( QKeyEvent *event )
243+
{
244+
if ( mMouseHandles->isDragging() || mMouseHandles->isResizing() )
245+
{
246+
return;
247+
}
248+
else
249+
{
250+
event->ignore();
251+
}
252+
}
253+
135254
void QgsLayoutViewToolSelect::deactivate()
136255
{
137256
if ( mIsSelecting )
@@ -141,3 +260,21 @@ void QgsLayoutViewToolSelect::deactivate()
141260
}
142261
QgsLayoutViewTool::deactivate();
143262
}
263+
264+
///@cond PRIVATE
265+
QgsLayoutMouseHandles *QgsLayoutViewToolSelect::mouseHandles()
266+
{
267+
return mMouseHandles;
268+
}
269+
270+
void QgsLayoutViewToolSelect::setLayout( QgsLayout *layout )
271+
{
272+
// existing handles are owned by previous layout
273+
274+
//add mouse selection handles to layout, and initially hide
275+
mMouseHandles = new QgsLayoutMouseHandles( layout, view() );
276+
mMouseHandles->hide();
277+
mMouseHandles->setZValue( QgsLayout::ZMouseHandles );
278+
layout->addItem( mMouseHandles );
279+
}
280+
///@endcond

src/gui/layout/qgslayoutviewtoolselect.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
#include "qgslayoutviewrubberband.h"
2323
#include <memory>
2424

25+
class QgsLayoutMouseHandles;
26+
2527
/**
2628
* \ingroup gui
2729
* Layout view tool for selecting items in the layout.
@@ -42,8 +44,21 @@ class GUI_EXPORT QgsLayoutViewToolSelect : public QgsLayoutViewTool
4244
void layoutPressEvent( QgsLayoutViewMouseEvent *event ) override;
4345
void layoutMoveEvent( QgsLayoutViewMouseEvent *event ) override;
4446
void layoutReleaseEvent( QgsLayoutViewMouseEvent *event ) override;
47+
void wheelEvent( QWheelEvent *event ) override;
48+
void keyPressEvent( QKeyEvent *event ) override;
4549
void deactivate() override;
4650

51+
///@cond PRIVATE
52+
53+
/**
54+
* Returns the view's mouse handles.
55+
* \note Not available in Python bindings.
56+
*/
57+
SIP_SKIP QgsLayoutMouseHandles *mouseHandles();
58+
///@endcond
59+
60+
void setLayout( QgsLayout *layout );
61+
4762
private:
4863

4964
bool mIsSelecting = false;
@@ -57,6 +72,7 @@ class GUI_EXPORT QgsLayoutViewToolSelect : public QgsLayoutViewTool
5772
//! Start of rubber band creation
5873
QPointF mRubberBandStartPos;
5974

75+
QgsLayoutMouseHandles *mMouseHandles = nullptr; //owned by scene
6076
};
6177

6278
#endif // QGSLAYOUTVIEWTOOLSELECT_H

0 commit comments

Comments
 (0)