mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-15 00:04:00 -04:00
Start work on node edit tool
This commit is contained in:
parent
d92b067b28
commit
ab7bb7235a
@ -296,6 +296,7 @@
|
||||
%Include layout/qgslayoutviewtool.sip
|
||||
%Include layout/qgslayoutviewtooladditem.sip
|
||||
%Include layout/qgslayoutviewtooladdnodeitem.sip
|
||||
%Include layout/qgslayoutviewtooleditnodes.sip
|
||||
%Include layout/qgslayoutviewtoolpan.sip
|
||||
%Include layout/qgslayoutviewtoolselect.sip
|
||||
%Include layout/qgslayoutviewtooltemporarykeypan.sip
|
||||
|
49
python/gui/layout/qgslayoutviewtooleditnodes.sip
Normal file
49
python/gui/layout/qgslayoutviewtooleditnodes.sip
Normal file
@ -0,0 +1,49 @@
|
||||
/************************************************************************
|
||||
* This file has been generated automatically from *
|
||||
* *
|
||||
* src/gui/layout/qgslayoutviewtooleditnodes.h *
|
||||
* *
|
||||
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
||||
************************************************************************/
|
||||
|
||||
|
||||
|
||||
|
||||
class QgsLayoutViewToolEditNodes : QgsLayoutViewTool
|
||||
{
|
||||
%Docstring
|
||||
Layout view tool for edit node based items in the layout.
|
||||
.. versionadded:: 3.0
|
||||
%End
|
||||
|
||||
%TypeHeaderCode
|
||||
#include "qgslayoutviewtooleditnodes.h"
|
||||
%End
|
||||
public:
|
||||
|
||||
QgsLayoutViewToolEditNodes( QgsLayoutView *view /TransferThis/ );
|
||||
%Docstring
|
||||
Constructor for QgsLayoutViewToolEditNodes.
|
||||
%End
|
||||
|
||||
virtual void activate();
|
||||
|
||||
|
||||
virtual void layoutPressEvent( QgsLayoutViewMouseEvent *event );
|
||||
|
||||
virtual void layoutMoveEvent( QgsLayoutViewMouseEvent *event );
|
||||
|
||||
virtual void layoutReleaseEvent( QgsLayoutViewMouseEvent *event );
|
||||
|
||||
virtual void deactivate();
|
||||
|
||||
|
||||
};
|
||||
|
||||
/************************************************************************
|
||||
* This file has been generated automatically from *
|
||||
* *
|
||||
* src/gui/layout/qgslayoutviewtooleditnodes.h *
|
||||
* *
|
||||
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
||||
************************************************************************/
|
@ -28,6 +28,7 @@
|
||||
#include "qgslayoutviewtoolpan.h"
|
||||
#include "qgslayoutviewtoolzoom.h"
|
||||
#include "qgslayoutviewtoolselect.h"
|
||||
#include "qgslayoutviewtooleditnodes.h"
|
||||
#include "qgslayoutitemwidget.h"
|
||||
#include "qgsgui.h"
|
||||
#include "qgslayoutitemguiregistry.h"
|
||||
@ -245,6 +246,11 @@ QgsLayoutDesignerDialog::QgsLayoutDesignerDialog( QWidget *parent, Qt::WindowFla
|
||||
connect( mAddItemTool, &QgsLayoutViewToolAddItem::createdItem, this, [ = ] { mView->setTool( mSelectTool ); } );
|
||||
connect( mAddNodeItemTool, &QgsLayoutViewToolAddNodeItem::createdItem, this, [ = ] { mView->setTool( mSelectTool ); } );
|
||||
|
||||
mNodesTool = new QgsLayoutViewToolEditNodes( mView );
|
||||
mNodesTool->setAction( mActionEditNodesItem );
|
||||
mToolsActionGroup->addAction( mActionEditNodesItem );
|
||||
connect( mActionEditNodesItem, &QAction::triggered, mNodesTool, [ = ] { mView->setTool( mNodesTool ); } );
|
||||
|
||||
//Ctrl+= should also trigger zoom in
|
||||
QShortcut *ctrlEquals = new QShortcut( QKeySequence( QStringLiteral( "Ctrl+=" ) ), this );
|
||||
connect( ctrlEquals, &QShortcut::activated, mActionZoomIn, &QAction::trigger );
|
||||
|
@ -28,6 +28,7 @@ class QgsLayoutViewToolAddNodeItem;
|
||||
class QgsLayoutViewToolPan;
|
||||
class QgsLayoutViewToolZoom;
|
||||
class QgsLayoutViewToolSelect;
|
||||
class QgsLayoutViewToolEditNodes;
|
||||
class QgsLayoutRuler;
|
||||
class QComboBox;
|
||||
class QSlider;
|
||||
@ -275,6 +276,7 @@ class QgsLayoutDesignerDialog: public QMainWindow, private Ui::QgsLayoutDesigner
|
||||
QgsLayoutViewToolPan *mPanTool = nullptr;
|
||||
QgsLayoutViewToolZoom *mZoomTool = nullptr;
|
||||
QgsLayoutViewToolSelect *mSelectTool = nullptr;
|
||||
QgsLayoutViewToolEditNodes *mNodesTool = nullptr;
|
||||
|
||||
QMap< QString, QToolButton * > mItemGroupToolButtons;
|
||||
QMap< QString, QMenu * > mItemGroupSubmenus;
|
||||
|
@ -418,7 +418,7 @@ void QgsLayoutItem::attemptMove( const QgsLayoutPoint &p, bool useReferencePoint
|
||||
|
||||
void QgsLayoutItem::attemptSetSceneRect( const QRectF &rect, bool includesFrame )
|
||||
{
|
||||
QPointF newPos = mapToScene( rect.topLeft() );
|
||||
QPointF newPos = rect.topLeft();
|
||||
|
||||
blockSignals( true );
|
||||
// translate new size to current item units
|
||||
|
@ -150,7 +150,9 @@ bool QgsLayoutNodesItem::addNode( QPointF pt,
|
||||
|
||||
void QgsLayoutNodesItem::drawNodes( QgsRenderContext &context, const QStyleOptionGraphicsItem *itemStyle ) const
|
||||
{
|
||||
double rectSize = 3.0 / itemStyle->matrix.m11();
|
||||
context.painter()->setRenderHint( QPainter::Antialiasing, false );
|
||||
|
||||
double rectSize = 9.0 / itemStyle->matrix.m11();
|
||||
|
||||
QgsStringMap properties;
|
||||
properties.insert( QStringLiteral( "name" ), QStringLiteral( "cross" ) );
|
||||
@ -163,7 +165,7 @@ void QgsLayoutNodesItem::drawNodes( QgsRenderContext &context, const QStyleOptio
|
||||
|
||||
symbol->startRender( context );
|
||||
for ( QPointF pt : mPolygon )
|
||||
symbol->renderPoint( pt, nullptr, context );
|
||||
symbol->renderPoint( pt * itemStyle->matrix.m11(), nullptr, context );
|
||||
symbol->stopRender( context );
|
||||
|
||||
if ( mSelectedNode >= 0 && mSelectedNode < mPolygon.size() )
|
||||
@ -172,7 +174,7 @@ void QgsLayoutNodesItem::drawNodes( QgsRenderContext &context, const QStyleOptio
|
||||
|
||||
void QgsLayoutNodesItem::drawSelectedNode( QgsRenderContext &context, const QStyleOptionGraphicsItem *itemStyle ) const
|
||||
{
|
||||
double rectSize = 3.0 / itemStyle->matrix.m11();
|
||||
double rectSize = 9.0 / itemStyle->matrix.m11();
|
||||
|
||||
QgsStringMap properties;
|
||||
properties.insert( QStringLiteral( "name" ), QStringLiteral( "square" ) );
|
||||
@ -185,7 +187,7 @@ void QgsLayoutNodesItem::drawSelectedNode( QgsRenderContext &context, const QSty
|
||||
symbol->setSize( rectSize );
|
||||
|
||||
symbol->startRender( context );
|
||||
symbol->renderPoint( mPolygon.at( mSelectedNode ), nullptr, context );
|
||||
symbol->renderPoint( mPolygon.at( mSelectedNode ) * itemStyle->matrix.m11(), nullptr, context );
|
||||
symbol->stopRender( context );
|
||||
}
|
||||
|
||||
@ -317,7 +319,6 @@ void QgsLayoutNodesItem::updateSceneRect()
|
||||
// update
|
||||
prepareGeometryChange();
|
||||
update();
|
||||
emit sizePositionChanged();
|
||||
}
|
||||
|
||||
|
||||
|
@ -171,6 +171,7 @@ SET(QGIS_GUI_SRCS
|
||||
layout/qgslayoutviewtool.cpp
|
||||
layout/qgslayoutviewtooladditem.cpp
|
||||
layout/qgslayoutviewtooladdnodeitem.cpp
|
||||
layout/qgslayoutviewtooleditnodes.cpp
|
||||
layout/qgslayoutviewtoolpan.cpp
|
||||
layout/qgslayoutviewtoolselect.cpp
|
||||
layout/qgslayoutviewtooltemporarykeypan.cpp
|
||||
@ -675,6 +676,7 @@ SET(QGIS_GUI_MOC_HDRS
|
||||
layout/qgslayoutviewtool.h
|
||||
layout/qgslayoutviewtooladditem.h
|
||||
layout/qgslayoutviewtooladdnodeitem.h
|
||||
layout/qgslayoutviewtooleditnodes.h
|
||||
layout/qgslayoutviewtoolpan.h
|
||||
layout/qgslayoutviewtoolselect.h
|
||||
layout/qgslayoutviewtooltemporarykeypan.h
|
||||
|
168
src/gui/layout/qgslayoutviewtooleditnodes.cpp
Normal file
168
src/gui/layout/qgslayoutviewtooleditnodes.cpp
Normal file
@ -0,0 +1,168 @@
|
||||
/***************************************************************************
|
||||
qgslayoutviewtooleditnodes.cpp
|
||||
---------------------------
|
||||
Date : July 2017
|
||||
Copyright : (C) 2017 Nyall Dawson
|
||||
Email : nyall dot dawson at gmail dot com
|
||||
***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "qgslayoutviewtooleditnodes.h"
|
||||
#include "qgslayoutviewmouseevent.h"
|
||||
#include "qgslayoutview.h"
|
||||
#include "qgslayout.h"
|
||||
#include "qgslayoutitemnodeitem.h"
|
||||
|
||||
QgsLayoutViewToolEditNodes::QgsLayoutViewToolEditNodes( QgsLayoutView *view )
|
||||
: QgsLayoutViewTool( view, tr( "Select" ) )
|
||||
{
|
||||
setCursor( Qt::CrossCursor );
|
||||
setFlags( QgsLayoutViewTool::FlagSnaps );
|
||||
}
|
||||
|
||||
void QgsLayoutViewToolEditNodes::activate()
|
||||
{
|
||||
displayNodes( true );
|
||||
QgsLayoutViewTool::activate();
|
||||
}
|
||||
|
||||
void QgsLayoutViewToolEditNodes::layoutPressEvent( QgsLayoutViewMouseEvent *event )
|
||||
{
|
||||
if ( event->button() != Qt::LeftButton )
|
||||
{
|
||||
event->ignore();
|
||||
return;
|
||||
}
|
||||
|
||||
const QList<QGraphicsItem *> itemsAtCursorPos = view()->items( event->pos().x(), event->pos().y(),
|
||||
mMoveContentSearchRadius,
|
||||
mMoveContentSearchRadius );
|
||||
if ( itemsAtCursorPos.isEmpty() )
|
||||
return;
|
||||
|
||||
mNodesItemIndex = -1;
|
||||
mNodesItem = nullptr;
|
||||
isMoving = false;
|
||||
|
||||
for ( QGraphicsItem *graphicsItem : itemsAtCursorPos )
|
||||
{
|
||||
QgsLayoutNodesItem *item = dynamic_cast<QgsLayoutNodesItem *>( graphicsItem );
|
||||
|
||||
if ( item && !item->isLocked() )
|
||||
{
|
||||
int index = item->nodeAtPosition( event->layoutPoint() );
|
||||
if ( index != -1 )
|
||||
{
|
||||
mNodesItemIndex = index;
|
||||
mNodesItem = item;
|
||||
mMoveContentStartPos = event->layoutPoint();
|
||||
}
|
||||
}
|
||||
|
||||
if ( mNodesItemIndex != -1 )
|
||||
{
|
||||
layout()->undoStack()->beginCommand( mNodesItem, tr( "Move Item Node" ) );
|
||||
setSelectedNode( mNodesItem, mNodesItemIndex );
|
||||
isMoving = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QgsLayoutViewToolEditNodes::layoutMoveEvent( QgsLayoutViewMouseEvent *event )
|
||||
{
|
||||
if ( !isMoving )
|
||||
{
|
||||
event->ignore();
|
||||
return;
|
||||
}
|
||||
|
||||
if ( mNodesItemIndex != -1 && event->layoutPoint() != mMoveContentStartPos )
|
||||
{
|
||||
mNodesItem->moveNode( mNodesItemIndex, event->snappedPoint() );
|
||||
}
|
||||
}
|
||||
|
||||
void QgsLayoutViewToolEditNodes::layoutReleaseEvent( QgsLayoutViewMouseEvent *event )
|
||||
{
|
||||
if ( event->button() != Qt::LeftButton || !isMoving )
|
||||
{
|
||||
event->ignore();
|
||||
return;
|
||||
}
|
||||
|
||||
isMoving = false;
|
||||
if ( mNodesItemIndex != -1 )
|
||||
{
|
||||
if ( event->layoutPoint() != mMoveContentStartPos )
|
||||
{
|
||||
layout()->undoStack()->endCommand();
|
||||
}
|
||||
else
|
||||
{
|
||||
layout()->undoStack()->cancelCommand();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QgsLayoutViewToolEditNodes::deactivate()
|
||||
{
|
||||
displayNodes( false );
|
||||
deselectNodes();
|
||||
QgsLayoutViewTool::deactivate();
|
||||
}
|
||||
|
||||
void QgsLayoutViewToolEditNodes::displayNodes( bool display )
|
||||
{
|
||||
QList<QgsLayoutNodesItem *> nodesShapes;
|
||||
layout()->layoutItems( nodesShapes );
|
||||
|
||||
for ( QgsLayoutNodesItem *item : qgis::as_const( nodesShapes ) )
|
||||
{
|
||||
item->setDisplayNodes( display );
|
||||
}
|
||||
|
||||
layout()->update();
|
||||
}
|
||||
|
||||
void QgsLayoutViewToolEditNodes::deselectNodes()
|
||||
{
|
||||
QList<QgsLayoutNodesItem *> nodesShapes;
|
||||
layout()->layoutItems( nodesShapes );
|
||||
|
||||
for ( QgsLayoutNodesItem *item : qgis::as_const( nodesShapes ) )
|
||||
{
|
||||
item->deselectNode();
|
||||
}
|
||||
|
||||
layout()->update();
|
||||
}
|
||||
|
||||
void QgsLayoutViewToolEditNodes::setSelectedNode( QgsLayoutNodesItem *shape, int index )
|
||||
{
|
||||
QList<QgsLayoutNodesItem *> nodesShapes;
|
||||
layout()->layoutItems( nodesShapes );
|
||||
|
||||
for ( QgsLayoutNodesItem *item : qgis::as_const( nodesShapes ) )
|
||||
{
|
||||
if ( item == shape )
|
||||
{
|
||||
item->setSelectedNode( index );
|
||||
layout()->setSelectedItem( item );
|
||||
item->update();
|
||||
}
|
||||
else
|
||||
{
|
||||
item->deselectNode();
|
||||
item->update();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
68
src/gui/layout/qgslayoutviewtooleditnodes.h
Normal file
68
src/gui/layout/qgslayoutviewtooleditnodes.h
Normal file
@ -0,0 +1,68 @@
|
||||
/***************************************************************************
|
||||
qgslayoutviewtooleditnodes.h
|
||||
-------------------------
|
||||
Date : October 2017
|
||||
Copyright : (C) 2017 Nyall Dawson
|
||||
Email : nyall dot dawson at gmail dot com
|
||||
***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef QGSLAYOUTVIEWTOOLEDITNODES_H
|
||||
#define QGSLAYOUTVIEWTOOLEDITNODES_H
|
||||
|
||||
#include "qgis.h"
|
||||
#include "qgis_gui.h"
|
||||
#include "qgslayoutviewtool.h"
|
||||
|
||||
class QgsLayoutNodesItem;
|
||||
|
||||
/**
|
||||
* \ingroup gui
|
||||
* Layout view tool for edit node based items in the layout.
|
||||
* \since QGIS 3.0
|
||||
*/
|
||||
class GUI_EXPORT QgsLayoutViewToolEditNodes : public QgsLayoutViewTool
|
||||
{
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor for QgsLayoutViewToolEditNodes.
|
||||
*/
|
||||
QgsLayoutViewToolEditNodes( QgsLayoutView *view SIP_TRANSFERTHIS );
|
||||
|
||||
void activate() override;
|
||||
|
||||
void layoutPressEvent( QgsLayoutViewMouseEvent *event ) override;
|
||||
void layoutMoveEvent( QgsLayoutViewMouseEvent *event ) override;
|
||||
void layoutReleaseEvent( QgsLayoutViewMouseEvent *event ) override;
|
||||
void deactivate() override;
|
||||
|
||||
private:
|
||||
|
||||
const double mMoveContentSearchRadius = 25;
|
||||
|
||||
QgsLayoutNodesItem *mNodesItem = nullptr;
|
||||
int mNodesItemIndex = -1;
|
||||
|
||||
//! Start position of content move
|
||||
QPointF mMoveContentStartPos;
|
||||
|
||||
bool isMoving = false;
|
||||
|
||||
void displayNodes( bool display = true );
|
||||
void deselectNodes();
|
||||
void setSelectedNode( QgsLayoutNodesItem *shape, int index );
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // QGSLAYOUTVIEWTOOLEDITNODES_H
|
@ -76,6 +76,7 @@
|
||||
<addaction name="mActionPan"/>
|
||||
<addaction name="mActionZoomTool"/>
|
||||
<addaction name="mActionSelectMoveItem"/>
|
||||
<addaction name="mActionEditNodesItem"/>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="menuBar">
|
||||
<property name="geometry">
|
||||
@ -1009,6 +1010,21 @@
|
||||
<string>F5</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="mActionEditNodesItem">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../images/images.qrc">
|
||||
<normaloff>:/images/themes/default/mActionNodeTool.svg</normaloff>:/images/themes/default/mActionNodeTool.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Edit Nodes Item</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Edit Nodes Item</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="../../../images/images.qrc"/>
|
||||
|
@ -155,6 +155,7 @@ class TestQgsLayoutItem: public QObject
|
||||
void blendMode();
|
||||
void opacity();
|
||||
void excludeFromExports();
|
||||
void setSceneRect();
|
||||
|
||||
private:
|
||||
|
||||
@ -1191,6 +1192,48 @@ void TestQgsLayoutItem::move()
|
||||
QCOMPARE( item->positionWithUnits().y(), 6.5 );
|
||||
}
|
||||
|
||||
void TestQgsLayoutItem::setSceneRect()
|
||||
{
|
||||
QgsProject p;
|
||||
QgsLayout l( &p );
|
||||
|
||||
//resize test item (no restrictions), same units as layout
|
||||
l.setUnits( QgsUnitTypes::LayoutMillimeters );
|
||||
std::unique_ptr< TestItem > item( new TestItem( &l ) );
|
||||
QSignalSpy spySizeChanged( item.get(), &QgsLayoutItem::sizePositionChanged );
|
||||
|
||||
item->attemptSetSceneRect( QRectF( 27.0, 29.0, 100, 200 ) );
|
||||
QCOMPARE( spySizeChanged.count(), 1 );
|
||||
QCOMPARE( item->rect().width(), 100.0 );
|
||||
QCOMPARE( item->rect().height(), 200.0 );
|
||||
QCOMPARE( item->scenePos().x(), 27.0 );
|
||||
QCOMPARE( item->scenePos().y(), 29.0 );
|
||||
QCOMPARE( item->positionWithUnits().x(), 27.0 );
|
||||
QCOMPARE( item->positionWithUnits().y(), 29.0 );
|
||||
QCOMPARE( item->positionWithUnits().units(), QgsUnitTypes::LayoutMillimeters );
|
||||
QCOMPARE( item->sizeWithUnits().width(), 100.0 );
|
||||
QCOMPARE( item->sizeWithUnits().height(), 200.0 );
|
||||
QCOMPARE( item->sizeWithUnits().units(), QgsUnitTypes::LayoutMillimeters );
|
||||
|
||||
//test conversion of units
|
||||
item->attemptMove( QgsLayoutPoint( 1, 2, QgsUnitTypes::LayoutCentimeters ) );
|
||||
item->attemptResize( QgsLayoutSize( 3, 4, QgsUnitTypes::LayoutCentimeters ) );
|
||||
QCOMPARE( spySizeChanged.count(), 3 );
|
||||
item->attemptSetSceneRect( QRectF( 27.0, 29.0, 100, 200 ) );
|
||||
QCOMPARE( item->rect().width(), 100.0 );
|
||||
QCOMPARE( item->rect().height(), 200.0 );
|
||||
QCOMPARE( item->scenePos().x(), 27.0 );
|
||||
QCOMPARE( item->scenePos().y(), 29.0 );
|
||||
QCOMPARE( spySizeChanged.count(), 4 );
|
||||
|
||||
QCOMPARE( item->positionWithUnits().x(), 2.70 );
|
||||
QCOMPARE( item->positionWithUnits().y(), 2.90 );
|
||||
QCOMPARE( item->positionWithUnits().units(), QgsUnitTypes::LayoutCentimeters );
|
||||
QCOMPARE( item->sizeWithUnits().width(), 10.0 );
|
||||
QCOMPARE( item->sizeWithUnits().height(), 20.0 );
|
||||
QCOMPARE( item->sizeWithUnits().units(), QgsUnitTypes::LayoutCentimeters );
|
||||
}
|
||||
|
||||
void TestQgsLayoutItem::rotation()
|
||||
{
|
||||
QgsProject proj;
|
||||
|
Loading…
x
Reference in New Issue
Block a user