4 #include <QDragEnterEvent>
5 #include <QGraphicsLineItem>
12 const int QgsComposerRuler::validScaleMultiples[] = {1, 2, 5};
13 const int QgsComposerRuler::validScaleMagnitudes[] = {1, 10, 100, 1000, 10000};
19 mScaleMinPixelsWidth( 0 )
21 setMouseTracking(
true );
24 mRulerFont =
new QFont();
26 mRulerFontMetrics =
new QFontMetrics( *mRulerFont );
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 );
66 QTransform t = mTransform.inverted();
68 p.setFont( *mRulerFont );
74 mmDisplay = optimumScale( mScaleMinPixelsWidth, magnitude, multiple );
77 int numSmallDivisions = optimumNumberDivisions( mmDisplay, multiple );
87 double startX = t.map( QPointF( 0, 0 ) ).x();
88 double endX = t.map( QPointF( width(), 0 ) ).x();
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 );
102 p.drawText( QPointF( pixelCoord + mPixelsBetweenLineAndText, mTextBaseline ), QString::number( markerPos ) );
105 drawSmallDivisions( &p, markerPos, numSmallDivisions, mmDisplay, endX );
107 markerPos += mmDisplay;
117 double startY = t.map( QPointF( 0, 0 ) ).y();
118 double endY = t.map( QPointF( 0, height() ) ).y();
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 );
136 QString label = QString::number( beforePageCoord );
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 );
189 QString label = QString::number( pageCoord );
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 )
215 painter->setPen( QColor( Qt::red ) );
218 painter->drawLine( mMarkerPos.x(), 0, mMarkerPos.x(), mRulerMinSize );
222 painter->drawLine( 0, mMarkerPos.y(), mRulerMinSize, mMarkerPos.y() );
226 void QgsComposerRuler::drawRotatedText( QPainter *painter, QPointF pos,
const QString &text )
229 painter->translate( pos.x(), pos.y() );
230 painter->rotate( 270 );
231 painter->drawText( 0, 0, text );
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();
322 QList<int> validSmallDivisions;
323 switch ( scaleMultiple )
328 validSmallDivisions << 10 << 5 << 2;
333 validSmallDivisions << 10 << 4 << 2;
338 validSmallDivisions << 10 << 5;
343 QList<int>::iterator divisions_it;
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 );
363 QString debug = QString::number( transform.dx() ) +
"," + QString::number( transform.dy() ) +
","
364 + QString::number( transform.m11() ) +
"," + QString::number( transform.m22() );
365 mTransform = transform;
373 setSnapLinePosition( event->posF() );
376 QPointF displayPos = mTransform.inverted().map( event->posF() );
380 displayPos.setY( 0 );
385 displayPos.setX( 0 );
395 QPointF pos = mTransform.inverted().map( event->pos() );
396 bool removeItem =
false;
399 removeItem = pos.x() < 0 ?
true :
false;
403 removeItem = pos.y() < 0 ?
true :
false;
409 mSnappedItems.clear();
420 x = mTransform.inverted().map( event->pos() ).x();
424 y = mTransform.inverted().map( event->pos() ).y();
436 mLineSnapItem = line;
440 void QgsComposerRuler::setSnapLinePosition(
const QPointF& pos )
442 if ( !mLineSnapItem || !mComposition )
447 QPointF transformedPt = mTransform.inverted().map( pos );
450 int numPages = mComposition->
numPages();
451 double lineHeight = numPages * mComposition->
paperHeight();
456 mLineSnapItem->setLine( QLineF( transformedPt.x(), 0, transformedPt.x(), lineHeight ) );
460 mLineSnapItem->setLine( QLineF( 0, transformedPt.y(), mComposition->
paperWidth(), transformedPt.y() ) );
464 QList< QPair< QgsComposerItem*, QgsComposerItem::ItemPositionMode > >::iterator itemIt = mSnappedItems.begin();
465 for ( ; itemIt != mSnappedItems.end(); ++itemIt )