Skip to content

Commit c6c9c6f

Browse files
committedAug 7, 2017
Show guide positions in rulers
1 parent ab726c4 commit c6c9c6f

File tree

7 files changed

+129
-11
lines changed

7 files changed

+129
-11
lines changed
 

‎python/core/layout/qgslayoutguidecollection.sip

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,10 +181,11 @@ class QgsLayoutGuideCollection : QAbstractTableModel
181181
Updates the position (and visibility) of all guide line items.
182182
%End
183183

184-
QList< QgsLayoutGuide * > guides( QgsLayoutGuide::Orientation orientation );
184+
QList< QgsLayoutGuide * > guides( QgsLayoutGuide::Orientation orientation, int page = -1 );
185185
%Docstring
186186
Returns the list of guides contained in the collection with the specified
187-
``orientation``.
187+
``orientation`` and on a matching ``page``.
188+
If ``page`` is -1, guides from all pages will be returned.
188189
:rtype: list of QgsLayoutGuide
189190
%End
190191

‎src/core/layout/qgslayoutguidecollection.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,10 +117,10 @@ double QgsLayoutGuide::layoutPosition() const
117117
switch ( mOrientation )
118118
{
119119
case Horizontal:
120-
return mLineItem->line().y1();
120+
return mLineItem->mapToScene( mLineItem->line().p1() ).y();
121121

122122
case Vertical:
123-
return mLineItem->line().x1();
123+
return mLineItem->mapToScene( mLineItem->line().p1() ).x();
124124
}
125125
return -999; // avoid warning
126126
}
@@ -237,6 +237,7 @@ bool QgsLayoutGuideCollection::setData( const QModelIndex &index, const QVariant
237237
m.setLength( newPos );
238238
whileBlocking( guide )->setPosition( m );
239239
guide->update();
240+
emit dataChanged( index, index, QVector<int>() << role );
240241
return true;
241242
}
242243
case PositionRole:
@@ -250,6 +251,7 @@ bool QgsLayoutGuideCollection::setData( const QModelIndex &index, const QVariant
250251
m.setLength( newPos );
251252
whileBlocking( guide )->setPosition( m );
252253
guide->update();
254+
emit dataChanged( index, index, QVector<int>() << role );
253255
return true;
254256
}
255257
case UnitsRole:
@@ -263,6 +265,7 @@ bool QgsLayoutGuideCollection::setData( const QModelIndex &index, const QVariant
263265
m.setUnits( static_cast< QgsUnitTypes::LayoutUnit >( units ) );
264266
whileBlocking( guide )->setPosition( m );
265267
guide->update();
268+
emit dataChanged( index, index, QVector<int>() << role );
266269
return true;
267270
}
268271
}
@@ -325,12 +328,13 @@ void QgsLayoutGuideCollection::update()
325328
}
326329
}
327330

