4 #include <QDragEnterEvent> 5 #include <QGraphicsLineItem> 12 const int QgsComposerRuler::validScaleMultiples[] = {1, 2, 5};
13 const int QgsComposerRuler::validScaleMagnitudes[] = {1, 10, 100, 1000, 10000};
17 mComposition( nullptr ),
18 mLineSnapItem( nullptr ),
19 mScaleMinPixelsWidth( 0 )
24 mRulerFont =
new QFont();
31 mScaleMinPixelsWidth = mRulerFontMetrics->
width(
"000" ) * 2.5;
33 mRulerMinSize = mRulerFontMetrics->
height() * 1.5;
35 mMinPixelsPerDivision = mRulerMinSize / 4;
37 if ( mMinPixelsPerDivision < 2 )
38 mMinPixelsPerDivision = 2;
40 mPixelsBetweenLineAndText = mRulerMinSize / 10;
41 mTextBaseline = mRulerMinSize / 1.667;
42 mMinSpacingVerticalLabels = mRulerMinSize / 5;
47 delete mRulerFontMetrics;
53 return QSize( mRulerMinSize, mRulerMinSize );
74 mmDisplay = optimumScale( mScaleMinPixelsWidth, magnitude, multiple );
77 int numSmallDivisions = optimumNumberDivisions( mmDisplay, multiple );
91 double markerPos = ( floor( startX / mmDisplay ) + 1 ) * mmDisplay;
94 drawSmallDivisions( &p, markerPos, numSmallDivisions, -mmDisplay );
96 while ( markerPos <= endX )
98 double pixelCoord = mTransform.
map(
QPointF( markerPos, 0 ) ).
x();
101 p.
drawLine( pixelCoord, 0, pixelCoord, mRulerMinSize );
105 drawSmallDivisions( &p, markerPos, numSmallDivisions, mmDisplay, endX );
107 markerPos += mmDisplay;
127 double beforePageCoord = -mmDisplay;
128 double firstPageY = mTransform.
map(
QPointF( 0, 0 ) ).
y();
131 while ( beforePageCoord > startY )
133 double pixelCoord = mTransform.
map(
QPointF( 0, beforePageCoord ) ).
y();
134 p.
drawLine( 0, pixelCoord, mRulerMinSize, pixelCoord );
137 int labelSize = mRulerFontMetrics->
width( label );
140 if ( pixelCoord + labelSize + 8 < firstPageY )
142 drawRotatedText( &p,
QPointF( mTextBaseline, pixelCoord + mMinSpacingVerticalLabels + labelSize ), label );
146 drawSmallDivisions( &p, beforePageCoord, numSmallDivisions, mmDisplay );
148 beforePageCoord -= mmDisplay;
152 drawSmallDivisions( &p, beforePageCoord + mmDisplay, numSmallDivisions, -mmDisplay, startY );
156 if ( endPage > ( mComposition->
numPages() - 1 ) )
158 endPage = mComposition->
numPages() - 1;
161 double nextPageStartPos = 0;
162 int nextPageStartPixel = 0;
164 for (
int i = startPage; i <= endPage; ++i )
166 double pageCoord = 0;
175 nextPageStartPixel = mTransform.
map(
QPointF( 0, nextPageStartPos ) ).
y();
180 nextPageStartPos = 0;
181 nextPageStartPixel = 0;
184 while (( totalCoord < nextPageStartPos ) || (( nextPageStartPos == 0 ) && ( totalCoord <= endY ) ) )
186 double pixelCoord = mTransform.
map(
QPointF( 0, totalCoord ) ).
y();
187 p.
drawLine( 0, pixelCoord, mRulerMinSize, pixelCoord );
190 int labelSize = mRulerFontMetrics->
width( label );
193 if (( pixelCoord + labelSize + 8 < nextPageStartPixel )
194 || ( nextPageStartPixel == 0 ) )
196 drawRotatedText( &p,
QPointF( mTextBaseline, pixelCoord + mMinSpacingVerticalLabels + labelSize ), label );
200 drawSmallDivisions( &p, totalCoord, numSmallDivisions, mmDisplay, nextPageStartPos );
202 pageCoord += mmDisplay;
203 totalCoord += mmDisplay;
212 void QgsComposerRuler::drawMarkerPos(
QPainter *painter )
218 painter->
drawLine( mMarkerPos.
x(), 0, mMarkerPos.
x(), mRulerMinSize );
222 painter->
drawLine( 0, mMarkerPos.
y(), mRulerMinSize, mMarkerPos.
y() );
235 void QgsComposerRuler::drawSmallDivisions(
QPainter *painter,
double startPos,
int numDivisions,
double rulerScale,
double maxPos )
237 if ( numDivisions == 0 )
241 double smallMarkerPos = startPos;
242 double smallDivisionSpacing = rulerScale / numDivisions;
247 for (
int i = 0; i < numDivisions; ++i )
249 smallMarkerPos += smallDivisionSpacing;
251 if ( maxPos > 0 && smallMarkerPos > maxPos )
260 pixelCoord = mTransform.
map(
QPointF( smallMarkerPos, 0 ) ).
x();
264 pixelCoord = mTransform.
map(
QPointF( 0, smallMarkerPos ) ).
y();
269 if (( numDivisions == 10 && i == 4 ) || ( numDivisions == 4 && i == 1 ) )
272 lineSize = mRulerMinSize / 1.5;
276 lineSize = mRulerMinSize / 1.25;
282 painter->
drawLine( pixelCoord, lineSize, pixelCoord, mRulerMinSize );
286 painter->
drawLine( lineSize, pixelCoord, mRulerMinSize, pixelCoord );
291 int QgsComposerRuler::optimumScale(
double minPixelDiff,
int &magnitude,
int &multiple )
296 for (
unsigned int magnitudeCandidate = 0; magnitudeCandidate <
COUNT_VALID_MAGNITUDES; ++magnitudeCandidate )
298 for (
unsigned int multipleCandidate = 0; multipleCandidate <
COUNT_VALID_MULTIPLES; ++multipleCandidate )
300 int candidateScale = validScaleMultiples[multipleCandidate] * validScaleMagnitudes[magnitudeCandidate];
302 double pixelDiff = mTransform.
map(
QPointF( candidateScale, 0 ) ).
x() - mTransform.
map(
QPointF( 0, 0 ) ).
x();
303 if ( pixelDiff > minPixelDiff )
306 magnitude = validScaleMagnitudes[magnitudeCandidate];
307 multiple = validScaleMultiples[multipleCandidate];
308 return candidateScale;
316 int QgsComposerRuler::optimumNumberDivisions(
double rulerScale,
int scaleMultiple )
319 double largeDivisionSize = mTransform.
map(
QPointF( rulerScale, 0 ) ).
x() - mTransform.
map(
QPointF( 0, 0 ) ).
x();
323 switch ( scaleMultiple )
328 validSmallDivisions << 10 << 5 << 2;
333 validSmallDivisions << 10 << 4 << 2;
338 validSmallDivisions << 10 << 5;
344 for ( divisions_it = validSmallDivisions.
begin(); divisions_it != validSmallDivisions.
end(); ++divisions_it )
347 double candidateSize = largeDivisionSize / ( *divisions_it );
349 if ( candidateSize >= mMinPixelsPerDivision )
352 return ( *divisions_it );
365 mTransform = transform;
373 setSnapLinePosition( event->
posF() );
380 displayPos.
setY( 0 );
385 displayPos.setX( 0 );
396 bool removeItem =
false;
399 removeItem = pos.
x() < 0 ?
true :
false;
403 removeItem = pos.
y() < 0 ?
true :
false;
409 mSnappedItems.
clear();
411 mLineSnapItem =
nullptr;
436 mLineSnapItem = line;
440 void QgsComposerRuler::setSnapLinePosition(
QPointF pos )
442 if ( !mLineSnapItem || !mComposition )
450 int numPages = mComposition->
numPages();
451 double lineHeight = numPages * mComposition->
paperHeight();
456 mLineSnapItem->
setLine(
QLineF( transformedPt.
x(), 0, transformedPt.
x(), lineHeight ) );
465 for ( ; itemIt != mSnappedItems.
constEnd(); ++itemIt )
void mousePressEvent(QMouseEvent *event) override
double paperWidth() const
Width of paper item.
void setPointSize(int pointSize)
const unsigned int COUNT_VALID_MULTIPLES
const unsigned int COUNT_VALID_MAGNITUDES
void drawLine(const QLineF &line)
double spaceBetweenPages() const
Returns the vertical space between pages in a composer view.
int numPages() const
Returns the number of pages in the composition.
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
void paintEvent(QPaintEvent *event) override
void setFont(const QFont &font)
QString number(int n, int base)
QSize minimumSizeHint() const override
void mouseMoveEvent(QMouseEvent *event) override
void setPen(const QColor &color)
void removeSnapLine(QGraphicsLineItem *line)
Remove custom snap line (and delete the object)
void setLine(const QLineF &line)
void setSceneTransform(const QTransform &transform)
void mouseReleaseEvent(QMouseEvent *event) override
void drawText(const QPointF &position, const QString &text)
QgsComposerRuler(QgsComposerRuler::Direction d)
int width(const QString &text, int len) const
void cursorPosChanged(QPointF)
Is emitted when mouse cursor coordinates change.
QGraphicsLineItem * nearestSnapLine(const bool horizontal, const double x, const double y, const double tolerance, QList< QPair< QgsComposerItem *, QgsComposerItem::ItemPositionMode > > &snappedItems) const
Get nearest snap line.
double paperHeight() const
Height of paper item.
void translate(const QPointF &offset)
void updateMarker(QPointF pos)
const QPoint & pos() const
const_iterator constEnd() const
QGraphicsLineItem * addSnapLine()
Add a custom snap line (can be horizontal or vertical)
const_iterator constBegin() const
const int RULER_FONT_SIZE