mirror of
https://github.com/qgis/QGIS.git
synced 2025-11-22 00:14:55 -05:00
Add search tolerance to QgsLayoutViewToolSelect
This commit is contained in:
parent
c431054d84
commit
8f3676dd80
@ -237,16 +237,20 @@ Note that template UUIDs are only available while a layout is being restored fro
|
||||
.. seealso:: :py:func:`itemByUuid`
|
||||
%End
|
||||
|
||||
QgsLayoutItem *layoutItemAt( QPointF position, bool ignoreLocked = false ) const;
|
||||
QgsLayoutItem *layoutItemAt( QPointF position, bool ignoreLocked = false, double searchTolerance = 0 ) const;
|
||||
%Docstring
|
||||
Returns the topmost layout item at a specified ``position``. Ignores paper items.
|
||||
If ``ignoreLocked`` is set to ``True`` any locked items will be ignored.
|
||||
|
||||
.. versionadded:: 3.32
|
||||
%End
|
||||
|
||||
QgsLayoutItem *layoutItemAt( QPointF position, const QgsLayoutItem *belowItem, bool ignoreLocked = false ) const;
|
||||
QgsLayoutItem *layoutItemAt( QPointF position, const QgsLayoutItem *belowItem, bool ignoreLocked = false, double searchTolerance = 0 ) const;
|
||||
%Docstring
|
||||
Returns the topmost layout item at a specified ``position`` which is below a specified ``item``. Ignores paper items.
|
||||
If ``ignoreLocked`` is set to ``True`` any locked items will be ignored.
|
||||
|
||||
.. versionadded:: 3.32
|
||||
%End
|
||||
|
||||
void setUnits( Qgis::LayoutUnit units );
|
||||
|
||||
@ -46,6 +46,13 @@ Constructor for QgsLayoutViewToolSelect.
|
||||
void setLayout( QgsLayout *layout );
|
||||
%Docstring
|
||||
Sets the a ``layout``.
|
||||
%End
|
||||
|
||||
double searchToleranceInLayoutUnits();
|
||||
%Docstring
|
||||
Compute the search tolerance in layout units from the view current scale
|
||||
|
||||
.. versionadded:: 3.34
|
||||
%End
|
||||
|
||||
};
|
||||
|
||||
@ -298,15 +298,23 @@ QgsLayoutMultiFrame *QgsLayout::multiFrameByUuid( const QString &uuid, bool incl
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QgsLayoutItem *QgsLayout::layoutItemAt( QPointF position, const bool ignoreLocked ) const
|
||||
QgsLayoutItem *QgsLayout::layoutItemAt( QPointF position, const bool ignoreLocked, double searchTolerance ) const
|
||||
{
|
||||
return layoutItemAt( position, nullptr, ignoreLocked );
|
||||
return layoutItemAt( position, nullptr, ignoreLocked, searchTolerance );
|
||||
}
|
||||
|
||||
QgsLayoutItem *QgsLayout::layoutItemAt( QPointF position, const QgsLayoutItem *belowItem, const bool ignoreLocked ) const
|
||||
QgsLayoutItem *QgsLayout::layoutItemAt( QPointF position, const QgsLayoutItem *belowItem, const bool ignoreLocked, double searchTolerance ) const
|
||||
{
|
||||
//get a list of items which intersect the specified position, in descending z order
|
||||
const QList<QGraphicsItem *> itemList = items( position, Qt::IntersectsItemShape, Qt::DescendingOrder );
|
||||
QList<QGraphicsItem *> itemList;
|
||||
if ( searchTolerance == 0 )
|
||||
{
|
||||
itemList = items( position, Qt::IntersectsItemShape, Qt::DescendingOrder );
|
||||
}
|
||||
else
|
||||
{
|
||||
itemList = items( QRectF( position.x() - searchTolerance, position.y() - searchTolerance, 2 * searchTolerance, 2 * searchTolerance ), Qt::IntersectsItemShape, Qt::DescendingOrder );
|
||||
}
|
||||
|
||||
bool foundBelowItem = false;
|
||||
for ( QGraphicsItem *graphicsItem : itemList )
|
||||
|
||||
@ -303,14 +303,16 @@ class CORE_EXPORT QgsLayout : public QGraphicsScene, public QgsExpressionContext
|
||||
/**
|
||||
* Returns the topmost layout item at a specified \a position. Ignores paper items.
|
||||
* If \a ignoreLocked is set to TRUE any locked items will be ignored.
|
||||
* \since QGIS 3.32 searchTolerance parameter was added, which can be used to specify a search tolerance in layout units
|
||||
*/
|
||||
QgsLayoutItem *layoutItemAt( QPointF position, bool ignoreLocked = false ) const;
|
||||
QgsLayoutItem *layoutItemAt( QPointF position, bool ignoreLocked = false, double searchTolerance = 0 ) const;
|
||||
|
||||
/**
|
||||
* Returns the topmost layout item at a specified \a position which is below a specified \a item. Ignores paper items.
|
||||
* If \a ignoreLocked is set to TRUE any locked items will be ignored.
|
||||
* \since QGIS 3.32 searchTolerance parameter was added, which can be used to specify a search tolerance in layout units
|
||||
*/
|
||||
QgsLayoutItem *layoutItemAt( QPointF position, const QgsLayoutItem *belowItem, bool ignoreLocked = false ) const;
|
||||
QgsLayoutItem *layoutItemAt( QPointF position, const QgsLayoutItem *belowItem, bool ignoreLocked = false, double searchTolerance = 0 ) const;
|
||||
|
||||
/**
|
||||
* Sets the native measurement \a units for the layout. These also form the default unit
|
||||
|
||||
@ -99,7 +99,17 @@ void QgsLayoutMouseHandles::setViewportCursor( Qt::CursorShape cursor )
|
||||
|
||||
QList<QGraphicsItem *> QgsLayoutMouseHandles::sceneItemsAtPoint( QPointF scenePoint )
|
||||
{
|
||||
QList< QGraphicsItem * > items = mLayout->items( scenePoint );
|
||||
QList< QGraphicsItem * > items;
|
||||
if ( QgsLayoutViewToolSelect *tool = qobject_cast< QgsLayoutViewToolSelect *>( mView->tool() ) )
|
||||
{
|
||||
const double searchTolerance = tool->searchToleranceInLayoutUnits();
|
||||
const QRectF area( scenePoint.x() - searchTolerance, scenePoint.y() - searchTolerance, 2 * searchTolerance, 2 * searchTolerance );
|
||||
items = mLayout->items( area );
|
||||
}
|
||||
else
|
||||
{
|
||||
items = mLayout->items( scenePoint );
|
||||
}
|
||||
items.erase( std::remove_if( items.begin(), items.end(), []( QGraphicsItem * item )
|
||||
{
|
||||
return !dynamic_cast<QgsLayoutItem *>( item );
|
||||
|
||||
@ -22,6 +22,9 @@
|
||||
#include "qgslayoutitemgroup.h"
|
||||
|
||||
|
||||
const double QgsLayoutViewToolSelect::sSearchToleranceInMillimeters = 2.0;
|
||||
|
||||
|
||||
QgsLayoutViewToolSelect::QgsLayoutViewToolSelect( QgsLayoutView *view )
|
||||
: QgsLayoutViewTool( view, tr( "Select" ) )
|
||||
{
|
||||
@ -94,19 +97,19 @@ void QgsLayoutViewToolSelect::layoutPressEvent( QgsLayoutViewMouseEvent *event )
|
||||
if ( previousSelectedItem )
|
||||
{
|
||||
//select highest item just below previously selected item at position of event
|
||||
selectedItem = layout()->layoutItemAt( event->layoutPoint(), previousSelectedItem, true );
|
||||
selectedItem = layout()->layoutItemAt( event->layoutPoint(), previousSelectedItem, true, searchToleranceInLayoutUnits() );
|
||||
|
||||
//if we didn't find a lower item we'll use the top-most as fall-back
|
||||
//this duplicates mapinfo/illustrator/etc behavior where ctrl-clicks are "cyclic"
|
||||
if ( !selectedItem )
|
||||
{
|
||||
selectedItem = layout()->layoutItemAt( event->layoutPoint(), true );
|
||||
selectedItem = layout()->layoutItemAt( event->layoutPoint(), true, searchToleranceInLayoutUnits() );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//select topmost item at position of event
|
||||
selectedItem = layout()->layoutItemAt( event->layoutPoint(), true );
|
||||
selectedItem = layout()->layoutItemAt( event->layoutPoint(), true, searchToleranceInLayoutUnits() );
|
||||
}
|
||||
|
||||
// if selected item is in a group, we actually get the top-level group it's part of
|
||||
@ -167,6 +170,17 @@ void QgsLayoutViewToolSelect::layoutMoveEvent( QgsLayoutViewMouseEvent *event )
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !mMouseHandles->isDragging() && !mMouseHandles->isResizing() )
|
||||
{
|
||||
if ( layout()->layoutItemAt( event->layoutPoint(), true, searchToleranceInLayoutUnits() ) )
|
||||
{
|
||||
view()->viewport()->setCursor( Qt::SizeAllCursor );
|
||||
}
|
||||
else
|
||||
{
|
||||
view()->viewport()->setCursor( Qt::ArrowCursor );
|
||||
}
|
||||
}
|
||||
event->ignore();
|
||||
}
|
||||
}
|
||||
@ -219,7 +233,10 @@ void QgsLayoutViewToolSelect::layoutReleaseEvent( QgsLayoutViewMouseEvent *event
|
||||
//find all items in rect
|
||||
QList<QGraphicsItem *> itemList;
|
||||
if ( wasClick )
|
||||
itemList = layout()->items( rect.center(), selectionMode );
|
||||
{
|
||||
const double tolerance = searchToleranceInLayoutUnits();
|
||||
itemList = layout()->items( QRectF( rect.center().x() - tolerance, rect.center().y() - tolerance, 2 * tolerance, 2 * tolerance ), selectionMode );
|
||||
}
|
||||
else
|
||||
itemList = layout()->items( rect, selectionMode );
|
||||
|
||||
@ -323,4 +340,9 @@ void QgsLayoutViewToolSelect::setLayout( QgsLayout *layout )
|
||||
mMouseHandles->setZValue( QgsLayout::ZMouseHandles );
|
||||
layout->addItem( mMouseHandles );
|
||||
}
|
||||
double QgsLayoutViewToolSelect::searchToleranceInLayoutUnits()
|
||||
{
|
||||
const double pixelsPerMm = view()->physicalDpiX() / 25.4;
|
||||
return sSearchToleranceInMillimeters * pixelsPerMm / view()->transform().m11();
|
||||
}
|
||||
///@endcond
|
||||
|
||||
@ -61,6 +61,12 @@ class GUI_EXPORT QgsLayoutViewToolSelect : public QgsLayoutViewTool
|
||||
//! Sets the a \a layout.
|
||||
void setLayout( QgsLayout *layout );
|
||||
|
||||
/**
|
||||
* Compute the search tolerance in layout units from the view current scale
|
||||
* \since QGIS 3.34
|
||||
*/
|
||||
double searchToleranceInLayoutUnits();
|
||||
|
||||
private:
|
||||
|
||||
bool mIsSelecting = false;
|
||||
@ -75,6 +81,9 @@ class GUI_EXPORT QgsLayoutViewToolSelect : public QgsLayoutViewTool
|
||||
QPointF mRubberBandStartPos;
|
||||
|
||||
QPointer< QgsLayoutMouseHandles > mMouseHandles; //owned by scene
|
||||
|
||||
//! Search tolerance in millimeters for selecting items
|
||||
static const double sSearchToleranceInMillimeters;
|
||||
};
|
||||
|
||||
#endif // QGSLAYOUTVIEWTOOLSELECT_H
|
||||
|
||||
@ -465,7 +465,6 @@ void QgsGraphicsViewMouseHandles::mousePressEvent( QGraphicsSceneMouseEvent *eve
|
||||
|
||||
//save current cursor position
|
||||
mMouseMoveStartPos = event->lastScenePos();
|
||||
mLastMouseEventPos = event->lastScenePos();
|
||||
//save current item geometry
|
||||
mBeginMouseEventPos = event->lastScenePos();
|
||||
mBeginHandlePos = scenePos();
|
||||
@ -526,8 +525,6 @@ void QgsGraphicsViewMouseHandles::mouseMoveEvent( QGraphicsSceneMouseEvent *even
|
||||
//resize from center if alt depressed
|
||||
resizeMouseMove( event->lastScenePos(), event->modifiers() & Qt::ShiftModifier, event->modifiers() & Qt::AltModifier );
|
||||
}
|
||||
|
||||
mLastMouseEventPos = event->lastScenePos();
|
||||
}
|
||||
|
||||
void QgsGraphicsViewMouseHandles::mouseReleaseEvent( QGraphicsSceneMouseEvent *event )
|
||||
|
||||
@ -216,9 +216,6 @@ class GUI_EXPORT QgsGraphicsViewMouseHandles: public QObject, public QGraphicsRe
|
||||
//! Start point of the last mouse move action (in scene coordinates)
|
||||
QPointF mMouseMoveStartPos;
|
||||
|
||||
//! Position of the last mouse move event (in scene coordinates)
|
||||
QPointF mLastMouseEventPos;
|
||||
|
||||
MouseAction mCurrentMouseMoveAction = NoAction;
|
||||
|
||||
//! True if user is currently dragging items
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user