Port more node tool actions

This commit is contained in:
Nyall Dawson 2017-10-17 20:21:53 +10:00
parent ab7bb7235a
commit 938b239277
10 changed files with 197 additions and 50 deletions

View File

@ -62,6 +62,7 @@ class QgsLayoutItem : QgsLayoutObject, QGraphicsRectItem, QgsLayoutUndoObjectInt
UndoRotation,
UndoShapeStyle,
UndoShapeCornerRadius,
UndoNodeMove,
};
explicit QgsLayoutItem( QgsLayout *layout, bool manageZValue = true );

View File

@ -179,6 +179,13 @@ class QgsLayoutView: QGraphicsView
.. seealso:: distributeSelectedItems()
%End
QPointF deltaForKeyEvent( QKeyEvent *event );
%Docstring
Returns the delta (in layout coordinates) by which to move items
for the given key ``event``.
:rtype: QPointF
%End
public slots:
void zoomFull();

View File

@ -26,8 +26,12 @@ class QgsLayoutViewToolEditNodes : QgsLayoutViewTool
Constructor for QgsLayoutViewToolEditNodes.
%End
virtual void activate();
void deleteSelectedNode();
%Docstring
Deletes the selected node from the item.
%End
virtual void activate();
virtual void layoutPressEvent( QgsLayoutViewMouseEvent *event );
@ -35,6 +39,10 @@ class QgsLayoutViewToolEditNodes : QgsLayoutViewTool
virtual void layoutReleaseEvent( QgsLayoutViewMouseEvent *event );
virtual void layoutDoubleClickEvent( QgsLayoutViewMouseEvent *event );
virtual void keyPressEvent( QKeyEvent *event );
virtual void deactivate();

View File

