diff --git a/python/gui/layout/qgslayoutruler.sip b/python/gui/layout/qgslayoutruler.sip index cd0d5ff19f3..9316109b843 100644 --- a/python/gui/layout/qgslayoutruler.sip +++ b/python/gui/layout/qgslayoutruler.sip @@ -72,6 +72,10 @@ class QgsLayoutRuler: QWidget virtual void mouseMoveEvent( QMouseEvent *event ); + virtual void mousePressEvent( QMouseEvent *event ); + + virtual void mouseReleaseEvent( QMouseEvent *event ); + signals: void cursorPosChanged( QPointF ); diff --git a/src/core/layout/qgslayoutguidecollection.cpp b/src/core/layout/qgslayoutguidecollection.cpp index 861fe5b8a80..73ed17d8323 100644 --- a/src/core/layout/qgslayoutguidecollection.cpp +++ b/src/core/layout/qgslayoutguidecollection.cpp @@ -80,7 +80,7 @@ void QgsLayoutGuide::update() switch ( mOrientation ) { case Horizontal: - if ( layoutPos > page->rect().width() ) + if ( layoutPos > page->rect().height() ) { mLineItem->hide(); } @@ -93,7 +93,7 @@ void QgsLayoutGuide::update() break; case Vertical: - if ( layoutPos > page->rect().height() ) + if ( layoutPos > page->rect().width() ) { mLineItem->hide(); } diff --git a/src/gui/layout/qgslayoutruler.cpp b/src/gui/layout/qgslayoutruler.cpp index 1b55093e8ba..dc8b18fe985 100644 --- a/src/gui/layout/qgslayoutruler.cpp +++ b/src/gui/layout/qgslayoutruler.cpp @@ -428,22 +428,118 @@ void QgsLayoutRuler::mouseMoveEvent( QMouseEvent *event ) mMarkerPos = event->posF(); update(); - //update cursor position in status bar - QPointF displayPos = mTransform.inverted().map( event->posF() ); - switch ( mOrientation ) + QPointF displayPos; + if ( mCreatingGuide ) { - case Qt::Horizontal: + // event -> layout coordinates + QgsLayout *layout = mView->currentLayout(); + QPoint viewPoint = mView->mapFromGlobal( mapToGlobal( event->pos() ) ); + displayPos = mView->mapToScene( viewPoint ); + int pageNo = layout->pageCollection()->pageNumberForPoint( displayPos ); + QgsLayoutItemPage *page = layout->pageCollection()->page( pageNo ); + + switch ( mOrientation ) { - //mouse is over a horizontal ruler, so don't show a y coordinate - displayPos.setY( 0 ); - break; + case Qt::Horizontal: + { + //mouse is creating a horizontal ruler, so don't show x coordinate + mGuideItem->setLine( 0, displayPos.y(), page->rect().width(), displayPos.y() ); + displayPos.setX( 0 ); + break; + } + case Qt::Vertical: + { + //mouse is creating a vertical ruler, so don't show a y coordinate + mGuideItem->setLine( displayPos.x(), 0, displayPos.x(), page->rect().height() ); + displayPos.setY( 0 ); + break; + } } - case Qt::Vertical: + } + else + { + //update cursor position in status bar + displayPos = mTransform.inverted().map( event->posF() ); + switch ( mOrientation ) { - //mouse is over a vertical ruler, so don't show an x coordinate - displayPos.setX( 0 ); - break; + case Qt::Horizontal: + { + //mouse is over a horizontal ruler, so don't show a y coordinate + displayPos.setY( 0 ); + break; + } + case Qt::Vertical: + { + //mouse is over a vertical ruler, so don't show an x coordinate + displayPos.setX( 0 ); + break; + } } } emit cursorPosChanged( displayPos ); } + +void QgsLayoutRuler::mousePressEvent( QMouseEvent *event ) +{ + if ( event->button() == Qt::LeftButton ) + { + mCreatingGuide = true; + mGuideItem.reset( new QGraphicsLineItem() ); + + mGuideItem->setZValue( QgsLayout::ZGuide ); + QPen linePen( Qt::DashLine ); + linePen.setColor( Qt::red ); + linePen.setWidthF( 0 ); + mGuideItem->setPen( linePen ); + + mView->currentLayout()->addItem( mGuideItem.get() ); + + switch ( mOrientation ) + { + case Qt::Horizontal: + { + QApplication::setOverrideCursor( Qt::SplitVCursor ); + break; + } + case Qt::Vertical: + QApplication::setOverrideCursor( Qt::SplitHCursor ); + break; + } + } +} + +void QgsLayoutRuler::mouseReleaseEvent( QMouseEvent *event ) +{ + if ( event->button() == Qt::LeftButton ) + { + mCreatingGuide = false; + QApplication::restoreOverrideCursor(); + mGuideItem.reset(); + + QgsLayout *layout = mView->currentLayout(); + + // create guide + QPoint viewPoint = mView->mapFromGlobal( mapToGlobal( event->pos() ) ); + QPointF scenePos = mView->mapToScene( viewPoint ); + int page = layout->pageCollection()->pageNumberForPoint( scenePos ); + std::unique_ptr< QgsLayoutGuide > guide; + switch ( mOrientation ) + { + case Qt::Horizontal: + { + //mouse is creating a horizontal guide + double posOnPage = layout->pageCollection()->positionOnPage( scenePos ).y(); + guide.reset( new QgsLayoutGuide( QgsLayoutGuide::Horizontal, QgsLayoutMeasurement( posOnPage, layout->units() ) ) ); + break; + } + case Qt::Vertical: + { + //mouse is creating a vertical guide + guide.reset( new QgsLayoutGuide( QgsLayoutGuide::Vertical, QgsLayoutMeasurement( scenePos.x(), layout->units() ) ) ); + break; + } + } + guide->setPage( page ); + mView->currentLayout()->guides().addGuide( guide.release() ); + } +} diff --git a/src/gui/layout/qgslayoutruler.h b/src/gui/layout/qgslayoutruler.h index 246e7b1f081..01560bfe2c2 100644 --- a/src/gui/layout/qgslayoutruler.h +++ b/src/gui/layout/qgslayoutruler.h @@ -81,6 +81,8 @@ class GUI_EXPORT QgsLayoutRuler: public QWidget protected: void paintEvent( QPaintEvent *event ) override; void mouseMoveEvent( QMouseEvent *event ) override; + void mousePressEvent( QMouseEvent *event ) override; + void mouseReleaseEvent( QMouseEvent *event ) override; private: static const int VALID_SCALE_MULTIPLES[]; @@ -102,6 +104,9 @@ class GUI_EXPORT QgsLayoutRuler: public QWidget int mTextBaseline; int mMinSpacingVerticalLabels; + bool mCreatingGuide = false; + std::unique_ptr< QGraphicsLineItem > mGuideItem; + //! Calculates the optimum labeled units for ruler so that labels are a good distance apart int optimumScale( double minPixelDiff, int &magnitude, int &multiple );