From 7f0142c86a03f82318a9aed1facd5bb6002fd863 Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Sat, 21 Oct 2017 12:24:11 +1000 Subject: [PATCH] Working move item content tool --- python/core/layout/qgslayoutitem.sip | 10 ++ python/core/layout/qgslayoutitemmap.sip | 8 +- python/gui/gui_auto.sip | 1 + .../qgslayoutviewtoolmoveitemcontent.sip | 45 +++++++ src/app/layout/qgslayoutdesignerdialog.cpp | 6 + src/app/layout/qgslayoutdesignerdialog.h | 2 + src/app/layout/qgslayoutmapwidget.cpp | 7 +- src/core/layout/qgslayoutitem.cpp | 5 + src/core/layout/qgslayoutitem.h | 10 ++ src/core/layout/qgslayoutitemmap.cpp | 4 +- src/core/layout/qgslayoutitemmap.h | 5 +- src/gui/CMakeLists.txt | 2 + src/gui/layout/qgslayoutmousehandles.cpp | 4 +- src/gui/layout/qgslayoutruler.cpp | 8 +- src/gui/layout/qgslayoutruler.h | 2 +- src/gui/layout/qgslayoutview.cpp | 19 +-- src/gui/layout/qgslayoutview.h | 6 +- .../qgslayoutviewtoolmoveitemcontent.cpp | 122 ++++++++++++++++++ .../layout/qgslayoutviewtoolmoveitemcontent.h | 56 ++++++++ src/ui/layout/qgslayoutdesignerbase.ui | 22 +++- 20 files changed, 312 insertions(+), 32 deletions(-) create mode 100644 python/gui/layout/qgslayoutviewtoolmoveitemcontent.sip create mode 100644 src/gui/layout/qgslayoutviewtoolmoveitemcontent.cpp create mode 100644 src/gui/layout/qgslayoutviewtoolmoveitemcontent.h diff --git a/python/core/layout/qgslayoutitem.sip b/python/core/layout/qgslayoutitem.sip index 3bf879eb67a..d835059eaf2 100644 --- a/python/core/layout/qgslayoutitem.sip +++ b/python/core/layout/qgslayoutitem.sip @@ -65,6 +65,7 @@ class QgsLayoutItem : QgsLayoutObject, QGraphicsRectItem, QgsLayoutUndoObjectInt UndoNodeMove, UndoAtlasMargin, UndoMapRotation, + UndoZoomContent, }; explicit QgsLayoutItem( QgsLayout *layout, bool manageZValue = true ); @@ -531,7 +532,16 @@ class QgsLayoutItem : QgsLayoutObject, QGraphicsRectItem, QgsLayoutUndoObjectInt %Docstring Moves the content of the item, by a specified ``dx`` and ``dy`` in layout units. The default implementation has no effect. +.. seealso:: setMoveContentPreviewOffset() .. seealso:: zoomContent() +%End + + virtual void setMoveContentPreviewOffset( double dx, double dy ); +%Docstring + Sets temporary offset for the item, by a specified ``dx`` and ``dy`` in layout units. + This is useful for live updates when moving item content in a QgsLayoutView. + The default implementation has no effect. +.. seealso:: moveContent() %End virtual void zoomContent( double factor, QPointF point ); diff --git a/python/core/layout/qgslayoutitemmap.sip b/python/core/layout/qgslayoutitemmap.sip index 4ad347ef4c6..487efa00fd3 100644 --- a/python/core/layout/qgslayoutitemmap.sip +++ b/python/core/layout/qgslayoutitemmap.sip @@ -250,6 +250,9 @@ class QgsLayoutItemMap : QgsLayoutItem virtual void moveContent( double dx, double dy ); + virtual void setMoveContentPreviewOffset( double dx, double dy ); + + virtual void zoomContent( double factor, QPointF point ); @@ -386,11 +389,6 @@ True if a draw is already in progress - void setOffset( double xOffset, double yOffset ); -%Docstring -Sets offset values to shift image (useful for live updates when moving item content) -%End - virtual QRectF boundingRect() const; diff --git a/python/gui/gui_auto.sip b/python/gui/gui_auto.sip index 07bdac32c3e..1cc33d4b230 100644 --- a/python/gui/gui_auto.sip +++ b/python/gui/gui_auto.sip @@ -297,6 +297,7 @@ %Include layout/qgslayoutviewtooladditem.sip %Include layout/qgslayoutviewtooladdnodeitem.sip %Include layout/qgslayoutviewtooleditnodes.sip +%Include layout/qgslayoutviewtoolmoveitemcontent.sip %Include layout/qgslayoutviewtoolpan.sip %Include layout/qgslayoutviewtoolselect.sip %Include layout/qgslayoutviewtooltemporarykeypan.sip diff --git a/python/gui/layout/qgslayoutviewtoolmoveitemcontent.sip b/python/gui/layout/qgslayoutviewtoolmoveitemcontent.sip new file mode 100644 index 00000000000..32920cc3414 --- /dev/null +++ b/python/gui/layout/qgslayoutviewtoolmoveitemcontent.sip @@ -0,0 +1,45 @@ +/************************************************************************ + * This file has been generated automatically from * + * * + * src/gui/layout/qgslayoutviewtoolmoveitemcontent.h * + * * + * Do not edit manually ! Edit header and run scripts/sipify.pl again * + ************************************************************************/ + + + +class QgsLayoutViewToolMoveItemContent : QgsLayoutViewTool +{ +%Docstring + Layout view tool for moving and zooming item content. +.. versionadded:: 3.0 +%End + +%TypeHeaderCode +#include "qgslayoutviewtoolmoveitemcontent.h" +%End + public: + + QgsLayoutViewToolMoveItemContent( QgsLayoutView *view /TransferThis/ ); +%Docstring + Constructor for QgsLayoutViewToolMoveItemContent. +%End + + virtual void layoutPressEvent( QgsLayoutViewMouseEvent *event ); + + virtual void layoutMoveEvent( QgsLayoutViewMouseEvent *event ); + + virtual void layoutReleaseEvent( QgsLayoutViewMouseEvent *event ); + + virtual void wheelEvent( QWheelEvent *event ); + + +}; + +/************************************************************************ + * This file has been generated automatically from * + * * + * src/gui/layout/qgslayoutviewtoolmoveitemcontent.h * + * * + * Do not edit manually ! Edit header and run scripts/sipify.pl again * + ************************************************************************/ diff --git a/src/app/layout/qgslayoutdesignerdialog.cpp b/src/app/layout/qgslayoutdesignerdialog.cpp index fc4938bdb8c..a35e7a784ee 100644 --- a/src/app/layout/qgslayoutdesignerdialog.cpp +++ b/src/app/layout/qgslayoutdesignerdialog.cpp @@ -26,6 +26,7 @@ #include "qgslayoutviewtooladditem.h" #include "qgslayoutviewtooladdnodeitem.h" #include "qgslayoutviewtoolpan.h" +#include "qgslayoutviewtoolmoveitemcontent.h" #include "qgslayoutviewtoolzoom.h" #include "qgslayoutviewtoolselect.h" #include "qgslayoutviewtooleditnodes.h" @@ -251,6 +252,11 @@ QgsLayoutDesignerDialog::QgsLayoutDesignerDialog( QWidget *parent, Qt::WindowFla mToolsActionGroup->addAction( mActionEditNodesItem ); connect( mActionEditNodesItem, &QAction::triggered, mNodesTool, [ = ] { mView->setTool( mNodesTool ); } ); + mMoveContentTool = new QgsLayoutViewToolMoveItemContent( mView ); + mMoveContentTool->setAction( mActionMoveItemContent ); + mToolsActionGroup->addAction( mActionMoveItemContent ); + connect( mActionMoveItemContent, &QAction::triggered, mMoveContentTool, [ = ] { mView->setTool( mMoveContentTool ); } ); + //Ctrl+= should also trigger zoom in QShortcut *ctrlEquals = new QShortcut( QKeySequence( QStringLiteral( "Ctrl+=" ) ), this ); connect( ctrlEquals, &QShortcut::activated, mActionZoomIn, &QAction::trigger ); diff --git a/src/app/layout/qgslayoutdesignerdialog.h b/src/app/layout/qgslayoutdesignerdialog.h index 5e196cf8d03..6eb50f6e205 100644 --- a/src/app/layout/qgslayoutdesignerdialog.h +++ b/src/app/layout/qgslayoutdesignerdialog.h @@ -29,6 +29,7 @@ class QgsLayoutViewToolPan; class QgsLayoutViewToolZoom; class QgsLayoutViewToolSelect; class QgsLayoutViewToolEditNodes; +class QgsLayoutViewToolMoveItemContent; class QgsLayoutRuler; class QComboBox; class QSlider; @@ -277,6 +278,7 @@ class QgsLayoutDesignerDialog: public QMainWindow, private Ui::QgsLayoutDesigner QgsLayoutViewToolZoom *mZoomTool = nullptr; QgsLayoutViewToolSelect *mSelectTool = nullptr; QgsLayoutViewToolEditNodes *mNodesTool = nullptr; + QgsLayoutViewToolMoveItemContent *mMoveContentTool = nullptr; QMap< QString, QToolButton * > mItemGroupToolButtons; QMap< QString, QMenu * > mItemGroupSubmenus; diff --git a/src/app/layout/qgslayoutmapwidget.cpp b/src/app/layout/qgslayoutmapwidget.cpp index 483e58a40a8..14fa52f9545 100644 --- a/src/app/layout/qgslayoutmapwidget.cpp +++ b/src/app/layout/qgslayoutmapwidget.cpp @@ -104,7 +104,6 @@ QgsLayoutMapWidget::QgsLayoutMapWidget( QgsLayoutItemMap *item ) if ( item ) { - mLabel->setText( tr( "Map %1" ).arg( item->id() ) ); connect( item, &QgsLayoutObject::changed, this, &QgsLayoutMapWidget::updateGuiElements ); #if 0 //TODO @@ -491,9 +490,8 @@ void QgsLayoutMapWidget::mScaleLineEdit_editingFinished() return; } - bool conversionSuccess; - double scaleDenominator = mScaleLineEdit->text().toDouble( &conversionSuccess ); - + bool conversionSuccess = false; + double scaleDenominator = QLocale::system().toDouble( mScaleLineEdit->text(), &conversionSuccess ); if ( !conversionSuccess ) { return; @@ -612,6 +610,7 @@ void QgsLayoutMapWidget::updateGuiElements() } blockAllSignals( true ); + mLabel->setText( tr( "Map %1" ).arg( item->id() ) ); whileBlocking( mCrsSelector )->setCrs( mMapItem->presetCrs() ); diff --git a/src/core/layout/qgslayoutitem.cpp b/src/core/layout/qgslayoutitem.cpp index 3b09cb64851..705c7619029 100644 --- a/src/core/layout/qgslayoutitem.cpp +++ b/src/core/layout/qgslayoutitem.cpp @@ -802,6 +802,11 @@ void QgsLayoutItem::moveContent( double, double ) } +void QgsLayoutItem::setMoveContentPreviewOffset( double, double ) +{ + +} + void QgsLayoutItem::zoomContent( double, QPointF ) { diff --git a/src/core/layout/qgslayoutitem.h b/src/core/layout/qgslayoutitem.h index f8595cc4a23..5212b0e1565 100644 --- a/src/core/layout/qgslayoutitem.h +++ b/src/core/layout/qgslayoutitem.h @@ -98,6 +98,7 @@ class CORE_EXPORT QgsLayoutItem : public QgsLayoutObject, public QGraphicsRectIt UndoNodeMove, //!< Node move UndoAtlasMargin, //!< Map atlas margin changed UndoMapRotation, //!< Map rotation changed + UndoZoomContent, //!< Item content zoomed }; /** @@ -528,10 +529,19 @@ class CORE_EXPORT QgsLayoutItem : public QgsLayoutObject, public QGraphicsRectIt /** * Moves the content of the item, by a specified \a dx and \a dy in layout units. * The default implementation has no effect. + * \see setMoveContentPreviewOffset() * \see zoomContent() */ virtual void moveContent( double dx, double dy ); + /** + * Sets temporary offset for the item, by a specified \a dx and \a dy in layout units. + * This is useful for live updates when moving item content in a QgsLayoutView. + * The default implementation has no effect. + * \see moveContent() + */ + virtual void setMoveContentPreviewOffset( double dx, double dy ); + /** * Zooms content of item. Does nothing by default. * \param factor zoom factor, where > 1 results in a zoom in and < 1 results in a zoom out diff --git a/src/core/layout/qgslayoutitemmap.cpp b/src/core/layout/qgslayoutitemmap.cpp index 841eb7ce2d7..edca7e41830 100644 --- a/src/core/layout/qgslayoutitemmap.cpp +++ b/src/core/layout/qgslayoutitemmap.cpp @@ -300,7 +300,7 @@ void QgsLayoutItemMap::moveContent( double dx, double dy ) transformShift( dx, dy ); mExtent.setXMinimum( mExtent.xMinimum() + dx ); mExtent.setXMaximum( mExtent.xMaximum() + dx ); - mExtent.setYMinimum( mExtent.xMinimum() + dy ); + mExtent.setYMinimum( mExtent.yMinimum() + dy ); mExtent.setYMaximum( mExtent.yMaximum() + dy ); //in case data defined extents are set, these override the calculated values @@ -746,7 +746,7 @@ QgsMapSettings QgsLayoutItemMap::mapSettings( const QgsRectangle &extent, QSizeF return jobMapSettings; } -void QgsLayoutItemMap::setOffset( double xOffset, double yOffset ) +void QgsLayoutItemMap::setMoveContentPreviewOffset( double xOffset, double yOffset ) { mXOffset = xOffset; mYOffset = yOffset; diff --git a/src/core/layout/qgslayoutitemmap.h b/src/core/layout/qgslayoutitemmap.h index 38e1ed63877..54b1390a4e0 100644 --- a/src/core/layout/qgslayoutitemmap.h +++ b/src/core/layout/qgslayoutitemmap.h @@ -265,6 +265,8 @@ class CORE_EXPORT QgsLayoutItemMap : public QgsLayoutItem void setFollowVisibilityPresetName( const QString &name ) { mFollowVisibilityPresetName = name; } void moveContent( double dx, double dy ) override; + void setMoveContentPreviewOffset( double dx, double dy ) override; + void zoomContent( double factor, QPointF point ) override; @@ -390,9 +392,6 @@ class CORE_EXPORT QgsLayoutItemMap : public QgsLayoutItem QgsRectangle extent() const {return mExtent;} #endif - //! Sets offset values to shift image (useful for live updates when moving item content) - void setOffset( double xOffset, double yOffset ); - #if 0 /** diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index 958aae4a207..a9a225a8795 100755 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -172,6 +172,7 @@ SET(QGIS_GUI_SRCS layout/qgslayoutviewtooladditem.cpp layout/qgslayoutviewtooladdnodeitem.cpp layout/qgslayoutviewtooleditnodes.cpp + layout/qgslayoutviewtoolmoveitemcontent.cpp layout/qgslayoutviewtoolpan.cpp layout/qgslayoutviewtoolselect.cpp layout/qgslayoutviewtooltemporarykeypan.cpp @@ -677,6 +678,7 @@ SET(QGIS_GUI_MOC_HDRS layout/qgslayoutviewtooladditem.h layout/qgslayoutviewtooladdnodeitem.h layout/qgslayoutviewtooleditnodes.h + layout/qgslayoutviewtoolmoveitemcontent.h layout/qgslayoutviewtoolpan.h layout/qgslayoutviewtoolselect.h layout/qgslayoutviewtooltemporarykeypan.h diff --git a/src/gui/layout/qgslayoutmousehandles.cpp b/src/gui/layout/qgslayoutmousehandles.cpp index 4f22cb9be77..441ea87c9fc 100644 --- a/src/gui/layout/qgslayoutmousehandles.cpp +++ b/src/gui/layout/qgslayoutmousehandles.cpp @@ -689,11 +689,13 @@ void QgsLayoutMouseHandles::mouseReleaseEvent( QGraphicsSceneMouseEvent *event ) void QgsLayoutMouseHandles::resetStatusBar() { + if ( !mView ) + return; + const QList selectedItems = mLayout->selectedLayoutItems( false ); int selectedCount = selectedItems.size(); if ( selectedCount > 1 ) { - //set status bar message to count of selected items mView->pushStatusMessage( tr( "%1 items selected" ).arg( selectedCount ) ); } diff --git a/src/gui/layout/qgslayoutruler.cpp b/src/gui/layout/qgslayoutruler.cpp index babf4b1cba6..d2c6cebc7ee 100644 --- a/src/gui/layout/qgslayoutruler.cpp +++ b/src/gui/layout/qgslayoutruler.cpp @@ -338,7 +338,8 @@ void QgsLayoutRuler::drawGuideAtPos( QPainter *painter, QPoint pos ) void QgsLayoutRuler::createTemporaryGuideItem() { - mGuideItem.reset( new QGraphicsLineItem() ); + delete mGuideItem; + mGuideItem = new QGraphicsLineItem(); mGuideItem->setZValue( QgsLayout::ZGuide ); QPen linePen( Qt::DotLine ); @@ -346,7 +347,7 @@ void QgsLayoutRuler::createTemporaryGuideItem() linePen.setWidthF( 0 ); mGuideItem->setPen( linePen ); - mView->currentLayout()->addItem( mGuideItem.get() ); + mView->currentLayout()->addItem( mGuideItem ); } QPointF QgsLayoutRuler::convertLocalPointToLayout( QPoint localPoint ) const @@ -735,7 +736,8 @@ void QgsLayoutRuler::mouseReleaseEvent( QMouseEvent *event ) { mCreatingGuide = false; QApplication::restoreOverrideCursor(); - mGuideItem.reset(); + delete mGuideItem; + mGuideItem = nullptr; // check that cursor left the ruler switch ( mOrientation ) diff --git a/src/gui/layout/qgslayoutruler.h b/src/gui/layout/qgslayoutruler.h index 7cc4f238c93..68828ee71f1 100644 --- a/src/gui/layout/qgslayoutruler.h +++ b/src/gui/layout/qgslayoutruler.h @@ -121,7 +121,7 @@ class GUI_EXPORT QgsLayoutRuler: public QWidget QgsLayoutGuide *mHoverGuide = nullptr; bool mCreatingGuide = false; - std::unique_ptr< QGraphicsLineItem > mGuideItem; + QGraphicsLineItem *mGuideItem = nullptr; //! Polygon for drawing guide markers QPolygonF mGuideMarker; diff --git a/src/gui/layout/qgslayoutview.cpp b/src/gui/layout/qgslayoutview.cpp index b8056008769..4847d75cd6c 100644 --- a/src/gui/layout/qgslayoutview.cpp +++ b/src/gui/layout/qgslayoutview.cpp @@ -54,7 +54,7 @@ QgsLayoutView::QgsLayoutView( QWidget *parent ) mSpacePanTool = new QgsLayoutViewToolTemporaryKeyPan( this ); mMidMouseButtonPanTool = new QgsLayoutViewToolTemporaryMousePan( this ); mSpaceZoomTool = new QgsLayoutViewToolTemporaryKeyZoom( this ); - mSnapMarker.reset( new QgsLayoutViewSnapMarker() ); + mSnapMarker = new QgsLayoutViewSnapMarker(); mPreviewEffect = new QgsPreviewEffect( this ); viewport()->setGraphicsEffect( mPreviewEffect ); @@ -81,16 +81,19 @@ void QgsLayoutView::setCurrentLayout( QgsLayout *layout ) viewChanged(); - mSnapMarker.reset( new QgsLayoutViewSnapMarker() ); + delete mSnapMarker; + mSnapMarker = new QgsLayoutViewSnapMarker(); mSnapMarker->hide(); - layout->addItem( mSnapMarker.get() ); + layout->addItem( mSnapMarker ); - mHorizontalSnapLine.reset( createSnapLine() ); + delete mHorizontalSnapLine; + mHorizontalSnapLine = createSnapLine(); mHorizontalSnapLine->hide(); - layout->addItem( mHorizontalSnapLine.get() ); - mVerticalSnapLine.reset( createSnapLine() ); + layout->addItem( mHorizontalSnapLine ); + delete mVerticalSnapLine; + mVerticalSnapLine = createSnapLine(); mVerticalSnapLine->hide(); - layout->addItem( mVerticalSnapLine.get() ); + layout->addItem( mVerticalSnapLine ); if ( mHorizontalRuler ) { @@ -771,7 +774,7 @@ void QgsLayoutView::mouseMoveEvent( QMouseEvent *event ) std::unique_ptr me( new QgsLayoutViewMouseEvent( this, event, false ) ); if ( mTool->flags() & QgsLayoutViewTool::FlagSnaps ) { - me->snapPoint( mHorizontalSnapLine.get(), mVerticalSnapLine.get(), mTool->ignoredSnapItems() ); + me->snapPoint( mHorizontalSnapLine, mVerticalSnapLine, mTool->ignoredSnapItems() ); } if ( mTool->flags() & QgsLayoutViewTool::FlagSnaps ) { diff --git a/src/gui/layout/qgslayoutview.h b/src/gui/layout/qgslayoutview.h index 8cbe1e8f426..a9869e3ef1b 100644 --- a/src/gui/layout/qgslayoutview.h +++ b/src/gui/layout/qgslayoutview.h @@ -470,10 +470,10 @@ class GUI_EXPORT QgsLayoutView: public QGraphicsView QgsLayoutRuler *mVerticalRuler = nullptr; std::unique_ptr< QgsLayoutViewMenuProvider > mMenuProvider; - std::unique_ptr< QgsLayoutViewSnapMarker > mSnapMarker; + QgsLayoutViewSnapMarker *mSnapMarker = nullptr; - std::unique_ptr< QGraphicsLineItem > mHorizontalSnapLine; - std::unique_ptr< QGraphicsLineItem > mVerticalSnapLine; + QGraphicsLineItem *mHorizontalSnapLine = nullptr; + QGraphicsLineItem *mVerticalSnapLine = nullptr; int mCurrentPage = 0; diff --git a/src/gui/layout/qgslayoutviewtoolmoveitemcontent.cpp b/src/gui/layout/qgslayoutviewtoolmoveitemcontent.cpp new file mode 100644 index 00000000000..f66c82876b4 --- /dev/null +++ b/src/gui/layout/qgslayoutviewtoolmoveitemcontent.cpp @@ -0,0 +1,122 @@ +/*************************************************************************** + qgslayoutviewtoolmoveitemcontent.cpp + ------------------------------------ + 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. * + * * + ***************************************************************************/ + +#include "qgslayoutviewtoolmoveitemcontent.h" +#include "qgslayoutviewmouseevent.h" +#include "qgslayoutview.h" +#include "qgslayout.h" +#include "qgslayoutitemnodeitem.h" +#include "qgssettings.h" + +QgsLayoutViewToolMoveItemContent::QgsLayoutViewToolMoveItemContent( QgsLayoutView *view ) + : QgsLayoutViewTool( view, tr( "Select" ) ) +{ + setCursor( Qt::ArrowCursor ); +} + +void QgsLayoutViewToolMoveItemContent::layoutPressEvent( QgsLayoutViewMouseEvent *event ) +{ + if ( event->button() != Qt::LeftButton ) + { + event->ignore(); + return; + } + + const QList itemsAtCursorPos = view()->items( event->pos() ); + if ( itemsAtCursorPos.isEmpty() ) + return; + + //find highest non-locked QgsLayoutItem at clicked position + //(other graphics items may be higher, e.g., selection handles) + for ( QGraphicsItem *graphicsItem : itemsAtCursorPos ) + { + QgsLayoutItem *item = dynamic_cast( graphicsItem ); + if ( item && !item->isLocked() ) + { + //we've found the highest QgsLayoutItem + mMoveContentStartPos = event->layoutPoint(); + mMoveContentItem = item; + mMovingItemContent = true; + break; + } + } +} + +void QgsLayoutViewToolMoveItemContent::layoutMoveEvent( QgsLayoutViewMouseEvent *event ) +{ + if ( !mMovingItemContent || !mMoveContentItem ) + { + event->ignore(); + return; + } + + //update item preview + mMoveContentItem->setMoveContentPreviewOffset( event->layoutPoint().x() - mMoveContentStartPos.x(), + event->layoutPoint().y() - mMoveContentStartPos.y() ); + mMoveContentItem->update(); +} + +void QgsLayoutViewToolMoveItemContent::layoutReleaseEvent( QgsLayoutViewMouseEvent *event ) +{ + if ( event->button() != Qt::LeftButton || !mMovingItemContent || !mMoveContentItem ) + { + event->ignore(); + return; + } + + //update item preview + mMoveContentItem->setMoveContentPreviewOffset( 0, 0 ); + + double moveX = event->layoutPoint().x() - mMoveContentStartPos.x(); + double moveY = event->layoutPoint().y() - mMoveContentStartPos.y(); + + mMoveContentItem->layout()->undoStack()->beginCommand( mMoveContentItem, tr( "Move Item Content" ) ); + mMoveContentItem->moveContent( -moveX, -moveY ); + mMoveContentItem->layout()->undoStack()->endCommand(); + mMoveContentItem = nullptr; + mMovingItemContent = false; +} + +void QgsLayoutViewToolMoveItemContent::wheelEvent( QWheelEvent *event ) +{ + event->accept(); + + QPointF scenePoint = view()->mapToScene( event->pos() ); + //select topmost item at position of event + QgsLayoutItem *item = layout()->layoutItemAt( scenePoint, true ); + if ( !item || !item->isSelected() ) + return; + + QgsSettings settings; + double zoomFactor = settings.value( QStringLiteral( "qgis/zoom_factor" ), 2.0 ).toDouble(); + + // "Normal" mouse have an angle delta of 120, precision mouses provide data faster, in smaller steps + zoomFactor = 1.0 + ( zoomFactor - 1.0 ) / 120.0 * std::fabs( event->angleDelta().y() ); + + if ( event->modifiers() & Qt::ControlModifier ) + { + //holding ctrl while wheel zooming results in a finer zoom + zoomFactor = 1.0 + ( zoomFactor - 1.0 ) / 20.0; + } + + //calculate zoom scale factor + bool zoomIn = event->angleDelta().y() > 0; + double scaleFactor = ( zoomIn ? zoomFactor : 1 / zoomFactor ); + + QPointF itemPoint = item->mapFromScene( scenePoint ); + item->layout()->undoStack()->beginCommand( item, tr( "Zoom Item Content" ), QgsLayoutItem::UndoZoomContent ); + item->zoomContent( scaleFactor, itemPoint ); + item->layout()->undoStack()->endCommand(); +} diff --git a/src/gui/layout/qgslayoutviewtoolmoveitemcontent.h b/src/gui/layout/qgslayoutviewtoolmoveitemcontent.h new file mode 100644 index 00000000000..695f24603ca --- /dev/null +++ b/src/gui/layout/qgslayoutviewtoolmoveitemcontent.h @@ -0,0 +1,56 @@ +/*************************************************************************** + qgslayoutviewtoolmoveitemcontent.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 QGSLAYOUTVIEWTOOLMOVEITEMCONTENT_H +#define QGSLAYOUTVIEWTOOLMOVEITEMCONTENT_H + +#include "qgis.h" +#include "qgis_gui.h" +#include "qgslayoutviewtool.h" + +/** + * \ingroup gui + * Layout view tool for moving and zooming item content. + * \since QGIS 3.0 + */ +class GUI_EXPORT QgsLayoutViewToolMoveItemContent : public QgsLayoutViewTool +{ + + Q_OBJECT + + public: + + /** + * Constructor for QgsLayoutViewToolMoveItemContent. + */ + QgsLayoutViewToolMoveItemContent( QgsLayoutView *view SIP_TRANSFERTHIS ); + + void layoutPressEvent( QgsLayoutViewMouseEvent *event ) override; + void layoutMoveEvent( QgsLayoutViewMouseEvent *event ) override; + void layoutReleaseEvent( QgsLayoutViewMouseEvent *event ) override; + void wheelEvent( QWheelEvent *event ) override; + + private: + + //! Item to move content + QgsLayoutItem *mMoveContentItem = nullptr; + + //! Start position of content move + QPointF mMoveContentStartPos; + + bool mMovingItemContent = false; +}; + +#endif // QGSLAYOUTVIEWTOOLMOVEITEMCONTENT_H diff --git a/src/ui/layout/qgslayoutdesignerbase.ui b/src/ui/layout/qgslayoutdesignerbase.ui index 5e2d1ac01c9..162a823d995 100644 --- a/src/ui/layout/qgslayoutdesignerbase.ui +++ b/src/ui/layout/qgslayoutdesignerbase.ui @@ -76,6 +76,7 @@ + @@ -84,7 +85,7 @@ 0 0 1083 - 25 + 42 @@ -1025,6 +1026,24 @@ Edit Nodes Item + + + true + + + + :/images/themes/default/mActionMoveItemContent.svg:/images/themes/default/mActionMoveItemContent.svg + + + Move &Content + + + Move item content + + + C + + @@ -1053,7 +1072,6 @@ -