328-
QList<QgsLayoutGuide *> QgsLayoutGuideCollection::guides( QgsLayoutGuide::Orientation orientation )
331+
QList<QgsLayoutGuide *> QgsLayoutGuideCollection::guides( QgsLayoutGuide::Orientation orientation, int page )
329332
{
330333
QList<QgsLayoutGuide *> res;
331334
Q_FOREACH ( QgsLayoutGuide *guide, mGuides )
332335
{
333-
if ( guide->orientation() == orientation && guide->item()->isVisible() )
336+
if ( guide->orientation() == orientation && guide->item()->isVisible() &&
337+
( page < 0 || page == guide->page() ) )
334338
res << guide;
335339
}
336340
return res;

‎src/core/layout/qgslayoutguidecollection.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -207,9 +207,10 @@ class CORE_EXPORT QgsLayoutGuideCollection : public QAbstractTableModel
207207

208208
/**
209209
* Returns the list of guides contained in the collection with the specified
210-
* \a orientation.
210+
* \a orientation and on a matching \a page.
211+
* If \a page is -1, guides from all pages will be returned.
211212
*/
212-
QList< QgsLayoutGuide * > guides( QgsLayoutGuide::Orientation orientation );
213+
QList< QgsLayoutGuide * > guides( QgsLayoutGuide::Orientation orientation, int page = -1 );
213214

214215
private:
215216

‎src/gui/layout/qgslayoutruler.cpp

Lines changed: 75 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "qgslayout.h"
1717
#include "qgis.h"
1818
#include "qgslayoutview.h"
19+
#include "qgslogger.h"
1920
#include <QDragEnterEvent>
2021
#include <QGraphicsLineItem>
2122
#include <QPainter>
@@ -52,6 +53,20 @@ QgsLayoutRuler::QgsLayoutRuler( QWidget *parent, Qt::Orientation orientation )
5253
mPixelsBetweenLineAndText = mRulerMinSize / 10;
5354
mTextBaseline = mRulerMinSize / 1.667;
5455
mMinSpacingVerticalLabels = mRulerMinSize / 5;
56+
57+
double guideMarkerSize = mRulerFontMetrics->width( "*" );
58+
switch ( mOrientation )
59+
{
60+
case Qt::Horizontal:
61+
mGuideMarker << QPoint( -guideMarkerSize / 2, mRulerMinSize - guideMarkerSize ) << QPoint( 0, mRulerMinSize ) <<
62+
QPoint( guideMarkerSize / 2, mRulerMinSize - guideMarkerSize );
63+
break;
64+
65+
case Qt::Vertical:
66+
mGuideMarker << QPoint( mRulerMinSize - guideMarkerSize, -guideMarkerSize / 2 ) << QPoint( mRulerMinSize, 0 ) <<
67+
QPoint( mRulerMinSize - guideMarkerSize, guideMarkerSize / 2 );
68+
break;
69+
}
5570
}
5671

5772
QSize QgsLayoutRuler::minimumSizeHint() const
@@ -70,6 +85,8 @@ void QgsLayoutRuler::paintEvent( QPaintEvent *event )
7085
QgsLayout *layout = mView->currentLayout();
7186
QPainter p( this );
7287

88+
drawGuideMarkers( &p, layout );
89+
7390
QTransform t = mTransform.inverted();
7491
p.setFont( mRulerFont );
7592
// keep same default color, but lower opacity a tad
@@ -260,6 +277,56 @@ void QgsLayoutRuler::drawMarkerPos( QPainter *painter )
260277
}
261278
}
262279

280+
void QgsLayoutRuler::drawGuideMarkers( QPainter *p, QgsLayout *layout )
281+
{
282+
QList< int > visiblePageNumbers = mView->visiblePageNumbers();
283+
QList< QgsLayoutGuide * > guides = layout->guides().guides( mOrientation == Qt::Horizontal ? QgsLayoutGuide::Vertical : QgsLayoutGuide::Horizontal );
284+
p->save();
285+
p->setRenderHint( QPainter::Antialiasing, true );
286+
p->setBrush( QBrush( QColor( 255, 0, 0 ) ) );
287+
p->setPen( Qt::NoPen );
288+
Q_FOREACH ( QgsLayoutGuide *guide, guides )
289+
{
290+
if ( visiblePageNumbers.contains( guide->page() ) )
291+
{
292+
QPointF point;
293+
switch ( mOrientation )
294+
{
295+
case Qt::Horizontal:
296+
point = QPointF( guide->layoutPosition(), 0 );
297+
break;
298+
299+
case Qt::Vertical:
300+
point = QPointF( 0, guide->layoutPosition() );
301+
break;
302+
}
303+
drawGuideAtPos( p, convertLayoutPointToLocal( point ) );
304+
}
305+
}
306+
p->restore();
307+
}
308+
309+
void QgsLayoutRuler::drawGuideAtPos( QPainter *painter, QPoint pos )
310+
{
311+
switch ( mOrientation )
312+
{
313+
case Qt::Horizontal:
314+
{
315+
painter->translate( pos.x(), 0 );
316+
painter->drawPolygon( mGuideMarker );
317+
painter->translate( -pos.x(), 0 );
318+
break;
319+
}
320+
case Qt::Vertical:
321+
{
322+
painter->translate( 0, pos.y() );
323+
painter->drawPolygon( mGuideMarker );
324+
painter->translate( 0, -pos.y() );
325+
break;
326+
}
327+
}
328+
}
329+
263330
void QgsLayoutRuler::createTemporaryGuideItem()
264331
{
265332
mGuideItem.reset( new QGraphicsLineItem() );
@@ -279,6 +346,12 @@ QPointF QgsLayoutRuler::convertLocalPointToLayout( QPoint localPoint ) const
279346
return mView->mapToScene( viewPoint );
280347
}
281348