@ -385,7 +385,10 @@ QgsLayoutDesignerDialog::QgsLayoutDesignerDialog( QWidget *parent, Qt::WindowFla
connect( mActionDeleteSelection, &QAction::triggered, this, [ = ]
{
mView->deleteSelectedItems();
if ( mView->tool() == mNodesTool )
mNodesTool->deleteSelectedNode();
else
mView->deleteSelectedItems();
} );
connect( mActionGroupItems, &QAction::triggered, this, [ = ]
{

View File

@ -95,6 +95,7 @@ class CORE_EXPORT QgsLayoutItem : public QgsLayoutObject, public QGraphicsRectIt
UndoRotation, //!< Rotation adjustment
UndoShapeStyle, //!< Shape symbol style
UndoShapeCornerRadius, //!< Shape corner radius
UndoNodeMove, //!< Node move
};
/**

View File

@ -25,7 +25,7 @@ QgsLayoutViewRubberBand *QgsLayoutItemAbstractGuiMetadata::createRubberBand( Qgs
return new QgsLayoutViewRectangularRubberBand( view );
}
QAbstractGraphicsShapeItem *QgsLayoutItemAbstractGuiMetadata::createNodeRubberBand( QgsLayoutView *view )
QAbstractGraphicsShapeItem *QgsLayoutItemAbstractGuiMetadata::createNodeRubberBand( QgsLayoutView * )
{
return nullptr;
}

View File

@ -274,6 +274,48 @@ void QgsLayoutView::resizeSelectedItems( QgsLayoutAligner::Resize resize )
QgsLayoutAligner::resizeItems( currentLayout(), selectedItems, resize );
}
QPointF QgsLayoutView::deltaForKeyEvent( QKeyEvent *event )
{
// increment used for cursor key item movement
double increment = 1.0;
if ( event->modifiers() & Qt::ShiftModifier )
{
//holding shift while pressing cursor keys results in a big step
increment = 10.0;
}
else if ( event->modifiers() & Qt::AltModifier )
{
//holding alt while pressing cursor keys results in a 1 pixel step
double viewScale = transform().m11();
if ( viewScale > 0 )
{
increment = 1 / viewScale;
}
}
double deltaX = 0;
double deltaY = 0;
switch ( event->key() )
{
case Qt::Key_Left:
deltaX = -increment;
break;
case Qt::Key_Right:
deltaX = increment;
break;
case Qt::Key_Up:
deltaY = -increment;
break;
case Qt::Key_Down:
deltaY = increment;
break;
default:
break;
}
return QPointF( deltaX, deltaY );
}
void QgsLayoutView::zoomFull()
{
fitInView( scene()->sceneRect(), Qt::KeepAspectRatio );
@ -811,47 +853,11 @@ void QgsLayoutView::keyPressEvent( QKeyEvent *event )
QgsLayout *l = currentLayout();
const QList<QgsLayoutItem *> layoutItemList = l->selectedLayoutItems();
// increment used for cursor key item movement
double increment = 1.0;
if ( event->modifiers() & Qt::ShiftModifier )
{
//holding shift while pressing cursor keys results in a big step
increment = 10.0;
}
else if ( event->modifiers() & Qt::AltModifier )
{
//holding alt while pressing cursor keys results in a 1 pixel step
double viewScale = transform().m11();
if ( viewScale > 0 )
{
increment = 1 / viewScale;
}
}
double deltaX = 0;
double deltaY = 0;
switch ( event->key() )
{
case Qt::Key_Left:
deltaX = -increment;
break;
case Qt::Key_Right:
deltaX = increment;
break;
case Qt::Key_Up:
deltaY = -increment;
break;
case Qt::Key_Down:
deltaY = increment;
break;
default:
break;
}
auto moveItem = [ l, deltaX, deltaY ]( QgsLayoutItem * item )
QPointF delta = deltaForKeyEvent( event );
auto moveItem = [ l, delta ]( QgsLayoutItem * item )
{
QgsLayoutPoint itemPos = item->positionWithUnits();
QgsLayoutPoint deltaPos = l->convertFromLayoutUnits( QPointF( deltaX, deltaY ), itemPos.units() );
QgsLayoutPoint deltaPos = l->convertFromLayoutUnits( delta, itemPos.units() );
itemPos.setX( itemPos.x() + deltaPos.x() );
itemPos.setY( itemPos.y() + deltaPos.y() );
item->attemptMove( itemPos );

View File

@ -208,6 +208,12 @@ class GUI_EXPORT QgsLayoutView: public QGraphicsView
*/
void resizeSelectedItems( QgsLayoutAligner::Resize resize );
/**
* Returns the delta (in layout coordinates) by which to move items
* for the given key \a event.
*/
QPointF deltaForKeyEvent( QKeyEvent *event );
public slots:
/**

View File

@ -26,6 +26,34 @@ QgsLayoutViewToolEditNodes::QgsLayoutViewToolEditNodes( QgsLayoutView *view )
setFlags( QgsLayoutViewTool::FlagSnaps );
}
void QgsLayoutViewToolEditNodes::deleteSelectedNode()
{
if ( mNodesItem && mNodesItemIndex != -1 )
{
layout()->undoStack()->beginCommand( mNodesItem, tr( "Remove Item Node" ) );
if ( mNodesItem->removeNode( mNodesItemIndex ) )
{
layout()->undoStack()->endCommand();
if ( mNodesItem->nodesSize() > 0 )
{
mNodesItemIndex = mNodesItem->selectedNode();
// setSelectedNode( mNodesItem, mNodesItemIndex );
}
else
{
mNodesItemIndex = -1;
mNodesItem = nullptr;
}
if ( mNodesItem )
mNodesItem->update();
}
else
{
layout()->undoStack()->cancelCommand();
}
}
}
void QgsLayoutViewToolEditNodes::activate()
{
displayNodes( true );
@ -65,7 +93,7 @@ void QgsLayoutViewToolEditNodes::layoutPressEvent( QgsLayoutViewMouseEvent *even
}
}
if ( mNodesItemIndex != -1 )
if ( mNodesItem && mNodesItemIndex != -1 )
{
layout()->undoStack()->beginCommand( mNodesItem, tr( "Move Item Node" ) );
setSelectedNode( mNodesItem, mNodesItemIndex );
@ -83,7 +111,7 @@ void QgsLayoutViewToolEditNodes::layoutMoveEvent( QgsLayoutViewMouseEvent *event
return;
}
if ( mNodesItemIndex != -1 && event->layoutPoint() != mMoveContentStartPos )
if ( mNodesItem && mNodesItemIndex != -1 && event->layoutPoint() != mMoveContentStartPos )
{
mNodesItem->moveNode( mNodesItemIndex, event->snappedPoint() );
}
@ -111,6 +139,89 @@ void QgsLayoutViewToolEditNodes::layoutReleaseEvent( QgsLayoutViewMouseEvent *ev
}
}
void QgsLayoutViewToolEditNodes::layoutDoubleClickEvent( QgsLayoutViewMouseEvent *event )
{
if ( event->button() != Qt::LeftButton )
{
event->ignore();
return;
}
// erase status previously set by the mousePressEvent method
if ( mNodesItemIndex != -1 )
{
mNodesItem = nullptr;
mNodesItemIndex = -1;
deselectNodes();
}
// search items in layout
const QList<QGraphicsItem *> itemsAtCursorPos = view()->items( event->pos().x(), event->pos().y(),
mMoveContentSearchRadius,
mMoveContentSearchRadius );
if ( itemsAtCursorPos.isEmpty() )
return;
bool rc = false;
for ( QGraphicsItem *graphicsItem : itemsAtCursorPos )
{
QgsLayoutNodesItem *item = dynamic_cast<QgsLayoutNodesItem *>( graphicsItem );
if ( item && !item->isLocked() )
{
layout()->undoStack()->beginCommand( item, tr( "Add Item Node" ) );
rc = item->addNode( event->layoutPoint() );
if ( rc )
{
layout()->undoStack()->endCommand();
mNodesItem = item;
mNodesItemIndex = mNodesItem->nodeAtPosition( event->layoutPoint() );
}
else
layout()->undoStack()->cancelCommand();
}
if ( rc )
break;
}
if ( rc )
{
setSelectedNode( mNodesItem, mNodesItemIndex );
mNodesItem->update();
}
}
void QgsLayoutViewToolEditNodes::keyPressEvent( QKeyEvent *event )
{
if ( mNodesItem && mNodesItemIndex != -1 && ( event->key() == Qt::Key_Left
|| event->key() == Qt::Key_Right
|| event->key() == Qt::Key_Up
|| event->key() == Qt::Key_Down ) )
{
QPointF currentPos;
if ( mNodesItem->nodePosition( mNodesItemIndex, currentPos ) )
{
QPointF delta = view()->deltaForKeyEvent( event );
currentPos.setX( currentPos.x() + delta.x() );
currentPos.setY( currentPos.y() + delta.y() );
layout()->undoStack()->beginCommand( mNodesItem, tr( "Move Item Node" ), QgsLayoutItem::UndoNodeMove );
mNodesItem->moveNode( mNodesItemIndex, currentPos );
layout()->undoStack()->endCommand();
layout()->update();
}
}
else
{
event->ignore();
}
}
void QgsLayoutViewToolEditNodes::deactivate()
{
displayNodes( false );
@ -126,9 +237,8 @@ void QgsLayoutViewToolEditNodes::displayNodes( bool display )
for ( QgsLayoutNodesItem *item : qgis::as_const( nodesShapes ) )
{
item->setDisplayNodes( display );
item->update();
}
layout()->update();
}
void QgsLayoutViewToolEditNodes::deselectNodes()
@ -139,9 +249,8 @@ void QgsLayoutViewToolEditNodes::deselectNodes()
for ( QgsLayoutNodesItem *item : qgis::as_const( nodesShapes ) )
{
item->deselectNode();
item->update();
}
layout()->update();
}
void QgsLayoutViewToolEditNodes::setSelectedNode( QgsLayoutNodesItem *shape, int index )

View File

@ -39,18 +39,24 @@ class GUI_EXPORT QgsLayoutViewToolEditNodes : public QgsLayoutViewTool
*/
QgsLayoutViewToolEditNodes( QgsLayoutView *view SIP_TRANSFERTHIS );
void activate() override;
/**
* Deletes the selected node from the item.
*/
void deleteSelectedNode();
void activate() override;
void layoutPressEvent( QgsLayoutViewMouseEvent *event ) override;
void layoutMoveEvent( QgsLayoutViewMouseEvent *event ) override;
void layoutReleaseEvent( QgsLayoutViewMouseEvent *event ) override;
void layoutDoubleClickEvent( QgsLayoutViewMouseEvent *event ) override;
void keyPressEvent( QKeyEvent *event ) override;
void deactivate() override;
private:
const double mMoveContentSearchRadius = 25;
QgsLayoutNodesItem *mNodesItem = nullptr;
QPointer< QgsLayoutNodesItem > mNodesItem;
int mNodesItemIndex = -1;
//! Start position of content move