mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-13 00:03:09 -04:00
Show guide positions in rulers
This commit is contained in:
parent
ab726c4777
commit
c6c9c6fabf
@ -181,10 +181,11 @@ class QgsLayoutGuideCollection : QAbstractTableModel
|
||||
Updates the position (and visibility) of all guide line items.
|
||||
%End
|
||||
|
||||
QList< QgsLayoutGuide * > guides( QgsLayoutGuide::Orientation orientation );
|
||||
QList< QgsLayoutGuide * > guides( QgsLayoutGuide::Orientation orientation, int page = -1 );
|
||||
%Docstring
|
||||
Returns the list of guides contained in the collection with the specified
|
||||
``orientation``.
|
||||
``orientation`` and on a matching ``page``.
|
||||
If ``page`` is -1, guides from all pages will be returned.
|
||||
:rtype: list of QgsLayoutGuide
|
||||
%End
|
||||
|
||||
|
@ -117,10 +117,10 @@ double QgsLayoutGuide::layoutPosition() const
|
||||
switch ( mOrientation )
|
||||
{
|
||||
case Horizontal:
|
||||
return mLineItem->line().y1();
|
||||
return mLineItem->mapToScene( mLineItem->line().p1() ).y();
|
||||
|
||||
case Vertical:
|
||||
return mLineItem->line().x1();
|
||||
return mLineItem->mapToScene( mLineItem->line().p1() ).x();
|
||||
}
|
||||
return -999; // avoid warning
|
||||
}
|
||||
@ -237,6 +237,7 @@ bool QgsLayoutGuideCollection::setData( const QModelIndex &index, const QVariant
|
||||
m.setLength( newPos );
|
||||
whileBlocking( guide )->setPosition( m );
|
||||
guide->update();
|
||||
emit dataChanged( index, index, QVector<int>() << role );
|
||||
return true;
|
||||
}
|
||||
case PositionRole:
|
||||
@ -250,6 +251,7 @@ bool QgsLayoutGuideCollection::setData( const QModelIndex &index, const QVariant
|
||||
m.setLength( newPos );
|
||||
whileBlocking( guide )->setPosition( m );
|
||||
guide->update();
|
||||
emit dataChanged( index, index, QVector<int>() << role );
|
||||
return true;
|
||||
}
|
||||
case UnitsRole:
|
||||
@ -263,6 +265,7 @@ bool QgsLayoutGuideCollection::setData( const QModelIndex &index, const QVariant
|
||||
m.setUnits( static_cast< QgsUnitTypes::LayoutUnit >( units ) );
|
||||
whileBlocking( guide )->setPosition( m );
|
||||
guide->update();
|
||||
emit dataChanged( index, index, QVector<int>() << role );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -325,12 +328,13 @@ void QgsLayoutGuideCollection::update()
|
||||
}
|
||||
}
|
||||
|
||||
QList<QgsLayoutGuide *> QgsLayoutGuideCollection::guides( QgsLayoutGuide::Orientation orientation )
|
||||
QList<QgsLayoutGuide *> QgsLayoutGuideCollection::guides( QgsLayoutGuide::Orientation orientation, int page )
|
||||
{
|
||||
QList<QgsLayoutGuide *> res;
|
||||
Q_FOREACH ( QgsLayoutGuide *guide, mGuides )
|
||||
{
|
||||
if ( guide->orientation() == orientation && guide->item()->isVisible() )
|
||||
if ( guide->orientation() == orientation && guide->item()->isVisible() &&
|
||||
( page < 0 || page == guide->page() ) )
|
||||
res << guide;
|
||||
}
|
||||
return res;
|
||||
|
@ -207,9 +207,10 @@ class CORE_EXPORT QgsLayoutGuideCollection : public QAbstractTableModel
|
||||
|
||||
/**
|
||||
* Returns the list of guides contained in the collection with the specified
|
||||
* \a orientation.
|
||||
* \a orientation and on a matching \a page.
|
||||
* If \a page is -1, guides from all pages will be returned.
|
||||
*/
|
||||
QList< QgsLayoutGuide * > guides( QgsLayoutGuide::Orientation orientation );
|
||||
QList< QgsLayoutGuide * > guides( QgsLayoutGuide::Orientation orientation, int page = -1 );
|
||||
|
||||
private:
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "qgslayout.h"
|
||||
#include "qgis.h"
|
||||
#include "qgslayoutview.h"
|
||||
#include "qgslogger.h"
|
||||
#include <QDragEnterEvent>
|
||||
#include <QGraphicsLineItem>
|
||||
#include <QPainter>
|
||||
@ -52,6 +53,20 @@ QgsLayoutRuler::QgsLayoutRuler( QWidget *parent, Qt::Orientation orientation )
|
||||
mPixelsBetweenLineAndText = mRulerMinSize / 10;
|
||||
mTextBaseline = mRulerMinSize / 1.667;
|
||||
mMinSpacingVerticalLabels = mRulerMinSize / 5;
|
||||
|
||||
double guideMarkerSize = mRulerFontMetrics->width( "*" );
|
||||
switch ( mOrientation )
|
||||
{
|
||||
case Qt::Horizontal:
|
||||
mGuideMarker << QPoint( -guideMarkerSize / 2, mRulerMinSize - guideMarkerSize ) << QPoint( 0, mRulerMinSize ) <<
|
||||
QPoint( guideMarkerSize / 2, mRulerMinSize - guideMarkerSize );
|
||||
break;
|
||||
|
||||
case Qt::Vertical:
|
||||
mGuideMarker << QPoint( mRulerMinSize - guideMarkerSize, -guideMarkerSize / 2 ) << QPoint( mRulerMinSize, 0 ) <<
|
||||
QPoint( mRulerMinSize - guideMarkerSize, guideMarkerSize / 2 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QSize QgsLayoutRuler::minimumSizeHint() const
|
||||
@ -70,6 +85,8 @@ void QgsLayoutRuler::paintEvent( QPaintEvent *event )
|
||||
QgsLayout *layout = mView->currentLayout();
|
||||
QPainter p( this );
|
||||
|
||||
drawGuideMarkers( &p, layout );
|
||||
|
||||
QTransform t = mTransform.inverted();
|
||||
p.setFont( mRulerFont );
|
||||
// keep same default color, but lower opacity a tad
|
||||
@ -260,6 +277,56 @@ void QgsLayoutRuler::drawMarkerPos( QPainter *painter )
|
||||
}
|
||||
}
|
||||
|
||||
void QgsLayoutRuler::drawGuideMarkers( QPainter *p, QgsLayout *layout )
|
||||
{
|
||||
QList< int > visiblePageNumbers = mView->visiblePageNumbers();
|
||||
QList< QgsLayoutGuide * > guides = layout->guides().guides( mOrientation == Qt::Horizontal ? QgsLayoutGuide::Vertical : QgsLayoutGuide::Horizontal );
|
||||
p->save();
|
||||
p->setRenderHint( QPainter::Antialiasing, true );
|
||||
p->setBrush( QBrush( QColor( 255, 0, 0 ) ) );
|
||||
p->setPen( Qt::NoPen );
|
||||
Q_FOREACH ( QgsLayoutGuide *guide, guides )
|
||||
{
|
||||
if ( visiblePageNumbers.contains( guide->page() ) )
|
||||
{
|
||||
QPointF point;
|
||||
switch ( mOrientation )
|
||||
{
|
||||
case Qt::Horizontal:
|
||||
point = QPointF( guide->layoutPosition(), 0 );
|
||||
break;
|
||||
|
||||
case Qt::Vertical:
|
||||
point = QPointF( 0, guide->layoutPosition() );
|
||||
break;
|
||||
}
|
||||
drawGuideAtPos( p, convertLayoutPointToLocal( point ) );
|
||||
}
|
||||
}
|
||||
p->restore();
|
||||
}
|
||||
|
||||
void QgsLayoutRuler::drawGuideAtPos( QPainter *painter, QPoint pos )
|
||||
{
|
||||
switch ( mOrientation )
|
||||
{
|
||||
case Qt::Horizontal:
|
||||
{
|
||||
painter->translate( pos.x(), 0 );
|
||||
painter->drawPolygon( mGuideMarker );
|
||||
painter->translate( -pos.x(), 0 );
|
||||
break;
|
||||
}
|
||||
case Qt::Vertical:
|
||||
{
|
||||
painter->translate( 0, pos.y() );
|
||||
painter->drawPolygon( mGuideMarker );
|
||||
painter->translate( 0, -pos.y() );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QgsLayoutRuler::createTemporaryGuideItem()
|
||||
{
|
||||
mGuideItem.reset( new QGraphicsLineItem() );
|
||||
@ -279,6 +346,12 @@ QPointF QgsLayoutRuler::convertLocalPointToLayout( QPoint localPoint ) const
|
||||
return mView->mapToScene( viewPoint );
|
||||
}
|
||||
|
||||
QPoint QgsLayoutRuler::convertLayoutPointToLocal( QPointF layoutPoint ) const
|
||||
{
|
||||
QPoint viewPoint = mView->mapFromScene( layoutPoint );
|
||||
return mapFromGlobal( mView->mapToGlobal( viewPoint ) );
|
||||
}
|
||||
|
||||
void QgsLayoutRuler::drawRotatedText( QPainter *painter, QPointF pos, const QString &text )
|
||||
{
|
||||
painter->save();
|
||||
@ -467,20 +540,19 @@ void QgsLayoutRuler::mouseMoveEvent( QMouseEvent *event )
|
||||
linePen.setColor( QColor( 255, 0, 0, 225 ) );
|
||||
}
|
||||
mGuideItem->setPen( linePen );
|
||||
|
||||
switch ( mOrientation )
|
||||
{
|
||||
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() );
|
||||
mGuideItem->setLine( page->scenePos().x(), displayPos.y(), page->scenePos().x() + 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() );
|
||||
mGuideItem->setLine( displayPos.x(), page->scenePos().y(), displayPos.x(), page->scenePos().y() + page->rect().height() );
|
||||
displayPos.setY( 0 );
|
||||
break;
|
||||
}
|
||||
|
@ -111,6 +111,9 @@ class GUI_EXPORT QgsLayoutRuler: public QWidget
|
||||
bool mCreatingGuide = false;
|
||||
std::unique_ptr< QGraphicsLineItem > mGuideItem;
|
||||
|
||||
//! Polygon for drawing guide markers
|
||||
QPolygonF mGuideMarker;
|
||||
|
||||
//! Calculates the optimum labeled units for ruler so that labels are a good distance apart
|
||||
int optimumScale( double minPixelDiff, int &magnitude, int &multiple );
|
||||
|
||||
@ -133,10 +136,17 @@ class GUI_EXPORT QgsLayoutRuler: public QWidget
|
||||
//! Draw current marker pos on ruler
|
||||
void drawMarkerPos( QPainter *painter );
|
||||
|
||||
void drawGuideMarkers( QPainter *painter, QgsLayout *layout );
|
||||
|
||||
//! Draw a guide marker on the ruler
|
||||
void drawGuideAtPos( QPainter *painter, QPoint pos );
|
||||
|
||||
void createTemporaryGuideItem();
|
||||
|
||||
QPointF convertLocalPointToLayout( QPoint localPoint ) const;
|
||||
|
||||
QPoint convertLayoutPointToLocal( QPointF layoutPoint ) const;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
@ -73,6 +73,19 @@ void QgsLayoutView::setCurrentLayout( QgsLayout *layout )
|
||||
mSnapMarker->hide();
|
||||
layout->addItem( mSnapMarker.get() );
|
||||
|
||||
if ( mHorizontalRuler )
|
||||
{
|
||||
connect( &layout->guides(), &QAbstractItemModel::dataChanged, mHorizontalRuler, [ = ] { mHorizontalRuler->update(); } );
|
||||
connect( &layout->guides(), &QAbstractItemModel::rowsInserted, mHorizontalRuler, [ = ] { mHorizontalRuler->update(); } );
|
||||
connect( &layout->guides(), &QAbstractItemModel::rowsRemoved, mHorizontalRuler, [ = ] { mHorizontalRuler->update(); } );
|
||||
}
|
||||
if ( mVerticalRuler )
|
||||
{
|
||||
connect( &layout->guides(), &QAbstractItemModel::dataChanged, mVerticalRuler, [ = ] { mVerticalRuler->update(); } );
|
||||
connect( &layout->guides(), &QAbstractItemModel::rowsInserted, mVerticalRuler, [ = ] { mVerticalRuler->update(); } );
|
||||
connect( &layout->guides(), &QAbstractItemModel::rowsRemoved, mVerticalRuler, [ = ] { mVerticalRuler->update(); } );
|
||||
}
|
||||
|
||||
//emit layoutSet, so that designer dialogs can update for the new layout
|
||||
emit layoutSet( layout );
|
||||
}
|
||||
@ -148,6 +161,12 @@ void QgsLayoutView::setHorizontalRuler( QgsLayoutRuler *ruler )
|
||||
{
|
||||
mHorizontalRuler = ruler;
|
||||
ruler->setLayoutView( this );
|
||||
if ( QgsLayout *layout = currentLayout() )
|
||||
{
|
||||
connect( &layout->guides(), &QAbstractItemModel::dataChanged, ruler, [ = ] { mHorizontalRuler->update(); } );
|
||||
connect( &layout->guides(), &QAbstractItemModel::rowsInserted, ruler, [ = ] { mHorizontalRuler->update(); } );
|
||||
connect( &layout->guides(), &QAbstractItemModel::rowsRemoved, ruler, [ = ] { mHorizontalRuler->update(); } );
|
||||
}
|
||||
viewChanged();
|
||||
}
|
||||
|
||||
@ -155,6 +174,12 @@ void QgsLayoutView::setVerticalRuler( QgsLayoutRuler *ruler )
|
||||
{
|
||||
mVerticalRuler = ruler;
|
||||
ruler->setLayoutView( this );
|
||||
if ( QgsLayout *layout = currentLayout() )
|
||||
{
|
||||
connect( &layout->guides(), &QAbstractItemModel::dataChanged, ruler, [ = ] { mVerticalRuler->update(); } );
|
||||
connect( &layout->guides(), &QAbstractItemModel::rowsInserted, ruler, [ = ] { mVerticalRuler->update(); } );
|
||||
connect( &layout->guides(), &QAbstractItemModel::rowsRemoved, ruler, [ = ] { mVerticalRuler->update(); } );
|
||||
}
|
||||
viewChanged();
|
||||
}
|
||||
|
||||
|
@ -149,7 +149,12 @@ class TestQgsLayoutGuide(unittest.TestCase):
|
||||
self.assertEqual(guides.data(guides.index(2, 0), QgsLayoutGuideCollection.UnitsRole), QgsUnitTypes.LayoutMillimeters)
|
||||
self.assertEqual(guides.data(guides.index(2, 0), QgsLayoutGuideCollection.PageRole), 1)
|
||||
self.assertEqual(guides.guides(QgsLayoutGuide.Horizontal), [g1, g2])
|
||||
self.assertEqual(guides.guides(QgsLayoutGuide.Horizontal, 0), [g1, g2])
|
||||
self.assertEqual(guides.guides(QgsLayoutGuide.Horizontal, 1), [])
|
||||
self.assertEqual(guides.guides(QgsLayoutGuide.Vertical), [g3])
|
||||
self.assertEqual(guides.guides(QgsLayoutGuide.Vertical, 0), [])
|
||||
self.assertEqual(guides.guides(QgsLayoutGuide.Vertical, 1), [g3])
|
||||
self.assertEqual(guides.guides(QgsLayoutGuide.Vertical, 2), [])
|
||||
|
||||
def testDeleteRows(self):
|
||||
p = QgsProject()
|
||||
|
Loading…
x
Reference in New Issue
Block a user