349+
QPoint QgsLayoutRuler::convertLayoutPointToLocal( QPointF layoutPoint ) const
350+
{
351+
QPoint viewPoint = mView->mapFromScene( layoutPoint );
352+
return mapFromGlobal( mView->mapToGlobal( viewPoint ) );
353+
}
354+
282355
void QgsLayoutRuler::drawRotatedText( QPainter *painter, QPointF pos, const QString &text )
283356
{
284357
painter->save();
@@ -467,20 +540,19 @@ void QgsLayoutRuler::mouseMoveEvent( QMouseEvent *event )
467540
linePen.setColor( QColor( 255, 0, 0, 225 ) );
468541
}
469542
mGuideItem->setPen( linePen );
470-
471543
switch ( mOrientation )
472544
{
473545
case Qt::Horizontal:
474546
{
475547
//mouse is creating a horizontal ruler, so don't show x coordinate
476-
mGuideItem->setLine( 0, displayPos.y(), page->rect().width(), displayPos.y() );
548+
mGuideItem->setLine( page->scenePos().x(), displayPos.y(), page->scenePos().x() + page->rect().width(), displayPos.y() );
477549
displayPos.setX( 0 );
478550
break;
479551
}
480552
case Qt::Vertical:
481553
{
482554
//mouse is creating a vertical ruler, so don't show a y coordinate
483-
mGuideItem->setLine( displayPos.x(), 0, displayPos.x(), page->rect().height() );
555+
mGuideItem->setLine( displayPos.x(), page->scenePos().y(), displayPos.x(), page->scenePos().y() + page->rect().height() );
484556
displayPos.setY( 0 );
485557
break;
486558
}

‎src/gui/layout/qgslayoutruler.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,9 @@ class GUI_EXPORT QgsLayoutRuler: public QWidget
111111
bool mCreatingGuide = false;
112112
std::unique_ptr< QGraphicsLineItem > mGuideItem;
113113

114+
//! Polygon for drawing guide markers
115+
QPolygonF mGuideMarker;
116+
114117
//! Calculates the optimum labeled units for ruler so that labels are a good distance apart
115118
int optimumScale( double minPixelDiff, int &magnitude, int &multiple );
116119

@@ -133,10 +136,17 @@ class GUI_EXPORT QgsLayoutRuler: public QWidget
133136
//! Draw current marker pos on ruler
134137
void drawMarkerPos( QPainter *painter );
135138

139+
void drawGuideMarkers( QPainter *painter, QgsLayout *layout );
140+
141+
//! Draw a guide marker on the ruler
142+
void drawGuideAtPos( QPainter *painter, QPoint pos );
143+
136144
void createTemporaryGuideItem();
137145

138146
QPointF convertLocalPointToLayout( QPoint localPoint ) const;
139147

148+
QPoint convertLayoutPointToLocal( QPointF layoutPoint ) const;
149+
140150

141151
};
142152

‎src/gui/layout/qgslayoutview.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,19 @@ void QgsLayoutView::setCurrentLayout( QgsLayout *layout )
7373
mSnapMarker->hide();
7474
layout->addItem( mSnapMarker.get() );
7575

76+
if ( mHorizontalRuler )
77+
{
78+
connect( &layout->guides(), &QAbstractItemModel::dataChanged, mHorizontalRuler, [ = ] { mHorizontalRuler->update(); } );
79+
connect( &layout->guides(), &QAbstractItemModel::rowsInserted, mHorizontalRuler, [ = ] { mHorizontalRuler->update(); } );
80+
connect( &layout->guides(), &QAbstractItemModel::rowsRemoved, mHorizontalRuler, [ = ] { mHorizontalRuler->update(); } );
81+
}
82+
if ( mVerticalRuler )
83+
{
84+
connect( &layout->guides(), &QAbstractItemModel::dataChanged, mVerticalRuler, [ = ] { mVerticalRuler->update(); } );
85+
connect( &layout->guides(), &QAbstractItemModel::rowsInserted, mVerticalRuler, [ = ] { mVerticalRuler->update(); } );
86+
connect( &layout->guides(), &QAbstractItemModel::rowsRemoved, mVerticalRuler, [ = ] { mVerticalRuler->update(); } );
87+
}
88+
7689
//emit layoutSet, so that designer dialogs can update for the new layout
7790
emit layoutSet( layout );
7891
}
@@ -148,13 +161,25 @@ void QgsLayoutView::setHorizontalRuler( QgsLayoutRuler *ruler )
148161
{
149162
mHorizontalRuler = ruler;
150163
ruler->setLayoutView( this );
164+
if ( QgsLayout *layout = currentLayout() )
165+
{
166+
connect( &layout->guides(), &QAbstractItemModel::dataChanged, ruler, [ = ] { mHorizontalRuler->update(); } );
167+
connect( &layout->guides(), &QAbstractItemModel::rowsInserted, ruler, [ = ] { mHorizontalRuler->update(); } );
168+
connect( &layout->guides(), &QAbstractItemModel::rowsRemoved, ruler, [ = ] { mHorizontalRuler->update(); } );
169+
}
151170
viewChanged();
152171
}
153172

154173
void QgsLayoutView::setVerticalRuler( QgsLayoutRuler *ruler )
155174
{
156175
mVerticalRuler = ruler;
157176
ruler->setLayoutView( this );
177+
if ( QgsLayout *layout = currentLayout() )
178+
{
179+
connect( &layout->guides(), &QAbstractItemModel::dataChanged, ruler, [ = ] { mVerticalRuler->update(); } );
180+
connect( &layout->guides(), &QAbstractItemModel::rowsInserted, ruler, [ = ] { mVerticalRuler->update(); } );
181+
connect( &layout->guides(), &QAbstractItemModel::rowsRemoved, ruler, [ = ] { mVerticalRuler->update(); } );
182+
}
158183
viewChanged();
159184
}
160185

‎tests/src/python/test_qgslayoutguides.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,12 @@ def testCollection(self):
149149
self.assertEqual(guides.data(guides.index(2, 0), QgsLayoutGuideCollection.UnitsRole), QgsUnitTypes.LayoutMillimeters)
150150
self.assertEqual(guides.data(guides.index(2, 0), QgsLayoutGuideCollection.PageRole), 1)
151151
self.assertEqual(guides.guides(QgsLayoutGuide.Horizontal), [g1, g2])
152+
self.assertEqual(guides.guides(QgsLayoutGuide.Horizontal, 0), [g1, g2])
153+
self.assertEqual(guides.guides(QgsLayoutGuide.Horizontal, 1), [])
152154
self.assertEqual(guides.guides(QgsLayoutGuide.Vertical), [g3])
155+
self.assertEqual(guides.guides(QgsLayoutGuide.Vertical, 0), [])
156+
self.assertEqual(guides.guides(QgsLayoutGuide.Vertical, 1), [g3])
157+
self.assertEqual(guides.guides(QgsLayoutGuide.Vertical, 2), [])
153158

154159
def testDeleteRows(self):
155160
p = QgsProject()

0 commit comments

Comments
 (0)
Please sign in to comment.